Skip to content

feat(rocsparse): add the rocsparse_spsort public API - #12553

Merged
jsandham merged 10 commits into
developfrom
users/jsandham/spsort-api
Oct 12, 2026
Merged

jsandham merged 10 commits into
developfrom
users/jsandham/spsort-api

Conversation

@jsandham

@jsandham jsandham commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

First PR of a stack adding a generic sparse matrix sort, rocsparse_spsort. It sorts an input matrix A into an output matrix B, or in place when the same descriptor is passed for both. COO, CSR and CSC are supported, including uniform strided batched matrices (every batch has the same sparsity pattern, and only the values differ).

This PR adds only the public API and its documentation, so the interface can be reviewed on its own:

  • rocsparse_spsort_buffer_size and rocsparse_spsort in internal/generic/rocsparse_spsort.h.
  • The rocsparse_spsort_descr descriptor with rocsparse_spsort_descr_create, rocsparse_spsort_descr_destroy and rocsparse_spsort_set_input.
  • The rocsparse_spsort_alg, rocsparse_spsort_input and rocsparse_spsort_stage enums.
  • Entries in the reference docs and in the hipGraph support table.

The functions are declared but not implemented until the following PRs in the stack. The doc example snippets are added together with the examples.

Test plan

  • Compiled a C and a C++ translation unit including rocsparse.h and using the new types.
  • Built the library with this PR.

JIRA ID: AISPARSE-717

Stack

This PR is part of a stack. Review and merge in order:

  1. feat(rocsparse): add the rocsparse_spsort public API #12553 ⬅ this PR
  2. feat(rocsparse): implement rocsparse_spsort for COO matrices #12555
  3. feat(rocsparse): implement rocsparse_spsort for CSR matrices #12556
  4. feat(rocsparse): implement rocsparse_spsort for CSC matrices #12557
  5. test(rocsparse): add rocsparse_spsort tests and benchmarks for COO #12558
  6. test(rocsparse): add rocsparse_spsort tests and benchmarks for CSR #12559
  7. test(rocsparse): add rocsparse_spsort tests and benchmarks for CSC #12560

Declares the generic sparse matrix sort: rocsparse_spsort_buffer_size and
rocsparse_spsort, the rocsparse_spsort_descr descriptor with its create,
destroy and set_input functions, and the rocsparse_spsort_alg,
rocsparse_spsort_input and rocsparse_spsort_stage enums. Also adds the
corresponding documentation entries.

The implementation follows in later changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@therock-pr-bot

therock-pr-bot Bot commented Sep 24, 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/library/include/internal/generic/rocsparse_spsort.h, projects/rocsparse/library/include/internal/rocsparse-generic.h, projects/rocsparse/library/include/rocsparse-auxiliary.h, projects/rocsparse/library/include/rocsparse-types.h; 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

Copy link
Copy Markdown

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

@codecov

codecov Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

