我正在尝试使用原子在 OpenCL 1.2 中实现全局同步,并且想知道是否有任何方法可以确保来自不同工作组的读取(通过程序的逻辑证明,发生在原子增量之后)看到更新结果。
详情: 我有一个我想要计算的值的二叉树(存储为数组)。内部节点的值取决于为其子节点计算的值。有n个叶子,产生n个线程,从叶子->根遍历。
对于任何特定值:
假设有两个线程,不一定在同一个工作组中:
因此,处理任何节点的线程都可以保证其两个子节点都已“实时”处理。我有一个在 CPU 上使用线程池来实现相同想法的工作实现。
问题:
当我从内部节点读取子节点的计算值时,其中少数是陈旧/未初始化的。事实上,即使是相应的子计数器(仅由原子操作修改),也可能给出过时的值(例如,0 或 1,而不是 2)。从上面的过程来看,在访问每个子节点两次之前不可能处理节点。
这表明 OpenCL 1.2 对同一内存上的工作组之间的全局内存读取仅提供最终一致性保证,即使写入是原子的。我的评估正确吗(如果是,有什么办法解决这个问题)吗?
我非常感谢任何有关此事的帮助!
TL;博士: 我知道 OpenCL 1.2 一般来说有一个宽松的一致性内存模型 - 这也适用于原子写入吗? (如果是这样,能否确保原子写入后发生的读取不会过时?)
(如果这是不可能的,这在我看来是一个重大问题,因为涉及读取的原子增量肯定可以与先前的原子写入同步(否则很多正确性保证将被排除在外)?当然,读取也可以通过原子写入在工作组之间同步吗?)
我最终自己解决了这个问题。对于遇到类似问题的其他人来说,原子操作似乎与常规读取不同步,并且 OpenCL API 不提供atomic_load。我自己实现了它(它与来自不同工作组和工作项的写入同步)如下:
uint atomic_load(volatile global uint* ptr) {
return atomic_cmpxchg(ptr, DUMMY_VALUE, DUMMY_VALUE);
}
其中 DUMMY_VALUE 是任意值(唯一重要的部分是最后 2 个参数是相同的值)。
这是有效的,因为如果 *ptr == DUMMY_VALUE,则存储 DUMMY_VALUE 并返回它,如果它们不相等,则保留并返回 *ptr 的旧值。