Skip to content

[REVIEW] Addition of gemm_strided_batched - #3106

Merged
rapids-bot[bot] merged 9 commits into
NVIDIA:mainfrom
landrumb:landrumb/cublaslt-strided-batched-matmul
Aug 13, 2026
Merged

[REVIEW] Addition of gemm_strided_batched#3106
rapids-bot[bot] merged 9 commits into
NVIDIA:mainfrom
landrumb:landrumb/cublaslt-strided-batched-matmul

Conversation

@landrumb

Copy link
Copy Markdown
Contributor

This PR adds the wrapper for strided and batched matrix multiplication with cublasLt requested by @achirkin in the reviews for NVIDIA/cuvs#2352 , where this operation is used for batched row-wise dot products. TF32 support is included.

The associated test covers most of the functionality besides eg transposed inputs, but can be expanded if reviewer(s) prefer.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 00b7982f-6c45-4fe4-9cbb-6ddcdb8da12b

📥 Commits

Reviewing files that changed from the base of the PR and between 406a785 and 8d73318.

📒 Files selected for processing (1)
  • cpp/include/raft/linalg/gemm.cuh
🚧 Files skipped from review as they are similar to previous changes (1)
  • cpp/include/raft/linalg/gemm.cuh

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added strided-batched matrix multiplication for rank-3 device arrays.
    • Added configurable compute types, including TF32 support.
    • Added support for row-major and column-major layouts, custom strides, batch counts, transpose options, and host- or device-resident scalar parameters.
  • Bug Fixes
    • Added validation for batch and matrix dimensions and strides.
    • Improved handling of default scalar values and padded batches.
    • Added coverage to verify output padding remains unchanged.

Walkthrough

Changes

The change adds cuBLASLt strided-batched matrix layouts and execution, public gemm_batched overloads with explicit and default compute types, and tests for padded column-major and contiguous row-major batches.

Strided-batched GEMM

Layer / File(s) Summary
Batched layouts and compute descriptors
cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp
Matrix layouts validate batch counts and set batch-count and batch-stride attributes. Matmul descriptors accept an optional compute type.
Batched execution and GEMM API
cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp, cpp/include/raft/linalg/gemm.cuh
The detail wrapper prepares scalars and calls cublasLtMatmul. The public gemm_batched overloads validate rank-3 mdspans, derive strides, support row- and column-major layouts, and select explicit or default compute types.
Padded and contiguous batch validation
cpp/tests/linalg/gemm_basic.cpp
The tests validate padded column-major batches, preserved padding, optional coefficients, TF32 computation, and contiguous row-major batches.

Estimated code review effort: 3 (Moderate) | ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% 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 The description clearly explains the strided-batched cuBLASLt wrapper, TF32 support, use case, and test coverage.
Title check ✅ Passed The title concisely identifies the addition of strided-batched GEMM functionality, which is the main change.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@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)
cpp/tests/linalg/gemm_basic.cpp (1)

188-212: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extend the batched coverage to the remaining argument combinations.

The test covers only the non-transposed, default-coefficient, host-pointer path. The following cases stay untested and each one exercises distinct code in matmul_strided_batched:

  • trans_a / trans_b set to true, which changes the layout row/column swap and the lda/ldb requirements.
  • Explicit non-null alpha and beta, which verifies that existing C padding and values are combined correctly.
  • DevicePointerMode = true, which exercises the coef_wrapper device allocation path.
  • A zero batch stride, which is the cuBLASLt broadcast case.

Do you want me to generate these additional test cases?

As per path instructions: "Tests should use synthetic data, validate numerical results and padding, and cover important edge cases."

🤖 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 `@cpp/tests/linalg/gemm_basic.cpp` around lines 188 - 212, Extend the batched
GEMM coverage around gemm_strided_batched to add synthetic cases for transposed
A/B operands with corresponding lda/ldb values, non-null alpha and beta while
validating C padding and accumulation, DevicePointerMode enabled to exercise
device coefficient allocation, and zero batch strides for broadcast behavior.
Assert numerical outputs and untouched padding for each case while preserving
the existing baseline test.

Source: Path instructions

