OpenCL 1.1规范说:
cl_int clEnqueueBarrier(cl_command_queue command_queue)
clEnqueueBarrier是一个同步点,可确保command_queue中的所有排队命令在下一批命令开始执行之前已完成执行。
cl_int clFinish(cl_command_queue command_queue)
阻止,直到command_queue中所有先前排队的OpenCL命令发布到关联设备并完成。在处理完成command_queue中的所有排队命令之前,clFinish不会返回。 clFinish也是一个同步点。
应该对有序或无序执行做些什么,但我看不出有什么区别。如果我有顺序执行,他们是否需要?目前我做了类似的事情:
...
for(...){
clEnqueuNDRangeKernel(...);
clFlush(command_queue);
clFinish(command_queue);
}
...
在Nvidia GPU上。任何相关评论表示赞赏。
答案 0 :(得分:5)
如果要编写无序队列作为确保依赖性的一种方法,则需要将障碍排入队列。您还可以使用cl_event
对象来确保命令队列上命令的正确排序。
如果您编写代码使得在每次内核调用后调用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
将等到kernel1完成,在这种情况下,clEnqueueBarrier
应立即将控制权返回给应用程序(允许您将更多内核排入队列或执行其他有用的工作。
作为旁注,我认为clFinish
会隐式调用clFlush
,因此您不需要每次都调用它。