Before edit:
I am making a simple code in C++ using MPI to do parallel processing. I do simple tasks like sending and receiving messages from one to another process, exchange messages with MPI_Sendrecv
, say Hello, and print the execution time for each process. It works, but outputs are not sorted in the order I want (Process 0: tasks... Process 1: tasks ...).
I know it is due to no synchronization between processes, and according to my search, I know that MPI_Send
,MPI_Recv
... are implicit blocking functions, but it seems that I did not understand how to use this feature. I also tried the MPI_Barrier()
function as it is often recommended, but without success. I run 8 processes.
Maybe someone can help me? Thanks in advance.
Here is my code:
#include <mpi.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
int rank,nbproc, length;
char name[80];
float time;
double SendData, ReceiveData;
int tag = 1;
int NumTo6 = 500;
int NumTo7 = 300;
int ReceiveFrom6, ReceiveFrom7;
char message[] = "pokay";
char receive[] = "none";
int longueur = strlen(message);
SendData = 1254.3356;
ReceiveData = 0;
MPI_Init(&argc, &argv);
time = MPI_Wtime();
cout << " " << endl;
MPI_Comm_size(MPI_COMM_WORLD, &nbproc);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// MPI_Get_processor_name(name, &length);
cout << "Hello from process\t" << rank << endl;
if (rank == 1)
{
cout << "2*5 = " << 2*5 << endl;
}
if (rank == 2)
{
MPI_Send(&SendData,1,MPI_DOUBLE,3,tag,MPI_COMM_WORLD);
}
if (rank == 3)
{
cout << "Data before the reception:\t" << ReceiveData << endl;
MPI_Recv(&ReceiveData,1,MPI_DOUBLE,2,tag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
cout << "Data received is :\t" << ReceiveData << endl;
tag+=1;
}
if (rank == 4)
{
MPI_Send(&message[1],4,MPI_CHAR,5,tag,MPI_COMM_WORLD);
}
if (rank == 5)
{
cout << "Message before the reception:\t" << receive << endl;
MPI_Recv(&receive,longueur+1,MPI_CHAR,4,tag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
cout << "Message after reception:\t" << receive << endl;
tag+=1;
}
// Exchange between 2 processes:
if(rank == 6)
{
MPI_Sendrecv(&NumTo7,1,MPI_INT,7,tag,&ReceiveFrom7,1,MPI_INT,7,tag+1,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
cout << "Num receive from 7:\t" << ReceiveFrom7 << endl;
}
if(rank == 7)
{
MPI_Sendrecv(&NumTo6,1,MPI_INT,6,tag+1,&ReceiveFrom6,1,MPI_INT,6,tag,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
cout << "Num receive from 6:\t" << ReceiveFrom6 << endl;
tag+=2;
}
time = MPI_Wtime() - time;
cout << "Time spend on process " << rank << " is: " << time << " sec" << endl;
MPI_Finalize();
return 0;
}
And here are my outputs:
Hello from process 6
Hello from process 7
Num receive from 6: 300
Time spend on process 7 is: 6.0746e-05 sec
Hello from process 2
Time spend on process 2 is: 5.0439e-05 sec
Hello from process 3
Data before the reception: 0
Data received is: 1254.34
Time spend on process 3 is: 0.000439355 sec
Hello from process 4
Time spend on process 4 is: 6.2342e-05 sec
Hello from process 5
Message before the reception: none
Message after reception: okay
Time spend on process 5 is: 0.000168845 sec
Hello from process 1
2*5 = 10
Time spend on process 1 is: 0.000132448 sec
Hello from process 0
Time spend on the process 0 is: 3.9762e-05 sec
Num receive from 7: 500
Time spend on process 6 is: 0.00206599 sec
EDIT with @VictorEijkhout 's comment:
I can print out almost all I want and how I want it, except with the MPI_Gather()
of char
... (see after my code).
My new code:
#include <mpi.h>
#include <iostream>
#include <math.h>
#include <string>
#include <cstring>
#include <stdlib.h>
using namespace std;
int main(int argc, char* argv[])
{
int rang,nbproc, taille;
char name[80];
float time;
double SendData, ReceiveData;
double NumTo6 = 500;
double NumTo7 = 300;
double ReceiveFrom6, ReceiveFrom7;
char message[] = "precu";
int longueur = strlen(message);
int len_buffer = 200;
char Buffer_Time[len_buffer];
char Buffer_Hello[len_buffer];
char Buffer_message[len_buffer];
char receive[] = "none";
int mylen = strlen(receive);
char* Gathered_Char_message = new char[len_buffer];
double DataMessage;
double* GatheredDataMessage = new double[20];
double* GateredDataTime = new double[20];
double DataTime;
int elements[] = {};
int source = 0;
int GatheredSources[] = {};
double NoData = NAN;
SendData = 1254.3356;
ReceiveData = 0;
cout << " " << endl;
MPI_Init(&argc, &argv);
time = MPI_Wtime();
MPI_Comm_size(MPI_COMM_WORLD, &nbproc);
MPI_Comm_rank(MPI_COMM_WORLD, &rang);
MPI_Get_processor_name(name, &taille);
sprintf(Buffer_Hello,"Hello from process %d among %d of the machine %s",rang,nbproc,name);
sprintf(Buffer_Time,"Time elapsed in process %d on %d is " ,rang,nbproc);
sprintf(Buffer_message,"Data received from process ");
MPI_Send(Buffer_Time,len_buffer,MPI_CHAR,0,rang+20,MPI_COMM_WORLD);
MPI_Send(Buffer_Hello,len_buffer,MPI_CHAR,0,rang+10,MPI_COMM_WORLD);
MPI_Send(Buffer_message,len_buffer,MPI_CHAR,0,rang+30,MPI_COMM_WORLD);
if (rang == 1)
{
DataMessage = 5*6;
source = 1;
}
if (rang == 2)
{
MPI_Send(&SendData,1,MPI_DOUBLE,3,1,MPI_COMM_WORLD);
DataMessage = NoData;
}
if (rang == 3)
{
MPI_Recv(&ReceiveData,1,MPI_DOUBLE,2,1,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
DataMessage = ReceiveData;
source = 2;
}
if (rang == 4)
{
MPI_Send(&message[1],longueur+1,MPI_CHAR,5,2,MPI_COMM_WORLD);
DataMessage = NoData;
}
if (rang == 5)
{
MPI_Recv(&receive,longueur+1,MPI_CHAR,4,2,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
DataMessage = NoData;
source = 4;
}
// Exchange between 2 processes:
if(rang == 6)
{
MPI_Sendrecv(&NumTo7,1,MPI_DOUBLE,7,3,&ReceiveFrom7,1,MPI_DOUBLE,7,4,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
DataMessage = ReceiveFrom7;
elements[rang] = 1;
source = 7;
}
if(rang == 7)
{
MPI_Sendrecv(&NumTo6,1,MPI_DOUBLE,6,4,&ReceiveFrom6,1,MPI_DOUBLE,6,3,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
DataMessage = ReceiveFrom6;
elements[rang] = 1;
source = 6;
}
DataTime = MPI_Wtime() - time;
MPI_Gather(&DataTime,1,MPI_DOUBLE,GateredDataTime,1,MPI_DOUBLE,0,MPI_COMM_WORLD);
MPI_Gather(&DataMessage,1,MPI_DOUBLE,GatheredDataMessage,1,MPI_DOUBLE,0,MPI_COMM_WORLD);
MPI_Gather(&source,1,MPI_INT,GatheredSources,1,MPI_INT,0,MPI_COMM_WORLD);
// int* recvcounts = new int[nbproc*sizeof(int)];
// MPI_Gather(&mylen,1,MPI_INT,recvcounts,1,MPI_INT,0,MPI_COMM_WORLD);
// int totlen = 0;
// int* displs = new int[nbproc*sizeof(int)];
// //char* totalstring = new char[totlen*sizeof(char)];
// if(rang == 0)
// {
// displs[0] = 0;
// totlen += recvcounts[0] + 1;
// for(int i=1; i< nbproc; i++)
// {
// totlen += recvcounts[i]+1;
// displs[i] = displs[i-1] + recvcounts[i-1] + 1;
// }
// }
// char* totalstring = new char[totlen*sizeof(char)];
// if(rang == 0)
// {
// for (int i=0; i<totlen-1; i++)
// totalstring[i] = ' ';
// totalstring[totlen-1] = '\0';
// }
// MPI_Gatherv(&receive, mylen, MPI_CHAR,
// totalstring, recvcounts, displs, MPI_CHAR,
// 0, MPI_COMM_WORLD);
if(rang == 0)
{
cout << Buffer_Hello << endl;
for(int i = 1; i < nbproc; i++)
{
MPI_Recv(Buffer_Hello,len_buffer,MPI_CHAR,i,i+10,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
MPI_Recv(Buffer_message,len_buffer,MPI_CHAR,i,i+30,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
cout << Buffer_Hello << endl;
if(isnan(GatheredDataMessage[i]))
{
}
else
{
cout << Buffer_message << GatheredSources[i] << ": "<<
GatheredDataMessage[i] << endl;
}
// cout << totalstring[i] << endl;
MPI_Recv(Buffer_Time,len_buffer,MPI_CHAR,i,i+20,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
cout << Buffer_Time << GateredDataTime[i] << " sec" << endl;
cout << " " << endl;
}
}
delete[] GatheredDataMessage;
delete[] GateredDataTime;
MPI_Finalize();
return 0;
}
And outputs:
Hello from process 0 among 8 of the machine jeremy-SATELLITE-P50-C
Hello from process 1 among 8 of the machine jeremy-SATELLITE-P50-C
Data received from process 1: 30
Time elapsed in process 1 on 8 is 0.000248922 sec
Hello from process 2 among 8 of the machine jeremy-SATELLITE-P50-C
Time elapsed in process 2 on 8 is 0.00013139 sec
Hello from process 3 among 8 of the machine jeremy-SATELLITE-P50-C
Data received from process 2: 1254.34
Time elapsed in process 3 on 8 is 0.000183373 sec
Hello from process 4 among 8 of the machine jeremy-SATELLITE-P50-C
Time elapsed in process 4 on 8 is 0.000121771 sec
Hello from process 5 among 8 of the machine jeremy-SATELLITE-P50-C
Time elapsed in process 5 on 8 is 0.00027475 sec
Hello from process 6 among 8 of the machine jeremy-SATELLITE-P50-C
Data received from process 7: 500
Time elapsed in process 6 on 8 is 0.00330783 sec
Hello from process 7 among 8 of the machine jeremy-SATELLITE-P50-C
Data received from process 6: 300
Time elapsed in process 7 on 8 is 0.000215519 sec
So I am close to what I want, it misses the gather and print of char that process 4 and 5 exchange, and print out the initial char "nothing" for all others processes. I tried several things like this for instance: https://stackoverflow.com/a/31932283/14901229, you can see that in my code with comments, but then nothing is printed ...
Maybe you could help me with this last thing? Also, if you see ways of optimization for my code (and I think there are...), please don't hesitate to tell me them!
Thanks in advance!