Repository navigation
T36: solve_alg = "algo1", the partitioned-inverse fused solve on DirectSolver - #187
michel2323 wants to merge 1 commit into
Conversation
…ctSolver - Fused.FusedSolve / fused_solve_plan / fused_solve!: one solve driver for DirectSolver (solve_alg = "algo1", after the stock factorization) and FusedSolver; algo2_sweeps! split into forward / diagonal / backward parts - DirectSolver: plan built at the analysis (slot 14 of memory_estimates), inverses at every factorization, solve and sub-phases run the fused solve, refinement (plain and FGMRES) and matching compose with it; one dependency-counter segment per run of narrow plan entries - scope checks raise NotSupportedError (CPU/Metal via forward_progress, complex, "G", pivoting, batch, Schur, nrhs > 1, solve_mode) - forward_progress capability (CUDA, AMDGPU, oneAPI extensions) - test/test_solve_algo1.jl; docs and the T36 Report Refs #82 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MsLzHn17wzxqT2iMbuJyUh
| ("random_spd 300", () -> random_spd(T, 300, 0.02)), | ||
| ("schur_example_cholesky 5×5", () -> schur_example_cholesky(T).A), | ||
| ) | ||
| algo1_indefinite_generators(::Type{T}) where {T} = ( |
There was a problem hiding this comment.
nit (non-blocking): none of the "S" generators here is likely to have a front wider than 256, so the one combination this PR newly enables and that FusedSolver never exercised — the vendor dense sweeps (_fwd_dense!/_bwd_dense! called with _SV_CHOLESKY from algo2_forward!/algo2_backward!) on a factor written by the stock regime-C LDLᵀ kernels — has no test. It works because the stock LDLᵀ stores a unit 1 on the diagonal and pivot_type = 'N' applies no local pivot order, but that is exactly the kind of layout coupling a test should pin down. Suggested fix: add one no-pivot "S" matrix whose root front exceeds 256 (a larger grid_kkt_matrix, or a kkt_matrix with a denser Hessian; assert the width with maximum(s.symbolic.schedule.width) > 256 as the 34³ case asserts its segment count), and keep the comparison against the level sweeps on the same factorization.
There was a problem hiding this comment.
VERDICT: APPROVE (head a4bb8bb)
Checked (T36 task text on main, AGENTS.md, PLAN §1.3/§2.5/§2.7/§3.9, git diff origin/main...HEAD):
- Scope: only the four T36 deliverables.
PLAN.mduntouched, noManifest.toml,TASKS.mdchanged only in the T36 section (marker[!], Report).test_fused.jlunchanged (the oldFusedSolverfields are forwarded bygetproperty). Parameter and phase strings as in PLAN §1.3/§3.1;"default"keeps the level sweeps with a stated justification. README/docs edits are the feature's own documentation. - Tests:
test/test_solve_algo1.jlcovers every listed item: all SPD and no-pivot"S"generators on the forward-progress backends ofBACKENDS, Float32/Float64 viaeltypes_among, residual and agreement with the level sweeps withintol(T), bitwise-equal solves and sub-phases underdeterministic_mode = 1,ir_n_steps = 2, FGMRES, matching, refactorization with new values,memory_estimatesslot 14, no device allocation plus thefused_cycle_alloc_budgethost budget, every unsupported combination (CPU backend included) raisingNotSupportedError.Random.seed!(666), shared helpers only, no@test_broken.test_optionsalready accepted"algo1". - Conventions: generic
T/INT; new buffers sized on the host and uploaded once at the analysis;invert!is one asynchronous launch and the solve path adds no host synchronization (the counter reset is a device-to-devicecopyto!); dense calls go through_fwd_dense!/_bwd_dense!; backend facts (forward_progress) live inext/; errors fromsrc/errors.jl. - Correctness: the no-pivot LDLᵀ path (
_lt_select!withr == 0) produces only 1×1 pivots, an identity local order and a unit stored diagonal, soalgo2_diagonal!(Y ./= d[1:n]) and the Cholesky-kind dense calls are exact for the enabled scope; the per-run segments (merged = false) count children outside the range as arrived/done, consistent with stream order; the graph capture onFusedSolverrecords without executing, so the eager sweeps of the capturing solve are not doubled;getpropertyforwarding and_clear_plans!are consistent; the workspace regrown for a refusednrhs > 1rebuilds the sameSolvePlanfrom the symbolic, so the segment indices stay valid. - Report: matches the diff; counts plausible (314 new); the first-run failure and the re-run are recorded honestly. CI is pending at review time (CUDA, AMDGPU, Aurora): the owner's call.
Blocking findings: none.
Non-blocking:
- Inline nit on
test/test_solve_algo1.jl: no"S"test has a front wider than 256, so the vendor dense sweeps on a stock-LDLᵀ factor are untested in this PR. - The task asked for the full SPD and KKT harness; apache2 was not measured (stated in the Report).
- The follow-ups under "Open issues" (Bunch–Kaufman under
"algo1", sm_89/AMD timing, accuracy of the explicit inverses, the_probe_atomiclog noise found in earlier code) have nofound-by-agentissues; AGENTS.md asks for them.
Closes #186
Task: T36 —
solve_alg = "algo1": the partitioned-inverse fused solve onDirectSolver(refs #82 solve half)What was built:
solve_alg = "algo1"onDirectSolverafter the stock factorization.src/fused.jl: aFusedSolveobject (L₁₁ inverses, theirinvert!launch, the dependency-counter solve segments, byte count, graph switch) built byfused_solve_planat the analysis;fused_sweeps!/fused_solve!are the single solve driver, used byFusedSolvertoo (its old fields stay readable throughgetproperty,test_fused.jlunchanged).src/solver.jl: thefsolvefield, the inverses computed at the end of every factorization/refactorization under"algo1"(no host sync, no allocation),"solve"and the sub-phases through the fused sweeps, refinement (IR and FGMRES,src/solve/refinement.jl) and matching composed with it,memory_estimatesslot 14, the scope checks (NotSupportedErrorat the analysis forCPU()/Metal, complexT,"G", pivoted"S"/"H", batches, Schur; at the solve fornrhs > 1,solve_mode ≠ 0,"algo1"set after the analysis, stale inverses). New capabilityforward_progress(backend)(src/dense/capabilities.jl;truein the CUDA, AMDGPU and oneAPI extensions). Docs:man/parameters.md,man/performance.md("Partitioned-inverse solve"), README.Tests:
SDS_TEST_ONLY=test_solve_algo1,test_fused,test_api,test_refinement,test_fgmres,test_options,test_solve,test_madnlp,test_aqua PTR_NUM_JOBS=4 julia --project=. -e 'using Pkg; Pkg.test()', KA CPU backend + CUDA (H200), all four element types: 7407 pass, 0 fail, 0 broken (newtest/test_solve_algo1.jl: 314). Full suite, AMDGPU, oneAPI: pending CI. One CPUtest_api[ComplexF32]allocation failure on the level-sweep path in an earlier 6-worker run did not reproduce (noted in the Report).Measurements (H200 sm_90, one exclusive Slurm GPU,
DirectSolverdefault options, medians of 21, cuDSS 0.8 in its own process): solve of the 78k condensed KKT 10.14 ms (level sweeps) → 2.12 ms ("algo1") vs cuDSS 1.40; case1354 0.886 → 0.269 vs 0.193; bcsstk38 1.540 → 0.327 vs 0.353; lap3d_40 11.72 → 6.99 vs 1.251. The inverse launch adds 0.2–1.3 % to a refactorization.memory_estimatesslot 1 on the 78k: 235.7 → 289.5 MiB (slot 14: 53.8), lap3d_40 182.7 → 191.8. Full table in the Report.Deviations from PLAN.md / TASKS.md:
"default"stays the level sweeps although"algo1"is faster on every harness matrix, because the explicit inverses are less accurate (relres 2× on the 78k, 35× on bcsstk38; refinement removes the gap), the default"S"uses Bunch–Kaufman pivoting (out of scope), only sm_90 was measured, and it costs ~23 % more device memory on the 78k.DirectSolverruns one counter segment per run of plan entries ≤ 256 wide (with a single segment lap3d_40 took 21.5 ms);FusedSolverkeeps its single segment."algo1"set after the analysis raises instead of building the plan late.FusedSolvernow also refuses Metal (no forward-progress guarantee). Matching is supported. Graph replay of the"algo1"solve onDirectSolveris off (T38). Proposed PLAN §1.3/§2.5/§2.7 wording in the Report.Follow-up issues opened: none (Bunch–Kaufman under
"algo1", sm_89/AMD timing of the multi-segment solve and the accuracy of the explicit inverses are listed under "Open issues" in the Report).🤖 Generated with Claude Code
https://claude.ai/code/session_01MsLzHn17wzxqT2iMbuJyUh