Thread control#
femorph-solver integrates with threadpoolctl to cap BLAS / OpenMP
thread pools inside every solver. Without a cap, NumPy / SciPy
inherit the BLAS backend’s default — often the host physical core
count — which oversubscribes the CPU on shared runners and makes
dense LAPACK paths 5-10x slower from scheduler contention.
Three levers, in resolution order:
Per-call kwarg. Every solver accepts
thread_limit: int | None = None:solve_modal(K, M, prescribed={}, n_modes=10, thread_limit=4)
An explicit integer caps threads for that call only.
Process-wide default. Set once and every subsequent solve picks it up:
import femorph_solver femorph_solver.set_thread_limit(4)
Environment variable.
FEMORPH_SOLVER_NUM_THREADS=<int>seeds the process-wide default at import time. Convenient for CI / container entrypoints.
Passing thread_limit=None (the default) defers to the
process-wide default; if that’s also unset, no cap is applied and the
backend decides.
See femorph_solver.set_thread_limit() and
femorph_solver.get_thread_limit() in the API reference.