1

我正在尝试使用 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 中)之前调用(在流 0cudaEventRecord中)。这导致功能性无操作。

我觉得不能以这种方式使用事件。是否有另一种方法来实现所需的同步?

顺便说一句,我不能只是颠倒流顺序,因为还有更多的依赖关系。

API调用顺序

根据要求,这是发出 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
...

可以看出,调用 tocudaStreamWaitEvent总是早于调用 to cudaEventRecord

4

1 回答 1

3

如果可能的话,您应该从单个 CPU 线程分派所有这些 GPU 工作。这样,(冒着说明显而易见的风险),可以从它们在代码中出现的顺序推断出执行 API 调用的顺序。因为cudaEventRecord()cudaStreamWaitEvent()调用都对与 CUDA 上下文关联的进度值进行操作,所以 API 调用的确切顺序很重要。cudaEventRecord()记录当前进度值,然后递增;cudaStreamWaitEvent()发出命令让当前 GPU 等待事件的当前进度值。(这就是为什么如果你颠倒调用的顺序,等待就变成了一个有效的空操作。)

如果 API 调用是从不同的线程进行的,您将不得不进行大量线程同步来生成所需的结果,这也会对性能产生负面影响。事实上,如果出于性能原因需要多个 CPU 线程,您可能需要重新构建代码以将 CUDA 调用委托给单个 CPU 线程以强制执行排序。

于 2014-11-26T23:03:58.697 回答