[kernel] Build + allow attn_qat_infer FP4 attention on sm_121a (DGX Spark) - #1598
[kernel] Build + allow attn_qat_infer FP4 attention on sm_121a (DGX Spark)#1598Mister-Raggs wants to merge 4 commits into
Conversation
Merge Protections🔴 1 of 1 protections blocking · waiting on 👀 reviews and 🤖 CI
🔴 PR merge requirementsWaiting for
This rule is failing.
|
There was a problem hiding this comment.
Code Review
This pull request extends support for Blackwell FP4 attention inference (ATTN_QAT_INFER) to include the sm_121a architecture (DGX Spark GB10) alongside sm_120a. It updates the CMake build configuration to dynamically enable sm_121a compilation when CUDA 12.9+ is available, updates documentation, and registers the backend in the model and pipeline configurations. The review feedback highlights a potential build failure when TORCH_CUDA_ARCH_LIST contains 12.1a but the CUDA Toolkit version is below 12.9, suggesting a fallback mechanism to downgrade 121a to 120a in those environments.
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.
| set(FASTVIDEO_MAIN_CUDA_ARCHS "${TORCH_CUDA_ARCH_LIST}") | ||
| string(REPLACE "sm_" "" FASTVIDEO_MAIN_CUDA_ARCHS "${FASTVIDEO_MAIN_CUDA_ARCHS}") | ||
| string(REPLACE "." "" FASTVIDEO_MAIN_CUDA_ARCHS "${FASTVIDEO_MAIN_CUDA_ARCHS}") | ||
| message(STATUS "[per-arch] main extension archs=${FASTVIDEO_MAIN_CUDA_ARCHS}, fp4* archs=120a") | ||
| message(STATUS "[per-arch] main extension archs=${FASTVIDEO_MAIN_CUDA_ARCHS}, fp4* archs=sm_120a/sm_121a") |
There was a problem hiding this comment.
If TORCH_CUDA_ARCH_LIST contains 12.1a (either via auto-detection on a GB10 GPU or manual configuration) but the CUDA Toolkit version is less than 12.9 (e.g., CUDA 12.8), the build of fastvideo_kernel_ops will fail because CUDA 12.8 does not support the sm_121a architecture. Since sm_120a binaries are compatible with sm_121a GPUs, we should sanitize FASTVIDEO_MAIN_CUDA_ARCHS to downgrade 121a to 120a when compiling with CUDA < 12.9.
set(FASTVIDEO_MAIN_CUDA_ARCHS "${TORCH_CUDA_ARCH_LIST}")
string(REPLACE "sm_" "" FASTVIDEO_MAIN_CUDA_ARCHS "${FASTVIDEO_MAIN_CUDA_ARCHS}")
string(REPLACE "." "" FASTVIDEO_MAIN_CUDA_ARCHS "${FASTVIDEO_MAIN_CUDA_ARCHS}")
if(CUDAToolkit_VERSION VERSION_LESS 12.9)
string(REPLACE "121a" "120a" FASTVIDEO_MAIN_CUDA_ARCHS "${FASTVIDEO_MAIN_CUDA_ARCHS}")
list(REMOVE_DUPLICATES FASTVIDEO_MAIN_CUDA_ARCHS)
endif()
set(FASTVIDEO_FP4_ARCHS_MSG "sm_120a")
if(NOT CUDAToolkit_VERSION VERSION_LESS 12.9)
set(FASTVIDEO_FP4_ARCHS_MSG "sm_120a/sm_121a")
endif()
message(STATUS "[per-arch] main extension archs=${FASTVIDEO_MAIN_CUDA_ARCHS}, fp4* archs=${FASTVIDEO_FP4_ARCHS_MSG}")
There was a problem hiding this comment.
Pull request overview
Enables the ATTN_QAT_INFER (FP4 attention) path to be buildable/opt-in selectable on Blackwell sm_121a (DGX Spark / GB10) in addition to existing sm_120a, while keeping default behavior unchanged unless users explicitly select the backend.
Changes:
- Extend
fastvideo-kernelCMake arch detection/gating to recognize12.1aand build FP4 targets for120aplus121a(when the CUDA toolkit supports it). - Allow
ATTN_QAT_INFERto be selected in Wan attention and the denoising stage allowlist (opt-in viaFASTVIDEO_ATTENTION_BACKEND). - Update inference optimization docs to reflect sm_120a/sm_121a support and add a quality caveat for stock (non-QAT) checkpoints.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| fastvideo-kernel/CMakeLists.txt | Detects/permits Blackwell 12.1a and adjusts FP4 build arch targeting and status messaging. |
| fastvideo/models/dits/wanvideo.py | Adds ATTN_QAT_INFER to Wan attention backend allowlist so it can be selected via env var. |
| fastvideo/pipelines/stages/denoising.py | Adds ATTN_QAT_INFER to the stage allowlist used during attention backend selection. |
| docs/inference/optimizations.md | Updates documentation to state sm_120a/sm_121a support and documents the stock-weights quality caveat. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # FP4 kernels target consumer/workstation Blackwell: sm_120a (RTX 5090 / | ||
| # PRO 6000) and sm_121a (DGX Spark GB10). sm_121a needs CUDA 13's ptxas | ||
| # (12.8 lacks it), so it is added only on CUDA >= 12.9 — pre-13 toolchains | ||
| # keep the original sm_120a-only build unchanged. sm_121a GB10-verified | ||
| # (cos ~0.98 vs bf16). | ||
| set(FASTVIDEO_FP4_CUDA_ARCHS "120a") | ||
| if(NOT CUDAToolkit_VERSION VERSION_LESS 12.9) | ||
| list(APPEND FASTVIDEO_FP4_CUDA_ARCHS "121a") | ||
| endif() |
| string(REPLACE "sm_" "" FASTVIDEO_MAIN_CUDA_ARCHS "${FASTVIDEO_MAIN_CUDA_ARCHS}") | ||
| string(REPLACE "." "" FASTVIDEO_MAIN_CUDA_ARCHS "${FASTVIDEO_MAIN_CUDA_ARCHS}") | ||
| message(STATUS "[per-arch] main extension archs=${FASTVIDEO_MAIN_CUDA_ARCHS}, fp4* archs=120a") | ||
| message(STATUS "[per-arch] main extension archs=${FASTVIDEO_MAIN_CUDA_ARCHS}, fp4* archs=sm_120a/sm_121a") |
| The `attn_qat_infer` kernel targets consumer/workstation Blackwell — **sm_120a | ||
| (RTX 5090 / PRO 6000)** and **sm_121a (DGX Spark GB10)**; the block-scaled FP4 | ||
| MMA is numerically correct on both (GB10-verified: cos ~0.98 vs bf16 SDPA). | ||
| sm_121a support needs a CUDA 13 build (`TORCH_CUDA_ARCH_LIST=12.1a`). On other | ||
| GPUs the backend logs a notice and falls back to Flash Attention. |
|
/merge |
Update — validated on the QAD checkpoint, and full 4-bit runs on sm_121Follow-up on a GB10 (aarch64, CUDA 13, torch 2.11+cu130, flashinfer 0.6.14) using 1. FP4 attention is quality-neutral on the intended checkpointThe description's "stock weights look below bf16" caveat was purely a Why the eye and not SSIM: SSIM-vs-bf16 lands ~0.5 here, but that is 3-step
So any FP4 numerical nudge reshuffles high-frequency texture through the 3-step 2. Full 4-bit (FP4 linear + FP4 attention) runs end-to-end on sm_121The description lists "FP4 linear crashes on Wan/sm_121" as a follow-up. On Timing (QAD-1.3B, 480×832×77, 3-step, eager, denoise mean over 3 runs)
FP4 attention ≈ 6% denoise, consistent across linear precision. FP4 linear is Remaining follow-upAbsolute quality is capped by the 3-step distillation, and there is no public Repro harness (A/B/C/D quality, FP4-linear isolator, SSIM/PSNR compare) on |
The cross-attn (attn2) LocalAttention allowlist had ATTN_QAT_INFER (added in hao-ai-lab#1598) but not ATTN_QAT_TRAIN, so QAT finetune silently ran cross-attn in Flash while self-attn fake-quantized — a train/inference mismatch vs the FP4 inference path (which quantizes both). Add ATTN_QAT_TRAIN so the finetune fake-quantizes cross-attn too. (self-attn already had it via the DiT config list.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
79858cd to
07de6f0
Compare
|
Maintainer repair wave is pushed at exact head Canonical rebase:
The repair makes the standard local build emit Local evidence before push:
Exact-head DGX Spark proof:
The fresh Spark venv initially lacked the repository's declared Fresh CI may evaluate this new head. No approval, retry, label, or merge action was taken. |
|
This PR has merge conflicts with the base branch. Please rebase: git fetch origin main
git rebase origin/main
# Resolve any conflicts, then:
git push --force-with-lease |
a12d6f8 to
1d68229
Compare
|
This PR has merge conflicts with the base branch. Please rebase: git fetch origin main
git rebase origin/main
# Resolve any conflicts, then:
git push --force-with-lease |
1d68229 to
fcb1381
Compare
|
This PR has merge conflicts with the base branch. Please rebase: git fetch origin main
git rebase origin/main
# Resolve any conflicts, then:
git push --force-with-lease |
fcb1381 to
0d03a58
Compare
|
This PR has merge conflicts with the base branch. Please rebase: git fetch origin main
git rebase origin/main
# Resolve any conflicts, then:
git push --force-with-lease |
0d03a58 to
2306230
Compare
5b51de5 to
a8f50b1
Compare
|
This PR has merge conflicts with the base branch. Please rebase: git fetch origin main
git rebase origin/main
# Resolve any conflicts, then:
git push --force-with-lease |
a8f50b1 to
597fa37
Compare
Pre-commit checks failedHi @Mister-Raggs, the pre-commit checks have failed. To fix them locally: # Install pre-commit if you haven't already
uv pip install pre-commit
pre-commit install
# Run all checks and auto-fix what's possible
pre-commit run --all-filesCommon fixes:
After fixing, commit and push the changes. The checks will re-run automatically. For future commits, |
597fa37 to
8ce3b80
Compare
generate_video returns a plain dict, so getattr(result, ...) always hit the fallback: generation_time silently became wall time and peak_memory_mb was always None. Use dict access. Label the measured metric honestly: generation_time is the full pipeline (text-encode + denoise + decode), not denoise. Also: the sm_121 runtime allowlist landed via hao-ai-lab#1647; hao-ai-lab#1598 is the remaining kernel build.
|
This PR has merge conflicts with the base branch. Please rebase: git fetch origin main
git rebase origin/main
# Resolve any conflicts, then:
git push --force-with-lease |
8ce3b80 to
cc31f34
Compare
|
This PR has merge conflicts with the base branch. Please rebase: git fetch origin main
git rebase origin/main
# Resolve any conflicts, then:
git push --force-with-lease |
…park) The modified-SageAttention3 FP4 attention kernels (fp4attn_cuda/fp4quant_cuda) were pinned to sm_120a, and the docs/comments called them "sm_120a-only". They are in fact numerically correct on sm_121a (DGX Spark / GB10) too — verified on a GB10: cos ~0.98 vs bf16 SDPA across shapes/causal, output bit-identical in structure. - CMakeLists: build the FP4 targets for sm_120a AND sm_121a (added only on CUDA >= 12.9, since sm_121a needs CUDA 13's ptxas; pre-13 toolchains keep the sm_120a-only build unchanged). AUTO-gate and local-GPU detect now recognize sm_121a. - Allow ATTN_QAT_INFER in the Wan attention + denoising-stage backend allowlists so it is opt-in-selectable on sm_121 (default stays FA/SDPA). - Docs: correct "sm_120a-only" -> sm_120a/sm_121a, with the quality caveat. Opt-in only (FASTVIDEO_ATTENTION_BACKEND=ATTN_QAT_INFER); default behavior is unchanged on every existing GPU.
…ch, wheel+README - Gemini(high): the main extension (fastvideo_kernel_ops) used the raw TORCH_CUDA_ARCH_LIST, so a CUDA<13 build with 12.1a in the list would fail to compile. Downgrade 121a->120a for the main archs too on CUDA<13 (sm_120a PTX forward-JITs to sm_121); mirrors the fp4* guard. - Copilot: gate sm_121a on CUDA>=13.0 (not 12.9) to match the doc/comment text; fix the "[per-arch]" status message to not always claim sm_121a. - Copilot: make the "sm_120a-only" claim true, not just reworded — update fastvideo-kernel/README.md support matrix, and add 12.1a to the aarch64 cu130 wheel arch list so the published Spark wheel actually includes sm_121a FP4.
…ao-ai-lab#1647) The hardening commit added fastvideo/tests/attention/test_attn_qat_infer_ capability.py to assert is_attn_qat_infer_available() gates on device capability. hao-ai-lab#1647 (same author) since landed test_attn_qat_infer_arch_gate.py on main — a strict superset that parametrizes the full sm_12x-CUTLASS / sm_100-103-FA4 resolution (incl. the same is_attn_qat_infer_available assertion) plus receipts, forward-dispatch safety, memoization and opcheck. The older test also asserted the now-stale (10,0)->False (pre-hao-ai-lab#1647 FA4 support), reddening CI. Remove it and its pr_test lane entry; arch_gate.py is the single source of truth.
cc31f34 to
aea590c
Compare
|
This PR has merge conflicts with the base branch. Please rebase: git fetch origin main
git rebase origin/main
# Resolve any conflicts, then:
git push --force-with-lease |
Summary
The
attn_qat_inferFP4 attention kernels (modified SageAttention3) were pinnedto sm_120a, with the build/docs treating them as "sm_120a-only." On real
hardware they're also numerically correct on sm_121a (DGX Spark / GB10) — the
"sm_120a-only" was an untested release-scope assumption (the kernels shipped on
RTX 5090), not an intrinsic limit. This makes them buildable + opt-in-selectable
on sm_121, with the correctness evidence below. Default behavior is unchanged
on every existing GPU — this is opt-in (
FASTVIDEO_ATTENTION_BACKEND=ATTN_QAT_INFER).Evidence — numerical correctness on sm_121 (GB10)
Built for
sm_121a(TORCH_CUDA_ARCH_LIST=12.1a, CUDA 13;cuobjdumpconfirmssm_121SASS), thensageattn_blackwellvs bf16 SDPA on a GB10:All ≥ 0.981 (min over 3 seeds each), no NaNs. For reference, an idealized
correct-math NVFP4 attention on the same random input caps ~0.975 — so this is at
the FP4 correctness ceiling. Robust across cross-attention (unequal q/kv), the
full Wan seqlen (32760), and
sm_scale=None.End-to-end on Wan-2.1-T2V-1.3B (sm_121)
FASTVIDEO_ATTENTION_BACKEND=ATTN_QAT_INFERruns end-to-end through a real Wanforward (self + cross attention via the kernel) with no crash. The full 4-bit
path (FP4 linear + FP4 attention) also runs end-to-end on sm_121 — all four
attention×linear precision combinations generate cleanly (see the validation
comment; QAD-checkpoint 3-step timing there too). Timing at 50 steps on stock
weights was ~10 min vs ~11 min bf16 (single run, ~9%) — modest as expected:
attention is a minority of Wan's denoise (linears dominate), and the win grows
with sequence length (attention is O(L²)) and on sm_120-tuned paths.
Quality
On the intended (QAD) checkpoint, FP4 attention is quality-neutral vs bf16.
Validated on
FastVideo/FastWan-QAD-1.3B(Wan2.1-1.3B, 3-step, fixed seed) acrossthree prompts — visually indistinguishable from bf16; both share the 3-step
distillation's quality ceiling. (SSIM-vs-bf16 ~0.5 is 3-step trajectory
divergence, not loss — determinism-controlled; full proof + full-4-bit results +
timing in the validation comment.)
On stock (non-QAT) Wan-2.1, by contrast, FP4 attention is visibly below bf16
(frames below). That's expected and is not a kernel defect: QAD is
Quantization-Aware Distillation, so the model must be trained to tolerate
FP4 attention — which is exactly why the neutral result needs the QAT checkpoint,
and why release-grade absolute quality on a full-step path is a training
follow-up (below).
BF16 (stock, 50-step):

