|
protobuf简介
protobuf是一种混合语言的数据标准:通过结构化数据进行序列化(串行化),用于通讯协议、数据存储等领域。
通常描述protobuf,有两个层面:
- 在表现形式上,定义了一种源文件,扩展名为.proto,可以在其中定义存储类的内容;同时,protobuf有自己的专门编译器protoc(后面会介绍如何安装),可以将.protoc编译成.cc和.h文件,使之能在C++/Python工程中直接使用的类
- 在本质上,定义了一种二进制数据交换格式,可以将C++/Python中定义的存储类的内容(结构化数据)与二进制序列相互转换,主要用于数据存储和传输。
protobuf使用流程
目前proto支持C++,python,java等语言,这里主要演示caffe中使用的C++调用。
- 编写XXX.proto文件。该文件里主要定义了各种数据结构及对应的数据类型,如int,string等。
- 使用protoc对XXX.proto文件进行编译,生成对应的数据结构文件的读取和写入程序,程序接口都是标准化的。生成的文件一般名为http://XXX.pb.cc和XXX.pb.h。
- 在新程序中使用XXX.pb.c和XXX.pb.h提供的代码。
syntax = "proto2";
package caffe;//c++ namespace
message NetParameter {
optional string name = 1; // consider giving the network a name
repeated LayerParameter layer = 2; // ID 100 so layers are printed last.
}
// LayerParameter next available layer-specific ID: 147 (last added: recurrent_param)
message LayerParameter {
optional string name = 1; // the layer name
optional string type = 2; // the layer type
repeated string bottom = 3; // the name of each bottom blob
repeated string top = 4; // the name of each top blob
// Layer type-specific parameters.
optional ConvolutionParameter convolution_param = 106;
}
message ConvolutionParameter {
optional uint32 num_output = 1; // The number of outputs for the layer
// Pad, kernel size, and stride are all given as a single value for equal
// dimensions in all spatial dimensions, or once per spatial dimension.
repeated uint32 pad = 3; // The padding size; defaults to 0
repeated uint32 kernel_size = 4; // The kernel size
repeated uint32 stride = 6; // The stride; defaults to 1
}其中,syntax 代表用的是proto版本号,package 对应C++的namespace,message 对应C++的类。
包声明(package):proto文件以package声明开头,有助于区分不同项目之间的命名冲突。在C++以package声明的文件内容对应生成的类,放在与包匹配的namesapce中,上面的.proto文件中声明都属于caffe。
字段声明(message): protobuf中定义一个消息类型是通过关键字message字段指定的,类似C++中class关键字,该类公开继承自google::protobuf::Message。(用Message关键字声明的消息体,允许你检查、增删改查整个消息,包括解析二进制字符串以及序列化二进制字符串等方法)
字段规则:1、required:消息体中必填字段,不设置会导致编解码异常;2、optional:消息体中可选字段,可通过defalut关键字设置默认值;3、repeated:消息体中可重复字段,重复的值的顺序会被保留。
总结,在一个AI训练的模型中,主要包括了模型的定义net_def和模型的权重net_weight。而protobuf在其中起到的作用就是基于.proto文件以及prototxt文件构建出对应C++/Python的graph模型结构的定义(net_def),而模型权重,通常存储在caffe的blob数据结构中,可以从onnx或caffe.bin中读取。
Cmake编译protobuf
大致可以分为三个步骤:
1、下载对应版本protobuf release版本
https://github.com/protocolbuffers/protobuf/releases2、这篇是cmake和protobuf的结合使用,所以我这里安装的是protobuf-cpp-3.6.1.tar.gz
$ tar xf protobuf-cpp-3.6.1.tar.gz
$ cd protobuf-3.6.1
$ ./configure
$ make
$ sudo make install 3、编写 cmake 来自动产生 proto 对应的 .cc 和 .h 文件,文件名分别是caffe.pb.cc和caffe.pb.h
cmake_minimum_required(VERSION 3.10)
project(nart_proto)
# 查找 protobuf
find_package(Protobuf REQUIRED)
if (PROTOBUF_FOUND)
message("protobuf found")
else ()
message(FATAL_ERROR "Cannot find Protobuf")
endif ()
# 编译 proto 为 .cpp 和 .h
file(GLOB NART_PROTOS *.proto)
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${NART_PROTOS})
message("PROTO_SRCS = ${PROTO_SRCS}")
message("PROTO_HDRS = ${PROTO_HDRS}")
# 将PROTO_SRCS生成静态库nart_proto.a文件
add_library(nart_proto STATIC ${PROTO_SRCS})
target_include_directories(nart_proto
PUBLIC ${CMAKE_CURRENT_BINARY_DIR}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC ${PROTOBUF_INCLUDE_DIRS})
# 关联 protobuf 到最后的二进制文件,生成可执行文件
add_executable(cmake_protobuf
src/main.cpp
${PROTO_SRCS}
${PROTO_HDRS})
target_link_libraries(cmake_protobuf nart_proto) |
|