caffe源码阅读2-syncedmem.hpp+.cpp
2016-07-18 10:32
567 查看
Manages memory allocation and synchronization between the host (CPU) and device (GPU).
因为在看Blob.hpp的时候,有一个东西不好理解,里面最重要的两个东西data, diff是定义成:
shared_ptr也就是智能指针,等涉及到其方法的时候再做一点说明。
那么SyncedMemory是什么呢?在syncedmem.hpp里面可以看到,方法和变量都比较少。从注释可以大概了解到,这个东西是为了处理CPU与GPU同步问题的。因为我们在运行caffe的时候,通常都会使用GPU来跑,那么在分配和释放存储的时候,自然也会分配释放显存中的存储。但是如果代码直接这样写的话,可能会出错,例如某些机器上没有GPU,直接使用CPU来跑caffe的呢?
那么此时,如果按照我自己的理解,SyncedMemory应该是对内存和显存的抽象,用户只需要分配和释放存储,而具体是分配什么地方的存储,释放什么地方的存储,全部都交给SyncedMemory来处理。不过有点可惜,从这个类的方法和变量来看,应该还没有抽象到我想象的程度。
在私有变量中,cpu_ptr_和gpu_ptr_应该很好理解,也就是只想内存和显存里面的数据的指针吧。那么size应该是内存+显存的咯。而own_cpu_data,应该只是想说明内存中是否有数据吧。至于head_,看起来像是指向数据的头,我的猜测也就是说数据头部在内存还是显存,不过在public的方法也指明了这一点:
其中的enum SyncedHead {...},也就是说变量SyncedHead是一个枚举类型的:
UNINITIALIZED:未初始化
HEAD_AT_CPU:数据头部在内存中
HEAD_AT_GPU:数据头部在显存中
SYNCED:内存显存中都有数据头部
读到这里,其它的东西得去看看cpp了,那么to_cpu()是什么呢?
那么to_gpu()也是类似的的吧。
而cpu_data()则是先将数据写回到内存中(to_cpu()),再返回数据指针。那么gpu_data()也是一样的道理。值得注意的是方法mutable_cpu_data()和mutable_gpu_data(),实现的功能基本与cpu_data(),gpu_data()一样,但是多了一个东西,就是会对数据头head_赋值,mutable_cpu_data()中的赋值就是HEAD_AT_CPU,mutable_gpu_data()中的赋值就是HEAD_AT_GPU。这样做的好处是什么呢?如果这种处理方式比直接调用cpu_data(),gpu_data()的效果好,那么为什么还要设置前两个方法呢?不理解。
另外还有一个函数,set_cpu_data(void* data)也就是将数据data写入内存。奇怪的是写入后为什么要将own_cpu_data_赋值为false呢?
因为在看Blob.hpp的时候,有一个东西不好理解,里面最重要的两个东西data, diff是定义成:
shared_ptr<SyncedMemory> data_; shared_ptr<SyncedMemory> diff_;
shared_ptr也就是智能指针,等涉及到其方法的时候再做一点说明。
那么SyncedMemory是什么呢?在syncedmem.hpp里面可以看到,方法和变量都比较少。从注释可以大概了解到,这个东西是为了处理CPU与GPU同步问题的。因为我们在运行caffe的时候,通常都会使用GPU来跑,那么在分配和释放存储的时候,自然也会分配释放显存中的存储。但是如果代码直接这样写的话,可能会出错,例如某些机器上没有GPU,直接使用CPU来跑caffe的呢?
那么此时,如果按照我自己的理解,SyncedMemory应该是对内存和显存的抽象,用户只需要分配和释放存储,而具体是分配什么地方的存储,释放什么地方的存储,全部都交给SyncedMemory来处理。不过有点可惜,从这个类的方法和变量来看,应该还没有抽象到我想象的程度。
private: void to_cpu(); void to_gpu(); void* cpu_ptr_; void* gpu_ptr_; size_t size_; SyncedHead head_; bool own_cpu_data_;
在私有变量中,cpu_ptr_和gpu_ptr_应该很好理解,也就是只想内存和显存里面的数据的指针吧。那么size应该是内存+显存的咯。而own_cpu_data,应该只是想说明内存中是否有数据吧。至于head_,看起来像是指向数据的头,我的猜测也就是说数据头部在内存还是显存,不过在public的方法也指明了这一点:
public: 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(); const void* cpu_data(); void set_cpu_data(void* data); const void* gpu_data(); 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_; }
其中的enum SyncedHead {...},也就是说变量SyncedHead是一个枚举类型的:
UNINITIALIZED:未初始化
HEAD_AT_CPU:数据头部在内存中
HEAD_AT_GPU:数据头部在显存中
SYNCED:内存显存中都有数据头部
读到这里,其它的东西得去看看cpp了,那么to_cpu()是什么呢?
inline void SyncedMemory::to_cpu() { switch (head_) { case UNINITIALIZED: //如果没有初始化,那么初始化数据在内存中 CaffeMallocHost(&cpu_ptr_, size_); caffe_memset(size_, 0, cpu_ptr_); head_ = HEAD_AT_CPU; own_cpu_data_ = true; break; case HEAD_AT_GPU: #ifndef CPU_ONLY //如果没有声明CPU_ONLY,则数据可以存在于显存中, //则将显存中的数据拷贝到内存中,并将own_cpu_data_赋值为true if (cpu_ptr_ == NULL) { CaffeMallocHost(&cpu_ptr_, size_); own_cpu_data_ = true; } caffe_gpu_memcpy(size_, gpu_ptr_, cpu_ptr_); head_ = SYNCED; #else NO_GPU; //如果声明了CPU_ONLY,那么数据不可能存在于显存中,应该是提示,或者报错吧 #endif break; case HEAD_AT_CPU: case SYNCED: break; } }
那么to_gpu()也是类似的的吧。
而cpu_data()则是先将数据写回到内存中(to_cpu()),再返回数据指针。那么gpu_data()也是一样的道理。值得注意的是方法mutable_cpu_data()和mutable_gpu_data(),实现的功能基本与cpu_data(),gpu_data()一样,但是多了一个东西,就是会对数据头head_赋值,mutable_cpu_data()中的赋值就是HEAD_AT_CPU,mutable_gpu_data()中的赋值就是HEAD_AT_GPU。这样做的好处是什么呢?如果这种处理方式比直接调用cpu_data(),gpu_data()的效果好,那么为什么还要设置前两个方法呢?不理解。
另外还有一个函数,set_cpu_data(void* data)也就是将数据data写入内存。奇怪的是写入后为什么要将own_cpu_data_赋值为false呢?
void SyncedMemory::set_cpu_data(void* data) { CHECK(data); if (own_cpu_data_) { CaffeFreeHost(cpu_ptr_); } cpu_ptr_ = data; head_ = HEAD_AT_CPU; own_cpu_data_ = false; }
相关文章推荐
- css选择器优先级
- 剑指offer学习笔记——用两个栈实现队列
- Bootstrap 布局组件(全)
- nodejs 阻塞与非阻塞
- Javascript面试题解析
- JS 随机数
- js验证真实姓名与身份证号,手机号的简单实例
- Bootstrap零基础入门教程(三)
- iOS学习笔记39-ReactiveCocoa入门
- iScroll.js 用法参考
- JavaScript图表库 ECharts
- 19. Remove Nth Node From End of List
- Cloudera Manager 5和CDH5离线安装,CDH-5.7.1
- C# Json转对象 序列化 反序列化
- ExtJS-bootstrap.js的工作方式
- jstree使用【一】初次使用
- caffe heatmaplayer
- CSS子选择符
- HTML文档插入JS代码的几种方法
- HTML文档插入JS代码的几种方法