SyncedMemory类主要负责在主机(CPU)和设备(GPU)之间管理内存分配和数据同步工作,封装了CPU和GPU之间的数据交互操作。

补充一点GPU的相关知识:

对CUDA架构而言,主机端的内存被分为两种,一种是可分页内存(pageable memroy)和页锁定内存(page-lock或
pinned)。可分页内存是由操作系统API malloc()在主机上分配的,页锁定内存是由CUDA函数cudaHostAlloc()在主机内存上分配的,页锁定内存的重要属性是主机的操作系统将不会对这块内存进行分页和交换操作,确保该内存始终驻留在物理内存中。

GPU知道页锁定内存的物理地址,可以通过“直接内存访问(Direct Memory Access,DMA)”技术直接在主机和GPU之间复制数据,速率更快。由于每个页锁定内存都需要分配物理内存,并且这些内存不能交换到磁盘上,所以页锁定内存比使用标准malloc()分配的可分页内存更消耗内存空间。

syncedmen.hpp文件注释:

#ifndef CAFFE_SYNCEDMEM_HPP_
#define CAFFE_SYNCEDMEM_HPP_ #include <cstdlib> #include "caffe/common.hpp" //SyncedMemory类也是在caffe命名空间下定义的,主要在Blob类中被调用
namespace caffe {
/*
如果配置为使用GPU,并且GPU可用,则会在主机上分配页锁定内存(Pinned Memory),
与之对应的另一种内存是可分页内存,由主机负责分配和管理,不能由GPU通过地址直接访问
cudaMallocHost函数提供了直接访问主机内存功能(DMA),速率更快
*/
// If CUDA is available and in GPU mode, host memory will be allocated pinned,
// using cudaMallocHost. It avoids dynamic pinning for transfers (DMA).
// The improvement in performance seems negligible in the single GPU case,
// but might be more significant for parallel training. Most importantly,
// it improved stability for large models on many GPUs. /*
CaffeMallocHost函数是对CUDA中cudaMallocHost函数的封装,用于在主机中分配页锁定内存
函数的参数分别是内存地址指针,大小以及是否使用CUDA的bool量
*/
inline void CaffeMallocHost(void** ptr, size_t size, bool* use_cuda) {
#ifndef CPU_ONLY
//如果没有配置只使用CPU,并且显明配置使用GPU
if (Caffe::mode() == Caffe::GPU) {
//cudaMallocHost函数用于分配页锁定内存,参数是内存在主机上的地址指针和大小
CUDA_CHECK(cudaMallocHost(ptr, size)); //检查CUDA操作返回的异常信息码
*use_cuda = true;
return;
}
#endif
*ptr = malloc(size); //如果定义只使用CPU,则通过C中malloc在主机上分配内存
*use_cuda = false;
//检查是否有内存分配异常信息并输出
CHECK(*ptr) << "host allocation of size " << size << " failed";
} //caffe中定义的主机内存(包括页锁定内存和可分页内存)释放函数,定义为内联函数
inline void CaffeFreeHost(void* ptr, bool use_cuda) {
#ifndef CPU_ONLY
if (use_cuda) {
CUDA_CHECK(cudaFreeHost(ptr)); //页锁定内存通过CUDA函数cudaFreeHost释放
return;
}
#endif
free(ptr); //主机普通内存通过free释放
} /**
* @brief Manages memory allocation and synchronization between the host (CPU)
* and device (GPU).
*
* TODO(dox): more thorough description.
*/ //SyncedMemory类完成数据在CPU和GPU间的内存管理和数据同步工作
class SyncedMemory {
public:
//默认的无参构造函数,默认数据状态设置为UNINITIALIZED,初始使用系统默认的GPU设备
SyncedMemory()
: cpu_ptr_(NULL), gpu_ptr_(NULL), size_(0), head_(UNINITIALIZED),
own_cpu_data_(false), cpu_malloc_use_cuda_(false), own_gpu_data_(false),
gpu_device_(-1) {}
//由explicit关键字定义的一个显式构造函数,带一个size大小参数
explicit SyncedMemory(size_t size)
: cpu_ptr_(NULL), gpu_ptr_(NULL), size_(size), head_(UNINITIALIZED),
own_cpu_data_(false), cpu_malloc_use_cuda_(false), own_gpu_data_(false),
gpu_device_(-1) {}
//析构函数,调用CaffeFreeHost或者cudaFree完成内存释放工作
~SyncedMemory();
//获取只读的CPU数据指针,在内部调用了to_CPU函数
const void* cpu_data();
//设置CPU内存数据,如果own_cpu_data有效,则会先释放内存,并把内存地址指向新的data数据
void set_cpu_data(void* data);
//获取只读的GPU数据指针,在内部调用了to_CPU函数
const void* gpu_data();
//设置GPU内存数据,如果own_gpu_data有效,则会先释放内存,并把内存地址指向新的data数据
void set_gpu_data(void* data);
//获取可以修改的CPU内存数据指针
void* mutable_cpu_data();
//获取可以修改的GPU内存数据指针
void* mutable_gpu_data();
//枚举类型,定义了4中数据存放状态,分别是未初始化,存放在CPU,存放在GPU和数据已经同步
enum SyncedHead { UNINITIALIZED, HEAD_AT_CPU, HEAD_AT_GPU, SYNCED };
//获取数据的存放状态
SyncedHead head() { return head_; }
//获取数据大小,以字节为单位
size_t size() { return size_; } #ifndef CPU_ONLY
//如果没有定义只使用CPU,则异步推送数据到GPU上,完成数据传输之后设置数据状态为已同步
void async_gpu_push(const cudaStream_t& stream);
#endif private:
void to_cpu(); //实现把数据存放在cpu功能
void to_gpu(); //实现把数据存放在gpu功能
void* cpu_ptr_; //指向cpu上数据的指针
void* gpu_ptr_; //指向gpu上数据的指针
size_t size_; //数据大小,以字节为单位
SyncedHead head_; //数据存放状态
bool own_cpu_data_; //标识是否已经分配cpu内存
bool cpu_malloc_use_cuda_; //标识是否通过cuda分配了主机内存, 即主机内存是否是页锁定内存
bool own_gpu_data_; //标识是否已经分配了gpu内存
int gpu_device_; //gpu设备编号 //禁止使用SyncedMemory类的拷贝和赋值操作
DISABLE_COPY_AND_ASSIGN(SyncedMemory);
}; // class SyncedMemory } // namespace caffe #endif // CAFFE_SYNCEDMEM_HPP_

总的来说,SyncedMemory类封装了在主机和设备上申请数据内存,互相之间通信,获取主机和设备上的内存数据指针,主机和设备的数据同步等功能。

【撸码caffe 一】syncedmen.hpp的更多相关文章

