梳理caffe代码syncedmem(二)

接着最重要的就是内存分配和Caffe的底层数据的切换(cpu模式和gpu模式),需要用到内存同步模块。这类个类的代码比较少,但是作用是非常明显的。文件对应着syncedmem.hpp,着syncedmem.cpp首先是两个全局的内联函数。如果机器是支持GPU的并且安装了cuda,通过cudaMallocHost分配的host memory将会被pinned,pinned的意思就是内存不会被paged out,我们知道内存里面是由页作为基本的管理单元。分配的内存可以常驻在内存空间中对效率是有帮助的,空间不会被别的进程所抢占。同样如果内存越大,能被分配的Pinned内存自然也越大。还有一点是,对于单一的GPU而言提升并不会太显著,但是对于多个GPU的并行而言可以显著提高稳定性。这里是两个封装过的函数,内部通过cuda来分配主机和释放内存的接口.

#ifndef CAFFE_SYNCEDMEM_HPP_
#define CAFFE_SYNCEDMEM_HPP_

#include <cstdlib>

#include "caffe/common.hpp"
#include "caffe/util/math_functions.hpp"

namespace caffe {

// Theoretically, CaffeMallocHost and CaffeFreeHost should simply call the
// cudaMallocHost and cudaFree functions in order to create pinned memory.
// However, those codes rely on the existence of a cuda GPU (I don't know
// why that is a must since allocating memory should not be accessing the
// GPU resource, but it just creates an error as of Cuda 5.0) and will cause
// problem when running on a machine without GPU. Thus, we simply define
// these two functions for safety and possible future change if the problem
// of calling cuda functions disappears in a future version.
//
// In practice, although we are creating unpinned memory here, as long as we
// are constantly accessing them the memory pages almost always stays in
// the physical memory (assuming we have large enough memory installed), and
// does not seem to create a memory bottleneck here.
//分别是分配和释放内存,这里指的是CPU内存。
inline void CaffeMallocHost(void** ptr, size_t size) {
  *ptr = malloc(size);
  CHECK(*ptr) << "host allocation of size " << size << " failed";
}

inline void CaffeFreeHost(void* ptr) {
  free(ptr);
}


/**
 * @brief Manages memory allocation and synchronization between the host (CPU)
 *        and device (GPU).
 *
 * TODO(dox): more thorough description.
 */
//功能:Caffe的底层数据的切换(cpu模式和gpu模式),需要用到内存同步模块。
class SyncedMemory {
 public:
/*
第一个为简单初始化,第二个只是把 size (大小)设置了,并未申请内存。
然后是析构函数,主要就是释放数据。own_gpu_data和own_cpu_data这两个成员变量
的作用表示是否拥有该数据,也即在cpu或gpu中是否
有其他指针指向该数据。
*/
  SyncedMemory()
      : cpu_ptr_(NULL), gpu_ptr_(NULL), size_(0), head_(UNINITIALIZED),
        own_cpu_data_(false) {}
  explicit SyncedMemory(size_t size)
      : cpu_ptr_(NULL), gpu_ptr_(NULL), size_(size), head_(UNINITIALIZED),
        own_cpu_data_(false) {}
  ~SyncedMemory();
/*
分别是获取cpu,gpu中数据的指针,需要说明的一点是,该过程会同步数据。
有获取,就有设置,下面两个函数就是设置数据了。这里设置后就不是拥有该数据,
即own_cpu_data或own_gpu_data就为false,因为还有data指向该数据。
一般来说,只有当同步后才会为true。也即to_cpu()或者to_gpu()后。
*/
  const void* cpu_data();//获取cpu数据,返回void * 指针
  void set_cpu_data(void* data);//用一个void * 指针修改指针,功能:清空CPU的数据
  const void* gpu_data();//获取gpu数据,返回void * 指针


  void* mutable_cpu_data();//获取可以更改cpu数据,返回void * 指针,并改变数据的状态为HEAD_AT_CPU,也是mutable是可读写性的
  void* mutable_gpu_data();//获取可以更改gpu数据,返回void * 指针,并改变数据的状态为HEAD_AT_GPU
//关于SymceHead,有四种状态,分别是未初始化,数据在 cpu 中,数据在 gpu 中,
//数据在 cpu和 gpu 中都有
  enum SyncedHead { UNINITIALIZED, HEAD_AT_CPU, HEAD_AT_GPU, SYNCED };//enum枚举值
/*
返回数据状态和大小。
*/
  SyncedHead head() { return head_; }//获得枚举值
  size_t size() { return size_; }//获得当前存储空间的数据大小

 private:
/*
功能:把数据放到cpu上
1.数据未初始化,则在cpu申请内存(申请为0)。此时状态为HEAD_AT_CPU
2.数据本来在gpu,则从gpu拷贝内存到cpu。此时状态为SYNCED
3.数据本来在cpu,不做处理
4.数据在cpu和gpu都有,不做处理
*/
  void to_cpu();
/*
功能:把数据放到gpu上
1.数据未初始化,在gpu申请内存(申请为0)。此时状态为HEAD_AT_GPU
2.数据在cpu,从cpu拷贝到gpu。此时状态为SYNCED
3.数据在gpu,不做操作。
4.数据在cpu和gpu都有,不做操作。
*/
  void to_gpu(); 
  void* cpu_ptr_;//指向cpu的指针
  void* gpu_ptr_;//指向gpu的指指针
  size_t size_; //大小
  SyncedHead head_; //数据存放的位置,枚举值之一
  bool own_cpu_data_;//是否有cpu数据
/*DISABLE_COPY_AND_ASSIGN是一个宏,用来把该类的拷贝函数和等号操作符给禁止掉,如果想让你的类
不能使用 copy 构造函数和赋值操作符,只要将该类的 copy 构造函数和赋值操作符函数定义为 private 
即可,并且只是声明,不用实现 .
*/
  DISABLE_COPY_AND_ASSIGN(SyncedMemory);
};  // class SyncedMemory

}  // namespace caffe

#endif  // CAFFE_SYNCEDMEM_HPP_


  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值