Standard Blocking Send/Receive
The most widely used send is the “standard” form. We will begin with the blocking version, since it is generally safer than the nonblocking form; it can be implemented intentionally or it can be used to develop a program and later replaced by nonblocking send/receive.
Send
The syntax for invocation for the standard MPI_Send is
int MPI_Send(&sendbuf, count, datatype, dest, tag, comm)
call MPI_Send(sendbuf, count, datatype, dest, tag, comm, ierr)
comm.Send([sendbuf,datatype],dest=rank,tag=0)
#or for pickled objects
comm.send(sendbuf,dest=rank,tag=0)
Receive
The matching receive is called as follows:
MPI_Status status;
int MPI_Recv(&recvbuf, count, datatype, source, tag, comm, &status)
integer, dimension(MPI_STATUS_SIZE) :: status
call MPI_Recv(recvbuf, count, datatype, source, int tag, comm, status, ierr)
comm.Recv([data,MPI_Type],source=rank,tag=0,status=status)
#or for pickled objects
data=comm.recv(source=rank,tag=0,status=status)
The status variable is optional for Python, but not for C++ or Fortran.
Example
Our first program will run on two processes and exchange some data between them.
C++
#include <iostream>
#include "mpi.h"
using namespace std;
int main(int argc, char *argv[]) {
int rank, npes;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &npes);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if ( npes != 2 ) {
cout<<"This program runs only on two processes\n";
MPI_Finalize();
exit(1);
}
float baton=0;
if ( rank == 0 ) {
MPI_Recv(&baton,1,MPI_FLOAT,1,0,MPI_COMM_WORLD,&status);
baton+=1.;
MPI_Send(&baton,1,MPI_FLOAT,1,0,MPI_COMM_WORLD);
}
else if ( rank == 1) {
baton=12.;
MPI_Send(&baton,1,MPI_FLOAT,0,0,MPI_COMM_WORLD);
MPI_Recv(&baton,1,MPI_FLOAT,0,0,MPI_COMM_WORLD,&status);
}
cout<<rank<<" "<<baton<<"\n";
MPI_Finalize();
exit(0);
}
Fortran
program send_receive
use mpi
implicit none
integer :: rank, npes, ierr
integer, dimension(MPI_STATUS_SIZE) :: status
real :: baton
call MPI_Init(ierr)
call MPI_Comm_size(MPI_COMM_WORLD, npes, ierr);
call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr);
if ( npes /= 2 ) then
write(*,*) "This program runs only on two processes"
call MPI_Finalize(ierr)
stop
endif
baton=0;
if ( rank == 0 ) then
call MPI_Recv(baton,1,MPI_REAL,1,0,MPI_COMM_WORLD,status,ierr);
baton=baton+1.
call MPI_Send(baton,1,MPI_REAL,1,0,MPI_COMM_WORLD,ierr)
else if ( rank == 1 ) then
baton=12.
call MPI_Send(baton,1,MPI_REAL,0,0,MPI_COMM_WORLD,ierr)
call MPI_Recv(baton,1,MPI_REAL,0,0,MPI_COMM_WORLD,status,ierr)
endif
write(*,*) rank,baton
call MPI_Finalize(ierr)
end program
Python
import sys
import numpy as np
from mpi4py import MPI
comm=MPI.COMM_WORLD
nprocs=comm.Get_size()
rank=comm.Get_rank()
if nprocs !=2:
print("This program works only for two processes.")
sys.exit()
baton=np.empty(1)
if rank==0:
comm.Recv([baton,MPI.DOUBLE],source=1)
baton+=1.
comm.Send([baton,MPI.DOUBLE],dest=1)
elif rank==1:
baton[:]=12.
comm.Send([baton,MPI.DOUBLE],dest=0)
comm.Recv([baton,MPI.DOUBLE],source=0)
print(rank,baton)