对于P2P复制,cudaMemcpy()和CUDAMEMCPyper()之间有什么区别?

对于P2P复制,cudaMemcpy()和CUDAMEMCPyper()之间有什么区别?,cuda,gpgpu,nvidia,Cuda,Gpgpu,Nvidia,我想不使用CPU-RAM直接将数据从GPU0-DDR复制到GPU1-DDR 如第15页所述: 如果使用,则必须首先设置标志CUDASETDEVICELAGS cudaDeviceMapHost吗? 我是否必须使用从函数cudaHostGetDevicePointer&uva_ptr,ptr,0得到的cudaMemcpy指针? 功能是否有任何优势?如果没有优势,为什么需要它? 统一虚拟寻址UVA为所有CPU和GPU内存启用一个地址空间,因为它允许根据指针值确定物理内存位置 具有UVA的点对点mem

我想不使用CPU-RAM直接将数据从GPU0-DDR复制到GPU1-DDR

如第15页所述:

如果使用,则必须首先设置标志CUDASETDEVICELAGS cudaDeviceMapHost吗? 我是否必须使用从函数cudaHostGetDevicePointer&uva_ptr,ptr,0得到的cudaMemcpy指针? 功能是否有任何优势?如果没有优势,为什么需要它?
统一虚拟寻址UVA为所有CPU和GPU内存启用一个地址空间,因为它允许根据指针值确定物理内存位置

具有UVA的点对点memcpy*

如果可以使用UVA,那么cudaMemcpy可以用于点对点memcpy,因为CUDA可以推断哪个设备拥有哪个内存。使用UVA执行点对点memcpy通常需要以下说明:

//Check for peer access between participating GPUs: 
cudaDeviceCanAccessPeer(&can_access_peer_0_1, gpuid_0, gpuid_1);
cudaDeviceCanAccessPeer(&can_access_peer_1_0, gpuid_1, gpuid_0);

//Enable peer access between participating GPUs:
cudaSetDevice(gpuid_0);
cudaDeviceEnablePeerAccess(gpuid_1, 0);
cudaSetDevice(gpuid_1);
cudaDeviceEnablePeerAccess(gpuid_0, 0);

//UVA memory copy:
cudaMemcpy(gpu0_buf, gpu1_buf, buf_size, cudaMemcpyDefault);
无UVA的点对点memcpy

如果无法使用UVA,则通过CUDAMEMCPYPER完成点对点memcpy。这里有一个例子

// Set device 0 as current
cudaSetDevice(0); 
float* p0;
size_t size = 1024 * sizeof(float);
// Allocate memory on device 0
cudaMalloc(&p0, size); 
// Set device 1 as current
cudaSetDevice(1); 
float* p1;
// Allocate memory on device 1
cudaMalloc(&p1, size); 
// Set device 0 as current
cudaSetDevice(0);
// Launch kernel on device 0
MyKernel<<<1000, 128>>>(p0); 
// Set device 1 as current
cudaSetDevice(1); 
// Copy p0 to p1
cudaMemcpyPeer(p1, 1, p0, 0, size); 
// Launch kernel on device 1
MyKernel<<<1000, 128>>>(p1);
用于启用主机到设备内存的映射,这是另一回事,它关注主机设备内存的移动,而不是对等内存的移动,这是本文的主题

总而言之,您的问题的答案是:

不 不 如果可能,启用UVA并使用cudaMemcpy,您无需指定设备;否则,请使用cudamemcpyper,您需要指定设备。
谢谢但在哪种情况下设置CUDADevice0或1;我必须在启动CudamemCPyperp1,1,p0,0,size;,之前到达吗;,在0或1中?@Alex我认为这与此无关,因为您在调用cudaMemcpyPeer.Thank时指定了源设备和目标设备。但是如果我使用cudaMemcpyPeerAsync,,,,stream;然后我必须使用SetCudDevice设置上下文;这个流是在什么地方创建的?@Alex我认为在这种情况下你不需要指定设备。从对的回答中,明确指出CUDAEMCPypeeRasync调用将显示在分配给它的流和设备中,尤其是源设备中。另请参见第20张幻灯片上的示例。您必须从另一个角度看待问题。您必须确保在对等异步内存传输的源设备上创建了用作cudaMemcpypeerAsync参数的流。
// Set device 0 as current
cudaSetDevice(0); 
float* p0;
size_t size = 1024 * sizeof(float);
// Allocate memory on device 0
cudaMalloc(&p0, size); 
// Set device 1 as current
cudaSetDevice(1); 
float* p1;
// Allocate memory on device 1
cudaMalloc(&p1, size); 
// Set device 0 as current
cudaSetDevice(0);
// Launch kernel on device 0
MyKernel<<<1000, 128>>>(p0); 
// Set device 1 as current
cudaSetDevice(1); 
// Copy p0 to p1
cudaMemcpyPeer(p1, 1, p0, 0, size); 
// Launch kernel on device 1
MyKernel<<<1000, 128>>>(p1);
cudaSetDeviceFlags(cudaDeviceMapHost);