Skip to content

[CUDA] Extend the GEMM FMA fallback to SM75 - #2811

Merged
LeiWang1999 merged 1 commit into
tile-ai:mainfrom
Chennesxu:feat/sm75-gemm-fma-fallback
Jul 30, 2026
Merged

[CUDA] Extend the GEMM FMA fallback to SM75#2811
LeiWang1999 merged 1 commit into
tile-ai:mainfrom
Chennesxu:feat/sm75-gemm-fma-fallback

Conversation

@Chennesxu

@Chennesxu Chennesxu commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

On SM75 (Turing), a T.gemm whose dtype combination has no native Turing mma.sync atom crashes instead of computing. FP32 and FP64 compile but trap when the kernel launches, leaving the CUDA context in an error state:

cute/arch/mma_sm80.hpp:315: Assertion `0 && "Attempting to use SM80_16x8x8_F32TF32TF32F32_TN without CUTE_ARCH_MMA_SM80_ENABLED"` failed.

BF16 fails during nvcc compilation:

src/tl_templates/cuda/instruction/mma.h(167): error: static assertion failed with "tl::mma_sync: unsupported configuration"

The FP32, FP64, and BF16 cases in test_tilelang_kernel_gemm.py all hit these failures on an SM75 GPU. The device-side asserts from FP32 and FP64 also cause later tests in the same process to fail.

Root Cause

On Turing, SelectInst routed GEMMs to the plain MMA path even when their dtype combination had no native SM75 atom. FP32, FP64, and BF16 therefore selected SM80-only atoms.

#2339 added the cuda.fma correctness fallback for GEMMs without a usable tensor-core MMA path, but only connected it to Volta.

Fix

Add AllowTuringMma alongside the Volta check and select the existing cuda.fma implementation when SM75 has no native atom for the requested dtype combination.

Unlike the Volta check, the Turing check is intentionally dtype-only. The SM75 emitter supports the same operand scopes and transpose combinations as the generic MMA path, so scope-based routing would incorrectly demote valid FP16 sr/rs cases to the fallback. Besides being slower, the fallback accumulates serially, and FP16 accumulation loses accuracy over long K.

Tested

  • Added test_tilelang_kernel_sm75_gemm_fma.py following the SM70 pattern from [TileOP] Add SM70 GEMM FMA fallback #2339. Compile-only checks pinned to an explicit sm_75 target, so they run on any CUDA runner, assert that FP32, FP64, and BF16 lower through the fallback while FP16 stays on MMA. Execution checks gated on compute capability 7.5 compare the results against PyTorch.
  • Reverting the SelectInst change makes the fallback tests fail with the errors above, while the FP16 test still passes.
  • Verified on a TITAN RTX (sm_75, Turing) with CUDA 12.4: test_tilelang_kernel_gemm.py and test_tilelang_kernel_gemm_sm75.py pass, with FP16, INT8, and INT4, including the sr/rs fragment cases, keeping their native MMA lowering.

Summary

  • Extended SM75 GEMM instruction selection to use the existing cuda.fma fallback for unsupported FP32, FP64, and BF16 combinations.
  • Preserved native Turing MMA lowering for supported FP16 and integer cases.
  • Added SM75 dispatch, compile-only lowering, and hardware correctness tests.

C++ style / lint notes

  • This PR does not modify docs/developer_guide/cpp_style.md or public C++ APIs.
  • The repository’s “C++ API Style Audit (warning only)” CI step remains applicable; no correctness or build issues are implied by advisory style findings.

On SM75, SelectInst routed GEMMs to the plain MMA path even when their
dtype combination had no native Turing mma.sync atom. In particular,
fp32, fp64, and bf16 selected SM80-only atoms: bf16 failed an nvcc
static_assert, while fp32 and fp64 compiled into runtime traps that
invalidated the CUDA context.

Add AllowTuringMma alongside the Volta check introduced in tile-ai#2339 and
select the existing cuda.fma implementation when SM75 has no native
atom. Keep the check dtype-only because the SM75 emitter supports the
same operand scopes and transposes as the generic MMA path. Valid f16
combinations remain on native MMA rather than being demoted to the
slower and less accurate serial FMA fallback.

Add compile-only dispatch checks pinned to an explicit sm_75 target,
so they run on any CUDA runner, verifying that fp32, fp64, and bf16
use the fallback while f16 remains on MMA. Add execution checks gated
on compute capability 7.5.
@github-actions

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the TileLang project.

