Skip to content

test(rocsparse): add unit tests for 80% unit-only coverage (AISPARSE-879) - #13475

Merged
kliegeois merged 40 commits into
ROCm:developfrom
kliegeois:task/unit-cov-fused
Oct 26, 2026
Merged

kliegeois merged 40 commits into
ROCm:developfrom
kliegeois:task/unit-cov-fused

Conversation

@kliegeois

@kliegeois kliegeois commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

JIRA ID : AISPARSE-879.

Summary

Adds rocSPARSE unit tests, built into the existing rocsparse-unit-test (host) and rocsparse-unit-test-device (GPU) binaries, so that the unit tests alone reach the 80% Codecov target, and reports unit-test and integration-test coverage as separate Codecov flags.

The branch is one commit per area so it can be reviewed area by area:

  1. Shared setup (clients/unittests/CMakeLists.txt, unit_test_utils.hpp): compiles the hidden library translation units that the tests need into rocsparse-unit-test-device with the library's configuration macros (ROCSPARSE_KEEP_INTERNAL_U16, and ROCSPARSE_WITH_MEMSTAT / ROCSPARSE_DEBUGGING when the library is built with them), passes -Drocsparse_ILP64 to the unit tests when BUILD_ROCSPARSE_ILP64 is on, adds scoped_env and a per-process temp_file_path, and includes one cmake/unit_tests_<area>.cmake file per area. No test and no library change.
  2. CI: the coverage run writes the profiles of rocsparse-test and of the unit-test binaries under different prefixes. A new coverage_split target exports them separately, and Jenkins uploads them as the rocSPARSE-unit and rocSPARSE-integration flags, next to the unchanged combined rocSPARSE upload. The extra uploads run only if coverage_split succeeds and never fail the job; a failed coverage_split is logged. coverage_cleanup also removes the split profiles, and clients/tests/testing.md describes the target and the flags. The flag declarations in codecov.yml (carry-forward, informational) are in ci(codecov): declare the rocSPARSE-unit and rocSPARSE-integration flags (AISPARSE-879) #14388: a root codecov.yml change makes CI run every project in the single-shard quick tier, where the rocSPARSE and rocFFT quick suites time out on Windows gfx110X ([develop] rocSPARSE quick-tier smoketest times out (300 s) on Windows gfx110X #13649, [develop] rocFFT quick-tier smoketest times out (600 s) on Windows gfx110X #13414). Until ci(codecov): declare the rocSPARSE-unit and rocSPARSE-integration flags (AISPARSE-879) #14388 lands, the two flags upload without a status or carry-forward.
  3. Host: bfloat16 rounding, auxiliary API branches (descriptors, debug switches, logging), internal BLAS wrappers, csxsldu.
  4. Level 2: SpMV/SpSV/SpTrSM dispatch tables across formats, operations and scalar types, BSR/GEBSR mv and sv, iterative triangular solves.
  5. Conversions: prune and extract, sort, descriptors, GEBSR, HYB and ELL conversions, check_matrix.
  6. Preconditioners: ILU0, IC0, ILDLT0, iterative ILU0, gtsv, triangular info.
  7. Extra routines: SpMM, SpGEMM, csrgemm/bsrgemm, SpGEAM/csrgeam/bsrgeam, SDDMM, SpSM/csrsm/bsrsm, gemm/geam.

The commits after these apply the review feedback, one commit per review thread, and make the unit tests build and pass under rocsparse_ILP64.

How the tests are written

  • Results are compared with host references built from matrices that are well posed by construction (diagonally dominant or SPD for the factorizations and triangular solves). The preconditioner tests scale their tolerances with the row length, level 2 uses a fixed tolerance per precision, and the extra routines compare exactly where the result is exact. The SpTRSM tolerance comment derives the error bound it covers. The itilu0 and gtsv tolerances were measured on gfx1201 and pass on gfx942 and gfx950.
  • Each status check asserts the one status the library returns. Where that status differs from the one the header documents, the check names the ticket that tracks the mismatch.
  • Inputs are built to catch common mistakes: entries in the triangle a solve must ignore, negative values for prune and compress, sentinel-filled outputs and row pointers that are read back, complex alpha and beta for complex types, and beta = 0 for the overwrite path.
  • No test overrides the handle's wavefront size. Results are checked the same way on wave32 and wave64. Tests for paths that only 64-lane hardware takes skip on wave32 and run with full value checks on gfx942/gfx950.
  • Code behind optional features is guarded (ROCSPARSE_WITH_SPMAT_SCALE, ROCSPARSE_WITH_ELL_TRSV, ROCSPARSE_WITH_TRSM_REFACTORING, ROCSPARSE_WITH_SPSORT, ROCSPARSE_WITH_DIAGONAL_SOLVE, rocBLAS). Library integer buffers use rocsparse_int, and buffers behind explicit i32/i64 descriptors use the matching fixed-width type.
  • Descriptors, handles, streams, device memory, environment variables, debug switches and temporary files are owned by RAII guards, so a failing assertion leaves no state behind.

Library bugs found

