Update
Blob对象不仅仅包括data还包括diff
float *p = a.mutable_cpu_data();
float *q = a.mutable_cpu_diff();
for (int i = 0; i < a.count(); ++i)
{
//将data初始化为0,1,2,...,23
p[i] = i;
//将diff初始化为23,22,21,...,0
q[i] = a.count()-1-i;
}
a.Update();
结果:
可以看出a.Update()执行了data=data-diff 这个操作~
数据描述
message BlobProto {
optional BlobShape shape = 7;//可选包括一个BlobShape对象
repeated float data = 5 [packed = true];//date咯
repeated float diff = 6 [packed = true];//diff咯
repeated double double_data = 8 [packed = true];//和data一样,只是是double
repeated double double_diff = 9 [packed = true];//和diff一样,只是是double
// 4D dimensions -- deprecated. Use "shape" instead.新版caffe推荐用shape不用下面的
optional int32 num = 1 [default = 0];
optional int32 channels = 2 [default = 0];
optional int32 height = 3 [default = 0];
optional int32 width = 4 [default = 0];
}
src/caffe/proto/caffe.proto看数据描述。这里是ProtoBuffer的结构。有些童鞋可能不太熟悉,没关系我们讲一讲:
message LogonReqMessage {
required int64 acctID = 1;
required string passwd = 2;
}
这里将给出以上消息定义的关键性说明。
1. message是消息定义的关键字,等同于C++中的struct/class,或是Java中的class。
2. LogonReqMessage为消息的名字,等同于结构体名或类名。
3. required前缀表示该字段为必要字段,既在序列化和反序列化之前该字段必须已经被赋值。与此同时,在Protocol Buffer中还存在另外两个类似的关键字,optional和repeated,带有这两种限定符的消息字段则没有required字段这样的限制。相比于optional,repeated主要用于表示数组字段。具体的使用方式:在每个消息中必须至少留有一个required类型的字段, 每个消息中可以包含0个或多个optional类型的字段,repeated表示的字段可以包含0个或多个数据。
4. int64和string分别表示长整型和字符串型的消息字段,在Protocol Buffer中存在一张类型对照表,既Protocol Buffer中的数据类型与其他编程语言(C++/Java)中所用类型的对照。该对照表中还将给出在不同的数据场景下,哪种类型更为高效。该对照表将在后面给出。
5. acctID和passwd分别表示消息字段名,等同于Java中的域变量名,或是C++中的成员变量名。
6. 标签数字1和2则表示不同的字段在序列化后的二进制数据中的布局位置。在该例中,passwd字段编码后的数据一定位于acctID之后。需要注意的是该值在同一message中不能重复。另外,对于Protocol Buffer而言,标签值为1到15的字段在编码时可以得到优化,既标签值和类型信息仅占有一个byte,标签范围是16到2047的将占有两个bytes,而Protocol Buffer可以支持的字段数量则为2的29次方减一。有鉴于此,我们在设计消息结构时,可以尽可能考虑让repeated类型的字段标签位于1到15之间,这样便可以有效的节省编码后的字节数量。