Skip to content

Update to cuDSS 0.8 - #12

Merged
alexkorovko merged 2 commits into
mainfrom
new_cudss
Jun 2, 2026
Merged

Update to cuDSS 0.8#12
alexkorovko merged 2 commits into
mainfrom
new_cudss

Conversation

@alexkorovko

@alexkorovko alexkorovko commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Chores

    • Build now downloads and uses prebuilt cuDSS binaries by default (configurable CUDSS_VERSION, default 0.8.0.10) with automatic CUDA-major selection.
    • Removed the previous optional local cuDSS build path.
  • Refactor

    • Compatibility handling updated to support both new and legacy cuDSS APIs, simplifying integration and build behavior.

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Switches cuDSS from optional local-source builds to downloaded prebuilt archives (CUDSS_VERSION), removes LOCAL_CUDSS_BUILD conditionals, adds CUDSS_NEW_API gating from header version macros, and refactors helper and linear-solver flows to support new and legacy cuDSS APIs.

Changes

cuDSS Prebuilt Archive Migration and API Versioning

Layer / File(s) Summary
CMake migration to prebuilt archives
CMakeLists.txt, cmake/AddCUDSS.cmake, cunls/common/CMakeLists.txt, cunls/linear_solver/CMakeLists.txt
Introduces CUDSS_VERSION cache variable and updates add_cudss to accept VERSION; AddCUDSS.cmake constructs CUDA-major and arch-specific prebuilt archive URLs, uses FetchContent to provide an imported cudss target (lib/libcudss_static.a and include), and removes local-build handling and conditional CUDSS_NEW_API injections.
cuDSS helper version detection and API gating
cunls/common/cudss_helper.cpp
Adds CUDSS_NEW_API detection from cuDSS header macros and conditional branches selecting CUDSS_REORDERING_ALG_* vs legacy CUDSS_ALG_* enums for descriptor/config creation; preserves existing control flow.
cuDSS helper implementation restructuring
cunls/common/cudss_helper.cpp
Reformats device memory pool allocator/deallocator wrappers and device memory handler attach/detach logic for readability while preserving behavior and guards.
Linear solver API versioning and phase management refactor
cunls/linear_solver/cudss_sparse_linear_solver.cpp
Adds CUDSS_NEW_API gating for ordering enums, refactors Initialize to run CUDSS_PHASE_ANALYSIS unconditionally and CUDSS_PHASE_FACTORIZATION only for FastInitSlowSolve, and refactors Solve to choose FACTORIZATION vs REFACTORIZATION then run CUDSS_PHASE_SOLVE.
BlockSparse PCG formatting and kernel updates
cunls/linear_solver/block_sparse_pcg_solver.cu
Formatting and signature rewrapping across kernels and dispatch logic; removes scalar-zeroing kernels and switches to caller-zeroed scalar slots with cudaMemsetAsync in DotAsync/DualDotAsync; refactors cuSPARSE SpMV descriptor setup and per-iteration Solve loop layout.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 From local builds to archives I bound,

Version tags and headers I did read,
New enums and old both kept around,
Kernels trimmed and mems cleared with speed,
Hoppity hop — the solver builds and runs with glee.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: updating cuDSS to version 0.8, which is the primary objective reflected throughout all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch new_cudss

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
cmake/AddCUDSS.cmake (1)

59-65: 💤 Low value

Consider pinning a URL_HASH for the fetched archive.

FetchContent_Declare for a remote binary without an integrity hash leaves the build vulnerable to corrupted or tampered downloads and is non-reproducible. Since the version is fixed, a URL_HASH SHA256=... per archive would harden the supply chain.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmake/AddCUDSS.cmake` around lines 59 - 65, Add an integrity hash to the
FetchContent declaration to pin the downloaded archive: compute the SHA256 of
the file at CUDSS_URL (or obtain the vendor-provided checksum) and add a
URL_HASH SHA256=<checksum> entry to the FetchContent_Declare call in
AddCUDSS.cmake (the block that declares "cudss" and uses CUDSS_URL and
FetchContent_MakeAvailable). This ensures reproducible, tamper-evident fetches;
update the stored checksum when intentionally changing versions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmake/AddCUDSS.cmake`:
- Around line 51-65: The FetchContent_Declare block for the cudss dependency
currently uses URL ${CUDSS_URL} without integrity verification; compute the
SHA256 of the expected .tar.xz archive for each supported release and add an
URL_HASH entry (e.g., URL_HASH SHA256=<computed-hash>) to the
FetchContent_Declare(cudss ...) call so FetchContent will verify the downloaded
artifact; update the FetchContent_Declare invocation in AddCUDSS.cmake alongside
the existing URL and keep the CUDSS_URL logic unchanged.

In `@cunls/common/cudss_helper.cpp`:
- Around line 245-254: The CUDSS_NEW_API branch of cudssMatrixCreateCsr is
calling the wrong signature and using non-public CUDSS_R_* enums; update the
CUDSS_NEW_API call in cudss_helper.cpp to match the public cuDSS CSR signature
used elsewhere by passing the same parameter order and types as the non-NEW
branch (use a single index type and a single value type), replacing
CUDSS_R_32I/CUDSS_R_32F with the public CUDA data-type enums (CUDA_R_32I,
CUDA_R_32F) and ensure the NULL/cols/values parameters match the non-NEW_API
invocation so the call mirrors the working cudssMatrixCreateCsr(&mat,
matrix_size, matrix_size, num_nonzeros, rows_ptr, NULL, cols_ptr, values_ptr,
CUDA_R_32I, CUDA_R_32F, CUDSS_MTYPE_SYMMETRIC, CUDSS_MVIEW_FULL,
CUDSS_BASE_ZERO).

