4

私は長い間この作品を作ろうとしてきました。

私のプロジェクトでは、テンプレート関数serializeを実装することにより、boostの正確なチュートリアルを使用してシリアル化されている6つのクラスがあります。

それらのクラスは、State、guState、Policy、Action、Param、Vec3Dです。

それらをシリアル化して保存すると、正常に動作します。確かに、さまざまな数字と文字列を含むテキストファイルを取得します。

不平、警告、例外はスローされません。唯一のケースは、クラスのポインターメンバーをシリアル化しようとすると、ホールプロセスがゾンビになることです。だから私はそうしようとはしません、そして節約はうまくいきます。

ただし、ロードしようとすると、次のようになります。

'boost :: archive :: archive_exception' what():ストリームエラーのインスタンスをスローした後に呼び出された終了

ここで興味深いのは、2つのboost :: ptr_vectorsをシリアル化することです。1つはStateポインターで構成され、もう1つはPolicyポインターで構成されます。

状態ベクトル、問題なく保存してロードしました。ポリシーベクトル、保存できますが、ロードしようとすると例外が発生します。

さらに、ブーストチュートリアルを読んだ後、ロードするためにシリアル化機能以外は何も必要ないという印象を受けました。

ただし、ロードしようとすると、ブーストシリアル化により、State()、Policy()などのデフォルトコンストラクターが見つからないと文句が言われます(各クラスに独自のコンストラクターを実装します)。

ここでこのチュートリアルを読んだ後、ブーストシリアル化が機能するように、何もしないデフォルトのコンストラクターを実装しました。確かにそれはコンパイルされました、そして私は上記の結果を得ました。

save_construct_dataとload_construct_dataを分離して実装しようとした、ここでの古い質問に見られる非常に複雑な道を進んでみましたが、これはあまりにも煩わしいと感じました。ここでも、上記の正確なエラーが発生しました。

誰かが私を助けてくれますか、ロードがどのように機能するか、デフォルトのコンストラクターとの関係は何ですか?または、少なくとも役立つかもしれないリンクを教えてください。私はブーストでマニュアルを読みました、そして、彼らは再建について多くを説明しません。

ありがとうございました。

編集(いくつかのスニペットを追加)

class State
{
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version);

  protected:
    std::map<std::string,float> positions;
    float reward;
    std::size_t hash_value;
    bool exists(const Action* A);
    bool operator== (State const& S);
    std::size_t hash();
    void clean_noise();
    State(){}; // NOTE: This is used only by serializer, without it, code won't compile

  public:
    enum position { standing, on_chest, on_back, on_left, on_right, getting_up };
    position current_position;
    Policy *my_policy;
    Vec3D gps;
    boost::ptr_vector<Action> actions;
    State(ACTION_MODE &m);
    ~State();
    bool operator== (State const* S);
    bool operator< (State const* S) const ;
    const float& getR() const;
    bool addAction(Action *A);
    Action* findAction(const Action *A);
    boost::ptr_vector<Action>& getAllActions();
    void printState();
    virtual bool isTerm();
};

template <class Archive>
void State::serialize(Archive& ar, const unsigned int version)
{
  ar & BOOST_SERIALIZATION_NVP(positions);
  ar & BOOST_SERIALIZATION_NVP(gps);
  ar & BOOST_SERIALIZATION_NVP(current_position);
  ar & BOOST_SERIALIZATION_NVP(reward);
  ar & BOOST_SERIALIZATION_NVP(hash_value);
  ar & BOOST_SERIALIZATION_NVP(actions);
  ar & BOOST_SERIALIZATION_NVP(my_policy);
}

Stateから継承する他のクラスにも、以下を使用してシリアル化関数があります。

  ar & boost::serialization::base_object<State>(*this);

クラスポリシー:

class Policy
{ 
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version);

    Policy() {}; // NOTE: Again same as with state, used only by serialize load

  protected:

    float QValue;
    State *state;                

  public:

    //! Base class constructor 
    Policy(State *s);
    ...        
};

template <class Archive>
void Policy::serialize(Archive& ar, const unsigned int version)
{
  ar & BOOST_SERIALIZATION_NVP(action);
  ar & BOOST_SERIALIZATION_NVP(state);
  ar & BOOST_SERIALIZATION_NVP(QValue);
  ar & BOOST_SERIALIZATION_NVP(r);
}

ご覧のとおり、これらは2つの主要なクラスですが、他のクラスも再構築の依存関係のためにシリアル化されています(クラスAction、クラスParamなど)。

マスタークラス:

template <class S, class P> class Task
{ 
  protected:
    ...
    //! Container of states of type S (template parameter)
    boost::ptr_vector<S> states;
    //! Container of policies of type P (template parameter)
    boost::ptr_vector<P> policies;
    ...

  public:

    Task(Agent &a, ACTION_MODE &m);
    ...
    void save_to_file();
    void load_from_file(std::string filename); 
};

template <class S, class P> 
void Task<S,P>::save_to_file()
{
  std::string output = ramdisk+"serialized";
  char *file = (char*)output.c_str();
  std::ofstream ofs(file);
  assert(ofs.good());  
  boost::archive::text_oarchive oa(ofs);
  oa << states;
  oa << policies;
  ofs.close();
}

template <class S, class P> 
void Task<S,P>::load_from_file(std::string filename)
{
  char *file = (char*)output.c_str();
  std::cout << file << std::endl;
  std::ifstream ifs(file);
  boost::archive::text_iarchive ia(ifs);
  ia >> states;
  ia >> policies;
  ifs.close();
}

状態とポリシーを保持する2つのboost::ptr_vectorsが効果的に含まれています。状態は問題なく保存およびロードされます。

ポリシーをロードするときに問題が発生します。それらを保存しても問題は発生しないようです(ただし、間違っている可能性があります)。

ポリシーなしで、およびポリシーを使用して保存/読み込みをテストしたところ、問題はポリシーの再構築にあるようです。

シリアル化によってのみ使用されるデフォルトのコンストラクターに注意してください。これがないと、コードはコンパイルされません。

編集#2:valgrindとmemcheckを使用してアプリケーションを実行した後、ポインターメモリリークがあることを報告します。ただし、valgrindを使用したデバッグは得意ではないため、リークが発生している場所や、シリアル化に関連しているかどうかはわかりません(そうだと思います)。

4

1 に答える 1

3

問題は、シリアル化statespoliciesPolicyいて、の同じインスタンスへの参照も保持していることですState。このような相互参照を持たないクラスのみをシリアル化できます。Boostは、ファイルへの書き込み時にポインター競合例外をスローする必要があります。私のテストでは、例外がスローされたかどうかは書き込みの順序に依存します。これは、書き込みが成功した場合でもロードが失敗するため、残念です。

oa << states回避策は、保存およびロード時に行を削除し、ロード後の手順でポインタを手動で修正することです。

コンストラクターについて:これは、ほとんどの場合、boost-apiがテンプレートマジックを実行するために必要なものです。ただし、バージョン管理を使用する場合は、メンバー変数にデフォルト値を指定して、古いバージョン番号のファイルをロードするときに初期化されないままにならないようにすることが重要です。

于 2011-09-05T12:39:28.010 に答える