tags:

views:

171

answers:

2

I am trying to send a user-defined structure named ABC using boost::mpi::send () call.

The given struct contains a vector "data" whose size is determined at runtime. Objects of struct ABC are sent by master to slaves. But the slaves need to know the size of vector "data" so that the sufficient buffer is available on the slave to receive this data. I can work around it by sending the size first and initialize sufficient buffer on the slave before receiving the objects of struct ABC. But that defeats the whole purpose of using STL containers.

Does anyone know of a better way to do handle this ? Any suggestions are greatly appreciated.

Here is a sample code that describes the intent of my program. This code fails at runtime due to above mentioned reason.

struct ABC
{
 double cur_stock_price;
 double strike_price;
 double risk_free_rate;
 double option_price;
 std::vector <char> data;
};

namespace boost
{
 namespace serialization
 {
   template<class Archive>
   void serialize (Archive &ar,
                   struct ABC &abc,
                   unsigned int version)
   {
     ar & abc.cur_stock_price;
     ar & abc.strike_price;
     ar & abc.risk_free_rate;
     ar & abc.option_price;
     ar & bopr.data;
   }
 }
}

BOOST_IS_MPI_DATATYPE (ABC);

int main(int argc, char* argv[])
{
 mpi::environment env (argc, argv);
 mpi::communicator world;

 if (world.rank () == 0)
 {
   ABC abc_obj;
  abc.cur_stock_price = 1.0;
  abc.strike_price = 5.0;
  abc.risk_free_rate = 2.5;
  abc.option_price = 3.0;
  abc_obj.data.push_back ('a');
  abc_obj.data.push_back ('b');

   world.send ( 1, ANY_TAG, abc_obj;);
   std::cout << "Rank 0 OK!" << std::endl;
 }

else if (world.rank () == 1)
{
   ABC abc_obj;

  // Fails here because abc_obj is not big enough
   world.recv (0,ANY_TAG, abc_obj;);
   std::cout << "Rank 1 OK!" << std::endl;

   for (int i = 0; i < abc_obj;.data.size(); i++)
     std::cout << i << "=" << abc_obj.data[i] << std::endl;
 }

 MPI_Finalize();
 return 0;
}
A: 

You shouldn't send the vector object itself in the message, as the receiver only needs its contents, and the internal state of the vector would probably be all messed up after receiving anyway (memory addresses that were valid on the sending end probably won't be valid on the receiving end).

Instead, here's what you need to do:

  1. Define a separate struct with four doubles and a simple char array.
  2. Whenever you need to send, create a temporary variable of this new struct, and fill the char array with the contents of the vector you want to send.
  3. Define a temporary MPI datatype that matches the size of this specific struct object.
  4. Send the temporary struct as an instance of this temporary datatype.
  5. Receive it in a suitably large receive buffer (or send the size in advance)
  6. Reconstruct the ABC struct based on the contents of the char array.

At least, that's what you need to do with vanilla C++ and MPI. I'm not familiar with boost, so I don't know if it makes any of these steps easier.

suszterpatt
Thanks for the response suszterpatt.Boost only adds the benefit of enabling vector to be used.I am currently using something similar to what you have recommended.But this is not optimized.I am keen to know if i can optimize it in any way using boost serialization and MPI libraries
lava
What do you mean by "not optimized"? What part would you like to optimize, and in what way?
suszterpatt
The amount of data one can send is restricted by the size of receive buffer. In order to avoid it, i have to send the size of the data i m sending so that the buffer can be allocated for the same.I am interested to know if there is a way to get rid of both these limitations.
lava
That's theoretically impossible. If the receiving process wants to allocate just enough memory to receive the message, then it will need to know the size of the message before receiving it. Since your messages are variable in size, that knowledge isn't available at compile time, so you'll have to lose one of those conditions. You can either send a preceding message containing the size of your payload, or use a method similar to what I describe [here](http://stackoverflow.com/questions/2258759/passing-variable-length-structures-between-mpi-processes/2274023#2274023).
suszterpatt
A: 

BOOST_IS_MPI_DATATYPE is only for fixed length data. Your array is not fixed length and this is why it fails.

baol
PS: simply remove the line with the macro, and it should start working.
baol