Skip to content

Mitigate cuBLASLt 13.6 GEMM bug for inputs greater than 2^31 - #3098

Merged
cjnolet merged 7 commits into
NVIDIA:release/26.08from
divyegala:large-gemm-bug
Jul 29, 2026
Merged

Mitigate cuBLASLt 13.6 GEMM bug for inputs greater than 2^31#3098
cjnolet merged 7 commits into
NVIDIA:release/26.08from
divyegala:large-gemm-bug

Conversation

@divyegala

Copy link
Copy Markdown
Contributor

Closes #3097

@divyegala
divyegala requested review from a team as code owners July 29, 2026 17:43
@divyegala
divyegala requested a review from bdice July 29, 2026 17:43
@divyegala divyegala added bug Something isn't working non-breaking Non-breaking change labels Jul 29, 2026
@coderabbitai

coderabbitai Bot commented Jul 29, 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
📝 Walkthrough

Walkthrough

Changes

GEMM workaround and regression coverage

Layer / File(s) Summary
cuBLASLt 13.6 heuristic filtering
cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp
Detects the affected FP32 configuration, requests multiple heuristic candidates, and excludes algorithm 68 when selecting a successful zero-workspace candidate.
GEMM regression tests and test wiring
cpp/tests/linalg/gemm_basic.cpp, cpp/tests/linalg/gemm_large.cpp, cpp/tests/CMakeLists.txt, build.sh
Adds predicate and large-span GEMM tests and registers GEMM_LARGE_TEST for default builds.

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

Suggested reviewers: bdice

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the cuBLASLt 13.6 GEMM workaround for large input spans.
Description check ✅ Passed The description is related to the changeset and links the fix to issue #3097.
Linked Issues check ✅ Passed The code adds the requested cuBLASLt 13.6 workaround, preserves below-boundary behavior, and includes tests for the affected boundary and architectures.
Out of Scope Changes check ✅ Passed The added build and test updates support the GEMM bug fix and do not appear unrelated to the issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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.

🧹 Nitpick comments (2)
cpp/tests/linalg/gemm_large.cpp (2)

74-84: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Validate an interior result too.

Checking only endpoints can miss a partial/corrupt result in the large output. Copy and assert at least one representative interior element, such as samples / 2.

As per path instructions, “Validate numerical correctness in the test beyond just edge elements as needed to avoid false positives.”

🤖 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_large.cpp` around lines 74 - 84, Extend the output
validation in the large GEMM test to copy and assert a representative interior
element, such as index samples / 2, in addition to the existing endpoint checks.
Update the output_edges storage and asynchronous cudaMemcpyAsync calls while
preserving synchronization and the existing zero-value assertions.

Source: Path instructions


46-48: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use RAFT owning mdarrays for the test buffers.

These are straightforward owned device buffers; replace rmm::device_uvector with suitable RAFT device vector/mdarray types and pass their data handles to GEMM.

As per coding guidelines, “Prefer raft mdarray types for owning data over rmm::device_uvector … when an mdarray fits the use case.”

🤖 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_large.cpp` around lines 46 - 48, Replace the three
rmm::device_uvector test buffers in the GEMM setup with suitable owning RAFT
device vector/mdarray types, preserving their element counts and stream
allocation. Update the GEMM calls to pass the RAFT containers’ data handles
instead of relying on rmm::device_uvector interfaces.

Source: Coding guidelines

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

Nitpick comments:
In `@cpp/tests/linalg/gemm_large.cpp`:
- Around line 74-84: Extend the output validation in the large GEMM test to copy
and assert a representative interior element, such as index samples / 2, in
addition to the existing endpoint checks. Update the output_edges storage and
asynchronous cudaMemcpyAsync calls while preserving synchronization and the
existing zero-value assertions.
- Around line 46-48: Replace the three rmm::device_uvector test buffers in the
GEMM setup with suitable owning RAFT device vector/mdarray types, preserving
their element counts and stream allocation. Update the GEMM calls to pass the
RAFT containers’ data handles instead of relying on rmm::device_uvector
interfaces.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 09766a0a-0585-481a-b532-56b3fb3e8258

📥 Commits

Reviewing files that changed from the base of the PR and between b9cf5e0 and 7852ceb.