❌ Your project check has failed because the head coverage (74.09%) is below the target coverage (80.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop   #12553   +/-   ##
========================================
  Coverage    72.12%   72.12%           
========================================
  Files         2869     2869           
  Lines       473745   473826   +81     
  Branches     69883    69895   +12     
========================================
+ Hits        341683   341742   +59     
- Misses      108312   108325   +13     
- Partials     23750    23759    +9     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 49.33% <ø> (ø) Carriedforward from a06350d
TensileLite-Unit 83.30% <ø> (ø) Carriedforward from a06350d
hipBLAS 90.62% <ø> (ø) Carriedforward from a06350d
hipBLASLt 38.91% <ø> (ø) Carriedforward from a06350d
hipCUB 82.68% <ø> (ø) Carriedforward from a06350d
hipDNN 86.66% <ø> (ø) Carriedforward from a06350d
hipFFT 43.43% <ø> (ø) Carriedforward from a06350d
hipRAND 76.12% <ø> (ø) Carriedforward from a06350d
hipSOLVER 68.96% <ø> (ø) Carriedforward from a06350d
hipSPARSE 86.99% <ø> (ø) Carriedforward from a06350d
rocBLAS 48.24% <ø> (ø) Carriedforward from a06350d
rocFFT 51.45% <ø> (ø) Carriedforward from a06350d
rocRAND 57.45% <ø> (ø) Carriedforward from a06350d
rocSOLVER 76.83% <ø> (ø) Carriedforward from a06350d
rocSPARSE 74.09% <ø> (-<0.01%) ⬇️
rocThrust 93.15% <ø> (ø) Carriedforward from a06350d

*This pull request uses carry forward flags. Click here to find out more.

🚀 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.

@jsandham
jsandham removed this pull request from stack #12562 September 24, 2026 22:14
@jsandham
jsandham added this pull request to stack #12575 September 24, 2026 22:15
jsandham and others added 2 commits September 24, 2026 22:22
- Rename rocsparse_create_spsort_descr and rocsparse_destroy_spsort_descr
  to rocsparse_spsort_descr_create and rocsparse_spsort_descr_destroy, and
  give them rocsparse_handle and rocsparse_error* arguments.
- Rename the mat_A and mat_B arguments of rocsparse_spsort_buffer_size and
  rocsparse_spsort to source and target, and buffer_size to
  buffer_size_in_bytes.
- Document the type of the data expected by each rocsparse_spsort_input.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
jsandham and others added 2 commits September 30, 2026 13:14
Every batch must have the same sparsity pattern, and only the values may
differ, as for the other generic routines.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep rocsparse_spgeam_set_input and rocsparse_spgeam_get_output together.

Co-authored-by: Cursor <cursoragent@cursor.com>
jsandham and others added 2 commits September 30, 2026 20:00
The CSR and CSC formats always sort the indices within each row or
column, so they do not need a direction.

Co-authored-by: Cursor <cursoragent@cursor.com>
Rename the buffer and error parameters to buffer and p_error, document
the host blocking and hipGraph behaviour of both routines, add the
rocsparse_spsort_alg_radix_sort algorithm, and allow a single source
matrix to be sorted into every sample of a batched target matrix.

Co-authored-by: Cursor <cursoragent@cursor.com>
@dso-amd

dso-amd commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

/docs-preview

@assistant-librarian

Copy link
Copy Markdown
Contributor

Docs preview for rocsparse is building on Read the Docs: https://rocm.docs.amd.com/projects/rocSPARSE/en/users-jsandham-spsort-api/ (Note: If a pull request includes multiple projects, only the preview for the first project will be built.)

@dso-amd

dso-amd commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Can we add a changelog entry for the new feature?

@ntrost57

ntrost57 commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

changelog is missing I think:

  • added: spsort
  • fixed: out of bounds

jsandham and others added 2 commits October 6, 2026 14:27
Separate the \ref to rocsparse_format_csc from the following colon, which
broke the documentation build. Document that rocsparse_spsort and
rocsparse_spsort_buffer_size reject the u8, i32 and u32 data types, and
that rocsparse_spsort_set_input returns rocsparse_status_invalid_value
once the analysis stage has been executed.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@jsandham

jsandham commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

changelog is missing I think:

  • added: spsort
  • fixed: out of bounds

Add cspsort to changelog in this PR and the fix entry in #12555.

@jsandham

jsandham commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Can we add a changelog entry for the new feature?

Done

… users/jsandham/spsort-api

Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	projects/rocsparse/CHANGELOG.md
@jsandham
jsandham merged commit 4d0a7e5 into develop Oct 12, 2026
115 of 116 checks passed
@jsandham
jsandham deleted the users/jsandham/spsort-api branch October 12, 2026 13:46
danila-permogorskii pushed a commit to danila-permogorskii/rocm-libraries that referenced this pull request Oct 12, 2026
)

## Motivation
Implements the SpSort descriptor, `rocsparse_spsort_buffer_size` and
`rocsparse_spsort` for COO matrices:
- Sorts by row (`rocsparse_direction_row`) or by column
(`rocsparse_direction_column`).
- Out of place (A into B) or in place (the same descriptor for A and B).
- Uniform strided batched matrices, where A and B may have different
batch strides. Every batch has the same sparsity pattern, so the indices
are sorted once and the resulting permutation is applied to the values
of every batch.

Adds the internal `rocsparse::coosort_buffer_size` and
`rocsparse::coosort` in the existing `rocsparse_coosort.cpp`. They take
the algorithm, the direction, the source and target sparse matrix
descriptors and the buffer size, and gather the values of each batch
with the shared permutation. The index type dispatch happens right
before the kernel launch through the existing `gcoosort` routines, so
the coosort templates are unchanged.

The SpSort descriptor is defined in `rocsparse_spsort.hpp`, with
`rocsparse_spsort_descr.cpp` (descriptor and
`rocsparse_spsort_set_input`), `rocsparse_spsort_buffer_size.cpp` and
`rocsparse_spsort.cpp`.

The extra gather buffer for the values is only allocated when sorting in
place. CSR and CSC return `rocsparse_status_not_implemented` until the
next PRs.

## Test plan
- Built the library and ran `example_rocsparse_spsort_coo`.
- Ran the existing `coosort` tests (quick and pre_checkin).
- Ran the `spsort_coo` tests added later in the stack against this
library (quick and pre_checkin).

JIRA ID: AISPARSE-717

