MPI_Recv blocks

Hi,

If i am using MPI_Send, I am not getting any problem but when I am using both MPI_Send and MPI_Recv my program blocks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <fstream>
#include <cmath>
#include <mpi.h>
#include <ctime>
#include <vector>

//using namespace std;

// Sorts the input row into chunks to be scattered two all the processors.
//void sortByProcess(std::vector<double> list1, double* list2, int count);

// Swaps two rows.
//void swap(double** list, int count, int row1, int row2);


//int N=32;
int rank, size;
int tag = 99;
int main(int argc, char * argv[])
{
  double sTime, eTime, rTime;
  std::ifstream inFile;
  int num_rows = 3200;
  int num_cols = 3200;
  int cur_control = 0;
  double * send_buffer = NULL;
  double * recv_buffer = NULL;
  double ** data = NULL;
  double determinant;
  MPI_Status stat;
  std::vector<double> file_buffer;
  

  // Just get the initialization of the program going.
  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);

  // If the input file is not given, print message and exit.
  if(argc < 2)
  {
    std::cout << "No input file given." << std::endl;
    MPI_Finalize();
    return 0;
  }
  // If the root node (0), then open the input file and read in the
  // number of rows.
  if(!rank)
  {
    inFile.open(argv[1]);
    inFile >> num_rows;
    file_buffer.resize(num_rows);
  }

  send_buffer = new double[num_rows];
  // Broadcasts p2p the number of rows to each processor.
  //MPI_Bcast (&num_rows, 1, MPI_INT, 0, MPI_COMM_WORLD);
  
  for(int i=1; i<size; ++i) {
     
     MPI_Send(&num_rows, 1, MPI_INT, i, tag, MPI_COMM_WORLD);
  }
  
  for(int i=1; i<size; ++i) {
     
     MPI_Recv(&num_rows, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &stat);
  }
  num_cols = num_rows / size;

  delete [] send_buffer;
  MPI_Finalize();
  return 0;
}


Some body please guide me.

Zulfi.
Only process 0 knows the correct value of num_rows (because it read it from file) so why do you have EVERY process sending it out in lines 60-63 and how do processes other than the root set up the buffer on line 56?

What is the purpose of index i in the loop from 65 to 68? You are waiting for parcels that were never sent. In that loop you are saying that ALL processes received size-1 messages ... from process 0. Well, process 0 sent just one message to each other process (and didn't post one to itself).

Why did you comment out your MPI_Bcast line? That would have been a much more logical way of doing it.
Last edited on
Here's a minimalist version with MPI_Send and MPI_Recv (which isn't really the best solution here). The input file holds 666 as first line.

Note that you have little control over the order of output if all processes do some. Hence the bizarre apparent order of output.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <fstream>
#include "mpi.h"

int rank, size;
int tag = 99;

int main( int argc, char * argv[] )
{
   int num_rows = -1;        // if you MUST initialise this, do so to an error marker
   MPI_Status stat;

   // Initialise the MPI system
   MPI_Init( &argc, &argv );
   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
   MPI_Comm_size( MPI_COMM_WORLD, &size );

   if ( !rank )                         // root process reads num_rows and sends it ...
   {
      std::ifstream inFile( "test.in" );
      inFile >> num_rows;
      std::cout << "Process 0 read " << num_rows << " ... \n";
      for ( int i = 1; i < size; i++ )
      {
         std::cout << "Process 0 sends " << num_rows << " to process " << i << "... \n";
         MPI_Send( &num_rows, 1, MPI_INT, i, tag, MPI_COMM_WORLD );
      }
   }
   else                                 // other processes receive it
   {
      MPI_Recv( &num_rows, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &stat);
      std::cout << "... Process " << rank << " receives " << num_rows << '\n';
   }

   MPI_Finalize();
}


C:\user>"C:\Program Files\Microsoft MPI\bin"\mpiexec -n 4 test.exe
... Process 1 receives 666
... Process 2 receives 666
... Process 3 receives 666
Process 0 read 666 ... 
Process 0 sends 666 to process 1... 
Process 0 sends 666 to process 2... 
Process 0 sends 666 to process 3... 




However, I think MPI_Bcast is much better here ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <fstream>
#include "mpi.h"

int rank, size;
int tag = 99;

