Memory 在OpenCL(如CUDA)中是否有供内核使用的主机内存的设备端指针?

Memory 在OpenCL(如CUDA)中是否有供内核使用的主机内存的设备端指针?,memory,cuda,opencl,zero-copy,Memory,Cuda,Opencl,Zero Copy,在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

在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.
int*a、*b、*c;//主机指针
int*dev_a、*dev_b、*dev_c;//指向主机内存的设备指针
…       
cudaHostGetDevicePointer(&dev_a,a,0);//记忆。现在不需要复制到设备,但需要PTR
cudaHostGetDevicePointer(&dev_b,b,0);
cudaHostGetDevicePointer(&dev_c,c,0);
…   
//内核启动
添加(开发a、开发b、开发c);
//dev_a、dev_b、dev_c被传递到内核,以便内核直接访问主机内存。
在上面的示例中,内核代码可以通过
devu a
devu b
devu c
访问主机内存。内核可以利用这些指针直接将数据从主机移动到共享内存,而无需通过全局内存进行中继


但似乎在OpenCL中这是一项不可能完成的任务?(OpenCL中的本地内存与CUDA中的共享内存相对应)

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

它在CUDA上的工作原理:

根据"基本法"和"基本法",

关于cudaHostGetDevicePointer的货币报价:

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

CUDA
cudaHostAlloc
with
cudaHostGetDevicePointer
的工作原理与
CL\u MEM\u ALLOC\u HOST\u PTR
with
MapBuffer
在OpenCL中的工作原理完全相同。基本上,如果是离散GPU,结果会缓存在设备中,如果是与主机共享内存的离散GPU,则会直接使用内存。因此,CUDA中的离散GPU没有实际的“零拷贝”操作

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

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

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


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

不可能具有相同的功能。但是,它不是一个核心功能。我想不出哪种情况下你真的被迫做这种手术。在调用内核之前,是否可以只调用clEnqueueWriteBuffer()?设备本地缓存对您来说是一个限制因素吗?它是重叠传输和计算的好方式。避免了从主机端发出的显式复制操作,该操作只能将数据从主机复制到设备全局内存。通过设备端指针,数据可以直接在主机和共享内存之间传输。它允许根据需要进行设备调度计算和数据传输,这意味着数据传输可能是隐藏的。传统的方法是多流(CUDA)和多命令队列(OpenCL)。传统的方法需要在主机端显式调度,这使得整个代码有点难看/毛茸茸的。嗨,谢谢你的回复。但我认为OpenCL2.0并不能满足我最初的目的。在OpenCL1.2中,CL_既不使用_HOST_PTR,也不使用CL_MEM_ALLOC_HOST_PTR。实际上,我查看了Nvidia的SDK示例和最佳实践指南,然后我意识到所有OpenCL技巧都是在内核启动之前玩的,因此这无助于重叠传输和计算(CUDA的主机内存设备端指针是这样做的,因为根据内核的要求,传输在内核启动之后开始)这取决于实际转移发生的阶段。即使在内核启动之前发出命令,实现也完全可以在内核启动之前确保读取。但是,在大多数情况下,这不是最佳方式,在大多数情况下,简单地缓存内存对象是最快的。你有什么特别的理由想直接从主机传输int大小的块吗?我编辑了主要的帖子。根据我发现的信息,Cuda设备端指针只是固定的内存,将在Cuda内核启动之前缓存在离散的GPU上。这并不奇怪,因为如果在启动前不传输数据,PciE总线上的内存延迟将完全破坏性能。谢谢sharpneli。似乎缓存是离散GPU必须的(隐式的)。第一个问题是缓存在哪里?(在GPU内存上还是在GPU内存下?)。一个更重要的问题是,在获取设备端指针(内核启动)之前,必须完全完成缓存?或者,即使在内核启动之后,也可以根据内核的需要以流水线方式进行缓存。前者类似于OpenCL的机制,后者可能具有传输-计算-重叠的优势。GPU的全局内存是仅次于本地内存的最快内存,因此实现几乎肯定会在这里移动所有数据。它的延迟约为PCIe总线延迟的1/100。缓存将完全完成,因为您可以看到,在获得设备指针后,无法再从主机写入缓冲区。我建议您在GPU中计算前一阶段时,只需为下一阶段的计算传输缓冲区。在当前硬件中,试图重叠已经运行的内核的传输很可能是一种浪费。