Articles
MPI Interview Questions: Deadlocks, Nonblocking Requests, and Collective Contracts
Practice MPI interview questions with two-rank deadlocks, nonblocking buffer lifetimes, message matching, and consistent collective call contracts.
Two MPI ranks exchange arrays successfully in a small test, then hang with larger messages. Replacing MPI_Send with MPI_Isend still leaves the program stuck because both ranks wait before posting their receives. Changing the call name left both receives behind the waits that depend on them.
For MPI interview questions, prove message matching, buffer ownership and collective order separately. Draw each rank’s call sequence, identify what permits completion, and state when the application can reuse each buffer. Nonblocking initiation is an opportunity to make progress, not evidence that communication has completed.
The worked schedules here are original exercises using MPI 4.1’s documented contracts as a baseline. MPI Forum lists MPI 5.0 as approved; 4.1 is not presented as the latest standard. Check your implementation’s supported version before using newer procedures. No candidate reports or cluster execution are claimed. MPI standards. Begin with Explain parallelism and collectives in training to practice distinguishing a communication contract from an implementation strategy.
Why can two blocking sends deadlock?
Official contract: a standard-mode send may use internal buffering, but MPI does not require buffering sufficient to make every send complete before a receive starts. Portable correctness must not depend on that choice. A synchronous send completes only after a matching receive has started receiving its message. MPI communication modes.
Original two-rank exercise: rank 0 sends to rank 1 and then receives from rank 1. Rank 1 performs the symmetric sequence. Assume matching tags, the same communicator and enough receive capacity; the question concerns ordering, not a typo in the destination.
| Stage | Rank 0 | Rank 1 | What the schedule permits |
|---|---|---|---|
| First call | Send to 1 | Send to 0 | Both may need the other rank’s receive |
| Intended next call | Receive from 1 | Receive from 0 | Neither is reached if both sends block |
| Small-message observation | Send happened to return | Send happened to return | Implementation buffering can conceal the cycle |
| Portability check | Replace send with synchronous send | Replace send with synchronous send | The missing posted receives become explicit |
The useful answer is not “large messages always deadlock.” Message size, available resources and implementation decisions affect the observed path. The portable defect is that completion relies on unspecified buffering.
Draw two edges: rank 0 waits for rank 1’s receive, and rank 1 waits for rank 0’s receive.
Rank 0 needs rank 1 to reach its receive, while rank 1 needs rank 0 to reach its receive. Both receives sit after the operations doing the waiting. That is the cycle you must remove.
An asymmetric send/receive order can break this two-rank cycle. It needs a deliberate protocol, especially when the interviewer extends the example to a ring or adds another phase. A fix that happens to work for two participants is not automatically a general neighbor-exchange algorithm.
Does Isend remove the deadlock?
Official contract: nonblocking calls start an operation and return a request associated with its completion. The application must not modify an active send buffer or access an active receive buffer before the corresponding operation completes. MPI communication initiation.
Now change each rank’s sequence to Isend → Wait(send) → Recv. Initiation returns, but the subsequent wait can still depend on the unposted receive. Both ranks can stop at the same dependency as before.
Original repair: post the matching receive and send before waiting for either completion. For exactly two ranks with rank values 0 and 1, a source-reviewed C sketch is:
int peer = 1 - rank;
int outgoing = rank + 100;
int incoming = -1;
MPI_Request requests[2];
MPI_Irecv(&incoming, 1, MPI_INT, peer, 17,
MPI_COMM_WORLD, &requests[0]);
MPI_Isend(&outgoing, 1, MPI_INT, peer, 17,
MPI_COMM_WORLD, &requests[1]);
MPI_Waitall(2, requests, MPI_STATUSES_IGNORE);
/* On successful completion, incoming is usable;
outgoing can be modified or released. */
This is a communication sketch, not a full program: it assumes initialized MPI, exactly two ranks, successful calls and valid matching buffers. It was not compiled or launched for this article. Production code needs an error policy; a failed completion is not permission to treat both transfers as successful.
Official progress rule: waiting on a receive can complete once its matching send has started, even if the sender has not yet waited on that send. The corresponding send progress rule depends on a matching receive having started. Nonblocking semantics.
The repair exposes the needed matching operations before either rank waits. “Use nonblocking” is too vague to explain why that particular schedule avoids the original cycle.
When is Sendrecv a better explanation?
Implementation documentation: Open MPI describes MPI_Sendrecv as a combined send/receive operation useful for shift patterns. Its send and receive buffers must be disjoint; counts, datatypes and peers describe the two directions independently. Open MPI Sendrecv.
For a simple exchange, it can express your intent more directly than manually managing two requests. Explain the matching source, destination, tags and communicator before choosing it. It does not repair an incorrect tag, insufficient receive storage or a missing participant.
Choose Sendrecv for a simple exchange, or requests when independent work belongs between initiation and completion. If useful independent computation exists between initiation and completion, requests can represent that interval. If the task is simply “exchange these values, then continue,” a combined blocking operation may be clearer.
A ring requires another decision: does each rank send to its right neighbor and receive from its left, or exchange both directions? Write those peers explicitly. Using the same neighbor for both directions can be correct for a two-rank exercise and wrong for a larger topology.
What does completion let you do with a buffer?
Official boundary: successful send completion allows reuse of the send buffer; it does not generally prove the receiver’s application has consumed the message. Receive completion makes the received data available locally. A nonpersistent request completed by MPI_Wait becomes inactive and its handle is set to MPI_REQUEST_NULL. MPI communication completion.
Treat a request as a record of an operation, not a detachable promise that a local variable can outlive by itself. The referenced storage must remain valid during the operation. Returning from a function that owns a stack array while its send is pending creates a lifetime problem even if the request handle survives elsewhere.
Original ownership ledger: before initiation, the application owns the outgoing value and can change it. After Isend, retain the value unchanged. After Irecv, leave the receive region untouched. Following successful Waitall, read the incoming value and reuse the outgoing region.
Reading an old receive value while waiting is not a safe progress indicator. It is an access to storage MPI may be updating. Track request status instead of polling buffer contents.
In a pipelined application, label buffers by phase as well as rank. If phase 2 overwrites phase 1’s send region before completion, correct tags will not save the data. Separate slots or complete the outstanding operation before reuse.
Also distinguish a completion handle from remote acknowledgment. If the application requires proof that a peer validated and stored the data, define a subsequent application-level response with its own matching and lifetime rules.
Which fields must match a point-to-point message?
Official definition: the message envelope includes source, destination, tag and communicator. A communicator provides a communication context; messages from different contexts do not interfere. Ranks are relative to the communicator’s group. MPI message envelope.
Original negative control: both ranks use tag 17 for sending, but rank 1 receives tag 18. Posting receives early removes the ordering defect yet leaves the matching defect. The repair must change the protocol agreement, not add a barrier before the same unmatched calls.
Wildcard receives can be appropriate, but they weaken assumptions about which sender supplied a value. If correctness depends on receiving rank 0’s control message before rank 2’s data, an unrestricted wildcard is not a substitute for that protocol.
For the tag-17 exchange, record communicator, peer, tag, datatype, count, buffer and phase beside each pending request. Then compare sender and receiver records. This ledger helps distinguish “the matching operation was never posted” from “a matching operation exists but the intended data contract is wrong.”
Do not confuse receive capacity with collective signature equality. A point-to-point receive may reserve more space than the actual message needs; a particular collective has its own participant rules.
What is the contract for a collective?
Official facts: collective operations must occur in the same order on a communicator. Nonblocking collectives do not match their blocking counterparts; they have no user tag argument. Their completion is local and does not generally establish that every other rank has completed. Nonblocking collectives.
For an intra-communicator MPI_Bcast, participants agree on communicator and root, and their count/datatype combinations have equal type signatures. Distinct memory layouts can still be valid. Do not reduce that rule to “everyone must use the identical datatype handle.” Broadcast contract.
Original contract matrix:
| Rank 0 sequence | Rank 1 sequence | Interview diagnosis |
|---|---|---|
| Bcast then Allreduce | Bcast then Allreduce | Order agrees; inspect each operation’s other arguments |
| Bcast then Allreduce | Allreduce then Bcast | Collective order disagrees on the same communicator |
| Bcast, root 0 | Bcast, root 1 | Root agreement fails for this intra-communicator case |
| Ibcast then wait | Bcast | Blocking and nonblocking calls do not match |
| Bcast | Conditional branch skips Bcast | A required participant is missing |
Collective correctness also involves cycles across communicators and interleaving with point-to-point calls. MPI’s correctness examples show why an application cannot assume every collective behaves as an extra barrier. Collective correctness.
Duplicating communicators separates communication contexts, but does not remove every dependency cycle. If one subsystem waits for another before either enters the required operation, the application can still hang. Specify both the communication universe and the allowed call order.
How would you demonstrate correctness and overlap?
First verify the protocol: expected participants, matching envelopes, collective sequence and buffer lifetimes. Then vary message sizes, rank counts and scheduling delays under the real runtime. Keep a synchronous-send control in the runtime test plan so success does not rest only on a small message being buffered.
The saved local controls check this article’s original dependency and contract ledgers, including a wrong-tag case and premature buffer reuse. They do not run MPI, demonstrate network progress or measure performance.
Inference: initiating communication leaves room for independent work, but useful asynchronous overlap depends on the implementation and workload. Measure complete iteration time with comparable work, not only the time for Isend to return. A faster initiation call can coexist with a longer final wait.
Sources and Further Reading
- MPI Forum standards and version status
- MPI 4.1 communication modes
- MPI 4.1 communication initiation
- MPI 4.1 nonblocking semantics
- Open MPI Sendrecv reference
- MPI 4.1 completion
- MPI 4.1 message envelope
- MPI 4.1 nonblocking collectives
- MPI 4.1 broadcast
- MPI 4.1 collective correctness
Research checked October 6, 2026. Schedules and ownership examples are original exercises, not observed MPI runs or candidate reports.