mpi4py.util.sync

New in version 4.0.0.

The mpi4py.util.sync module provides parallel synchronization utilities.

Sequential execution

class mpi4py.util.sync.Sequential

Sequential execution.

Context manager for sequential execution within a group of MPI processes.

The implementation is based in MPI-1 point-to-point communication. A process with rank i waits in a blocking receive until the previous process rank i-1 finish executing and signals the next rank i with a send.

__init__(comm, tag=0)

Initialize sequential execution.

Parameters:
  • comm (Intracomm) – Intracommunicator context.

  • tag (int) – Tag for point-to-point communication.

Return type:

None

__enter__()

Enter sequential execution.

Return type:

Self

__exit__(*exc)

Exit sequential execution.

Parameters:

exc (object) –

Return type:

None

begin()

Begin sequential execution.

Return type:

None

end()

End sequential execution.

Return type:

None

Global counter

class mpi4py.util.sync.Counter

Parallel counter.

Produce consecutive values within a group of MPI processes. The counter interface is close to that of itertools.count.

The implementation is based in MPI-3 one-sided operations. A root process (typically rank 0) holds the counter, and its value is queried and incremented with an atomic RMA fetch-and-add operation.

__init__(comm, start=0, step=1, typecode='i', root=0, info=INFO_NULL)

Initialize counter object.

Parameters:
  • comm (Intracomm) – Intracommunicator context.

  • start (int) – Start value.

  • step (int) – Increment value.

  • typecode (str) – Type code as defined in the array module.

  • root (int) – Process rank holding the counter memory.

  • info (Info) – Info object for RMA context creation.

Return type:

None

__iter__()

Implement iter(self).

Return type:

Self

__next__()

Implement next(self).

Return type:

int

next(incr=None)

Return current value and increment.

Parameters:

incr (int | None) – Increment value.

Returns:

The counter value before incrementing.

Return type:

int

free()

Free counter resources.

Return type:

None

Mutual exclusion

class mpi4py.util.sync.Mutex

Parallel mutex.

Establish a critical section or mutual exclusion among MPI processes. The mutex interface is close to that of threading.Lock. However, its intended uses and specific semantics are somewhat different:

  • A mutex should be used within a group of MPI processes, not threads.

  • Once acquired, a mutex is held and owned by a process until released.

  • Trying to acquire a mutex already held raises RuntimeError.

  • Trying to release a mutex not yet held raises RuntimeError.

This mutex implementation uses the scalable and fair spinlock algorithm from [mcs-paper] and took inspiration from the MPI-3 RMA implementation of [uam-book].

[mcs-paper]

John M. Mellor-Crummey and Michael L. Scott. Algorithms for scalable synchronization on shared-memory multiprocessors. ACM Transactions on Computer Systems, 9(1):21-65, February 1991. https://doi.org/10.1145/103727.103729

[uam-book]

William Gropp, Torsten Hoefler, Rajeev Thakur, Ewing Lusk. Using Advanced MPI - Modern Features of the Message-Passing Interface. Chapter 4, Section 4.7, Pages 130-131. The MIT Press, November 2014. https://mitpress.mit.edu/9780262527637/using-advanced-mpi/

__init__(comm, info=INFO_NULL)

Initialize mutex object.

Parameters:
  • comm (Intracomm) – Intracommunicator context.

  • info (Info) – Info object for RMA context creation.

Return type:

None

__enter__()

Acquire mutex.

Return type:

Self

__exit__(*exc)

Release mutex.

Parameters:

exc (object) –

Return type:

None

acquire(blocking=True)

Acquire mutex, blocking or non-blocking.

Parameters:

blocking (bool) – If True, block until the mutex is held.

Returns:

True if mutex is held, False otherwise.

Return type:

bool

release()

Release mutex.

Return type:

None

locked()

Return whether the mutex is held.

Return type:

bool

free()

Free mutex resources.

Return type:

None

class mpi4py.util.sync.RMutex

Parallel recursive mutex.

Establish a critical section or mutual exclusion among MPI processes. The mutex interface is close to that of threading.RLock, allowing for recursive acquire and release operations. However, the mutex should be used within a group of MPI processes, not threads.

The implementation is based on a Mutex providing mutual exclusion and a counter tracking the recursion level.

__init__(comm, info=INFO_NULL)

Initialize recursive mutex object.

Parameters:
  • comm (Intracomm) – Intracommunicator context.

  • info (Info) – Info object for RMA context creation.

Return type:

None

__enter__()

Acquire mutex.

Return type:

Self

__exit__(*exc)

Release mutex.

Parameters:

exc (object) –

Return type:

None

acquire(blocking=True)

Acquire mutex, blocking or non-blocking.

Parameters:

blocking (bool) – If True, block until the mutex is held.

Returns:

True if mutex is held, False otherwise.

Return type:

bool

release()

Release mutex.

Return type:

None

count()

Return recursion count.

Return type:

int

free()

Free mutex resources.

Return type:

None

Examples

test-sync-1.py
 1from mpi4py import MPI
 2from mpi4py.util.sync import Counter, Sequential
 3
 4comm = MPI.COMM_WORLD
 5
 6counter = Counter(comm)
 7with Sequential(comm):
 8   value = next(counter)
 9counter.free()
10
11assert comm.rank == value
test-sync-2.py
 1from mpi4py import MPI
 2from mpi4py.util.sync import Counter, Mutex
 3
 4comm = MPI.COMM_WORLD
 5
 6mutex = Mutex(comm)
 7counter = Counter(comm)
 8with mutex:
 9   value = next(counter)
10counter.free()
11mutex.free()
12
13assert (
14   list(range(comm.size)) ==
15   sorted(comm.allgather(value))
16)