7

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 命令都发送到相关设备并完成。clFinish 在 command_queue 中所有排队的命令都被处理和完成之前不会返回。clFinish 也是一个同步点。

应该必须对按顺序或无序执行做一些事情,但我看不出有什么区别。如果我有顺序执行,他们是否需要?目前我做类似的事情:

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

在英伟达 GPU 上。任何相关评论表示赞赏。

4

1 回答 1

6

如果您正在编写乱序队列作为确保依赖关系的一种方法,则需要将屏障加入队列。您还可以使用这些cl_event对象来确保命令队列中命令的正确排序。

如果您正在编写代码,以便clFinish在每次内核调用后调用 a,那么 usingclEnqueueBarrier不会对您的代码产生任何影响,因为您已经确保了排序。

使用的要点是clEnqueueBarrier这样的情况:

clEnqueueNDRangeKernel(queue, kernel1);
clEnqueueBarrier(queue);
clEnqueueNDRangeKernel(queue, kernel2);

在这种情况下,kernel2 依赖于 kernel1 的结果。如果这个队列是无序的,那么在没有屏障的情况下,kernel2可以在 kernel1 之前执行,从而导致不正确的行为。您可以通过以下方式实现相同的排序:

clEnqueueNDRangeKernel(queue, kernel1);
clFinish(queue);
clEnqueueNDRangeKernel(queue, kernel2);

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

作为旁注,我认为这clFinish会隐式调用clFlush,因此您不需要每次都调用它。

于 2012-11-02T18:22:15.433 回答