如何在 CUDA 中正确使用全局内存?

How I use global memory correctly in CUDA?

本文关键字:全局 内存 CUDA      更新时间:2023-10-16

我正在尝试在 CUDA 中创建一个使用设备定义的全局内存的应用程序。 此变量在 .cuh 文件中声明。

在另一个文件中,.cu 是我的主要文件,我在其中做 cudaMallocs 和 cudaMemCpy。

这是我代码的一部分:

cudaMalloc((void**)&varOne,*tam_varOne * sizeof(cuComplex));
cudaMemcpy(varOne,C_varOne,*tam_varOne * sizeof(cuComplex),cudaMemcpyHostToDevice);

varOne 在 .cuh 文件中声明如下:

__device__ cuComplex *varOne;

当我启动我的内核(我没有将 varOne 作为参数传递)并尝试使用调试器读取 varOne 时,它说无法读取变量。指针地址为 000..0,所以显然它是错误的。

那么,我必须如何在 CUDA 中声明和复制全局内存?

首先,您需要声明指向将从 CPU 复制到 GPU 的数据的指针。在上面的示例中,我们希望将数组original_cpu_array复制到 CUDA 全局内存。

int original_cpu_array[array_size];   
int *array_cuda;

计算数据将占用的内存大小。

int size = array_size * sizeof(int);

库达内存分配:

msg_erro[0] = cudaMalloc((void **)&array_cuda,size);

从 CPU 复制到 GPU:

msg_erro[0] = cudaMemcpy(array_cuda, original_cpu_array,size,cudaMemcpyHostToDevice);

执行内核

从 GPU 复制到 CPU:

msg_erro[0] = cudaMemcpy(original_cpu_array,array_cuda,size,cudaMemcpyDeviceToHost);

可用内存:

cudaFree(array_cuda);

出于调试原因,通常我将函数调用的状态保存在数组中。(例如,cudaError_t msg_erro[var];)。这不是绝对必要的,但如果在分配和内存传输期间发生错误,它将为您节省一些时间。

如果确实发生错误,我使用如下函数打印它们:

void printErros(cudaError_t *erros,int size, int flag)
{
for(int i = 0; i < size; i++)
if(erros[i] != 0)
{
if(flag == 0) printf("Alocacao de memoria");
if(flag == 1) printf("CPU -> GPU  ");
if(flag == 2) printf("GPU -> CPU  ");
printf("{%d} => %sn",i ,cudaGetErrorString(erros[i]));
}
}

该标志主要用于指示代码中发生错误的部分。例如,在内存分配后:

msg_erro[0] = cudaMalloc((void **)&array_cuda,size);
printErros(msg_erro,msg_erro_size, 0);

我尝试了一些示例,发现如果不传递给全局变量,就不能直接在内核中使用全局变量。即使您在 .cuh 文件中初始化,也需要在 main() 中初始化。

原因:

  1. 如果全局声明它,则不会在 GPU 全局内存中分配内存。您需要使用cudaMalloc((void**)&varOne,sizeof(cuComplex))来分配内存。它只能在 GPU 上分配内存。声明__device__ cuComplex *varOne;仅用作原型和变量声明。但是,在使用cudaMalloc((void**)&varOne,sizeof(cuComplex))之前不会分配内存。
  2. 此外,您最初需要将 main() 中的*varOne初始化为 Host 指针。使用cudaMalloc()后,就会知道指针是设备指针。

步骤顺序是:(对于我测试的代码)

int *Ad;        //If you can allocate this in .cuh file, you dont need the shown code in main()
__global__ void Kernel(int *Ad){
....
}
int main(){
....
int size=100*sizeof(int);
cudaMalloc((void**)&Ad,size);
cudaMemcpy(Ad,A,size,cudaMemcpyHostToDevice);
....
}