为什么cudaMemcpyAsync P2P拷贝没有在指定的流中发生

时间:2015-03-24 07:03:57

标签: cuda gpu nvidia

正如在回答这个问题的答案中指出的那样

What device number should I use (0 or 1), to copy P2P (GPU0->GPU1)?

源或目标GPU上的cuda流都可用​​于对等拷贝。然而,这是我从分析中得到的,它有点令人困惑。

#include <cuda.h>
#include <cuda_runtime.h>

int main() {
  cudaDeviceEnablePeerAccess(0, 1);
  cudaDeviceEnablePeerAccess(1, 0);

  // on device 0
  cudaSetDevice(0);
  float* data0;
  cudaMalloc(&data0, 1024000);

  // on device 1
  cudaSetDevice(1);
  cudaStream_t stream1;
  cudaStreamCreate(&stream1);
  float* data1;
  cudaMalloc(&data1, 1024000);

  cudaMemcpyAsync(data0, data1, 1024000, cudaMemcpyDefault, stream1);
  cudaDeviceSynchronize();
  cudaMemcpyAsync(data1, data0, 1024000, cudaMemcpyDefault, stream1);
  cudaDeviceSynchronize();
}

enter image description here

问题是,

为什么在我明确地将其分配给设备1时,在设备0上执行了复制作业?

2 个答案:

答案 0 :(得分:3)

分析器中的索引方案与cudaSetDevice函数使用的索引不同。如果查看代码,则创建的流在设备1上生成,但它与分析器上的设备索引[0]相关联。您应该使用NVTX's Resource Naming API来命名设备。它将使您更好地了解资源在资源管理器上的映射方式。

答案 1 :(得分:0)

这段代码真的很粗心!

cudaDeviceEnablePeerAccess不接受两个设备ID,第二个参数应始终为0。

在正确调用cudaDeviceEnablePeerAccess之后,分析结果显示无论设置哪个流,cudaMemcpyAsync始终在源设备中发生。似乎如果使用目标GPU中的流,它将被重新分配给源设备中的流,该流是自动创建的。

但是,尽管副本始终在源设备中执行,但如果该功能发布到目标流,它将阻止目标流,直到副本完成,我想这是通过cudaEvent。我猜这就是为什么

  

“当流属于源GPU时,性能最大化。”如本文所述   What device number should I use (0 or 1), to copy P2P (GPU0->GPU1)?

例如:

cudaMemcpyPeerAsync(data0, 0, data1, 1, 1024000, stream0);
cudaMemcpyPeerAsync(data1, 1, data0, 0, 1024000, stream0);

虽然第一个副本将分配给设备0,第二个副本将分配给设备1,但这两个操作不会重叠,因为它们位于同一个流中。

如果第一个副本设置为设备1,则它们可以重叠。

cudaMemcpyPeerAsync(data0, 0, data1, 1, 1024000, stream1);
cudaMemcpyPeerAsync(data1, 1, data0, 0, 1024000, stream0);