Precompile a mass matrix DAE in the OrdinaryDiffEqBDF workload#3966
Conversation
The BDF workload only precompiled pure-ODE problems, so the algebraic variable detection and DAE initialization solve were never covered. Every mass matrix FBDF user paid that inference on their first solve. Adding an index-1 Robertson mass matrix problem takes the first solve of an unrelated mass matrix DAE from 4.2s to 0.33s, at the cost of ~5.5s of package precompile time. Gated behind a PrecompileMassMatrixDAE preference so it can be turned off alongside the existing specialization toggles. Measured on Julia 1.12.6, first solve of a Robertson DAE distinct from the one in the workload: before: 4.21s, 3.94s after: 0.32s, 0.34s, 0.34s Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
CI failure triage5 jobs are red. All 5 are pre-existing on master and none are attributable to this diff, which only touches
Master's own recent Follow-ups filed / suggested
|
Triage update — 2 further failures, both also pre-existingTwo more jobs went red since the previous comment. Both verified as pre-existing, so the count is now 7/7 not attributable to this diff.
Worth stating explicitly since this PR does add two imports: neither
Summary
The two QA failures share one root cause and would be fixed together by promoting the |
Releases unreleased changes on master across four sublibraries: - OrdinaryDiffEqCore 4.7.1 -> 4.8.0 (minor: restores isdiscretecache public API (#3907); also recompute non-lazy interpolation stages after a truncated step (#3964)) - OrdinaryDiffEqBDF 2.3.1 -> 2.3.2 (precompile a mass matrix DAE in the workload (#3966)) - OrdinaryDiffEqExtrapolation 2.3.0 -> 2.3.1 (drop stale BaseThreads/Sequential imports (#3945)) - OrdinaryDiffEqRosenbrock 2.4.1 -> 2.4.2 (SIMD-fuse RosenbrockCache stage loops; document public HybridExplicitImplicitRK (#3938)) Claude-Session: https://claude.ai/code/session_01SFmcAmLrGPrGtzwP333mX8 Co-authored-by: ChrisRackauckas-Claude <accounts@chrisrackauckas.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Please ignore until reviewed by @ChrisRackauckas.
Problem
OrdinaryDiffEqBDF's@compile_workloadonly precompiles pure-ODE problems (lorenz). Nothing in it reaches the algebraic variable detection or the DAE initialization solve, so every mass matrix FBDF user pays that inference on their first solve — even though DAEs are one of the main reasons to reach for BDF.This came out of a broader TTFX investigation into stiff ODE solves. The interesting part of that investigation was a negative result:
using OrdinaryDiffEqinvalidates ~3300 MethodInstances, but the FBDF solve path's pkgimage survives them intact (staleinstances= 0 on the ODE path). First-solve cost is almost entirely precompile coverage misses, not invalidation. This PR closes one such gap.Change
Adds an index-1 Robertson mass matrix problem to the workload, gated behind a new
PrecompileMassMatrixDAEpreference (defaulttrue) so it can be disabled alongside the existing specialization toggles.Measurements
Julia 1.12.6, first solve of a Robertson mass matrix DAE distinct from the one in the workload (so this measures genuine cache reuse, not an exact-signature hit):
Cost:
OrdinaryDiffEqBDFprecompile time goes from ~12s to ~17.5s.Non-DAE path is unaffected (lorenz FBDF first solve stays at 0.0016s).
Solution correctness cross-checked against
Rodas5Patabstol=reltol=1e-10: max component difference 1.8e-10, algebraic constraint residual exactly 0.Tests
ODEDIFFEQ_TEST_GROUP=Coreon this branch vs. clean master — identical results:The
BDF Inference Testserror is pre-existing on master (248c2fd6f), not introduced here — it reproduces on a clean checkout with this change stashed. It is an@inferredfailure onbuild_nlsolverwithNonlinearSolveAlg(TrustRegion(...))atlib/OrdinaryDiffEqBDF/test/inference_tests.jl:19, and is being investigated separately.Runic-formatted.
🤖 Generated with Claude Code