clEnqueueBarrier和clFinish有什么区别?

时间:2012-11-02 17:28:59

标签: opencl gpu

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上。任何相关评论表示赞赏。

1 个答案:

答案 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,因此您不需要每次都调用它。