---

Nitpick comments:
In `@cmake/AddCUDSS.cmake`:
- Around line 59-65: Add an integrity hash to the FetchContent declaration to
pin the downloaded archive: compute the SHA256 of the file at CUDSS_URL (or
obtain the vendor-provided checksum) and add a URL_HASH SHA256=<checksum> entry
to the FetchContent_Declare call in AddCUDSS.cmake (the block that declares
"cudss" and uses CUDSS_URL and FetchContent_MakeAvailable). This ensures
reproducible, tamper-evident fetches; update the stored checksum when
intentionally changing versions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Enterprise

Run ID: 5e7fe0a8-0e83-4c84-a43e-264ef769a7f5

📥 Commits

Reviewing files that changed from the base of the PR and between c703856 and e265a3d.

📒 Files selected for processing (6)
  • CMakeLists.txt
  • cmake/AddCUDSS.cmake
  • cunls/common/CMakeLists.txt
  • cunls/common/cudss_helper.cpp
  • cunls/linear_solver/CMakeLists.txt
  • cunls/linear_solver/cudss_sparse_linear_solver.cpp
💤 Files with no reviewable changes (2)
  • cunls/common/CMakeLists.txt
  • cunls/linear_solver/CMakeLists.txt

Comment thread cmake/AddCUDSS.cmake
Comment thread cunls/common/cudss_helper.cpp
ZeroScalarKernel and Zero2ScalarKernel were never launched (the solver
zeros scalar slots with cudaMemsetAsync), producing nvcc #177-D
"declared but never referenced" warnings. Remove them and update the
two comments that referenced them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cunls/linear_solver/block_sparse_pcg_solver.cu (1)

650-664: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix grid-wide race in PcgDirectionKernel updating rz_old_ptr[0]

  • PcgDirectionKernel has CTAs reading rz_old_ptr[0] (for denom) while blockIdx.x==0 writes rz_old_ptr[0]=num within the same kernel launch; __syncthreads() doesn’t order across CTAs, so beta can vary nondeterministically.
🐛 Proposed fix
 __global__ void PcgDirectionKernel(const float *__restrict__ rz_new_ptr,
-                                   float *__restrict__ rz_old_ptr, const float *__restrict__ z,
+                                   const float *__restrict__ rz_old_ptr,
+                                   const float *__restrict__ z,
                                    float *__restrict__ p, int n) {
   __shared__ float b;
   if (threadIdx.x == 0) {
     float num = rz_new_ptr[0];
     float denom = rz_old_ptr[0];
     b = (fabsf(denom) > 0.f) ? num / denom : 0.f;
-    // Only the first CTA's thread 0 writes rz_old; all other CTAs
-    // skip the write (the rz_old slot is read by the *next*
-    // iteration's PcgUpdate, which happens after this kernel
-    // completes, so any one writer is enough).
-    if (blockIdx.x == 0) {
-      rz_old_ptr[0] = num;
-    }
   }
   __syncthreads();
   int i = blockIdx.x * blockDim.x + threadIdx.x;
   if (i >= n) {
     return;
   }
   p[i] = z[i] + b * p[i];
 }
   PcgDirectionKernel<<<blocks, threads, 0, stream>>>(
       d_scratch_.data() + kRzNew, d_scratch_.data() + kRzOld, z_.data(), p_.data(), n);
+  THROW_ON_CUDA_ERROR(cudaMemcpyAsync(d_scratch_.data() + kRzOld,
+                                      d_scratch_.data() + kRzNew,
+                                      sizeof(float),
+                                      cudaMemcpyDeviceToDevice,
+                                      stream));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cunls/linear_solver/block_sparse_pcg_solver.cu` around lines 650 - 664,
PcgDirectionKernel races because multiple CTAs read rz_old_ptr[0] (denom) while
blockIdx.x==0 writes rz_old_ptr[0]=num in the same kernel; remove the in-kernel
write to rz_old_ptr[0] inside PcgDirectionKernel to eliminate the cross-CTA race
and instead perform the update to rz_old_ptr[0] from the host (or in a separate
single-block kernel launched after PcgDirectionKernel completes) so denom is
read-only inside the kernel; keep the rest of the logic (reading rz_new_ptr[0]
into num, computing b, and updating p/z) unchanged and reference
PcgDirectionKernel, rz_new_ptr, rz_old_ptr, num, denom, and blockIdx.x when
applying the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@cunls/linear_solver/block_sparse_pcg_solver.cu`:
- Around line 650-664: PcgDirectionKernel races because multiple CTAs read
rz_old_ptr[0] (denom) while blockIdx.x==0 writes rz_old_ptr[0]=num in the same
kernel; remove the in-kernel write to rz_old_ptr[0] inside PcgDirectionKernel to
eliminate the cross-CTA race and instead perform the update to rz_old_ptr[0]
from the host (or in a separate single-block kernel launched after
PcgDirectionKernel completes) so denom is read-only inside the kernel; keep the
rest of the logic (reading rz_new_ptr[0] into num, computing b, and updating
p/z) unchanged and reference PcgDirectionKernel, rz_new_ptr, rz_old_ptr, num,
denom, and blockIdx.x when applying the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Enterprise

Run ID: 6c632087-a817-4ab0-b637-9833f915a17a

📥 Commits

Reviewing files that changed from the base of the PR and between 09f87fb and 32add6a.

📒 Files selected for processing (1)
  • cunls/linear_solver/block_sparse_pcg_solver.cu

@alexkorovko
alexkorovko merged commit d5c792c into main Jun 2, 2026
8 checks passed
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.

1 participant