Conversation
With one solver the solve still ran inside a one-thread parallel region, so OpenMP code the model calls during the solve (a CasADi external function, for example) ran nested at level 1. It then took the nested-level ICVs, so under OMP_NUM_THREADS=8,1 its regions got one thread instead of eight. A single solver now runs directly on the calling thread; several solvers keep the self-scheduled team. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5837 +/- ##
=======================================
Coverage 98.09% 98.09%
=======================================
Files 346 346
Lines 35354 35354
=======================================
Hits 34680 34680
Misses 674 674 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
aabills
marked this pull request as ready for review
October 2, 2026 22:50
Contributor
|
| Project | PyBaMM |
| Branch | fix/idaklu-single-solver-openmp |
| Testbed | bare-metal |
🐰 View full continuous benchmarking report in Bencher
⚠️ WARNING: Truncated view!The full continuous benchmarking report exceeds the maximum length allowed on this platform.
This branch has not been deployed
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.
Description
IDAKLUSolverGroup::solveruns its solvers under#pragma omp parallel num_threads(team_size). That's also true when there is only one solver, the usual case, so a single solve ran inside a one-thread parallel region. OpenMP code that the model calls during the solve, such as a CasADi external function, therefore ran nested atomp_get_level() == 1and took the nested-level ICVs instead of the top-level ones.The most visible effect shows up with a per-level
OMP_NUM_THREADSlist. UnderOMP_NUM_THREADS=8,1, an OpenMP region in a CasADi external called from the solve got 1 thread instead of 8. The8,1setting asks for a team of 8 at the top level, and that's the level the external is logically at.Fix. The team body becomes a lambda,
run_thread(thread). Whenteam_size == 1it's called directly on the calling thread, with no parallel region. Otherwise it runs under the same#pragma omp parallel num_threads(team_size)as before. The multi-solver path is unchanged.Reproducer
A CasADi external, built with
-fopenmpagainst the same libomp aspybammsolvers, is used both as the model's RHS and as an output variable. It reports what OpenMP looks like from inside the solve:The probe is passed to
create_casadi_solver_groupas an output variable, withnum_solvers=1andnum_threads=1. Results on macOS arm64 with Homebrew libomp:omp_get_level()in solvemainOMP_NUM_THREADS=8,1mainOMP_NUM_THREADS=8,1OMP_NUM_THREADS=8,2mainOMP_NUM_THREADS=8,2With default settings the per-region overhead was the same either way: about 23 µs for a small
parallel forat 8 threads, both inside and outside a solve. This PR is therefore about OpenMP semantics, not speed. A nested setting meant for code that runs inside the external's regions no longer gets applied to the external itself.Type of change
Bug fix. There's an entry under
## Bug fixesin CHANGELOG.md.Tests
No new test yet. The reproducer needs an OpenMP-compiled shared library loaded as a CasADi external, and the test suite has no existing way to build one. Pointers to an acceptable way to cover this in CI would be welcome.
The existing
test_parallel_solver_group_uses_multiple_solverscovers the multi-solver path, which still opens the parallel region.Important checks:
packages/pybamm/tests/unit/test_solversandpackages/pybamm/tests/integration/test_solvers(467 passed, 95 skipped) andpackages/pybammsolvers/tests(64 passed). The fullnox -s testshasn't been run.nox -s doctestsnot run (no documentation changes)🤖 Generated with Claude Code