Please remember to run pre-commit run --all-files in the root directory of the project to ensure your changes are properly linted and formatted. This will help ensure your contribution passes the format check.

We appreciate you taking this step! Our team will review your contribution, and we look forward to your awesome work! 🚀

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Turing GEMM instruction selection now validates datatype compatibility before using mma.sync, falling back to CUDA FMA when unsupported. New SM75 tests cover dispatch, generated lowering, and runtime correctness across fp32, fp64, bf16, and fp16.

Changes

Turing GEMM Fallback

Layer / File(s) Summary
Turing MMA eligibility and selection
src/cuda/op/gemm.cc
Adds dtype eligibility checks and selects kCudaFMA for unsupported Turing GEMM configurations.
SM75 dispatch and lowering coverage
testing/python/cuda/test_cuda_mma_sm75_dispatch.py, testing/python/kernel/test_tilelang_kernel_sm75_gemm_fma.py
Verifies cuda.fma dispatch and datatype-specific presence or absence of tl::mma_sync.
SM75 runtime correctness validation
testing/python/kernel/test_tilelang_kernel_sm75_gemm_fma.py
Compares fp32, fp64, and bf16 SM75 GEMM results with PyTorch references.

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

Sequence Diagram(s)

sequenceDiagram
  participant GEMMKernel
  participant GemmSelectInst
  participant TuringEligibility
  participant CUDAImplementation
  GEMMKernel->>GemmSelectInst: select GEMM instruction for sm_75
  GemmSelectInst->>TuringEligibility: check operand and accumulator dtypes
  TuringEligibility-->>GemmSelectInst: eligible or unsupported
  GemmSelectInst->>CUDAImplementation: use mma.sync or cuda.fma
Loading

Possibly related PRs

  • tile-ai/tilelang#2339: Adds related architecture-specific GEMM MMA eligibility and FMA fallback dispatch coverage.
  • tile-ai/tilelang#2392: Adds SM75 MMA dispatcher entries for configurations affected by Turing eligibility checks.

Suggested reviewers: leiwang1999

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: extending GEMM FMA fallback for SM75 CUDA targets.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
src/cuda/op/gemm.cc (1)

132-142: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use a descriptive dtype variable name.

Proposed refactor
-  DataType a = op.a_->dtype;
-  if (a != op.b_->dtype) {
+  DataType a_dtype = op.a_->dtype;
+  if (a_dtype != op.b_->dtype) {
     return false;
   }
-  if (a == DataType::Float(16)) {
+  if (a_dtype == DataType::Float(16)) {
     return op.c_->dtype == DataType::Float(16) ||
            op.c_->dtype == DataType::Float(32);
   }
-  if ((a.is_int() || a.is_uint()) && (a.bits() == 8 || a.bits() == 4)) {
+  if ((a_dtype.is_int() || a_dtype.is_uint()) &&
+      (a_dtype.bits() == 8 || a_dtype.bits() == 4)) {

As per path instructions, “Parameters and local variables should use descriptive lower_snake names; avoid ambiguous T for API parameters.”

🤖 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 `@src/cuda/op/gemm.cc` around lines 132 - 142, Rename the local dtype variable
`a` in the GEMM dtype validation logic to a descriptive lower_snake_case name,
such as one representing the input dtype, and update all comparisons and checks
in that block to use the new name.

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.

Nitpick comments:
In `@src/cuda/op/gemm.cc`:
- Around line 132-142: Rename the local dtype variable `a` in the GEMM dtype
validation logic to a descriptive lower_snake_case name, such as one
representing the input dtype, and update all comparisons and checks in that
block to use the new name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 95b20a2e-8464-466a-9186-45f742bc85f0

📥 Commits

Reviewing files that changed from the base of the PR and between dd92b78 and fc015c5.

📒 Files selected for processing (3)
  • src/cuda/op/gemm.cc
  • testing/python/cuda/test_cuda_mma_sm75_dispatch.py
  • testing/python/kernel/test_tilelang_kernel_sm75_gemm_fma.py

@cklxx

cklxx commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

good job

@Chennesxu

Copy link
Copy Markdown
Contributor Author

good job

thanks!

@LeiWang1999
LeiWang1999 merged commit 7fd9536 into tile-ai:main Jul 30, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants