CUDA C++从设备全局内存访问结构体触发非法内存访问问题
CUDA全局__device__结构体指针非法内存访问的原因分析
全局__device__变量的赋值方式错误
主机端不能直接给__device__修饰的指针赋值。比如下面的错误写法:__device__ MyStruct* dev_global_ptr; int main() { MyStruct* dev_ptr; cudaMalloc(&dev_ptr, sizeof(MyStruct)); // 错误:主机端直接赋值会让dev_global_ptr存主机虚拟地址,设备访问无效 dev_global_ptr = dev_ptr; kernel<<<1,1>>>(); }正确操作必须用
cudaMemcpyToSymbol把设备地址拷贝到全局变量:cudaMemcpyToSymbol(dev_global_ptr, &dev_ptr, sizeof(MyStruct*));而你把结构体指针作为参数传给内核时,传递的是
dev_ptr(正经的设备地址),内核直接用这个有效地址访问自然没问题;但全局指针如果没这么做,存的就是无效地址,一访问就触发非法内存错误。全局变量初始化顺序问题
复杂项目里,__device__全局指针的设备端初始化逻辑可能还没执行,你就启动了内核。比如设备模块加载后,全局变量的初始化代码滞后于内核启动,导致指针还是空值或者无效值。而传参的方式是主机端明确分配好有效地址再传递,完全不存在这个时序问题。地址空间混淆
CUDA主机和设备是独立地址空间,__device__变量存在设备全局内存里。如果你误把主机端malloc出来的地址赋值给全局指针,或者没通过CUDA API完成地址映射,设备端访问时这个地址就是无效的。而传参时你用的是cudaMalloc分配的设备地址,自然能正常访问。
内容的提问来源于stack exchange,提问作者Evelyn
相关产品推荐
相关产品推荐