Cases that expose a library bug either live in that bug's fix PR, or stay here with a workaround and a comment naming the ticket at the site, to be removed by the fix:

  • Fixed in their own PRs (to follow), each adding its test: AISPARSE-896 to AISPARSE-913.
  • Workarounds kept here, tracked by: AISPARSE-903, AISPARSE-904, AISPARSE-909, AISPARSE-920, AISPARSE-923 to AISPARSE-929.
  • Transposed generic SpGEMM and SpGEAM: AISPARSE-907 and AISPARSE-908.
  • Library code no public API reaches, which still counts toward rocSPARSE-unit: AISPARSE-921.
  • Making rocSPARSE-unit gating in Codecov: AISPARSE-922.

Test plan

  • gfx1201: rocsparse-unit-test and rocsparse-unit-test-device pass with default options, and in a --gtest_shuffle run.
  • gfx1201: both binaries build and pass with BUILD_ROCSPARSE_ILP64=ON.
  • gfx1201: both binaries build and pass with ROCSPARSE_ENABLE_SPMAT_SCALE, ROCSPARSE_ENABLE_SDDMM_BATCHED, BUILD_WITH_ELL_TRSV, BUILD_WITH_TRSM_REFACTORING, BUILD_WITH_SPSORT and BUILD_WITH_DIAGONAL_SOLVE all off.
  • gfx950: both unit binaries pass, including the wave64-only tests.
  • All files added by this PR are clang-format (13) clean; in existing files the changed lines are.
  • gfx942: both unit binaries pass, including the wave64-only tests (before the review fixes; CI reruns them).
  • CI on Linux gfx942/gfx950 runs both unit binaries; Codecov rocSPARSE-unit flag.
  • Windows gfx110X: build only. The installed CTest list does not register rocsparse-unit-test-device on Windows, so CI there does not run these tests.

@therock-pr-bot

therock-pr-bot Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

✅ All Checks Passed — Ready for Review

Check Status Details
📝 PR Description ✅ Pass —
⛔ Forbidden Files ✅ Pass —
🧪 Unit Test ⚠️ Warning Error: Source/code files changed without an accompanying unit test.
Expected: add at least one test file named like test_<name>.py / test_<name>.cpp (or <name>_test.*).
Current: code file(s) changed: projects/rocsparse/clients/unittests/unit_test_bfloat16.cpp, projects/rocsparse/clients/unittests/unit_test_device_conv_check.cpp, projects/rocsparse/clients/unittests/unit_test_device_conv_common.hpp, projects/rocsparse/clients/unittests/unit_test_device_conv_dense.cpp, projects/rocsparse/clients/unittests/unit_test_device_conv_descr.cpp (+63 more); no test file found
🔎 pre-commit ✅ Pass —
🚫 Draft PR 🔜 To Be Enabled —
🚩 Feature Flag 🔜 To Be Enabled —
📊 Code Coverage 🔜 To Be Enabled —
🤖 therock-pr-bot ✅ Pass —

🎉 All checks passed! This PR is ready for review.

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

🙋 Wish to Override Policy?

@therock-pr-bot

therock-pr-bot Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

🎉 All checks passed! This PR is ready for review.

@codecov

codecov Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #13475      +/-   ##
===========================================
+ Coverage    75.84%   77.00%   +1.16%     
===========================================
  Files         2881     2876       -5     
  Lines       479150   477218    -1932     
  Branches     72006    71629     -377     
===========================================
+ Hits        363369   367440    +4071     
+ Misses       90863    85679    -5184     
+ Partials     24918    24099     -819     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 48.91% <ø> (-0.03%) ⬇️ Carriedforward from 0651d73
TensileLite-Unit 83.65% <ø> (-0.03%) ⬇️ Carriedforward from 0651d73
hipBLAS 90.62% <ø> (ø) Carriedforward from 0651d73
hipBLASLt 64.34% <ø> (+0.03%) ⬆️ Carriedforward from 0651d73
hipCUB 82.68% <ø> (ø) Carriedforward from 0651d73
hipDNN 87.04% <ø> (+0.19%) ⬆️ Carriedforward from 0651d73
hipFFT 42.00% <ø> (-0.56%) ⬇️ Carriedforward from 0651d73
hipRAND 76.12% <ø> (ø) Carriedforward from 0651d73
hipSOLVER 69.67% <ø> (ø) Carriedforward from 0651d73
hipSPARSE 86.99% <ø> (ø) Carriedforward from 0651d73
rocBLAS 68.73% <ø> (+0.01%) ⬆️ Carriedforward from 0651d73
rocFFT 48.10% <ø> (+2.42%) ⬆️ Carriedforward from 0651d73
rocRAND 57.30% <ø> (-0.01%) ⬇️ Carriedforward from 0651d73
rocSOLVER 76.74% <ø> (ø) Carriedforward from 0651d73
rocSPARSE 83.51% <ø> (+6.35%) ⬆️
rocSPARSE-integration 74.85% <ø> (?)
rocSPARSE-unit 78.93% <ø> (?)
rocThrust 93.15% <ø> (ø) Carriedforward from 0651d73

