OpenCL中的障碍
在OpenCL中,我的理解是可以使用barrier()
函数来同步工作组中的线程。 我确实(通常)了解他们是什么以及何时使用它们。 我也意识到工作组中的所有线程都必须碰到障碍,否则就会出现问题。 不过,每次我试图使用屏障到目前为止,这似乎导致我的视频驱动程序崩溃,或者访问某种types的无效内存的错误消息。 到目前为止,我已经在2个不同的video卡上看到了这一点(1个ATI,1个NVIDIA)。
所以,我的问题是:
- 任何想法为什么会发生?
-
barrier(CLK_LOCAL_MEM_FENCE)
和barrier(CLK_GLOBAL_MEM_FENCE)
之间有什么区别? 我阅读了文档,但我不清楚。 - 关于何时使用
barrier(CLK_LOCAL_MEM_FENCE)
与barrier(CLK_GLOBAL_MEM_FENCE)
什么一般规则? - 是否曾经有一段时间调用
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页)