2012-10-16 111 views
1

我想解决一个应用程序,OpenCL可以同时使用CPU和GPU。具体来说,我有两个内核,一个用于CPU执行,另一个用于GPU。 CPU内核会改变一个缓冲区的内容,当GPU检测到缓冲区已被CPU改变时,GPU会做其他事情。从OpenCL中的两个命令队列执行命令异步执行

__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中异步执行两个设备上运行的两个内核?

回答

0

你问的太多了。正如您可能已经注意到的,缓冲区对象与上下文相关,而命令队列与设备相关。 如果内核在缓冲区对象上运行,则相应的数据必须位于此设备上。如果你不用clEnqueueWriteBuffer()明确地传递它,OpenCL将为你做到这一点。因此,如果您在一个设备(例如CPU)上修改具有内核的缓冲区对象,并且刚刚在另一个设备(例如GPU)上修改该缓冲区对象,则OpenCL驱动程序将等待第一个内核完成,传输数据,然后运行第二个内核。

+0

谢谢,但我对你的观点持怀疑态度。首先,我使用零拷贝缓冲区,它被认为是CPU和GPU的一个拷贝,我认为不需要拷贝。其次,您说相应的数据必须位于该设备上,但我使用AMD Fusion APU,主内存由CPU和GPU共享,即在物理上只有一个内存。因此,也许我应该以另一种方式提问:对于AMD Fusion APU,零拷贝区域中的缓冲区在CPU和GPU之间始终保持一致,或者OpenCL实现是否会创建此缓冲区的两个副本并在某个同步点之后保持一致? – acekiller

+0

好的,我不知道你使用AMD Fusion APU。我的回答是基于我对nvidia gpu和opencl实现的经验。我没有使用AMD Fusion的经验。 但是,您的OpenCL实现可能不允许两个不同的命令队列同时访问相同的缓冲区。也许你可以通过使用两种不同的缓冲区来测试它(尽管它打败了你的目的)。 –