我需要在一些数据上运行很长的内核序列,比如
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;
}
有几种方法可以安排这些操作:
在第二个(异步)案例中,我有几个问题:
如果有人能澄清在这些情况下会发生什么,我将不胜感激,也许在OpenCL规范中有相关内容。
谢谢。
答案 0 :(得分:1)
你的第二个案例是要走的路。
在第二个(异步)案例中,我有几个问题:
Do I have to keep references to all cl_mem objects in the long chain of actions and release them after everything is complete?
是。但是如果所有数据数组都具有相同的大小,我将只使用2,并在每次迭代时一个接一个地覆盖。 然后你只需要有2个内存区域,释放和分配只应该发生在beggining / end。
不要担心数据值不正确,如果设置了正确的事件,处理将等待I / O完成。即:
data -> kernel1 -> data1 -> kernel2 -> data -> kernel3 -> data1
-> I/O operation -> I/O operation
为此,只需设置一个强制kernel3仅在第一个I / O完成时启动的条件。你可以用这种方式链接所有事件。
注意:使用2个队列,一个用于I / O,另一个用于处理将为您带来并行I / O,这是2倍。
分配时重要的是,OpenCL如何处理这种情况 所有内存对象的数量超过了可用的总内存数 设备?
给出错误OUT_OF_RESOURCES或类似错误。
内核只需要输入和输出内核 (应该适合内存),但如果有4个或5个这样的缓冲区怎么办? 超过总数,OpenCL如何分配/释放这些内存 幕后的物品?这对读取有何影响?
除非您将内存设置为主机PTR,否则它不会自动执行此操作。但我不确定OpenCL驱动程序是否会正确处理它。如果我是你,我不会分配超过最大值。
答案 1 :(得分:1)
我的印象很糟糕(抱歉,我要引用规范,但今天无法找到它,所以我降低了我的断言的强度),当你用cl_mem引用排队内核时,它需要保留那些对象,并在内核完成后释放它们。
这可以允许您在引入内核后释放这些对象,而不必等待内核完成运行。这就是异步“clEnqueue”操作与同步操作(即内存释放)协调的方式,并防止运行时和内核使用已释放的内存对象。