我有一个启动 OpenCL 内核的循环(大约 10 亿次迭代)。每个内核由 1 个线程执行,并执行非常微不足道的操作。问题是在执行几百万次迭代后,代码冻结(停止)并且程序根本没有终止。它在对 clFinish() 的调用中冻结。程序并不总是在同一个迭代中冻结。
如果每 1000 次迭代调用一次 clFinish() 而不是在每次迭代中调用一次,问题就会消失,所以我觉得问题是 clFinish() 正在等待内核的结束,但内核被杀死(不知何故)在调用 clFinish() 之前。另请注意,当我在循环内插入许多 printf() 调用时,问题就消失了!
当我在 CPU 设备上执行程序时遇到问题(在我的笔记本电脑上,我使用 AMD SDK),并且我在带有 Nvidia Fermi GPU 的机器上也遇到了问题(Nvidia SDK 和驱动程序,AMD SDK 也安装在该机器上)。
我在每次 OpenCL API 调用后检查错误,但未检测到错误。我删除了错误检查以使代码清晰。
我的问题:
他们是否对下面的 OpenCL API 有任何不正确的使用?
如果同时启动大量 OpenCL 内核,它们有什么问题吗?
代码是由我们的一些工具自动生成的,所以请不要问我为什么要调用只有 1 个线程的内核(这是另一个问题,我知道这样的代码不利于性能)。我的目标是了解代码中的问题是什么,理论上应该运行没有任何问题。
主机代码:
/* OpenCL initialization. */
/* ... */
cl_mem dev_acc = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(double), NULL, &err);
for (int h0 = 1; h0 <= ni; h0 += 1)
for (int h2 = 0; h2 < nj; h2 += 1)
for (int h5 = 0; h5 < h2 - 1; h5 += 1) {
size_t global_work_size[1] = {1};
size_t block_size[1] = {1};
cl_kernel kernel2 = clCreateKernel(program, "kernel2", &err);
clSetKernelArg(kernel2, 0, sizeof(cl_mem), (void *) &dev_acc);
clEnqueueNDRangeKernel(queue, kernel2, 1, NULL, global_work_size,block_size,0, NULL, NULL);
clFinish(queue);
clReleaseKernel(kernel2);
}
内核代码:
__kernel void kernel2(__global double *acc)
{
*acc = 1;
}
编译:gcc -O3 -lm -std=gnu99 polybench.c ocl_utilities.c symm_host.c -lOpenCL -lm -I/opt/AMDAPP/include -L/opt/AMDAPP/lib/x86_64
我正在使用 Ubuntu 12.04,内核 3.2.0-29-generic,X86_64,RAM:2 GB