2.3.1 Blob:
Caffe基础存储结构,用于数据的保存、交换和操作。在内存中表示4维数组,在caffe/blob.hpp中,维度包括(width_,height_,channels_,num_),num_用于存储数据或权重(data)和权值增量(diff)。
(1)#blob.hpp:模板类源码分析
$ cd caffe/include/caffe/blob.hpp
#include "caffe/common.hpp"
//主要singleton化Caffe类,并封装boost和CUDA随机数生成的函数,提供统一接口。
#include "caffe/proto/caffe.pb.h"
//根据caffe.proto自动生成,从src/caffe/proto/caffe.proto里看BlobProto、Datum、
//NetParameter的数据定义
#include "caffe/syncedmem.hpp"
// 定义接口:inline void CaffeMallocHost(void ** ptr,size_t size)
// inline void CaffeFreeHost(void* ptr), 主要分配内存和释放内存。
class Blob {
public:
Blob()
: data_(), diff_(), count_(0), capacity_(0) {} //四维数组
explicit Blob(const int num, const int channels, const int height, const int width);
explicit Blob(const vector<int>& shape);
//成员变量
protected:
//SyncedMemory类主要负责在GPU或者CPU上分配内存以及保持数据的同步作用//SyncedMemory类主要应用在BLOB类中,我们可以在BLOB类中看出一些使用方法
//如 const Dtype* gpu_data() const; const Dtype* cpu_diff() const;const Dtype* gpu_diff() const;
shared_ptr<SyncedMemory> data_;
//共享SyncedMemory类智能指针,申请内存,正向传播使用
shared_ptr<SyncedMemory> diff_;
//共享SyncedMemory类智能指针,存储偏差
shared_ptr<SyncedMemory> shape_data_; //存储Blob形状
vector<int> shape_; //int型的vector
int count_;
//整型变量,Blob中的元素个数:个数*通道数*高度*宽度
int capacity_;
//整型变量,当前的元素个数,因为Blob可能会reshape
//成员函数
void Reshape(const int num, const int channels, const int height, const int width);
void Reshape(const vector<int>& shape);
void Reshape(const BlobShape& shape);
void ReshapeLike(const Blob& other);
void Update();
void ShareData(const Blob& other);
....
#
# cd caffe/src/caffe/proto/caffe.proto //数据定义
message BlobProto {
optional BlobShape shape = 7;
//repeated:float类型的data\diff可以重复任意次,[packed=true]:为了更高效的编码。
repeated float data = 5 [packed = true];
repeated float diff = 6 [packed = true];
repeated double double_data = 8 [packed = true];
repeated double double_diff = 9 [packed = true];
//optional意味Blob可以有一个或者没有这个参数,每个名字后的数字是名字的标签,用来生成二进制文件中搜索查询的标签。
//用num、channels、height、width四个维度确定数据的具体位置,做数据查询和Blob reshape操作。
optional int32 num = 1 [default = 0];
optional int32 channels = 2 [default = 0];
optional int32 height = 3 [default = 0];
optional int32 width = 4 [default = 0];
}
message Datum {
optional int32 channels = 1;
optional int32 height = 2;
optional int32 width = 3;
}
#cd caffe/scr/caffe/blob.cpp
#include “caffe/util/math_functions.hpp” //封装了很多Cblas矩阵运算
(2)操作
# 改变库路径
$ cd caffe/build
$ export LD_LIBRARY_PATH=/usr/local/lib:${LD_LIBRARY_PATH}
# test_blob.cpp test_pb.cpp
$ vim test_blob.cpp
3 * 功能:
4 * 1. 测试使用Blob
5 * 2. 给blob赋值
6 * 3. 获取blob指定位置的值
7 * 4. 输出通过L1范式和L2范式得到的结果
11 #include <iostream>
12 #include "caffe/blob.hpp" //主要用于数据定义
14 int main(int argc,char* argv[]){
15 //构造一个Blob
16 caffe::Blob<float> b;
17 std::cout<<"Size : "<<b.shape_string()<<std::endl;
18 b.Reshape(1,2,3,4);
19 std::cout<<"Size : "<<b.shape_string()<<std::endl;
21 //使用mutable_cpu_data函数修改Blob内部数值
22 float* p = b.mutable_cpu_data();
23 for(int i=0;i<b.count();i++){
24 p[i] = i; }
28 //打印指定位置的每一个数值
29 for(int u=0; u<b.num() ;u++){
30 for(int v=0;v<b.channels();v++){
31 for(int w=0;w<b.height();w++){
32 for(int x=0; x<b.width();x++){
33 std::cout<<"b["<<u<<"] ["<<v<<"] ["<<w<<"] ["<<x<<"] ="<<b.data_at(u,v,w,x)<<std::endl;//b.data_at(),位置
34 }}}}
39 //求L1,L2范式及其输出结果
40 std::cout<<"ASUM : "<<b.asum_data()<<std::endl;
41 std::cout<<"SUMSQ : "<<b.sumsq_data()<<std::endl;
42
43 return 0;
# 编译
$ gcc -o test_blob test_blob.cpp -D CPU_ONLY -lcaffe -lstdc++ -lglog
$ ls
#test_blob test_pb.cpp test_blob.cpp
$ ./test_blob