## Stack
This PR is part of a stack. Review and merge in order:

1. ROCm#12553
2. ROCm#12555 ⬅ this PR
3. ROCm#12556
4. ROCm#12557
5. ROCm#12558
6. ROCm#12559
7. ROCm#12560

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
danila-permogorskii pushed a commit to danila-permogorskii/rocm-libraries that referenced this pull request Oct 12, 2026
)

## Motivation
Adds CSR support to `rocsparse_spsort`. It sorts the column indices, and
the corresponding values, within each row. The direction must be
`rocsparse_direction_row`, and any other direction returns
`rocsparse_status_invalid_value`. Out of place, in place and strided
batched matrices are supported.

Batches must be uniform: every batch has the same sparsity pattern, so
the column indices are sorted once and the resulting permutation is
applied to the values of every batch.

Batch rules:
- The columns/values batch stride must be at least nnz.
- The offsets batch stride must be 0 (shared row pointer) or at least m
+ 1.
- B may only share its row pointer if A does.

Changes:
- Adds the internal `rocsparse::csrsort_buffer_size` and
`rocsparse::csrsort` in the existing `rocsparse_csrsort.cpp`, which take
the source and target sparse matrix descriptors like the COO ones. They
wrap `rocsparse::csxsort_buffer_size` and `rocsparse::csxsort`, which
CSC reuses in the next PR.
- Turns the existing csrsort implementation in the same file into file
local templates on the row pointer and column index types, dispatched on
the index types right before the call. The `rocsparse_csrsort` C API now
calls those templates.
- Adds the mixed 32-bit key and 64-bit value segmented radix sort
instantiations needed for 64-bit row pointers with 32-bit column
indices.

## Test plan
- Built the library and ran `example_rocsparse_spsort`.
- Ran the existing `csrsort` and `cscsort` tests (quick and
pre_checkin).
- Ran the `spsort_csr` tests added later in the stack against this
library (quick and pre_checkin).

JIRA ID: AISPARSE-717

## Stack
This PR is part of a stack. Review and merge in order:

1. ROCm#12553
2. ROCm#12555
3. ROCm#12556 ⬅ this PR
4. ROCm#12557
5. ROCm#12558
6. ROCm#12559
7. ROCm#12560

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
danila-permogorskii pushed a commit to danila-permogorskii/rocm-libraries that referenced this pull request Oct 12, 2026
)

## Motivation
Adds CSC support to `rocsparse_spsort`. It sorts the row indices, and
the corresponding values, within each column. Out of place, in place and
strided batched matrices are supported, with the same batch rules as
CSR, using n + 1 for the column pointer.

Adds the internal `rocsparse::cscsort_buffer_size` and
`rocsparse::cscsort` in the existing `rocsparse_cscsort.cpp`. They take
the source and target sparse matrix descriptors and reuse
`rocsparse::csxsort_buffer_size` and `rocsparse::csxsort` from the CSR
PR, which sort a CSC matrix as the CSR layout of its transpose.

## Test plan
- Built the library.
- Ran the existing `csrsort` and `cscsort` tests.
- Ran the `spsort_csc` tests added later in the stack against this
library (quick and pre_checkin).

JIRA ID: AISPARSE-717

## Stack
This PR is part of a stack. Review and merge in order:

1. ROCm#12553
2. ROCm#12555
3. ROCm#12556
4. ROCm#12557 ⬅ this PR
5. ROCm#12558
6. ROCm#12559
7. ROCm#12560

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
danila-permogorskii pushed a commit to danila-permogorskii/rocm-libraries that referenced this pull request Oct 12, 2026
…OCm#12558)

## Motivation
Adds tests and a benchmark for `rocsparse_spsort` with COO matrices:
- Checks out of place results (A unchanged) and in place results against
a host reference, for both directions.
- Covers strided batched matrices, with A padded between batches to
check that its stride is honoured.
- Checks the SpSort argument handling: descriptor inputs, stage
ordering, matching A and B, and batch counts and strides.
- Adds the `spsort_coo` benchmark.

The test times are about 0.6 s for quick, 6 s for pre_checkin and 67 s
for nightly.

## Test plan
- `rocsparse-test --gtest_filter='*spsort*'`: 382 tests passed.
- `rocsparse-bench -f spsort_coo`

JIRA ID: AISPARSE-717

## Stack
This PR is part of a stack. Review and merge in order:

1. ROCm#12553
2. ROCm#12555
3. ROCm#12556
4. ROCm#12557
5. ROCm#12558 ⬅ this PR
6. ROCm#12559
7. ROCm#12560

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
danila-permogorskii pushed a commit to danila-permogorskii/rocm-libraries that referenced this pull request Oct 12, 2026
…OCm#12559)

