同步两个CUDA流

时间:2013-07-19 21:02:13

标签: cuda

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

我应该将CUDA事件用于此类同步还是其他一些机制?

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

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

1 个答案:

答案 0 :(得分: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的{​​{1}}已完成之前开始,同样适用于stream1以及kernel2中的数据传输。

我认为没有任何理由将上述活动分解为单独的CPU线程。这不必要地使事情复杂化。管理单个设备最无故障的方法是从单个CPU线程。