[feat]: FA4-FP4 ATTN_QAT_INFER on sm_100/sm_103 + NVFP4 weight purge - #1647
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
Merge Protections🔴 1 of 1 protections blocking · waiting on 👀 reviews and 🤖 CI
🔴 PR merge requirementsWaiting for
This rule is failing.
|
da109cc to
b74a185
Compare
|
CI fix pushed in
Fix: kernel resolution moved back to per-forward; the constructor no longer raises. The unavailable-at-forward ImportError now carries the arch receipt. Local evidence: the failing test + full Standing by for the GB200 parity traceback on the FA4 route — if it's a code bug in |
b74a185 to
9ef3328
Compare
|
Second
Fix: |
9ef3328 to
8f371c3
Compare
|
Two GB200-validation follow-ups pushed in 1. Purge breadth fix (real bug caught by the GB200 purge validation). 2. Dependency pins declared (parity-failure attribution: NOT a code bug). The reported FA4-route parity failure on GB200 was a dependency-lattice issue, reproduced and root-caused with a full traceback: the fork's Quality measurement on this branch (GB200, distilled LTX-2 QAD): MS-SSIM 0.846894 vs reference 0.846790 (measured self-noise 0.000000) — the +1.04e-4 delta is formally out-of-band only because the reference band is zero-width; flagged for a verdict rather than self-blessed. |
|
sm_103 upgraded: code-verified → hardware-validated. The FA4-FP4
The capability gate's |
8f371c3 to
ad4d5e2
Compare
|
Dispatch guard repaired in |
Pre-commit checks failedHi @SolitaryThinker, 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, |
0984304 to
cc358f1
Compare
|
Compile-interaction fix pushed in Fix at both call sites ( |
cc358f1 to
afb29e5
Compare
|
Compile fix round 2 in Fix: the FP4 quantize step is now a New regression alongside the resolve-once test: |
afb29e5 to
e05849c
Compare
|
Compile fix round 3 in Fix: the fake now builds the scale-factor output with the impl's own base shape and permutation — Regression upgraded so this class is mechanically caught: |
e05849c to
8e5d609
Compare
…FA4 sm_100/103 hao-ai-lab#1647 extended ATTN_QAT_INFER to datacenter Blackwell (sm_100/sm_103) via the FP4 FA4 path, so is_attn_qat_infer_available() now resolves True on (10,0)/(10,3) too — the pre-hao-ai-lab#1647 assertion (10,0)->False is stale. Parametrize over both kernel paths and force both probes "installed" (_get_attn_qat_infer for sm_12x CUTLASS, _fa4_fp4_available for sm_100/103 FA4) so the test isolates the capability gate deterministically regardless of what's importable on the runner.
…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.
…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.
…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.
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.
…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.
…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.
Problem
Two follow-ups to the LTX-2 NVFP4 QAD deploy path (author task, one PR by request):
(A)
ATTN_QAT_INFERonly resolves on consumer Blackwell (sm_12x, fastvideo-kernel CUTLASS extension). On GB200 (sm_100) / GB300 (sm_103) the selector silently demotes to FlashAttention — measured on the GB200 bench: the NVFP4 arm requestedATTN_QAT_INFER, got flash, so FP4 bought nothing at attention. Meanwhile the FP4 FA4 kernel for exactly these archs is already merged (#1221, credit @Edenzzzz):flash_attn.cuteplumbing with per-16 block-scaled NVFP4 Q/K + BF16 P/V, from hao-ai-lab/flash-attention-fp4 @ fp4 (kernel README).(B)
NVFP4Config's linear method retains the original bf16layer.weightalongside_nvfp4_weight+scales on every quantized layer (+6.8 GiB measured on the GB200 LTX-2 bench) — deliberate for the stage-profile dense fallback, but only 3 of 13 curated suffixes (the cross-modal AV projections) can ever take that dense path.Solution
(A) Arch-aware ATTN_QAT_INFER resolution (
fastvideo/attention/backends/attn_qat_infer.py):_SUPPORTED_DEVICE_CAPABILITIES(CUTLASS ext, value untouched) and_FA4_FP4_CAPABILITIES = {(10,0), (10,3)}.(10,0)/(10,3)routeAttnQatInferImpl.forwardthrough feat: FP4 Flash Attention 4 for Blackwell GPUs #1221's plumbing verbatim (mirrorsFlashAttentionImpl._forward_nvfp4: flashinfernvfp4_quantize→flash_attn_fp4_func). Tuned defaults passed through, not re-tuned: qk_mode=nvfp4 (per-16 E4M3 SFs), pv_mode=bf16 — recorded in the resolution receipt.ATTN_QAT_INFER resolved: arch=... kernel=... qk_mode=... pv_mode=...); the fallback log keeps its stable trailing sentence and now names arch + install pointer.flash_attn.cuteimport (cutlass-dsl skew maps to ImportError with a loud warning) — never a hard crash; install pointer = the fork @ fp4 branch.Train-sim mismatch (stated, measured, not assumed):
ATTN_QAT_TRAINsimulates the sm_12x CUTLASS scheme. The FA4 scheme (block-scaled QK-only) differs, so sm_100/sm_103 deployment carries a train-sim mismatch. Documented in the QAD recipe header and the LTX-2 deploy example; MS-SSIM against the recorded QAT quality reference (0.846) is being measured on GB200 on this branch — in-tolerance ships with the receipt, out-of-tolerance gets surfaced before merge.(B) Fallback-aware weight purge (
fastvideo/layers/quantization/nvfp4_config.py):NVFP4Config(retain_original_weights=None|True|False): auto (default) purges always-FP4 layers' originals and retains the 3 refine-only suffixes;Falsepurges everything (single-stage deploys, e.g. the QAD distilled 8-step bench);True= old behavior.convert_model_to_nvfp4(the single conversion site);apply()takesout_dimfrom the packed FP4 weight when the original is gone, and a purged layer hitting the dense path raises naming the flag. FSDP-sharded (DTensor) originals are skipped (retained) until a sharded deploy needs per-shard purge.NVFP4 weight purge receipt: purged N (... GiB freed); retained M. Target on the GB200 bench config: NVFP4 peak alloc below bf16's 63.9 GiB (re-measured on GB200 for the receipt).torch.compile interaction
The FA4-FP4 forward previously resolved its quantization/kernel entry points on every call (function-level imports + flashinfer's JIT-module lookup, whose first resolution probes the CUDA toolchain via a subprocess). Under
torch.compilethat pattern graph-breaks every step —fullgraph=Truewas impossible for the NVFP4 path, and atfullgraph=Falsethe per-step break kept eager dispatch overhead on the hot path (measurable at short-step resolutions; documented as Finding 1 of the LTX-2.3 bf16-vs-NVFP4 compile benchmark). Two-stage fix. Round 1 memoized the resolution (lazy, module-level) — necessary for eager overhead but insufficient for compile: Dynamo traces function bodies symbolically, so a runtime cache hit is invisible at trace time and tracing still descended into the toolchain probe. Round 2 registers the whole quantize step as atorch.librarycustom op (fastvideo::nvfp4_quantize_fa4, forward + fake — the same boundary pattern as the masked flash-attention entry points), making it one opaque graph node. Regressions: the resolve-once-across-N-forwards test (eager) plus atorch.compile(fullgraph=True)trace-and-run test over the op-backed path with a CPU kernel registered in-test. The construct-anywhere/fail-cleanly-at-forward contract is unchanged. Round 3 (this head): the previous note called the fake's contiguous-vs-permuted-view stride mismatch "known minor — at worst an inductor copy". That was wrong: torch.compile bakes the fake's output strides into the compiled artifact and asserts at runtime (expected size 32==32, stride 16==8192 at dim=0) — tracing was fixed but all compiled NVFP4 executions crashed. The fake now constructs its scale-factor output with the impl's own base shape and permutation (new_empty((batch, nheads, rest_m, rest_k, 32, 4, 4)).permute(4, 5, 2, 6, 3, 1, 0)), matching the real strided view for general batch. Regression upgraded accordingly:torch.library.opchecknow cross-checks the registered fake against a real kernel run — shapes, dtypes, AND strides — with a batch>1, non-multiple-of-128 seqlen input so no stride is degenerate; the fullgraph trace test's CPU kernel also produces the production stride contract. Lesson encoded: shape-only fakes are insufficient for ops returning non-contiguous views.Final performance evidence (at this head)
Matched same-node comparisons (LTX-2.3-Distilled, single GPU, identical prompts/seeds/settings, compiled inference, within-batch ratios), replicated across three nodes:
At 720p the ordering itself flips with the node: two nodes measured NVFP4 1.34x and 1.21x faster, a third measured it 1.43x slower — with identical graph-break counts in both arms, so it is not a compile artifact. The 1080p advantage and the memory reduction are the replicated claims; 720p performance should be measured on the target node before deployment decisions.
torch.compile(fullgraph=True)now executes for the NVFP4 path (previously impossible): zero graph breaks, routing receipt confirmed in-log.Blast radius (two-stack)
is_attn_qat_infer_availableis also touched by my open [bugfix]: complete #1601: atomic export, attn pass-through, arch gating #1646 (which narrows the CUTLASS capability set to the built arch) — same owner, whichever lands second rebases trivially; the capability-set VALUE stays [bugfix]: complete #1601: atomic export, attn pass-through, arch gating #1646/[kernel] Build + allow attn_qat_infer FP4 attention on sm_121a (DGX Spark) #1598's concern, the routing structure is this PR's.Test evidence
fastvideo/tests/attention/test_attn_qat_infer_arch_gate.py(resolution matrix for (12,0)/(12,1)/(10,0)/(10,3)/(9,0)/(8,9)/no-cuda + receipt-content tests) andfastvideo/tests/ops/quantization/test_nvfp4_purge.py(construction-level: auto/retain/purge matrix, out_dim after purge, dense-path-after-purge raises, receipt log content).tests/local_tests/test_nvfp4_fa4.pyextended with the ATTN_QAT_INFER-on-sm_100/103 route: resolution + receipt, forward parity vs SDPA (cos ≥ 0.97, same bound as the sm_120 kernel test), cross-attention lengths. Runs on GB200; sm_103 (GB300) is hardware-validated: route/parity/cross-attention 3/3 PASS and an 8-shape fp32-SDPA sweep (cos 0.99044–0.99077) on a single-GPU GB300 node (NVIDIA GB300, compute_cap 10.3) — receipts in the PR comments.Context