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)

Previous
Next