Opencl 排队到循环中的设备端队列

Opencl 排队到循环中的设备端队列,opencl,Opencl,在我的代码中有kernelA和kernelBkernelB取决于kernelA结果。我正在对这个内核进行多次迭代,每次迭代都取决于上一次迭代的结果 截取的主机端排队代码如下所示: for(int x = 0; x < iterations; ++x) { queue.enqueueNDRangeKernel(kernelA, cl::NullRange, cl::NDRange(3*256, 1), cl::NDRange(256, 1)); queue.enqueueND

在我的代码中有kernelAkernelBkernelB取决于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上运行时从内核返回的结果是错误的。有时内核也会挂起,这可能表明内核同步可能有问题。同样的代码在Intel CPU上运行良好,不确定这是运气好还是内核中的同步点有问题



更新:
enqueue\u内核在第1025个enqueue命令上失败,出现错误
-1
。我试图获得更详细的错误(在构建过程中添加了
-g
),但没有成功。我将设备队列大小增加到最大,但这并没有改变任何事情(1025 enqueue命令仍然失败)。删除
kernelA
kernelB
的内容也不会改变任何东西。有什么想法吗?

回答一个老问题,希望能在将来为某人节省时间。如果在设备上查询
CL\u DEVICE\u MAX\u ON\u DEVICE\u EVENTS
,它将返回1024。这是“在设备上”可以排队的最大事件数。这就是它在1025队列上失败的原因。如果您在不同的GPU(如Intel)上运行OpenCL代码,您可能会幸运地得到一个真正的错误代码,它将是
CLK\u DEVICE\u QUEUE\u FULL
或-161。AMD忽略了
-g
选项,在设备排队失败时,AMD似乎只会返回-1。

在您的第一个代码段(从主机排队)中,kernelA的工作组大小设置为
3*256
。在第二次截取(从设备排队)中,内核的工作组大小设置为
256
?它们应该是相同的吗?@jprice
kernelA
kernelB
对于这两个版本来说是完全相同的<代码>内核
在这两种情况下都作为3个工作组启动,共256个工作项。请注意,内核端排队设置为
nRange_1D(3*256,256)
。好的,但是问题顶部的主机排队代码会为
kernelA
启动一个
3*256
工作项的工作组,而不是
256
工作项的
3
工作组。@jprice,是的,你是对的,这只是我在准备剪报的时候犯的一个错误,很抱歉,这很公平。看不出代码还有什么问题。如果只运行一个迭代,它是否会产生正确的结果?您是否尝试过检查
enqueue_内核
函数是否总是返回
CLK_SUCCESS
__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));