int main( int argc, char * argv[] )
{
   int num_rows = -1;
   MPI_Status stat;

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

   if ( !rank )                                             // root process reads num_rows ...
   {
      std::ifstream inFile( "test.in" );
      inFile >> num_rows;
      std::cout << "Process 0 reads " << num_rows << " ... \n";
   }

   MPI_Bcast( &num_rows, 1, MPI_INT, 0, MPI_COMM_WORLD );   // root process broadcasts to all
   std::cout << "Process " << rank << " holds " << num_rows << '\n';

   MPI_Finalize();
}


c:\user>"C:\Program Files\Microsoft MPI\bin"\mpiexec -n 4 test1.exe 
Process 1 holds 666
Process 2 holds 666
Process 0 reads 666 ... 
Process 0 holds 666
Process 3 holds 666


Last edited on
Hi my Friend lastchance,

Thanks for your message.

<Only process 0 knows the correct value of num_rows (because it read it from file) so why do you have EVERY process sending it out in lines 60-63>
Yes you are right only process 0 knows the value of num_rows because it is retrieving it from the file.
Note in my code, I am using num_rows as a local variable assigned a value of 3200. So if i don't read it from file, Will rank ==0 know that the value of num_rows is 3200?

And you are right that every process is sending it out because i did not put the code
1
2
3
4
5

if (! rank){
:
:
}

<What is the purpose of index i in the loop from 65 to 68?>

index 'i' is a loop counter variable. I thought this loop would be executed by all threads in the communicator and they would receive the data sent by all processes (which I don't mean, I actually wanted process '0' to send.)

<You are waiting for parcels that were never sent.>
Why my code line# 62 is not sending? and If this line is sending then each process should send "num_rows" to each other process in the communicator. This means that each process should receive data. And you are also saying this:
<Well, process 0 sent just one message to each other process (and didn't post one to itself).>
So if process 0 send the message why that message is not received? Why I am going in an infinite loop?
But this code:
1
2
3
4
for(int i=1; i<size; ++i) {
     
     MPI_Send(&num_rows, 1, MPI_INT, i, tag, MPI_COMM_WORLD);
  }

should be used by other processes also to send the data to each other except process 0. Where is this data going?
<Why did you comment out your MPI_Bcast line? That would have been a much more logical way of doing it>
I want to do point to point communication so that I can have better idea of what's going on. I modified my code to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <fstream>
#include <cmath>
#include <mpi.h>
#include <ctime>
#include <vector>

//using namespace std;

// Sorts the input row into chunks to be scattered two all the processors.
//void sortByProcess(std::vector<double> list1, double* list2, int count);

// Swaps two rows.
//void swap(double** list, int count, int row1, int row2);


//int N=32;
int rank, size;
int tag = 99;
int main(int argc, char * argv[])
{
  double sTime, eTime, rTime;
  std::ifstream inFile;
  int num_rows = 3200;
  int num_cols = 3200;
  int cur_control = 0;
  double * send_buffer = NULL;
  double * recv_buffer = NULL;
  double ** data = NULL;
  double determinant;
  MPI_Status stat;
  std::vector<double> file_buffer;
  

  // Just get the initialization of the program going.
  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);

  // If the input file is not given, print message and exit.
 /* if(argc < 2)
  {
    std::cout << "No input file given." << std::endl;
    MPI_Finalize();
    return 0;
  }*
  // If the root node (0), then open the input file and read in the
  // number of rows.
 /* if(!rank)
  {
    inFile.open(argv[1]);
    inFile >> num_rows;
    file_buffer.resize(num_rows);

   //I hardcoded the value of num_rows
  }*/

  send_buffer = new double[num_rows];
  // Broadcasts p2p the number of rows to each processor.
  //MPI_Bcast (&num_rows, 1, MPI_INT, 0, MPI_COMM_WORLD);
  
 if(! rank) { 
//Now ony thread 0 should send
 for(int i=1; i<size; ++i) {
     
     MPI_Send(&num_rows, 1, MPI_INT, i, tag, MPI_COMM_WORLD);
  }
  }
  for(int i=1; i<size; ++i) {
     
     MPI_Recv(&num_rows, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &stat);
    //Why MPI_Recv(...) does not return  
}
  num_cols = num_rows / size;

  delete [] send_buffer;
  MPI_Finalize();
  return 0;
}

but the above code goes into sleeping in the loop for MPI_Recv(..). I don't know why?

Any way I would now work on the solution provided by yourself.

God bless you.

Zulfi.








Last edited on
Hi lastchance,
Thanks for helping me.

Your code is working. Now I have to add more to it using point-to-point communication.

Zulfi.
Topic archived. No new replies allowed.