*This pull request uses carry forward flags. Click here to find out more.
see 312 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kliegeois
kliegeois force-pushed the task/unit-cov-fused branch from b1ddb52 to 13b9150 Compare October 12, 2026 21:39
@kliegeois kliegeois changed the title test(rocsparse): evaluate coverage of the extra unit tests test(rocsparse): add unit tests to raise rocSPARSE coverage above 80% Oct 13, 2026
@kliegeois
kliegeois marked this pull request as ready for review October 13, 2026 01:43
@kliegeois
kliegeois requested a review from a team as a code owner October 13, 2026 01:43
@kliegeois
kliegeois force-pushed the task/unit-cov-fused branch from 7ce7142 to 02d8f45 Compare October 14, 2026 20:08
@kliegeois
kliegeois marked this pull request as draft October 20, 2026 21:53
@kliegeois

Copy link
Copy Markdown
Contributor Author

Moving the PR to draft as we need to discuss how to review it and/or split it.

…SPARSE-879)

Groundwork for the per-area unit tests; no test is added here.

- unit_test_utils.hpp: set_env/unset_env, a scoped_env guard that restores the variable when a test returns early, and temp_file_path with the process id in the name.
- clients/unittests/CMakeLists.txt: compile the additional library translation units into rocsparse-unit-test-device, add the library/src/conversion and library/src/precond/itilu0 include directories, pass -Drocsparse_ILP64 to the unit tests when BUILD_ROCSPARSE_ILP64 is on, and include cmake/unit_tests_<area>.cmake (OPTIONAL) for the areas level2, conv, precond, extra and host, so that an area adds only its own files.
…RSE-879)

CI reporting change only; no test or library code is touched. Write the profile data of rocsparse-test and of the unit-test binaries with different file name prefixes and add a coverage_split target that merges and exports them separately (coverage-unit.info and coverage-integration.info). The Jenkins coverage step uploads both under the flags rocSPARSE-unit and rocSPARSE-integration in addition to the existing combined report.
…es, BLAS wrappers) (AISPARSE-879)

Unit tests for the host area of rocSPARSE, added to the rocsparse-unit-test and rocsparse-unit-test-device binaries through clients/unittests/cmake/unit_tests_host.cmake. The shared setup in clients/unittests/CMakeLists.txt, unit_test_utils.hpp and rocsparse_common.hpp is identical in every unit-test PR of this series, so the PRs can land in any order.
…riangular solves) (AISPARSE-879)

Unit tests for the level2 area of rocSPARSE, added to the rocsparse-unit-test and rocsparse-unit-test-device binaries through clients/unittests/cmake/unit_tests_level2.cmake. The shared setup in clients/unittests/CMakeLists.txt, unit_test_utils.hpp and rocsparse_common.hpp is identical in every unit-test PR of this series, so the PRs can land in any order.
… GEBSR, HYB, ELL) (AISPARSE-879)

Unit tests for the conv area of rocSPARSE, added to the rocsparse-unit-test and rocsparse-unit-test-device binaries through clients/unittests/cmake/unit_tests_conv.cmake. The shared setup in clients/unittests/CMakeLists.txt, unit_test_utils.hpp and rocsparse_common.hpp is identical in every unit-test PR of this series, so the PRs can land in any order.
…sv) (AISPARSE-879)

Unit tests for the precond area of rocSPARSE, added to the rocsparse-unit-test and rocsparse-unit-test-device binaries through clients/unittests/cmake/unit_tests_precond.cmake. The shared setup in clients/unittests/CMakeLists.txt, unit_test_utils.hpp and rocsparse_common.hpp is identical in every unit-test PR of this series, so the PRs can land in any order.
… and GEMM (AISPARSE-879)

Unit tests for the extra area of rocSPARSE, added to the rocsparse-unit-test and rocsparse-unit-test-device binaries through clients/unittests/cmake/unit_tests_extra.cmake. The shared setup in clients/unittests/CMakeLists.txt, unit_test_utils.hpp and rocsparse_common.hpp is identical in every unit-test PR of this series, so the PRs can land in any order.
@kliegeois
kliegeois force-pushed the task/unit-cov-fused branch from 6e93ab0 to a149a23 Compare October 21, 2026 16:10
@kliegeois
kliegeois marked this pull request as ready for review October 21, 2026 16:27
@kliegeois kliegeois changed the title test(rocsparse): add unit tests to raise rocSPARSE coverage above 80% test(rocsparse): add unit tests for 80% unit-only coverage (AISPARSE-879) Oct 21, 2026

@jsandham jsandham left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review

The per-area split, the RAII around handles, env vars and temp files, and the host references on the documented success paths are in good shape. A few patterns undercut the 80% unit-coverage goal, because lines get counted while the result is not actually checked.

  1. Wave64 kernels are selected by writing handle->wavefront_size = 64 on a wave32 GPU. For the preconditioners, that path is allowed to return non-finite values and still pass. The coverage numbers in the description were collected on gfx1201, so those lines count without a numeric oracle. gfx942/gfx950 run the native wave64 kernels and do check them; gfx110X does not run this binary (see the CMake note).
  2. Several calls that return rocsparse_status_success skip the reference check (SpMM COO transpose, SpSM conjugate transpose, symmetric csrmv, transposed SpGEMM/SpGEAM, and rocsparse_csrsv_buffer_size with a null handle). A wrong implementation that returns success stays green, and the lines still count.
  3. rocSPARSE-unit is informational: true, so a unit-coverage drop under 80% will not fail CI.

