dolfinx.common#
General tools for timing and configuration.
Functions
|
Create an index map for a subset of the indices of an index map. |
|
Create an index map. |
|
Print out a summary of all Timer measurements. |
|
Create a scatterer for data with a layout described by an index map. |
|
Decorator for timing functions. |
|
Return the logged elapsed time. |
Classes
|
Map indices across processes. |
|
|
|
Scatter and gather data with a layout described by an |
|
A timer for timing section of code. |
- class dolfinx.common.IndexMap(imap: IndexMap)[source]#
Bases:
objectMap indices across processes.
An index map describes the parallel distribution of a range of indices. Each index is owned by exactly one process. A process holds the indices it owns, numbered
[0, size_local)locally, followed by the ‘ghost’ indices it holds but does not own, numbered[size_local, size_local + num_ghosts).Create an index map.
Note
This initialiser is intended for internal library use only. User code should call
index_map()to create an index map.- Parameters:
imap – C++ IndexMap object.
- property ghosts: ndarray[tuple[Any, ...], dtype[int64]]#
Global index of each ghost index.
Note
The returned array is a read-only view.
- global_to_local(global_index: ndarray[tuple[Any, ...], dtype[int64]]) ndarray[tuple[Any, ...], dtype[int32]][source]#
Map global indices to local indices.
- Parameters:
global_index – Global indices.
- Returns:
Local index of each entry of
global_index, with-1for indices that are not owned or ghosted by the caller.
- index_to_dest_ranks(tag: int) tuple[ndarray[tuple[Any, ...], dtype[int32]], ndarray[tuple[Any, ...], dtype[int32]]][source]#
Ranks that ghost each owned index, as an adjacency list.
- Parameters:
tag – MPI tag used by the consensus exchange. Must be the same on all ranks, and must not clash with another in-flight exchange.
- Returns:
Ghosting ranks of each owned index, as a (data, offsets) pair.
- local_to_global(local: ndarray[tuple[Any, ...], dtype[int32]]) ndarray[tuple[Any, ...], dtype[int64]][source]#
Map local indices to global indices.
- Parameters:
local – Local indices.
- Returns:
Global index of each entry of
local.
- class dolfinx.common.Scatterer(s: Scatterer)[source]#
Bases:
objectScatter and gather data with a layout described by an
IndexMap.A scatterer is stateless: it holds only the communication pattern derived from an
IndexMap, and does not track buffers or the status of in-flight MPI requests. Callers ofscatter_fwd_begin/scatter_rev_beginare responsible for managing the send/receive buffers and the returned request, and can share one scatterer between multiple objects (e.g.dolfinx.la.Vector) that use the same index map.A forward scatter sends data associated with owned/local indices to the ranks that ghost them; a reverse scatter sends ghost data back to the owning ranks, to be accumulated into the owned data. Both use the same two-step begin/end pattern, splitting the non-blocking exchange from its completion so that unrelated work can be done while communication is in flight. A round trip for a forward scatter with block size 1, where
xholds the owned data andx_ghostthe ghost data:local_idx = sc.local_indices_block remote_idx = sc.remote_indices_block send_buffer = x[local_idx] recv_buffer = np.empty(remote_idx.size, dtype=x.dtype) request = sc.scatter_fwd_begin(send_buffer, recv_buffer, 1) # ... unrelated work can be done here while communication is # in flight, but send_buffer/recv_buffer must not be touched ... sc.scatter_fwd_end(request) x_ghost[remote_idx] = recv_buffer
A reverse scatter follows the same pattern with the roles of
local_indices_block/remote_indices_blockand ofsend_buffer/recv_bufferswapped, and accumulating (rather than assigning) into the destination array; seescatter_rev_begin()andscatter_rev_end().Create a scatterer.
Note
This initialiser is intended for internal library use only. User code should call
scatterer()to create a scatterer object.- Parameters:
s – C++ Scatterer object.
- property local_indices_block: ndarray[tuple[Any, ...], dtype[int32]]#
Indices for packing/unpacking owned data in a send/recv buffer.
For a forward scatter, used to copy owned entries into a send buffer. For a reverse scatter, used to accumulate received values into the owned entries. Blocked: for block size
bsa buffer holdsbsvalues per index and must bebs * local_indices_block.sizelong.
- property remote_indices_block: ndarray[tuple[Any, ...], dtype[int32]]#
Indices for packing/unpacking ghost data in a send/recv buffer.
For a forward scatter, used to unpack received values into ghost entries. For a reverse scatter, used to pack ghost entries into a send buffer. Blocked: for block size
bsa buffer holdsbsvalues per index and must bebs * remote_indices_block.sizelong.
- scatter_fwd_begin(send_buffer: ndarray[tuple[Any, ...], dtype[int64 | float32 | float64 | complex64 | complex128]], recv_buffer: ndarray[tuple[Any, ...], dtype[int64 | float32 | float64 | complex64 | complex128]], bs: int = 1) Request[source]#
Start a non-blocking exchange of owned data with ghosting ranks.
The communication is completed by calling
scatter_fwd_end(). Seelocal_indices_blockfor how to packsend_bufferandremote_indices_blockfor how to unpackrecv_buffer.Note
Collective. Every rank in the communicator must call this, including ranks without neighbours.
Note
send_buffer/recv_buffermust not be changed or accessed until after a call toscatter_fwd_end().- Parameters:
send_buffer – Packed owned data, blocked by
bs, sizedbs * local_indices_block.size.recv_buffer – Buffer for storing received data, blocked by
bs, sizedbs * remote_indices_block.size.bs – Number of values per index map index.
- Returns:
Request to pass to
scatter_fwd_end().
- scatter_fwd_end(request: Request) None[source]#
Complete the exchange started by
scatter_fwd_begin().Note
Local completion of the caller’s own request, not itself collective. Every rank that called
scatter_fwd_begin()must still call this before reusing the buffers.- Parameters:
request – Request returned by
scatter_fwd_begin().
- scatter_rev_begin(send_buffer: ndarray[tuple[Any, ...], dtype[int64 | float32 | float64 | complex64 | complex128]], recv_buffer: ndarray[tuple[Any, ...], dtype[int64 | float32 | float64 | complex64 | complex128]], bs: int = 1) Request[source]#
Start a non-blocking exchange of ghost data with owning ranks.
The communication is completed by calling
scatter_rev_end(). Seeremote_indices_blockfor how to packsend_bufferandlocal_indices_blockfor how to unpack (accumulate into)recv_buffer.Note
Collective. Every rank in the communicator must call this, including ranks without neighbours.
Note
send_buffer/recv_buffermust not be changed or accessed until after a call toscatter_rev_end().- Parameters:
send_buffer – Data associated with each ghost index, blocked by
bs, sizedbs * remote_indices_block.size.recv_buffer – Buffer for storing received data, blocked by
bs, sizedbs * local_indices_block.size.bs – Number of values per index map index.
- Returns:
Request to pass to
scatter_rev_end().
- scatter_rev_end(request: Request) None[source]#
Complete the exchange started by
scatter_rev_begin().Note
Local completion of the caller’s own request, not itself collective. Every rank that called
scatter_rev_begin()must still call this before reusing the buffers.- Parameters:
request – Request returned by
scatter_rev_begin().
- class dolfinx.common.Timer(name: str | None = None)[source]#
Bases:
objectA timer for timing section of code.
The recommended usage is with a context manager.
Example
With a context manager, the timer is started when entering and stopped at exit. With a named
Timer:with Timer("Some costly operation"): costly_call_1() costly_call_2() delta = timing("Some costly operation") print(delta)
or with an un-named
Timer:with Timer() as t: costly_call_1() costly_call_2() print(f"Elapsed time: {t.elapsed()}")
Example
It is possible to start and stop a timer explicitly:
t = Timer("Some costly operation") costly_call() delta = t.stop()
and retrieve timing data using:
delta = t.elapsed()
To flush the timing data for a named
Timerto the logger, the timer should be stopped and flushed:t.stop() t.flush()
Timings are stored globally (if task name is given) and once flushed (if used without a context manager) may be printed using functions
timing()andlist_timings(), e.g.:list_timings(comm)
Create timer.
- Parameters:
name – Identifier to use when storing elapsed time in logger.
- dolfinx.common.create_sub_index_map(imap: IndexMap, indices: ndarray[tuple[Any, ...], dtype[int32]]) tuple[IndexMap, ndarray[tuple[Any, ...], dtype[int32]], bool][source]#
Create an index map for a subset of the indices of an index map.
An index that is included by a process that ghosts it, but not by its owner, is re-assigned to one of the including processes.
Note
Collective.
- Parameters:
imap – Index map to build a sub-map of.
indices – Local indices of
imap, unique and in range, to include in the sub-map.
- Returns:
The sub-map, the index in
imapof each of its indices, and whether any index acquired a new owner.
Note
The owner-change flag is rank-local and is not reduced, so it can differ across ranks. Reduce it (e.g.
comm.allreduce(..., op=MPI.LOR)) before using it in a collective decision; branching on the unreduced value can leave some ranks in a collective that others have skipped.
- dolfinx.common.index_map(comm: Comm, local_size: int, ghosts: tuple[ndarray[tuple[Any, ...], dtype[int64]], ndarray[tuple[Any, ...], dtype[int32]]] | None = None, *, dest_src: Sequence[ndarray[tuple[Any, ...], dtype[int32]]] | None = None, tag: int = 1202) IndexMap[source]#
Create an index map.
Note
Collective.
ghostsmust beNoneon every process or given on every process, and likewise fordest_src. This is a precondition and is not checked, since checking it would require communication on every call.- Parameters:
comm – MPI communicator to distribute the indices over.
local_size – Number of indices owned by the calling process.
ghosts – Tuple
(ghost_indices, owners)of global ghost indices and their owning ranks. IfNone, the index map is non-overlapping andghostsmust beNoneon every process. For an overlapping map, a process with no ghosts must pass empty arrays.dest_src – Pair
(dest, src)of destination and source rank arrays.destlists ranks that ghost caller-owned indices;srclists ranks that own the caller’s ghosts and must equal the unique values inowners. Both arrays must be sorted, unique, and contain valid ranks. Supplying them avoids the consensus exchange that otherwise discovers which ranks ghost the caller’s owned indices.tag – MPI tag for the consensus exchange. Ignored if
dest_srcis given. Must be the same on all ranks, and must not clash with another in-flight exchange.
- Returns:
A new index map.
- dolfinx.common.list_timings(comm: Comm, reduction: Reduction = Reduction.max) None[source]#
Print out a summary of all Timer measurements.
When used in parallel, a reduction is applied across all processes. By default, the maximum time is shown.