Skip to content

Mpi wrappers - #1570

Open
GiovanniBussi wants to merge 24 commits into
masterfrom
mpi_wrappers
Open

GiovanniBussi wants to merge 24 commits into
masterfrom
mpi_wrappers

Conversation

@GiovanniBussi

@GiovanniBussi GiovanniBussi commented Nov 5, 2026 •

Copy link
Copy Markdown
Member
Description

This branch contains a few fixes that might be backported, as separate commits. The last commit is the main addition. In short, it allows plumed to choose an MPI implementation at runtime or to inherit from an MD code.

When plumed is compiled with MPI, nothing changes wrt previous versions. When it is compiled without MPI (--disable-mpi or just mpicxx is not available), it in fact builds simple wrappers that can be associated at run time to a specific MPI library. In addition, the PLUMED library embeds a copy of the thread_mpi library from GROMACS 2026.4, which allows using PLUMED emulating MPI with threads when MPI is not available.

The mechanism to choose the MPI library is the following (high priority to low priority):

  • C/C++ code can explicitly inject their implementation. I didn't test this yet, but it is meant to work in GROMACS, so that GROMACS will just pass function pointers to its own MPI implementation to PLUMED at runtime. Other C/C++ code could do the same. This is the safest option
  • You can override this with an env var PLUMED_MPI_WRAPPER pointing to a small implementation library that you can create with plumed mkmpi once you choose a specific MPI implementation. For instance, you can have an env module with serial plumed, and an additional module that you load to link PLUMED to mpich, and another to link to openmpi
  • Last resort, PLUMED will use the embedded thread_mpi implementation. This is useful to run simple analysis within PLUMED that require MPI even on machines where we do not have MPI installed

This is still a draft, but should be working. Regtests already cover most of the new code:

  • all serial builds will now behave as if they had MPI and run all tests (via embedded thread mpi)
  • at the end of two serial builds, I added an installation of opempi and test with an a posteriori set library
  • there is an additional dedicated job which tests corner cases
Target release

I would like my code to appear in release v2.11

Build mklib outputs on the destination filesystem and publish completed libraries by rename. Preserve a usable previous output if compilation or linking fails, and reuse a completed up-to-date output from a concurrent builder. Clarify the existing timestamp-based -n behavior.

The output removal and failed-link publication problems also exist in v2.9 and v2.10. v2.9 has an older mklib implementation and needs adaptation; no backport performed. The standalone publication regression passes. Shell-only changes are outside astyle rules.

Agents: Codex (implementation and review); GPT-6-Luna (workflow and script review).
Allgather local atom counts as int to match the int receive buffer, rather than combining MPI_UNSIGNED and MPI_INT signatures. Check the local count before converting and multiplying by six.

The mismatched call is present in origin/v2.9 and origin/v2.10. This is independent of MPI wrapper support; no backport performed. Verified the send and receive type paths and applied project astyle.

Agents: Codex (implementation and review); GPT-6-Luna (maintained-branch audit).
The pointer overload records a zero receive extent because its size is supplied by recvcounts. Comparing that extent with the send count rejects valid nonempty serial calls. Remove the incorrect check from both serial paths while retaining datatype/count/displacement validation.

Add a make regression that runs without MPI initialization in either build mode and verifies a displaced contribution leaves surrounding elements unchanged. The bug is present in origin/v2.9 and origin/v2.10. No backport performed. Project astyle and diff checks passed; the fresh thread-MPI build is running the regression.

Agent: Codex.
The existing rt-sphere normalizer already masks the undefined longitudinal derivative at the branch boundary and rounds its smooth samples. Round the radial derivative to the same five decimal places, avoiding compiler-dependent last-digit failures while preserving the grid coordinates, bias and boundary checks.

The same normalizer is present in origin/v2.9 and origin/v2.10. This test-only fix is independent of MPI wrappers; no backport performed. Shell syntax and diff checks passed; shell files are outside astyle rules.

Agents: Codex; GPT-6-Luna contributed the original numerical-regression investigation.
Imported-module diagnostics are already filtered from the report. Avoid analyzing their files as direct inputs, including the many asmjit headers, while keeping included headers visible and retaining the complete file list for plumedcheck. Preserve cppcheck configuration exploration and its cache.

