Opencl clEnqueueBarrier和clFinish有什么区别?

Opencl clEnqueueBarrier和clFinish有什么区别?,opencl,gpu,Opencl,Gpu,OpenCL 1.1规范规定: CLU int CLENQUEUEBARIER(CLU命令队列命令队列) clEnqueueBarrier是一个同步点,用于确保在下一批命令开始执行之前,命令队列中的所有排队命令都已完成执行 cl_int clFinish(cl_命令队列命令队列) 阻塞,直到命令队列中所有先前排队的OpenCL命令被发送到相关设备并完成。clFinish在命令队列中的所有排队命令都已处理并完成之前不会返回。clFinish也是一个同步点 应该对有序执行或无序执行做些什么,但我看不

OpenCL 1.1规范规定:

CLU int CLENQUEUEBARIER(CLU命令队列命令队列)

clEnqueueBarrier是一个同步点,用于确保在下一批命令开始执行之前,命令队列中的所有排队命令都已完成执行

cl_int clFinish(cl_命令队列命令队列)

阻塞,直到命令队列中所有先前排队的OpenCL命令被发送到相关设备并完成。clFinish在命令队列中的所有排队命令都已处理并完成之前不会返回。clFinish也是一个同步点

应该对有序执行或无序执行做些什么,但我看不出有什么区别。如果我有命令执行,是否需要它们?目前,我做了如下工作:

...
for(...){
    clEnqueuNDRangeKernel(...);
    clFlush(command_queue);
    clFinish(command_queue);
}
...

在Nvidia GPU上。如有任何相关评论,我们将不胜感激

如果要将无序队列作为确保依赖性的一种方法写入,则需要将屏障排队。您还可以使用
cl\u事件
对象来确保命令队列上的命令顺序正确

如果编写代码时在每次内核调用后调用
clFinish
,那么使用
clEnqueueBarrier
不会对代码产生任何影响,因为您已经在确保排序

使用
clEnqueueBarrier
的要点如下:

clEnqueueNDRangeKernel(queue, kernel1);
clEnqueueBarrier(queue);
clEnqueueNDRangeKernel(queue, kernel2);
在这种情况下,kernel2取决于kernel1的结果。如果此队列出现故障,那么在没有障碍的情况下,kernel2可能在kernel1之前执行,从而导致错误行为。您可以通过以下方式实现相同的订购:

clEnqueueNDRangeKernel(queue, kernel1);
clFinish(queue);
clEnqueueNDRangeKernel(queue, kernel2);
因为
clFinish
将等待队列为空(所有内核/数据传输都已完成)。但是,
clFinish
将等待内核1完成,在这种情况下,
clEnqueueBarrier
应立即将控制权返回给应用程序(允许您将更多内核排队或执行其他有用的工作)


作为旁注,我认为
clFinish
将隐式调用
clFlush
,因此您不必每次都调用它。

谢谢您的回答。因此,总结一下:两者都是这样做的,但是clEnqueueBarrier()是一个异步函数,因此它会立即继续承载代码。我测试了两个解决方案,如果一个比另一个需要更多的时间,但似乎没有这样的问题。我想知道clEnqueueBarrier是否实际上等同于clEnqueueMarker,然后是clEnqueueWaitForEvents?或者是否有一些我忽略的细节?@TomiAarnio这可能是clEnqueueBarrier的一个实现,但我不确定clEnqueueMarker在无序队列中是如何工作的,这可能会影响这两个队列的语义。对于有序队列,我认为可能是这样。