OpenCL缓冲区创建

时间:2018-11-25 21:35:25

标签: opencl buffer-objects

我对OpenCL还是很陌生,尽管到目前为止我都了解所有内容,但是在理解缓冲区对象的工作方式方面还是有困难。

我不知道缓冲区对象的存储位置。在this StackOverflow问题中指出:

  

如果只有一台设备,则可能(99.99%)将位于设备中。 (在极少数情况下,如果设备暂时没有足够的内存,则可能在主机中)

对我来说,这意味着缓冲区对象存储在设备内存中。但是,如this StackOverflow问题中所述,如果在CL_MEM_ALLOC_HOST_PTR中使用了标志clCreateBuffer,则使用的内存很可能是固定内存。我的理解是,固定内存时不会将其换出。这意味着固定的内存必须位于RAM中,而不是在设备内存中。

那到底是怎么回事?

我想知道这些标志的作用:

  • CL_MEM_USE_HOST_PTR
  • CL_MEM_COPY_HOST_PTR
  • CL_MEM_ALLOC_HOST_PTR

暗示有关缓冲区的位置。

谢谢

2 个答案:

答案 0 :(得分:2)

我们首先来看一下clCreateBuffer的签名:

cl_mem clCreateBuffer(
    cl_context context,
    cl_mem_flags flags,
    size_t size,
    void *host_ptr,
    cl_int *errcode_ret)

这里没有参数可以为OpenCL运行时提供一个确切的设备,缓冲区应放入该设备,因为上下文可以有多个设备。运行时仅在我们使用缓冲区对象时才知道,例如对其进行读/写操作,因为这些操作需要连接到特定设备的命令队列。

每个内存对象都驻留在主机内存或上下文设备的内存之一中,运行时可能会根据需要迁移它。 因此,通常,每个内存对象在OpenCL运行时中可能都有一块内部主机内存。运行时实际执行的操作取决于实现,因此我们不能做太多的假设,也无法获得可移植的保证。 。这意味着有关固定等的所有内容都依赖于实现,您只能寄希望于最佳状态,但要避免使用一定会阻止使用固定内存的模式。

我们为什么要固定存储? 固定内存意味着,我们进程的地址空间中内存页面的虚拟地址具有固定转换为RAM的物理内存地址。这样就可以使用PCIe在GPU的设备内存和CPU内存之间进行DMA(直接内存访问)传输(对物理地址进行操作)。 DMA降低了CPU负载,并可能提高了复制速度。因此,我们希望固定OpenCL内存对象的内部主机存储器,以提高内部主机存储器和OpenCL存储器对象的设备存储器之间的数据传输性能。

作为基本的经验法则:如果运行时分配了主机内存,则可能会将其固定。如果在应用程序代码中分配它,则运行时将悲观地假设它未固定-这通常是正确的假设。

  

CL_MEM_USE_HOST_PTR

允许我们为OpenCL实现提供内存以用于对象的内部主机存储。这并不意味着如果我们调用内核,内存对象将不会迁移到设备内存中。由于该内存是由用户提供的,因此运行时无法假定其已固定。在设备传输之前,这可能会导致在未固定的内部主机存储和固定的缓冲区之间产生额外的副本,从而为主机设备传输启用DMA。

  

CL_MEM_ALLOC_HOST_PTR

我们告诉运行时为该对象分配主机内存。 可以固定

  

CL_MEM_COPY_HOST_PTR

我们提供主机内存来从中复制初始化缓冲区,而不在内部使用它。我们也可以将其与CL_MEM_ALLOC_HOST_PTR结合使用。运行时将为内部主机存储分配内存。 可以固定。

希望有帮助。

答案 1 :(得分:0)

specification在这个主题上(故意吗?)含糊不清,为实现者留出了很多自由。因此,除非您要定位的OpenCL实施对标志做出明确保证,否则应将其视为建议。

首先,CL_MEM_COPY_HOST_PTR实际上与分配无关,这只是意味着您希望clCreateBuffer用{{1}处的内存内容预填充已分配的内存。 },您转接到了电话。就像您使用host_ptr调用clCreateBuffer且没有此标志,然后进行了阻塞的clEnqueueWriteBuffer调用来写入整个缓冲区。

关于分配方式:

  • host_ptr = NULL-这意味着您已经预先分配了一些内存,并且已经正确对齐,并且希望将其用作缓冲区的后备内存。如果设备不支持直接访问主机内存,或者驱动程序确定到VRAM的卷影副本将比直接访问系统更有效,则实现仍可以分配设备内存并在缓冲区和分配的内存之间来回复制。记忆。在 可以直接从系统内存中读取的实现中,这是零拷贝缓冲区的一种选择。
  • CL_MEM_USE_HOST_PTR-这是一个提示,告诉OpenCL实施您打算通过将其映射到主机地址空间来从主机端访问缓冲区,但是与CL_MEM_ALLOC_HOST_PTR不同,您要离开分配给OpenCL实现本身。对于支持它的实现,这是零拷贝缓冲区的另一种选择:创建缓冲区,将其映射到主机,获取主机算法或I / O以写入映射的内存,然后取消映射并在GPU内核中使用。与CL_MEM_USE_HOST_PTR不同,这为使用可直接映射到CPU地址空间(例如PCIe BAR)的VRAM敞开了大门。
  • 默认值(以上2个都不选):分配给设备最方便的位置。通常是VRAM,并且如果设备不支持将内存映射到主机内存,这通常意味着,如果将其映射到主机地址空间,则会得到2个缓冲区副本,一个在VRAM中,一个在系统内存中,而OpenCL实施会在2之间进行内部来回复制。

请注意,该实现还可以使用提供的任何访问标志(CL_MEM_USE_HOST_PTRCL_MEM_HOST_WRITE_ONLYCL_MEM_HOST_READ_ONLYCL_MEM_HOST_NO_ACCESSCL_MEM_WRITE_ONLY和{{1} })来影响在哪里分配内存的决定。

最后,关于“固定”内存:许多现代系统都具有IOMMU,并且当它处于活动状态时,从设备进行的系统内存访问可能会导致IOMMU页面错误,因此从技术上讲,甚至不需要驻留主机内存。无论如何,OpenCL实现通常与内核级设备驱动程序进行深度集成,该驱动程序通常可以根据需要固定系统内存范围(从分页中排除它们)。因此,如果使用CL_MEM_READ_ONLY,则只需要确保提供适当对齐的内存即可,实现将为您固定。