CUDA C和C有很多相似的地方,其中的cudaMalloc和C语言的malloc就是一粒。但首次使用cudaMalloc时还是难于理解其为啥要使用二重指针。对于这个问题我思考了一段时间,也找了一些资料查看,现在觉得算是理解了,故在此记录整理一下。

       cudaMalloc和C语言的malloc都是为了动态的分配指定字节的内存。首先我们看一下这两个函数的原始定义。

       1、void *malloc(size_t size)

   2、__host__ ​ __device__ ​cudaError_t cudaMalloc ( void** devPtr, size_t size )

            Allocate memory on the device.

          Parameters

           devPtr

          - Pointer to allocated device memory

           size

         - Requested allocation size in bytes

           Returns

          cudaSuccess, cudaErrorInvalidValue, cudaErrorMemoryAllocation

通过上面我看到,两个函数的最大的不同是函数的返回值类型,malloc返回的是void *,而cudaMalloc返回的是cudaError_t(它不是指针类型哦,对其实根本原因就是这个),CUDA中的函数好像都是采用这种结构返回值类型为cudaError_t,但现在我们是想得到函数cudaMalloc在device上申请的内存,这可咋搞?既然要把申请的内存地址返回给一个指针,那就用二重指针解决吧,这样既解决了CUDA函数返回类型的统一,也解决了申请的内存地址返回给一个指针问题

下面是我的一个小实验用于证实这个想法:

#include <stdio.h>
#include<stdlib.h>

void P1Malloc(int* p)
{
	p=(int*)malloc(10);
	printf("P1Malloc,current malloc address:%p\n",p);
}

void P2Malloc(void** p)
{
	*p=malloc(10);
	printf("P2Malloc,current malloc address:%p\n",*p);
}

int main()
{
	int Num=10;
	int* a=&Num;
	printf("initial pointer a:%p\n",a);
	P1Malloc(a);
	printf("after using *,ponter a:%p\n",a);
	P2Malloc((void**)&a);
	printf("after using **,ponter a:%p\n",a);

	return 0;
}

打印结果如下:

initial pointer a:0x7ffd4751803c
P1Malloc,current malloc address:0xd8b500
after using *,ponter a:0x7ffd4751803c
P2Malloc,current malloc address:0xd8b520
after using **,ponter a:0xd8b520

程序不多解释,有点c语言基础一看就懂,实验发现只有void P2Malloc(void** p)真正把新申请的内存地址给了指定变量。

好了理解了这些基本上也就解决了这个疑惑。

在查阅资料时遇到了一些好的blog放置在此

1、https://stackoverflow.com/questions/7989039/use-of-cudamalloc-why-the-double-pointer

这篇blog的问答都很不错,我摘录一段回答得分最好的网友的解释:

All CUDA API functions return an error code (or cudaSuccess if no error occured). All other parameters are passed by reference. However, in plain C you cannot have references, that's why you have to pass an address of the variable that you want the return information to be stored. Since you are returning a pointer, you need to pass a double-pointer.

Another well-known function which operates on addresses for the same reason is the scanf function. How many times have you forgotten to write this & before the variable that you want to store the value to? ;)

int i;
scanf("%d",&i);

2、https://blog.csdn.net/TwT520Ly/article/details/81100301

这篇blog没有过多理论,主要使用了一些示例代码,简洁明了,我的示例程序和她很相似。

GitHub 加速计划 / ma / mall
76.84 K
28.62 K
下载
mall项目是一套电商系统,包括前台商城系统及后台管理系统,基于SpringBoot+MyBatis实现,采用Docker容器化部署。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。
最近提交(Master分支:2 个月前 )
cf9ddbf5 - 4 个月前
70a226f4 - 4 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