Inline comments are on the specific sites.

Comment thread codecov.yml Resolved
…-879)

- sddmm alg_dense: distinct A/B values, alpha != 1, beta != 0 and distinct
  initial C on a non-symmetric 3x4 pattern (CSR, CSC, padded ELL, COO-AoS)
  and the width ladder; every stored value is compared with a host
  reference. With rocBLAS success is required; without it the test skips.
- to_host: fail on a hipMemcpy error instead of returning zeros.
- argdescr getters: compare status, index, name, function name, line, msg.
- csxsldu: read lnnz/unnz and the factor pointers back for the row and
  column directions (column path pre-sets ptr[0], see comment).
- copy_csrmv_info: compare every copied array and scalar, and the last
  bytes of the 64-bit copies.
- csrsv_buffer_size null handle, m == 0: accept invalid_handle or success,
  and require buffer_size == 0 on success.
- logging sink, coo_aos/ell/sell getters, SWDEV csr descriptor and second
  hyb copy: check every returned field.
…SE-879)

- bsr: drop the forced 64-lane wavefront on the handle; the specialised
  bsrxmv/bsrmv kernels (2x2..32x32, including 5x5 and 8x8 for every
  precision) now run only on a GPU whose wavefront is 64, value-checked.
- csrmv: a symmetric product that succeeds is compared with the host
  reference (not_implemented stays allowed).
- SpTRSV/SpTRSM/csrsm dispatch: a solve documented as unsupported that
  succeeds anyway is compared with the host reference.
- SpTRSM mixed scalar type: the op_c solve is checked before Y is reset.
- SpTRSV mixed scalar type: the device pointer mode run is checked; the
  f32-scalar/f64-compute device case is left out because rocsparse_sptrsv
  solves with handle->alpha instead of the converted alpha.
- bsrsv: the zero pivot position is checked exactly.
- clang-format 13 on the level2 files.
…-879)

- convert_array: nonzero sources and sentinel targets; every pair that
  converts is compared byte for byte with a host cast. The cross-type
  pairs that return success without writing are no longer asserted.
- dnvec_transfer_from: stop asserting success for the f32-from-i32 no-op.
- gebsr2gebsc: distinct block values, numeric output compared with the
  host block permutation.
- extract: a distinct value per entry, values compared exactly; unit
  diagonal outputs compared against the kept or dropped diagonal
  reference; non-unit run for 64-bit pointers with 32-bit indices.
- csxsldu_compute: expected values for every produced factor and the
  diagonal on a direction change.
- csr2bsr: exact block count, block pointers, and a valid scsr2bsr call
  compared with a host BSR reference.
- gebsr2csr, csr2gebsr nnz, coo2dense_aos int64, csr2csc m == 0: exact
  checks instead of status-only or bound checks.
- Dense, sparse_to_dense and block-value outputs start at a sentinel.
- prune by percentage: distinct magnitudes; print: compare i8/u8 text.
- ell2csr_nnz quick return: sentinel setup, output check left out.
- DevBuf::read checks the hipMemcpy status.
…RSE-879)

- Drop every forced 64-lane run (handle->wavefront_size override) and the
  structure-only check_bsr_matrix path. bsr_wave64_kernels now runs only on
  a wave64 GPU with full value checks; the long block row bsric0, csrilu0
  1024-entry and csrildlt0 value-type cases run natively on both wave sizes;
  x_async_split_wavefront_64 is removed (the bucket test covers it natively).
- ILU(0) long-row inputs (csrilu0 binsearch, spilu0 band/fat rows) get a
  mirrored upper triangle and a diagonally dominant diagonal, so the update,
  hash and binary-search lookups run.
- Singularity trackers: check fresh read-backs and planted exact/near
  positions and classifications.
- Compare the factor in singular_case (near-singular and tolerance after
  analysis) and in validate_stage_api.
- Add spilu0 numeric boost cases; forward the boost to the ILDLT host
  reference. spildlt0 is left out: it ignores its descriptor boost inputs.
- Run check_boost_arguments for csrilu0/bsrilu0, without the undocumented
  null-pointer disable.
- bsrilu0 boost checks the device pivot is exactly +-2.
- gtsv: check the imaginary padding of strided batches; row exchanges for
  every value type.
- itilu0 sweep kernels: check the history (non-negative, decreasing, tol
  reached on an early stop); drop the dead poisoned branch.
- clang-format 13 on every precond file.
…E-879)

- csrgemm numeric groups: distinct values and two products per entry of C;
  row pointer, columns and values compared with the host reference.
- Generic spgemm (CSR every value/index type, BSR bd 1 and 2): non-symmetric
  operands with alpha = 2 and complex imaginary parts, whole C compared.
- spgeam: whole C compared, including the split symbolic/numeric stages;
  csrgeam_nnz row pointer checked for both index bases.
- Transposed generic spgemm/spgeam are no longer run: the library returns
  success and computes the untransposed result.
