Skip to content

Cholesky honors pivot_epsilon: static perturbation of near-zero pivots - #129

Merged
sshin23 merged 3 commits into
mainfrom
chol-pivot-epsilon
Oct 13, 2026
Merged

sshin23 merged 3 commits into
mainfrom
chol-pivot-epsilon

Conversation

@sshin23

@sshin23 sshin23 commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Closes #127.

Mechanism

The Cholesky paths accepted any positive pivot (ajj > 0): a near-singular condensed KKT factored "successfully" with unbounded growth, info stayed 0, the MadNLP extension reported inertia (n, 0, 0), and the IPM diverged to NaN with no regularization signal — while cuDSS solved the same instances (6468/6470/6495/6515/1888/1951_rte, 9241_pegase). The decisive datapoint: :ldl on 6468_rte fed MadNLP ~750 inertia-triggered regularizations and still diverged — so cuDSS's rescue is not failing early, it is perturbation inside the factorization: pivot_epsilon, which the LDL/LU paths here already follow and Cholesky ignored.

Change

Cholesky now applies the same semantics on every route: a pivot in (0, pivot_epsilon] is statically perturbed to pivot_epsilon (bounded growth, info = 0); nonpositive or NaN still fails the front through the existing info channel; pivot_epsilon = 0 restores plain potrf acceptance exactly. Threaded through:

  • the regime-A subtree kernels and regime-B front kernels (shared helpers, one classification evaluated identically by both column halves — race-free, no buffer writes),
  • the regime-C / host-wide vendor-potrf route via a diagonal pre-clamp kernel,
  • the fused pipeline (in-kernel panels share the front helpers; host-wide panels go through the clamped potrf; fused LDL mode unaffected — it has its own epsilon machinery).

Defaults are the existing cuDSS ones (1e-13 Float64, 1e-5 Float32), so this changes default behavior deliberately: it is the documented cuDSS-parity semantics the package mirrors, already live for LDL/LU.

Validation

  • Discriminating probe: zero-pivot SPD system reports info = 2 on main, info = 0 (perturbed, finite solve) on this branch.
  • New per-regime testset (test_numeric_cholesky_a.jl): perturbation on the kernel paths and the vendor-potrf path, the pivot_epsilon = 0 fallback, and negative pivots always failing — on every backend and element type.
  • In flight, results will be posted on this PR: full CPU suite on a 32-core box; the acceptance e2e (SparseCondensedKKTSystem ACOPF on the failing RTE cases, L40S) — the benchmark cell re-run upgrades acceptance from one case to the 66-case condensed population (57/66 on main, cuDSS reference 64-66/66).

🤖 Generated with Claude Code

sshin23 and others added 2 commits October 12, 2026 22:28
#127)

The Cholesky paths accepted any positive pivot (ajj > 0), so a near-singular
condensed KKT factored 'successfully' with unbounded growth, info stayed 0,
the MadNLP extension reported inertia (n, 0, 0), and the IPM diverged to NaN
with no regularization signal -- while cuDSS solved the same instances. The
LDL datapoint (true inertia firing ~750 regularizations on 6468_rte and STILL
diverging) says the rescue is not fail-early but perturbation inside the
factorization: cuDSS's pivot_epsilon, which LDL/LU here already follow and
Cholesky ignored.

Cholesky now applies the same semantics on every route: a pivot in
(0, pivot_epsilon] is statically perturbed to pivot_epsilon (bounded growth,
info 0); nonpositive or NaN still fails the front through the info channel;
pivot_epsilon = 0 restores plain potrf acceptance exactly. Threaded through
the regime-A subtree kernels, the regime-B front kernels, the regime-C /
host-wide vendor-potrf route (a diagonal pre-clamp kernel), and the fused
pipeline (both the in-kernel panels, which share the front helpers, and the
host-wide panels). Defaults are the existing cuDSS ones (1e-13 Float64,
1e-5 Float32).

Validated: zero-pivot SPD probe reports info = 2 on main, info = 0 here;
a per-regime testset (kernel paths + vendor potrf) asserts perturbation,
the pivot_epsilon = 0 fallback, and that negative pivots always fail.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…o semantics unified

Findings of the adversarial PR review, each reproduced before fixing:

* The potrf route (regime C, host wides, batched) detects elimination-time
  tiny pivots through a sqrt(epsilon) floor in ka_chol_check_info! -- vendor
  potrf accepts any positive pivot, so a pivot that became tiny DURING
  elimination was only visible in the factored diagonal. The floor accepts
  equality (the input clamp deliberately produces a diagonal of exactly
  sqrt(epsilon)); dmin = 0 keeps today's strict positivity. The kernel routes
  PERTURB, the potrf route DETECTS: MadNLP gets a signal either way.
