Skip to content

AISPARSE-703: clamp bsr2csr / csr2bsr / csr2bsr_nnz block-row grids and add grid-stride loops - #12007

Open
kliegeois wants to merge 1 commit into
ROCm:developfrom
kliegeois:aisparse-703-bsr-grid-clamp
Open

AISPARSE-703: clamp bsr2csr / csr2bsr / csr2bsr_nnz block-row grids and add grid-stride loops#12007
kliegeois wants to merge 1 commit into
ROCm:developfrom
kliegeois:aisparse-703-bsr-grid-clamp

Conversation

@kliegeois

Copy link
Copy Markdown
Contributor

JIRA ID: AISPARSE-703

The BSR conversion routines launch one block, or one wavefront, per block row,
with the count taken from the 64-bit template parameter J and no clamp against
the device grid limit. Ten launch sites across three files, none of them touched
by any other ticket in the epic.

How the 64-bit path is reached

The legacy rocsparse_Xbsr2csr entry point takes rocsparse_int and so selects
J = int32_t; it cannot reach the defect. The generic API can:
rocsparse_sparse_to_sparse at stage compute calls spmat_bsr2csr, which calls
gbsr2csr passing source->rows as an int64_t, and that instantiates
bsr2csr_core<T, I, int64_t>. rocsparse_gbsr2csr is also directly callable and
takes an int64_t mb.

What changed

Each affected grid is clamped against handle->properties.maxGridSize[0] and the
corresponding kernel gains a grid-stride loop over block rows. Most of the
launches sit inside #define macro bodies expanded once per block-dimension
branch, so clamping the macro covers several call sites at once.

The kernels that use global scratch (csr2bsr_65_inf_kernel,
csr2bsr_nnz_65_inf_kernel) needed one extra change: their temp1/temp2/temp3
segments were indexed by the block row, which goes out of bounds as soon as the
grid is clamped below the block-row count. They are now partitioned by the
physical block index instead, which is bounded by the launched grid by
construction. Each iteration re-initialises its segment, so sequential reuse
across grid-stride iterations is safe.

The two launches that already divide by 256 and by 1024 are left alone — they
cannot overflow the grid limit and the ticket says to leave them.

Loop bounds are block-uniform in every kernel, so the __syncthreads() calls
stay convergent. The wavefront-per-row kernel has no block-wide barrier at all,
only __threadfence_block().

Reviewing

Wrapping the kernel bodies in the grid-stride loop re-indents them, which
inflates the raw diff to +175/-132. Ignoring whitespace it is +108/-65. Please
review with ?w=1
appended to the Files changed URL.

Testing

Built and tested on gfx1201 (Radeon RX 9070 XT): 1,639 conversion tests, 0
failing.

Coverage caveat: grid.x on this hardware allows about 2.1 billion blocks, which
at divisor 1 corresponds to roughly 17 GB of row pointers alone, so the clamp
cannot be driven past one grid-stride iteration on any real device. The loop is a
correctness guard for the clamp rather than a path the test suite can enter.

…e loops

The BSR conversion routines launched one block (or wavefront) per block
row with the grid taken directly from the 64-bit template parameter J and
no clamp. Reached via the generic API (rocsparse_sparse_to_sparse ->
spmat_bsr2csr -> gbsr2csr, and rocsparse_gbsr2csr) with J=int64_t, the
grid overflows the 32-bit x-dimension limit at ~2.1e9 block rows.

Clamp every block-per-row / wavefront-per-row grid against
handle->properties.maxGridSize[0] and add a grid-stride loop over block
rows to the corresponding kernels so a clamped grid still covers all
block rows. The block_dim==1 launches already use divisor 1024/256 with
a grid-stride kernel and are left unchanged.

Part of ROCM-28974 (AISPARSE-703).

Co-authored-by: Cursor <cursoragent@cursor.com>
@kliegeois
kliegeois requested a review from a team as a code owner September 11, 2026 21:06
@therock-pr-bot

therock-pr-bot Bot commented Sep 11, 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/src/conversion/bsr2csr_device.h, projects/rocsparse/library/src/conversion/csr2bsr_device.h, projects/rocsparse/library/src/conversion/csr2bsr_nnz_device.h, projects/rocsparse/library/src/conversion/rocsparse_bsr2csr.cpp, projects/rocsparse/library/src/conversion/rocsparse_csr2bsr.cpp (+1 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

Copy link
Copy Markdown

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

@codecov

codecov Bot commented Sep 11, 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.61%) 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   #12007   +/-   ##
========================================
  Coverage    70.55%   70.55%           
========================================
  Files         2810     2810           
  Lines       462487   462501   +14     
  Branches     68090    68093    +3     
========================================
+ Hits        326286   326298   +12     
  Misses      112661   112661           
- Partials     23540    23542    +2     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 46.45% <ø> (ø) Carriedforward from 7e7415b
TensileLite-Unit 76.06% <ø> (ø) Carriedforward from 7e7415b
hipBLAS 90.62% <ø> (ø) Carriedforward from 7e7415b
hipBLASLt 35.27% <ø> (ø) Carriedforward from 7e7415b
hipCUB 82.68% <ø> (ø) Carriedforward from 7e7415b
hipDNN 87.02% <ø> (ø) Carriedforward from 7e7415b
hipFFT 42.66% <ø> (ø) Carriedforward from 7e7415b
hipRAND 76.12% <ø> (ø) Carriedforward from 7e7415b
hipSOLVER 68.92% <ø> (ø) Carriedforward from 7e7415b
hipSPARSE 86.99% <ø> (ø) Carriedforward from 7e7415b
rocBLAS 48.31% <ø> (ø) Carriedforward from 7e7415b
rocFFT 51.72% <ø> (ø) Carriedforward from 7e7415b
rocRAND 56.90% <ø> (ø) Carriedforward from 7e7415b
rocSOLVER 76.83% <ø> (ø) Carriedforward from 7e7415b
rocSPARSE 74.61% <100.00%> (+<0.01%) ⬆️
rocThrust 91.60% <ø> (ø) Carriedforward from 7e7415b

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

Files with missing lines Coverage Δ
...parse/library/src/conversion/rocsparse_bsr2csr.cpp 82.85% <100.00%> (ø)
...parse/library/src/conversion/rocsparse_csr2bsr.cpp 85.67% <100.00%> (+0.10%) ⬆️
...e/library/src/conversion/rocsparse_csr2bsr_nnz.cpp 73.31% <100.00%> (+0.15%) ⬆️

... and 1 file 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.

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.

1 participant