atomicInc()不起作用

时间:2013-08-02 04:48:08

标签: cuda gpu-atomics

我使用atomicInc()尝试过以下程序。

__global__ void ker(int *count)
{
    int n=1;
    int x = atomicInc ((unsigned int *)&count[0],n);
    CUPRINTF("In kernel count is %d\n",count[0]);
}

int main()
{
    int hitCount[1];
    int *hitCount_d;

    hitCount[0]=1;
    cudaMalloc((void **)&hitCount_d,1*sizeof(int));

    cudaMemcpy(&hitCount_d[0],&hitCount[0],1*sizeof(int),cudaMemcpyHostToDevice);

    ker<<<1,4>>>(hitCount_d);

    cudaMemcpy(&hitCount[0],&hitCount_d[0],1*sizeof(int),cudaMemcpyDeviceToHost);

    printf("count is %d\n",hitCount[0]);
  return 0;
}

输出是:

In kernel count is 1
In kernel count is 1
In kernel count is 1
In kernel count is 1

count is 1

我不明白为什么它没有递增。任何人都可以帮忙

1 个答案:

答案 0 :(得分:7)

参考documentationatomicInc执行此操作:

以下内容:

atomicInc ((unsigned int *)&count[0],n);

计算:

((count[0] >= n) ? 0 : (count[0]+1))

并将结果存储回count[0]

(如果您不确定?运算符的作用,请查看here

由于您已通过n = 1,而count[0]从1开始,atomicInc实际上从未将变量count[0]实际增加到超过1。

如果您想看到它增加超过1,请为n传递更大的值。

变量n实际上充当&#34;翻转值&#34;用于递增过程。当要递增的变量实际达到n的值时,下一个atomicInc会将其重置为零。

虽然你没有问过这个问题,但你可能会问,&#34;如果我达到翻转价值,为什么我从未看到零值?&#34;

要回答这个问题,你必须记住所有4个线程都是以锁步方式执行的。在执行后续的print语句之前,所有4个都执行atomicInc指令。

因此我们的变量count[0]从1开始。

  1. 执行原子的第一个线程将其重置为零。
  2. 下一个线程将其递增为1.
  3. 第三个帖子将其重置为零。
  4. 第四个也是最后一个线程将其递增为1.
  5. 然后所有4个线程都打印出值。

    作为另一个实验,尝试启动5个线程而不是4个线程,看看你是否可以预测打印出来的值。

    ker<<<1,5>>>(hitCount_d);
    

    正如@talonmies在评论中指出的那样,如果您将atomicInc替换为atomicAdd

    int x = atomicAdd ((unsigned int *)&count[0],n);
    

    你会得到你可能期待的结果。