关于CUDA结构体数组cudaMemcpy调用的疑问:为何用HostToDevice?
关于CUDA中cudaMemcpy拷贝结构体指针成员的疑问解答
嘿,这个问题抓得特别准!我来给你把逻辑理清楚,你就明白为啥这里用cudaMemcpyHostToDevice是对的了:
先搞懂各个变量的“身份”和位置
dev_arr1、dev_arr2、dev_arr3是主机端的指针变量:它们本身存在主机内存里,里面存储的内容是cudaMalloc分配出来的设备内存地址。dev_s是设备端的结构体指针:它指向的是我们在设备内存上分配的结构体空间,结构体里的arr1、arr2、arr3成员是用来保存设备数组地址的指针位。
这段cudaMemcpy到底在拷贝什么?
我们要做的是:把主机端dev_arr1里存的设备地址值,写到设备端结构体dev_s的arr1成员里。这时候:
- 数据源的位置是主机端:
&dev_arr1取的是主机上dev_arr1这个变量的地址,我们要拷贝的是这个主机变量里的内容(也就是设备数组的地址)。 - 数据目标的位置是设备端:
dev_s->arr1是设备内存里结构体的成员,我们要把地址值写到这里。
所以用cudaMemcpyHostToDevice完全符合数据传输的方向——从主机到设备,一点问题都没有!
什么时候才用cudaMemcpyDeviceToDevice?
如果是要把设备内存里的数组数据(比如dev_arr1指向的设备数组内容)拷贝到另一块设备内存(比如dev_arr2指向的空间),那才需要用cudaMemcpyDeviceToDevice。但这里根本不是拷贝数组内容,只是把“设备数组的地址”这个值从主机传到设备结构体里,方向完全不同。
举个更直观的代码场景:
// 主机端定义设备指针变量 float *dev_arr1, *dev_arr2, *dev_arr3; // 分配设备内存,此时dev_arr1里存的是设备地址(主机变量) cudaMalloc(&dev_arr1, sizeof(float)*100); cudaMalloc(&dev_arr2, sizeof(float)*100); cudaMalloc(&dev_arr3, sizeof(float)*100); // 设备端结构体指针 struct MyStruct *dev_s; cudaMalloc(&dev_s, sizeof(MyStruct)); // 把主机端dev_arr1里的设备地址,拷贝到设备结构体的arr1成员 cudaMemcpy(&(dev_s->arr1), &dev_arr1, sizeof(dev_s->arr1), cudaMemcpyHostToDevice);
总结一下:别被“dev_”前缀迷惑,要看清楚实际传输的数据是在主机还是设备,这里传输的是主机端保存的设备地址值,所以方向是HostToDevice。
内容的提问来源于stack exchange,提问作者horus
相关产品推荐
相关产品推荐

