2013-07-19 63 views
1

我正在使用CUDA流启用异步数据传输并隐藏内存拷贝延迟。我有2个CPU线程和2个CUDA流:一个是“数据”流,它基本上是由第一个CPU线程启动的一系列cudaMemcpyAsync调用,另一个是执行计算内核的“计算”流。数据流正在为计算流准备批处理,因此对于计算流来说,确保流将要处理的批次完全加载到内存中至关重要。同步两个CUDA流

我应该使用CUDA事件进行这种同步还是其他一些机制?

更新:让我澄清为什么我不能在每个流中使用具有数据副本/计算的单独流。问题是批处理必须按顺序处理,我不能并行执行它们(当然,这可能会对多个流执行)。但是,在处理每批时,我可以预先加载下一批的数据,从而隐藏数据传输。 要使用罗伯特的例子:

cudaMemcpyAsync(<data for batch1>, dataStream); 
cudaMemcpyAsync(<data for batch2>, dataStream); 
kernelForBatch1<<<..., opsStream>>>(...); 
kernelForBatch2<<<..., opsStream>>>(...); 

回答

3

您当然可以使用CUDA事件同步流,如使用cudaStreamWaitEvent API函数。然而,将所有数据副本放在一个流中而将所有内核调用放在另一个流中的想法可能不是对流的合理使用。

确保在单个流内发出的cuda函数(API调用,内核调用)按顺序执行,该流中的任何cuda函数都不会开始,直到该流中所有先前的cuda活动都已完成(即使您使用诸如cudaMemcpyAsync之类的调用...)

因此流已经为您提供了一种机制,以确保内核调用在所需数据被复制之前不会开始。只需在数据复制后将该内核调用放入同一个流中即可。

像这样的东西应该照顾你同步:

cudaMemcpyAsync(<data for kernel1>, stream1); 
cudaMemcpyAsync(<data for kernel2>, stream2); 
kernel1<<<..., stream1>>>(...); 
kernel2<<<..., stream2>>>(...); 
cudaMemcpyAsync(<data from kernel1>, stream1); 
cudaMemcpyAsync(<data from kernel2>, stream2); 

以上所有的调用都是异步的,所以假设你已经满足了异步执行的其他要求(比如使用固定的内存),所有上述呼叫应该“排队”并立即返回。然而kernel1保证不会在前面cudaMemcpyAsync发布到stream1已经完成之前开始,并且kernel2stream2的数据传输也是如此。

我没有看到任何理由将上述活动分解为单独的CPU线程。这不必要地使事情复杂化。管理单个设备的最麻烦的方法是来自单个CPU线程。

+1

谢谢。我现在意识到我没有很好地解释我的问题,所以我添加了更多细节。 –

+0

尽管你有更新,但我不清楚为什么你不能直接使用流。对于必须按顺序处理的批次,将这些内核放在同一个流中。从概念上讲,一个内核依次调用几个并没有什么区别。如果有帮助,请使用2个以上的流。如果你确信你不能使用流,你可以像我指出的那样使用事件。 –