Search code examples
c++parallel-processingopenmpi

openmpi for c++: rank changes inside function apparently without reason.


following code produces the output pasted below

#include "mpi.h"
#include <stdio.h>

#define NUM 5
#define TRANSACTIONS 1

main(int argc, char *argv[])  {
int numtasks, rank, dest, source, rc, count, tag=1;  
char outmsg[] = "Hello World, today is a not so fantastic day for programmers";
char inmsg[20] = "-------------------";
MPI_Status Stat[2];

MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

char* baseaddr;

if (rank == 0) {
  dest = 1;
  source = 1;
  printf("a) I am: %d\n", rank);
  rc = MPI_Send(outmsg, NUM, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
  printf("OUTBUFFER OF WORKER %d: %s\n", rank, outmsg);
  printf("b) I am: %d\n", rank);
  baseaddr=outmsg+5;
  //rc = MPI_Send(outmsg+5, NUM, MPI_CHAR, dest, 10, MPI_COMM_WORLD);
  rc = MPI_Send(baseaddr, NUM, MPI_CHAR, dest, 10, MPI_COMM_WORLD);
  printf("OUTBUFFER OF WORKER %d: %s\n", rank, outmsg);
  //rc = MPI_Recv(inmsg, NUM, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat);
  printf("c) I am: %d\n", rank);
  } 

else if (rank == 1) {
  dest = 0;
  source = 0;
  printf("d) I am: %d\n", rank); 
  baseaddr = inmsg+5;
  //rc = MPI_Recv(inmsg+5, NUM, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat);
  rc = MPI_Recv(inmsg, NUM, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat[0]);
  printf("e) I am: %d\n", rank);
  printf("INBUFFER OF WORKER %d: %s\n", rank, inmsg);
  rc = MPI_Recv(baseaddr, NUM, MPI_CHAR, source, 10, MPI_COMM_WORLD, &Stat[1]);
  //rc = MPI_Send(outmsg, NUM, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
  printf("f) I am: %d\n", rank);
  printf("INBUFFER OF WORKER %d: %s\n", rank, inmsg);
  }


for(int i=0; i<=TRANSACTIONS; ++i){
    rc = MPI_Get_count(&Stat[i], MPI_CHAR, &count);
    printf("Task %d: Received %d char(s) from task %d with tag %d \n",
           rank, count, Stat[i].MPI_SOURCE, Stat[i].MPI_TAG);
}

MPI_Finalize();
}

Here the output:

d) I am: 1
e) I am: 1
INBUFFER OF WORKER 1: Hello--------------
f) I am: 1
a) I am: 0
OUTBUFFER OF WORKER 0: Hello World, today is a not so fantastic day for programmers
b) I am: 0
OUTBUFFER OF WORKER 0: Hello World, today is a not so fantastic day for programmers
c) I am: 0
Task 0: Received 0 char(s) from task 4227856 with tag 0 
Task 0: Received 6365232 char(s) from task 0 with tag 4227856 
INBUFFER OF WORKER 1: Hello Worl---------
Task 1: Received 5 char(s) from task 0 with tag 1 
Task 1: Received 5 char(s) from task 0 with tag 10 

THIS OUTPUT SEEMS TO BE CORRECT. Now following code should produce the same output (to my limited understanding), but this will not be the case as shown in the end:

#include "mpi.h"
#include <stdio.h>

#define NUM 10
#define TRANSACTIONS 1

main(int argc, char *argv[])  {
int numtasks, rank, dest, source, rc, count, tag=1;  
char outmsg[] = "Hello world, today is a beautiful day.\n";
char inmsg[30] = "-----------------------------";
MPI_Request req;
MPI_Status Stat[TRANSACTIONS];

MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

char* baseaddr;

if (rank == 0) {
  dest = 1;
  source = 1;
  rc = MPI_Send(outmsg, NUM, MPI_CHAR, dest, 99, MPI_COMM_WORLD);
  printf("OUTBUFFER OF WORKER %d: %s\n", rank, outmsg);
  printf("a) I am: %d\n", rank);
  baseaddr = outmsg + NUM; 
  //rc = MPI_Send(baseaddr, NUM, MPI_CHAR, dest, 999, MPI_COMM_WORLD);
  printf("OUTBUFFER OF WORKER %d: %s\n", rank, outmsg);
  printf("b) I am: %d\n", rank);
  //rc = MPI_Irecv(&inmsg, NUM, MPI_CHAR, source, 2, MPI_COMM_WORLD, &req);
  } 

else if (rank == 1) {
  dest = 0;
  source = 0;
  //rc = MPI_Recv(inmsg, NUM, MPI_CHAR, source, 99, MPI_COMM_WORLD, &Stat[0]);
  printf("INBUFFER OF WORKER %d: %s\n", rank, inmsg);
  printf("c) I am: %d\n", rank);
  baseaddr = inmsg + NUM; 
  rc = MPI_Recv(baseaddr, NUM, MPI_CHAR, source, 99, MPI_COMM_WORLD, &Stat[1]);
  printf("INBUFFER OF WORKER %d: %s\n", rank, inmsg);
  printf("d) I am: %d\n", rank);
  //rc = MPI_Isend(&outmsg, NUM, MPI_CHAR, dest, 2, MPI_COMM_WORLD, &req);
  }

for(int i=0; i<=TRANSACTIONS; ++i){
    rc = MPI_Get_count(&Stat[i], MPI_CHAR, &count);
    printf("Task %d: Received %d char(s) from task %d with tag %d \n",
           rank, count, Stat[i].MPI_SOURCE, Stat[i].MPI_TAG);
}

MPI_Finalize();
}

And here the output that is not equivalent to the output above

OUTBUFFER OF WORKER 0: Hello world, today is a beautiful day.

a) I am: 0
OUTBUFFER OF WORKER 0: Hello world, today is a beautiful day.

b) I am: 0
Task 0: Received 0 char(s) from task 6362440 with tag 0 
Task 0: Received 2 char(s) from task 0 with tag 1969314218 
INBUFFER OF WORKER 1: Hello worl-------------------
c) I am: 1
INBUFFER OF WORKER 0: Hello world, today i---------
d) I am: 0
Task 0: Received 10 char(s) from task 0 with tag 99 
Task 0: Received 10 char(s) from task 0 with tag 999 

Observe that between c) and d) rank seems to change from 1 to zero

c) I am: 1

d) I am: 0

Also note the INBUFFER OF WORKER 0 output (instead of WORKER 1).

What am I missing ? THX


Solution

  • What you are missing is that you declare Stat as an array of one element:

    #define TRANSACTIONS 1
    MPI_Status Stat[TRANSACTIONS];
    

    but then you refer the (out-of-bound) second element of the array Stat[1]:

    rc = MPI_Recv(baseaddr, NUM, MPI_CHAR, source, 99, MPI_COMM_WORLD, &Stat[1]);
    //                                                                  ^^^^^^^
    

    This results in some stack memory being overwritten, including the one holding rank.