Reputation: 901
Amaey helped me fix the problem.
I was trying to learn about the MPI_Comm_spawn function to spawn processes, because I'm working on migrating a project from PVM to MPI. I found a good example program here. So I decided to change it a bit to make the parent process send a message to the two child processes, and then make the child processes output the message. The thing is that the child process with rank 0 doesn't receive the message properly, it just receives a part of it, while the child process with rank 1 receives the message and outputs it normally. Can someone please explain why this is happening, what I'm doing wrong or how I can fix this. Thanks a lot to those who can help!
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#define NUM_SPAWNS 2
// Based on the example from: http://mpi.deino.net/mpi_functions/MPI_Comm_spawn.html
int main( int argc, char *argv[] )
{
int my_rank;
int size;
int np = NUM_SPAWNS;
int errcodes[NUM_SPAWNS];
MPI_Comm parentcomm, intercomm;
char greeting[100];
char greeting2[100];
char greeting3[100];
MPI_Init( &argc, &argv );
MPI_Status stat;
MPI_Comm_get_parent( &parentcomm );
if (parentcomm == MPI_COMM_NULL)
{
/* Create 2 more processes - this example must be called spawn_example.exe for this to work. */
MPI_Comm_spawn( "spawn_example", MPI_ARGV_NULL, np, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &intercomm, errcodes );
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Called this Jreeting because process 0 in the new MPI_COMM_WORLD was only receiving a part of this string.
sprintf(greeting2, "Jreeting from master1 %d of %d\n", my_rank, size);
sprintf(greeting3, "Greeting from master2 %d of %d\n", my_rank, size);
for(int i = 0; i<np;i++)
{
if(i == 0)
{
MPI_Send(greeting2, strlen(greeting)+1, MPI_BYTE, i,1,intercomm);
}
if(i == 1)
{
MPI_Send(greeting3, strlen(greeting)+1, MPI_BYTE, i,1,intercomm);
}
MPI_Recv(greeting, sizeof(greeting), MPI_BYTE, i, 1, intercomm, &stat);
fputs (greeting, stdout);
}
}
else
{
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if(my_rank == 0)
{
MPI_Recv(greeting2, sizeof(greeting2), MPI_BYTE, 0, 1, parentcomm, &stat);
std::cout << greeting2 << "\n";
}
if(my_rank == 1)
{
MPI_Recv(greeting3, sizeof(greeting3), MPI_BYTE, 0, 1, parentcomm, &stat);
std::cout << greeting3 << "\n";
}
sprintf(greeting, "Hello world: processor %d of %d\n", my_rank, size);
MPI_Send(greeting, strlen(greeting)+1, MPI_BYTE, 0,1,parentcomm);
}
fflush(stdout);
MPI_Finalize();
return 0;
}
When I compile I have warnings...:
hrognkelsi:MPI_TUTORIAL gumundureinarsson$ mpic++ spawn_example.cc -o spawn_example
spawn_example.cc: In function ‘int main(int, char**)’:
spawn_example.cc:24: warning: deprecated conversion from string constant to ‘char*’
When I run:
hrognkelsi:MPI_TUTORIAL gumundureinarsson$ mpirun spawn_example
Jre
Hello world: processor 0 of 2
Greeting from master2 0 of 1
Hello world: processor 1 of 2
As you can see, the child process only outputs Jre instead of Jreeting from master1 0 of 1 as it is supposed to. What's going on? Why does it work for the other child process?
Upvotes: 0
Views: 1223
Reputation: 36
Look at the line:
MPI_Send(greeting2, strlen(greeting)+1, MPI_BYTE, i,1,intercomm);
So unless i've overlooked something isn't 'strlen(greeting)' simply 0. You are definitely putting more things in the Send buffer than 1 element. I think you want to put 'strlen(greeting2)' in there.
What I think is happening is that the parent process sends a truncated string and gets a reply from process 0, which populates 'greeting'. Thus on the second MPI_Send 'sizeof(greeting)' is non-zero hence you're able to send the entire message through.
Upvotes: 2