Receive Status
The status variable contains information about the message.
-
MPI_SOURCE The source rank of the message. This is a field of the status structure.
- C++ status.MPI_SOURCE
- Fortran status(MPI_SOURCE)
- Python status.Get_Source()
-
MPI_TAG The tag. This is another field of the structure (or element of the array).
- C++ status.MPI_TAG
- Fortran status(MPI_TAG)
- Python status.Get_tag()
-
MPI_Get_count(MPI_Status* status, MPI_Datatype datatype, int* count) The length (item count) of the message.
- C++ MPI_Get_count(&status,MPI_TYPE,&item_count);
- Fortran MPI_Get_count(status,MPI_TYPE,item_count,ierr)
- Python status.Get_count(MPI.TYPE)
-
MPI_Error The error number. Not often needed.
- C++ status.MPI_ERROR
- Fortran status(MPI_ERROR)
- Python status.Get_error()
Note that mpi4py implements some C/C++/Fortran procedures as methods in the status
object.
The MPI_SOURCE and MPI_TAG items may be especially useful for the special dummy variables defined for source and tag.
If the programmer does not intend to examine the status field, the special value MPI_STATUS_IGNORE may be passed as the status parameter (C++/Fortran) or in Python, by omitting the argument, since it is optional.
Special Source and Tag Variables
MPI defines special variables that can be used in MPI_Recv
MPI_ANY_SOURCE
MPI_ANY_TAG
Either or both can be used in a receive if the MPI_Recv can accept a message from any source and/or any tag.
Example Status Usage
Add a status query to the exchange code to find the source, tag, and any error. Note that Python uses functions to retrieve all the members of the status structure, and must also initialize it with a constructor.
Although the status data structure can also return the item count, if the receiver does not know the number or size of the message, we recommend invoking MPI_PROBE
, which allows the receiving process to determine the specifics of the message without actually receiving it. It can then set up an appropriate MPI_Recv.
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);
int item_count;
MPI_Get_count(&status,MPI_FLOAT,&item_count);
cout<<"Source "<<status.MPI_SOURCE<<" Tag "<<status.MPI_TAG<<" Num Items "<<item_count<<" Error "<<status.MPI_ERROR<<"\n";
}
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
integer :: item_count
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)
call MPI_Get_count(status,MPI_REAL,item_count,ierr)
write(*,*) "Source",status(MPI_SOURCE),"Tag",status(MPI_TAG),"Num items",item_count,"Error",status(MPI_ERROR)
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)
status=MPI.Status()
if rank==0:
comm.Recv([baton,MPI.DOUBLE],source=1,status=status)
baton+=1.
comm.Send([baton,MPI.DOUBLE],dest=1)
print("Source",status.Get_source(),"Tag",status.Get_tag(),"Item count",status.Get_count(MPI.DOUBLE),"Error",status.Get_error())
elif rank==1:
baton[:]=12.
comm.Send([baton,MPI.DOUBLE],dest=0)
comm.Recv([baton,MPI.DOUBLE],source=0,status=status)
print(rank,baton)