MPI to generate first 20 numbers
An answer to this question on Stack Overflow.
Question
Here is code that I was trying to generate the first 20 numbers starting from 0 in an attempt to learn MPI.
My code is given below :
#include <mpi.h>
#include <stdio.h>
int i = 0;
void test(int edge_count){
while(i < edge_count){
printf("Edge count %d\n",i);
i++;
}
}
int main(int argc, char** argv) {
int edge_count = 20;
// int *p = &i;
// Initialize the MPI environment. The two arguments to MPI Init are not
// currently used by MPI implementations, but are there in case future
// implementations might need the arguments.
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
// Get the name of the processor
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
// Print off a hello world message
printf("Hello world from processor %s, rank %d out of %d processors\n",
processor_name, world_rank, world_size);
test(edge_count);
printf("The value of i is %d \n",i);
// Finalize the MPI environment. No more MPI calls can be made after this
MPI_Finalize();
}
My output is :
Hello world from processor ENG401651, rank 0 out of 2 processors
Edge count 0
Edge count 1
Edge count 2
Edge count 3
Edge count 4
Edge count 5
Edge count 6
Edge count 7
Edge count 8
Edge count 9
Edge count 10
Edge count 11
Edge count 12
Edge count 13
Edge count 14
Edge count 15
Edge count 16
Edge count 17
Edge count 18
Edge count 19
The value of i is 20
Hello world from processor ENG401651, rank 1 out of 2 processors
Edge count 0
Edge count 1
Edge count 2
Edge count 3
Edge count 4
Edge count 5
Edge count 6
Edge count 7
Edge count 8
Edge count 9
Edge count 10
Edge count 11
Edge count 12
Edge count 13
Edge count 14
Edge count 15
Edge count 16
Edge count 17
Edge count 18
Edge count 19
The value of i is 20
The code that I used to run it is:
mpirun -np 2 execFile
I was expecting that both the processor would communicate and generate a number from 0 to 19 only once but it seems like each of the processor are generating their own set of numbers independently.
What am I doing wrong? I am new to MPI and couldnot figure out what is the reason behind this.
Answer
Computers only do what you tell them to. This is true not just of MPI but of any kind of programming.
Where in your script did you explicitly tell the processors to divide the work between them? The thing is, you didn't. And it won't happen by automagically.
The following modified version of your code shows how you can use world_size and world_rank to have each process independently calculate what share of the work it should perform.
To better demonstrate the gains of parallelism, I use thread sleeping to simulate the time that would otherwise be taken by work in an actual implementation.
#include <mpi.h>
#include <stdio.h>
#include <chrono>
#include <thread>
void test(int start, int end){
for(int i=start;i<end;i++){
printf("Edge count %d\n",i);
//Simulates complicated, time-consuming work
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
int main(int argc, char** argv) {
int edge_count = 20;
// int *p = &i;
// Initialize the MPI environment. The two arguments to MPI Init are not
// currently used by MPI implementations, but are there in case future
// implementations might need the arguments.
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
// Get the name of the processor
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
// Print off a hello world message
printf("Hello world from processor %s, rank %d out of %d processors\n",
processor_name, world_rank, world_size);
const int interval = edge_count/world_size;
const int iter_start = world_rank*interval;
const int iter_end = (world_rank+1)*interval;
test(iter_start, iter_end);
// Finalize the MPI environment. No more MPI calls can be made after this
MPI_Finalize();
}