atomicInc()无法正常运作

阿尔文

我已经尝试过以下使用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

我不明白为什么它没有增加。谁能帮忙

罗伯特·克罗维拉

参考文档atomicInc执行以下操作:

对于以下内容:

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

计算:

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

并将结果存储回 count[0]

(如果不确定?操作员的工作方式,请查看此处

由于您已传递n= 1,并且count[0]1开始,所以atomicInc从不实际将变量count[0]增加到1以上。

如果您希望看到它增加到大于1,则为传递一个更大的值n

该变量n实际上充当增量过程的“滚动值”。当要增加的变量实际达到的值时n,下一个atomicInc会将其重置为零。

尽管您没有问过这个问题,但是您可能会问:“如果我要达到转存值,为什么为什么我永远不会看到零值?”

要回答这个问题,您必须记住所有4个线程都在同步执行。它们中的所有4个都atomicInc在执行后续的print语句之前执行该指令。

因此,我们有一个count[0]从1开始的变量

  1. 执行原子的第一个线程将其重置为零。
  2. 下一个线程将其递增为1。
  3. 第三个线程将其重置为零。
  4. 第四个也是最后一个线程将其递增为1。

然后,所有4个线程都会打印出该值。

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

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

如评论中的@talonmies所示,如果您将交换atomicIncatomicAdd

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

您将获得预期的结果。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章