The post-analysis-only filtering is present in origin/v2.9 and origin/v2.10; v2.9 uses a different invocation layout and needs adaptation. No backport performed. Shell syntax/diff checks passed. This shell-only change has no astyle-covered files.

Agents: Codex; GPT-6-Luna reviewed fatal diagnostic handling.
Idle OpenMP workers may still execute runtime code after the last kernel is unloaded. Locate a shared OpenMP runtime and retain it with RTLD_NODELETE, closing the extra dlopen reference and allowing the kernel itself to unload. Leave static runtimes unchanged and provide PLUMED_OPENMP_RETAIN_RUNTIME=no for applications managing runtime cleanup themselves.

Replace test-local Python dlclose workarounds with the shared fix. Add runtime-only regression linkage and an isolated baseline/unload test plus 100 threaded calculation cycles. A kernel that cannot unload even with retention disabled skips mapping assertions but still runs the calculations. This addresses the underlying lifetime issue behind PRs #1470/#1473; the lifetime risk exists in v2.9/v2.10 as well. Older namespace/layout and regression differences require review when backporting; no backport performed.

Validation: project astyle passed on all changed C++ files; runtime-only test previously passed CI and is included in the fresh rebased suite. Linux loader behavior requires Linux CI; it cannot be established on this macOS host.

Agents: Codex (implementation and review); GPT-6-Luna (lifetime and regression review).
Let serial-built PLUMED match the host's native MPI through an opt-in generated Plumed.h adapter or an environment-selected provider library/compiler. Keep direct-MPI callers and initialization unchanged. A versioned C-compatible pointer transport preserves native handle bytes at offset zero, including nested communicator forwarding; missing functions throw cleanly.

Embed the isolated, flat GROMACS 2026.4 thread-MPI runtime as the default serial-build backend, with an opt-out. Share rank launching between CLTools and standalone programs, keep serial fallbacks and deferred SELF initialization, and forbid CHDIR while thread ranks are active. Use the existing command API for injection; no kernel symbol-table entry, public object type or existing wrapper implementation changes.

Include mapped-API and provider/lifecycle tests, mechanical MPI test conversions, and serial-build injection CI while preserving all current master jobs. src/mpiwrap/README.md documents design, limits and source-change justifications. Independent maintained-branch fixes precede this commit.

Validation after rebasing on e5e90a2: fresh clang/default-module thread-MPI build, 528 regtests with zero failures (497 not applicable), 15 standalone tests; MPICH/OpenMPI/tMPI generated signature checks; C99/C++98 native adapter checks; registry capacities; reproducible import and host/internal symbol isolation; publication fixtures and workflow/shell syntax. All 114 changed astyle-covered files match project formatting. Real-MPI execution after this rebase awaits the user's external runner or CI.

Keep machine-specific test orchestration, ABI investigation probes and local review checkpoints outside the repository. Retain reproducible generator inputs and maintained CI/regression checks. The cleanup changes no generated code; template generation and parameterized native-adapter checks pass, and removed files have no direct or indirect workflow dependency.

Classify the imported thread-MPI runtime as third-party in the new master warning gate and coverage exclusions. Replaying the reported clang build log changes 19 imported missing-field warnings from a false failure to success; an added mpiwrap warning remains fatal. No C++ source changed.

Agents: Codex (supervision, implementation and final review); GPT-6-Luna workers (implementation, source/workflow audits and validation).
@GiovanniBussi GiovanniBussi added the wip Do not merge label Nov 5, 2026
Comment thread src/mpiwrap/generate.py Fixed
Comment thread src/mpiwrap/generate.py Fixed
Comment thread src/mpiwrap/generate.py Fixed
Comment thread src/mpiwrap/generate.py Fixed
Comment thread src/mpiwrap/generate.py Fixed
Comment thread src/mpiwrap/generate.py Fixed
Comment thread src/core/CLToolMain.cpp Fixed
@carlocamilloni

Copy link
Copy Markdown
Member

This is super to have in combination with the pypi stuff, it make it far more flexible

@codecov

codecov Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.52632% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.55%. Comparing base (9dc724c) to head (276cedf).