  1. 【撸码caffe 五】数据层搭建

    caffe.cpp中的train函数内声明了一个类型为Solver类的智能指针solver: // Train / Finetune a model. int train() { -- shared_ ...

  2. 【撸码caffe 二】 blob.hpp

    Blob类是caffe中对处理和传递的实际数据的封装,是caffe中基本的数据存储单元,包括前向传播中的图像数据,反向传播中的梯度数据以及网络层间的中间数据变量(包括权值,偏置等),训练模型的参数等等 ...

  3. 【撸码caffe 三】 caffe.cpp

    caffe.cpp文件完成对网络模型以及模型配置参数的读入和提取,提供了网络模型训练的入口函数train和对模型的测试入口函数test.文件中使用了很多gflags和glog指令,gflags是goo ...

  4. 【撸码caffe四】 solver.cpp&&sgd_solver.cpp

    caffe中solver的作用就是交替低啊用前向(forward)算法和后向(backward)算法来更新参数,从而最小化loss,实际上就是一种迭代的优化算法. solver.cpp中的Solver ...

  5. caffe的db_lmdb.hpp文件

    先总的说一下: 类:LMDBCursor:  它干了点什么?它需要传入参数为:mdb_txn(传入它是因为用完它,把它absort掉), mdb_cursor;它应该是用来读出数据的: 类:LMDBT ...