📒 Files selected for processing (5)
  • build.sh
  • cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp
  • cpp/tests/CMakeLists.txt
  • cpp/tests/linalg/gemm_basic.cpp
  • cpp/tests/linalg/gemm_large.cpp

@divyegala
divyegala changed the base branch from main to release/26.08 July 29, 2026 17:49

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

Have you considered constraining our dependency?

{
constexpr uint64_t max_safe_span = (uint64_t{1} << 31) - 1;
const auto a_columns = args.trans_a ? args.m : args.k;
return version == 130600 && args.lda != 0 && a_columns > max_safe_span / args.lda;

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.

Did you test other versions? Are we confident that only this very specific version is affected? What about future versions?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, but the tests should help with that if it fails in a future version. If you prefer being defensive, then I can add a >= check instead?

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.

I think we might have to be defensive here and actually set 130600 as a lower bound unless we get some kind of assurance that this will be fixed in the next patch release.

Comment thread cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp Outdated
Comment thread cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp Outdated
* cuBLASLt 13.6 may select algorithm 68 once A's physical span reaches 2^31 elements, but that
* algorithm fails during execution for FP32. Prefer the validated alternatives.
*/
inline auto needs_cublaslt_13_6_workaround(const matmul_key_t& args, std::size_t version) noexcept

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.

I'd recommend checking whether the work-around is needed on all archs or only sm_120/sm_121.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This will be a bit tough to verify this close to the release.

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.

Yes, but I think we should at least check sm_90 since restricting the algorithm might lead to a performance regression.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point, let me skip the heuristic for non SM120/121 and CI tests should give us an indication for sm80 and sm90.

@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

🤖 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/tests/linalg/gemm_large.cpp`:
- Around line 30-32: Update the test setup around the device vector allocations
for a, b, and c to query available GPU memory and skip the test when the
required allocation, including a suitable overhead margin, cannot be satisfied.
Ensure the skip occurs before constructing any of these vectors and reports that
insufficient free device memory makes the test unsupported.
🪄 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.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 22149fed-0883-4328-b9d7-95d09c8ab553

📥 Commits

Reviewing files that changed from the base of the PR and between 4b60632 and f083600.

📒 Files selected for processing (2)
  • cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp
  • cpp/tests/linalg/gemm_large.cpp

Comment thread cpp/tests/linalg/gemm_large.cpp

@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

🤖 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/tests/linalg/gemm_basic.cpp`:
- Around line 205-216: Add an EXPECT_FALSE assertion for device architecture
(12, 2) in the GemmCublasLt136WorkaroundArchitectures test, alongside the
existing SM12 cases, using the same at_boundary and affected_version inputs.
🪄 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.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b9fa7dc9-3460-4b7e-bfec-9c7b88be42f6

📥 Commits

Reviewing files that changed from the base of the PR and between f083600 and 32a0db4.

📒 Files selected for processing (2)
  • cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp
  • cpp/tests/linalg/gemm_basic.cpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • cpp/include/raft/linalg/detail/cublaslt_wrappers.hpp

Comment thread cpp/tests/linalg/gemm_basic.cpp

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

One quick question, besides it lgtm


constexpr int workaround_heuristic_results = 2;
std::array<cublasLtMatmulHeuristicResult_t, workaround_heuristic_results> heuristic_results{};
const int requested_results = use_cublaslt_13_6_workaround ? workaround_heuristic_results : 1;

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.

Is it guaranteed or documented that these affected GEMMs always have a usable non-68 algorithm in the top two heuristic results?

@divyegala divyegala Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, but this only skips 68 if it's at the top of the heuristics. If nothing but 68 is returned we will have to fail.

@cjnolet

cjnolet commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

/merge

@cjnolet
cjnolet merged commit fcef0d3 into NVIDIA:release/26.08 Jul 29, 2026
80 checks passed
divyegala added a commit that referenced this pull request Jul 30, 2026
The fix in #3098 was incomplete, as
according to the cublas team there is no guarantee that `algo13` will be
returned along with `algo68` (the failing version for A matrix with >
2^31 elements). Also, the cublas team will patch this bug in version
`13.6.1` so we will automatically receive the fix by guarding only
against `13.6.0`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working non-breaking Non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] RAFT GEMM fails at a 2^31-element input span with cuBLASLt 13.6

6 participants