我正在使用 Cereal 库对结构化数据进行序列化,通过 MPI 发送它们,然后使用 CUDA 在 GPU 上处理它们。由于后者,我不能使用 std::vector,因为 CUDA 在动态对象方面存在问题。因此,我正在使用结构的静态数组。
目标
对具有嵌套静态对象数组的对象进行二进制序列化和反序列化。
要序列化的对象
//==========================================================//
// ELEMENT DEFINITION //
//==========================================================//
class element{
public:
//==========================//
// CONTENT //
//==========================//
int grid_id;
int NN_id;
int debug;
//==========================//
// SERIALIZATION //
//==========================//
// function required by cereal library
template<class Archive>
void serialize(Archive & ar){
ar( grid_id );
ar( NN_id );
ar( debug );
}
};
//==========================================================//
// CONTAINER DEFINITION //
//==========================================================//
class GPU_in_grid : public Managed{
public:
//==========================//
// CONTENT //
//==========================//
int gpu_id;
element element[GRID_SIZE]; <------ static array of structures
int debug;
//==========================//
// SERIALIZATION //
//==========================//
template<class Archive>
void serialize(Archive & ar){
ar( gpu_id );
ar( debug );
ar( element );
}
};
序列化函数
// cereal serialization
#include <cereal/archives/binary.hpp>
#include <cereal/archives/portable_binary.hpp>
//#include <cereal/archives/xml.hpp>
template<typename data_type>
int Process::serialize(data_type * data, char *serial_data, int *size){
// serialize the data
std::ostringstream oss(std::ios::binary);
cereal::BinaryOutputArchive ar(oss);
//cereal::XMLOutputArchive ar(std::cout);
ar(*data);
std::string s=oss.str();
*size = s.length();
strncpy(serial_data, s.c_str(), s.length());
std::cout << "buffer["<< s.length() << "] >> " << s << std::endl;
s.clear();
return _SUCCESS_;
};
template<typename data_type>
int Process::deserialize(data_type * data, char *serial_data, int size){
// create temporary buffer to store the received data
char * buf=new char[size];
strncpy(buf, serial_data, size);
std::istringstream iss(std::string(serial_data, size), std::ios::binary);
cereal::BinaryInputArchive arin(iss);
arin(*data);
// clean buffer
delete[] buf;
return _SUCCESS_;
};
调试输出
cpu_mem BEFORE serialization
cpu_mem.debug = -1
cpu_mem.gpu_id = -5
cpu_mem.element[0].NN_id = 1
cpu_mem.element[0].debug = 2
buffer[248] >> �������� <------ binary format
cpu_mem AFTER deserialization
cpu_mem.debug = -1 <----- CORRECT
cpu_mem.gpu_id = -5 <----- CORRECT
cpu_mem.element[0].NN_id = 0 <----- INCORRECT
cpu_mem.element[0].debug = 0 <----- INCORRECT
如果我尝试一下流,我可以将序列化的对象打印为 XML,以检查序列化是否成功。
<?xml version="1.0" encoding="utf-8"?>
<cereal>
<value0>
<gpu_id>-5</gpu_id> <----- CORRECT
<debug>-1</debug> <----- CORRECT
<element>
<value0>
<grid_id>0</grid_id>
<NN_id>1</NN_id> <----- CORRECT
<debug>2</debug> <----- CORRECT
</value0>
<value1>
<grid_id>32522</grid_id>
<NN_id>2</NN_id>
<debug>4612412</debug>
</value1>
</element>
</value0>
</cereal>
问题
上面的输出显示,反序列化正确识别容器(类 GPU_in_grid)中的变量,但无法反序列化我的结构的较低级别,即结构静态数组 -> element[]。
最佳答案
由于某些我不知道的原因,strncpy() 出现故障。字符串的内容与数组的内容不同,即使我关注“\0”,也需要将其附加到 char 数组的末尾,此处显示 http://www.cplusplus.com/reference/string/string/copy/ .
我最终改用了 std::string.copy(),只要您在 char 数组末尾添加 '\0',它就会按预期执行。
上面的代码可以正常工作。
关于使用 Cereal 对静态结构数组进行 C++ 序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47574784/