我已经尝试过以下使用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开始的变量。
然后,所有4个线程都会打印出该值。
作为另一个实验,尝试启动5个线程而不是4个线程,看看是否可以预测输出的值。
ker<<<1,5>>>(hitCount_d);
如评论中的@talonmies所示,如果您将交换atomicInc
为atomicAdd
:
int x = atomicAdd ((unsigned int *)&count[0],n);
您将获得预期的结果。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句