3

スケルトン/コンテンツメカニズムを介したstl複合データの送信は機能しないようです。

問題を示す簡単なコードを次に示します。

#include <boost/mpi.hpp>
#include <boost/serialization/complex.hpp>
#include <boost/serialization/vector.hpp>
#include <iostream>
namespace mpi = boost::mpi;
using namespace std;

int main(int argc, char* argv[])
{
     mpi::environment env(argc, argv);
     mpi::communicator world;
     int NN=world.size();
     int myid=world.rank();

     if (myid == 0)
     {
         int N = 10;
         vector <complex<double> > l(N);
         for (int p=1; p!=NN; p++)
             {
             int taskid=1;
             world.send(p, 0, taskid);
             world.send(p, 1, mpi::skeleton(l));
         }
         mpi::content c = mpi::get_content(l);
             for (int n = 0; n!=l.size() ; n++)
         {
             l[n]=complex<double>(1.0,1.0);
         }
         for (int p=1; p!=NN; p++)
         {
                 world.send(p, 1, c);
         }
     }
     else if (myid == 2)
     {
         vector <complex<double> > l;
         mpi::content c;
         world.recv(0, 1, mpi::skeleton(l));
         c = mpi::get_content(l);
         world.recv(0, 1, c);
         for (int n=0; n!=l.size(); n++)
         {
                 cout << l[n] << " ";
         }
         cout << endl;
     }
} 

出力のベクトルlのエントリは(1.0,1.0)ではありませんが、初期化されていないようです。これは、複雑なデータ型とスケルトン/コンテンツメカニズムを使用する場合にのみ発生します。

これが組み込みの問題なのか、それとも私が何か間違ったことをしているのか、誰か知っていますか?

4

3 に答える 3

3

最近、クラスの1つで同様の問題が発生しました。デバッガーでシリアル化手順を実行した後、何が起こっているのか理解できたと思います。問題は、シリアル化演算子で一時的なものを使用することです。boost / serialization / complex.hppでは、シリアル化関数は次のようになります。

template<class Archive, class T>
inline void save(
    Archive & ar,
    std::complex< T > const & t,
    const unsigned int /* file_version */
){
    const T re = t.real();
    const T im = t.imag();
    ar << boost::serialization::make_nvp("real", re);
    ar << boost::serialization::make_nvp("imag", im);
}

template<class Archive, class T>
inline void load(
    Archive & ar,
    std::complex< T >& t,
    const unsigned int /* file_version */ 
){
    T re;
    T im;
    ar >> boost::serialization::make_nvp("real", re);
    ar >> boost::serialization::make_nvp("imag", im);
    t = std::complex< T >(re,im);
}

シリアル化は一時的に行われることに注意してください。get_content機能は、MPIデータ型を構築することによって機能します。これは、実際にはメモリ内のコンテンツの場所のマップです。メッセージを受信すると、MPIは、シリアル化演算子を呼び出さずに、データをこれらの場所に直接コピーします。問題は、「save」が一時データを使用する場合、get_content()は実際のデータの場所ではなく一時データの場所を取得するため、受信したデータが適切な場所に配置されないことです。

スケルトン/コンテンツ機能が機能するためには、save関数(get_content()が呼び出すもの)がオブジェクトのデータメンバーを直接、そして唯一、シリアル化する必要があるというのが私の印象です。この場合、complexの内部表現にアクセスできないため、できません。クラスのメンバーとしてシリアル化演算子を作成する必要があると思います。

(これらの制限は、Boost :: MPIドキュメントではまったく言及されていないようです。)

于 2011-11-28T17:17:54.403 に答える
0

この問題の可能な回避策は次のとおりです。

複合型用に独自のシリアル化を作成しました。

#include <boost/mpi.hpp>
#include <boost/serialization/vector.hpp>
#include <iostream>
namespace mpi = boost::mpi;
using namespace std;

namespace boost
{
    namespace serialization
    {
        template<class Archive>
        void serialize(Archive & ar, complex<double> & g, const unsigned int version)
        {
            ar & g.real();
            ar & g.imag();
        }
    }
}

int main(int argc, char* argv[])
{
    mpi::environment env(argc, argv);
    mpi::communicator world;
    int NN=world.size();
    int myid=world.rank();

    if (myid == 0) 
    {
        int N = 10;
        vector <complex<double> > l(N);
        for (int p=1; p!=NN; p++)
        {
            world.send(p, 1, mpi::skeleton(l));
        }
        mpi::content c = mpi::get_content(l);
        for (int n = 0; n!=l.size() ; n++) 
        {
            l[n]=complex<double>(1.0,1.0);
        }
        for (int p=1; p!=NN; p++)
        {
            world.send(p, 1, c);
        }
    } 
    else 
    {
        vector <complex<double> > l;
        mpi::content c;
        world.recv(0, 1, mpi::skeleton(l));
        c = mpi::get_content(l);
        world.recv(0, 1, c);
        for (int n=0; n!=l.size(); n++)
        {
            cout << l[n] << " ";
        }
        cout << endl;
    }
}
于 2011-12-07T15:12:40.833 に答える
0
namespace boost { 
namespace mpi {
    template <>
    struct is_mpi_datatype< complex<double> > : mpl::true_ { };
} }

これを使用すると、問題を解決できます。ブーストシリアル化の最適化

于 2014-03-11T09:58:59.870 に答える