我正试图向CUDA新手解释全局内存。我想出了以下虚拟内核,该虚拟内核会阻塞其他线程束中的其他线程,直到选定的线程束将全局变量设置为另一个值为止:
__global__ void with_sync()
{
while (threadIdx.x / 32 != 0)
{
if (is_done != 0)
{
break;
}
}
if (threadIdx.x / 32 == 0)
{
is_done = 1;
printf("I'm done!\n");
}
}
变量is_done
在函数外部被声明为__device__ __managed__ int
(如果我错了,请更正我,这意味着该变量将位于全局内存空间中。
但是,当我执行该内核时(单个块中有1024个1D线程),如下所示:
with_sync<<<1, 1024>>>();
cudaDeviceSynchronize();
I'm done
将按预期打印。但是,CUDA程序不会终止(我在主机代码中放置了cudaDeviceSynchronize()
,以等待所有线程)。这使我想知道其他经纱是否没有收到is_done
变量中的更改。但是,我知道全局内存意味着可以在设备级别(即至少在网格中的所有块)都可以看到该值。
我的问题如下:CUDA是否进行了任何缓存/优化,以致可能发生这种不一致的全局内存视图?有没有办法从驻留在全局内存中的变量访问“最新”值?
答案 0 :(得分:6)
CUDA是否进行了任何缓存/优化,以致可能发生这种不一致的全局内存视图?有没有办法从驻留在全局内存中的变量访问“最新”值?
是的,存在缓存行为。您可以使用volatile
qualifier对其进行修改。
这是一个可行的示例:
$ cat t310.cu
#include <stdio.h>
#ifndef USE_VOLATILE
__device__ __managed__ int is_done = 0;
#else
__device__ volatile __managed__ int is_done = 0;
#endif
__global__ void with_sync()
{
while (threadIdx.x / 32 != 0)
{
if (is_done != 0)
{
break;
}
}
if (threadIdx.x / 32 == 0)
{
is_done = 1;
printf("I'm done!\n");
}
}
int main(){
with_sync<<<1,1024>>>();
cudaDeviceSynchronize();
}
$ nvcc -o t310 t310.cu
$ ./t310
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
^C
$ nvcc -o t310 t310.cu -DUSE_VOLATILE
$ ./t310
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
I'm done!
$
(如果不清楚,则由于挂起,上面的第一次运行被Ctrl-C终止了)
Tesla P100 PCIE CUDA 10.0,CentOS 7