- spmm: COO with transposed A must succeed and is value-checked.
- spsm: conjugate-transpose solves that succeed are value-checked; complex
  matrices get imaginary off-diagonals.
- sddmm: transposed A/B for every format and storage order.
- spgemm: long-row/bitmap products with sorted B, mixed index bases.
- bsrsm: exact zero-pivot position, tighter float tolerance.
Remove the test cases and comments that work around library bugs; each
case moves, enabled, to the PR that fixes the bug:
AISPARSE-896, AISPARSE-897, AISPARSE-898, AISPARSE-899, AISPARSE-900,
AISPARSE-901, AISPARSE-902, AISPARSE-903, AISPARSE-905, AISPARSE-906,
AISPARSE-907, AISPARSE-908, AISPARSE-909, AISPARSE-910, AISPARSE-911.
…-879)

Add device unit tests for paths that no unit test reached yet:

- unit_test_device_extra_bell.cpp: dense_to_sparse into a blocked ELL
  matrix, checked through spmm against the dense product.
- unit_test_device_extra_sptrsm.cpp: strided batches with one and several
  right-hand sides for every data type and order (including the documented
  unsupported conjugate transposed X), and the diagonal solve mode for CSR
  and CSC with mixed index types.
- unit_test_device_conv_internal.cpp: the csxsldu C entry points (buffer
  size, preprocess, compute).
- unit_test_internal_conversion_csr2ell_batch.cpp: the complex
  csr2ell_strided_batched entry points.
- unit_test_device_level2_bsr.cpp: gebsrmv with an empty block grid.
- unit_test_device_level2_dispatch.cpp: the handle based sptrsv descriptor
  create and destroy.
…macros (AISPARSE-879)

The unit tests compile library translation units, so they now get ROCSPARSE_KEEP_INTERNAL_U16, and ROCSPARSE_WITH_MEMSTAT and ROCSPARSE_DEBUGGING when the library is built with them.
…e profiles (AISPARSE-879)

Jenkins logs when the per-flag uploads are skipped, coverage_cleanup deletes the profraw and profdata files of a previous run, and testing.md describes coverage_split and the rocSPARSE-unit and rocSPARSE-integration flags.
…products (AISPARSE-879)

case_scalar gave beta = 0 an imaginary part for complex types, so the beta = 0 path was never taken. The BSR mv tests now use complex alpha and beta for complex types.
…ns (AISPARSE-879)

The csritilu0 drivers also stop when the residual stagnates below 10 * tol (1e-5 for async_inplace), so a stopping run either reached tol or stagnated.
…SE-879)

Draws that were operands of one expression are unsequenced, so the generated values depended on the compiler. They are now drawn into locals in the order clang used.
…AISPARSE-879)

The unit tests now see rocsparse_ILP64, so index buffers passed to rocsparse_int APIs and to the rocsparse_int csritilu0x instantiations use rocsparse_int, and rocsparse_int buffers behind generic descriptors are described with the matching index type. Buffers behind i32 descriptors keep int32_t.
@kliegeois
kliegeois requested a review from a team as a code owner October 23, 2026 14:56
@kliegeois

Copy link
Copy Markdown
Contributor Author

Thanks @ntrost57, @amontoison. The inline threads have their commits; for the points in the review bodies:

  • Split: we decided as a team to keep this as one PR, reviewed commit by commit (one commit per area, then one per review thread).

  • Second copy of library code: the definitions are mirrored now. Sharing one object library between the library and the tests is a larger build change;

  • Hash probe precondition: tracked by AISPARSE-896, named at the generator precondition.

  • Ticket keys: each workaround now names its ticket at the site. The full list is in the description under "Library bugs found". The csrsv null-handle case turned out to be a public API bug (the m == 0 quick return runs before the argument checks), so it has its own ticket, AISPARSE-929.

  • Several accepted statuses: each check now asserts the one status the library returns. The few that still differ from the header name their ticket.

  • Compile definitions: the unit-test targets get ROCSPARSE_KEEP_INTERNAL_U16, and ROCSPARSE_WITH_MEMSTAT / ROCSPARSE_DEBUGGING when the library is built with them.

  • CI: a failed coverage_split is logged, coverage_cleanup removes the split profiles, and testing.md documents the target and the two flags. Making rocSPARSE-unit gating is AISPARSE-922.

  • Complex beta = 0: beta = 0 now stays 0 for complex types, so the overwrite path runs. I did not add a NaN-in-y case: no header documents that beta = 0 ignores the input y, so the test would pin undocumented behaviour.

  • BSR mv scalars: complex alpha and beta for complex types.

  • blas handle: heap-allocated, released only when blas_destroy_handle deletes it.

  • itilu0 stop: the stopping runs accept either convergence or the library's stagnation exit, with the stagnation rule of each algorithm.

  • RNG order: all draws are sequenced into locals; the generated data is unchanged.

  • Tolerances: the description now says what each area does. The SpTRSM tolerance comment derives the error bound it covers.

  • Test plan: ILP64 added, gfx942 checked from your run (rerun on the fixes pending), Windows timeout noted as unrelated.

  • ILP64: the unit tests now build and pass with BUILD_ROCSPARSE_ILP64=ON; this needed the buffers behind explicit i32 descriptors to be int32_t in a few older files too.