FP4 (stock, 50-step):

Changes
fastvideo-kernel/CMakeLists.txt— build the FP4 targets forsm_120aandsm_121a(added only on CUDA ≥ 13.0, sincesm_121aneeds CUDA 13 ptxas;pre-13 toolchains keep the exact sm_120a-only build). AUTO-gate + local-GPU
detect recognize
sm_121a.wanvideo.py/denoising.py— addATTN_QAT_INFERto the attention +denoising-stage allowlists so it's opt-in-selectable on Wan (default unchanged).
docs/inference/optimizations.md— correct "sm_120a-only" → sm_120a/sm_121a,with the quality caveat.
Not in this PR (follow-ups)
weights are the 3-step distill, so today's demo is capped by 3-step. A full-step
QAT-finetune (stage 1 of the QAD recipe, before the DMD step-distillation) would
give full-sharpness FP4-attention output — a training-side follow-up.
FP4 linear crashes on Wan/sm_121— resolved / was stale: FP4 linearruns correctly on sm_121 on current
main(isolated + end-to-end; see thevalidation comment). Full 4-bit works.
Validation
cuobjdump sm_121+ cos sweep: on a GB10 (aarch64, CUDA 13,torch 2.11+cu130). The
sm_121abuild path is validated on-silicon; maintainersshould confirm it on the CI toolchain/arch matrix (it's CUDA-version-guarded so
it can't change the existing sm_120 build).
🤖 Generated with Claude Code