0

假设我有一个结构:

typedef enum {ON_CPU,ON_GPU,ON_BOTH} memLocation;

typedef struct foo *foo;
struct foo {
  cudaEvent_t event;
  float       *deviceArray;
  float       *hostArray;
  memLocation arrayLocation;
};

一个功能:

void copyArrayFromCPUToGPUAsync(foo bar, cudaStream_t stream)
{
  cudaStreamWaitEvent(stream, bar->event);
  if (bar->arrayLocation == ON_CPU) {
    // ON_CPU means !ON_GPU and !ON_BOTH
    cudaMemcpyAsync(cudaMemcpyHostToDevice, stream);
    bar->arrayLocation = ON_BOTH;
  }
  cudaEventRecord(bar->event, stream);
}

void doWorkOnGPUAsync(foo bar, cudaStream_t stream)
{
  cudaStreamWaitEvent(stream, bar->event);
  // do async work
  cudaEventRecord(bar->event, stream);
}

以及以下场景(狮子、女巫和衣柜也适合某个地方):

// stream1, stream2, and stream3 have no prior work
// assume bar->arrayLocation = ON_GPU

doWorkOnGPUAsync(bar, stream1);
copyArrayFromCPUToGPUAsync(bar, stream2); // A no-op
doWorkOnGPUAsync(bar, stream3);

以上安全吗?即如果它本身不起作用,它stream2仍然会等待完成它的“工作”吗?stream1结果记录是否会cudaEvent反映这一点,stream3直到stream1完成才开始?

4

1 回答 1

1

这应该是安全的。

由于在等待事件和记录另一个事件之间缺乏其他工作,任何地方(我知道)都没有提到某种“事件取消”。您在调用中重新使用相同的事件对象并不重要cudaEventRecord(),因为正如运行时 API 文档所说

cudaEventRecord()可以在同一事件上多次调用,并将覆盖先前捕获的状态。其他 API,例如cudaStreamWaitEvent()在 API 调用时使用最近捕获的状态,并且不受以后对cudaEventRecord().


补充说明:

  • 对于您明显的用例,您可能还需要考虑使用托管内存而不是手动来回复制的可能性。
  • 您应该检查各种操作是否成功,而不仅仅是假设它们成功了。
于 2021-03-05T21:41:37.937 回答