Context
DESIGN.md §10.4 is now resolved: MDLA first (done), ImplicitGlobalGrid.jl for multi-node next.
MDLA is implemented in ext/MatrixFreeOperatorsMDLAExt.jl behind the _dist_scatter! / _dist_reduce! seam and covers single-node multi-GPU with the adjoint carried through. It cannot go multi-node, and it is CUDA-only. IGG is production-proven GPU-aware MPI halo exchange over a Cartesian MPI topology — exactly our uniform CartesianGrid case, multi-node, CPU+GPU.
This issue is to investigate first, then implement — the investigation gate below is real and may change the shape of the implementation.
Scope
- In: uniform
CartesianGrid, multi-node, CPU + GPU, behind the existing distributed seam, as ext/MatrixFreeOperatorsIGGExt.jl. No new core dependency.
- Out: multi-node AMR (
BlockForest). IGG assumes one fixed uniform Cartesian decomposition; the forest's halo_update! is intra-forest and a distributed forest needs a separate answer. Track that separately if/when it comes up.
- Not adopted: ParallelStencil.jl. We take IGG's halo only.
@init_parallel_stencil(backend, precision, ndims) is module-level global state fixed at load, which is incompatible with keeping GPU support in a weak-dep extension; PS also brings no operator algebra, no linear-solve path, and no AMR. Our hot-stencil escape hatch remains KernelAbstractions @kernel (DESIGN §1.A).
Investigation gate (do this first)
IGG owns its own grid construction (init_global_grid) and array allocation (@zeros). The load-bearing question:
Can update_halo! be driven against MFO-owned Field storage, or is only the topology / MPI-Cartesian-communicator part reusable, with the exchange itself written directly on MPI.jl?
Prototype both far enough to answer it before committing to the extension's shape. If only the topology is reusable, the honest outcome may be "depend on MPI.jl directly and borrow IGG's decomposition logic" — which is a fine result for this issue, just a different one.
Secondary questions for the same prototype:
- How
init_global_grid's global state interacts with partition_grid / prepare_distributed, which already compute local-vs-global ranges. One of the two has to own the decomposition; they must not disagree.
- Whether the adjoint contract survives:
_dist_reduce! must remain the exact transpose of _dist_scatter! across ranks, including the ∂/∂κ scatter-add over owned cells. This is the part with no equivalent anywhere in the IGG/PS ecosystem, and it is the easiest thing to get silently wrong.
Calibrate the expected payoff — do not over-invest in overlap
For the driving workload (reaction–diffusion where a large local ODE dominates each node — cardiac monodomain, ~65 states and ~255 exp per node per step) only the scalar field crosses a boundary while the full state churns over the volume. For a 256³ subdomain that is roughly a 2800:1 byte ratio, so even a naive blocking exchange should cost low single-digit percent of a step.
IGG is being adopted for correctness and multi-node CPU+GPU portability, not because the halo is a bottleneck. Get a correct blocking exchange working and measured before reaching for @hide_communication-style overlap. If a benchmark later shows the exchange is actually material, that is the trigger to revisit — not an assumption to build on.
Done when
🤖 Filed by Claude — Kyle supplied the judgement, I supplied the typing.
Context
DESIGN.md §10.4 is now resolved: MDLA first (done), ImplicitGlobalGrid.jl for multi-node next.
MDLA is implemented in
ext/MatrixFreeOperatorsMDLAExt.jlbehind the_dist_scatter!/_dist_reduce!seam and covers single-node multi-GPU with the adjoint carried through. It cannot go multi-node, and it is CUDA-only. IGG is production-proven GPU-aware MPI halo exchange over a Cartesian MPI topology — exactly our uniformCartesianGridcase, multi-node, CPU+GPU.This issue is to investigate first, then implement — the investigation gate below is real and may change the shape of the implementation.
Scope
CartesianGrid, multi-node, CPU + GPU, behind the existing distributed seam, asext/MatrixFreeOperatorsIGGExt.jl. No new core dependency.BlockForest). IGG assumes one fixed uniform Cartesian decomposition; the forest'shalo_update!is intra-forest and a distributed forest needs a separate answer. Track that separately if/when it comes up.@init_parallel_stencil(backend, precision, ndims)is module-level global state fixed at load, which is incompatible with keeping GPU support in a weak-dep extension; PS also brings no operator algebra, no linear-solve path, and no AMR. Our hot-stencil escape hatch remains KernelAbstractions@kernel(DESIGN §1.A).Investigation gate (do this first)
IGG owns its own grid construction (
init_global_grid) and array allocation (@zeros). The load-bearing question:Prototype both far enough to answer it before committing to the extension's shape. If only the topology is reusable, the honest outcome may be "depend on MPI.jl directly and borrow IGG's decomposition logic" — which is a fine result for this issue, just a different one.
Secondary questions for the same prototype:
init_global_grid's global state interacts withpartition_grid/prepare_distributed, which already compute local-vs-global ranges. One of the two has to own the decomposition; they must not disagree._dist_reduce!must remain the exact transpose of_dist_scatter!across ranks, including the∂/∂κscatter-add over owned cells. This is the part with no equivalent anywhere in the IGG/PS ecosystem, and it is the easiest thing to get silently wrong.Calibrate the expected payoff — do not over-invest in overlap
For the driving workload (reaction–diffusion where a large local ODE dominates each node — cardiac monodomain, ~65 states and ~255
expper node per step) only the scalar field crosses a boundary while the full state churns over the volume. For a 256³ subdomain that is roughly a 2800:1 byte ratio, so even a naive blocking exchange should cost low single-digit percent of a step.IGG is being adopted for correctness and multi-node CPU+GPU portability, not because the halo is a bottleneck. Get a correct blocking exchange working and measured before reaching for
@hide_communication-style overlap. If a benchmark later shows the exchange is actually material, that is the trigger to revisit — not an assumption to build on.Done when
ext/MatrixFreeOperatorsIGGExt.jlimplements_dist_scatter!/_dist_reduce!∂/∂κ) parity against the single-rank resulttest/multigpu(see test(ci): officially instantiate test/multigpu (>=3-GPU distributed tests) #30), skipped by default🤖 Filed by Claude — Kyle supplied the judgement, I supplied the typing.