CUDA入门

您所在的位置:网站首页 调用函数void用法 CUDA入门

CUDA入门

2023-10-09 13:19| 来源: 网络整理| 查看: 265

关于CUDA中cudaMalloc函数的参数问题

很多小伙伴在学习CUDA时接触到的第一个API:cudaMalloc会有疑问,第一个参数为地址指针。关于这个地址指针,今天通过这篇文章阐述我的理解。

cudaMalloc的原型为: cudaError_t cudaMalloc(void** devPtr, size_t size) 这个API与C语言中的malloc大同小异。malloc用法为: int *a = (int )malloc(nsizeof(int)),返回的是一个int型指针,指向大小为n个int型数据的连续内存地址的首地址,可以理解为a是这个数组的首地址。

理解了这个有利于理解cudaMalloc的参数。我们在进行cuda编程时,第一步需要在GPU内分配内存,与数组的声明步骤是一样的。

假如我们要在GPU内申明一段n个大小的float型数组,我们需要定义float *addr,用于指向GPU内这个地址的首地址。因此,addr这个变量中存的就是用户在GPU中声明的float型数组的首地址。

我们需要通过cudaMalloc来改变addr中存的内容,准确地找出GPU中这个数组的首地址。正确的调用方法为:cudaMalloc(float(**)&addr,n*sizeof(float))

下面对它进行完整的解释: 第二个参数大家都知道具体意思了。第一个参数我们首先看到的是&addr。前面我们假设addr内部存放的是一个指向GPU中的数组的首地址,需要对addr的内容进行改变,因此我们必须采用引用的方式进行形参传递。否则,完成了cudaMalloc函数调用后仅仅是形参的值发生变化(参考C语言学习中的引用调用),原来我们声明的float *addr这个实参没有发生任何变化。注意:我们需要的是把addr指针的内容改变,而函数原型的devPtr返回的是地址的值,因此需要通过对addr这个指针进行引用调用,改变其内部的值。

理解了上面的内容,接着是强制类型转换成指针型指针的理解,就简单多了。前面说过,addr是指向地址的指针。cudaMalloc完成了*addr的内容的改变后,需要转换数据类型。把它转换成指针型指针是对于主机端而言的(GPU称为设备端),addr这个变量是指向我们在GPU内部声明的连续地址的首地址,因此,我们对addr进行第一次引用计算,得到的是首地址的值。我们需要通过这个值来在GPU的内存进行操作,因此需要再做一次引用计算,得到的就是GPU中连续地址的第一个单元,接下来就可以进行主机端设备端的内存内容拷贝了。

之所以这样设计,是因为在cudaMemcpy内存拷贝函数中,采用的形参均是地址。这个函数的原型为:

cudaError_t cudaMemcpy(void *dist, const void* src,size_t count,CudaMemcpyKind kind)

前两个参数分别是目的地址和源地址。完成了内存声明后,我们把addr作为形参,这时,dist指针指向了addr的地址。对dist做引用运算后,返回的就是我们声明好的GPU内存的首地址了。

总结: cudaMalloc的参数与我们设置的地址类型数据有一定的关系。由于cudaMemcpy等重要的内存操作函数均以指针作为形参,因此我们需要定义一个与之相同类型的指针完成形参赋值。 由于指针是指向地址的,必须把我们声明的指针变量初始化为GPU的内存首地址。这样一来,addr实质上就变成了一个存放了地址的指针。 这也决定了cudaMalloc函数调用时,需要对addr进行引用计算,将GPU内存首地址放在addr指向的地址中。完成了这个函数调用后,addr就变成了一个指向GPU内存首地址的地址(指针)了。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3