转载请注明出处,楼燚(yì)航的blog,http://www.cnblogs.com/louyihang loves baiyan/

看到SyncedMem就知道,这是在做内存同步的操作。这类个类的代码比较少,但是作用是非常明显的。文件对应着syncedmem.hpp,着syncedmem.cpp

首先是两个全局的内联函数。如果机器是支持GPU的并且安装了cuda,通过cudaMallocHost分配的host memory将会被pinned,这里我谷歌了一下,pinned的意思就是内存不会被paged out,我们知道内存里面是由页作为基本的管理单元。分配的内存可以常驻在内存空间中对效率是有帮助的,空间不会被别的进程所抢占。同样如果内存越大,能被分配的Pinned内存自然也越大。还有一点是,对于单一的GPU而言提升并不会太显著,但是对于多个GPU的并行而言可以显著提高稳定性。

这里是两个封装过的函数,内部通过cuda来分配主机和释放内存的接口

inline void CaffeMallocHost(void** ptr, size_t size, bool* use_cuda) {
#ifndef CPU_ONLY
  if (Caffe::mode() == Caffe::GPU) {
    CUDA_CHECK(cudaMallocHost(ptr, size));// GPU模式下cuda分配内存
    *use_cuda = true;
    return;
  }
#endif
  *ptr = malloc(size);//如果没有cuda则通过c的malloc函数分配
  *use_cuda = false;
  CHECK(*ptr) << "host allocation of size " << size << " failed";
}

inline void CaffeFreeHost(void* ptr, bool use_cuda) {
#ifndef CPU_ONLY
  if (use_cuda) {
    CUDA_CHECK(cudaFreeHost(ptr));//cuda的主机内存释放操作
    return;
  }
#endif
  free(ptr);//c的释放操作
}

SyncedMemory类,首先是构造函数和析构函数

class SyncedMemory {
 public:
  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 SyncedMemory(size_t size)//带explicit关键字的,单个参数构造函数,explicit禁止单参数构造函数的隐式转换
      : 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) {}
  ~SyncedMemory();//其在析构时调用的也是CaffeFreeHost

这几个函数分别是

  const void* cpu_data();
  void set_cpu_data(void* data);
  const void* gpu_data();
  void set_gpu_data(void* data);

cpu_data()主要是获得cpu上data的地址,set_cpu_data是将cpu的data指针指向一个新的区域由data指针传入,并且将原来申请的内存释放。下面两个同理,分别是获得gpu数据地址和set gpu数据地址。

  void* mutable_cpu_data();
  void* mutable_gpu_data();
  enum SyncedHead { UNINITIALIZED, HEAD_AT_CPU, HEAD_AT_GPU, SYNCED };
  SyncedHead head() { return head_; }
  size_t size() { return size_; }

前两个分别是返回cpu和gpu上的data指针,并且置状态为head_ = HEAD_AT_CPU和响应的gpu版本。SyncedHead主要是个枚举类型,用来设定head_的状态,head()函数即返回相应的数据状态,而size()函数返回数据大小

#ifndef CPU_ONLY
  void async_gpu_push(const cudaStream_t& stream);
#endif

这是一个cuda拷贝的异步传输,从数据从cpu拷贝到gpu,异步传输是已经假定caller会在使用之前做同步操作。

 private:
  void to_cpu();
  void to_gpu();
  void* cpu_ptr_;
  void* gpu_ptr_;
  size_t size_;
  SyncedHead head_;
  bool own_cpu_data_;
  bool cpu_malloc_use_cuda_;
  bool own_gpu_data_;
  int gpu_device_;

  DISABLE_COPY_AND_ASSIGN(SyncedMemory);//禁止该类的拷贝与赋值
};  // class SyncedMemory

