Chapter 4. Thread-Safe MPI


Note: The Linux implementation of MPI is not currently thread-safe.


The SGI implementation of MPI on IRIX systems assumes the use of POSIX threads or processes (see the pthread_create(3) or the sprocs(2) commands, respectively). MPI processes can be multithreaded. Each thread associated with a process can issue MPI calls. However, the rank ID in send or receive calls identifies the process, not the thread. A thread behaves on behalf of the MPI process. Therefore, any thread associated with a process can receive a message sent to that process.

Threads are not separately addressable. To support both POSIX threads and processes (known as sprocs), thread-safe MPI must be run on an IRIX 6.5 system or later.

It is the user's responsibility to prevent races when threads within the same application post conflicting communication calls. By using distinct communicators for each thread, the user can ensure that two threads in the same process do not issue conflicting communication calls.

All MPI calls on IRIX 6.5 or later systems are thread-safe. This means that two concurrently running threads can make MPI calls and the outcome will be as if the calls executed in some order, even if their execution is interleaved.

If you block an MPI call, only the calling thread is blocked, allowing another thread to execute, if available. The calling thread is blocked until the event on which it waits occurs. Once the blocked communication is enabled and can proceed, the call completes and the thread is marked runnable within a finite time. A blocked thread does not prevent progress of other runnable threads on the same process, and does not prevent them from executing MPI calls.

Initialization

To initialize MPI for a program that will run in a multithreaded environment, the user must call the MPI-2 function, MPI_Init_thread(). In addition to initializing MPI in the same way as MPI_Init(3) does, MPI_Init_thread() also initializes the thread environment.

You can create threads before MPI is initialized, but before MPI_Init_thread() is called, the only MPI call these threads can execute is MPI_Initialized(3).

Only one thread can call MPI_Init_thread(). This thread becomes the main thread. Since only one thread calls MPI_Init_thread(), threads must be able to inherit initialization. With the SGI implementation of thread-safe MPI, for proper MPI initialization of the thread environment, a thread library must be loaded before the call to MPI_Init_thread(). This means that dlopen(3c) cannot be used to open a thread library after the call to MPI_Init_thread().

Query Functions

The MPI-2 query function, MPI_Query_thread(), is available to query the current level of thread support. The MPI-2 function, MPI_Is_thread_main(), can be used to find out whether a thread is the main thread. The main thread is the thread that called MPI_Init_thread().

Requests

More than one thread cannot work on the same request. A program in which two threads block, waiting on the same request is erroneous. Similarly, the same request cannot appear in the array of requests of two concurrent MPI_Wait{any|some|all} calls. In MPI, a request can be completed only once. Any combination of wait or test that violates this rule is erroneous.

Probes

A receive call that uses source and tag values returned by a preceding call to MPI_Probe(3) or MPI_Iprobe(3) will receive the message matched by the probe call only if there was no other matching receive call after the probe and before that receive. In a multithreaded environment, it is the user's responsibility to use suitable mutual exclusion logic to enforce this condition. You can enforce this condition by making sure that each communicator is used by only one thread on each process.

Collectives

Matching collective calls on a communicator, window, or file handle is performed according to the order in which the calls are issued in each process. If concurrent threads issue such calls on the communicator, window, or file handle, it is the user's responsibility to use interthread synchronization to ensure that the calls are correctly ordered.

Exception Handlers

An exception handler does not necessarily execute in the context of the thread that made the exception-raising MPI call. The exception handler can be executed by a thread that is distinct from the thread that will return the error code.

Signals

If a thread that executes an MPI call is cancelled by another thread, or if a thread catches a signal while executing an MPI call, the outcome is undefined. When not executing MPI calls, a thread associated with an MPI process can terminate and can catch signals or be cancelled by another thread.

Internal Statistics

The SGI internal statistics diagnostics are not thread-safe.

Finalization

The call to MPI_Finalize(3) occurs on the same thread that initialized MPI (also known as the main thread). It is the user's responsibility to ensure that the call occurs only after all the processes' threads have completed their MPI calls and have no pending communications or I/O operations.