Add adaptive Jacobian reuse to first-order solvers#1072
Add adaptive Jacobian reuse to first-order solvers#1072ChrisRackauckas-Claude wants to merge 14 commits into
Conversation
|
Implementation scratchpad for commit
Benchmarking showed wins for expensive dense/sparse factorizations but overhead and policy sensitivity on small/problem-library cases, so the solver default remains exact Newton. |
6dd2157 to
99348eb
Compare
|
Published final stacked head Safety and history checks:
Final local outputs include:
CI is now running on the combined stack, which includes both focused prerequisite fixes before the unchanged feature commit. |
99348eb to
63e043b
Compare
|
Final-stack update at
The PR description now records the actual stack, benchmark/default decision, baseline-failure investigations, and observed validation. Refreshed combined-stack CI is running. |
Avoid temporary reshape wrappers for dense AutoForwardDiff Jacobians and same-buffer restructure calls, with direct warmed allocation regressions. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
63e043b to
ed4d653
Compare
|
Published rebuilt combined head Before replacing the old
New local evidence includes:
The superseded combined CI run finished 90 successful, 3 skipped, and 4 failed. Two Ubuntu failures were the already-audited Brown unexpected-pass behavior. The two macOS failures were the allocation issue addressed by the cached destination. Fresh CI is now running; Apple ARM must pass before the cross-platform fix is claimed. |
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
ed4d653 to
5b9e07d
Compare
|
Published rebuilt combined head Safety audit immediately before publication:
The prior Apple prerelease job is important negative evidence: it still measured exactly 772.0/400.0 B per sweep/arclength step after the cached Jacobian destination. The remaining allocation came from constructing a complete solution for every interior corrector. The new helper runs those correctors to completion in the reused cache; ordinary solve results, anchors, landings, and failure originals are unchanged. Final local evidence includes cache-only 0 B with same-cache identity, end-to-end 0.0/0.0 B per step, Base Core on Julia 1.12 and 1.10, all 39 continuation files, Base QA 18/18, ForwardDiff cache reinit 1/1, Runic 1.7, and |
|
Final-tree local integration update for
Fresh Apple ARM Core checks remain queued and are still required for the cross-architecture allocation claim. |
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
|
Apple ARM prerelease result on feature head
|
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
|
Diagnostic rerun correction at
|
|
Apple allocation profile root cause and upstream follow-up:
|
|
Upstream Apple-silicon validation update for LinearSolve #1099:
These are direct LinearSolve macOS tests of the fixed Apple Accelerate path. They do not replace the required NonlinearSolve end-to-end continuation rerun. The combined PR therefore still makes no downstream cross-platform allocation claim until #1099 is merged/released and this branch is retested against that dependency. |
|
Fresh exact-graph validation of the stacked #1057 prerequisite:
|
Prompt
Add OrdinaryDiffEq-style Jacobian reuse heuristics to NonlinearSolve's first-order methods, benchmark standalone nonlinear-solver behavior before choosing a default, and keep OrdinaryDiffEq's separately owned Jacobian/iteration-matrix lifecycle unaffected.
Summary
JacobianReuse(max_age = 10, max_residual_ratio = 1)policyjacobian_reuse = trueor a configured policyreinit!; explicitstep!(...; recompute_jacobian = true/false)decisions take precedenceNewtonRaphson already constructs
GeneralizedFirstOrderAlgorithm, so no second solver type is needed: the existing solver becomes adaptive only when the policy is supplied.Prerequisite stack
The published branch is stacked on upstream master
60736b5b6, in this order:The feature stack has 12 commits.
git range-diffmarks every feature patch equal to the previously published stack; the new #1061 follow-up was moved beside its prerequisite.git diff --exit-codeconfirms that the reordered feature head is tree-identical to the locally tested pre-reorder tree. Two temporary test-only commits add failure-only allocation profiling for the unresolved Apple result and declare theProfilestdlib in the existing root test target. Every commit retains the required Chris Rackauckas co-author trailer.Benchmark and default decision
BenchmarkTools medians, one BLAS thread, warmed solves:
For the sparse Brusselator, age 5 reduced Jacobian evaluations 4→3 and factorizations 3→2, while nonlinear steps increased 3→7. Policy sensitivity is real: the age-5 problem-library run regressed to 3.36 ms, and the n=2 case showed pure overhead. Matrix-free runs had identical Jacobian/factorization counts and inconsistent timing noise, so no matrix-free benefit is claimed.
Therefore exact Newton and the default polyalgorithm remain unchanged.
jacobian_reuse = trueselects a conservative age-10 bounded policy; users with expensive concrete Jacobians can tune age and residual ratio.OrdinaryDiffEq isolation
OrdinaryDiffEqNonlinearSolve owns distinct
JandWrefresh decisions, including mass-matrix orγdtchanges and convergence history across time steps. Its explicitrecompute_jacobianBoolean overrides this standalone policy, whilereinit!resets standalone reuse state.The Robertson FBDF/TRBDF2 Jacobian-reuse test passed 8/8. Repeating both methods with
NewtonRaphson(jacobian_reuse = true)remained accurate and successful; FBDF observed 10 Jacobian calls versus 115 W builds, and TRBDF2 observed 7 versus 129.Apple ARM allocation follow-up
The first #1061 implementation depended on scalar replacement of temporary array wrappers. Caching the fixed-shape ForwardDiff destination removed that wrapper construction but did not resolve the combined Apple result: macOS prerelease still measured exactly 772.0 B/step for sweep and 400.0 B/step for arclength.
The cache-only follow-up factors generic cache iteration from solution construction. Sweep and arclength consume the reused cache directly for interior attempts; ordinary
solve!, anchors, final landings, and reported failure originals still build complete solutions. Specialized polyalgorithm, no-init, and ForwardDiff caches keep their existing full-solution fallback.Fresh Apple ARM prerelease CI on feature head
5b9e07da1disproved the proposed root-cause attribution: the direct cache-only solve and other fast-path checks passed, but the end-to-end slopes remained exactly772.0and400.0B/step. The remaining allocations are therefore outside_solve_without_solution!. Current test-only headcfb8e2d18profiles allocation types and NonlinearSolve stack sites only when the unchanged strict slope assertions fail; the follow-up declaresProfilein the existing root[extras]/[targets]test environment. The completed stable-macOS profile identifies the dominant allocator upstream in LinearSolve'sAppleAccelerateLUFactorization: repeatedLU{Float64, Matrix, Vector{Int32}}construction contributed 25,984 bytes / 812 allocations in sweep and 11,648 bytes / 364 allocations in arclength, with additional tuple,Ref, range, and keyword-NamedTupleallocations. The profiled slopes were 957.28 and 496 bytes per step.A focused upstream fix is now draft LinearSolve #1099. It reuses private factor, pivot, and status workspaces and adds direct macOS LTS/stable/pre allocation coverage. Its Apple-silicon CI now passes on Julia 1.10, 1.12, and 1.13: the refactorization-reuse suites passed 55/55, 59/59, and 59/59, while each mixed-precision suite passed 19 tests with its one pre-existing broken expectation. No cross-platform allocation fix is claimed in this downstream PR until #1099 is merged/released and the continuation profile is rerun against that dependency.
Validation
Feature-stack head:
5b9e07da11ab32181e86824ef0c33051f3989a29. Current test-only diagnostic head:cfb8e2d18e7fc2df972beab9c0bf5959acfa987d.Final-tree local runs:
0B and same-cache identity; sweep/arclength0.0/0.0B per step--check --diff .andgit diff --check: passedThe Jacobian-reuse feature patch itself is unchanged by range-diff. Its prior integrated validation passed adaptive reuse 64/64, General NLLS 472/472, NewtonRaphson 309/309, TrustRegion 1176/1176, PseudoTransient 51/51, LevenbergMarquardt 33/33, EisenstatWalker 27/27, sparse 12/12, mass-matrix 27/27, structured 16/16, and operator-Jacobian 14/14. The full final-tree FirstOrder Core run has since repeated these feature totals successfully. Fresh combined CI passed 78 checks before the Apple prerelease Core lane reproduced the unchanged
772.0/400.0B/step failure. The exact diagnostic test passes locally on Julia 1.13.0-rc1 x86_64; the first diagnostic CI attempt exposed only the missing isolated-test declaration forProfile, now corrected at the current head. The completed profiling rerun isolated the remaining Apple allocations to LinearSolve's Accelerate LU wrapper construction; the downstream retest is pending LinearSolve #1099.The canonical root Core run on this EPYC 7502 host stops before continuation at the separately audited Brown bad-Broyden
@test_brokenunexpected pass. The identical dependency/source graph fails on another EPYC model; this platform-sensitive clean-base issue remains tracked in #1056. No platform gate or weakened expectation is included.No test threshold, tolerance, skip, broken-test designation, documentation failure mode, or unrelated public API was changed.