7

I am trying to send and recieve string using MPI but results are hopless.

Send function:

MPI_Send(&result, result.size(), MPI_CHAR, 0, 0, MPI_COMM_WORLD);

And the recv function:

    MPI_Recv(&result,      /* message buffer */
        128,                 /* one data item */
        MPI_CHAR,        /* of type char real */
        MPI_ANY_SOURCE,    /* receive from any sender */
        MPI_ANY_TAG,       /* any type of message */
        MPI_COMM_WORLD,    /* default communicator */
        &status);          /* info about the received message */

Where result is a string.

I didn't get any error but program doesn't want to finish.

Donald_W
  • 1,773
  • 21
  • 35
John
  • 363
  • 2
  • 6
  • 19

2 Answers2

18

The address of a std::string is not the same as address of the underlying C string, so sending should be fixed like this:

MPI_Send(result.c_str(), result.size(), MPI_CHAR, 0, 0, MPI_COMM_WORLD);

Receiving cannot be done as you tried to do it. You need a buffer (an array of char), which you will pass to MPI_Recv and use it later to create a std::string instance. To get a length of the string received use MPI_Get_count - this you should pass along the pointer to buffer to std::string constructor.

In order to avoid preallocating the buffer and allow it to receive a string of any size you should call MPI_Probe and MPI_Get_count to get the length first. Knowing the length you can allocate the buffer with the exact size which is necessary, and only then call MPI_Recv.

If this sounds a bit complicated then you can consider using BOOST MPI wrappers.

piokuc
  • 25,594
  • 11
  • 72
  • 102
  • 1
    +1, beat me to it. Regarding the receive, if `result` is known to have a large enough buffer (previously created), he can use `&result[0]` to get a non-const pointer to the internal buffer. – Eran Dec 16 '13 at 20:53
  • If `result` is a `std::string` then `&result[0]` should be the same as `result.c_str()`, except it is non-const. I would personally use the former, with a `const_cast`. I see what you mean here, passing a preallocated `std::string` can work with `MPI_Recv`, but it will fail if the string contains `0`, for example, so care should be taken... – piokuc Dec 16 '13 at 21:03
  • When I change argument to array of char, everything works fine. Thx guys. :) – John Dec 16 '13 at 22:42
  • 2
    Should not you use MPI_Send(result.c_str(), result.size() + 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD); in order to incorporate string termination sign '\0' ? – Darqer Aug 23 '14 at 22:23
  • @piokuc MPI_Send(result.c_str(), result.size(), MPI_CHAR, 0, 0, MPI_COMM_WORLD); gives compiler error telling the first argument with type of const char* is incompatable with parameter void*. How can I solve that? – Nurlan Mar 29 '15 at 14:30
  • @Nurlan I know this is very late, but your problem is that you declared `result` as `const`. However, by definition of a Send/Recv pair, you need to be able to change `result` on the receiving end. So it cannot be a `const std::string`, but rather a non-const `std::string`. – NoseKnowsAll Oct 19 '15 at 21:02
-1

I was having similar problem where I had to pass a string between two processes in MPI C. My solution, aligned to your problem, is the following:

MPI_Send(&result, strlen(result)+1, MPI_CHAR, 1, 0, MPI_COMM_WORLD); // Destination: Process 1

On the other side, process 0 will have the following MPI_Recv function:

MPI_Recv(&result, 100, MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); // Source: Process 0 and considering 100 as the maximum string length

<string.h> has to be added in the header.