Repository navigation
perf: reduce solver overhead and add opt-in L-BFGS-B strategies - #132
Conversation
- Retain accepted Wolfe evaluations and add opt-in fused trials - Reuse TNC, L-BFGS, and line-search working buffers - Batch independent columns in L-BFGS-B compact Gram updates - Add regression coverage, benchmarks, and solver documentation
Stage columns in a padded scalar buffer and reuse residual probe storage, preserving stencil arithmetic, callback counts, and output on errors. Add regression coverage across dense backend versions and document benchmark findings. Retain the existing parallel path.
Reuse sequential Jacobian kernels and one scratch buffer for finite-difference range maps when Rayon has one worker. Add vector-clone accounting and scratch regression tests. Preserve gradient staging and multi-worker scheduling after benchmark evaluation.
Add inverse two-loop and single-coordinate reduced solves with native fallbacks, preserving default behavior and numerical safeguards. Cover dense backends, checkpoint continuation, and reference parity; add matched kernel and whole-solve benchmarks.
Add opt-in signed-column and scaled compact models, dimension-aware reduced solves, InteriorFirst, and projected L-BFGS with retained free-coordinate curvature. Defer unused model factorization. Preserve existing defaults and add backend, numerical-reference, checkpoint, and failure-recovery coverage.
jolars
left a comment
There was a problem hiding this comment.
Thanks! Looks good, just one small nit.
| pub fn with_compact_model(self) -> model_strategy::ModelLbfgsb<V, F, S> { | ||
| model_strategy::ModelLbfgsb::new(self) |
There was a problem hiding this comment.
When callers use Executor::from_start, selecting .with_compact_model() fails with E0277 because the returned ModelLbfgsb does not implement InitialState. The existing Lbfgs supports this constructor, and the wrapper still needs only a starting point. Forward InitialState<V, State = FirstOrderState<V, F>>, as already done for ProjectedLbfgs, so callers can select the compact model without constructing the state manually.
There was a problem hiding this comment.
Oh right. My mistake, I'll fix that up. Cheers!
|
Btw, can you check the website failure? I see: Maybe you can either replace that URL with a permanent link or add it as an exception to the url checker. |
|
For sure. Forgot to make it public. Don't need the link in there anyhow. Your project is a much better home for the work. Thank you. |
|
Thanks for the fixes! |
Solver buffer allocation, compact-model work, and repeated derivative evaluations add overhead to bounded quasi-Newton solves. This PR reduces that work and adds opt-in L-BFGS-B model strategies and projected L-BFGS searches. Existing defaults and checkpoint layouts are preserved; no dependency, version, or MSRV changes are included.
Changes
ModelDirection::ProjectedChordis the single chord-policy name.with_projected_search(). Form curvature pairs from actual accepted displacements, support retention or reset-on-mask-change, and serialize the preceding mask for exact continuation.Recorded performance
These figures were checked by recomputing summaries from the latest recorded raw runs on November 5. Baseline: Basin
a673d9f. These are native f64/Vec measurements with combined callbacks.Ratios are median previous default time / method time over common target successes, shown as cheap / synthetic-expensive callbacks. Hits mean the first observed normalized objective gap <= 1e-8, including rejected probes, and do not imply native convergence or returned-point accuracy. Misses and failures remain in the success denominators.
Default current and baseline L-BFGS-B both reach 170/206 targets with identical recorded numerical results and callback work. Projected methods disable relative-cost stopping while the baseline retains it: these ratios measure solver effectiveness under different policies, rather than isolated implementation speedups.
Retention shows no universal benefit: reset-on-mask-change reaches 172 ray and 171 chord targets, versus retained 171 and 170; both Armijo settings reach 167. Median callback ratios are one and timing differences are within about one percent. All projected settings and references reach 7/8 targets on the additional starts. Small timing differences are inconclusive.
The latest final TNC run records 194/206 observed targets for baseline and ordinary/fused current Basin. Fused TNC returns 191/206 points meeting the target. Its target-time ratios are 1.200x / 1.373x versus baseline, with a median target-callback ratio of 0.714x versus baseline. Fusion remains opt-in; these figures apply to combined-callback workloads.
Benchmark protocol and audit
The projected-search run contains 28,248 measured solves: 206 scenarios plus eight additional starts, two callback costs, separate total-only/target-logging passes, and three repeats, excluding warmups. The earlier final TNC/model run contains 30,816 solves. Reanalysis of both raw JSONL sets reproduces their stored summaries exactly. Recorded manifest and projected-run executable hashes were checked.
All contestants use Rust 1.99.1, thin LTO and one codegen unit, fixed dependency locks, history capacity 10, a 20,000 raw-callback guard, and a 5,000-iteration limit. Thread counts are one; CPU affinity is not pinned. Expensive callbacks add 2,000 synthetic work units. Baseline/current process order alternates; candidate and reference methods are shuffled together.
Projected methods use projected-gradient tolerance 1e-6, gradient-only stopping, and relative global curvature tolerance 1e-10. Armijo uses 40 trials, c1=1e-4 and contraction 0.5. More-Thuente uses 20 trials, c1=1e-3, c2=0.9 and relative bracket tolerance 0.1. Basin retains its rounding/recovery safeguards. These previously inspected scenarios provide regression evidence, not unseen generalization tests or confidence intervals.
The audit checks repeat/pass consistency, finite feasible returned points, and callback guards. A freshly rebuilt final-source harness also reproduces all numerical and work fields across 4,280 cheap-callback records (206 scenarios plus eight starts, all ten methods and both passes); its timings are not substituted into the recorded performance comparisons. Published website benchmark data are unchanged.
Validation
chained_rosenbrock_6dfailure was excluded and separately reproduced on the baseline.