Skip to content

fix(quantization): prefer arch-specific fp4_quantization module on SM12x - #3906

Open
yichengj0 wants to merge 3 commits into
flashinfer-ai:mainfrom
yichengj0:fp4-quant-arch-dispatch
Open

yichengj0 wants to merge 3 commits into
flashinfer-ai:mainfrom
yichengj0:fp4-quant-arch-dispatch

Conversation

@yichengj0

@yichengj0 yichengj0 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

📌 Description

Resolves item 15 of the SM121 support audit (#3170): the FP4 quantization runtime and AOT disagree about which module to use on SM12x.

get_fp4_quantization_module() unconditionally redirected backends "120"/"121" to "120f" on CUDA >= 12.9 (introduced in #2650), while aot.py builds the arch-specific fp4_quantization_120/_121 modules. The AOT artifacts for 12.0a/12.1a were dead weight, and a JIT-cache build without 12.0f in the arch list broke FLASHINFER_DISABLE_JIT.

Fixes:

  • Use the arch-specific module (sm_120a/sm_121a) directly.
  • Redirect to 120f only when it is the module available ahead-of-time, so release wheels keep loading their prebuilt module with no new JIT compile.

🔍 Related Issues

#3170 (item 15), #2650 (introduced the redirect).

🧪 Tests

On DGX Spark (GB10, SM121, CUDA 13, source install):

  • New CPU-only test_fp4_quantization_module_selection covering the arch-vs-family selection.
  • tests/utils/test_fp4_quantize.py (10300 passed) and test_fp4_quantize_padding.py (16 passed); the JIT cache now builds fp4_quantization_121 with compute_121a.
  • Wheel-fallback simulation: with a real sm_120f module staged in FLASHINFER_AOT_DIR, a fresh process loads it and round-trips correctly.

Reviewer Notes

  • Source installs on SM12x recompile once (the warm 120f JIT cache no longer matches).
  • Wheel installs on SM121 load sm_120f while source installs compile sm_121a, matching the existing SM12x GEMM/MoE behavior.
  • The CUDA >= 12.9 gate is dropped: the redirect only loads a prebuilt .so, so the toolkit version is irrelevant.
  • Verified on SM121 only; SM120 takes the identical path.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved FP4 quantization backend selection for greater compatibility across supported architectures.
    • Preserved requested backend selection while applying the appropriate available AOT module when needed.
    • Removed outdated CUDA-version-based backend remapping.
  • Tests

    • Added coverage for backend and AOT module selection scenarios, including architecture-specific and family-level modules.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ee438b41-bbcf-47c8-8c3e-24b86aeb9fcd

📥 Commits

Reviewing files that changed from the base of the PR and between f092274 and abd7b0c.

📒 Files selected for processing (2)
  • flashinfer/quantization/fp4_quantization.py
  • tests/utils/test_fp4_quantize.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • flashinfer/quantization/fp4_quantization.py
  • tests/utils/test_fp4_quantize.py

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

FP4 quantization module dispatch now validates the backend and conditionally selects the AOT 120f module for backends 120 and 121. A parametrized CPU-only test covers AOT availability and backend selection.

Changes

FP4 backend dispatch

Layer / File(s) Summary
AOT-aware backend selection
flashinfer/quantization/fp4_quantization.py
The selector validates the backend and uses the requested backend unless an AOT 120f family module is required for backend 120 or 121.
Backend selection coverage
tests/utils/test_fp4_quantize.py
Parametrized tests simulate AOT artifacts and verify module selection across backend combinations.

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

Merge Risk: ⚪ Minimal · up to abd7b

The change selects architecture-specific FP4 modules for SM12x while preserving prebuilt wheel fallback behavior; no actionable merge-blocking risk remains after normal checks and review.

Suggested labels: op: misc

Suggested reviewers: yzh119, aleozlx, dhiraj113

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.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
Title check ✅ Passed The title clearly identifies the FP4 quantization module-selection fix for SM12x architectures.
Description check ✅ Passed The description explains the problem, solution, related issues, tests, and reviewer considerations; the pre-commit checklist is not explicitly included.
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 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 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 updates the backend selection logic for SM12x architectures in fp4_quantization.py to prefer arch-specific modules over the family variant, falling back to the family variant only when it is prebuilt (AOT) and the arch-specific one is not. The reviewer suggested optimizing this logic by instantiating the module generators once to avoid redundant calls and return early.

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 thread flashinfer/quantization/fp4_quantization.py Outdated

@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)
flashinfer/quantization/fp4_quantization.py (1)

237-248: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider using backend_modules["120f"]() instead of gen_fp4_quantization_sm120f_module() for consistency.

Line 247 uses the direct function reference gen_fp4_quantization_sm120f_module() while line 246 uses the dictionary lookup backend_modules[backend](). Since "120f" is already a key in backend_modules, using backend_modules["120f"]() would be more consistent and make the relationship between the two checks clearer.

♻️ Consistency tweak
         if (
             version_at_least(torch.version.cuda, "12.9")
             and not backend_modules[backend]().is_aot
-            and gen_fp4_quantization_sm120f_module().is_aot
+            and backend_modules["120f"]().is_aot
         ):
🤖 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 `@flashinfer/quantization/fp4_quantization.py` around lines 237 - 248, Replace
the direct gen_fp4_quantization_sm120f_module() call in the SM12x dispatch
condition with backend_modules["120f"](), keeping the existing AOT check and
aligning it with the backend_modules[backend]() lookup.
🤖 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 `@flashinfer/quantization/fp4_quantization.py`:
- Around line 237-248: Replace the direct gen_fp4_quantization_sm120f_module()
call in the SM12x dispatch condition with backend_modules["120f"](), keeping the
existing AOT check and aligning it with the backend_modules[backend]() lookup.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5945f2e3-434f-455f-8dba-595100daa324

📥 Commits

Reviewing files that changed from the base of the PR and between f2f9646 and cda1eb0.

📒 Files selected for processing (1)
  • flashinfer/quantization/fp4_quantization.py

@yichengj0

Copy link
Copy Markdown
Contributor Author

@coderabbitai The backend_modules["120f"]() consistency nitpick is adopted in 3574fd1, which also restructures the dispatch to bind the spec once.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@yichengj0 Thanks for confirming — glad the consistency nitpick and the broader dispatch restructuring (binding the spec once) landed in 3574fd1. That resolves the concern.

ᕦ(ò_óˇ)ᕤ

@waynehacking8

Copy link
Copy Markdown
Contributor

Verified on an RTX PRO 6000 (SM120, CUDA 13.0, JIT path, no AOT dir) at 3574fd1: the runtime now builds and loads fp4_quantization_120 with -gencode=arch=compute_120a,code=sm_120a where main picks the 120f module on the same box, and the full tests/utils/test_fp4_quantize.py passes 10306/10306 vs main's 10300/10300 baseline (the +6 are this PR's selection tests). The AOT-redirect leg (release wheel shipping only 120f) is the one path I couldn't exercise here -- no AOT directory on this box.

