原子函数真的使CUDA中的变量不稳定吗?

原子函数真的使CUDA中的变量不稳定吗?,cuda,atomic,Cuda,Atomic,我已经编写了一个非常简单的代码,要求线程0更新一个全局变量,而其他线程一直在读取该变量。但我发现其他线程并没有真正获得该值 代码在这里,非常简单。有人能给我一些建议如何修理它吗? 非常感谢 \uuuuu全局\uuuuuu无效添加内核(int*c) { int i=threadIdx.x; int j=0; 如果(i==0) { 而(*c

我已经编写了一个非常简单的代码,要求线程0更新一个全局变量,而其他线程一直在读取该变量。但我发现其他线程并没有真正获得该值

代码在这里,非常简单。有人能给我一些建议如何修理它吗? 非常感谢

\uuuuu全局\uuuuuu无效添加内核(int*c)
{
int i=threadIdx.x;
int j=0;
如果(i==0)
{
而(*c<2000){
int temp=*c;
printf(“*c=%d\n”,*c);
原子(c,温度,温度+1);
}       
}否则{
而(*c<1000)
{
j++;
}
}

}

我想打个比方:想象一下,原子操作是互斥体:为了让程序得到良好定义,访问共享资源的两个线程必须都同意使用互斥体以独占方式访问资源。如果其中一个线程在不首先持有互斥锁的情况下访问资源,则结果是未定义的

原子学也是如此:如果您决定将内存中的某个特定位置视为原子变量,那么访问该位置的所有线程都应该同意并将其视为原子变量,这样您的程序才有意义。您应该只通过原子加载和存储操作它,而不是通过非原子操作和原子操作的组合

换言之,这:

atomicCAS(c,temp, temp+1);
包含原子负载比较存储。生成的指令将一直下到全局内存以加载
c
,进行比较,然后一直下到全局内存以存储新值

但这是:

while(*c < 2000)
但据我所知,在撰写本文时,CUDA中没有这样的结构

关于这一点,<代码> Value限定符<强>可> <强>帮助:它告诉编译器不优化变量,并将其视为“可从外部源修改的”。这将触发每次读取变量的加载,尽管我不确定该加载是否会绕过所有缓存。在实践中,它可能有效,但在理论上我认为你不应该依赖它。此外,这还将禁用对该变量的任何优化(例如常数传播或将变量升级到寄存器以获得更好的性能)

您可能想尝试以下黑客(我没有尝试过):

while(原子添加(c,0)<2000)

这将发出一条从全局内存加载的原子指令,因此应该可以看到
c
的最新值。但是,它还引入了一个(在本例中是无用的)原子存储。

volatile
atomic
是正交概念,在使用原子操作时不需要
volatile
。你想干什么?是的,我想是的。但通过这段代码,我们可以证明原子操作并不会真正使其他线程对该值进行实时更新。是的,没错。其他线程不知道
c
可以从其他地方修改,因此它们仍在从注册表/缓存读取。@Cicada我不完全清楚从注册表/缓存读取是什么意思。原子操作绕过L1并使用L2,L2的可见性在设备范围内。@jackolanten绝对有效,但另一个读取
,而(*c<…)
不是原子加载:它们仍在读取(L1)缓存(或寄存器,取决于编译器优化)。在这种情况下,需要
volatile
来强制负载绕过缓存。嗨,我已经修复了它。被读取的东西不是原子的。所以我们需要将其声明为volatile,并在使用原子函数时将其转换为(int*)。非常感谢@罗伯特·克罗维拉特
while(*c < 2000)
while (atomicLoad(c) < 2000)
while(atomicAdd(c, 0) < 2000)