我正在使用myvar
说明符在设备上声明全局变量__device__
。我没有在任何地方将它设置为有意义的值(在我的内核启动方法中没有像通常那样使用cudaMemcpyToSymbol)。
我希望myvar
的值是随机垃圾,但每次都是0.0。 CUDA会对设备变量进行自动初始化吗?
我也使用CUDA调试器检查了它,该值实际上是0。
__device__ float myvar;
__global__ void kernel(){
printf("my var: %f", myvar);
}
int kernel_launch(){
kernel<<<1,5>>>();
cudaDeviceSynchronize();
return 0;
}
答案 0 :(得分:2)
CUDA不会自动初始化任何变量。这只是一个基于CUDA实现的巧合,myvar
在您的测试应用中变为零。
在IEEE-754浮点(由NVIDIA GPU使用)中,全零模式对应于0.0,因此它比“1.0f”更可能是“随机”值。
不要根据单个单词中的值来推断所有GPU内存的值...
我做了一个小实验,虽然对结果略感惊讶。我使用myvar
初始化__device__ float myvar(1.1f);
并更改了printf()
,以便它打印变量的值和地址。然后我运行它,得到1.1f
输出并记下地址。然后我删除了初始化并再次运行它。这一次,当地址保持不变时,值返回到0.0f
,表明此变量所在的内存块确实在常规CUDA操作中被清零。例如,如果将CUDA程序复制到其他数据为零的固定大小的块中的GPU,并且myvar
被分配给该块中的地址,则可能发生这种情况。
答案 1 :(得分:0)
__device__
未初始化的变量与其全局__host__
对应变量非常相似,需要在可执行文件中按其大小和位置在内存中声明。据我所知,这样的声明总是需要一个占位符值,不出所料,似乎是零。
这可以很容易地检查。例如,此命令反汇编简单__device__ int a;
声明的输出:
nvcc -o test.o -c -x cu - <<< "__device__ int a;" && cuobjdump -xelf all test.o && nvdisasm *cubin
您将获得以下输出:
.headerflags @"EF_CUDA_TEXMODE_UNIFIED EF_CUDA_64BIT_ADDRESS EF_CUDA_SM20 EF_CUDA_PTX_SM(EF_CUDA_SM20)"
//--------------------- .nv.constant14 --------------------------
.section .nv.constant14,"a",@progbits
.align 4
.align 8
.nv.constant14:
/*0000*/ .dword a
//--------------------- .nv.global --------------------------
.section .nv.global,"aw",@nobits
.align 4
.type a,@object
.size a,(.L_1 - a)
a:
.nv.global:
.zero 4
.L_1:
您可以清楚地看到隐式零初始化。
但是,我认为依靠这一点是不安全的。