OpenCL中的障碍

在OpenCL中,我的理解是可以使用barrier()函数来同步工作组中的线程。 我确实(通常)了解他们是什么以及何时使用它们。 我也意识到工作组中的所有线程都必须碰到障碍,否则就会出现问题。 不过,每次我试图使用屏障到目前为止,这似乎导致我的视​​频驱动程序崩溃,或者访问某种types的无效内存的错误消息。 到目前为止,我已经在2个不同的video卡上看到了这一点(1个ATI,1个NVIDIA)。

所以,我的问题是:

  1. 任何想法为什么会发生?
  2. barrier(CLK_LOCAL_MEM_FENCE)barrier(CLK_GLOBAL_MEM_FENCE)之间有什么区别? 我阅读了文档,但我不清楚。
  3. 关于何时使用barrier(CLK_LOCAL_MEM_FENCE)barrier(CLK_GLOBAL_MEM_FENCE)什么一般规则?
  4. 是否曾经有一段时间调用barrier()与错误的参数types可能会导致错误?

正如你所说的,障碍只能同步同一工作组中的线程。 没有办法在内核中同步不同的工作组。

现在回答你的问题,这个规范对我来说也不是很清楚,但是在我看来,第6.11.9节包含了答案:

CLK_LOCAL_MEM_FENCE – 屏障function将刷新存储在本地存储器中的任何variables,或排队存储器栏以确保将存储器操作正确sorting到本地存储器。

CLK_GLOBAL_MEM_FENCE – 屏障函数将对内存栏进行排队,以确保将内存操作正确sorting到全局内存。 当工作项目,例如,写入缓冲区或图像内存对象,然后想要读取更新的数据时,这可能很有用。

所以,据我的理解,写入和读取__local本地存储器空间时应使用CLK_LOCAL_MEM_FENCE,写入__local全局存储器空间时应使用CLK_GLOBAL_MEM_FENCE。

我还没有testing过这是否是慢的,但大多数情况下,当我需要一个屏障,并且对于哪个内存空间受到影响有疑问的时候,我简单地使用两者的组合,即:

 barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE); 

这样,你不应该有任何内存读\写订购问题(只要你确信组中的每一个线程通过障碍,但你知道这一点)。

希望能帮助到你。

在这里复兴一个古老的线程。 我自己也有一点障碍()。

关于你的碰撞问题,一个潜在的原因可能是如果你的障碍是在一个条件。 我读到,当你使用障碍时,组中的所有工作项必须能够达到该指令,否则将挂起你的内核 – 通常会导致崩溃。

 if(someCondition){ //do stuff barrier(CLK_LOCAL_MEM_FENCE); //more stuff }else{ //other stuff } 

我的理解是,如果一个或多个工作项目满足某些条件,所有工作项目必须满足这个条件,否则会有一些工作项目会跳过障碍。 障碍等到所有工作项目达到这一点。 要修复上面的代码,我需要重新构造一下:

 if(someCondition){ //do stuff } barrier(CLK_LOCAL_MEM_FENCE); if(someCondition){ //more stuff }else{ //other stuff } 

现在所有的工作项目都会到达障碍。

我不知道这适用于循环的程度。 如果一个工作项目从一个for循环中断,它是否会遇到障碍? 我不确定。

更新:我已经成功地崩溃了一些for循环障碍ocl程序。 确保所有工作项目同时退出for循环 – 或者更好的是,把屏障放在循环之外。

(来源:使用OpenCL的异构计算第5章,第90-91页)