@dso-amd dso-amd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@kliegeois
kliegeois enabled auto-merge (squash) October 24, 2026 04:29
@kliegeois
kliegeois disabled auto-merge October 24, 2026 05:06
… declarations to their own PR (AISPARSE-879)

A change to the root codecov.yml makes CI run every project's tests in the
single-shard quick tier, where the rocSPARSE and rocFFT quick suites time out
on Windows gfx110X (ROCm#13649, ROCm#13414). Undeclared flags upload without a status,
so the split uploads still work until the declarations land.
@kliegeois
kliegeois merged commit 8ac7c83 into ROCm:develop Oct 26, 2026
131 checks passed
@kliegeois
kliegeois deleted the task/unit-cov-fused branch October 26, 2026 19:03
kliegeois added a commit to kliegeois/rocm-libraries that referenced this pull request Oct 26, 2026
…AISPARSE-910)

The primary template of copy_farray_mix_safe_kernel_t had an empty
kernel. For a (target, source) data type pair without a specialization,
for example f32 <- i32, convert_data_array_compute_core launched that
empty kernel and returned success with the target untouched. Callers
such as internal_spmat_transfer_from and spmat_coo2csr (reached from
rocsparse_sparse_to_sparse when the source and target data types
differ) and dnvec_transfer_from then went on with unconverted values.

The primary template now has no kernel and declares
implemented = false; every specialization declares implemented = true.
convert_data_array_compute_core returns rocsparse_status_not_implemented
for pairs that are not implemented, and keeps the n = 0 early success.
The routine is internal and documents no status, so rejecting the pair
is the smallest safe behaviour; adding conversions is left for when a
caller needs one.

internal_spmat_transfer_from, spmat_coo2csr and spmat_csr2coo now
convert the values before they write the index arrays, so a rejected
call leaves the target matrix untouched.

spmat_csc2csr had no data type check and wrote source-typed values
into the target. It now returns rocsparse_status_not_implemented when
both value arrays are set and the data types differ, like
spmat_csr2csc and the other conversions that do not convert values.

The rocsparse_sparse_to_sparse doc now says, by target format, which
mixed data type conversions convert the values: to the same format, to
COO or COO AoS (from CSC, ELL and BSR in permissive mode, through an
intermediate CSR matrix), to CSR also from COO or COO AoS, and to CSC,
ELL and BSR only from the same format. Other combinations return
rocsparse_status_not_implemented, which is now listed as a return
value.

Tests in clients/unittests/unit_test_device_conv_internal.cpp:
- ConvInternal.ConvertArrayDatatypes runs rocsparse::convert_array over
  all 100 pairs of the 10 value data types. The six converting pairs
  and the same-type copies must succeed and match a host reference.
  Every other pair must return rocsparse_status_not_implemented and
  leave the target untouched. n = 0 must succeed for every pair.
- ConvInternal.DnvecTransferFrom checks that an f32 <- i32 transfer
  returns rocsparse_status_not_implemented and leaves the target
  unchanged.
- ConvInternal.SparseToSparseMixedDatatypes converts a matrix with f32
  values into CSR and COO targets with i32 values (CSR -> CSR,
  COO -> CSR, CSR -> COO, CSC -> CSR) with rocsparse_sparse_to_sparse,
  through the sparse_to_sparse helper of the same file. It expects
  rocsparse_status_not_implemented and untouched target arrays.

ConvertArrayDatatypes and DnvecTransferFrom replace the narrower
versions that ROCm#13475 added, which skipped the pairs without a kernel and
the f32 <- i32 transfer.
kliegeois added a commit to kliegeois/rocm-libraries that referenced this pull request Oct 26, 2026
…rse (AISPARSE-911)

rocsparse_ell2csr_nnz returned success without touching csr_nnz or
csr_row_ptr when m, n or ell_width was zero. The caller then read an
uninitialized nnz and an unset row pointer array. The ELL -> CSR path of
rocsparse_sparse_to_sparse goes through the same quick return and
inherited the problem.

The quick return now writes nnz = 0 (to host or device memory according
to the pointer mode) and fills the m + 1 row pointer entries with the
index base before returning. To get the index types right, the
quickreturn and checkarg helpers are now templates on the CSR and ELL
index types, the same as core. The quickreturn helper is instantiated,
like core, for the four (I, J) combinations that gell2csr uses.

rocsparse_sparse_to_sparse reads the nnz of the target (or the ELL
width) into a host variable, but the ELL -> CSR, CSR -> BSR and
CSR -> ELL analysis stages passed that host address to routines that
follow the handle's pointer mode. In device pointer mode, CSR -> BSR
and one-based ELL -> CSR wrote the nnz from a kernel to the host
address and aborted with a GPU memory access fault. An empty CSR -> BSR
or CSR -> ELL conversion returned rocsparse_status_internal_error, and
with the new quick return alone an empty ELL -> CSR conversion would
too. spmat_ell2csr_nnz, spmat_csr2bsr_nnz and spmat_csr2ell_width now
switch the handle to host pointer mode around the call and restore it
afterwards, as spgemm does for csrgemm_nnz. This also covers COO, COO
AoS, CSC and BSR -> ELL, and the other conversions that go through
these stages via an intermediate CSR matrix.