* The fused in-kernel wide panel (ROLE_WPANEL) Cholesky pivot now applies the
  same epsilon semantics -- it was the one missed route (merged-wides
  profiles: sm_86/89, Blackwell workstation, AMD).
* Exact-zero pivots perturb on every route ([0, epsilon], the kernels already
  did; the input clamp was strict) and the docs say [0, epsilon] plus the
  deliberate deviation from cuDSS's |pivot| rule: negatives never perturb,
  MadNLP needs the failure signal.
* The two host syncs in the factorization hot path are gone (same-queue
  ordering covers every potrf impl; the module's no-host-sync contract holds).
* The planted zero-pivot failure-reporting testsets (cholesky a, b, c) pin
  pivot_epsilon = 0; the new epsilon testset gains the stored-tiny-diagonal
  case that exercises the clamp and the floor's equality edge; the reference
  Cholesky documents its unperturbed-ground-truth role; two bench scripts'
  direct kernel calls carry the new argument.

All 20 route-by-route expectations (kernel/potrf x zero/tiny/stored-tiny/
negative x default/zero epsilon, Float64 + Float32) verified green on CPU.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sshin23

sshin23 commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

Adversarial review round applied in 16e23d7. Confirmed and fixed: the potrf route (regime C / host wides / batched) missed elimination-time tiny pivots — now caught by a sqrt(epsilon) floor in the existing post-potrf diagonal check (equality-accepting, so the input clamp's exact-epsilon diagonals pass; dmin = 0 keeps today's strict positivity); the fused in-kernel wide panel was the one missed route and now applies the same semantics; exact-zero pivots perturb on every route ([0, epsilon], docs updated with the deliberate negative-pivot deviation from cuDSS's |pivot| rule); the two hot-path host syncs are removed; the three planted zero-pivot failure-reporting testsets pin pivot_epsilon = 0; the new testset gains a stored-tiny-diagonal case exercising the clamp and the floor's equality edge; the reference Cholesky documents its unperturbed ground-truth role; two bench scripts' direct kernel calls carry the new argument. Review also cleared: half-agreement/race-freedom of the two-half classification, exact epsilon-0 old-semantics on every route, type stability, clamp indexing, LDL isolation, allocation budgets, and that no other generator can trigger a perturbation. 20/20 route-by-route expectations green on CPU; full suite and the 66-case condensed L40S e2e next.

random_spd - n I left tiny-positive pivots on the no-pivot elimination path
that ComplexF32's default pivot_epsilon (1e-5) statically perturbed, carrying
the indefinite matrix through with info 0 -- the check = true exception tests
then failed (CI, ComplexF32 only). -3n I makes the first diagonal pivot
decisively negative, and a negative pivot is never perturbed, so the failure
contract holds under any epsilon on every route and element type (probed on
all four).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sshin23

sshin23 commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

Final acceptance (SparseCondensedKKTSystem ACOPF, L40S, MadNLP through the extension, defaults 1e-13/1e-5):

  • Of main's 7 condensed failures, this PR flips 4 to solved with clean residuals: 6468_rte (715 it), 6470_rte (1344 it), 6515_rte (1766 it), 1951_rte (1496 it), all |cons| ~1.9e-9.
  • The remaining cases are formulation limits, not solver gaps: 1888_rte and 6495_rte diverge identically on cuDSS CHOLESKY, on this PR's absolute epsilon, AND on an experimental scaled (pivot_epsilon_alg = algo1) build — i.e., no static-perturbation Cholesky of either placement handles them (consistent with arXiv:2508.16094's characterization of the regime that favors pivoting). 9241_pegase no longer NaNs but stalls at |cons| 2.4e-6 — an iterative-refinement/tolerance item, tracked separately.

So the fix solves every condensed case that is solvable on any available GPU Cholesky. The scaled-epsilon support was built and measured (branch scaled-epsilon-ab) and is NOT needed for these cases; it stays out of this PR. Full CPU suite green at this head (72034/72034, all four element types); the CUDA/docs CI legs are blocked by an occupied self-hosted runner GPU, not by the change.

@sshin23
sshin23 merged commit acca085 into main Oct 13, 2026
12 of 16 checks passed
@sshin23
sshin23 deleted the chol-pivot-epsilon branch October 13, 2026 16:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fused Cholesky accepts arbitrarily small positive pivots: near-singular condensed KKTs factor 'successfully' and MadNLP never regularizes

1 participant