在CUDA中,我们可以通过主机内存的设备端指针实现从主机内存到设备共享内存的内核管理数据传输。像这样:
int *a,*b,*c; // host pointers
int *dev_a, *dev_b, *dev_c; // device pointers to host memory
…
cudaHostGetDevicePointer(&dev_a, a, 0); // mem. copy to device not need now, but ptrs needed instead
cudaHostGetDevicePointer(&dev_b, b, 0);
cudaHostGetDevicePointer(&dev_c ,c, 0);
…
//kernel launch
add<<<B,T>>>(dev_a,dev_b,dev_c);
// dev_a, dev_b, dev_c are passed into kernel for kernel accessing host memory directly.
在上面的示例中,内核代码可以通过dev_a
,dev_b
和dev_c
访问主机内存。内核可以利用这些指针直接将数据从主机移动到共享内存,而无需通过全局内存中继它们。
但似乎在OpenCL中这是不可能完成的任务? (OpenCL中的本地内存与CUDA中的共享内存相对应)
答案 0 :(得分:3)
您可以在OpenCL中找到完全相同的API。
它如何在CUDA上运作:
根据this presentation和official documentation。
关于cudaHostGetDevicePointer
的报价:
传回分配的映射主机内存的设备指针 cudaHostAlloc或由cudaHostRegister注册。
CUDA cudaHostAlloc
与cudaHostGetDevicePointer
完全相同,CL_MEM_ALLOC_HOST_PTR
与MapBuffer
在OpenCL中有效。基本上如果它是一个独立的GPU,结果会缓存在设备中,如果它是一个与主机共享内存的独立GPU,它将直接使用内存。因此,在CUDA中没有实际的“零拷贝”操作与离散GPU。
函数cudaHostGetDevicePointer
不接受原始malloced指针,就像OpenCL中的限制一样。从API用户的角度来看,这两者是完全相同的方法,允许实现执行几乎相同的优化。
使用离散GPU,指针可以指向GPU可以通过DMA直接传输内容的区域。否则,驱动程序将获取指针,将数据复制到DMA区域,然后启动传输。
但是在OpenCL2.0中明确可行,具体取决于设备的功能。通过最精细的粒度共享,您可以使用随机malloced主机指针甚至在主机上使用原子,因此您甚至可以在主机运行时从主机动态控制内核。
http://www.khronos.org/registry/cl/specs/opencl-2.0.pdf
有关共享虚拟内存规范,请参见第162页。请注意,当您编写内核时,即使从内核的角度来看,它们仍然只是__global指针。