Skip to content

feat(attention): enable SM121 (GB10/DGX Spark) for NVFP4 attention - #3897

Merged
saltyminty merged 4 commits into
flashinfer-ai:mainfrom
bkryu:sm120_nvfp4_prefill_on_sm121
Jul 13, 2026
Merged

saltyminty merged 4 commits into
flashinfer-ai:mainfrom
bkryu:sm120_nvfp4_prefill_on_sm121

Conversation

@bkryu

@bkryu bkryu commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

📌 Description

Enables the SM120 NVFP4 attention kernel (#3640) on SM121 (GB10 / DGX Spark). The kernel code needs no changes — it compiles and runs correctly for sm_121a; this PR only widens the SM120-only gates

Config (H8) FA2 BF16 NVFP4 Speedup
B4 S4096 D128 2.97 ms (93 TF/s) 1.28 ms (215 TF/s) 2.32×
B2 S8192 D128 5.81 ms (95 TF/s) 2.48 ms (221 TF/s) 2.34×
B1 S32768 D128 46.09 ms (95 TF/s) 19.51 ms (225 TF/s) 2.36×
B1 S16384 D64 5.89 ms (93 TF/s) 3.81 ms (144 TF/s) 1.55×

Speedup is stable across head counts (2.2–2.6× for H=1…32 at D128); throughput saturates from B·H ≥ 16 at S4096. Speedup is around 1.5-1.6x for head dim 64.

Commands to reproduce the perf numbers

NVFP4 (shape lists zip together; one row printed per config):

# D=128 rows + head-dim sweep                                                                                                                                                              
python benchmarks/bench_nvfp4_attention_sm120.py \                                                                                                                                         
    --batch-size 4 2 2 1 1 --num-heads 8 --head-dim 128 \                                                                                                                                  
    --seq-len 4096 4096 8192 16384 32768 \                                                                                                                                                 
    --no-causal --warmup 3 --repeat 10                                                                                                                                                     
                                                                                                                                                                                           
# D=64 rows                                                                                                                                                                                
python benchmarks/bench_nvfp4_attention_sm120.py \                                                                                                                                         
    --batch-size 4 2 2 1 1 --num-heads 8 --head-dim 64 \                                                                                                                                   
    --seq-len 4096 4096 8192 16384 32768 \                                                                                                                                                 
    --no-causal --warmup 3 --repeat 10                                                                                                                                                     
                                                                                                                                                                                           
# head-count sweep (B*H occupancy)                                                                                                                                                         
python benchmarks/bench_nvfp4_attention_sm120.py \                                                                                                                                         
    --batch-size 1 --num-heads 1 2 4 8 16 32 --head-dim 128 \                                                                                                                              
    --seq-len 4096 --no-causal --warmup 3 --repeat 10                                                                                                                                      

The "NVFP4" column is the attention_only number (CUDA-graph replay, pure kernel time,
quantization excluded); end_to_end additionally includes quantize_qkv each iteration.

FA2 BF16 baseline (identical shapes; CUPTI kernel timing is on by default; uniform
full-length sequences — do not pass --random_actual_seq_len):

for cfg in "4 4096" "2 4096" "2 8192" "1 16384" "1 32768"; do                                                                                                                              
  set -- $cfg                                                                                                                                                                              
  python benchmarks/flashinfer_benchmark.py \                                                                                                                                              
      --routine BatchPrefillWithRaggedKVCacheWrapper --backends fa2 \                                                                                                                      
      --batch_size $1 --s_qo $2 --s_kv $2 \                                                                                                                                                
      --num_qo_heads 8 --num_kv_heads 8 \                                                                                                                                                  
      --head_dim_qk 128 --head_dim_vo 128 \                                                                                                                                                
      --q_dtype bfloat16 --kv_dtype bfloat16 --refcheck                                                                                                                                    
done                                                                                                                                                                                       
# D=64 baseline: same loop with --head_dim_qk 64 --head_dim_vo 64                                                                                                                          
# head sweep baseline: --batch_size 1 --s_qo 4096 --s_kv 4096, loop --num_qo_heads/--num_kv_heads over 1 2 4 8 16 32                                                                       

Environment: NVIDIA GB10 (SM121), CUDA 13.0, torch 2.11. FA2 median of 30 iters
(CUPTI); NVFP4 median of 10 iters (CUDA-graph). Comparing FA2 kernel time against
NVFP4 attention_only is apples-to-apples — both exclude host launch overhead.

🔍 Related Issues

🚀 Pull Request Checklist

Thank you for contributing to FlashInfer! Before we review your pull request, please make sure the following items are complete.

✅ Pre-commit Checks

  • I have installed pre-commit by running pip install pre-commit (or used your preferred method).
  • I have installed the hooks with pre-commit install.
  • I have run the hooks manually with pre-commit run --all-files and fixed any reported issues.

If you are unsure about how to set up pre-commit, see the pre-commit documentation.

🧪 Tests

  • Tests have been added or updated as needed.
  • All tests are passing (unittest, etc.).

Reviewer Notes

Summary by CodeRabbit

  • New Features

    • Expanded NVFP4 attention support to include GPU compute capability 12.1 in addition to 12.0.
    • Broadened which NVFP4 SM120 modules are generated and enabled, and improved JIT build flag selection across compatible CUDA environments.
  • Bug Fixes

    • Updated compute-capability validation and the related error/skip messaging to reflect 12.0 and 12.1 support.
    • Adjusted test gating to run when either supported compute capability is available, reducing unnecessary skips.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

NVFP4 attention now accepts SM121 alongside SM120 across CUDA validation, AOT generation, JIT compilation flags, Python entry points, benchmark gating, and test gating.

Changes

SM120/SM121 support expansion

Layer / File(s) Summary
Core capability and build gating
csrc/nvfp4_attention_sm120/..., flashinfer/aot.py
The CUDA binding accepts compute capability 12.0 or 12.1, and AOT generation includes the module when either SM120 or SM121 is available.
JIT compilation flag selection
flashinfer/jit/nvfp4_attention_sm120.py
JIT generation uses NVCC flags from the current compilation context and falls back to SM120 flags on RuntimeError.
Public API capability declarations
flashinfer/nvfp4_attention_sm120.py
Quantization and forward entry points declare support for compute capabilities 120 and 121.
Benchmark and test capability gating
benchmarks/bench_nvfp4_attention_sm120.py, tests/attention/test_nvfp4_attention_sm120.py
Benchmark and test checks accept either SM120 or SM121 support and update related skip messaging and imports.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: sricketts, dhiraj113, aleozlx, yongwww, yzh119

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% 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
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.
Title check ✅ Passed The title is concise and accurately states the main change: enabling SM121 for NVFP4 attention.
Description check ✅ Passed The description follows the template and includes a clear summary, related issues, checklist items, tests, and reviewer notes.
✨ 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.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request extends support for the NVFP4 attention SM120 kernel to SM121 (compute capability 12.1) devices. This involves updating capability checks across benchmarks, CUDA bindings, JIT compilation, API decorators, and tests. The reviewer suggested using the existing is_sm12x_supported utility function in the test suite to simplify the check and make it more future-proof.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +35 to +43
from flashinfer.utils import is_sm120a_supported, is_sm121a_supported


def _require_sm120():
if not torch.cuda.is_available():
pytest.skip("CUDA is required")
if not is_sm120a_supported(torch.device("cuda")):
pytest.skip("SM120 GPU is required")
device = torch.device("cuda")
if not (is_sm120a_supported(device) or is_sm121a_supported(device)):
pytest.skip("SM120 or SM121 GPU is required")

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.

medium

Instead of importing and checking individual SM120 and SM121 support functions, we can use the existing is_sm12x_supported utility function. This simplifies the check and automatically supports any future SM12x variants without requiring code changes.

Suggested change
from flashinfer.utils import is_sm120a_supported, is_sm121a_supported
def _require_sm120():
if not torch.cuda.is_available():
pytest.skip("CUDA is required")
if not is_sm120a_supported(torch.device("cuda")):
pytest.skip("SM120 GPU is required")
device = torch.device("cuda")
if not (is_sm120a_supported(device) or is_sm121a_supported(device)):
pytest.skip("SM120 or SM121 GPU is required")
from flashinfer.utils import is_sm12x_supported
def _require_sm120():
if not torch.cuda.is_available():
pytest.skip("CUDA is required")
device = torch.device("cuda")
if not is_sm12x_supported(device):
pytest.skip("SM120 or SM121 GPU is required")

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Current change is not too messy so this should be fine.

@bkryu bkryu added the run-ci label Jul 9, 2026
@bkryu

bkryu commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator Author

/bot run

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

GitLab MR !926 has been created, and the CI pipeline #57441966 is currently running. I'll report back once the pipeline job completes.

@bkryu

bkryu commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator Author

/bot run tests/attention

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

GitLab MR !926 has been created, and the CI pipeline #57442248 is currently running. I'll report back once the pipeline job completes.

@saltyminty saltyminty left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Non-blocking, but do we need to add sm121 to the JIT-cache wheels in .github/workflows/release.yml?

Comment thread flashinfer/jit/nvfp4_attention_sm120.py Outdated
]
include_paths: list[str | Path] = []
include_paths.extend(_nvfp4_attention_sm120_include_paths())
nvcc_flags = current_compilation_context.get_nvcc_flags_list(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This change causes sm120 to no longer be supported on CUDA 12.8, as _normalize_cuda_arch enforces >= 12.9. Is this intended?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Right thanks @saltyminty, this was unintended. Fixed in the latest commit with a gated compilation-context path

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

[FAILED] Pipeline #57442248: 7/20 passed

@waynehacking8

Copy link
Copy Markdown
Contributor

Verified this head (a5922cd) on an RTX PRO 6000 (SM120, CUDA 13.0): all 7 tests pass and the JIT build.ninja now emits -gencode=arch=compute_120f,code=sm_120f, so SM120 is functionally unchanged on CUDA >= 12.9. On the 12.8 question: the gate is compilation_context._normalize_cuda_arch (raises for any SM12x below 12.9, compilation_context.py:56), and the same get_nvcc_flags_list(supported_major_versions=[12]) path already governs xqa, mla, gemm and fused_moe on main -- a CUDA 12.8 + SM120 install has already lost those modules, so this just aligns nvfp4_attention with the existing convention (the old sm120a flags were the last 12.8-compatible holdout besides fp4_quantization, which #3906 migrates). Since #3838 landed yesterday, a rebase would pick up its 5 extra tests for the SM121 leg too.

@bkryu

bkryu commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Non-blocking, but do we need to add sm121 to the JIT-cache wheels in .github/workflows/release.yml?

It's a good point, and in fact there is #3907 that is WIP adding the wheel

@bkryu

bkryu commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

/bot run tests/attention

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

GitLab MR !926 has been updated with latest changes, and the CI pipeline #57826220 is currently running. I'll report back once the pipeline job completes.

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

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 `@flashinfer/jit/nvfp4_attention_sm120.py`:
- Around line 93-99: Update the SM12 architecture handling in
_normalize_cuda_arch and the current_compilation_context flow so CUDA 12.8 with
SM120 can reach the sm120a_nvcc_flags fallback without raising. Preserve raw
SM12 capability for this path, while retaining normalization for CUDA 12.9+ and
existing behavior for other architectures.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8b8e367b-ac71-40e6-ba67-3bb172ddb339

📥 Commits

Reviewing files that changed from the base of the PR and between a5922cd and c3baa30.

📒 Files selected for processing (4)
  • csrc/nvfp4_attention_sm120/nvfp4_attention_sm120_binding.cu
  • flashinfer/jit/nvfp4_attention_sm120.py
  • flashinfer/nvfp4_attention_sm120.py
  • tests/attention/test_nvfp4_attention_sm120.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • csrc/nvfp4_attention_sm120/nvfp4_attention_sm120_binding.cu
  • tests/attention/test_nvfp4_attention_sm120.py
  • flashinfer/nvfp4_attention_sm120.py

Comment thread flashinfer/jit/nvfp4_attention_sm120.py Outdated
@bkryu

bkryu commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

/bot run tests/attention

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

GitLab MR !926 has been updated with latest changes, and the CI pipeline #57828791 is currently running. I'll report back once the pipeline job completes.

@saltyminty
saltyminty merged commit 0f69698 into flashinfer-ai:main Jul 13, 2026
35 checks passed
@bkryu bkryu self-assigned this Jul 23, 2026
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.

4 participants