我正在尝试使用CUDA在GPU上实现以下类型的管道:
我有四个流,每个流都有一个Host2Device副本,一个内核调用和一个Device2Host副本。但是,内核调用必须等待下一个流的Host2Device副本完成。
我打算使用cudaStreamWaitEvent
进行同步。但是,根据文档,这仅适用于之前为相应事件调用cudaEventRecord
的情况。在这种情况下情况并非如此。
流由不同的CPU线程管理,基本上如下所示:
Do some work ...
cudaMemcpyAsync H2D
cudaEventRecord (event_copy_complete[current_stream])
cudaStreamWaitEvent (event_copy_complete[next_stream])
call kernel on current stream
cudaMemcpyAsync D2H
Do some work ...
管理CPU线程以正确的顺序启动流。因此,在该事件的cudaStreamWaitEvent
之前(在流1中)调用流{1的复制完成事件的cudaEventRecord
(在流0中)。这导致功能无操作。
我觉得事件不能以这种方式使用。还有另一种方法可以实现所需的同步吗?
顺便说一下,我不能只是反转流顺序,因为还有一些依赖项。
根据要求,以下是发出CUDA呼叫的顺序:
//all on stream 0
cpy H2D
cudaEventRecord (event_copy_complete[0])
cudaStreamWaitEvent (event_copy_complete[1])
K<<< >>>
cpy D2H
//all on stream 1
cpy H2D
cudaEventRecord (event_copy_complete[1])
cudaStreamWaitEvent (event_copy_complete[2])
K<<< >>>
cpy D2H
//all on stream 2
cpy H2D
cudaEventRecord (event_copy_complete[2])
cudaStreamWaitEvent (event_copy_complete[3])
K<<< >>>
cpy D2H
...
可以看出,对cudaStreamWaitEvent
的调用总是早于对cudaEventRecord
的调用。
答案 0 :(得分:1)
如果可能,您应该从单个CPU线程调度所有这些GPU工作。这样,(存在明显陈述的风险),API调用的执行顺序可以从它们在代码中出现的顺序推断出来。由于cudaEventRecord()
和cudaStreamWaitEvent()
调用都对与CUDA上下文关联的进度值进行操作,因此API调用的确切顺序非常重要。 cudaEventRecord()
记录当前进度值,然后递增它; cudaStreamWaitEvent()
发出当前GPU等待事件当前进度值的命令。 (这就是为什么如果你颠倒调用的顺序,等待就变成了有效的无操作。)
如果API调用是从不同的线程进行的,则必须进行大量的线程同步才能生成所需的结果,这也会对性能产生负面影响。实际上,如果出于性能原因需要多个CPU线程,您可能需要重新构建代码以将CUDA调用委托给单个CPU线程以强制执行排序。