🤖 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 `@cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp`:
- Around line 378-416: Update matmul_strided_batched to validate positive m, n,
k, and batch_count; require lda and ldc to meet the row requirements for the
configured layouts and ldb to meet the corresponding B-matrix requirement;
validate non-null matrix and scalar pointers and permitted pointer locations
before constructing cuBLASLt layouts. Validate strides for invalid values while
explicitly allowing zero strides for broadcasting, and reject any precondition
failure before forwarding inputs to cuBLASLt.
- Around line 417-432: Update the strided-batched matmul flow around
cublasLtMatmul to create or reuse a valid initialized cublasLtMatmulAlgo_t
instead of passing nullptr. Cache heuristic algorithm results and their
descriptors using strides, batch_count, and compute_type in the key, then
configure and pass workspace when supported while preserving the existing
operation and coefficient parameters.

---

Nitpick comments:
In `@cpp/tests/linalg/gemm_basic.cpp`:
- Around line 188-212: Extend the batched GEMM coverage around
gemm_strided_batched to add synthetic cases for transposed A/B operands with
corresponding lda/ldb values, non-null alpha and beta while validating C padding
and accumulation, DevicePointerMode enabled to exercise device coefficient
allocation, and zero batch strides for broadcast behavior. Assert numerical
outputs and untouched padding for each case while preserving the existing
baseline test.
🪄 Autofix

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

Review profile: CHILL

Plan: Enterprise

Run ID: 821297de-e419-4c57-93c2-210c59d3c380

📥 Commits

Reviewing files that changed from the base of the PR and between 07652ba and 088de61.

📒 Files selected for processing (3)
  • cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp
  • cpp/include/raft/linalg/gemm.cuh
  • cpp/tests/linalg/gemm_basic.cpp

Comment thread cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp
Comment thread cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp

@achirkin achirkin 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.

Thanks for implementing this! Let's refine the API (see below)

Comment thread cpp/include/raft/linalg/gemm.cuh Outdated
Comment thread cpp/include/raft/linalg/gemm.cuh Outdated
@achirkin achirkin added feature request New feature or request non-breaking Non-breaking change labels Aug 11, 2026
Co-authored-by: Artem M. Chirkin <9253178+achirkin@users.noreply.github.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 (2)
cpp/include/raft/linalg/gemm.cuh (2)

286-317: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the Doxygen contract for gemm_batched.

The documentation describes undeclared raw-pointer parameters and template types. Document the 3D mdspan arguments, batch-axis convention, supported layouts, scalar-view behavior, and compute_type_override.

As per path instructions, new public APIs require Doxygen documentation.

🤖 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 `@cpp/include/raft/linalg/gemm.cuh` around lines 286 - 317, Update the Doxygen
block for gemm_batched to match its declared API: document the 3D mdspan A, B,
and C arguments, explain the batch-axis convention, list supported layouts,
describe scalar-view behavior for alpha and beta, and document
compute_type_override. Remove references to undeclared raw-pointer parameters
and template types while preserving the public API’s actual semantics.

Source: Path instructions


328-354: 🎯 Functional Correctness | 🔴 Critical | 🏗️ Heavy lift

Implement gemm_batched from its mdspan parameters.

The overload passes undeclared identifiers to detail::matmul_strided_batched, passes optional scalar objects instead of nullable scalar pointers, and ignores compute_type_override. Derive dimensions, leading dimensions, element strides, and batch count from the 3D mdspans. Validate extents and supported contiguous layouts before dispatch.

🤖 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 `@cpp/include/raft/linalg/gemm.cuh` around lines 328 - 354, Implement
gemm_batched using its x, y, and z mdspan parameters: validate compatible
extents and supported contiguous layouts, derive m, n, k, leading dimensions,
batch count, and per-batch strides from the mdspan shapes/strides, and pass the
correct underlying matrix data pointers. Convert optional alpha and beta values
to nullable scalar pointers expected by detail::matmul_strided_batched, and
forward compute_type_override instead of an undeclared compute_type; remove all
undeclared identifiers from the dispatch.

Sources: Coding guidelines, Path instructions