Files with missing lines Patch % Lines
src/core/CLToolMain.cpp 44.44% 20 Missing ⚠️
src/main/main.cpp 72.72% 6 Missing ⚠️
src/core/GREX.cpp 50.00% 3 Missing ⚠️
src/generic/EffectiveEnergyDrift.cpp 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1570      +/-   ##
==========================================
- Coverage   87.11%   86.55%   -0.56%     
==========================================
  Files         636      638       +2     
  Lines       80686    81351     +665     
==========================================
+ Hits        70287    70414     +127     
- Misses      10399    10937     +538     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Parallel completion generation invokes mklib.sh --options before src/config/compile_options.sh necessarily exists. The script used to source that file before parsing options, printing an error even though the query eventually returned success. Handle metadata/help before loading compiler settings, and restore the missing early exit for --description. Real library builds still require the configuration and now stop if loading it fails.

Add a regression check to rt15-mklib for clean metadata/help queries without configuration. Reproduced the original diagnostic, then verified actual completion generation in an unconfigured tree under Bash 3 and 5. Both rt15-mklib and rt-mklib-subdir pass. This independent fix applies to master and v2.10; v2.9 already handles metadata before loading configuration. No C/C++ changes; astyle is not applicable.

Agent: Codex (no subagents).
The catch-all previously recorded only the iteration, hiding the cause of intermittent macOS failures. Print standard exception details and errno observed at the catch to stderr, which the regression runner includes in its report. Keep all 5000 iterations and the empty-output reference unchanged.

The stress and signal-handling tests pass locally. A deliberately restricted file-descriptor limit confirms that a failing pipe operation and its error are included in the diagnostic. This does not claim to fix the unresolved CI subprocess failure; the implementation and original test are also present on master.

Agent: Codex (no subagents).
Keep mpiwrap and thread_mpi symbols in their module namespaces, flatten generated interfaces, move focused probes into their regression directories, and remove module-specific lint exceptions. Separate MPI handle declarations from function declarations so TypesafePtr does not include the full generated frontend.

Require the explicit launcher for internal thread-MPI. Discover native providers beside the kernel or build one with the default MPI compiler search when a host supplies a communicator. Reuse the standard C-compatible main for mkmpi executables. Check communicator and descriptor arguments while preserving old-header/kernel combinations, and keep provider-mode custom reductions deferred beyond the initial release.

Consolidate the implementation and its focused test/documentation updates; discard reverted cppcheck experiments. Backportable fixes, conda packaging and GROMACS integration remain separate. Verified generator reproducibility for all 118 functions, whitespace, and all 21 changed astyle-covered files before committing. This regrouping preserves the previously tested source changes.

Agents: Codex (implementation, supervision and history review); GPT-6-Luna workers (implementation, audits and validation of the grouped changes).
Keep plumed as the base package with explicit internal thread-MPI, and add
small plumed-mpi variants for MPICH and Open MPI containing a provider and
MPI-enabled executable. Keep Python packages independent of the MPI
implementation. Test provider discovery, injection, relocation and add-on
removal against unchanged kernel bytes.

Extend the conda matrix to native Linux ARM64 and keep test traffic off
inaccessible CI RDMA devices while honoring explicit UCX overrides. Use the
validated conda-ci master bootstrap, including ARM64 support and compatible
Anaconda upload handling. Document packaging benefits and runtime selection.

Grouped the conda work with its completed bootstrap follow-up. The owner
confirmed conda-ci success and publication to master; its public source
contains ARM64 and standalone-upload support. Bash 3/5 syntax, workflow and
variant YAML, native-host formatting and whitespace checks pass. No PLUMED
astyle-covered source changed in this commit.

Agents: Codex (implementation, supervision and regrouping); GPT-6-Luna
(UCX investigation and test-environment fix).

Copy macOS executables instead of hardlinking them to the package cache.
Concurrent hardlink staging can make dyld select the cache kernel and miss
its environment dependencies. Set no_link for plumed and plumed-mpi and
check executable link counts in fresh test environments. A native
reproducer failed 34/160 hardlinked launches and 0/160 copied launches;
two offline no_link fixture installations also passed. Full package
validation remains for CI. The base no_link rule is a v2.9/v2.10 backport
candidate. Agent: Codex (additional investigation and fix).
Inject the initialized host implementation before PLUMED MPI setup, preserving native legacy behavior and the old-kernel multi-rank thread-MPI rejection. Use the standard top-level Plumed.h from both integration and test helper, leaving the bundled GROMACS header untouched. Keep the original patch comments and standard cleanup machinery.

