【问题标题】:Creating a copy of the buffer pointed by host ptr on the GPU from GPU kernel in OpenCL在 OpenCL 中从 GPU 内核创建由主机 ptr 指向的缓冲区的副本
【发布时间】:2012-07-08 05:34:56
【问题描述】:

我试图了解 CL_MEM_USE_HOST_PTR 和 CL_MEM_COPY_HOST_PTR 的工作原理。 基本上当使用 CL_MEM_USE_HOST_PTR 时,比如在创建 2D 图像时,这不会将任何内容复制到设备,而是 GPU 将参考主机上的映射内存(clEnqueueMapBuffer 映射它),进行处理,我们可以将结果写入其他位置.

另一方面,如果我使用 CL_MEM_COPY_HOST_PTR,它将创建设备上主机 ptr 指向的数据的副本(我猜它会创建一个单独的副本而不仅仅是缓存)。现在将对复制到设备的数据进行处理,然后将结果再次复制到主机。希望我理解正确。

所以我的查询是... 我想这样做只是出于我的好奇心。我将使用 CL_MEM_USE_HOST_PTR 现在即使设备可以访问主机内存,我希望 GPU 内核在设备本身上创建一个单独的副本(不使用 COPY_HOST_PTR,因为这再次在主机本身中完成)然后执行处理这些数据。这是怎么做到的??

【问题讨论】:

    标签: opencl gpu


    【解决方案1】:

    使用 CL_MEM_READ_WRITE 创建要复制到的缓冲区,但不要在主机上对其进行初始化。 我最近不得不为连续整数初始化一个新缓冲区

    cl_mem _offsetBuffer;
    _offsetBuffer = clCreateBuffer(_context, CL_MEM_READ_WRITE, (size_t)(count * sizeof(cl_int)), NULL, &errorCode);
    

    上面的 clCreateBuffer 除了为您提供内存对象的句柄外,不会对主机的内存做任何事情。然后我使用内核来分配顺序值,因为事实证明显卡上的内存速度比在 cpu 上分配值快得多。

    __kernel void initOffsetBuffer(__global int* offsetBuffer, const int offsetBufferLength, const int startValue){
        int gid = get_global_id(0);
        int gs = get_global_size(0);
        int i;
        for(i=gid;i<offsetBufferLength;i+=gs){
            offsetBuffer[i] = i+startValue;
        }
    }
    

    此时主机内存中仍然没有缓冲区的副本。我需要使用 clEnqueueReadBuffer 将其复制到主机。

    您可以轻松地将此代码修改为复制内核,而不仅仅是直接赋值。

    __kernel void copyBuffer(__global const int* srcBuffer, __global int* dstBuffer, const int bufferLength){
        int gid = get_global_id(0);
        int gs = get_global_size(0);
        int i;
        for(i=gid;i<bufferLength;i+=gs){
            dstBuffer[i] = srcBuffer[i];
        }
    }
    

    【讨论】:

      【解决方案2】:

      OpenCL 缓冲区通常在主机内存中具有其“位”的副本(这是在 OpenCL 规范中调用缓冲区内容的方式)。这是必要的,因为设备内存是有限的,并且这些位通常只有在内核使用时才会传输到设备。

      当您使用 USE_HOST_PTR 创建缓冲区时,您允许 OpenCL 运行时将 host_ptr 位置用于此主机内存副本。当内核将使用缓冲区时,这些位将被复制到设备中。执行后,您需要确保这些位同步回您的主机内存。这是通过调用clEnqueueMapBuffer来完成的,这个函数返回的指针将在你的主机内存区域内。

      当您使用 COPY_HOST_PTR 创建缓冲区时,运行时会分配缓冲区的新主机内存副本,并将您的位复制到其中。通常,此时不会向设备发送任何内容。

      【讨论】:

        【解决方案3】:

        CL_MEM_HOST_PTR - 实际上 cl_mem 对象将在设备上分配内存并复制主机指针指定的数据。对设备端缓冲区对象的任何修改对主机端都是不可见的。

        CL_MEM_USE_HOST_PTR - cl_mem 对象使用host_ptr 提供的内存,因此设备可以直接修改分配在主机上的数据,这样我们不涉及任何数据传输。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-23
          • 1970-01-01
          • 2023-03-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多