2012-10-03 52 views
0

当我尝试在内核中查找有关原子操作的更多细节时,发现有些奇怪的东西。据我所知,当在一个数字上使用原子操作时,所有线程的所有这类操作都将被序列化以启动此数字以保持完整性。以下是我的一个内核代码: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]的最新值,该值应该是新值。但是我的实验表明,无论我设置了多大的值,结果总是正确的,即无论T1遇到多长时间,T2始终可以读取正确的值(新值)。任何人都可以帮助看看这种情况?非常感谢。

回答

2
  1. 编译器可能足够聪明地发现你的“延迟”循环没有副作用并完全优化它。

  2. 在GPU上,来自同一工作组的OpenCL工作项通常在lock-step(至少在某种程度上取决于确切的硬件)下运行。这意味着两个线程同时执行相同的指令。他们基本上共享一个指令指针。如果有不同的控制流程,每个线程都会记录它是否当前处于活动状态,并且只有在执行当前指令时才记录。原子操作仍然是序列化的。