title: 【CUDA 基础】4.2 内存管理
categories:
- CUDA
- Freshman
tags:
- CUDA内存管理
- CUDA内存分配和释放
- CUDA内存传输
- 固定内存
- 零拷贝内存
- 统一虚拟寻址
- 统一内存寻址
toc: true
date: 2018-05-01 21:39:47


Abstract: 本文主要介绍CUDA内存管理,以及CUDA内存模型下的各种内存的特点。
Keywords: CUDA内存管理,CUDA内存分配和释放,CUDA内存传输,固定内存,零拷贝内存,统一虚拟寻址,统一内存寻址

开篇废话

迷茫和困惑会影响我们的前进,彻底摆脱也许不太可能,但是我们必须肯定信仰的力量,专注你所热爱的,就会走出迷雾。

CUDA编程的目的是给我们的程序加速,尤其是机器学习,人工智能类的计算,CPU不能高效完成,说白了,我们在控制硬件,控制硬件的语言属于底层语言,比如C语言,最头疼的就是管理内存,python,php这些语言有自己的内存管理机制,c语言的内存管理机制——程序员管理。这样的好处是学起来特别困难,但是学会了又会觉得特别爽,因为自由,你可以随意的控制计算机的计算过程。CUDA是C语言的扩展,内存方面基本集成了C语言的方式,由程序员控制CUDA内存,当然,这些内存的物理设备是在GPU上的,而且与CPU内存分配不同,CPU内存分配完就完事了,GPU还涉及到数据传输,主机和设备之间的传输。
接下来我们要了解的是:

  • 分配释放设备内存
  • 在主机和设备间传输内存

为达到最优性能,CUDA提供了在主机端准备设备内存的函数,并且显式地向设备传递数据,显式的从设备取回数据。

内存分配和释放

内存的分配和释放我们在前面已经用过很多次了,前面所有的要计算的例子都包含这一步:

cudaError_t cudaMalloc(void ** devPtr,size_t count)

这个函数用过很多次了,唯一要注意的是第一个参数,是指针的指针,一般的用法是首先我们生命一个指针变量,然后调用这个函数:

float * devMem=NULL;
cudaError_t cudaMalloc((float**) devMem, count)

这里是这样的,devMem是一个指针,定义时初始化指向NULL,这样做是安全的,避免出现野指针,cudaMalloc函数要修改devMem的值,所以必须把他的指针传递给函数,如果把devMem当做参数传递,经过函数后,指针的内容还是NULL。
不知道这个解释有没有听明白,通俗的讲,如果一个参数想要在函数中被修改,那么一定要传递他的地址给函数,如果只传递本身,函数是值传递的,不会改变参数的值。
内存分配支持所有的数据类型,什么int,float。。。这些都无所谓,因为他是按照字节分配的,只要是正数字节的变量都能分配,当然我们根本没有半个字节的东西。
函数执行失败返回:cudaErrorMemoryAllocation.
当分配完地址后,可以使用下面函数进行初始化:

cudaError_t cudaMemset(void * devPtr,int value,size_t count)

用法和Memset类似,但是注意,这些被我们操作的内存对应的物理内存都在GPU上。
当分配的内存不被使用时,使用下面语句释放程序。

cudaError_t cudaFree(void * devPtr)

注意这个参数一定是前面cudaMalloc类的函数(还有其他分配函数)分配到空间,如果输入非法指针参数,会返回 cudaErrorInvalidDevicePointer 错误,如果重复释放一个空间,也会报错。
目前为止,套路基本和C语言一致。但是,设备内存的分配和释放非常影响性能,所以,尽量重复利用!

内存传输

完整内容参考https://face2ai.com/CUDA-F-4-2-内存管理/

 posted on 2018-06-26 17:58  TonyShengTan  阅读(244)  评论(0编辑  收藏  举报