对于P2P复制,cudaMemcpy()和CUDAMEMCPyper()之间有什么区别?
我想不使用CPU-RAM直接将数据从GPU0-DDR复制到GPU1-DDR 如第15页所述:对于P2P复制,cudaMemcpy()和CUDAMEMCPyper()之间有什么区别?,cuda,gpgpu,nvidia,Cuda,Gpgpu,Nvidia,我想不使用CPU-RAM直接将数据从GPU0-DDR复制到GPU1-DDR 如第15页所述: 如果我使用,那么我必须首先设置一个标志cudaSetDeviceFlags(cudadevicemapost) 我是否必须使用从函数cudaHostGetDevicePointer(&uva_ptr,ptr,0)中得到的cudaMemcpy()指针 功能是否有任何优势?如果没有优势,为什么需要它 统一虚拟寻址(UVA)为所有CPU和GPU内存启用一个地址空间,因为它允许根据指针值确定物理内存位置 带UV
cudaSetDeviceFlags(cudadevicemapost)
李>
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,则通过cudamemcypeer
完成点对点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
(您不需要指定设备);否则,请使用cudaMemcpyPeer
(您需要指定设备)
谢谢但是在启动cudamemcypeer(p1,1,p0,0,size)之前,我必须在哪个上下文中(setCudaDevice(0或1);
)
,在0或1中?@Alex我认为这与此无关,因为您在调用cudamemcypeer
时指定了源设备和目标设备。谢谢。但是如果我使用cudaMemcpyPeerAsync(,,,,stream)
那么我必须使用setCudaDevice()设置上下文吗
此流是在哪个位置创建的?@Alex我认为在这种情况下您不需要指定设备。从对的回答中,明确指出,cudaMemcpyPeerAsync
调用将显示在分配给它的流(和设备)中,尤其是源设备。另请参见第20张幻灯片上的示例。您必须从另一个角度看待问题。您必须确保在对等异步内存传输的源设备上创建了用作cudamemcypeerasync
参数的流。
// 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);