Tests in clients/unittests/unit_test_device_conv_gebsr.cpp:
- ConvGebsr.Ell2CsrEmpty runs m = 0, n = 0 and ell_width = 0 in host
  and device pointer mode. It checks nnz == 0 and the exact contents of
  the row pointer array, including the guard entries past m + 1. It
  also checks that rocsparse_sell2csr then succeeds.
- ConvGebsr.SparseToSparseNnz converts empty matrices and the 4 x 4
  identity, with index base 0 and 1, ELL -> CSR, CSR -> BSR and
  CSR -> ELL with rocsparse_sparse_to_sparse, with 32-bit and 64-bit
  row pointers, in both pointer modes. It checks the target nnz or ELL
  width, the row pointers, column indices and values including guard
  entries, and that the handle's pointer mode is unchanged.

Ell2CsrEmpty replaces the version that ROCm#13475 added, which checked
only the statuses.
kliegeois added a commit to kliegeois/rocm-libraries that referenced this pull request Oct 26, 2026
…SPARSE-901)

check_matrix_csc_core checked the CSC arrays as CSR arrays with the
caller's fill mode. The CSC arrays of A are the CSR arrays of A^T, and
A^T stores the opposite triangle. So a symmetric, Hermitian or
triangular CSC matrix that stored the triangle given by uplo was
reported as rocsparse_data_status_invalid_fill, and one that stored the
other triangle passed. rocsparse_check_spmat (CSC format) goes through
the same code. check_matrix_gebsc_core had the same bug: it passes the
BSC arrays to the GEBSR check with mb and nb swapped and the caller's
fill mode.

The CSR and GEBSR checks now get the opposite fill mode, the same way
spsv and spsm handle CSC input. The header doc of
rocsparse_Xcheck_matrix_csc and rocsparse_Xcheck_matrix_csc_buffer_size
now gives the size of csc_col_ptr as n + 1 instead of m + 1, and the
argument check of csc_col_ptr in rocsparse_Xcheck_matrix_csc uses n, as
the buffer size routine already does.

The client matrix factory builds a CSC or BSC matrix as the CSR or BSR
matrix of the transpose with the same uplo, so these matrices hold the
opposite triangle. testing_check_matrix_csc, testing_check_matrix_gebsc
and the CSC case of testing_check_spmat now pass the opposite uplo to
the factory. The invalid-fill corruption in testing_check_matrix_csc and
testing_check_matrix_gebsc now moves an entry out of the correct
triangle.

Tests in clients/unittests/unit_test_device_conv_spmat.cpp:
- ConvSpmat.CheckMatrixCscFillMode checks 3 x 3 lower and upper
  triangular CSC matrices, as symmetric and as triangular matrices with
  either fill mode, through rocsparse_dcheck_matrix_csc and
  rocsparse_check_spmat. A matrix must be valid only for the fill mode
  of the triangle it stores.
- ConvSpmat.CheckMatrixGebscFillMode does the same for the same block
  patterns in BSC format with 1 x 1 and 2 x 2 blocks, both block
  directions and both storage modes, through
  rocsparse_dcheck_matrix_gebsc.

A new check_matrix_gebsc_file quick entry in test_check_matrix_gebsc.yaml
runs symmetric and triangular rocalution file matrices with both fill
modes, directions and storage modes. The existing entries are all
general, so they never reached the fill check.

The test file includes a trimmed copy of the ROCm#13475 helper header
unit_test_device_conv_common.hpp with only the helpers it uses. It is
registered inline in clients/unittests/CMakeLists.txt; that entry is
dropped when ROCm#13475 lands with cmake/unit_tests_conv.cmake.
kliegeois added a commit to kliegeois/rocm-libraries that referenced this pull request Oct 26, 2026
The BSR -> BSR conversion of rocsparse_sparse_to_sparse copied the
source arrays into the target unchanged, even when the two descriptors
had different block dimensions or block directions. The values came out
wrong, and when the target blocks were smaller than the source blocks
the copy wrote nnzb * source_block_dim^2 values into arrays sized for
the target. internal_spmat_transfer_from did not check the block layout
either.

Now a BSR -> BSR conversion with a different block dimension, or with a
different direction and blocks larger than 1 x 1, goes through the
existing intermediate CSR path. The direction does not change the
arrays of 1 x 1 blocks, so that case stays a plain copy. A target whose
block row or block column count is not the number of rows or columns of
the intermediate CSR matrix (source block count times source block
dimension) divided by the target block dimension, rounded up, is
rejected with rocsparse_status_invalid_size. Otherwise, like the other
conversions on that path, the conversion needs
rocsparse_sparse_to_sparse_permissive and returns
rocsparse_status_not_implemented without it. Source and target must
also have the same index types, and the same value type when both value
arrays are set, as for CSR -> BSR. These type checks now run next to
the grid checks, so a mismatch returns rocsparse_status_not_implemented
before the intermediate CSR matrix is built.

internal_spmat_transfer_from now refuses BSR descriptors whose block
dimension differs, or whose direction differs for blocks larger than
1 x 1. sparse_to_sparse no longer reaches it with such descriptors.

