cudaMemcpy有四种类型:HostToHost, DeviceToHost, HostToDevice, DeviceToDevices
现在我有两个指针:h_ptr
, d_ptr
,分别指向host端某数组的起始位置,和device端数组的起始位置。num
是h_ptr数组的大小,一开始只有host端存有这个数组。
这两个指针是直接定义在host端的,比如
int *h_ptr;
int *d_ptr;
当我要在Device(也就是GPU)上创建一个d_ptr
指向的数组,并把h_ptr
数组的值拷贝过去时:
cudaMalloc((void**)&d_ptr, (num) * sizeof(int)); //注意这里是void**
cudaMemcpy(d_ptr, h_ptr,
sizeof(int) * (num), cudaMemcpyHostToDevice);
需要先在GPU上malloc一段内存,然后使用cudaMemcpyHostToDevice指定内存传输方向,把num个int传过去。
那么现在,虽然d_ptr
仍然是host端的指针,但它指向的地址是device端的了,我在GPU的kernel function中将d_ptr
作为参数传进去,便可以在GPU端通过d_ptr
获取数组的值了:
__global__ void kernel_opt(int *d_ptr, int num){
int id = blockIdx.x * blockDim.x + threadIdx.x;
if(id < num)
d_ptr[id] = calc(d_ptr[id]);
// 计算
}
在GPU端计算完毕之后,可能要把数组中新的值传回host端,也就是d_ptr
到h_ptr
,在host端这样操作即可:
cudaMemcpy(h_ptr, d_ptr, sizeof(int) * (num), cudaMemcpyDeviceToHost);
总结:host端只能获取位于host端的内存(比如 h_ptr[0]
),device端只能获取位于device端的内存(比如 d_ptr[0]
),如要跨界,使用cudaMemcpy。