## Motivation
Adds tests and a benchmark for `rocsparse_spsort` with CSR matrices:
- Checks out of place and in place results against a host reference that
sorts each row.
- Covers all supported row pointer and column index type combinations
(i32/i32, i64/i32, i64/i64).
- Covers strided batched matrices, with A's offsets and columns/values
padded between batches.
- Checks the CSR specific argument handling: the direction and the batch
stride rules.
- Adds the `spsort_csr` benchmark.

The test times are about 0.5 s for quick, 5 s for pre_checkin and 35 s
for nightly.

## Test plan
- `rocsparse-test --gtest_filter='*spsort*:-nightly*spsort_coo*'`: 486
tests passed, including 179 nightly `spsort_csr` tests.
- `rocsparse-bench -f spsort_csr`

JIRA ID: AISPARSE-717

## Stack
This PR is part of a stack. Review and merge in order:

1. ROCm#12553
2. ROCm#12555
3. ROCm#12556
4. ROCm#12557
5. ROCm#12558
6. ROCm#12559 ⬅ this PR
7. ROCm#12560

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
danila-permogorskii pushed a commit to danila-permogorskii/rocm-libraries that referenced this pull request Oct 12, 2026
…OCm#12560)

## Motivation
Adds tests and a benchmark for `rocsparse_spsort` with CSC matrices:
- Checks out of place and in place results against a host reference that
sorts each column.
- Covers all supported column pointer and row index type combinations.
- Covers strided batched matrices.
- Checks the CSC specific argument handling: the direction and the batch
stride rules.
- Adds the `spsort_csc` benchmark.

The test times are about 0.5 s for quick, 5 s for pre_checkin and 33 s
for nightly.

## Test plan
- `rocsparse-test
--gtest_filter='quick*spsort*:pre_checkin*spsort*:nightly*spsort_csc*'`:
651 tests passed.
- `rocsparse-bench -f spsort_csc`

JIRA ID: AISPARSE-717

## Stack
This PR is part of a stack. Review and merge in order:

1. ROCm#12553
2. ROCm#12555
3. ROCm#12556
4. ROCm#12557
5. ROCm#12558
6. ROCm#12559
7. ROCm#12560 ⬅ this PR

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
kliegeois pushed a commit that referenced this pull request Oct 12, 2026
## Motivation
Adds the `BUILD_WITH_SPSORT` build option, which gates
`rocsparse_spsort` so that it can be enabled or disabled at build time,
in the same way as `BUILD_WITH_DIAGONAL_SOLVE`. The option is `ON` by
default.

When the option is `OFF`, `ROCSPARSE_WITH_SPSORT` is not defined in
`rocsparse-config.h` and the following are left out:
- The `rocsparse_spsort` and `rocsparse_spsort_buffer_size`
declarations, the `rocsparse_spsort_descr_create`,
`rocsparse_spsort_descr_destroy` and `rocsparse_spsort_set_input`
declarations, and the `rocsparse_spsort_descr`, `rocsparse_spsort_alg`,
`rocsparse_spsort_input` and `rocsparse_spsort_stage` types.
- The implementation of those routines. Their sources are still listed
in the library, but compile to nothing.
- The `spsort_coo`, `spsort_csr` and `spsort_csc` tests and benchmarks.
- The `rocsparse_spsort` documentation examples, which build as a stub
that prints that rocSPARSE was built without `rocsparse_spsort`.

`ROCSPARSE_WITH_SPSORT` is also added to the Doxygen `PREDEFINED` list
so the documentation is still generated.

The legacy `coosort`, `csrsort` and `cscsort` routines, and the fixes
made to them earlier in the stack, are not gated.

This PR only adds the guards. It does not change the code of the PRs
below it, so their CI results are unaffected.

## Test plan
- Build with `-DBUILD_WITH_SPSORT=OFF`: the library, `rocsparse-test`,
`rocsparse-bench` and the samples build, `librocsparse.so` exports no
`rocsparse_spsort*` symbols, and the spsort examples print the stub
message. `rocsparse-test
--gtest_filter='*coosort*:*csrsort*:*cscsort*'`: 556 tests passed.
- Build with `-DBUILD_WITH_SPSORT=ON`: `rocsparse-test
--gtest_filter='*spsort*'`: 1482 tests passed.

JIRA ID: AISPARSE-717

## Stack
This PR is part of a stack. Review and merge in order:

1. #12553
2. #12555
3. #12556
4. #12557
5. #12558
6. #12559
7. #12560
8. #13392 ⬅ this PR

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
@assistant-librarian

Copy link
Copy Markdown
Contributor

TheRock Submodule Bump Activity

Newest first

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