It seems that sending stl complex data via the skeleton/content
mechanism does not work.
Here is a simple code that shows the problem:
#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;
}
}
The entries of the vector l on the output are not (1.0,1.0) but they seem to be
uninitialized. This only occurs if one uses complex data types AND
the skeleton/content mechanism.
Does anyone know, if this is a build
in problem, or if I am doing something wrong?
I ran into a similar problem with one of my classes recently, and after some stepping through the serialization procedure in the debugger, I think I figured out what’s going on. The problem is using temporaries in the serialization operators. In boost/serialization/complex.hpp, the serialization functions look like this:
Notice that the serialization is done through temporaries. The get_content functionality works by building an MPI datatype, which really is a map of the locations of content in memory. When receiving the message, MPI copies the data directly into those locations, without calling any serialization operators. The problem is that when “save” uses temporaries, get_content() won’t get the locations of the actual data but the temporaries, so the data received is not put into the right place.
For the skeleton/content functionality to work, my impression is that the save function (which is what get_content() calls) must directly, and only, serialize the data members of the object. In this case it can’t, because it doesn’t have access to the internal representation of complex. One would have to write the serialization operators as members of the class, I think.
(These limitations appear to not be mentioned at all in the Boost::MPI documentation.)