clEnqueueBarrier和clFinish有什么区别?

las*_*dre 7 gpu opencl

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);
}
...
Run Code Online (Sandbox Code Playgroud)

在Nvidia GPU上.任何相关评论表示赞赏.

KLe*_*ee1 6

如果您正在编写无序队列作为确保依赖性的一种方法,则需要将障碍排入队列.您还可以使用这些cl_event对象来确保命令队列上的命令的正确排序.

如果您正在编写代码,以便clFinish在每次内核调用之后调用,那么使用clEnqueueBarrier将不会对代码产生任何影响,因为您已经确保了订购.

使用的点将是clEnqueueBarrier如下情况:

clEnqueueNDRangeKernel(queue, kernel1);
clEnqueueBarrier(queue);
clEnqueueNDRangeKernel(queue, kernel2);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,kernel2取决于kernel1的结果.如果此队列是乱序的,那么没有障碍,kernel2 可以在kernel1之前执行,从而导致不正确的行为.您可以通过以下方式实现相同的排序

clEnqueueNDRangeKernel(queue, kernel1);
clFinish(queue);
clEnqueueNDRangeKernel(queue, kernel2);
Run Code Online (Sandbox Code Playgroud)

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

作为旁注,我认为这clFinish将隐式调用,clFlush所以你不应该每次都调用它.

  • @TomiAarnio这可能是clEnqueueBarrier的一个实现,但我不确定clEnqueueMarker如何在无序队列中工作,这可能会影响二者的语义.对于有序队列,我想说可能就是这种情况. (2认同)