在OpenCL 1.2中的内核之间传递变量/内核之间的通信

时间:2016-10-26 12:33:43

标签: c++ kernel opencl global communication

我对OpenCL比较陌生。我正在使用OpenCL 1.2 C ++包装器。假设我有以下问题:我有三个整数值a,b和c都在主机上声明

int a = 1;
int b = 2;
int c = 3;
int help;
int d;

d是我的结果,帮助成为帮助变量。

我想计算d =(a + b)* c。为此,我现在有两个名为'add'和'multiply'的内核。

目前,我正在通过以下方式执行此操作(请不要因为我的指针编程方式而感到困惑):首先,我创建缓冲区

bufferA = new cl::Buffer(*context, CL_MEM_READ_ONLY, buffer_length);
cl::Buffer bufferB = new cl::Buffer(*context, CL_MEM_READ_ONLY, buffer_length);
bufferC = new cl::Buffer(*context, CL_MEM_READ_ONLY, buffer_length);
bufferHelp = new cl::Buffer(*context, CL_MEM_READ_WRITE, buffer_length);
bufferD = new cl::Buffer(*context, CL_MEM_WRITE_ONLY, buffer_length);

然后,我为添加内核

设置我的内核参数
add->setArg(0, *bufferA);
add->setArg(1, *bufferB);
add->setArg(2, *bufferHelp);

和multiplicatoin内核

multiply->setArg(0, *bufferC);
multiply->setArg(1, *bufferHelp);
multiply->setArg(2, *bufferD);

然后我将我的数据排入队列

queueAdd->enqueueWriteBuffer(*bufferA, CL_TRUE, 0, datasize, &a);
queueAdd->enqueueWriteBuffer(*bufferB, CL_TRUE, 0, datasize, &b);
queueAdd->enqueueNDRangeKernel(*add, cl::NullRange, global[0], local[0]);
queueAdd->enqueueReadBuffer(*bufferHelp, CL_TRUE, 0, datasize, &help);

和乘法

queueMult->enqueueWriteBuffer(*bufferC, CL_TRUE, 0, datasize, &c);
queueMult->enqueueWriteBuffer(*bufferHelp, CL_TRUE, 0, datasize, &help);
queueMult->enqueueNDRangeKernel(*multiply, cl::NullRange, global[0], local[0]);
queueMult->enqueueReadBuffer(*bufferD, CL_TRUE, 0, datasize, &d);

这很好用。但是,我不想将帮助值复制回主机,然后再次返回设备。为实现这一目标,我想到了3种可能性:

  1. 一个全局变量,用于设备端的帮助。这样做,两个内核都可以随时访问帮助的值。
  2. 内核在运行时添加调用内核。然后我们将c的值插入到添加内核中,并在添加完成后立即将help和c传递给multiply内核。
  3. 只需将帮助值传递给乘法内核即可。我在这里搜索的内容类似于OpenCL 2.0可用的管道对象。有没有人知道类似的OpenCL 1.2。?
  4. 如果有人能提出解决问题的最顺畅的方法,我将非常感激!

    提前致谢!

1 个答案:

答案 0 :(得分:2)

无需读写bufferHelp。只需将其留在设备内存中即可。您提出的解决方案的数量1)cl::Buffers已经是如何,设备内存中的全局变量。

这相当于您的代码,并会产生相同的结果:

queueAdd->enqueueWriteBuffer(*bufferA, CL_FALSE, 0, datasize, &a);
queueAdd->enqueueWriteBuffer(*bufferB, CL_FALSE, 0, datasize, &b);
queueAdd->enqueueNDRangeKernel(*add, cl::NullRange, global[0], local[0]);
//queueAdd->enqueueReadBuffer(*bufferHelp, CL_FALSE, 0, datasize, &help);

queueMult->enqueueWriteBuffer(*bufferC, CL_FALSE, 0, datasize, &c);
//queueMult->enqueueWriteBuffer(*bufferHelp, CL_FALSE, 0, datasize, &help);
queueMult->enqueueNDRangeKernel(*multiply, cl::NullRange, global[0], local[0]);
queueMult->enqueueReadBuffer(*bufferD, CL_TRUE, 0, datasize, &d);

注意:我也改变了阻塞写入调用,这将提供更好的速度,因为缓冲区C的复制和内核的执行"添加"可以并行化。