OpenCL内核中的原子操作



当我试图在内核中找到更多关于原子操作的细节时,我发现了一些奇怪的事情。据我所知,当在一个数字上使用原子操作时,所有线程的所有此类操作都将被序列化,以便在这个数字上启动,以保持完整性。以下是我的一段内核代码:

if(atomic_cmpxchg(&A[ptr],0,-1) == -1)
ptr = A[ptr + 3];
//To delay
uint k = 1000000;
while(k--);
A[ptr + 3] = newValue;

对于上面的代码,假设只有两个线程T1和T2。据我所知,T1和T2都将执行代码片段,但当它们尝试执行atomic_cmpxchg操作时,T2必须等待T1完成(假设T1首先运行)。正如我所设计的,当T1读取A[ptr]时,A[ptr】的旧值是0,因此它将原子地更改为-1。之后,因为对于T1,条件不满足,所以T1将直接进入延迟码并被延迟。现在是T2处理A[ptr]的时候了,因为现在A[ptr】已经设置为-1,所以T2的条件是满足的,所以T2将运行到"ptr=A[ptr+3];"。但我的问题是:因为T2完成条件判断后,它会立即执行"ptr=A[ptr+3];",但T1遇到了延迟,所以A[ptr+3]的值还没有被T1更新(因为k太大了,延迟会很长)。因此T2将不会读取A[ptr+3]的最新值,该值应为newValue。但我的实验表明,无论我设置多大的k值,结果总是正确的,即无论T1遇到多长延迟,T2都可以读取正确的值(newValue)。有人能帮忙调查这个案子吗?非常感谢。

  1. 编译器可能足够聪明,可以发现您的"延迟"循环没有副作用,并完全优化它。

  2. 在GPU上,来自同一工作组的OpenCL工作项通常以锁定步骤运行(至少在一定程度上,取决于确切的硬件)。这意味着两个线程同时执行相同的指令。它们基本上共享一个指令指针。在发散控制流的情况下,如果每个线程当前处于活动状态,则重新进行计数,如果处于活动状态则仅执行当前指令。原子操作仍然是序列化的。

最新更新