OpenCL 如何在从主机读取结果之前等待设备端队列完成

问题描述 投票:0回答:1

这是我简化的程序结构:

// I call one main kernel from host side
err = clEnqueueNDRangeKernel(queue, main_kernel, 1, NULL, globalSize_g, 0, 0, NULL, NULL);

// Then on device side this kernel goes like this :

__kernel void main_kernel(...
{
    for (int i = 0; i <= 1000...
    {
        enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_NO_WAIT, ...
        .
        .
        .
        enqueue_kernel(get_default_queue(), CLK_ENQUEUE_FLAGS_NO_WAIT, ...
    }
}

//Then back on host side I read the result from a buffer 

clEnqueueReadBuffer(queue, buffer, CL_TRUE, 0, ...);

基本上我有一个内核,然后在循环中对设备端的一堆其他内核进行排队,每个设备端内核都需要等待前一个内核完成。 for 循环显然早于所有设备端内核完成。

我的问题是,当我读回结果时,并非所有设备端内核都已完成执行,因此结果不完整。我的问题是,在读回主机端缓冲区之前,如何确保设备端队列中的所有内容都已完成?

在读回结果之前,我尝试为主机端队列和设备端队列调用 clFinish,但这似乎并不能解决我的问题。

我尝试设置一个事件并像这样等待它,但这也不起作用,因为我假设这只是等待主内核完成,而不是等待设备端内核完成。

cl_event event1;
err = clEnqueueNDRangeKernel(queue, main_kernel, 1, NULL, globalSize_g, 0, 0, NULL, &event1);
clWaitForEvents(1, &event1);

我想也许有一些东西我可以从设备端调用,但我在 OpenCL 规范中找不到专门用于此目的的东西,但也许我错过了它。

我考虑在 for 循环之外放置一个 while 循环,它检查循环中最后一个内核更新的一些全局变量,当该变量达到它应该经历的迭代次数时,我会跳出 while 循环。这看起来很愚蠢,我确信有一个正确的方法可以做到这一点。

c opencl gpgpu
1个回答
0
投票

我发现出了什么问题,显然设备上可以排队的内核数量确实有限制,这是由 CL_DEVICE_MAX_ON_DEVICE_EVENTS 给出的,在我的设备上似乎是 1024,为什么它这么小,让我感到困惑功能相当无用。这仍然不能解释为什么 clFinish 或 clFlush 不会在内核调用之间清空队列,即使我没有达到它的限制,但至少我弄清楚了为什么这不起作用。

© www.soinside.com 2019 - 2024. All rights reserved.