2016-03-05 92 views
1

我的OpenCL程序并不总是在进一步执行主机(C++)代码之前完成。 OpenCL代码只能执行到某个点(它随机是随机的)。代码缩短了一些,所以可能会遗漏一些东西。等内核完成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)抛出:0000005:访问冲突读取位置0x0000002C。

如何让主机等待GPU在这里完成?

编辑:queue.enqueueNDRangeKernel返回-1000。虽然它在一个相当小的内核上返回0

回答

1

当内核完成时,版本1表示信号wait[0] - 这是正确的做法。

版本2要求您的clEnqueueNDRangeKernel()等待wait中的事件,然后再启动内核[显然无法工作]。

就它自己而言,queue.finish() [或clFinish()]应该足以确保您的内核已经完成。

由于您没有完成clCreateUserEvent,并且您没有将它传递给其他任何初始化事件,所以第二个变体不起作用。

这是相当糟糕,它崩溃[它应该返回“无效事件”或一些这样的 - 但大概你正在使用的驱动程序没有办法来检查事件尚未初始化]。我相当肯定与我合作的驱动程序会为这种情况发出错误 - 但我尽量避免出错...

我不知道-1000来自哪里 - 它既不是有效的错误代码,也不是来自CL C++包装的合理的返回值。无论内核是小型还是大型[和/或在短时间内完成]都不应该影响入队的返回值,因为所有应该做的就是排队工作[不能保证它开始直到queue.flush()或执行clFlush]。等待它完成应该发生在其他地方。

我通过原始OpenCL API来完成大部分工作,而不是C++包装器,这就是为什么我指的是他们所做的,而不是C++包装器。