在Boost MPI中使用骨架/内容机制发送复杂数据

时间:2011-11-14 20:11:46

标签: boost stl mpi complex-numbers

似乎通过骨架/内容发送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),但它们似乎是 初始化。只有在使用复杂数据类型AND时才会出现这种情况 骨架/内容机制。

有人知道,如果这是一个版本 在问题中,或者如果我做错了什么?

3 个答案:

答案 0 :(得分:3)

我最近在我的一个类中遇到了类似的问题,在调试器中逐步完成序列化过程之后,我想我发现了正在发生的事情。问题是在序列化运算符中使用临时值。在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会将数据直接复制到这些位置,而无需调用任何序列化运算符。问题是当“保存”使用临时值时,get_content()不会获得实际数据的位置而是临时数据,因此收到的数据不会放到正确的位置。

为了使骨架/内容功能起作用,我的印象是save函数(get_content()调用的函数)必须直接且仅序列化对象的数据成员。在这种情况下,它不能,因为它无法访问复杂的内部表示。我认为,必须将序列化运算符编写为类的成员。

(Boost :: MPI文档中似乎没有提到这些限制。)

答案 1 :(得分: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;
    }
}

答案 2 :(得分:0)

namespace boost { 
namespace mpi {
    template <>
    struct is_mpi_datatype< complex<double> > : mpl::true_ { };
} }
使用这个可以解决问题。在Boost序列化优化中