cannot send std::vector using MPI_Send and MPI_Recv
Asked Answered
I

2

9

I am trying to send std:vector using MPI send and recv functions but I have reached no where. I get errors like

Fatal error in MPI_Recv: Invalid buffer pointer, error stack:
MPI_Recv(186): MPI_Recv(buf=(nil), count=2, MPI_INT, src=0, tag=0, MPI_COMM_WORLD, status=0x7fff9e5e0c80) failed
MPI_Recv(124): Null buffer pointer

I tried multiple combinations

A) like what used to send arrays ..

 std::vector<uint32_t> m_image_data2; // definition of  m_image_data2
     m_image_data2.push_back(1);
     m_image_data2.push_back(2);
     m_image_data2.push_back(3);
     m_image_data2.push_back(4);
     m_image_data2.push_back(5);

MPI_Send( &m_image_data2[0], 2, MPI_INT, 1, 0, MPI_COMM_WORLD);
MPI_Send( &m_image_data2[2], 2, MPI_INT, 1, 0, MPI_COMM_WORLD);

MPI_Recv( &m_image_data2[0], 2, MPI_INT, 0, 0, MPI_COMM_WORLD, &status );

B) without []

MPI_Send( &m_image_data2, 2, MPI_INT, 1, 0, MPI_COMM_WORLD);
MPI_Send( &m_image_data2 + 2, 2, MPI_INT, 1, 0, MPI_COMM_WORLD);

MPI_Recv( &m_image_data2, 2, MPI_INT, 0, 0, MPI_COMM_WORLD, &status );

C) using vector methods like at()..

MPI_Send( &m_image_data2.at(0), 2, MPI_INT, 1, 0, MPI_COMM_WORLD);
MPI_Send( &m_image_data2.at(2), 2, MPI_INT, 1, 0, MPI_COMM_WORLD);

MPI_Recv( &m_image_data2.at(0), 2, MPI_INT, 0, 0, MPI_COMM_WORLD, &status );

I am thinking of converting vector to int[] at master node then convert it back to vector in worker node but it will unnecessary overhead.

Does anyone know how to solve it?

Irreligion answered 16/3, 2015 at 2:27 Comment(1)
Please post complete code examples. As you commented below, your error has nothing to do with MPI and everything to do with code you omitted to show , but nobody could have known that!Rerun
F
13

Without a more complete example I don't know what's going on, but it seems that you are mismatching the sends and receives (or you didn't initialize the receive vector correctly).

Something like the following would be enough:

std::vector<uint32_t> m_image_data2;

if (rank==0) {
  m_image_data2.push_back(1);
  m_image_data2.push_back(2);
  m_image_data2.push_back(3);
  m_image_data2.push_back(4);
  m_image_data2.push_back(5);
  // send 5 ints at once
  MPI_Send( &m_image_data2[0], 5, MPI_INT, 1, 0, MPI_COMM_WORLD);
}
else {
  // make space for 5 ints
  m_image_data2.resize(5);
  // receive 5 ints
  MPI_Recv(&m_image_data2[0], 5, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
}
Fontanez answered 16/3, 2015 at 4:20 Comment(5)
I would improve this slightly by using the size() of the vector i.e. MPI_Send(&m_image_data2[0],m_image_data2.size(),...); To cleanly move complex data types you might also investigate the custom data type functionality in MPI. It's tricky, but you can then send structs. Also, transferring data that is of unknown size will require you to be send the size of the vector too, so that the receiver has a chance to allocate. You might check out Boost MPI boost.org/doc/html/mpi.htmlFriedcake
Really!!. Thanks it worked!. I was missing this line: m_image_data2.resize(5);Irreligion
You don't need to use &m_image_data2[0] to get the data from std::vector, there is a .data() function that does exactly that; i.e. &m_image_data2[0] == m_image_data2.data()Ferromagnetic
@Ferromagnetic std::vector.data() is a C++11 feature, it may not be available to the OP, but yes that's a less verbose way.Fontanez
I think both Intel and GCC had it as early as 2010, before it became part of the standard. Fair enough, though.Ferromagnetic
H
4

Consider Boost::MPI, which explicits supports e.g. std::vector through Boost::Serialization.

Of course, Boost::MPI does not support all of MPI 3.0, but rather MPI 1.3 (and maybe a subset of MPI 2.2, but definitely not RMA), so it is not a perfect solution. However, if you use only common features of MPI introduced in MPI-1, then it should be fine.

Herschel answered 16/3, 2015 at 14:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.