深度学习 Caffe 内存管理机制理解

栏目: 数据库 · 发布时间: 5年前

内容简介:之前在简书的文章,搬迁过来 ^-^本文是作者原创,如有理解错误,恳请大家指出,如需引用,请注明出处。#Blob内存管理分析

之前在简书的文章,搬迁过来 ^-^

本文是作者原创,如有理解错误,恳请大家指出,如需引用,请注明出处。

#Blob内存管理分析

在caffe的分层结构中,Blob充当了内存管理的角色,屏蔽了上层逻辑代码对于数据的申请释放的感知,同时也屏蔽了底层设备对上层逻辑的影响,本文主要分析Blob的管理机制和实际内存申请单元SyncedMemory 的机制。 首先我们看一下Blob和SyncedMemory的关系,类图如下:

深度学习 Caffe 内存管理机制理解

实际上整个Blob的实现就是在SyncedMemory上封装了一层,所以首先需要分析一下SyncedMemory的实现机制。

##SyncedMemory的实现机制 SyncedMemory的目的是为了屏蔽上层代码对不同硬件设备的内存分配的感知,同时隐藏了CPU和GPU之间的同步过程。同时,SyncedMemory实现时,采用的是 “lazy”的模式,就是内存的实际申请时机是在第一次使用时进行的。有了大体的了解,下面我们来详细分析一下。 下面是SyncedMemory 提供的一组接口,

名称 功能
cpu_data() 获取CPU数据指针
gpu_data() 获取GPU数据指针

实现的代码如下:

const void* SyncedMemory::cpu_data() {
  to_cpu();
 return (const void*)cpu_ptr_;
}

const void* SyncedMemory::gpu_data() {
#ifdef USE_CUDA
  to_gpu();
  return (const void*)gpu_ptr_;
#else
  NO_GPU;
  return NULL;
#endif  // USE_CUDA
}
复制代码

可以看出,每次调用接口时,都会有 to_cpu() 和 to_gpu() 的操作,那么这两个操作是什么作用呢,我们先看下SyncedMemory中的一些关键参数:

名称 功能
cpu_ptr_ cpu数据指针
gpu_ptr_ gpu数据指针
size_ 当前SyncedMemory需要维护的数据个数
head_ 当前 SyncedMemory处于的状态

前三个都比较好理解,最后一个比较特殊,它维护的是 SyncedMemory 当前的状态,分为 UNINITIALIZED,HEAD_AT_GPU,HEAD_AT_CPU ,SYNCED 四中状态。现在介绍一下具体的流程,当第一次调用 to_cpu()时, head_处于UNINITIALIZED状态,那么系统会调用 CPU的申请内存的方式去获得内存区域,之后设置 head_ = HEAD_AT_CPU ,如果中间过程没有GPU设备则不会有状态变动,如果中间有代码调用了 to_gpu() ,则会发现 head_处于 HEAD_AT_CPU 状态,此时会调用同步函数,将数据从CPU同步到GPU, 之后如果又回到CPU上,则同样会发现 head_ 处于HEAD_AT_GPU的状态,那么又会调用相应的同步代码,将数据同步回CPU,通过 head_这样一个状态参数屏蔽了GPU和CPU间的申请和切换的不同。

所以上层业务只需要知道当前自己需要的是CPU还是GPU的数据,然后调用不同的接口,就可以完成数据获取的操作。

##Blob的实现分析 了解了SyncedMemory的实现,再来看Blob 就较为简单了,它仅仅做了一些上层的管理逻辑,向外界提供了几个关键的接口:

名称 功能
cpu_data() 获取CPU数据指针,不能改变数据内容
mutable_cpu_data() 获取CPU数据指针,可以改变数据内容
gpu_data() 获取GPU数据指针,不能改变数据内容
mutable_gpu_data() 获取GPU数据指针,可以改变数据内容
Reshape() 调整数据的维度信息

前四个就是对 SyncedMemory 的 cpu_data() 和 gpu_data()的封装,只需要确保每次获取数据前都调用相对的 to_cpu 或者 to_gpu就可以了。对于最后一个Reshape函数,主要是为了调整维度信息,同时可能是出于适配多种数据格式的目的,所以提供3个重载函数,如下:

void Blob::Reshape(const int num, const int channels,const int height, const int width);
void Blob::Reshape(const BlobShape& shape) ;
void Blob::Reshape(const vector<int>& shape);
复制代码

前两个重载函数仅仅进行了数据格式的转换,然后调用第三个函数,所以 void Blob::Reshape(const vector<int>& shape); 才是实际的执行者,这里需要介绍一下Blob里面较为关键的几个参数:

名称 功能
data_ 数据的实际存储位置
shape_data_ 数据的维度信息存储位置(NCHW)
capacity_ 当前数据块的大小
count_ reshape后的数据块的大小

阅读代码不难发现,cout_中所存储的就是所有维度的的乘积,也就是当前要reshape到的数据大小,整个的reshape 过程如下:

深度学习 Caffe 内存管理机制理解

##结束 以上就是我对Blob的一些理解,希望对大家有帮助。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

解码宇宙

解码宇宙

(美) 塞费 / 隋竹梅 / 上海科技教育出版社 / 2010-4 / 26.00元

《解码宇宙:新信息科学看天地万物》:宇宙,或许就是一台庞大的计算机。这是查尔斯·塞费在《解码宇宙:新信息科学看天地万物》中对宇宙做出的结论。作者从信息的特点开始谈起,详细论述了信息论和量子计算,向我们展示了一种不可思议的拜占庭式宇宙的情景,涉及生命的本质、热力学、相对论、量子力学、黑洞、多重宇宙,直至宇宙的命运。《解码宇宙:新信息科学看天地万物》资料翔实,内容丰富多彩,思路清晰,观点明确,读后使人......一起来看看 《解码宇宙》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试