Add fused NVFP4 fake-QAT QDQ kernels - #2864
Merged
yueming-yuan merged 12 commits intoSep 11, 2026
Merged
Conversation
6 tasks
zianglih
marked this pull request as ready for review
September 1, 2026 19:22
zianglih
requested review from
Shi-Dong,
Zhichenzzz,
fzyzcjy,
guapisolo,
jybsuper,
maocheng23 and
yueming-yuan
as code owners
September 1, 2026 19:22
zianglih
marked this pull request as draft
September 1, 2026 20:28
zianglih
marked this pull request as ready for review
September 1, 2026 20:28
Signed-off-by: Ziang Li <ziangli@umich.edu>
Signed-off-by: Ziang Li <ziangli@umich.edu>
ziang-and
force-pushed
the
agent/nvfp4-qdq-kernel-miles
branch
from
September 8, 2026 22:15
ca0c342 to
ca7abae
Compare
Signed-off-by: Ziang Li <ziangli@umich.edu>
Signed-off-by: Ziang Li <ziangli@umich.edu>
Signed-off-by: Ziang Li <ziangli@umich.edu>
Signed-off-by: Ziang Li <ziangli@umich.edu>
ziang-and
force-pushed
the
agent/nvfp4-qdq-kernel-miles
branch
from
September 9, 2026 06:14
4a5e743 to
142e904
Compare
yueming-yuan
approved these changes
Sep 11, 2026
18 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
@HumansAnd
Adds fused CuTe DSL NVFP4 fake-QAT QDQ, strict numerical tests, and a colocated
GLM-5.2 W4A16 RL end-to-end recipe in Miles, paired with the minimal Megatron integration in
Megatron-LM #91.
ci-megatron-pr: #91
E2E recipe. The manual benchmark was measured and removed in a separate cleanup commit; its source and raw results remain linked below. The paired Megatron PR adds only the env-gated lazy call in
TEGroupedLinear._get_weight_tensors().and packed E2M1 value in registers, and writes only the dequantized BF16/FP16 result. This removes
the quantized-data and block-scale global-memory round trips in the former
quantize(...).dequantize(...)fake-QAT path.no assumption that the weight count is 4, 8, or another fixed multiple; eight weights are only
the requested benchmark proxy.
candidate-error behavior are compile-time CuTe specializations cached outside the steady-state
path. The grid-stride kernels do not branch on those modes at runtime.
amax;
NVTE_USE_FAST_MATH=0; standard NVFP4 plus the complete 4over6 MAE/MSE, E4M3 256/448,exact-error/FP16-error matrix. The public config field is
error_use_fast_math, matchingNVTE_NVFP4_4OVER6_ERR_USE_FAST_MATH, while its TE 2.17 meaning is explicitly documented asFP16-rounded candidate-error math rather than ordinary instruction fast math.
deliberately carries no pre-2.17 version fallback or runtime support validator; recipe
compatibility is configured by the caller.
test_glm5_2_744b_a40b_5layer_nvfp4.pyintotest_glm5_2_744b_a40b_5layer_nvfp4_w4a16.py. It selects--sglang-moe-runner-backend flashinfer_cutedsl,SGLANG_FLASHINFER_CUTEDSL_NVFP4_W4A16=1, andSGLANG_FLASHINFER_MOE_FUSED_FINALIZE=0.The actor enables the fake-QAT hook and uses a pure BF16 TE recipe for forward/backward GEMMs;
--no-gradient-accumulation-fusionlets STE gradients reach the original expert parameters.NVTE_NVFP4_4OVER6_ERR_USE_FAST_MATH=1(FP16 candidate-error math) and sets
NVTE_NVFP4_4OVER6_E4M3_USE_256=none(E4M3 max 448).Removes
NVTE_BACKWARD_OVERRIDE, the unusedFLASHINFER_NVFP4_4OVER6*settings, andSGLANG_DEEPEP_NUM_MAX_DISPATCH_TOKENS_PER_RANK. There are no first/last-layer BF16exclusions; shared experts remain BF16. Actor TP8/EP8 and four 2-GPU rollout engines share
one 8-GPU node with
--colocate; the recipe runs two GRPO rollouts with routing replay.stage-c-8-gpu-b200(est_time=3600,model-scripts).The existing
test_nvfp4_quantizer.pyregistration remains unchanged; Blackwell routing forthat file is handled separately.
row scaling, ordinary quantization fast math, pre-TE-2.17 compatibility, TE's experimental
single-grouped-parameter path, and a grouped/persistent rank-3 QDQ kernel.
The vectorized loading, FP4 conversion, and 4over6 structure are adapted from the bit-exact work in
FlashInfer #3448. The per-tensor arithmetic
order follows the current Transformer Engine contract and the work in
TE #2972 and
TE #3068. The strict oracle follows TE's
test_nvfp4_quantize_exact.py,while the four data families mirror FlashInfer's
test_fp4_quantize.py.The timing method follows
TE commit
83e23087.This preserves Megatron-LM #88 unchanged
as the complete single-repository implementation and re-expresses it as a cleaner paired split.
It remains a standalone follow-up to Megatron-LM #75.
Current rebase and C1 validation
142e9047c805d2486f48304309b413f6195e744cremoves onlytests/manual/benchmark_fused_nvfp4_qdq.pyin a separate commit, after the E2E passed and both PR bodies were refreshed. The E2E was measured on1d1c1c11b87b2fc392b3acd92818524fe4f70394; the benchmark-file deletion was not rerun on GPU. Runtime code, the E2E recipe,tests/fast-gpu/test_nvfp4_quantizer.py, and the paired Megatron hook are unchanged. The manual benchmark at its historical tested revision and complete raw C2 results remain referenced below. The strict quantizer test remains in the final tree.1d1c1c11b87b2fc392b3acd92818524fe4f70394on4dff6f262576bf751fefa17c3c4db985fc935062(main); Megatron12ea91ff82f9e38fd47d63fe0a06c729654d27d4on8c1e05747eb612b382df2632783df5c83a853646(miles-main). Range-diff preserved the original semantic patches; the rebase-only Miles head was pushed before adding the E2E. The paired Megatron hook remains four lines.radixark/miles:dev-202609081227, amd64 digestsha256:5b060f9c8304394fb8cb789d5b30ae54e9057e0487ed81c5a85cb7e17c3a0269. Selected from the live tag list immediately before allocation as the latest eligible CUDA 13 development image. Image CUDA 13.0.3; no SGLang, FlashInfer, or TE package override.b200-70, 8x NVIDIA B200 (SM100, 183359 MiB each), driver 580.126.09; PyTorch2.13.0+cu130, runtime CUDA13.0, TE2.17.0, FlashInfer0.6.18, SGLang0.5.20.dev54+ga8e5c63(a8e5c632fe40555f720d4f2c69771ea8cf24f3c4), CuTe DSL4.6.2.Pinaster/GLM-5.2_5layerat1c749139f70e158e4420ba67f342bef1de2e650d;zhuzilin/dapo-math-17kat2e65612930298bde4c5d58fd97b3f23a483aaff9. Five layers (three dense, two routed MoE), hidden size 6144, 256 experts. Shared experts retain BF16; no first/last-layer exclusions.1e-6, TIS[0.5,2], KL/entropy coefficients zero, routing replay enabled. Training uses BF16 TE GEMMs with routed-weight fake QDQ; serving uses CuTe DSL NVFP4 W4A16 with A2Anoneand unfused finalization.--sglang-enable-fp32-lm-headproduces FP32 LM-head outputs with BF16 operands;--moe-router-use-torch-mmuses Torch router matmul with FP32 router dtype. The latter was already enabled by Miles defaults and is now explicit in the test.--ci-disable-kl-checkerskips the existing one-sided MLA signed-PPO-KL assertion, following Miles #2855. PPO KL, trainer/rollout KL, absolute logprob difference, and other diagnostics remain computed and logged. Logprob and tensor-weight-equality checkers are also disabled. Explicit rollout/train/trajectory dumps replace--dump-details, avoiding its event logger and unsupported NVFP4 weight-checksum request. This is integration coverage, not actor/rollout numerical parity.git diff --check, CI registration discovery, and preparation/training argument/environment/BF16-recipe capture passed. Parser spellings were verified in the actual image. The quantizer's integer-view and zero-tolerance assertions were not changed.Exact test environment (the E2E sets these for preparation/training/serving as applicable):
Reproduction from a fresh bare devbox using the image above:
Strict C1 quantizer validation
Measured on Miles
67d7fe7b2601470005cbe6ac17112738490c8becand the same paired Megatron head, on two visible B200 GPUs. Subsequent commits change only the E2E diagnostic/precision flags; the tested quantizer, adapter, and Megatron hook are unchanged.Exit
0; log SHA25603ced2512a924b9b390678ecc0f2dbc41a83fd28e89d6d6b90cad4671e5a5845.E2E attempts before the final configuration
67d7fe7b, exit 1: conversions, W4A16 engine initialization and initial weight update completed, then event logging requested a checksum that SGLang does not implement forModelOptNvFp4FusedMoEMethod. Commit30c101240replaces--dump-detailswith the three explicit data-dump flags above. No rollout numerics were produced in this attempt.30c101240, exit 1: both RL iterations logged metrics, but step 1 failed the one-sidedtrain/ppo_kl < 1e-8condition with0.00023829405836295336. Step 0 passed by sign with-0.00007193960482254624; that does not imply near-zero magnitude. Only initial and post-step-0 weight synchronization completed. Both steps had zero rewards, advantages, losses and gradient norms. The final configuration disables that assertion and enables FP32 serving LM-head outputs; this is not a controlled ablation of either change.ppo_kltrain_rollout_logprob_abs_difftrain_rollout_klgrad_normFinal E2E completion proof
1d1c1c11b(the later manual-benchmark deletion is a separate commit).artifacts/c1-w4a16-e2e-attempt3.log.92ff1f8d4d6c592d51d1ba04cc91f5adc54da87b360fecb3747067deeab191d7.0fromartifacts/c1-w4a16-e2e-attempt3.exitcode.Stack (most recent call first)dumps at lines 7932–7953 occur after final synchronization and explicit server disposal, show Ray worker main_loop frames, and precede normal WebSocket closure and Ray success. They are retained as shutdown diagnostics.Exact log excerpts (ANSI colors removed; original physical line numbers):
Recorded RL numerics
c1-w4a16-e2e-attempt3.log(SHA256 below).92ff1f8d4d6c592d51d1ba04cc91f5adc54da87b360fecb3747067deeab191d7.completion_evidence_present; recorded Python exit:0.ci_disable_kl_checker=True; numerical metrics remain active.< 1e-8)Checker scope:
training_utils/ci_utils.py:13-16checkstrain/ppo_kl < 1e-8on optimizer step 0 of each rollout for MLA. This test has one optimizer step per rollout. The condition is one-sided; a negative value satisfies it regardless of magnitude. A disabled condition is never reported as passed.3. A full two-rollout run requires three (startup, after rollout 0, after rollout 1).Measured limitations:
[0, 1].[0, 1]. This run does not demonstrate a nonzero policy-gradient update or learning.train/entropy_loss=0is not a measurement of zero entropy: entropy computation is disabled with entropy coefficient 0 and observe-training-entropy false in this test. The reference KL metric is computed but contributes zero to total loss because its coefficient is 0.Complete raw logged numeric payloads
Source line(s)
5324:Source line(s)
5746:Source line(s)
6275, 6276:Source line(s)
6286:Source line(s)
6968:Source line(s)
7212:Source line(s)
7523, 7524:Source line(s)
7535:Historical C2 numerical validation (not rerun after rebase)
The following raw results were measured on Miles
ffa7dc4ac3741c1e4f2c896aa78273730c418fe4and Megatron
65940a7197427997bbfd411b3944849f68c1aaf0. They do not validate the current heads,new image, or new E2E recipe.
radixark/miles:dev-202609010119(
sha256:3ee2af22223ee8f0d0b0bf19340fc06bf8da6ddb26a36c76136f8f5e5c462728on amd64/B300)2.13.0+cu130, CUDA13.0,Transformer Engine
2.17.0, Cutlass DSL4.6.2The existing Blackwell quantization test is extended with
2 dtypes x 12 shapes x 4 data families x 9 numerical modes = 864strict TE-oracle cases.It compares BF16/FP16 integer views to retain signed-zero sensitivity and also calls
torch.testing.assert_close(..., rtol=0, atol=0). Tolerance is never relaxed. The same file alsotests env mapping, invalid contracts, STE/main-grad behavior, two-device state restoration, the
general arbitrary-count adapter, and a real three-weight
TEGroupedLinearforward/backward pass.cd /hai-workspace/nvfp4-qdq-split/miles CUDA_VISIBLE_DEVICES=0,1 PYTHONWARNINGS=ignore \ PYTHONPATH=/hai-workspace/nvfp4-qdq-split/miles:/hai-workspace/nvfp4-qdq-split/Megatron-LM \ pytest -q -o addopts= tests/fast-gpu/test_nvfp4_quantizer.pyLog SHA-256:
cbe0279a94cbd7adcdce5cd1f8d20dece5a8036fd4ec2ae717ac50097f34731f.Historical repository checks:
Historical C2 performance (not rerun after rebase)
The target is the complete loop over eight independently stored TE-style parameters. Each weight
is contiguous
[4096, 6144]; the reported logical shape is6144 x 4096, so every 1x16 NVFP4block lies along the 6144 input-feature axis.
--num-weightsis configurable and the productionhelper accepts arbitrary list lengths.
quantizer.quantize(x_padded).dequantize(dtype=x.dtype)[:m, :n].contiguous().maybe_fake_quantize_nvfp4_weight_tensors(...)call, including env/config resolution, one FP32PyTorch amax reduction per weight, STE wrapping, output allocation, TVM-FFI marshalling, kernel
launches, and the complete weight loop.
the speedup or geomean.
torch.utils.benchmark.Timer.blocked_autorange(min_run_time=1); three repeats;interleaved naive/fused/naive order. The naive median uses all six A/B/A samples and the fused
median uses three samples.
Exact-error remains fully covered by zero-tolerance tests but is deliberately excluded from the
benchmark target and geomean.
cd /hai-workspace/nvfp4-qdq-split/miles git checkout --detach ffa7dc4ac3741c1e4f2c896aa78273730c418fe4 CUDA_VISIBLE_DEVICES=2 PYTHONPATH=/hai-workspace/nvfp4-qdq-split/miles \ python tests/manual/benchmark_fused_nvfp4_qdq.py \ --num-weights 8 --shape 6144x4096 --dtype both \ --min-run-time 1 --repeats 3 \ --image radixark/miles:dev-202609010119@sha256:3ee2af22223ee8f0d0b0bf19340fc06bf8da6ddb26a36c76136f8f5e5c462728 \ --miles-commit ffa7dc4ac3741c1e4f2c896aa78273730c418fe4 \ --megatron-commit 65940a7197427997bbfd411b3944849f68c1aaf0Benchmark log SHA-256:
ed4e0d77d6d8bcf947a9fddf978bbf1cb078c6e2de71c791667ec682d71bbfe3.Geomean history
Exact-error 4over6 is excluded from every row. The first three rows are retained historical runs
from the single-repository PR #88. They used an older image/PyTorch build, so they document the
optimization progression rather than a strict cross-image A/B comparison. The last row is the
historically measured paired implementation in the full table above.
30d5fd6321e63642d761b2c1170ffa7dc4acLimitations and untested scope
No Hopper or pre-Blackwell execution is claimed.
and no compatibility fallback is included.
geomeans.