为什么我需要在主机上声明CUDA变量才能在Device上分配它们

时间:2017-03-27 04:58:40

标签: cuda

我刚刚开始尝试再次学习CUDA并遇到了一些我不太了解的代码。

// declare GPU memory pointers
float * d_in;
float * d_out;

// allocate GPU memory
cudaMalloc((void**) &d_in, ARRAY_BYTES);
cudaMalloc((void**) &d_out, ARRAY_BYTES);

当声明GPU内存指针时,它们会在主机上分配内存。 cudaMalloc调用抛弃了d_ind_out指向浮点数的信息。

我想不出为什么cudaMalloc需要知道主机内存d_in& d_out最初已存储。我甚至不清楚为什么我需要使用主机字节来存储任何主机地址d_in& d_out指向。

那么,主机上原始变量声明的目的是什么?

=============================================== =======================

我会认为这样的事情会更有意义:

// declare GPU memory pointers
cudaFloat * d_in;
cudaFloat * d_out;

// allocate GPU memory
cudaMalloc((void**) &d_in, ARRAY_BYTES);
cudaMalloc((void**) &d_out, ARRAY_BYTES);

这样,GPU相关的一切都发生在GPU上。如果在主机代码中意外使用d_ind_out,则在编译时可能会抛出错误,因为这些变量不会在主机上定义。

我想我也感到困惑的是,通过在主机上存储设备内存地址,感觉设备不完全负责管理自己的内存。感觉主机代码意外覆盖d_ind_out的值,或者通过在主机代码中意外分配它们或另一个更微妙的错误,这可能导致GPU无法访问它自己的记忆。同样,分配给d_in&的地址似乎很奇怪。 d_out由主机选择,而不是设备。为什么主机应该知道设备上哪些地址不可用?

我在这里没有理解的是什么?

2 个答案:

答案 0 :(得分:3)

  

我想不出为什么cudaMalloc需要知道主机内存中的位置d_in& d_out最初已存储

这只是C pass by reference成语。

  

我甚至不清楚为什么我需要使用主机字节来存储任何主机地址d_in& d_out指向。

好的,让我们按照您的方式设计API。这是主机上的典型操作序列 - 在设备上分配一些内存,将一些数据复制到该内存,启动内核以对该内存执行某些操作。您可以自己思考如何在没有指向存储在主变量中的已分配内存的指针的情况下执行此操作:

cudaMalloc(somebytes);
cudaMemcpy(?????, hostdata, somebytes, cudaMemcpyHOstToDevice);
kernel<<<1,1>>>(?????);

如果我们可以解释如果我们没有存储在主机变量中的设备上的内存分配地址,那么应该用?????做什么,那么你真的要做些什么。如果你不能,那么你已经推断出我们将主机变量中GPU分配的内存返回地址存储的基本原因。

此外,由于使用类型化主机指针来存储设备分配的地址,因此CUDA运行时API可以进行类型检查。所以这个:

__global__ void kernel(double *data, int N);

// .....
int N = 1 << 20;
float * d_data;
cudaMalloc((void **)&d_data, N * sizeof(float));
kernel<<<1,1>>>(d_data, N);

可以在编译时报告类型不匹配,这非常有用。

答案 1 :(得分:1)

您的基本概念失败是混合主机端代码和设备端代码。如果你从CPU上的代码执行中调用cudaMalloc(),那么,它就在CPU上:它想要使用CPU内存中的参数,以及CPU内存中的结果。你自找的。 cudaMalloc告诉GPU /设备要分配多少(设备的)内存,但如果CPU /主机想要访问该内存,则需要一种方法来引用它会明白。设备上的内存位置是一种方法。

或者,您can设备端代码中调用它;然后一切都发生在GPU上。 (虽然坦率地说,我自己从来没有这样做过,除非在特殊情况下这不是一个好主意。)