从OpenCL中的两个命令队列异步执行命令

时间:2012-10-16 09:30:01

标签: asynchronous opencl

我正在尝试使用OpenCL同时使用CPU和GPU的应用程序。具体来说,我有两个内核,一个用于CPU执行,一个用于GPU。 CPU内核将改变一个缓冲区的内容,当GPU检测到缓冲区已被CPU更改时,GPU将执行其他操作。

__kernel void cpuKernel(__global uint * dst1,const uint size)
{
    uint tid  = get_global_id(0);
    uint size = get_global_size(0);

    while(tid < size)
    {
        atomic_xchg(&dst1[tid],10);

        tid += size;
    }
}

__kernel void gpuKernel(__global uint * dst1, __global uint * dst2, const uint size)
{
    uint tid = get_global_id(0);
    uint size = get_global_size(0);

    while(tid < vectorSize)
    {
        while(dst1[vectorOffset + tid] != 10)
            ;

        dst2[vectorOffset + tid] = dst1[vectorOffset+tid];
        tid += size;
    }
}

如上所示,cpuKernel会将dst1缓冲区的每个元素更改为10,相应地,在GPU检测到这些更改后,它会将元素值(10)分配给另一个缓冲区dst2的相同位置。 cpuKernel在与CPU设备关联的command1中排队,并且gpuKernel在与GPU设备关联的command2中排队,两个命令队列已设置为CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE标志。 然后我做了两个案例: 案例1:

clEnqueueNDRangeKernel(command2,gpuKernel);
clEnqueueNDRangeKernel(command1,cpuKernel);
clfinish(command1);
clfinish(command2);

案例2:

clEnqueueNDRangeKernel(command1,cpuKernel);
clfinish(command1);
clEnqueueNDRangeKernel(command2,gpuKernel);
clfinish(command2);

但结果显示两个案例所消耗的时间几乎相同,但我预计案例1会有一些重叠,但事实并非如此。谁能帮我?谢谢!

或者,任何人都可以帮助解释如何在OpenCL中异步实现在两个设备上运行的两个内核吗?

1 个答案:

答案 0 :(得分:0)

你问的太多了。您可能已经注意到,缓冲区对象与上下文相关,而命令队列与设备相关。 如果内核在缓冲区对象上运行,则相应的数据必须在此设备上。如果你没有用clEnqueueWriteBuffer()明确地转移它,OpenCL会为你做这件事。

因此,如果在一个设备(例如CPU)上修改具有内核的缓冲区对象,并且在另一个设备(例如GPU)之后修改缓冲区对象,则OpenCL驱动程序将等待第一个内核完成,转移数据,然后运行第二个内核。