Compiler construction 何时将volatile与共享CUDA内存一起使用

Compiler construction 何时将volatile与共享CUDA内存一起使用,compiler-construction,cuda,gpu,gpgpu,volatile,Compiler Construction,Cuda,Gpu,Gpgpu,Volatile,在什么情况下,应该将volatile关键字与CUDA内核的共享内存一起使用?我知道volatile告诉编译器永远不要缓存任何值,但我的问题是关于共享数组的行为: __shared__ float products[THREADS_PER_ACTION]; // some computation products[threadIdx.x] = localSum; // wait for everyone to finish their computation __syncthreads();

在什么情况下,应该将
volatile
关键字与CUDA内核的共享内存一起使用?我知道
volatile
告诉编译器永远不要缓存任何值,但我的问题是关于共享数组的行为:

__shared__ float products[THREADS_PER_ACTION];

// some computation
products[threadIdx.x] = localSum;

// wait for everyone to finish their computation
__syncthreads();

// then a (basic, ugly) reduction:
if (threadIdx.x == 0) {
    float globalSum = 0.0f;
    for (i = 0; i < THREADS_PER_ACTION; i++)
        globalSum += products[i];
}
\uuuuu共享\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
//一些计算
产品[threadIdx.x]=localSum;
//等待每个人完成他们的计算
__同步线程();
//然后(基本的,丑陋的)减少:
if(threadIdx.x==0){
浮球温度=0.0f;
对于(i=0;i
在这种情况下,我是否需要
产品
?每个数组条目仅由单个线程访问,但在末尾除外,该线程的所有内容都由线程0读取。编译器是否可能缓存整个数组,因此我需要它是易变的,还是只缓存元素


谢谢

如果不将共享数组声明为volatile,那么编译器可以根据自己的选择,通过在寄存器(其作用域特定于单个线程)中为任何线程定位共享内存中的位置,从而自由地优化这些位置。无论您是否仅从一个线程访问特定的共享元素,这都是正确的。因此,如果使用共享内存作为块线程之间的通信工具,最好将其声明为volatile。然而,这种通信模式通常还需要执行障碍来强制执行读/写顺序,因此请继续阅读下面的障碍

显然,如果每个线程只访问自己的共享内存元素,而从不访问与另一个线程关联的元素,那么这并不重要,编译器优化也不会破坏任何东西

在您的情况下,如果您有一段代码,其中每个线程正在访问它自己的共享内存元素,并且唯一的线程间访问发生在一个很好理解的位置,那么您可以使用强制编译器逐出临时存储在寄存器中的任何值,返回到共享数组。因此,您可能认为
\uuu threadfence\u block()
可能有用,但在您的情况下,
\uu syncthreads()
。因此,您的
\uuu syncthreads()
调用足以强制线程同步,以及强制将共享内存中的任何寄存器缓存值逐出回共享内存


顺便说一下,如果你的代码结尾的减少是性能问题,你可以考虑使用并行还原方法来加速它。

伟大的答案,我不知道内存击剑。非常感谢。