NVcaffe源码阅读——Blob的重新构建
来源:互联网 发布:百度云 知乎 编辑:程序博客网 时间:2024/06/06 09:20
NVcaffe源码阅读——blob的重新构建
nvcaffe由于对数据类型做了很大的拓展,所以作者对blob的构建上做了很大改动。即向下的内存/显存管理提供了tensor类,blob类使用tensor类作为成员变量代替以前的data和diff指针;blob提供与caffe相兼容的api借口,保持功能的一致性,添加部分适应新功能的api;最后使用Tblob类包裹blob类,提供更加灵活的模板定义。
Type
变量类型Type在代码里到处可见,它是作者定义不同数据类型的一个枚举结构,定义在caffe.proto最开头。通过定义可以看到目前nvcaffe所支持的数据类型:
// Math and storage typesenum Type { DOUBLE = 0; FLOAT = 1; FLOAT16 = 2; INT = 3; // math not supported UINT = 4; // math not supported}
其具体数值大小则是个数据类型的字节长度,定义在type.cpp中。
Syncedmem的修改
syncedmem是在tensor(或老版caffe的blob)之下一层、直接管理内存/显存的操作封装。nvcaffe由于着重改进了多gpu并行性能,因此在这一块做了一些改动,主要包括但不限于:
1. to_string:将运行信息字符串化以帮助debug;
2. 在这里实现了原来在blob.cpp中实现的asum、sumsq、amax等数学操作;
3. valid和invalid函数。SyncedMemory类中有一个布尔成员变量valid_,而valid和invalid函数则是修改这个变量的接口。该变量与Tensor类对不同数据类型的数据进行管理的方式紧密相关;
4. to_cpu和to_gpu在新分配内存/显存时扩展了操作。具体表现为:
- to_cpu在新分配内存时多了一步加锁操作;
- to_gpu在新分配显存时没有使用简单的cudaMalloc,而是封装了一套既可以使用cudaMalloc也可以使用CachingDeviceAllocator的工具,实现在gpu_memory.hpp/cpp的GPUMemory命名空间中,主要功能集中在try_allocate函数上。 当使用CachingDeviceAllocator时,程序会在分配显存时加锁,且不停刷新各个gpu的显存使用情况。 使用CachingDeviceAllocator的原因应该是其’thread-safe and stream-safe on multiple devices’的特性。 由于代码注释很少,加之没有花很多时间去分析,暂不清楚记录各个gpu的显存使用情况的作用是什么。
Tensor
Tensor类的出现是为了nvcaffe支持多种数据类型。tensor.hpp/cpp中的操作都原属于原版caffe的blob.hpp/cpp,现在把涉及到这个新特性的操作单独拿出来。
Tensor类中的操作可以分为这几类:
1. 数据存取;
2. 数据管理(Reshape: 相同数量不同类型的数据大小不一样;convert: 数据类型之间的相互转换);
3. 数据使用(一些blas操作: 要么调用syncedmem.cpp中实现的,要么根据数据类型调用不同模板的mathfunction(2).cpp中的函数)。
Tensor类数据的取用依赖于这两个成员变量:
// numerical type stored here at a moment (might change due to conversion) Type type_; // array of projections to different types (including current type_) shared_ptr<vector<shared_ptr<SyncedMemory>>> synced_arrays_;
其中type_按照Type枚举结构的定义只有5个不同的整数值。synced_arrays_是一个SyncedMemory类的指针向量,长度为5,对应nvcaffe支持的5种不同的数据类型。当第一次被赋予数据时,Tensor类会将type_变量设置为对应的数据类型,数据的头指针被放在synced_arrays_[type_]处,且该部分数据对应的SyncedMemory类实例的valid变量变为true。如果调用了convert函数,则将type_设置为转换后的数据类型,并在synced_arrays_[type_]处开辟新的或者抹去已有的数据,使用math_function中的caffe_convert函数进行类型转换和数据复制(对元素进行循环迭代)。
当synced_arrays_存取数据时,只对synced_arrays_[type_]进行操作。
其他操作如Reshape等较好理解,在此不再赘述。
Blob
Blob类的变化并不大,主要是为了在api上与以前的caffe保持一致。其变化包括:
1. 以前shared_ptr类型的data_和diff_变成了shared_ptr类型的data_tensor_和diff_tensor_;
2. 一些函数,如FromProto等增加了针对不同数据类型而进行分别处理的语句。
TBlob
TBlob是Blob的子类,主要是对诸如cpu_data(), mutable_gpu_data()等取数据指针的方法进行了重新实现。与Blob提供的方法的区别是,Blob可以通过变换模板数据类型来动态转换实际存储的数据,而TBlob则进行了数据类型一致性的约束,不能随意变换数据类型。举cpu_data的实现作例子即可清楚得到对比:
// Blob code template<typename Dtype> const Dtype* cpu_data() const { // convert data type if Dtype != type_ convert_data(tp<Dtype>()); return static_cast<const Dtype*>(data_tensor_->synced_mem()->cpu_data()); } // TBlob code template<typename T = Dtype> const T* cpu_data() const { // raise an Error if T != type_ check_integrity(true, data_type(), tp<T>()); return Blob::cpu_data<T>(); } static void check_integrity(bool do_data, Type current_type, Type new_type) { CHECK_EQ(current_type, new_type) << "Attempt to change TBlob native " << (do_data ? "data" : "diff") << " type from " << Type_Name(current_type) << " to " << Type_Name(new_type); }
在使用上,Blob用于网络feature的前向和后向的传递,TBlob用于存储网络使用到的中间变量。
- NVcaffe源码阅读——Blob的重新构建
- NVcaffe源码阅读——Layer
- NVcaffe源码阅读——Net&Solver
- caffe源码阅读——Blob类
- caffe源码阅读——Blob类
- caffe源码阅读之Blob
- webkit源码阅读:dom树的构建
- caffe源码阅读1-blob.hpp
- caffe源码阅读3-blob.cpp
- Caffe源码阅读笔记(1):Blob
- Caffe源码解读1 —— Blob
- caffe源码解析 — blob.cpp
- caffe源码解析 — blob.cpp
- 重新改写的Blob Tracking Tests工程
- Caffe 源码阅读笔记 [基本模块] Syncedmem & Blob
- 阅读ISE源码过程中重新对单例模式的理解
- 使用Intellij构建spark源码阅读环境
- IDEA构建Alluxio最新源码阅读环境
- Go语言学习笔记 --- 入门介绍
- Spring boot 整合mybtais和druid
- JDBC技术
- spring boot 使用hibernate-validation
- osgViewer应用基础
- NVcaffe源码阅读——Blob的重新构建
- 排序算法
- NOIP2016Day1T1玩具谜题解题报告
- spring boot 多数据源动态切换
- Ubuntu14.04安装最新版Docker
- Hadoop小兵笔记【五】hadoop2.2.0伪分布式环境搭建疑难-第一个用例wordcount失败
- 一个m*n的矩阵,从左到右从上到下都是递增的,给一个数x,判断x是否在矩阵中。要求效率尽可能的高
- 多人聊天室(基于Linux的SOCKET UDP编程)
- Python 标准库 urllib