2

I want to send a string variable via MPI, but I don't know how should I do it! my code is here:

static string  fourTupX="Hello";

now I want to send it via MPI:

int l=std::strlen(fourTupX.c_str());
l++;
MPI::COMM_WORLD.Send (&l,1,MPI::INT,1,7);
MPI::COMM_WORLD.Send ( &fourTupX, 1, MPI::CHAR, 1, 1 );

and receive it in another side:

int l;
 source=0;
 MPI::COMM_WORLD.Recv (&l,1,MPI::INT , source, 7, status1 );
 cout<<l;
 char* myfourTupX=new char[l];
 MPI::COMM_WORLD.Recv (myfourTupX,l,MPI_CHAR , source, 1, status1 );

but after receiving there isn't any thing in fourTupx!!! what is the problem?

  • possible duplicate of [how to send and recieve string using MPI](http://stackoverflow.com/questions/20620421/how-to-send-and-recieve-string-using-mpi) – fachexot Jul 03 '14 at 13:46

4 Answers4

10

You have to send the content of the string buffer obtained from c_str(). You don't have to send the string length first as the receiver could simply probe for a message first and then allocate an appropriately-sized buffer:

// Sender

string bla = "blabla";
MPI::COMM_WORLD.Send(bla.c_str(), bla.length(), MPI::CHAR, dest, 1);

// Receiver

MPI::Status status;
MPI::COMM_WORLD.Probe(source, 1, status);
int l = status.Get_count(MPI::CHAR);
char *buf = new char[l];
MPI::COMM_WORLD.Recv(buf, l, MPI::CHAR, source, 1, status);
string bla1(buf, l);
delete [] buf;

Here the receiver uses Probe to probe for a matching message and examines the status object to find out how many characters are in the message. Then it allocates a buffer of the same size, receives the message and constructs an std::string object out of it.

Hristo Iliev
  • 72,659
  • 12
  • 135
  • 186
  • thank you ,I want to send a link-list with send Command in MPICH2,is there any way to do this? – marziye esmslampanah Jan 27 '14 at 13:41
  • MPI cannot do that out of the box. You should take a look at [Boost.MPI](http://www.boost.org/doc/libs/1_55_0/doc/html/mpi.html) or a similar wrapper library that can automatically (de-)serialise C++ container classes. Besides the MPI C++ bindings were deprecated in MPI-2.2 and completely removed from the newest MPI-3.0 standard. – Hristo Iliev Jan 27 '14 at 14:16
  • std::basic_string::c_str() and std::basic_string::data() return const char* what causes an invalid conversion. Is that secure anyway? – fachexot Jul 03 '14 at 23:56
  • @fachexot, according to the MPI standard, `MPI_Send` does not modify the content of the buffer. In MPI-3.0 the argument has been given the `const` treatment (and also no C++ bindings exists in MPI-3.0) – Hristo Iliev Jul 04 '14 at 06:56
  • @HristoIliev MPI_Send(bla.c_str(), bla.length(), MPI_CHAR, source, tag, MPI_COMM_WORLD); gives compiler error telling the first argument type of const char* is incompatable with parameter void*. How can I solve that? – Nurlan Mar 29 '15 at 14:26
2

As I understand, you're sending 1 character, which is 1 byte, from the beginning of the string object. You need to send the whole thing.

When sending objects, you need to be careful about pointers inside the object, you might be sending the pointer address, but not the content itself. This might be the case with string object if it's storing the actual char array in the heap.

In this case, I'd rather send the c_str() than the object itself, and the size would be the length of the c_str() plus 1 to include the null character at the end. Then you can reconstruct the string object from the character array after receiving it.

EDIT Modify your string send:

MPI::COMM_WORLD.Send ( fourTupX.c_str(), l, MPI::CHAR, 1, 1 ); //it's l, not 1

Then it should work.

adrin
  • 4,511
  • 3
  • 34
  • 50
2

I know this is a pretty old question, but I'd like to share my experience in case anyone else bumps into this.

It seems that Hristo's answer is outdated. To make it work on newer releases of MPI, I suggest you use

// Sender
std::string s = "somestring";
MPI_Send(&s[0],s.size()+1,MPI_CHAR,<destination>,<tag>,MPI_COMM_WORLD);

// Receiver
MPI_Status status;
MPI_Probe(<sender>,<tag>,MPI_COMM_WORLD,&status);
int count;
MPI_Get_count(&status,MPI_CHAR,&count);
char buf [count];
MPI_Recv(&buf,count,MPI_CHAR,<sender>,<tag>,MPI_COMM_WORLD,&status);
std::string s = buf; 
sondrelv
  • 111
  • 2
  • 6
0

The answer by @sondrelv is correct, but it throws a warning of "ISO C++ forbids variable-size array". This code fixes the warning with newing and deleteing the buffer.

// Sender
std::string s = "somestring";
MPI_Send(s.c_str(), s.size()+1, MPI_CHAR, <destination>, <tag>, MPI_COMM_WORLD);

// Receiver
MPI_Status status;
MPI_Probe(source, tag, MPI_COMM_WORLD, &status);
int count;
MPI_Get_count(&status, MPI_CHAR, &count);
char *buf = new char[count];
MPI_Recv(buf, count, MPI_CHAR, source, tag, MPI_COMM_WORLD, &status);
str = buf;
delete[] buf;
Aaron Caba
  • 73
  • 8