Point to Point Communication II

2. Basic Deadlock

Deadlock is a phenomenon most common with blocking communication. It occurs when all tasks are waiting for events that haven't been initiated yet.

The following diagram represents two SPMD tasks: both are calling blocking standard sends at the same point of the program. Each task's matching receive occurs later in the other task's program.

 

Deadlock

A simple example of deadlock is one in which the two sends are each waiting on their corresponding receives in order to complete, but those receives are executed after the sends, so if the sends do not complete and return, the receives can never be executed, and both sets of communications will stall indefinitely.

A more complex example of deadlock can occur if the message size is greater than the threshold; deadlock will occur because neither task can synchronize with its matching receive. If the message size is less than or equal to the threshold, deadlock can still occur if insufficient system buffer space is available. Both tasks will be waiting for a receive to draw message data out of the system buffer, but these receives cannot be executed because both tasks are blocked at the send.

Solutions for avoiding deadlock:

There are four ways to avoid deadlock:

  1. different ordering of calls between tasks

    Arrange for one task to post its receive first and for the other to post its send first. That clearly establishes that the message in one direction will precede the other.

  2. non-blocking calls

    Have each task post a non-blocking receive before it does any other communication. This allows each message to be received, no matter what the task is working on when the message arrives or in what order the sends are posted.

  3. MPI_Sendrecv
    MPI_Sendrecv_replace

    Use MPI_Sendrecv (S) . This is an elegant solution. In the _replace (S) version, the system allocates some buffer space (not subject to the threshold limit) to deal with the exchange of messages.

  4. buffered mode

    Use buffered sends so that computation can proceed after copying the message to the user-supplied buffer. This will allow the receives to be executed. Buffered sends were discussed earlier, in MPI Point to Point Communication I.