为了更清楚地说明(希望如此),
mem_fence()
等待直到调用工作项在 mem_fence() 之前对本地和/或全局内存进行的所有读/写操作对工作组中的所有线程都是可见的。
这来自:http: //developer.download.nvidia.com/presentations/2009/SIGGRAPH/asia/3_OpenCL_Programming.pdf
内存操作可以重新排序以适应它们正在运行的设备。规范声明(基本上)内存操作的任何重新排序都必须确保内存在单个工作项中处于一致状态。但是,如果您(例如)执行存储操作并且 value 决定暂时住在工作项特定的缓存中,直到更好的时间出现来写入本地/全局内存怎么办?如果您尝试从该内存中加载,写入该值的工作项会将其保存在其缓存中,所以没问题。但是工作组中的其他工作项没有,因此它们可能会读取错误的值。放置内存栅栏可确保在调用内存栅栏时,本地/全局内存(根据参数)将保持一致(任何缓存都将被刷新,
我承认它仍然令人困惑,我不会发誓我的理解是 100% 正确的,但我认为这至少是一般的想法。
跟进:
我找到了这个关于 CUDA 内存栅栏的链接,但同样的一般想法也适用于 OpenCL:
http://developer.download.nvidia.com/compute/cuda/2_3/toolkit/docs/NVIDIA_CUDA_Programming_Guide_2.3.pdf
查看第B.5 节记忆栅栏功能。
他们有一个代码示例,可以在一次调用中计算一组数字的总和。该代码设置为计算每个工作组中的部分总和。然后,如果要进行更多求和,则代码让最后一个工作组完成这项工作。
因此,每个工作组基本上都做了两件事:部分和,更新全局变量,然后是计数器全局变量的原子增量。
之后,如果还有更多工作要做,将计数器增加到 ("work-group size" - 1) 的值的工作组将被视为最后一个工作组。该工作组继续完成。
现在,问题(正如他们解释的那样)是,由于内存重新排序和/或缓存,计数器可能会增加,并且最后一个工作组可能会在部分总和全局变量拥有它之前开始工作写入全局内存的最新值。
内存栅栏将确保该部分总和变量的值在移过栅栏之前对于所有线程都是一致的。
我希望这有点道理。这令人困惑。