简化的问题 我有两个主机线程,每个线程都具有通往同一GPU设备的命令队列。这两个队列都是乱序的,执行顺序是使用等待事件显式管理的(简化示例不需要此,但实际应用程序需要)。
ThreadA
是一种轻量级的处理管道,可在获取新数据时实时运行。 ThreadB
是重量级的较慢的处理管道,它使用相同的输入数据,但以较慢的速率异步处理它。我正在使用一个双缓冲区来保持管线分开,但允许ThreadB
处理ThreadA
写入设备的相同输入数据。
ThreadA
的循环:
cl_mem BufferA
将图像写入设备clEnqueueWriteBuffer(CommandQueueA)
KernelA
后,使用clEnqueueNDRangeKernel(CommandQueueA)
调用图像处理cl_mem OutputA
OutputA
从clEnqueueReadBuffer(CommandQueueA)
读取处理后的结果 ThreadB
的循环
BufferA
(双缓冲区交换)将BufferB
复制到clEnqueueCopyBuffer(CommandQueueB)
KernelB
调用clEnqueueNDRangeKernel(CommandQueueB)
进行较慢的图像处理(内核将结果输出到cl_mem OutputB
)OutputB
从clEnqueueReadBuffer(CommandQueueB)
读取处理后的结果我的问题
在ThreadA
的第2步和ThreadB
的第2步之间存在潜在的竞争条件。我不在乎哪个先执行,我只想确保不复制将BufferA
写入BufferB
到BufferA
。
ThreadB
的第2步上使用clEnqueueCopyBuffer(CommandQueueA)
,以便将写操作和复制操作都放在同一命令队列中,是否可以确保即使在同一时间它们也不能同时运行队列是否允许乱序执行?ThreadA
中的WriteBuffer事件添加到ThreadB
中的CopyBuffer命令的等待列表更好的解决方案?似乎所有这些都应该起作用,但是我在OpenCL规范中找不到它说的很好。如果可能,请在您的答案中引用OpenCL规范。
答案 0 :(得分:2)
OpenCL是否提供任何暗示保证不会发生这种情况?
否,除非您使用单个顺序命令队列,否则没有隐式同步。
如果没有,如果我改为在ThreadB步骤2上使用 clEnqueueCopyBuffer(CommandQueueA)以便写和写 复制操作在同一命令队列中, 确保即使 队列是否允许乱序执行?
否,无论队列的类型如何(顺序与无序), OpenCL运行时不跟踪以下项的内存依赖性 命令。用户负责在等待列表中指定事件, 如果命令之间存在任何依赖关系。
以下引用可以证明这一点:
s3.2.1执行模型:上下文和命令队列
乱序执行:命令按顺序发出,但是可以 在执行以下命令之前不要等待完成。任何 订单约束由程序员通过 显式同步命令。
这不是您问题的直接答案,但我认为如果 提供了任何担保,在此应提及 部分。
如果没有,是否有比添加 ThreadA中WriteBuffer的事件到 ThreadB中的CopyBuffer命令?
如果您可以使用单个顺序队列,则可能是 至少比某些情况比跨队列事件更有效 实施。