Caffe源码解析2:SycedMem
2016-01-22 10:58
369 查看
转载请注明出处,楼燚(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号
相关文章推荐
- 基于JavaScript实现高德地图和百度地图提取行政区边界经纬度坐标
- Managed File Transfer and Network Solutions
- Html.ActionLink
- js的history.pushstate()作用
- javascript开发的45个技巧
- EasyUi、SpringMVC、jquery的ajax、导出Excel文件
- javascript中的toString()方法
- EXTJS改变自带样式的那种风格
- JQuery 判断某个属性是否存在 hasAttr
- JavaScript对象与数组
- CSS层叠样式表
- CSS或者JS实现鼠标悬停显示另一元素
- html基本知识点
- JQuery 的跨域方法 可跨任意网站
- JavaScript 逼真图片倒计时实现代码 js时间图片倒计时
- MVC按钮提交js验证
- 防止过度的模块化/组件化
- 在JavaScript中call()与apply()区别
- 毫秒数转换为指定格式日期的js代码
- jsp之间传参中文乱码问题