我的OpenCL程序在执行进一步的主机(c ++)代码之前并不总是完成。 OpenCL代码只执行到某个点(它看起来是随机的)。代码缩短了一些,因此可能会遗漏一些东西。
cl::Program::Sources sources;
string code = ResourceLoader::loadFile(filename);
sources.push_back({ code.c_str(),code.length() });
program = cl::Program(OpenCL::context, sources);
if (program.build({ OpenCL::default_device }) != CL_SUCCESS)
{
exit(-1);
}
queue = CommandQueue(OpenCL::context, OpenCL::default_device);
kernel = Kernel(program, "main");
Buffer b(OpenCL::context, CL_MEM_READ_WRITE, size);
queue.enqueueWriteBuffer(b, CL_TRUE, 0, size, arg);
buffers.push_back(b);
kernel.setArg(0, this->buffers[0]);
vector<Event> wait{ Event() };
版本1:
queue.enqueueNDRangeKernel(kernel, NDRange(), range, NullRange, NULL, &wait[0]);
第2版:
queue.enqueueNDRangeKernel(kernel, NDRange(), range, NullRange, &wait, NULL);
wait[0].wait();
queue.finish();
版本1只是不等待OpenCL程序。版本2使程序崩溃(在queue.enqueueNDRangeKernel上):
foo.exe中的0x51D99D09(nvopencl.dll)抛出异常:0xC0000005:访问冲突读取位置0x0000002C。
如何让主机等待GPU在这里完成?
编辑:queue.enqueueNDRangeKernel返回-1000。虽然它在一个相当小的内核上返回0
答案 0 :(得分:1)
版本1表示在内核完成时发出wait[0]
信号 - 这是正确的做法。
版本2要求你的clEnqueueNDRangeKernel()
等待wait
中的事件,然后再启动内核[显然无法工作]。
在它上面,queue.finish()
[或clFinish()
]应该足以确保你的内核已经完成。
由于您尚未完成clCreateUserEvent
,并且您尚未将其传递到初始化该事件的任何其他内容,因此第二个版本无效。
它很糟糕,它会崩溃[它应该返回&#34;无效事件&#34;或者其他一些 - 但可能你正在使用的驱动程序没有办法检查事件是否已经初始化]。我合理地确定我使用的驱动程序会在这种情况下发出错误 - 但我尽量避免错误...
我不知道-1000来自哪里 - 它既不是有效的错误代码,也不是CL C ++包装器的合理返回值。内核是小还是大[和/或短时间或长时间完成]不应该影响入队的返回值,因为所有应该做的就是将工作排入队列[不保证它开始直到queue.flush()
或clFlush
已执行]。等待它完成应该发生在其他地方。
我通过原始OpenCL API完成大部分工作,而不是C ++包装器,这就是为什么我指的是他们所做的,而不是C ++包装器。
答案 1 :(得分:0)
我在使用OpenCL时遇到了类似的问题,即OpenCL不处理某些数据流包。
我意识到这只是在笔记本计算机插入扩展坞时发生的。
也许这对您有帮助。 (没有clFlush或clFinish调用)