Skip to content

get_differential_vars: check Diagonal.diag, not the full matrix (fixes GPU DAE 100% failure)#3923

Open
singhharsh1708 wants to merge 1 commit into
SciML:masterfrom
singhharsh1708:fix-gpu-diagonal-massmatrix-scalar-index
Open

get_differential_vars: check Diagonal.diag, not the full matrix (fixes GPU DAE 100% failure)#3923
singhharsh1708 wants to merge 1 commit into
SciML:masterfrom
singhharsh1708:fix-gpu-diagonal-massmatrix-scalar-index

Conversation

@singhharsh1708

Copy link
Copy Markdown
Contributor

Fixes #3922.

Bug

get_differential_vars (lib/OrdinaryDiffEqCore/src/misc_utils.jl) checks the mass matrix with:

elseif all(!iszero, mm)

before the _isdiag branch. For a Diagonal, all(!iszero, ::AbstractMatrix) visits every (i, j) pair, including a call to getindex on the underlying diagonal vector for each i == j. test/gpu/dae_tests.jl builds its mass matrix as cu(Diagonal([1, 1, 0, 0])), i.e. Diagonal{Float64, <:CuVector} — CUDA disallows scalar getindex on device arrays by default, so this throws on every DAE init. get_differential_vars runs whenever W hasn't already been built (lib/OrdinaryDiffEqCore/src/solve.jl:592), which is the common case, so this hits every solver × jac_prototype combination in that test file — matching the 100% failure rate on the GPU CI lane since it was turned back on in #3813.

Fix

Diagonal structurally guarantees off-diagonal zeros, so check mm.diag directly instead of the full matrix. Same result for CPU Diagonal (verified against master: identical output for mixed/all-nonzero/all-zero diagonals), just without the wasted O(n²) structural traversal, and without the unsafe scalar indexing for a GPU-backed diagonal.

Also wires up show_errors(results) in the GPU DAE test's @testset entry point. It was defined but never called, so CI logs only ever showed a status glyph, no exception text — that's why this took reading the full raw job log to pin down instead of the test's own diagnostics.

Verification

No GPU hardware available here, so this isn't verified against real CUDA. What is verified:

  • CPU behavior for get_differential_vars on Diagonal is byte-for-byte identical before/after the change (mixed, all-nonzero, all-zero diagonal cases).
  • Sparse isdiag Performance (10/10) and Algebraic Vars Detection (21/21, includes 3 new tests for the Diagonal case) pass.
  • Runic clean.

The mm.diag reduction is exactly the same operation CUDA.jl already supports for all/any over a CuVector (proper GPU reduction, not scalar indexing), so this should clear the GPU failure, but someone with GPU access needs to confirm.

AI Disclosure

Claude assisted with this work.

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Member

The GPU job on this PR gets past the get_differential_vars path, but it exposes a second independent blocker in the same Simple DAE GPU test: 87623782250 fails at simple_dae.jl:54 with DimensionMismatch: array could not be broadcast to match destination. The first package frame is the three-argument ldiv!(x::CuMatrix, qr::QR, b::CuMatrix) in cuSOLVER linalg.jl:301; x and b are both matrix right-hand sides. That exact upstream defect and regression are already addressed by CUDA.jl #3199.

This appears to confirm that this PR cleared the earlier scalar-indexing barrier, after which CI reached the unrelated QR barrier. I would keep this PR focused; its GPU job cannot become green until the CUDA fix is available in the resolved environment.

…L#3922)

all(!iszero, mm) visits every (i, j) pair, including scalar getindex
on the underlying diagonal vector. For a GPU-backed diagonal mass
matrix (Diagonal{Float64, <:CuVector}), that's disallowed and throws
on every DAE init, which is why every case in test/gpu/dae_tests.jl
fails regardless of solver or jac_prototype. Diagonal structurally
guarantees off-diagonal zeros, so check mm.diag directly.

Also wires up show_errors(results) in the GPU DAE test entry point,
which was defined but never called, so a real failure prints its
actual exception instead of just a status glyph.
@singhharsh1708
singhharsh1708 force-pushed the fix-gpu-diagonal-massmatrix-scalar-index branch from ff724e9 to 59b1424 Compare July 21, 2026 14:31
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.

GPU DAE tests: 100% failure since GPU CI lane restored (#3813), likely Diagonal mass matrix scalar indexing

2 participants