Respect GROMACS configuration guards for the three optional long-long datatype constants. Cover their presence and absence in C99/C++98 host-adapter checks. Document the integration and its focused validation.

GROMACS 2026.0 through 2026.4 patch/revert checks pass in default and --include modes with byte-identical restoration. Fresh patched 2026.4 tMPI rank/hybrid force checks and clean unpatched build/runtime checks pass. Earlier user-run MPICH/Open MPI 1/2/4-rank and hybrid calculations pass. After regrouping, generator checks and native adapter/header checks pass for MPICH, Open MPI and pinned tMPI. Plumed.h matches astyle; GROMACS patch files retain upstream formatting.

Agents: GPT-6-Luna (implementation and fresh build/runtime validation); Codex (review, corrections, independent checks and regrouping).
Preserve upstream history and incorporate the new checkpoint regression tests before their replica-log correction. Agent: Codex (history integration and verification).
Add driver --log FILE using the existing setLogFile command, with the
usual replica suffix before the filename extension. Convert four new
checkpoint regtests to inspect those files instead of merged stdout,
retaining sorted checkpoint diagnostics and all data-file comparisons.
Remove only redundant unprefixed driver startup lines from references.

Concurrent stdout collection is not a reliable test oracle for either
thread-MPI or real MPI. Leave OFile write behavior unchanged.

All four tests pass twenty consecutive internal thread-MPI runs.
Single-rank --log and default stdout behavior also pass. An audit found
no matching combined-stdout comparisons among 115 MPI configs in v2.9
and 120 in v2.10; these checkpoint cases are new in v2.11. Shell syntax,
whitespace and project astyle checks pass.

Agent: Codex (investigation, implementation and validation).
@GiovanniBussi

Copy link
Copy Markdown
Member Author

News in 3375063

  • Injection is now tested locally: GROMACS 2026.4 passed with thread-MPI, MPICH, and Open MPI.
  • plumed mkmpi --executable can build an MPI-enabled executable that initializes MPI and injects it into a serial PLUMED kernel.
  • Discovery has expanded: when a native communicator is supplied without injection or an explicit provider, PLUMED first looks for an adjacent libplumed-mpi-provider library, then tries building one with an available MPI compiler. This allows having a plumed serial package and a plumed-mpi package side by side, the latter only generating the compatibiliy library and the executable plumed-mpi
  • Internal thread_mpi is not anymore a fallback, it is now only used when launching plumed. For example, four ranks:
plumed --tmpi-threads 4 driver --plumed plumed.dat --ixyz trajectory.xyz

This requires a serial-built kernel with embedded thread-MPI enabled.

I will make a new review before merging but I think this is basically complete. I also plan to locally test LAMMPS and AMBER for MPI injection

Comment thread src/main/main.cpp Fixed
Check pthread_create when thread-MPI is enabled and retain any required pthread library in the generated kernel link flags. Use PLUMED_SEARCH_LIBS to preserve --disable-libsearch behavior, and diagnose missing thread support with the option to disable the embedded runtime.

The Linux x86_64 and aarch64 manylinux2014 wheel builds failed with missing pthread symbols when OpenMP was disabled. Newer libc environments masked the dependency. Configure probes for separate, missing and disabled pthread support pass. A fresh macOS wheel-backend runtime build without OpenMP, relocation and four-rank driver smoke pass. Regenerated configure reproducibly with Autoconf 2.69. No astyle-covered source changed; Linux wheel confirmation remains for CI.

Agent: Codex (CI investigation, implementation and validation).
Copy Open MPI into fresh macOS test environments before installing the PLUMED add-on, avoiding dyld resolving prte dependencies from a hardlinked package-cache location. Keep normal installation for both PLUMED packages so their no_link assertions remain meaningful.

Use Open MPI's ob1 PML and TCP/self BTLs for packaging smoke tests, alongside the existing UCX software-transport restriction. The ARM log fails inside Open MPI's nonblocking collective during Comm_dup; CI must confirm whether selecting portable transports resolves it. Print the runtime version for subsequent failure analysis.

Validation: shell syntax and diff checks passed; an offline copied Open MPI environment has a single-link prte executable and passed 20 loader/version checks. Full native MPI startup and the ARM runner still require CI validation. No files covered by astyle changed.

