Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/content/docs/building.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,10 @@ requests that touch `tools/container/` or the workflow. `tools/container/smoke-t
checks the monoprop image before it is pushed. It never imports monoprop, because the CI
machine's CPU may lack the instructions `-march` enables, so check a new image on the
target machine as well (see [MareNostrum5](/clusters/marenostrum5#check-the-image)).
Being a source build, the image has a single MPI backend, for the ABI family of the base
image's Open MPI; the smoke test checks that mpi4py loads that same family, without which
propagators given a communicator raise
[MPIAbiMismatchError][monoprop.exceptions.MPIAbiMismatchError].

To reproduce the build locally:

Expand Down
6 changes: 4 additions & 2 deletions docs/content/docs/clusters/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ title: HPC clusters
description: Running monoprop on HPC systems from its MPI-enabled container image.
---

Some HPC systems give their login nodes no outbound network, so monoprop cannot be
installed there with `pip`. For those, every release, the `main` branch and pull requests that
Where `pip` works, `pip install "monoprop[mpi]"` installs wheels that run on the cluster's own
MPI, if it is from the MPICH family (MPICH, Intel MPI, MVAPICH, Cray MPICH) or Open MPI and
not older than the versions listed in [Enabling MPI](/features/parallelism#enabling-mpi). Some HPC systems, however, give their login
nodes no outbound network, so monoprop cannot be installed there with `pip`. For those, every release, the `main` branch and pull requests that
change the container recipes publish an MPI-enabled container image to the GitHub Container Registry:

```text
Expand Down
22 changes: 16 additions & 6 deletions docs/content/docs/clusters/marenostrum5.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,28 @@ rsync -P monoprop_<tag>.sif <user>@<mn5-host>:<project-dir>/

## Check the image

Get an interactive allocation on a compute node, then check that monoprop imports and sees
MPI on two ranks:
Get an interactive allocation on a compute node, then check that monoprop runs a propagator
over MPI on two ranks:

```bash
salloc --nodes=1 --account=<account> -q gp_debug --exclusive --time=00:10:00
module load singularity
srun -n 2 --mpi=pmix singularity exec monoprop_<tag>.sif \
python3 -c 'import monoprop; print(monoprop.__version__, monoprop.has_mpi)'
srun -n 2 --mpi=pmix singularity exec monoprop_<tag>.sif python3 -c '
import monoprop
from mpi4py import MPI
comm = MPI.COMM_WORLD.Dup()
operator = monoprop.PauliOperator({monoprop.Pauli("Z", (0,)): 1.0}, 2)
propagator = monoprop.PauliPropagator(operator, [0], cutoff=2, comm=comm)
print(comm.Get_rank(), monoprop.__version__, "MPI backend loaded")
del propagator
comm.Free()'
```

Both ranks should print the image's version and `True`. This is the check CI cannot run:
the CI machines may lack the Sapphire Rapids instructions the image is compiled for.
Each rank should print its rank, the image's version and `MPI backend loaded`. Building a
propagator with a communicator loads monoprop's MPI backend for the MPI library mpi4py uses,
so this also checks that the image's mpi4py and monoprop agree on it; if they did not, it would
raise [MPIAbiMismatchError][monoprop.exceptions.MPIAbiMismatchError]. This is the check CI
cannot run: the CI machines may lack the Sapphire Rapids instructions the image is compiled for.

MN5's Slurm offers munge authentication to PMIx, which the container's PMIx is built
without. The image sets `PMIX_MCA_psec=native`, so the ranks use PMIx's native
Expand Down
30 changes: 30 additions & 0 deletions tools/container/smoke-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,36 @@ echo "$mpi4py_library"
[[ "$mpi4py_library" == *"Open MPI v${ompi_version}"* ]] \
|| fail "mpi4py did not load the image's Open MPI v$ompi_version"

echo "== MPI ABI of monoprop's backend"
# monoprop loads its MPI extension for the ABI family mpi4py uses, and raises if it was not
# built for that family. Both sides are read from files, so monoprop is still not imported.
abi_check="$(python3 - "$package_dir" <<'PY'
import ast
import pathlib
import re
import sys

import mpi4py

mpi4py.rc.initialize = False
from mpi4py import MPI

source = (pathlib.Path(sys.argv[1]) / "_mpi_abis.py").read_text()
built = next(
ast.literal_eval(node.value)
for node in ast.parse(source).body
if isinstance(node, ast.AnnAssign) and getattr(node.target, "id", "") == "ABIS"
)
variant = re.match(r"MPI\.(mpich|openmpi|mpiabi)\.", pathlib.Path(MPI.__spec__.origin).name)
print(" ".join(built), variant[1] if variant else "unknown", sep="|")
PY
)"
built_abis="${abi_check%|*}"
mpi4py_abi="${abi_check#*|}"
echo "built for: ${built_abis:-none}; mpi4py uses: $mpi4py_abi"
[[ " $built_abis " == *" $mpi4py_abi "* ]] \
|| fail "mpi4py uses the $mpi4py_abi MPI ABI, but monoprop was built for: ${built_abis:-none}"

echo "== Open MPI build"
grep -q 'MCA pml: ucx' <<< "$ompi_details" || fail "Open MPI was built without the UCX PML"
# The base image builds PMIx into /usr/local/pmix; srun --mpi=pmix talks to it.
Expand Down
Loading