Boost MPI中使用骨架/内容机制发送复杂数据
似乎通过骨架/内容发送stl复杂数据 这个机制不起作用 下面是一个简单的代码,显示了问题:Boost MPI中使用骨架/内容机制发送复杂数据,boost,stl,mpi,complex-numbers,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;
#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;
}
}
#包括
#包括
#包括
#包括
名称空间mpi=boost::mpi;
使用名称空间std;
int main(int argc,char*argv[])
{
环境环境(argc,argv);
mpi::通信器世界;
int NN=world.size();
int myid=world.rank();
如果(myid==0)
{
int N=10;
向量l(N);
对于(int p=1;p!=NN;p++)
{
int taskid=1;
发送(p,0,taskid);
send(p,1,mpi::skeleton(l));
}
mpi::content c=mpi::get_content(l);
对于(int n=0;n!=l.size();n++)
{
l[n]=络合物(1.0,1.0);
}
对于(int p=1;p!=NN;p++)
{
发送(p,1,c);
}
}
else if(myid==2)
{
向量l;
mpi::内容c;
recv(0,1,mpi::skeleton(l));
c=mpi::获取内容(l);
世界记录(0,1,c);
对于(int n=0;n!=l.size();n++)
{
cout我最近在我的一个类中遇到了类似的问题,在调试程序中逐步完成序列化过程后,我想我知道了发生了什么。问题是在序列化运算符中使用临时变量。在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);
}
模板
内联作废保存(
存档和ar,
标准::复杂const&T,
常量unsigned int/*文件\u版本*/
){
常数T re=T.real();
常数T im=T.imag();
ar>boost::serialization::make_nvp(“真实”,re);
ar>>boost::serialization::make_nvp(“imag”,im);
t=std::complex(re,im);
}
请注意,序列化是通过临时对象完成的。get_content功能通过构建MPI数据类型来工作,MPI数据类型实际上是内存中内容位置的映射。收到消息时,MPI直接将数据复制到这些位置,而不调用任何序列化运算符。问题是当“保存”时使用临时表时,get_content()不会获取实际数据的位置,而是临时表,因此接收到的数据没有放在正确的位置
为了使骨架/内容功能正常工作,我的印象是save函数(get_content()调用这个函数)必须直接且仅序列化对象的数据成员。在这种情况下,它不能,因为它无法访问复杂的内部表示。我认为,必须将序列化运算符作为类的成员编写
(Boost::MPI文档中似乎根本没有提到这些限制。)以下是解决此问题的可能方法:
我为复杂类型编写了自己的序列化:
#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;
}
}
#包括
#包括
#包括
名称空间mpi=boost::mpi;
使用名称空间std;
名称空间提升
{
命名空间序列化
{
模板
无效序列化(存档和ar、复杂和g、常量未签名整数版本)
{
ar&g.real();
ar&g.imag();
}
}
}
int main(int argc,char*argv[])
{
环境环境(argc,argv);
mpi::通信器世界;
int NN=world.size();
int myid=world.rank();
如果(myid==0)
{
int N=10;
向量l(N);
对于(int p=1;p!=NN;p++)
{
send(p,1,mpi::skeleton(l));
}
mpi::content c=mpi::get_content(l);
对于(int n=0;n!=l.size();n++)
{
l[n]=络合物(1.0,1.0);
}
对于(int p=1;p!=NN;p++)
{
发送(p,1,c);
}
}
其他的
{
向量l;
mpi::内容c;
recv(0,1,mpi::skeleton(l));
c=mpi::获取内容(l);
世界记录(0,1,c);
对于(int n=0;n!=l.size();n++)
{
coutnamespace boost{
名称空间mpi{
模板
结构是mpi_datatype:mpl::true{};
} }
使用此选项可以解决问题。在Boost Serialization Optimization中,请注意其他类型似乎也会受到此影响。例如,序列化枚举也会使用临时变量,因此对skeleta也不起作用。感谢您的回答。至少我现在知道,在Boost/Serialization中使用内置变量是不可能做到这一点的/complex.hpp.@tstollenw:(显然我不能给你的答案添加注释,所以我在这里发表评论。)我认为你的解决方案不能保证有效,因为至少有些规范似乎说real()和imag()是按值返回的。
namespace boost {
namespace mpi {
template <>
struct is_mpi_datatype< complex<double> > : mpl::true_ { };
} }