Add fused NVFP4 fake-QAT QDQ kernels - #2864
Open
zianglih wants to merge 2 commits into
Open
Conversation
Signed-off-by: Ziang Li <ziangli@umich.edu>
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
Signed-off-by: Ziang Li <ziangli@umich.edu>
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
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
Moves the fused CuTe DSL NVFP4 fake-QAT QDQ implementation, numerical tests, and benchmark into
Miles, paired with the minimal Megatron integration in
Megatron-LM #91.
ci-megatron-pr: #91
manual benchmark. 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_nvfp4_quantizer.pyCI registration unchanged;Blackwell routing for that 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 draft 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.
Validation
ca0c3425f2c5b5f8ec97fc4af6e8fd976d32f704ffa7dc4ac3741c1e4f2c896aa78273730c418fe4(the head differs only by restoring the pre-existing CI registration metadata)
2799fe386320c156334bf763ad4d7ca0f85dca4e(main)65940a7197427997bbfd411b3944849f68c1aaf0radixark/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.Repository checks:
Performance
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 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
current paired implementation and latest full table above.
30d5fd6321e63642d761b2c1170ffa7dc4acLimitations and untested scope
and no compatibility fallback is included.
geomeans.