首页 > 解决方案 > `clCreateBuffer`中`host_ptr`参数的作用是什么

问题描述

host_ptr`clCreateBuffer中的参数是什么意思?

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

从文档中并不清楚:

host_ptr :指向可能已由应用程序分配的缓冲区数据的指针。host_ptr 指向的缓冲区的大小必须大于或等于 size 字节。

对我来说,这听起来像是要复制到设备缓冲区中的主机缓冲区。但是,在许多示例中,我看到此操作实际上是由 执行的,实际上没有任何内容作为参数clEnqueueWriteBuffer传递给。clCreateBufferhost_ptr

你能澄清一下吗?

标签: opencl

解决方案


host_ptr 参数有几种不同的用途,具体取决于传递给 flags 参数的值。使用它的两个标志是CL_MEM_USE_HOST_PTR& CL_MEM_COPY_HOST_PTR。如果 flags 不包含其中任何一个且 host_ptr 不为 NULL,则该函数将给出CL_INVALID_HOST_PTR错误(请参阅clCreateBuffer页面底部的错误)。


CL_MEM_COPY_HOST_PTR

这基本上按照您的描述进行,它将 host_ptr 复制到设备内存中。clCreateBuffer这通过有效地组合&提供了便利clEnqueueWriteBuffer。请注意,您不需要按照要求的命令队列clEnqueueWriteBuffer,数据将在您使用之前复制到上下文中的所有设备,多么方便!

顾名思义,这是一个副本。如果您在设备上写入此内存,则 host_ptr 中的内存将永远不会看到这些写入(除非您执行clEnqueueReadBuffer)。同样,如果您在创建缓冲区后写入 host_ptr,设备上的内存将看不到这些写入(除非您执行clEnqueueWriteBuffer)。

CL_MEM_USE_HOST_PTR

OpenCL 不会在设备内存中创建缓冲区,而是直接使用 host_ptr 指向的内存。如果您的设备是 PCIe 连接上的专用 GPU,这意味着每次您在设备代码中读取或写入此内存时,都必须通过 PCIe 发送数据(慢)。OpenCL 允许设备在内核执行期间创建数据缓存,这在一定程度上有所帮助。如果您的设备与集成 GPU 等主机共享物理内存,则不应有任何此类开销。

请注意,尽管您必须小心确保内存一致性。如果主机在内核处理与其关联的内存时修改了 host_ptr(反之亦然),您将获得未定义的行为。


使用哪个?

这取决于您在做什么以及您正在使用什么硬件。如果您不太担心内存复制性能,并且想要一种简单安全的方法,请使用CL_MEM_COPY_HOST_PTR.

如果设备通过 PCIe(或其他接口)

对于大型数组,通常我会CL_MEM_COPY_HOST_PTR根据需要使用读/写并将其排入队列。如果我只是写入一个 int 或小型结构,我会使用CL_MEM_USE_HOST_PTR, 只是要注意内存一致性。

如果您真的对内存性能感兴趣,您可能需要研究诸如固定内存(AMD GPU 参考)之类的技术。

如果设备共享主机内存(集成 GPU 或仅 CPU 设备)

如果您确信主机和设备在另一个正在写入时不会读取,那么您可以使用CL_MEM_USE_HOST_PTR任何大小的内存对象。为了获得最佳性能,您可能必须确保 host_ptr 对齐并且是特定大小的倍数(对于 Intel 设备,对齐在 4 KB 边界和 64 字节的倍数上)。是有关英特尔硬件零拷贝的更多信息。


推荐阅读