内核执行期间OpenCL clEnqueueReadBuffer?

时间:2013-11-16 00:28:49

标签: opencl gpgpu

在发生OpenCL clEnqueueReadBuffer操作时,排队的内核是否可以继续执行?

换句话说,clEnqueueReadBuffer是否在设备上进行阻止操作?

1 个答案:

答案 0 :(得分:5)

从主机API的角度来看, clEnqueueReadBuffer 可以阻止或不阻止,具体取决于您是否将 blocking_read 参数设置为CL_TRUE或CL_FALSE。

如果将其设置为不阻塞,则读取刚刚排队,您应该使用事件(或后续阻塞调用)来确定它何时完成(即,在您访问正在读取的内存之前)。

如果将其设置为阻止,则在读取完成之前不会返回呼叫。正在读取的内存是正确的。此外(并回答您的实际问题)您在clEnqueueReadBuffer之前排队的任何操作都必须在读取开始之前完成(请参阅下面的例外说明)。

所有clEnqueue * API调用都是异步的,但有些调用可以设置“阻塞”参数。使用它相当于使用非阻塞版本,然后调用 clFinish 。命令队列将刷新到设备,主机线程将不会继续,直到工作完成。当然,很难让GPU始终忙于这样做,因为现在它没有任何工作,但如果你足够快地排队新工作,你仍然可以让它保持相当繁忙。

这都假设一个有序的命令队列。如果您的命令队列无序且您的设备支持无序队列,则排队项目可以按任何不违反您提供的 event_wait_list 参数的顺序执行。同样,您可以拥有多个命令队列,这些命令队列可以按照不违反您提供的 event_wait_list参数的任何顺序再次执行。通常,它们用于重叠内存传输和计算,并使多个计算单元保持繁忙。无序命令队列和多个命令队列都是高级OpenCL概念,在您完全理解并具有有序命令队列经验之前不应尝试。

在DarkZeros指出OP问题的“设备上”部分之后添加了澄清:我的答案来自主机线程API的观点。在设备上,使用有序命令队列,当前命令会阻止所有下游命令。对于无序队列,它们仅被event_wait_list阻止。但是,今天的驱动程序不能很好地支持无序命令队列。对于多个命令队列,理论上命令仅被先前命令(如果按顺序)和event_wait_list阻止。实际上,有时会有特殊的供应商规则阻止您可能喜欢的潜在非阻塞命令的自由流动。这通常是因为多个OpenCL命令队列被转移到设备端内存和计算队列,并在那里按顺序执行。因此,根据您向多个命令队列添加命令的 order ,它们可能会以这种方式交错,以便以次优方式阻塞。我所知道的最好的解决方案是要么小心你排队的顺序(基于这个实现细节的知识),要么使用一个队列用于内存,一个用于计算,这与设备端排队匹配。

如果内存和计算重叠是您的目标,AMD和NVIDIA都提供了如何重叠内存和计算操作的示例,以及支持多个计算操作的GPU,如何执行此操作。 NVIDIA的例子很难得到,但他们在那里(来自CUDA 4天)。