其实这里的东西也不多了,to_cpu(),to_gpu()这个看名字就知道了,需要注意的是,如果head 是未被初始化的状态,那么首先需要先分配内存,这个根据cpu和gpu视情况而定,之后再将数据从cpu或者gpu拷贝到另一处。之后函数会重新标记Head的状态,数据是否在cpu或者在gpu中,cpu这里是简称,其实是主机。
cpu_ptr和gpu_ptr分别是在cpu和gpu中的数据指针,size_这就不再说了,head_之前也液晶提到过了,后面都是几个相应的标记为,以及gpu的ID号

Caffe源码解析2:SycedMem的更多相关文章

  1. Caffe源码解析7:Pooling_Layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ Pooling 层一般在网络中是跟在Conv卷积层之后,做采样 ...

  2. Caffe源码解析6:Neuron_Layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ NeuronLayer,顾名思义这里就是神经元,激活函数的相应 ...

  3. Caffe源码解析5:Conv_Layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ Vision_layer里面主要是包括了一些关于一些视觉上的操 ...

  4. Caffe源码解析4: Data_layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ data_layer应该是网络的最底层,主要是将数据送给blo ...

  5. Caffe源码解析3:Layer

    转载请注明出处,楼燚(yì)航的blog,http://home.cnblogs.com/louyihang-loves-baiyan/ layer这个类可以说是里面最终的一个基本类了,深度网络呢就是 ...

  6. Caffe源码解析1:Blob

    转载请注明出处,楼燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/ 首先看到的是Blob这个类,Blob是作为Caffe中数据流通的 ...

  7. caffe源码解析

    http://blog.csdn.net/lanxuecc/article/details/53186613

  8. caffe源码阅读

    参考网址:https://www.cnblogs.com/louyihang-loves-baiyan/p/5149628.html 1.caffe代码层次熟悉blob,layer,net,solve ...

  9. vscode下调试caffe源码

    caffe目录: ├── build -> .build_release // make生成目录,生成各种可执行bin文件,直接调用入口: ├── cmake ├── CMakeLists.tx ...

随机推荐

  1. UITextFiled

    - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...

  2. 【python】python文件和目录操作方法大全(含实例)

    转自:http://www.jb51.net/article/48001.htm 一.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法.1.得到当前工作目录,即当前Pyt ...

  3. CodeForces 149D Coloring Brackets 区间DP

    http://codeforces.com/problemset/problem/149/D 题意: 给一个给定括号序列,给该括号上色,上色有三个要求 1.只有三种上色方案,不上色,上红色,上蓝色 2 ...

  4. phpstorm8 配置svn

    步骤1 步骤2. 步骤3.

  5. 【JavaScript创建对象】

    JavaScript 中的所有事物都是对象:字符串.数字.数组.日期,等等. 创建对象的四种方式: <!DOCTYPE html> <html> <head> &l ...

  6. nyoj161 取石子 (四) 威佐夫博弈

    思路:详细证明见博弈总结 如何判断威佐夫博弈的奇异局势? 对于状态(a, b),c = b - a,如果是奇异局势必定满足 a == c * (1+√5)/ 2. AC代码 #include < ...

  7. python clock装饰器 计算函数执行时间,执行结果及传入的参数

    import time import functools def clock(func): @functools.wraps(func)#还原被装饰函数的__name__和__doc__属性 def ...

  8. ng-book札记——依赖注入

    依赖注入是一种使程序的一部分能够访问另一部分的系统,并且可以通过配置控制其行为. "注入"可以理解为是"new"操作符的一种替代,不再需要使用编程语言所提供的& ...

  9. 【Java编程】Eclipse快捷键

    Alt+左箭头,右箭头        以在编辑窗口切换标签 Alt+上下箭头,                以自动选择鼠标所在行,并将其上下移动 Ctrl+f6                    ...

  10. IOS 选择会员资格

    选择会员资格 针对所有 Apple 平台进行开发从未如此简单.要开始为 macOS.iOS.tvOS 和 watchOS 开发 app,请从 Mac App Store 下载 Xcode.如果您已准备 ...