From Education
#include <mpi.h>
#include <stdio.h>
void Usage(char *msg, char *prog);
void Send(int rank, int size, int msgLen, int mode, char modeChar);
void Recv(int rank, int size, int msgLen);
void checkParameters(int *msgLen, int *order, int *mode,
int argc, char **argv, int size, char orderChar, char modeChar);
#define MAX_ARRAY_LENGTH 800000
#define modeB 0
#define modeR 1
#define modeS 2
#define modeV 3
#define orderR 0
#define orderS 1
#define orderA 2
#define tag 42
/*
* compile -> mpicc -o deadlock deadlock.c
* run -> mpirun -np 2 deadlock 0 10 S
*
*/
int main(int argc, char **argv) {
int mode = -1, order=2;
int size, rank, msgLen;
char orderChar, modeChar;
int *buffer;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
orderChar = *(argv[1]);
modeChar = *(argv[3]);
checkParameters(&msgLen, &order, &mode, argc, argv, size, orderChar, modeChar);
if (mode == modeB) {
buffer = (int *)malloc(MPI_BSEND_OVERHEAD + msgLen*sizeof(int));
MPI_Buffer_attach(buffer, MPI_BSEND_OVERHEAD + msgLen);
}
if ((order != orderR) && (rank || (order == orderS))) {
Send(rank,size,msgLen, mode, modeChar);
Recv(rank,size,msgLen);
} else {
Recv(rank,size,msgLen);
Send(rank,size,msgLen, mode, modeChar);
}
MPI_Finalize();
return(0);
}
void Recv(int rank, int size, int msgLen) {
MPI_Status status;
int retVal, buffer_in[MAX_ARRAY_LENGTH];
fprintf(stderr,"\n%d/%d: receiving %d\n", rank, size, msgLen);
retVal = MPI_Recv(buffer_in, MAX_ARRAY_LENGTH, MPI_INT,
1-rank, tag, MPI_COMM_WORLD, &status);
fprintf(stderr, "%d/%d: received %d\n", rank, size, retVal);
}
void Send(int rank, int size, int msgLen, int mode, char modeChar) {
MPI_Status status;
int retVal, buffer_out[MAX_ARRAY_LENGTH];
fprintf(stderr,"\n%d/%d: sending %d in mode %c\n",
rank, size, msgLen, modeChar);
switch (mode) {
case modeB: retVal = MPI_Bsend(buffer_out, msgLen, MPI_INT,
1-rank, tag, MPI_COMM_WORLD);
break;
case modeR: retVal = MPI_Rsend(buffer_out, msgLen, MPI_INT,
1-rank, tag, MPI_COMM_WORLD);
break;
case modeS: retVal = MPI_Ssend(buffer_out, msgLen, MPI_INT,
1-rank, tag, MPI_COMM_WORLD);
break;
case modeV: retVal = MPI_Send(buffer_out, msgLen, MPI_INT,
1-rank, tag, MPI_COMM_WORLD);
break;
}
fprintf(stderr, "%d/%d: sent %d\n", rank, size, retVal);
}
void checkParameters(int *msgLen, int *order, int *mode,
int argc, char **argv, int size, char orderChar, char modeChar) {
char errbuf[200];
if (size != 2) {
sprintf(errbuf, "wrong number of processes (%d)", size);
Usage(errbuf, argv[0]);
}
if (argc < 3) {
sprintf(errbuf, "wrong number of arguments (%d)", argc);
Usage(errbuf, argv[0]);
}
switch (orderChar) {
case 's':
case 'S':
*order = orderS;
break;
case 'R':
case 'r':
*order = orderR;
break;
case 'A':
case 'a':
*order = orderA;
break;
default:
sprintf(errbuf, "unrecognized order=%c", orderChar);
Usage(errbuf, argv[0]);
}
if (!sscanf(argv[2], "%d", msgLen) ||
*msgLen < 1 || *msgLen > MAX_ARRAY_LENGTH) {
sprintf(errbuf, "msgLen out of bounds=%s", argv[2]);
Usage(errbuf, argv[0]);
}
switch (modeChar) {
case 'B':
case 'b':
*mode = modeB;
break;
case 'R':
case 'r':
*mode = modeR;
break;
case 'S':
case 's':
*mode = modeS;
break;
case 'V':
case 'v':
*mode = modeV;
break;
default:
sprintf(errbuf, "unrecognized mode=%c", modeChar);
Usage(errbuf, argv[0]);
}
}
void Usage(char *msg, char *prog) {
printf("\n%s\nUsage: %s order msgLen mode\n", msg, prog);
printf("\twhere\n");
printf("\t\torder is R(receive first), S(send first), or A(alternate)\n");
printf("\t\tmsgLen can be 1 to %d\n", MAX_ARRAY_LENGTH);
printf("\t\tmode is B(Buffered), R(Ready), S(Synchronous), or V(Standard)\n");
exit(1);
}