Agent: Codex.
Merge bbfb298 without rewriting the published MPI branch. Review automatic merges in Driver, PlumedMain, EffectiveEnergyDrift and the PLUMED action.

Validation: all 25 changed source/header files covered by project astyle rules are already formatted. Preserve upstream reference-output whitespace.

Agent: Codex.
The new GREX and MaxEnt MPI checkpoint tests counted restored-state messages in merged stdout. Concurrent replicas can interleave PLUMED prefixes, making counts differ while all restart data still match. Write driver logs per replica and read checkpoint messages and warnings from those files.

Normalize BSD/GNU uniq count padding to the existing reference format; keep all numerical comparisons and reference files unchanged.

Validation: merged code rebuilt with OpenMP; each test passed 20 times with four internal thread-MPI ranks, ten runs with one OpenMP thread and ten with two. Both BSD and GNU uniq match the unchanged references. Shell syntax and diff checks passed. No changed files are covered by astyle.

Agent: Codex.
Comment thread src/thread_mpi/reimport.py Fixed
Comment thread src/thread_mpi/winthreads.cpp Fixed
Comment thread src/thread_mpi/winthreads.cpp Fixed
Comment thread src/thread_mpi/winthreads.cpp Fixed
Comment thread src/thread_mpi/winthreads.cpp Fixed
Comment thread src/thread_mpi/scatter.cpp Fixed
Comment thread src/thread_mpi/errhandler.cpp Fixed
Comment thread src/thread_mpi/comm.cpp Fixed
Comment thread src/thread_mpi/collective.cpp Fixed
Comment thread src/thread_mpi/collective.cpp Fixed
Comment thread src/thread_mpi/barrier.cpp Fixed
Extract only regular archive files into the importer's temporary directory. Reject absolute paths, parent traversal, links and special files before writing, including paths escaping through an existing directory symlink. Keep compatibility with Python versions lacking tarfile extraction filters.

Use an explicit while loop when --tmpi-threads consumes its following argument, avoiding modification of a for-loop counter inside the loop body. Parsing behavior is unchanged.

Validation: malicious-archive regression tests, reproducible import check against pinned GROMACS, rebuilt thread-MPI CLI/benchmark/CHDIR checks, malformed/duplicate/conflicting option checks, Ruff and diff checks passed. Applied project astyle to CLToolMain.cpp.

Agents: Codex implemented and tested; GPT-6-Luna audited PR diagnostics.
…positive

Postprocess CodeQL SARIF before uploading it, retaining diagnostics for security issues in imported thread-MPI and all diagnostics in its Python importer. Remove only commented-out-code notes in imported C++ files, which must remain reproducible from upstream.

Exclude the constant-comparison finding on main.cpp's specific API-version guard: getApiVersion writes through the generic C API pointer, a side effect CodeQL cannot model. Match the source statement and path so other comparison findings remain visible. Keep the C-compatible launcher unchanged.

Validation: filter regression tests verify security findings, importer diagnostics and other comparisons remain enabled and report metadata is preserved. Importer/CLI tests, native Open MPI host --no-mpi injection check, Ruff, YAML and diff checks passed. No files covered by astyle changed. CI must confirm the CodeQL rerun.

Agents: Codex implemented and tested; GPT-6-Luna audited PR diagnostics.
Build one serial OpenMP PLUMED artifact per OS, then validate native MD MPI injection with Open MPI, MPICH and GROMACS thread-MPI. Include non-MPI AmberTools and LAMMPS builds, pinned engine sources, reversible minimal host patches, native rank checks and analytic bias and atomic-force comparisons.

Run the expensive matrix only through workflow_dispatch; preserve all existing CI jobs and triggers. All 20 jobs passed on Linux and macOS, including the four serial engine jobs. Both serial engine builds also passed local Apple Silicon numerical checks, including LAMMPS with one and two OpenMP threads.

Collaborators: Codex and GPT-6-Luna.
The Intel injected-MPI run reported different COLVAR files but testclean then removed the evidence. Print column names and unified diffs to stderr while retaining the existing exact comparisons and restart_check reference output.

Validated the focused four-rank tMPI test and matching/mismatching synthetic outputs. The Intel mismatch itself still requires a CI reproduction.

Collaborators: Codex and GPT-6-Luna.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wip Do not merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants