【问题标题】:Synchronizing two CUDA streams同步两个 CUDA 流
【发布时间】:2017-08-12 21:04:04
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: cuda


    【解决方案1】:

    您当然可以使用 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 线程。

    【讨论】:

    • 谢谢。我现在意识到我没有很好地解释我的问题,所以我添加了更多细节。
    • 尽管您进行了更新,但我完全不清楚为什么您不能直接使用流。对于必须按顺序处理的批次,将这些内核放在同一个流中。从概念上讲,一个内核按顺序调用多个内核之间没有区别。如果有帮助,请使用 2 个以上的流。如果你确信你不能使用流,你可以按照我的指示使用事件。
    猜你喜欢
    • 1970-01-01
    • 2016-12-14
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 2010-12-11
    相关资源
    最近更新 更多