Tests in clients/unittests/unit_test_device_conv_spmat.cpp:
- ConvSpmat.SparseToSparseBsrReblock converts BSR sources to BSR
  targets with every other block dimension from 1 to 4 and either
  direction. The sources cover 32-bit and 64-bit indices, index base 0
  and 1, row-major and column-major blocks, a non-square matrix, a
  source padded past the matrix edge and 1 x 1 blocks. The target
  arrays start as sentinels and must equal host BSR arrays of the
  padded source, the target nnzb must match, and nothing may be
  written past the target entries. Each re-block also checks that the
  conversion returns rocsparse_status_not_implemented without
  permissive mode; the 1 x 1 direction change must succeed without it.
- ConvSpmat.SparseToSparseBsrTargetTooSmall converts the matrix into a
  target with the same block grid and 1 x 1 blocks, with and without
  permissive mode. It expects rocsparse_status_invalid_size and checks
  that nothing is written past the target arrays.
- ConvSpmat.SparseToSparseBsrReblockTypes changes the block dimension
  together with the index type or the value type, in permissive mode,
  and expects rocsparse_status_not_implemented from the analysis
  buffer size.

The test file includes a trimmed copy of the ROCm#13475 helper header
unit_test_device_conv_common.hpp with only the helpers it uses. It is
registered inline in clients/unittests/CMakeLists.txt; that entry is
dropped when ROCm#13475 lands with cmake/unit_tests_conv.cmake.
kliegeois added a commit to kliegeois/rocm-libraries that referenced this pull request Oct 26, 2026
…RSE-904)

Several public headers listed a status that the routine never returns:

- rocsparse_{spmat,coo,csr,csc,ell,dnmat,dnvec}_set_strided_batch
  documented invalid_size for an invalid batch count or stride. All of
  them return invalid_value, like the other scalar argument checks of
  the library.
- rocsparse_{spmat,dnmat,dnvec}_get_strided_batch documented
  invalid_size for an invalid output. A null output pointer gives
  invalid_pointer.
- rocsparse_spmat_set_nnz said only that ELL and BELL descriptors give
  an error. It returns invalid_value, now listed.
- rocsparse_Xprune_dense2csr_by_percentage and
  rocsparse_Xprune_csr2csr_by_percentage, with their _nnz_by_percentage
  routines, documented invalid_size for a percentage outside of
  [0, 100]. They return invalid_value, which the integration tests
  (testing_prune_*_by_percentage.cpp) already expect. The _buffer_size
  routines did not list the size or the percentage checks at all, and
  named only buffer_size for invalid_pointer. None of the six listed
  requires_sorted_storage.
- rocsparse_dnmat_copy_data and rocsparse_dnmat_transpose documented
  invalid_value for different data types. They return not_implemented
  ("mixed precision not implemented"). The lists also lacked
  invalid_handle, and now state the dimension and batch-count rule.

The headers now describe what the code returns. No routine changes.

Test: the test files come from ROCm#13475. ConvDescr.EllNnzAndStridedBatch,
ConvDescr.DnmatCopyInvalid,
ConvPrune.PruneCsr2CsrByPercentageQuickReturnsAndArguments and
ConvPrune.PruneDense2CsrByPercentageArguments are ROCm#13475's tests with
the either-status checks pinned to the code's status, plus new checks:
ELL batch_count = -1, set_nnz on ELL, the broadcast and order-switch
alpha cases of dnmat_copy_data, and the out-of-range percentage on the
csr2csr compute and dense2csr buffer-size calls.
ConvDescr.StridedBatchSettersAndGetters (the other six setters and the
three getters) and ConvDescr.DnmatTransposeInvalid (every documented
transpose status, alpha included) are new. The shared helpers are in
unit_test_device_conv_common.hpp.
@assistant-librarian

Copy link
Copy Markdown
Contributor

TheRock Submodule Bump Activity

Newest first

kliegeois added a commit that referenced this pull request Nov 6, 2026
…gs (AISPARSE-879) (#14388)

JIRA ID : AISPARSE-879.

## Summary

Declares the `rocSPARSE-unit` and `rocSPARSE-integration` Codecov flags
that #13475 uploads, so they carry forward and report informational
project statuses (80% target on `rocSPARSE-unit`). The combined
`rocSPARSE` flag is unchanged.

This was split out of #13475. Any change to the root `codecov.yml` makes
CI run every project's tests in the single-shard quick tier, where the
rocSPARSE and rocFFT quick suites time out on Windows gfx110X (#13649,
#13414). Keeping it separate lets #13475 run its normal rocSPARSE-only
CI.

## Merge order

Either order works. Before this lands, the #13475 uploads still appear
in Codecov, without a status and without carry-forward (`default_rules:
carryforward: false`). After both land, the flags behave as described
above.

## Test plan

- `codecov.yml` parses, and the flag entries match the ones reviewed in
#13475.
- Expect the Windows gfx110X rocSPARSE and rocFFT quick-tier timeouts
(#13649, #13414) on this PR: they come from the all-projects quick run
that a `codecov.yml` change triggers, not from this change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants