mpi: Add basic2 and basic3 modes - #2995
Open
georgebisbas wants to merge 1 commit into
Open
Conversation
Closed
Adds two MPI halo-exchange schemes, both variants of `basic` that avoid
re-allocating gather/scatter buffers on every halo exchange call:
- `basic2`: `basic`, but the send/recv buffers are allocated once (via a
pre-allocated MPIMsg-style C struct, MPIMsgBasic2) instead of malloc'd
and freed on every single haloupdate() call.
- `basic3`: `basic2`, further optimized the same way `overlap2` optimizes
`overlap`: ranks and gather/scatter offsets are precomputed once in
Python and read directly off the message struct (MPIMsgEnrichedBasic2)
inside a single Iteration loop, instead of being recomputed via
MPINeighborhood/symbolic-offset lookups at each of the 2*ndim unrolled
sendrecv() call sites basic2 generates. haloupdate()'s code size is
independent of the number of exchange directions as a result;
func_table drops from 4 entries under basic2 to 3 under basic3 (no
separate sendrecv0).
Both are selected the same way as the existing modes: DEVITO_MPI=basic2
/ DEVITO_MPI=basic3.
devito/mpi/routines.py:
- MPIMsgBase/MPIMsg/MPIMsgBasic2/MPIMsgEnriched: buffer allocation goes
through infer_datasize() for overflow-safe sizing, and lazily pulls
the allocator from args.allocator, matching current API conventions.
- Basic2HaloExchangeBuilder._make_haloupdate delegates to the shared
BasicHaloExchangeBuilder._make_haloupdate instead of duplicating its
mapper/loop logic just to inject a haloid; the base method threads
haloid through generically (a no-op for plain basic), matching how
DiagHaloExchangeBuilder already does it.
- MPIMsgBasic2/MPIMsgEnrichedBasic2's _make_msg filters hse.halos down
to axis-aligned pairs only (diagonal corners are filled implicitly by
basic's sequential per-axis exchange order and were previously
counted towards npeers without ever being allocated).
- New: Basic3HaloExchangeBuilder and MPIMsgEnrichedBasic2.
- mpi_registry gains 'basic2' and 'basic3'.
tests/test_mpi.py:
- basic2/basic3 added to the relevant existing parametrizations
(test_trivial_eq_2d/3d, test_coupled_eqs_mixed_dims, test_cire,
test_adjoint_F, test_min_code_size).
- New: test_trivial_eq_2d_bundled (two same-pattern TimeFunctions
forcing Bundle/Bag packing through MPIMsgBasic2/MPIMsgEnrichedBasic2),
test_basic2_msg_fields, test_basic2_comm_scheme, test_basic3_comm_scheme
(white-box checks on generated sendrecv/haloupdate structure, in the
style of the existing test_diag_comm_scheme/test_poke_progress).
benchmarks/user/README.md: mentions basic2 alongside basic/diag2/full as
one of Devito's three most prevalent MPI modes.
Testing: tests/test_mpi.py 239 passed, 0 failed. pytest -m parallel
tests/ (CI's pytest-core-mpi command): 648 passed, 0 failed. MPI-examples
step (examples/seismic/{acoustic,tti}): 20/20 passed on both ranks.
Numerical correctness cross-checked bit-for-bit against basic/diag/
overlap/full at 1-8 ranks, 2D/3D, space_order 2 and 4, bundled
multi-field targets, and a real acoustic seismic example.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
mpi: Add
basic2andbasic3modesSummary
This PR adds two new MPI halo-exchange schemes, both variants of
basicthat avoid re-allocating gather/scatter buffers on every halo exchange
call:
basic2—basic, but the send/recv buffers are allocated once(via a pre-allocated
MPIMsg-style C struct,MPIMsgBasic2) instead ofmalloc'd and freed on every single
haloupdate()call.basic3—basic2, further optimized the same wayoverlap2optimizes
overlap: ranks and gather/scatter offsets are precomputedonce in Python and read directly off the message struct
(
MPIMsgEnrichedBasic2) inside a singleIterationloop, instead ofbeing recomputed via
MPINeighborhood/symbolic-offset lookups at eachof the
2*ndimunrolledsendrecv()call sitesbasic2generates.Both are selected the same way as the existing modes:
DEVITO_MPI=basic2/
DEVITO_MPI=basic3.Why
basic's gather/scatter buffers are heap-allocated and freed on everysingle halo exchange — i.e. every timestep, for every halo-touching
Function. For runs with many timesteps this is pure overhead: the buffer
shape for a given
(Function, halo direction)pair never changes acrossthe run.
basic2/basic3allocate it once, mirroring whatoverlap/overlap2/fullalready do for the asynchronous modes, but forbasic'ssynchronous, non-overlapped exchange pattern.
basic3additionally cuts downhaloupdate()'s own code size:basic/basic2emit one unrolledsendrecv()call per(dimension, side)pair,so the generated code grows with the number of exchange directions.
basic3collapses that into one small loop, the same wayoverlap2ismore compact than
overlap:haloupdate0's code size is now independent of the number of exchangedirections — this matters more as dimensionality grows (3D, subdomains,
tensor/vector equations with several components), where
basic2wouldotherwise keep emitting more unrolled calls.
func_tabledrops from 4entries (
gather0,scatter0,sendrecv0,haloupdate0) underbasic2to 3 under
basic3(no separatesendrecv0).What changed
devito/mpi/routines.py:MPIMsgBase/MPIMsg/MPIMsgBasic2/MPIMsgEnriched: bufferallocation now goes through
infer_datasize()for overflow-safesizing, and lazily pulls the allocator from
args.allocator— theconvention
mainmoved to since this branch was first opened.Basic2HaloExchangeBuilder:_make_haloupdatenow delegates to theshared
BasicHaloExchangeBuilder._make_haloupdateinstead ofduplicating its mapper/loop logic just to inject a
haloid;BasicHaloExchangeBuilder._make_haloupdatethreadshaloidthroughgenerically (a no-op for plain
basic), matching howDiagHaloExchangeBuilderalready does it.MPIMsgBasic2/MPIMsgEnrichedBasic2's_make_msgnow filtershse.halosdown to axis-aligned pairs only (diagonal corners arefilled implicitly by
basic's sequential per-axis exchange order andwere previously counted towards
npeerswithout ever beingallocated).
Basic3HaloExchangeBuilderandMPIMsgEnrichedBasic2.mpi_registrygains'basic2'and'basic3'.tests/test_mpi.py:basic2/basic3added to the relevant existingparametrizations (
test_trivial_eq_2d/3d,test_coupled_eqs_mixed_dims,test_cire,test_adjoint_F,test_min_code_size), plus new tests:test_trivial_eq_2d_bundled— two same-patternTimeFunctionsforcing Devito's Bundle/Bag packing (a feature added to
mainafterthis branch first forked) through
MPIMsgBasic2/MPIMsgEnrichedBasic2.test_basic2_msg_fields— locks inMPIMsgEnrichedBasic2's field set.test_basic2_comm_scheme/test_basic3_comm_scheme— white-boxchecks on the generated
sendrecv/haloupdatestructure for eachmode, in the style of the existing
test_diag_comm_scheme/test_poke_progress.benchmarks/user/README.md: mentionsbasic2alongsidebasic/diag2/fullas one of Devito's three most prevalent MPI modes.Testing
tests/test_mpi.py: 239 passed, 0 failed (local run, OpenMPI 4.1.6).pytest -m parallel tests/(the broader suite CI'spytest-core-mpiworkflow runs, not just
test_mpi.py): 648 passed, 3 skipped,1 xpassed (pre-existing, unrelated
xfail), 0 failed.DEVITO_MPI=1 mpirun -n 2 pytest examples/seismic/{acoustic,tti}(theworkflow's MPI-examples step): 20/20 passed on both ranks — exercises
the shared
BasicHaloExchangeBuilder._make_haloupdatecode path thisPR touches, under plain
basic.basic/diag/overlap/fullat 1, 2, 3, 4, and 8 ranks; 2D and 3D;space_order2and 4; with bundled multi-field targets; and on a real acoustic seismic
example (
norm(rec)matches to fullfloat32precision across everymode and rank count tested).
Not verified locally: CI's
pytest-core-mpijob uses MPICH; this wastested locally against OpenMPI 4.1.6 (MPICH wasn't installable
without
sudoin this environment). Neither mode uses anything beyondthe portable MPI API already exercised identically by the working
overlap/diag2paths (MPI_Isend/Irecv/Wait,MPI_PROC_NULL,Comm_shift,Get_cart_rank), so this is expected to be a non-issue,but CI will be the first real confirmation on MPICH.