前言:
由于业务需要,接触caffe已经有接近半年,一直忙着阅读各种论文,重现大大小小的模型. 期间也总结过一些caffe源码学习笔记,断断续续,这次打算系统的记录一下caffe源码学习笔记,巩固一下C++,同时也梳理一下自己之前的理解。
正文:
我们先不看caffe的框架结构,先介绍一下caffe.proto,是google开源的一种数据交互格式--Google Protobuf,这种数据的格式,我们可以看到caffe.proto中内容:
syntax = "proto2"; package caffe; //caffe.prto中的各个结构封装在caffe包中,可以通过using namespace caffe; 或者caffe::** 调用 // Specifies the shape (dimensions) of a Blob. message BlobShape { repeated int64 dim = 1 [packed = true]; } message BlobProto { optional BlobShape shape = 7; 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]; // 4D dimensions -- deprecated. Use "shape" instead. optional int32 num = 1 [default = 0]; optional int32 channels = 2 [default = 0]; optional int32 height = 3 [default = 0]; optional int32 width = 4 [default = 0]; } .......
当我们在编译完成caffe之后,会自动在src/caffe/proto中生成两个文件caffe.pb.h 和caffe.pb.cc
那么这种数据格式在程序中是如何被使用的呢? 我们举一个简单的例子,来演示caffe.proto生成caffe.pb.h和caffe.pb.cc以及被调用的过程
如果你之前能够编译caffe成功,则说明你已经成功安装了Protobuf,那么我简单的编写一个使用Protobuf的例子吧.
我们先编写一个文件caffe.proto:
package caffe; message student { required int32 age = 1; //ID required 表示必要字段 required string name = 2; //str 必要字段 optional int32 grade = 3 ; //optional field 可选字段,可以有无,最多b }
然后我们执行如下操作。
protoc -I=. --cpp_out=. ./caffe.proto
protobuf会自动生成.cc和.h文件
1 // Generated by the protocol buffer compiler. DO NOT EDIT! 2 // source: caffe.proto 3 4 #ifndef PROTOBUF_caffe_2eproto__INCLUDED 5 #define PROTOBUF_caffe_2eproto__INCLUDED 6 7 #include <string> 8 9 #include <google/protobuf/stubs/common.h> 10 11 #if GOOGLE_PROTOBUF_VERSION < 2005000 12 #error This file was generated by a newer version of protoc which is 13 #error incompatible with your Protocol Buffer headers. Please update 14 #error your headers. 15 #endif 16 #if 2005000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 17 #error This file was generated by an older version of protoc which is 18 #error incompatible with your Protocol Buffer headers. Please 19 #error regenerate this file with a newer version of protoc. 20 #endif 21 22 #include <google/protobuf/generated_message_util.h> 23 #include <google/protobuf/message.h> 24 #include <google/protobuf/repeated_field.h> 25 #include <google/protobuf/extension_set.h> 26 #include <google/protobuf/unknown_field_set.h> 27 // @@protoc_insertion_point(includes) 28 29 namespace caffe { 30 31 // Internal implementation detail -- do not call these. 32 void protobuf_AddDesc_caffe_2eproto(); 33 void protobuf_AssignDesc_caffe_2eproto(); 34 void protobuf_ShutdownFile_caffe_2eproto(); 35 36 class student; 37 38 // =================================================================== 39 40 class student : public ::google::protobuf::Message { 41 public: 42 student(); 43 virtual ~student(); 44 45 student(const student& from); 46 47 inline student& operator=(const student& from) { 48 CopyFrom(from); 49 return *this; 50 } 51 52 inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { 53 return _unknown_fields_; 54 } 55 56 inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { 57 return &_unknown_fields_; 58 } 59 60 static const ::google::protobuf::Descriptor* descriptor(); 61 static const student& default_instance(); 62 63 void Swap(student* other); 64 65 // implements Message ---------------------------------------------- 66 67 student* New() const; 68 void CopyFrom(const ::google::protobuf::Message& from); 69 void MergeFrom(const ::google::protobuf::Message& from); 70 void CopyFrom(const student& from); 71 void MergeFrom(const student& from); 72 void Clear(); 73 bool IsInitialized() const; 74 75 int ByteSize() const; 76 bool MergePartialFromCodedStream( 77 ::google::protobuf::io::CodedInputStream* input); 78 void SerializeWithCachedSizes( 79 ::google::protobuf::io::CodedOutputStream* output) const; 80 ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; 81 int GetCachedSize() const { return _cached_size_; } 82 private: 83 void SharedCtor(); 84 void SharedDtor(); 85 void SetCachedSize(int size) const; 86 public: 87 88 ::google::protobuf::Metadata GetMetadata() const; 89 90 // nested types ---------------------------------------------------- 91 92 // accessors ------------------------------------------------------- 93 94 // required int32 age = 1; 95 inline bool has_age() const; 96 inline void clear_age(); 97 static const int kAgeFieldNumber = 1; 98 inline ::google::protobuf::int32 age() const; 99 inline void set_age(::google::protobuf::int32 value); 100 101 // required string name = 2; 102 inline bool has_name() const; 103 inline void clear_name(); 104 static const int kNameFieldNumber = 2; 105 inline const ::std::string& name() const; 106 inline void set_name(const ::std::string& value); 107 inline void set_name(const char* value); 108 inline void set_name(const char* value, size_t size); 109 inline ::std::string* mutable_name(); 110 inline ::std::string* release_name(); 111 inline void set_allocated_name(::std::string* name); 112 113 // optional int32 grade = 3; 114 inline bool has_grade() const; 115 inline void clear_grade(); 116 static const int kGradeFieldNumber = 3; 117 inline ::google::protobuf::int32 grade() const; 118 inline void set_grade(::google::protobuf::int32 value); 119 120 // @@protoc_insertion_point(class_scope:caffe.student) 121 private: 122 inline void set_has_age(); 123 inline void clear_has_age(); 124 inline void set_has_name(); 125 inline void clear_has_name(); 126 inline void set_has_grade(); 127 inline void clear_has_grade(); 128 129 ::google::protobuf::UnknownFieldSet _unknown_fields_; 130 131 ::std::string* name_; 132 ::google::protobuf::int32 age_; 133 ::google::protobuf::int32 grade_; 134 135 mutable int _cached_size_; 136 ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; 137 138 friend void protobuf_AddDesc_caffe_2eproto(); 139 friend void protobuf_AssignDesc_caffe_2eproto(); 140 friend void protobuf_ShutdownFile_caffe_2eproto(); 141 142 void InitAsDefaultInstance(); 143 static student* default_instance_; 144 }; 145 // =================================================================== 146 147 148 // =================================================================== 149 150 // student 151 152 // required int32 age = 1; 153 inline bool student::has_age() const { 154 return (_has_bits_[0] & 0x00000001u) != 0; 155 } 156 inline void student::set_has_age() { 157 _has_bits_[0] |= 0x00000001u; 158 } 159 inline void student::clear_has_age() { 160 _has_bits_[0] &= ~0x00000001u; 161 } 162 inline void student::clear_age() { 163 age_ = 0; 164 clear_has_age(); 165 } 166 inline ::google::protobuf::int32 student::age() const { 167 return age_; 168 } 169 inline void student::set_age(::google::protobuf::int32 value) { 170 set_has_age(); 171 age_ = value; 172 } 173 174 // required string name = 2; 175 inline bool student::has_name() const { 176 return (_has_bits_[0] & 0x00000002u) != 0; 177 } 178 inline void student::set_has_name() { 179 _has_bits_[0] |= 0x00000002u; 180 } 181 inline void student::clear_has_name() { 182 _has_bits_[0] &= ~0x00000002u; 183 } 184 inline void student::clear_name() { 185 if (name_ != &::google::protobuf::internal::kEmptyString) { 186 name_->clear(); 187 } 188 clear_has_name(); 189 } 190 inline const ::std::string& student::name() const { 191 return *name_; 192 } 193 inline void student::set_name(const ::std::string& value) { 194 set_has_name(); 195 if (name_ == &::google::protobuf::internal::kEmptyString) { 196 name_ = new ::std::string; 197 } 198 name_->assign(value); 199 } 200 inline void student::set_name(const char* value) { 201 set_has_name(); 202 if (name_ == &::google::protobuf::internal::kEmptyString) { 203 name_ = new ::std::string; 204 } 205 name_->assign(value); 206 } 207 inline void student::set_name(const char* value, size_t size) { 208 set_has_name(); 209 if (name_ == &::google::protobuf::internal::kEmptyString) { 210 name_ = new ::std::string; 211 } 212 name_->assign(reinterpret_cast<const char*>(value), size); 213 } 214 inline ::std::string* student::mutable_name() { 215 set_has_name(); 216 if (name_ == &::google::protobuf::internal::kEmptyString) { 217 name_ = new ::std::string; 218 } 219 return name_; 220 } 221 inline ::std::string* student::release_name() { 222 clear_has_name(); 223 if (name_ == &::google::protobuf::internal::kEmptyString) { 224 return NULL; 225 } else { 226 ::std::string* temp = name_; 227 name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); 228 return temp; 229 } 230 } 231 inline void student::set_allocated_name(::std::string* name) { 232 if (name_ != &::google::protobuf::internal::kEmptyString) { 233 delete name_; 234 } 235 if (name) { 236 set_has_name(); 237 name_ = name; 238 } else { 239 clear_has_name(); 240 name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); 241 } 242 } 243 244 // optional int32 grade = 3; 245 inline bool student::has_grade() const { 246 return (_has_bits_[0] & 0x00000004u) != 0; 247 } 248 inline void student::set_has_grade() { 249 _has_bits_[0] |= 0x00000004u; 250 } 251 inline void student::clear_has_grade() { 252 _has_bits_[0] &= ~0x00000004u; 253 } 254 inline void student::clear_grade() { 255 grade_ = 0; 256 clear_has_grade(); 257 } 258 inline ::google::protobuf::int32 student::grade() const { 259 return grade_; 260 } 261 inline void student::set_grade(::google::protobuf::int32 value) { 262 set_has_grade(); 263 grade_ = value; 264 } 265 266 267 // @@protoc_insertion_point(namespace_scope) 268 269 } // namespace caffe 270 271 #ifndef SWIG 272 namespace google { 273 namespace protobuf { 274 275 276 } // namespace google 277 } // namespace protobuf 278 #endif // SWIG 279 280 // @@protoc_insertion_point(global_scope) 281 282 #endif // PROTOBUF_caffe_2eproto__INCLUDED
1 // Generated by the protocol buffer compiler. DO NOT EDIT! 2 // source: caffe.proto 3 4 #define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION 5 #include "caffe.pb.h" 6 7 #include <algorithm> 8 9 #include <google/protobuf/stubs/common.h> 10 #include <google/protobuf/stubs/once.h> 11 #include <google/protobuf/io/coded_stream.h> 12 #include <google/protobuf/wire_format_lite_inl.h> 13 #include <google/protobuf/descriptor.h> 14 #include <google/protobuf/generated_message_reflection.h> 15 #include <google/protobuf/reflection_ops.h> 16 #include <google/protobuf/wire_format.h> 17 // @@protoc_insertion_point(includes) 18 19 namespace caffe { 20 21 namespace { 22 23 const ::google::protobuf::Descriptor* student_descriptor_ = NULL; 24 const ::google::protobuf::internal::GeneratedMessageReflection* 25 student_reflection_ = NULL; 26 27 } // namespace 28 29 30 void protobuf_AssignDesc_caffe_2eproto() { 31 protobuf_AddDesc_caffe_2eproto(); 32 const ::google::protobuf::FileDescriptor* file = 33 ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( 34 "caffe.proto"); 35 GOOGLE_CHECK(file != NULL); 36 student_descriptor_ = file->message_type(0); 37 static const int student_offsets_[3] = { 38 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(student, age_), 39 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(student, name_), 40 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(student, grade_), 41 }; 42 student_reflection_ = 43 new ::google::protobuf::internal::GeneratedMessageReflection( 44 student_descriptor_, 45 student::default_instance_, 46 student_offsets_, 47 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(student, _has_bits_[0]), 48 GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(student, _unknown_fields_), 49 -1, 50 ::google::protobuf::DescriptorPool::generated_pool(), 51 ::google::protobuf::MessageFactory::generated_factory(), 52 sizeof(student)); 53 } 54 55 namespace { 56 57 GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); 58 inline void protobuf_AssignDescriptorsOnce() { 59 ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, 60 &protobuf_AssignDesc_caffe_2eproto); 61 } 62 63 void protobuf_RegisterTypes(const ::std::string&) { 64 protobuf_AssignDescriptorsOnce(); 65 ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( 66 student_descriptor_, &student::default_instance()); 67 } 68 69 } // namespace 70 71 void protobuf_ShutdownFile_caffe_2eproto() { 72 delete student::default_instance_; 73 delete student_reflection_; 74 } 75 76 void protobuf_AddDesc_caffe_2eproto() { 77 static bool already_here = false; 78 if (already_here) return; 79 already_here = true; 80 GOOGLE_PROTOBUF_VERIFY_VERSION; 81 82 ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( 83 " 13caffe.proto 22 05caffe"3 07student 22 13 03age 30 01" 84 " 02( 05 22 14 04name 30 02 02( 22 05grade 30 03 01( 05", 73); 85 ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( 86 "caffe.proto", &protobuf_RegisterTypes); 87 student::default_instance_ = new student(); 88 student::default_instance_->InitAsDefaultInstance(); 89 ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_caffe_2eproto); 90 } 91 92 // Force AddDescriptors() to be called at static initialization time. 93 struct StaticDescriptorInitializer_caffe_2eproto { 94 StaticDescriptorInitializer_caffe_2eproto() { 95 protobuf_AddDesc_caffe_2eproto(); 96 } 97 } static_descriptor_initializer_caffe_2eproto_; 98 99 // =================================================================== 100 101 #ifndef _MSC_VER 102 const int student::kAgeFieldNumber; 103 const int student::kNameFieldNumber; 104 const int student::kGradeFieldNumber; 105 #endif // !_MSC_VER 106 107 student::student() 108 : ::google::protobuf::Message() { 109 SharedCtor(); 110 } 111 112 void student::InitAsDefaultInstance() { 113 } 114 115 student::student(const student& from) 116 : ::google::protobuf::Message() { 117 SharedCtor(); 118 MergeFrom(from); 119 } 120 121 void student::SharedCtor() { 122 _cached_size_ = 0; 123 age_ = 0; 124 name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); 125 grade_ = 0; 126 ::memset(_has_bits_, 0, sizeof(_has_bits_)); 127 } 128 129 student::~student() { 130 SharedDtor(); 131 } 132 133 void student::SharedDtor() { 134 if (name_ != &::google::protobuf::internal::kEmptyString) { 135 delete name_; 136 } 137 if (this != default_instance_) { 138 } 139 } 140 141 void student::SetCachedSize(int size) const { 142 GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); 143 _cached_size_ = size; 144 GOOGLE_SAFE_CONCURRENT_WRITES_END(); 145 } 146 const ::google::protobuf::Descriptor* student::descriptor() { 147 protobuf_AssignDescriptorsOnce(); 148 return student_descriptor_; 149 } 150 151 const student& student::default_instance() { 152 if (default_instance_ == NULL) protobuf_AddDesc_caffe_2eproto(); 153 return *default_instance_; 154 } 155 156 student* student::default_instance_ = NULL; 157 158 student* student::New() const { 159 return new student; 160 } 161 162 void student::Clear() { 163 if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { 164 age_ = 0; 165 if (has_name()) { 166 if (name_ != &::google::protobuf::internal::kEmptyString) { 167 name_->clear(); 168 } 169 } 170 grade_ = 0; 171 } 172 ::memset(_has_bits_, 0, sizeof(_has_bits_)); 173 mutable_unknown_fields()->Clear(); 174 } 175 176 bool student::MergePartialFromCodedStream( 177 ::google::protobuf::io::CodedInputStream* input) { 178 #define DO_(EXPRESSION) if (!(EXPRESSION)) return false 179 ::google::protobuf::uint32 tag; 180 while ((tag = input->ReadTag()) != 0) { 181 switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { 182 // required int32 age = 1; 183 case 1: { 184 if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == 185 ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { 186 DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< 187 ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( 188 input, &age_))); 189 set_has_age(); 190 } else { 191 goto handle_uninterpreted; 192 } 193 if (input->ExpectTag(18)) goto parse_name; 194 break; 195 } 196 197 // required string name = 2; 198 case 2: { 199 if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == 200 ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { 201 parse_name: 202 DO_(::google::protobuf::internal::WireFormatLite::ReadString( 203 input, this->mutable_name())); 204 ::google::protobuf::internal::WireFormat::VerifyUTF8String( 205 this->name().data(), this->name().length(), 206 ::google::protobuf::internal::WireFormat::PARSE); 207 } else { 208 goto handle_uninterpreted; 209 } 210 if (input->ExpectTag(24)) goto parse_grade; 211 break; 212 } 213 214 // optional int32 grade = 3; 215 case 3: { 216 if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == 217 ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { 218 parse_grade: 219 DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< 220 ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( 221 input, &grade_))); 222 set_has_grade(); 223 } else { 224 goto handle_uninterpreted; 225 } 226 if (input->ExpectAtEnd()) return true; 227 break; 228 } 229 230 default: { 231 handle_uninterpreted: 232 if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == 233 ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { 234 return true; 235 } 236 DO_(::google::protobuf::internal::WireFormat::SkipField( 237 input, tag, mutable_unknown_fields())); 238 break; 239 } 240 } 241 } 242 return true; 243 #undef DO_ 244 } 245 246 void student::SerializeWithCachedSizes( 247 ::google::protobuf::io::CodedOutputStream* output) const { 248 // required int32 age = 1; 249 if (has_age()) { 250 ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->age(), output); 251 } 252 253 // required string name = 2; 254 if (has_name()) { 255 ::google::protobuf::internal::WireFormat::VerifyUTF8String( 256 this->name().data(), this->name().length(), 257 ::google::protobuf::internal::WireFormat::SERIALIZE); 258 ::google::protobuf::internal::WireFormatLite::WriteString( 259 2, this->name(), output); 260 } 261 262 // optional int32 grade = 3; 263 if (has_grade()) { 264 ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->grade(), output); 265 } 266 267 if (!unknown_fields().empty()) { 268 ::google::protobuf::internal::WireFormat::SerializeUnknownFields( 269 unknown_fields(), output); 270 } 271 } 272 273 ::google::protobuf::uint8* student::SerializeWithCachedSizesToArray( 274 ::google::protobuf::uint8* target) const { 275 // required int32 age = 1; 276 if (has_age()) { 277 target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->age(), target); 278 } 279 280 // required string name = 2; 281 if (has_name()) { 282 ::google::protobuf::internal::WireFormat::VerifyUTF8String( 283 this->name().data(), this->name().length(), 284 ::google::protobuf::internal::WireFormat::SERIALIZE); 285 target = 286 ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 287 2, this->name(), target); 288 } 289 290 // optional int32 grade = 3; 291 if (has_grade()) { 292 target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->grade(), target); 293 } 294 295 if (!unknown_fields().empty()) { 296 target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( 297 unknown_fields(), target); 298 } 299 return target; 300 } 301 302 int student::ByteSize() const { 303 int total_size = 0; 304 305 if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { 306 // required int32 age = 1; 307 if (has_age()) { 308 total_size += 1 + 309 ::google::protobuf::internal::WireFormatLite::Int32Size( 310 this->age()); 311 } 312 313 // required string name = 2; 314 if (has_name()) { 315 total_size += 1 + 316 ::google::protobuf::internal::WireFormatLite::StringSize( 317 this->name()); 318 } 319 320 // optional int32 grade = 3; 321 if (has_grade()) { 322 total_size += 1 + 323 ::google::protobuf::internal::WireFormatLite::Int32Size( 324 this->grade()); 325 } 326 327 } 328 if (!unknown_fields().empty()) { 329 total_size += 330 ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( 331 unknown_fields()); 332 } 333 GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); 334 _cached_size_ = total_size; 335 GOOGLE_SAFE_CONCURRENT_WRITES_END(); 336 return total_size; 337 } 338 339 void student::MergeFrom(const ::google::protobuf::Message& from) { 340 GOOGLE_CHECK_NE(&from, this); 341 const student* source = 342 ::google::protobuf::internal::dynamic_cast_if_available<const student*>( 343 &from); 344 if (source == NULL) { 345 ::google::protobuf::internal::ReflectionOps::Merge(from, this); 346 } else { 347 MergeFrom(*source); 348 } 349 } 350 351 void student::MergeFrom(const student& from) { 352 GOOGLE_CHECK_NE(&from, this); 353 if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { 354 if (from.has_age()) { 355 set_age(from.age()); 356 } 357 if (from.has_name()) { 358 set_name(from.name()); 359 } 360 if (from.has_grade()) { 361 set_grade(from.grade()); 362 } 363 } 364 mutable_unknown_fields()->MergeFrom(from.unknown_fields()); 365 } 366 367 void student::CopyFrom(const ::google::protobuf::Message& from) { 368 if (&from == this) return; 369 Clear(); 370 MergeFrom(from); 371 } 372 373 void student::CopyFrom(const student& from) { 374 if (&from == this) return; 375 Clear(); 376 MergeFrom(from); 377 } 378 379 bool student::IsInitialized() const { 380 if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; 381 382 return true; 383 } 384 385 void student::Swap(student* other) { 386 if (other != this) { 387 std::swap(age_, other->age_); 388 std::swap(name_, other->name_); 389 std::swap(grade_, other->grade_); 390 std::swap(_has_bits_[0], other->_has_bits_[0]); 391 _unknown_fields_.Swap(&other->_unknown_fields_); 392 std::swap(_cached_size_, other->_cached_size_); 393 } 394 } 395 396 ::google::protobuf::Metadata student::GetMetadata() const { 397 protobuf_AssignDescriptorsOnce(); 398 ::google::protobuf::Metadata metadata; 399 metadata.descriptor = student_descriptor_; 400 metadata.reflection = student_reflection_; 401 return metadata; 402 } 403 404 405 // @@protoc_insertion_point(namespace_scope) 406 407 } // namespace caffe 408 409 // @@protoc_insertion_point(global_scope)
生成之后,我们编写一个读取文件caffeReader.cpp
#include "caffe.pb.h" #include<iostream> #include<ios> using namespace std; void InfoStudents(const caffe::student & stu){ cout<< "student info:"<<endl; cout<<"name: "<<stu.name()<<endl; cout<<"age: "<<stu.age()<<endl; cout<<"grade: "<<stu.grade()<<endl; } int main(void) { caffe::student stu; stu.set_age(18); stu.set_name("gongxijun"); stu.set_grade(146); InfoStudents(stu); return 0; }
编译完成之后,我们执行如下命令:
g++ caffeRead.cpp -o caffeReader caffe.pb.cc -I /usr/local/protobuf/include -L /usr/local/protobuf/lib -lprotobuf -pthread
生成二进制执行文件caffeReader.我们运行该文件就会显示如下信息:
知道了proto文件是如何使用之,再去caffe.proto中看看caffe中定义的结构体:
message 表示需要传输的的参数的结构体.
caffe.proto中保存的有二进制大文件Blob的结构信息:BlobProto, BlobProtoVector, Datum
BlobProto:
1 // Specifies the shape (dimensions) of a Blob. 2 //用来表示图片的shape 3 message BlobShape { 4 repeated int64 dim = 1 [packed = true]; 5 } 6 7 message BlobProto { 8 optional BlobShape shape = 7; //现在用来替换下面的num,channels ,height,width,推荐使用 9 repeated float data = 5 [packed = true]; //forward计算数据 10 repeated float diff = 6 [packed = true]; //backward的残差数据 11 repeated double double_data = 8 [packed = true]; //双精度forward计算数据 12 repeated double double_diff = 9 [packed = true]; //双精度backward的残差数据 13 14 // 4D dimensions -- deprecated. Use "shape" instead. 15 optional int32 num = 1 [default = 0]; // 图片个数or 维度 16 optional int32 channels = 2 [default = 0]; //通过比如rgb便是3维 17 optional int32 height = 3 [default = 0]; //图片高度 18 optional int32 width = 4 [default = 0]; //图片宽度 19 }
BlobProtoVector:BlobProto的动态数组
message BlobProtoVector { repeated BlobProto blobs = 1; }
Datum是lmdb的数据格式,详情可以看这里 http://blog.csdn.net/u010668907/article/details/51834411
message Datum {//lmdb中的数据格式 optional int32 channels = 1;//图片通道数比如rgb的通道数为3 optional int32 height = 2;//图片的高度 optional int32 width = 3;//图片的宽度 // the actual image data, in bytes optional bytes data = 4;//图片的数据.比如rgb的三维数组格式 optional int32 label = 5;//这张图片对应的标签,或者这块图像对应的标签[比如20个分类转换成数字之后对应的[0~19] // Optionally, the datum could also hold float data. repeated float float_data = 6;//图片的数据,有时候图片在转换过程中会变成浮点型 // If true data contains an encoded image that need to be decoded optional bool encoded = 7 [default = false];//是否需要解码 }
剩下的大部分都是Layer部分和Net部分和Solver部分的参数,关于Blob和Layer,Net还有Solver这四个部分的关系:
blob作为贯穿整个框架的数据单元,Sovler通过sovler.prototxt【我觉得我可能需要说明一下:.proto和.prototxt的区别吧,这两个都是google protobuff的文件,.proto用来定义结构体参数,.prototxt用来相应的.proto中的结构体的初始化数据】配置初始化Net,然后Net通过调用trainval.prototxt这些参数,来调用对应的Layer,并将数据blob输入到相应的Layer中,Layer来对流入的数据进行计算处理,然后再将计算后的blob数据返回,通过Net流向下一个Layer,每次执行一次,Solver就会计数一次,然后调整learn_rate,descay_weith等权值,参考的是caffe论坛上的这个话题:这里附上链接
http://www.caffecn.cn/?/question/123&sort_key=agree_count&sort=DESC