[PyTorch] MXFP4 weight QAT on MXFP8 and FP8 block-scaling recipes - #3264
Open
xiuhu17 wants to merge 2 commits into
Open
[PyTorch] MXFP4 weight QAT on MXFP8 and FP8 block-scaling recipes#3264xiuhu17 wants to merge 2 commits into
xiuhu17 wants to merge 2 commits into
Conversation
xiuhu17
requested review from
Oleg-Goncharov,
ksivaman,
ptrendx and
timmoon10
as code owners
July 27, 2026 07:41
Contributor
Greptile SummaryThe PR adds weight-only MXFP4 quantization-aware training on MXFP8 and FP8 block-scaling recipes.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; the previously reported cached-weight issue is resolved because the skip-update flag now reaches the in-place quantization operation, which preserves the existing workspace on non-first microbatches. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
W["Master BF16/FP32 weight"] --> QAT["MXFP4 fake quantization<br/>1x32 E2M1 grid"]
QAT --> P["Projected high-precision weight"]
P --> Host["Existing MXFP8 or FP8 block quantizer"]
Host --> GEMM["Existing quantized GEMM"]
GEMM --> FWD["Forward output"]
GEMM --> BWD["Backward using configured override"]
BWD --> STE["Straight-through gradient"]
STE --> W
Reviews (7): Last reviewed commit: "update" | Re-trigger Greptile |
xiuhu17
marked this pull request as draft
July 27, 2026 08:38
xiuhu17
marked this pull request as ready for review
July 29, 2026 05:49
Contributor
|
Want your agent to iterate on Greptile's feedback? Try greploops. |
Weight-only MXFP4 quantization-aware training: weights are projected onto the MXFP4 grid (E2M1 payloads, 1x32 power-of-two UE8M0 scales) before the host recipe quantizes them, so training sees exactly the deployment weight while activations and gradients keep the base recipe untouched. The only new numerics is the fused projection bf16/fp32 -> MXFP4 grid -> bf16/fp32 (tex.mxfp4_fake_quantize): per 1x32 block, scale 2^clamp(ceil(log2(amax/6)), -126, 125) derived from the amax bit pattern, RTNE onto E2M1, straight-through-estimator gradient. All MXFP8 and 128x128 blockwise FP8 encoding/decoding of the projected weight runs through the existing quantizer pipeline unchanged. Since every projected value is a grid point p * 2^e, the existing encodings are decoded-value exact: MXFP8 rowwise unconditionally, 128x128 blockwise for tile scale spreads up to 2^14. Recipes: MXFP4QATMXFP8BlockScaling(MXFP8BlockScaling) and MXFP4QATFloat8BlockScaling(Float8BlockScaling); QAT can also be enabled on the stock host recipes via the mxfp4_qat_weights field (NVTE_MXFP4_QAT=1). backward_override keeps its base-recipe semantics. Also fixes ptx::exp2f(e8m0) to decode UE8M0 code 0 as 2^-127 and code 255 as NaN. Known limitations: for amax > 6*2^125 the fake-dequant saturates at the cap while packed deployment moves to scale 2^126; fp16 weights and fp16 activation/dequantize dtypes are rejected (the MXFP4 grid exceeds fp16 range); distributed end-to-end verification with a real optimizer master step and a fused projection+quantize kernel are future work.
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.
Description
Weight-only MXFP4 quantization-aware training: weights are projected onto the MXFP4 grid (E2M1 payloads, 1x32 power-of-two UE8M0 scales) before the host recipe quantizes them, so training sees exactly the deployment weight while activations and gradients keep the base recipe untouched.
The only new numerics is the fused projection
bf16/fp32 -> MXFP4 grid -> bf16/fp32(tex.mxfp4_fake_quantize: per 1x32 block, scale2^clamp(ceil(log2(amax/6)), -126, 125)derived from the amax bit pattern, RTNE onto E2M1, straight-through-estimator gradient). All MXFP8 and 128x128 blockwise FP8 encoding/decoding of the projected weight runs through the existing quantizer pipeline unchanged. Since every projected value is a grid pointp * 2^e, the existing encodings are decoded-value exact: MXFP8 rowwise unconditionally, 128x128 blockwise for tile scale spreads up to 2^14.Recipes:
MXFP4QATMXFP8BlockScaling(MXFP8BlockScaling)andMXFP4QATFloat8BlockScaling(Float8BlockScaling); QAT can also be enabled on the stock host recipes via themxfp4_qat_weightsfield (NVTE_MXFP4_QAT=1).backward_overridekeeps its base-recipe semantics. Also fixesptx::exp2f(e8m0)to decode UE8M0 code 0 as 2^-127 and code 255 as NaN.Test results (B200,
tests/pytorch/test_mxfp4_qat.py)--use_fast_mathrebuild of the same kernel sourcebackward_override{None, dequantized, high_precision} x fused/unfused wgrad; recipe-switch cache invalidation; loud rejection of unsupported surfaces (ops API, fused Userbuffers/grouped-MLP, fp16, primary FP8 weights)Known limitations
Type of change
Checklist: