First, you need to keep in mind a correct MPI application should not expect a blocking send (e.g. MPI_Send()
) returns before a matching receive has been posted. For example, if two tasks need to exchange data, it is not correct to
MPI_Send(...);
MPI_Recv(...);
since it might deadlock.
An option is to manually order to communications
if (peer < me) {
MPI_Send(...);
MPI_Recv(...);
} else {
MPI_Recv(...);
MPI_Send(...);
}
IMHO, that makes the application harder to write and maintain.
An other option is to use non blocking communications so you no more have to worry about deadlocks.
MPI_Isend(...);
MPI_Irecv(...);
MPI_Waitall(...);
Note in this a simple example that illustrates a more general issue, and MPI_Sendrecv()
should be preferred here.
Some MPI libraries implement a progress thread with some interconnects. (Keep in mind most do not, but that will hopefully change).
In this case, non blocking communications can be used to overlap computation and communication, and hence make the application more efficient.
MPI_Irecv(...);
// perform some computation that do no require the data to be received
MPI_Wait(...);
If your MPI library does not implement a progress thread, then no message will start being received before MPI_Wait()
is invoked.
Not all applications can (simply) benefit from overlapping computations and communications. In this case
MPI_Recv(...);
is not only more compact, but might be more efficient than the non blocking counterpart since it leaves extra room for optimization by the MPI library compared to
MPI_Irecv(...);
MPI_Wait(...);
Bottom line, blocking is not better than non blocking nor the other way around. That being said, on a case by case basis, one is generally a better fit than the other.