yichengj0 and others added 3 commits August 20, 2026 00:29
get_fp4_quantization_module() unconditionally redirected backends "120"
and "121" to "120f" on CUDA >= 12.9, while aot.py builds the
arch-specific fp4_quantization_120/_121 modules for 12.0a/12.1a arch
lists. The AOT artifacts were dead weight, and JIT-cache builds without
12.0f in the arch list broke FLASHINFER_DISABLE_JIT (or silently
recompiled) because the runtime asked for a module nobody built.

Use the arch-specific module (sm_120a / sm_121a, strict supersets of
sm_120f) directly, matching GEMM/MoE dispatch. Redirect to 120f only
when it is the module available ahead-of-time, so release wheels
(built with 12.0f only) keep loading their prebuilt module.

AI-assisted (Claude Code).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… test

Address review feedback on the arch-specific dispatch:

- Bind the JitSpec once instead of constructing it for the AOT probe and
  again for build_and_load.
- Drop the CUDA >= 12.9 gate: the redirect loads a prebuilt .so, so the
  toolkit version is irrelevant, and the non-AOT path keeps the same
  arch flags either way.
- Reword the comment; the old text wrongly claimed release wheels
  prebuild only sm_120f (a 12.0f wheel also prebuilds sm_120a via
  aot.py's substring match, so only backend "121" ever redirects) and
  overstated the parallel with GEMM/MoE dispatch.
- Add a CPU-only unit test for the selection logic, which CI never
  exercises through a real AOT directory.

AI-assisted (Claude Code).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The class-level is_aot monkeypatch broke when JitSpec grew subclasses
(the subclass property shadows the base-class patch). Point
FLASHINFER_AOT_DIR at a tmp dir with placeholder .so files so the
production is_aot check runs unmodified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@yichengj0
yichengj0 force-pushed the fp4-quant-arch-dispatch branch from 3574fd1 to abd7b0c Compare August 20, 2026 00:36
@yichengj0
yichengj0 requested a review from feih-nv as a code owner August 20, 2026 00:36
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@kahyunnam kahyunnam added the op: misc norm, activation, sampling, RoPE, quantization, etc. label Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

op: misc norm, activation, sampling, RoPE, quantization, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants