【问题标题】:Sending complex data with skeleton/content mechanism in Boost MPI在 Boost MPI 中使用骨架/内容机制发送复杂数据
【发布时间】:2011-12-28 23:19:22
【问题描述】:

似乎通过骨架/内容发送 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) 但它们似乎是 未初始化。这仅在使用复杂数据类型和 骨架/内容机制。

有谁知道,如果这是一个构建 有问题,或者我做错了什么?

【问题讨论】:

    标签: boost stl mpi complex-numbers


    【解决方案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()获取的不是实际数据的位置而是临时对象,所以接收到的数据没有放到正确的位置。

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

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

    【讨论】:

    • 请注意,其他类型似乎也受此影响。例如,序列化枚举也使用临时变量,因此也不适用于 skeleta。
    • 感谢您的回答。至少我现在知道,使用 boost/serialization/complex.hpp 中的构建是不可能做到这一点的。
    • @tstollenw:(我显然无法将 cmets 添加到您的答案中,所以我在这里发表评论。)我认为您的解决方法不能保证有效,因为至少某些规范似乎说 real() 和 imag() 按值返回。
    【解决方案2】:

    以下是该问题的可能解决方法:

    我为复杂类型编写了自己的序列化:

    #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;
        }
    }
    

    【讨论】:

      【解决方案3】:
      namespace boost { 
      namespace mpi {
          template <>
          struct is_mpi_datatype< complex<double> > : mpl::true_ { };
      } }
      

      使用它可以解决问题。在 Boost 序列化优化中

      【讨论】:

        猜你喜欢
        • 2010-10-17
        • 2021-04-30
        • 1970-01-01
        • 2015-08-20
        • 2016-11-30
        • 2012-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多