我有很长的内核序列,我需要在一些数据上运行,比如
data -> kernel1 -> data1 -> kernel2 -> data2 -> kernel3 -> data3 etc.
我还需要将所有中间结果复制回主机,所以这个想法类似于(伪代码):
inputdata = clCreateBuffer(...hostBuffer[0]);
for (int i = 0; i < N; ++i)
{
// create output buffer
outputdata = clCreateBuffer(...);
// run kernel
kernel = clCreateKernel(...);
kernel.setArg(0, inputdata);
kernel.setArg(1, outputdata);
enqueueNDRangeKernel(kernel);
// read intermediate result
enqueueReadBuffer(outputdata, hostBuffer[i]);
// output of operation becomes input of next
inputdata = outputdata;
}
有几种方法可以安排这些操作:
- 最简单的是总是等待上一个入队操作的事件,所以我们在继续下一个内核之前等待读取操作完成。我可以在不需要缓冲区时立即释放它们。
- 或者使一切尽可能异步,其中内核和读取队列只等待以前的内核,因此缓冲区读取可以在另一个内核运行时发生。
在第二种(异步)情况下,我有几个问题:
- 我是否必须在长链操作中保留对所有 cl_mem 对象的引用并在一切完成后释放它们?
- 重要的是,当所有内存对象的总和超过设备上可用的总内存时,OpenCL 如何处理这种情况?在任何时候内核都只需要输入和输出内核(应该适合内存),但是如果这些缓冲区中有 4 或 5 个超过了总数,OpenCL 如何在幕后分配/释放这些内存对象?这对读取有何影响?
如果有人能澄清在这些情况下会发生什么,我将不胜感激,也许在 OpenCL 规范中有与此相关的内容。
谢谢你。