3

在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 中的共享内存)

4

1 回答 1

3

您可以在 OpenCL 中找到完全相同的 API。

它在 CUDA 上的工作原理:

根据这个介绍官方文档

关于钱的报价cudaHostGetDevicePointer

传回由 cudaHostAlloc 分配或由 cudaHostRegister 注册的映射主机内存的设备指针。

CUDAcudaHostAlloc的工作方式与OpenCL 中的cudaHostGetDevicePointer工作方式完全相同。基本上,如果它是一个独立的 GPU,结果会缓存在设备中,如果它是一个与主机共享内存的独立 GPU,它将直接使用内存。因此,在 CUDA 中没有使用离散 GPU 进行实际的“零复制”操作。CL_MEM_ALLOC_HOST_PTRMapBuffer

该函数cudaHostGetDevicePointer不接受原始的 malloced 指针,就像 OpenCL 中的限制一样。从 API 用户的角度来看,这两种方法完全相同,允许实现进行几乎相同的优化。

使用离散 GPU,您获得的指针指向 GPU 可以通过 DMA 直接传输内容的区域。否则驱动程序将获取您的指针,将数据复制到 DMA 区域,然后启动传输。

但是在 OpenCL2.0 中,这显然是可能的,具体取决于您设备的功能。通过最精细的粒度共享,您可以使用随机分配的主机指针,甚至可以对主机使用原子,因此您甚至可以在主机运行时从主机动态控制内核。

http://www.khronos.org/registry/cl/specs/opencl-2.0.pdf

有关共享虚拟内存规范,请参见第 162 页。请注意,当您编写内核时,即使从内核的角度来看,这些仍然只是 __global 指针。

于 2013-11-05T09:07:05.577 回答