0

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

    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] 的最新值,这应该是新值。但我的实验表明,无论我设置多大的k值,结果总是正确的,即无论T1遇到多长时间的延迟,T2总能读取到正确的值( newValue )。谁能帮忙调查一下这个案子?非常感谢。

4

1 回答 1

2
  1. 编译器可能足够聪明,可以确定您的“延迟”循环没有副作用并完全优化它。

  2. 在 GPU 上,来自同一工作组的 OpenCL 工作项通常以同步方式运行至少在一定程度上,取决于具体的硬件)。这意味着两个线程同时执行相同的指令。它们基本上共享一个指令指针。在发散控制流的情况下,每个线程都会记住它当前是否处于活动状态,并且只有在处于活动状态时才执行当前指令。原子操作仍然是序列化的。

于 2012-10-04T07:38:21.087 回答