  6. 我和小美的撸码日记--基于MVC+Jqgrid的.Net快速开发框架

    前言:以前的帐号没有发首页的权限,特此把这篇文章从另外一个博客移过来,这篇是<我和小美的撸码日记>的序 一转眼务农6年了,呆过大公司也去过小作坊,码农的人生除了抠腚还是抠腚.在所有呆过的公 ...

  7. 推荐几个IDEA插件,Java开发者撸码利器(转载)

    推荐几个IDEA插件,Java开发者撸码利器.   这里只是推荐一下好用的插件,具体的使用方法不一一详细介绍. JRebel for IntelliJ 一款热部署插件,只要不是修改了项目的配置文件,用 ...

  8. Intellij IDEA 撸码最头大的问题。。

    想栈长我当初从 Eclipse 转用 IDEA 真是纠结,放弃然后尝试了N次,不过现在已经算是转型成功了,可以完全脱离 Eclipse 撸码了,虽然说我现在真的撸得非常少了.. 说到 IDEA 的痛点 ...

  9. 响应国家号召,在家撸码之React迁移记

    最近这段时间新型冠状病毒肆虐,上海确诊人数每天都在增加,人人提心吊胆,街上都没人了.为了响应国家号召,近期呆在家里撸码,着手将项目迁移到React中,项目比较朴素,是一张线索提交页面,包含表单.图片滚 ...

随机推荐

  1. 三维重建:SFM中BA的并行化

    1. BA在重建中的作用 借鉴于运动中重建的方法,BA引入SLAM过程,而传统的滤波方法引入BA是跟随闭环检测出现. 1.1 BA在滤波方法中的嵌入 PTAM 1.2 BA在闭环检测之后的应用 在三维 ...

  2. linux环境jdk安装及配置

    linux环境jdk安装及配置 linux环境jdk安装及配置 1.下载jkd( http://www.oracle.com/technetwork/java/javase/downloads/ind ...

  3. spirngMvc

    配置方式就略了 直接开始注解方式: 1.  新建项目 2.  导入jar包 3.  创建controller,用注解方式声明 4.  在web.xml配置核心分发器DispatcherServlet ...

  4. vue-router同路由地址切换无效解决

    本来还想写的,一搜就有现成的,算了: http://blog.csdn.net/peng_guan/article/details/59702699

  5. Java基础学习笔记三 正则表达式和校验、Date、DateFormat、Calendar

    正则表达式 正则表达式(英语:Regular Expression,在代码中常简写为regex).正则表达式是一个字符串,使用单个字符串来描述.用来定义匹配规则,匹配一系列符合某个句法规则的字符串.在 ...

  6. 有关微信小程序

    每个页面都要在app.json中配置 "pages": [ "pages/index/index", "pages/list/list", ...

  7. vue: This relative module was not found

    这是今天运行vue项目报的一个错误,特地在此记录一下. 错误信息如下: ERROR Failed to compile with 1 errors This relative module was n ...

  8. Java基本类型转换

    1.自动类型转换 java所有的数值型变量都可以相互转换,如果系统支持把某种基本类型的值直接付赋给另一个基本类型的变量,则这种方式被称为自动类型转换. 当把一个表数范围小的数值或变量直接赋给另一个表数 ...

  9. Ubuntu18.04 安装后应该做的事!!!

    一.WPS 进入WPS_Linux官网,下载对应的deb文件. WPS有官方的文件说明可供查看,WPS社区 WPS 的依赖关系,部分数学公式显示支持,都可以通过WPS社区查看 安装wps sudo d ...

  10. Nikita and stack

    Nikita and stack time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...