C 使用谷物序列化结构的静态阵列

C++ serialization of static array of struct using Cereal

本文关键字:结构 静态 阵列 序列化      更新时间:2023-10-16

我正在使用谷物库来序列化结构化数据,将它们通过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 element []。p>

出于某些未知原因,strncpy()出现故障。字符串的内容与数组的内容不同,即使我密切关注' 0',需要在char数组的末尾附加,此处显示http://www.cplusplus.com/reference/string/string/copy/。

我最终使用了std :: string.copy(),只要您在char数组的末尾添加' 0',它会按预期执行。

上面的代码正常工作。