在我的代码中,我有 kernelA 和 kernelB 。 kernelB 取决于 kernelA 结果。我在这个内核上迭代了数千次,每次迭代都取决于前一次迭代的结果。
剪切的主机端入队代码如下:
for(int x = 0; x < iterations; ++x)
{
queue.enqueueNDRangeKernel(kernelA, cl::NullRange, cl::NDRange(3*256, 1), cl::NDRange(256, 1));
queue.enqueueNDRangeKernel(kernelB, cl::NullRange, cl::NDRange(256, 1), cl::NDRange(256, 1));
}
queue.finish();
上面的代码工作正常。
现在我想将上面的代码移植到使用设备端入队并且我在AMD GPU上遇到问题。内核代码:
__attribute__((reqd_work_group_size(256, 1, 1)))
__kernel void kernelA(...){}
__attribute__((reqd_work_group_size(256, 1, 1)))
__kernel void kernelB(...){}
__attribute__((reqd_work_group_size(1, 1, 1)))
__kernel void kernelLauncher(...)
{
queue_t default_queue = get_default_queue();
clk_event_t ev1, ev2;
for (int x = 0; x < iterations; ++x)
{
void(^fnKernelA)(void) = ^{ kernelA(
... // kernel params come here
); };
if (x == 0)
{
enqueue_kernel(default_queue,
CLK_ENQUEUE_FLAGS_NO_WAIT,
ndrange_1D(3 * 256, 256),
0, NULL, &ev1,
fnKernelA);
}
else
{
enqueue_kernel(default_queue,
CLK_ENQUEUE_FLAGS_NO_WAIT,
ndrange_1D(3 * 256, 256),
1, &ev2, &ev1, // ev2 sets dependency on kernelB here
fnKernelA);
}
void(^fnKernelB)(void) = ^{ kernelB(
... // kernel params come here
); };
enqueue_kernel(default_queue,
CLK_ENQUEUE_FLAGS_NO_WAIT,
ndrange_1D(256, 256),
1, &ev1, &ev2, // ev1 sets dependency on kernelA here
fnKernelB);
}
}
主持人代码:
queue.enqueueNDRangeKernel(kernelLauncher, cl::NullRange, cl::NDRange(1, 1), cl::NDRange(1, 1));
问题是在AMD GPU上运行时从内核返回的结果是错误的。有时内核也会挂起,这可能表明内核同步可能存在问题。相同的代码在Intel CPU上工作正常,不确定这是运气还是内核中的同步点有问题。
更新: enqueue_kernel
在第1025个enqueue命令失败,错误为-1
。我试图获得更详细的错误(在构建期间添加-g
),但无济于事。我将设备队列大小增加到最大但没有改变任何东西(仍然在第1025次排队命令失败)。删除kernelA
和kernelB
的内容也没有改变任何内容。有什么想法吗?
答案 0 :(得分:0)
回答一个老问题,希望将来可以节省一些时间。如果在设备上查询CL_DEVICE_MAX_ON_DEVICE_EVENTS
,它将返回1024。这是您可以在“设备上”排队的最大事件数。这就是为什么它在1025队列上失败。如果您在其他GPU(例如Intel)上运行OpenCL代码,那么您可能很幸运地获得了返回的错误代码,它们是CLK_DEVICE_QUEUE_FULL
或-161。 AMD忽略了-g
选项,除了在设备上排队失败时,-1似乎一无所获。