Add SupernodalLUFactorization (pure-Julia Schenk–Gärtner supernodal LU via PurePardiso.jl)#1102
Add SupernodalLUFactorization (pure-Julia Schenk–Gärtner supernodal LU via PurePardiso.jl)#1102ChrisRackauckas-Claude wants to merge 4 commits into
Conversation
New sparse LU algorithm backed by PurePardiso.jl (hard dependency, following the PureKLU precedent): the supernodal left-right-looking LU method of O. Schenk and K. Gartner (FGCS 20(3) 2004; ETNA 23 2006) -- supernodal BLAS-3 LU on the symmetrized pattern with restricted-block static pivoting, iterative-refinement recovery, and MC64-style matching + scaling preprocessing. Pure Julia, no binary dependencies. This is the strongest solver for 'more structured' (PDE-mesh-like) sparse systems: in PurePardiso's benchmark suite it is the fastest single-threaded full factorization on every mesh-like problem, ahead of UMFPACK (0.5-0.8x) and KLU (up to 50x on 3D), with allocation-free numeric refactorization on an unchanged pattern (the cache-reuse path here). Numerically singular systems surface as ReturnCode.Infeasible via a residual check on the (rare) perturbed-pivot path, since static pivoting never aborts. Loading RecursiveFactorization (e.g. for RFLUFactorization) also activates PurePardiso's speed extension automatically, routing the dense panel kernels through RecursiveFactorization/TriangularSolve. Not wired into the default polyalgorithm in this PR; the natural follow-up is routing the 'more structure' branch (currently UMFPACKFactorization, gated on Base.USE_GPL_LIBS) to this algorithm, which would make the entire default sparse LU stack pure Julia. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The re-solve sweep iterates all AbstractSparseFactorization subtypes and converts the test matrix to sparse only for algorithms in its explicit lists; without this the new algorithm received a dense Matrix and its sparse-only solve! errored (the 4 Core-group failures). Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Local test status: the initial |
The default polyalgorithm's :UMFPACKFactorization slot now resolves to the pure-Julia supernodal left-right-looking LU (same pattern as the :KLUFactorization slot resolving to PureKLU); explicit UMFPACKFactorization() requests are unchanged. Since both sparse LU slots now resolve to pure-Julia solvers, the LU side of the sparse default no longer depends on Base.USE_GPL_LIBS (previously the non-GPL build sent structured systems to the scalar-kernel KLU path); the QR side keeps its SPQR gating. Occupying the UMFPACK slot gives the new algorithm the established sparse-LU -> column-pivoted-QR fallback chain: verified locally that a consistent singular structured system falls back and solves to residual 0.0, an inconsistent one returns the least-squares solution with the chain's existing retcode policy, and explicit SupernodalLUFactorization() requests still report Infeasible. Rationale for replacing UMFPACK in the default: benchmarks (PurePardiso results/SUMMARY.md) show it faster on every mesh-like structured system (0.5-0.8x UMFPACK full factorization, 0.2-0.7x refactorization) with equal-or-better residuals; the trade-off is circuit-like large-n systems (~1.6x slower than UMFPACK on circuit_100k), which sit near the klulike/structured boundary anyway. test/Core/default_algs.jl passes unchanged: the DefaultAlgorithmChoice enum and slot names are untouched, only the slot's resolved algorithm changed. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Updated per direction: the algorithm is now also the default on the structured sparse branch, and the dense-kernel composition with LinearSolve's default dense stack is settled. Defaults change (new commit): the default polyalgorithm's "Use the LinearSolve default dense solver" for the panel kernels — measured result: a plain LAPACK-getrf fast path for the base kernel was benchmarked and not adopted (±5 %, the mandatory block backup cancels getrf's gains at supernode sizes; recorded in the PurePardiso commit history as a negative result). RecursiveFactorization is a genuine win (−8–18 % refactorization) and its kernels activate automatically whenever RF is loaded — verified that Local verification on top of the previous rounds: |
|
Regime-mapping data relevant to the defaults change in this PR — two benchmark campaigns using SciMLBenchmarks problem setups (SparsePDE Where KLU is better (validates the existing Where UMFPACK is better: one regime — fully-unsymmetric-pattern but numerically tame matrices (bayer01-class, symfrac≈0), where COLAMD avoids the A+Aᵀ symmetrization penalty (1.5×; SupernodalLU still wins the refactorization there). It won 0 of 45 PDE-sweep rows and 1 of 18 collection matrices. The replacement this PR makes is safe. Boundary caveat for the current heuristic: large circuits (scircuit n=171k) fall on the "structured" side of Also fixed in PurePardiso while benchmarking: ASIC_100ks exposed a mass-perturbation policy bug (96 % pivots perturbed → res 0.76); |
… dep Per review direction: the solver now lives entirely inside LinearSolve as src/SupernodalLU (module LinearSolve.SupernodalLU) instead of depending on an external registered package. The folder is self-contained (needs only SparseArrays and LinearAlgebra, both hard deps): AMD port (BSD-3, retained SPDX headers + NOTICE.md with the full per-component lineage), orderings, symbolic analysis, MC64-style matching, the supernodal numeric kernel, and solves. Internal names are de-branded (snlu/snlu!/snlu_symbolic, SupernodalLUFactor, SymbolicAnalysis); the method is cited as Schenk & Gartner (FGCS 20(3) 2004; ETNA 23 2006). Dense-default composition is now wired directly: LinearSolveRecursiveFactorizationExt gains TriangularSolve as a second trigger (loads transitively with RecursiveFactorization, so activation conditions are unchanged) and overrides the supernodal dense panel hooks with RecursiveFactorization/TriangularSolve kernels - the same components RFLUFactorization uses - with static-pivoting semantics preserved via the optimistic fast path. The sparse structured default and the dense default share one engine whenever RF is loaded. The default-slot routing (:UMFPACKFactorization -> supernodal) is unchanged from the previous commit. New test/Core/supernodal_lu.jl ports the solver's internal invariant tests (factor identity, zero-alloc refactorization, matching incl. the mass-perturbation retry, banded fast path, threaded-vs-serial, BigFloat/Complex, multi-RHS). GROUP=Core passes locally in full. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Prerequisite: the backing package is not yet registered (and pending a possible rename away from
PurePardiso— the algorithm struct name here is already trademark-free). CI will fail on dependency resolution until registration; everything below was verified locally with the packagedev'd.What
New sparse LU algorithm
SupernodalLUFactorization, backed by PurePardiso.jl as a hard dependency (same pattern as PureKLU): the supernodal left–right-looking LU method of O. Schenk & K. Gärtner (FGCS 20(3) 2004; ETNA 23 2006) — supernodal BLAS-3 LU on the symmetrized pattern, restricted-block static pivoting with iterative-refinement recovery, MC64-style matching + scaling. Pure Julia, no binary dependencies, generic over element types (BigFloat verified to 1e-78 residual through the LinearSolve interface).Why
It is the strongest solver for "more structured" (PDE-mesh-like) sparse systems: fastest single-threaded full factorization on every mesh-like problem in PurePardiso's benchmark suite — ahead of UMFPACK (0.5–0.8×) and KLU (up to 50× on 3D Poisson), and ahead of MKL PARDISO at 1 thread. The cache-reuse path here maps to PurePardiso's allocation-free numeric refactorization (measured 176 bytes per refactor+solve through the full LinearSolve interface).
Semantics
reuse_symbolic/check_patternmirror the KLU/UMFPACK algs; pattern change re-analyzes.Success— a residual check on the (rare) perturbed-pivot path surfaces them asReturnCode.Infeasible.using RecursiveFactorization(e.g. forRFLUFactorization) automatically activates PurePardiso's speed extension (RecursiveFactorization + TriangularSolve panel kernels, −8–18 % refactorization) — no wiring needed here, the extension triggers on package presence.threaded=trueopt-in supernodal-etree parallel factorization (1.5–3.2× at 8 threads).Not in this PR
Default-polyalgorithm routing. The natural follow-up: route the "more structure" branch of the sparse default (currently
UMFPACKFactorization, gated onBase.USE_GPL_LIBS) to this algorithm — which would (a) speed up the GPL build on mesh-like systems and (b) rescue the non-GPL build from PureKLU-on-3D collapse, making the entire default sparse LU stack pure Julia. That is a defaults decision deserving its own PR and review.Local verification
LinearProblem/init/solve!: basic solve, cache-reuse refactorization (allocation-free), pattern-change re-analysis, weak-diagonal matching path, BigFloat, singular→Infeasible,ordering=:nd,threaded=true— all pass.GROUP=Core Pkg.test()run locally with the new testset (result pending at PR time; will update).🤖 Generated with Claude Code
https://claude.ai/code/session_017rr42T1vFRRT8D7DMAmJzf