从OpenCL中的GPU内核在GPU上创建主机ptr指向的缓冲区副本

从OpenCL中的GPU内核在GPU上创建主机ptr指向的缓冲区副本,opencl,gpu,Opencl,Gpu,我试图理解CL_MEM_USE_HOST_PTR和CL_MEM_COPY_HOST_PTR是如何工作的。 基本上,当使用CL_MEM_USE_HOST_PTR时,比如在创建2D图像时,这不会将任何内容复制到设备,而是GPU将引用主机上的映射内存(ClenqueueEmapBuffer映射它),进行处理,然后我们可以将结果写入其他位置 另一方面,如果我使用CL_MEM_COPY_HOST_PTR,它将在设备上创建主机PTR指向的数据的副本(我猜它将创建一个单独的副本,而不仅仅是缓存)。现在,将对复

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

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

所以我的问题是。。。
只是出于好奇,我想这样做。我将使用CL_MEM_use_HOST_PTR,现在即使设备可以访问主机内存,我希望GPU内核在设备本身上创建一个单独的副本(不使用copy_HOST_PTR,因为这也是在主机本身中完成的),然后对该数据进行处理。如何做到这一点???

使用CL\u MEM\u READ\u 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;
    }
}
\uuuu内核无效initOffsetBuffer(\uuu全局int*offsetBuffer,const int offsetBufferLength,const int startValue){
int gid=获取全局id(0);
int gs=获取全局大小(0);
int i;

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

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


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

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

CL_MEM_USE_HOST_PTR-CL_MEM对象使用主机_PTR引用的内存,因此设备可以直接修改主机上分配的数据,这样我们就不涉及任何数据传输

__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];
    }
}