我使用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
我不明白为什么它没有递增。任何人都可以帮忙
答案 0 :(得分:7)
参考documentation,atomicInc
执行此操作:
以下内容:
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开始。
然后所有4个线程都打印出值。
作为另一个实验,尝试启动5个线程而不是4个线程,看看你是否可以预测打印出来的值。
ker<<<1,5>>>(hitCount_d);
正如@talonmies在评论中指出的那样,如果您将atomicInc
替换为atomicAdd
:
int x = atomicAdd ((unsigned int *)&count[0],n);
你会得到你可能期待的结果。