and*_*oke 11 gpgpu memory-fences opencl memory-barriers barrier
与barrier()(我认为我理解)不同,mem_fence()不会影响工作组中的所有项目.OpenCL规范说(第6.11.10节),用于mem_fence():
订单执行内核的工作项的加载和存储.
(因此它适用于单个工作项).
但是,与此同时,在第3.3.1节中,它说:
在工作项内存中具有加载/存储一致性.
所以在工作项中内存是一致的.
那么什么样的东西mem_fence()有用呢?它不适用于项目,但在项目中不需要......
请注意,我没有使用原子操作(第9.5节等).mem_fence()与这些想法一起使用的想法是什么?如果是这样,我很乐意看到一个例子.
谢谢.
更新:我可以看到使用时,它是如何有效使用 barrier()(隐式,由于阻挡调用mem_fence()) -但肯定必须有更多,因为它单独存在?
试着把它说得更清楚(希望如此),
mem_fence()等待,直到对mem_fence()之前的调用工作项所做的对本地和/或全局内存的所有读/写操作对工作组中的所有线程都可见.
它来自:http://developer.download.nvidia.com/presentations/2009/SIGGRAPH/asia/3_OpenCL_Programming.pdf
可以重新排序内存操作以适应它们运行的设备.该规范(基本上)指出任何内存操作的重新排序必须确保内存在单个工作项中处于一致状态.但是,如果您(例如)执行商店操作并且值决定现在直播工作项特定缓存,直到更好的时间呈现给本地/全局内存?如果您尝试从该内存加载,则写入该值的工作项将其包含在其缓存中,因此没有问题.但是工作组中的其他工作项没有,因此他们可能会读错了值.放置内存栅栏可确保在内存栅栏调用时,本地/全局内存(根据参数)将保持一致(任何缓存都将被刷新,任何重新排序都会考虑到您希望其他线程可能此后需要访问此数据).
我承认它仍然令人困惑,我不会发誓我的理解是100%正确的,但我认为这至少是一般的想法.
跟进:
我发现这个链接谈论CUDA内存栅栏,但同样的一般想法适用于OpenCL:
查看B.5内存栅栏功能部分.
他们有一个代码示例,用于计算一次调用中数字数组的总和.设置代码以计算每个工作组中的部分和.然后,如果要做更多的求和,代码就会让最后一个工作组完成工作.
因此,在每个工作组中基本上完成了两件事:一个部分和,它更新一个全局变量,然后是一个计数器全局变量的原子增量.
之后,如果还有其他工作要做,将计数器增加到("工作组大小" - 1)值的工作组将被视为最后一个工作组.那个工作组继续完成.
现在,问题(正如他们解释的那样)是,由于内存重新排序和/或缓存,计数器可能会增加,最后一个工作组可能会在部分和全局变量得到它之前开始工作写入全局内存的最新值.
内存围栏将确保在移动经过围栏之前,该部分和变量的值对于所有线程是一致的.
我希望这是有道理的.这令人困惑.