如何将主机指针传递到映射设备内存而不复制主机数据?

时间:2012-09-17 09:04:40

标签: c opencl gpgpu

我是C,C ++和OpenCL的新手。我有两个问题。

(1)如果我有许多主机输入数据变量,例如长数组和双数组,有什么方法可以避免将每个数据复制到设备(以传统的OpenCL方式,即createBuffer等),而只是简单地映射一些内存从设备进入主机并将主机指针写入设备内存然后在内核中访问?我被告知有,但我无法弄清楚这样做的代码。

下面我有一个示例输入数据数组。目标是以某种方式将指向它的指针中继到设备而不以任何方式复制它,因为各种输入数据变量可能非常大。我分配一个缓冲区,将一个映射缓冲区排入队列,然后获取一个设备指针,但后来我不确定如何将输入传递给该设备指针。我使用了一种cl_long作为设备指针,这可能是错误的。

cl_long inputData[2] = {1,2};

cl_mem inputBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, 
        sizeof(cl_long) * 2, NULL, NULL);

cl long* inputMap = (cl_long*) clEnqueueMapBuffer(
        queue, inputBuffer, TRUE, CL_MAP_WRITE, 0, 
        sizeof(cl_long) * 2, 0, NULL, NULL, NULL);

// what to do here?

clEnqueueUnmapMemObject(queue, inputBuffer, inputMap, 0, NULL, NULL);

我已经将空间用于上面的两个cl_longs,但实际上如果我将指针传递给主机数据,我会在这里分配什么?

(2)将多个输入变量的指针打包到clEnqueueMapBuffer返回的同一个内存空间怎么样?假设我有一个长数组和一个双数组,我可以将指针传递给同一块映射设备内存吗?

我真的很感激一些示例源代码,特别详细说明了主机和设备内存以及它们如何保持同步以及指针,因为我对它们有点新鲜。

P.S。我已经看到了另一个关于将主机数据写入设备映射内存的示例(http://stackoverflow.com/questions/5673794/opencl-mapped-memory-doesnt-work),但它再次使用手动将数据写入内存相当于复制。

更新:回应Raj的评论(如果我的评论太长,请回复此处)我已经开始使用该标志,但我的指针代码可能在某处出错。

double a[2] = { 3.0, 6.0 } ;
size_t pointerSize = sizeof(double*);

cl_mem bufA = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR, pointerSize, NULL, NULL);
clSetKernelArg(kernel, 0, sizeof(cl_mem), &bufA);

double* pA = (double*) clEnqueueMapBuffer(queue, bufA, CL_TRUE, CL_MAP_WRITE, 0, pointerSize, 0, NULL, NULL, &err);
*pA = *a;

此时如果我在内核中打印[0]和[1],我得到:

a[0]=3.000000
a[1]=-0.000000

a [1]显然是错误的。我有什么想法吗?

1 个答案:

答案 0 :(得分:2)

所以答案是使用clCreateBuffer创建缓冲区并传递此参数CL_MEM_ALLOC_HOST_PTR

查看此说明OpenCL create Buffer API

在CUDA架构上,它类似于cudaHostAlloccudaHostAlloc将在主机上分配内存,GPU设备也可以访问该内存。有关相同内容的更多信息,请参阅此Webpage