🤖 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 `@cpp/include/raft/linalg/gemm.cuh`:
- Around line 286-317: Update the Doxygen block for gemm_batched to match its
declared API: document the 3D mdspan A, B, and C arguments, explain the
batch-axis convention, list supported layouts, describe scalar-view behavior for
alpha and beta, and document compute_type_override. Remove references to
undeclared raw-pointer parameters and template types while preserving the public
API’s actual semantics.
- Around line 328-354: Implement gemm_batched using its x, y, and z mdspan
parameters: validate compatible extents and supported contiguous layouts, derive
m, n, k, leading dimensions, batch count, and per-batch strides from the mdspan
shapes/strides, and pass the correct underlying matrix data pointers. Convert
optional alpha and beta values to nullable scalar pointers expected by
detail::matmul_strided_batched, and forward compute_type_override instead of an
undeclared compute_type; remove all undeclared identifiers from the dispatch.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d25f523a-0974-4c73-a9a1-527f500b558e

📥 Commits

Reviewing files that changed from the base of the PR and between a8d89a2 and 9ee66b1.

📒 Files selected for processing (1)
  • cpp/include/raft/linalg/gemm.cuh

@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: 1

🧹 Nitpick comments (1)
cpp/tests/linalg/gemm_basic.cpp (1)

206-219: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for non-default alpha and beta in the batched tests.

Both batched tests leave alpha and beta empty. The alpha_val = 2.0f and beta_val = 3.0f path through gemm_batched therefore stays untested, and the beta != 0 path never verifies that the existing Z contents are accumulated. The device-scalar pointer mode is also untested for the batched overload.

Add at least one batched case with raft::make_host_scalar alpha and beta, and one with raft::make_device_scalar, following the pattern of test_gemm_pointer_mode_host and test_gemm_pointer_mode_device.

As per path instructions, cpp/REVIEW_GUIDELINES.md requires that "tests should exercise numerical correctness, layouts, padding/strides, scalar modes, and relevant edge cases using synthetic data".

🤖 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 `@cpp/tests/linalg/gemm_basic.cpp` around lines 206 - 219, Extend the batched
GEMM coverage in the tests containing gemm_batched to exercise non-default
alpha=2.0f and beta=3.0f, verifying accumulation with existing C contents and
numerical results. Add cases using raft::make_host_scalar and
raft::make_device_scalar, following test_gemm_pointer_mode_host and
test_gemm_pointer_mode_device while preserving the existing layout, stride, and
padding coverage.

Source: Path instructions

🤖 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 `@cpp/include/raft/linalg/gemm.cuh`:
- Around line 377-417: Update both `detail::matmul_strided_batched<kDeviceMode>`
calls in the `z_col_major` and row-major branches to explicitly cast extents and
leading dimensions to `uint64_t`, strides to `int64_t`, and the batch count to
`int32_t`. Before casting `z.extent(0)`, validate it is no greater than
`INT32_MAX` and reject or report out-of-range values using the surrounding API’s
established validation behavior.

---

Nitpick comments:
In `@cpp/tests/linalg/gemm_basic.cpp`:
- Around line 206-219: Extend the batched GEMM coverage in the tests containing
gemm_batched to exercise non-default alpha=2.0f and beta=3.0f, verifying
accumulation with existing C contents and numerical results. Add cases using
raft::make_host_scalar and raft::make_device_scalar, following
test_gemm_pointer_mode_host and test_gemm_pointer_mode_device while preserving
the existing layout, stride, and padding coverage.
🪄 Autofix

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

Review profile: CHILL

Plan: Enterprise

Run ID: 98e54e7c-b250-4197-853b-f4816a35fa50

📥 Commits

Reviewing files that changed from the base of the PR and between 9ee66b1 and 406a785.

📒 Files selected for processing (2)
  • cpp/include/raft/linalg/gemm.cuh
  • cpp/tests/linalg/gemm_basic.cpp

Comment thread cpp/include/raft/linalg/gemm.cuh

@achirkin achirkin 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.

Looks very nice, thanks!
Seems like there's an invalid cublas config in the test, otherwise I think this is ready to merge.

Comment thread cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp Outdated
@achirkin

Copy link
Copy Markdown
Contributor

/merge

@rapids-bot
rapids-bot Bot merged commit a609a2e into NVIDIA:main Aug 13, 2026
132 of 136 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request New feature or request non-breaking Non-breaking change

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants