背景
最近处理自然语言相关模块时,遇到模型初始化过慢问题,究其原因是持久化的模型数据需要层层计算才能得到最终内存中需要的数据结构。而模型文件发成变化评率很低,因此考虑对内存数据结构的序列化和反序列化来实现加速。
调研c++相关比较方便的序列化/反序列化的办法主要有Boost和ProtoBuf 2种方案。后者在跨语言传输方面大有作为,但对c++ 标准库的支持较为麻烦,而前者是c++方面成熟的框架,支持包括map在内的std库的持久化。正好模型数据最耗时的一部分在内存中正好是map形式保存,因此直接接入Boost。
过程
cmake 接入boost库
CMakeList.txt
# 增加include
target_include_directories(YOUR_MODULE_NAME PRIVATE /your_boost_path/include)
# 增加库引用
target_link_libraries(YOUR_MODULE_NAME /your_boost_path//lib/libboost_serialization.a)
配置头文件
/**
* part 1: 配置头文件
*/
// 保存为二进制
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
// 保存为XML
//#include <boost/archive/xml_iarchive.hpp>
//#include <boost/archive/xml_oarchive.hpp>
// 保存为纯文本
//#include <boost/archive/text_iarchive.hpp>
//#include <boost/archive/text_oarchive.hpp>
// 要保存什么类型,则需要引用对应的boost头文件
//#include <boost/serialization/list.hpp>
//#include <boost/serialization/vector.hpp>
#include <boost/serialization/map.hpp>
序列化和反序列化方法
/**
* part 2: 序列化和反序列化方法
*/
void save(string path, map<int, map<int, float>> &m) {
std::ofstream file(path);
// binary_oarchive 会以二进制形式保存,若要改为xml或text,将头文件和该类型的“binary”直接替换为xml或者text即可
boost::archive::binary_oarchive oa(file, boost::archive::no_header);
oa << m;
}
void load(string path, map<int, map<int, float>> &m)
{
std::ifstream file(path);
boost::archive::binary_iarchive ia(file, boost::archive::no_header);
ia >> m;
}
调用示例
/**
* part 3: 调用示例
*/
std::map<int, map<int, float>> m1;
save("1.bin", m1); // 将map保存到文件1.bin
std::map<int, map<int, float>> m2;
load("1.bin", m1); // 从1.bin文件加载map
完整示例
/**
* part 1: 配置头文件
*/
// 保存为二进制
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
// 保存为XML
//#include <boost/archive/xml_iarchive.hpp>
//#include <boost/archive/xml_oarchive.hpp>
// 保存为纯文本
//#include <boost/archive/text_iarchive.hpp>
//#include <boost/archive/text_oarchive.hpp>
// 要保存什么类型,则需要引用对应的boost头文件
//#include <boost/serialization/list.hpp>
//#include <boost/serialization/vector.hpp>
#include <boost/serialization/map.hpp>
/**
* part 2: 序列化和反序列化方法
*/
void save(string path, map<int, map<int, float>> &m) {
std::ofstream file(path);
// binary_oarchive 会以二进制形式保存,若要改为xml或text,将头文件和该类型的“binary”直接替换为xml或者text即可
boost::archive::binary_oarchive oa(file, boost::archive::no_header);
oa << m;
}
void load(string path, map<int, map<int, float>> &m)
{
std::ifstream file(path);
boost::archive::binary_iarchive ia(file, boost::archive::no_header);
ia >> m;
}
/**
* part 3: 调用示例
*/
std::map<int, map<int, float>> m1;
save("1.bin", m1); // 将map保存到文件1.bin
std::map<int, map<int, float>> m2;
load("1.bin", m1); // 从1.bin文件加载map