Repository navigation
[megatron]feat: Deepseek v4 RL MXFP4 experts qat support - #7895
Draft
sophiayyya wants to merge 6 commits into
Draft
sophiayyya wants to merge 6 commits into
sophiayyya wants to merge 6 commits into
Conversation
The DeepSeek-V4 report describes FP4 quantization-aware training applied to MoE expert weights during post-training. This adds `qat.mode=mxfp4_experts`: a weight-only ModelOpt fake-quant onto the MXFP4 grid (E2M1 values, one E8M0 power-of-two scale per 32 contiguous K elements) scoped to routed experts via `*mlp.experts*weight_quantizer`, with `algorithm=None` because dynamic block quantization derives its scale per call and ModelOpt asserts it is never calibrated. The GEMMs keep running in real FP8 through TE's blockwise autocast rather than falling back to a simulated BF16 matmul. ModelOpt refuses to run any quantizer under `fp8_autocast` -- a guard that keeps pure simulation faithful, but here the stacking is the point (FP4 weights feeding a real FP8 GEMM, which is what the checkpoint's own mixed MXFP4/FP8 layout implies). `qat.bypass_te_fp8_assert` lifts it at runtime without patching ModelOpt. Activations are quantized once, by TE; ModelOpt's input_quantizer stays disabled so they are not quantized twice. Two adjacent fixes were required to make QAT usable on such a model: - The ModelOpt layer spec is no longer forced on providers that declare an `experimental_attention_variant` (DeepSeek-V4 "dsv4_hybrid", GLM5 "dsa", Qwen3-Next "gated_delta_net"). Those install their own heterogeneous spec in `provider_bridge()`, and the generic ModelOpt GPT spec would silently replace it and build a different model. ModelOpt swaps QuantModules by class, so the spec change is not needed for quantization to apply. - `export_qat_weights` is gated to the NVFP4 modes it actually implements. For `mxfp4_experts` the bridge already re-quantizes routed experts to MXFP4 on every weight sync, so the training forward and the rollout weights land on one grid without a second exporter. `apply_qat_to_modules` now fails fast if the experts-only config did not land where intended: it requires at least one enabled routed-expert weight quantizer and no other enabled quantizer (a mis-ordered cfg would leave every remaining linear on ModelOpt's default per-tensor INT8), and logs whether the fake-quant is the identity on the loaded weights -- it is, exactly, when the checkpoint already stores those experts on the MXFP4 grid. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: OpenAI Codex <noreply@openai.com>
Mirrors run_deepseek_v4_flash_megatron.sh with TE fp8 blockwise training, fp8 vLLM rollout and the optional `mxfp4_experts` QAT (off by default). Documents why the FP4 step is simulated on Hopper while the FP8 GEMM is not, and why filter_overlong_prompts must stay off for DeepSeek-V4. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Preserve native Megatron checkpoint methods around stateless expert MXFP4 quantization, and restore offloaded optimizer shards before loading HDO state. Add independent length-only and MXFP4 expert QAT recipes with a 4096-token response budget, 40 total steps and validation every 10 steps. Require model and dataset locations from the environment and use portable output defaults. Validation: checkpoint regressions passed (6 and 7 tests); the original length-only and QAT runs each completed 40 steps including save/resume. Published launch arguments match both completed experiments at 20/40 steps. Shell syntax, required-input checks and credential/path scans passed. Two pre-existing repository checks are excluded: stale generated reference configuration and naming of an older example. New example names pass. Co-authored-by: OpenAI Codex <noreply@openai.com>
Remove the two checkpoint regression test files from this branch as requested. Co-authored-by: OpenAI Codex <noreply@openai.com>
Record the HDO FP32-shard detach prerequisite, upstream fix and validation provenance in the standalone MXFP4 QAT script. Remove the length-only recipe and its stale reference from the QAT header. Validation: bash -n and git diff --check pass; the executable QAT script body is byte-for-byte unchanged. Co-authored-by: OpenAI Codex <noreply@openai.com>
Rename the original DeepSeek-V4-Flash QAT example to use the required Megatron backend suffix, preserving its contents. Refresh the generated Megatron reference config with the existing bypass_te_fp8_assert defaults. Co-authored-by: Codex
|
|
7 of 8 tasks
4 of 8 tasks
wuxibin89
pushed a commit
that referenced
this pull request
Sep 29, 2026
…8062) ### What does this PR do? The FP8 end-to-end section of `docs/low_precision/fp8.md` lists `NVTE_FP8_BLOCK_SCALING_FP32_SCALES=1` as a general requirement. It only applies on Hopper. On Blackwell (SM100+), Transformer Engine has no native block-scaled GEMM. It runs the block-wise recipe through MXFP8 GEMMs, whose E8M0 scales hold only an exponent. So both of its block-quantize kernels assert power-of-two scales on SM100+, and a run with the variable set stops at the first FP8 quantization: ``` transformer_engine/common/transpose/quantize_transpose_vector_blockwise.cu:534 in function quantize_transpose_vector_blockwise: Assertion failed: pow2_scale. On Blackwell and newer, the FP8 block scaling recipe is emulated with MXFP8, which requires using power of two scaling factors. ``` This is the failure reported in #6172 (8×B200) when following this doc and the verl-recipe FP8 E2E script. This PR marks the variable as Hopper-only and says that on Blackwell it must stay unset; power-of-two scales are the Transformer Engine default. Docs only. Refs #6172. This does not fix #6172: that issue also reports garbled FP8 rollouts on Blackwell once the variable is removed, and this PR does not address that. ### Checklist Before Starting - [x] Search for similar PRs: - [NVTE_FP8_BLOCK_SCALING_FP32_SCALES](https://github.com/verl-project/verl/pulls?q=NVTE_FP8_BLOCK_SCALING_FP32_SCALES) - [blockwise Blackwell](https://github.com/verl-project/verl/pulls?q=blockwise+Blackwell) - No PR changes this requirement. Related: #6172 (the issue above); #7895 (sets the variable in its DeepSeek-V4 example scripts, does not touch this doc); #7519 (MXFP8 training, does not change this line). - [x] Format the PR title as `[{modules}] {type}: {description}` ### Test Documentation-only change. - `pre-commit run --files docs/low_precision/fp8.md`: all hooks pass, including "Check docs Last updated info". - Reproduced on 1×B200 (SM 10.0, torch 2.11.0+cu130, CUDA 13.0, Transformer Engine 2.16.1). `te.Linear` (2048→2048) and `te.GroupedLinear` (4 × 2048→768) ran forward and backward under `Float8BlockScaling(fp8_format=Format.E4M3)` and were compared with a bf16 run of the same module: | `NVTE_FP8_BLOCK_SCALING_FP32_SCALES` | `te.Linear` out / dgrad / wgrad rel. err | `te.GroupedLinear` out / dgrad / wgrad rel. err | |---|---|---| | unset (power-of-two scales) | 0.0377 / 0.0423 / 0.0462 | 0.0376 / 0.0475 / 0.0510 | | `1` | `RuntimeError`: the `pow2_scale` assertion above | same | The same modules under `MXFP8BlockScaling` give the same errors as the unset row, with or without the variable. Source references (Transformer Engine 2.16.1, commit c9877beb): - `transformer_engine/common/transpose/quantize_transpose_vector_blockwise.cu:533-536` and `transformer_engine/common/transpose/quantize_transpose_square_blockwise.cu:490-493`: `if (sm_arch() >= 100) NVTE_CHECK(pow2_scale, ...)`. - `transformer_engine/pytorch/csrc/extensions/gemm.cpp:289-300`: "Emulate the FP8 block scaling recipe with MXFP8 on Blackwell and newer as it is not natively supported by cublasLt". - `transformer_engine/common/swizzle/swizzle_block_scaling.cu:116-118, 205-206`: each FP32 block scale becomes an E8M0 scale by keeping only its exponent byte, `(sf >> 23) & 0xFF`. This is why the scales must be powers of two. ### API and Usage Example None. ### Design & Code Changes `docs/low_precision/fp8.md`: - The requirement line now says that the variable is Hopper-only, why it fails on Blackwell, and what to do there. - "Last updated" is bumped. The verl-recipe script `low_precision/run_dapo_qwen3_moe_30b_megatron_fp8e2e.sh` also exports the variable unconditionally. That lives in the recipe repository and can get a matching note separately. ### Checklist Before Submitting - [ ] Read the [Contribute Guide](https://github.com/verl-project/verl/blob/main/CONTRIBUTING.md). - [x] Apply [pre-commit checks](https://github.com/verl-project/verl/blob/main/CONTRIBUTING.md#code-linting-and-formatting). - [x] Add / Update [the documentation](https://github.com/verl-project/verl/tree/main/docs). - [ ] Add unit or end-to-end test(s) to [the CI workflow](https://github.com/verl-project/verl/tree/main/.github/workflows) to cover all the code. If not feasible, explain why: documentation-only change; the behaviour it documents was checked on B200 as described under Test. - [ ] Once your PR is ready for CI, send a message in [the `ci-request` channel](https://verl-project.slack.com/archives/C091TCESWB1). - [ ] If your PR is related to the `recipe` submodule, please also update the reference to the submodule commit: not applicable. AI assistance: this PR was prepared with AI assistance (Claude Code). I reviewed the change and the evidence above, and the checks listed under Test were run for this PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
6 of 7 tasks
5 of 6 tasks
This was referenced Oct 29, 2026
wuxibin89
added a commit
that referenced
this pull request
Nov 2, 2026
…h live refit (#7971) ### What does this PR do? Add end-to-end native NVFP4 W4A4 training and rollout on NVIDIA Blackwell GPUs, demonstrated with Qwen3-30B-A3B-Base DAPO using Megatron/Transformer Engine and vLLM. This contributes to Sophia's [low-precision roadmap #5972](#5972), specifically **NVFP4 real quant** and **NVFP4 training in Megatron**. In brief: - **Training:** Transformer Engine runs selected routed-expert MLPs in NVFP4 with per-token activation scaling and dequantized backward. Persistent policy weights remain BF16, with full optimizer state. - **Weight synchronization:** following the trainer-side quantization boundary of #8287, the trainer exports the routed experts as NVFP4 with `moe: NVFP4` and `moe_activation: nvfp4_per_token` after each policy update. - **Rollout:** vLLM loads the NVFP4 expert weights and quantizes activations per token, matching training. Refit preserves the storage referenced by CUDA graphs. Attention and the configured boundary-layer MLPs remain BF16. The Qwen3 example keeps the first two and last four MLP layers in BF16 and applies NVFP4 to the remaining 42 routed-expert MLP layers. ### Checklist Before Starting - [x] Search for similar PRs: [NVFP4](https://github.com/verl-project/verl/pulls?q=is%3Apr+is%3Aopen+NVFP4), [roadmap #5972](https://github.com/verl-project/verl/pulls?q=is%3Apr+is%3Aopen+5972+in%3Abody). - [x] Format the PR title as `[{modules}] {type}: {description}`. Related work: #6455 targets ModelOpt/TRT-LLM synchronization; #6992 provides FSDP W4A8 simulation; #7895 targets DeepSeek MXFP4 on TE FP8; #7519 adds MXFP8 training and rollout. #8287 adds ModelOpt NVFP4 QAT with static activation scales; this PR adds native TE NVFP4 training with per-token activation scaling, on the same export path. ### Test Unit tests (CPU and GB200) pass; scoped Ruff, formatting and lockfile checks pass. The trainer-side export is bit-identical to vLLM's online `nvfp4_per_token` quantization, and 6-step runs on Qwen3-30B-A3B (8 × 4 GB200) and a small DeepSeek-V3-layout model pass. #### Long run BF16 and W4A4 runs of the example script below (Qwen3-30B-A3B-Base, DAPO, R3, token-level TIS) on 8 nodes × 4 GB200 GPUs, 700 steps with checkpoint resume across jobs. **W4A4 vs BF16:** **Training score (`critic/score/mean`)** <img width="1813" height="957" alt="image" src="https://github.com/user-attachments/assets/d0693c0b-6789-4285-8658-44a885d72a72" /> **Entropy (`actor/entropy`)** <img width="1814" height="952" alt="image" src="https://github.com/user-attachments/assets/e63b552c-fe9b-4b23-9751-62c38976732c" /> **Train–rollout mismatch (`rollout_corr/kl`)** <img width="1811" height="952" alt="image" src="https://github.com/user-attachments/assets/13131fe5-c670-41ea-91e1-68e5fff123ee" /> **Gradient norm (`actor/grad_norm`)** <img width="1813" height="953" alt="image" src="https://github.com/user-attachments/assets/b121c562-b6f7-4432-8a7e-ed5768d78e69" /> **Performance:** at matched response length, NVFP4 rollout generation is about 1.3× faster than BF16 once the mean response exceeds ~2.5k tokens, giving roughly 1.2× shorter end-to-end steps; NVFP4 training itself is still slower than BF16 in Transformer Engine. ### API and Usage Example With a Ray cluster running on eight nodes, provide model and dataset paths shared by all workers: ```bash MODEL_PATH=/shared/models/Qwen3-30B-A3B-Base \ TRAIN_FILE=/shared/data/train.parquet \ TEST_FILE=/shared/data/validation.parquet \ EXP_NAME=qwen3-native-nvfp4 \ PRECISION_MODE=real_nvfp4 \ bash examples/real_nvfp4/run_qwen3_30b_megatron.sh ``` Use `PRECISION_MODE=bf16` for the baseline. NVFP4 training is enabled like FP8 training, through `actor_rollout_ref.actor.megatron.override_transformer_config` (`fp4: e2m1`, `fp4_recipe: nvfp4`, and `first_last_layers_bf16` with `num_layers_at_start_in_bf16` / `num_layers_at_end_in_bf16`), and rollout through `actor_rollout_ref.rollout.quantization.moe=NVFP4` with `moe_activation=nvfp4_per_token`, whose `ignore` list keeps the same layers in BF16; the trainer checks that the two agree. The example uses the standard verl PPO entry point, parquet datasets and built-in reward manager, with the DAPO recipe (clip-higher, token-level loss, dynamic sampling and the overlong penalty), R3 routing replay and token-level TIS. See [the example guide](https://github.com/zhangyimi/verl/blob/feat/native-nvfp4/examples/real_nvfp4/README.md) for configuration and runtime setup. ### Design & Code Changes - **Training precision:** the Megatron per-module recipe (attention BF16, routed-expert MLPs NVFP4, carved-out layers BF16) is generated from the configuration rather than maintained as a file. After model construction, the effective precision of every attention and expert linear layer is checked against it. Packed THD sequences use the TE alignment for FP4 as for FP8. - **Rollout config and refit:** `moe_activation=nvfp4_per_token` selects a compressed-tensors scheme (NVFP4 weights, fully dynamic NVFP4 inputs). The trainer quantizes the experts with its own Triton kernel, sharing one global scale across `gate_proj`/`up_proj`, bit-identical to vLLM's online `nvfp4_per_token` quantization. In vLLM the scheme selects FlashInfer TRT-LLM with per-token activations; refits load each bucket in place into the expert storage captured by CUDA graphs and post-process each MoE layer, so the extra memory is one MoE layer. - **Routing replay:** use vLLM’s native fused-MoE routing capture and align replay data with FP4 training padding. - **Runtime compatibility:** Transformer Engine 2.20.2 from the verl wheelhouse. No vLLM source patch is needed. The validated Megatron + vLLM stack uses: | Component | Version | |---|---| | PyTorch | 2.13 / CUDA 13 | | vLLM | 0.32.0 | | Transformers | 5.16.1 | | Megatron-Core | 0.19.2 | | Megatron-Bridge | 0.6.2 | | Transformer Engine | 2.20.2 | | FlashInfer | 0.7.0.post1 | | CUTLASS DSL / QuACK | 4.8.0 / 0.6.5 | SGLang end-to-end validation remains follow-up work. ### Checklist Before Submitting - [x] Read the [Contribute Guide](https://github.com/verl-project/verl/blob/main/CONTRIBUTING.md). - [ ] Run the complete all-files pre-commit suite. Focused lint, formatting, shell and lockfile checks have passed. - [x] Add usage, design and runtime compatibility documentation. - [x] Add focused unit and end-to-end coverage. Project CI integration remains to be completed. - [x] Request project CI and review. - [x] Check recipe coordination: the recipe submodule reference is unchanged; no companion recipe PR is required. AI assistance: OpenAI Codex and Anthropic Claude assisted with implementation, testing and this PR description. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Codex <noreply@openai.com> Co-authored-by: wuxibin <wuxibin@bytedance.com>
7 of 8 tasks
wuxibin89
added a commit
that referenced
this pull request
Nov 2, 2026
### What does this PR do? Add shared TileLang quantization kernels for FP8_BLOCK, MXFP8, and MXFP4 QAT and parameter export. QAT uses fused quantize-dequantize with straight-through gradients, while export uses the same kernels without dequantization so values and scales follow the same numerical recipe. NVFP4 QAT uses triton kernel in #8494. This overlaps with [#7895](#7895), which adds DeepSeek-specific routed-expert MXFP4 weight-only QAT using ModelOpt's CUDA extension. This PR instead provides reusable TileLang kernels for FP8_BLOCK, MXFP8, and MXFP4, applies them to both weight/activation fake quantization and checkpoint export, and keeps the existing QAT mode interface. AI assistance was used for implementation, numerical comparison, testing, debugging, and preparation of this PR description. The human submitter directed the numerical design and must review every changed line and validation result before requesting maintainer review. ### Checklist Before Starting - [x] Search for similar PRs: [QAT quant kernel search](https://github.com/verl-project/verl/pulls?q=is%3Apr+is%3Aopen+QAT+quant+kernel), [MXFP4 QAT search](https://github.com/verl-project/verl/pulls?q=is%3Apr+is%3Aopen+MXFP4+QAT). - [x] Format the PR title as `[{modules}] {type}: {description}`. ### Test ```bash # FP8, MXFP8, MXFP4 kernels, export integration, and ModelOpt integration pytest -q tests/utils/test_qat_fp8_on_gpu.py tests/utils/test_qat_fp4_on_gpu.py tests/utils/test_qat_export_kernels_on_gpu.py tests/utils/test_modelopt_mxfp8_on_gpu.py # 51 passed # CPU CI-equivalent environment uv run --frozen --all-packages --extra cpu pytest -s -x --asyncio-mode=auto tests/utils/real_nvfp4 # 24 passed, 1 skipped uvx --with hydra-core pre-commit run --all-files --show-diff-on-failure --color=always # all hooks passed git diff --check origin/main...HEAD # passed ``` FP8 and MXFP4 quantized values, scales, and fused QDQ outputs were also compared bitwise against the DeepSeek-V4.1 inference reference kernels. ### API and Usage Example ```python from verl.utils.qat.fp4 import fp4_quant from verl.utils.qat.fp8 import fp8_quant fp8_weight, fp8_scale = fp8_quant(weight, (128, 128)) mxfp8_weight, mxfp8_scale = fp8_quant(weight, (1, 32), scale_fmt="e8m0") mxfp4_weight, mxfp4_scale = fp4_quant(weight) # Fused fake quantization used by QAT: dequantized_activation = fp8_quant(activation, (1, 32), scale_fmt="e8m0", dequant=True) ``` ### Design & Code Changes - Add 2D FP8_BLOCK and 1D MXFP8 TileLang kernels with optional fused dequantization and FP32/E8M0 scale output. - Add a packed 1x32 MXFP4 TileLang kernel with optional fused dequantization. - Route ModelOpt FP8_BLOCK, MXFP8, and MXFP4 fake quantizers through the new kernels while retaining straight-through gradients. - Route compressed-tensors FP8_BLOCK, MXFP8, and MXFP4 CUDA weight export through the same kernels; retain CPU and NVFP4 fallbacks. - Add numerical and export integration tests and document the shared QAT/export behavior. - Upgrade ModelOpt to 0.47.0 and update the lockfile. - Isolate Megatron stubs in the Muon CPU tests so they do not pollute later tests through `sys.modules`. ### Checklist Before Submitting - [x] Read the [Contribute Guide](https://github.com/verl-project/verl/blob/main/CONTRIBUTING.md). - [x] Apply [pre-commit checks](https://github.com/verl-project/verl/blob/main/CONTRIBUTING.md#code-linting-and-formatting). - [x] Add / Update [the documentation](https://github.com/verl-project/verl/tree/main/docs). - [x] Add unit tests to cover the kernels, QAT integration, and export integration. - [ ] Once the PR is ready for CI, send a message in the `ci-request` channel. - [x] This PR is not related to the `recipe` submodule.
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?
MXFP4 QAT precision and data flow
This change adds routed-expert weight-only MXFP4 fake quantization on top of Transformer Engine (TE) FP8 training for DeepSeek-V4-Flash-0731. Checkpoint storage, trainable parameter dtype, and GEMM precision are separate:
w1,w2,w3I8byte; one E8M0 scale per 32 contiguous input-channel elementsmlp.experts.linear_fc1/linear_fc2wq_a,wq_b,wkv,wo_a,wo_b; indexerwq_bweights_projhc_attn_fn/hc_ffn_fn,attn_sink, and compressorapeI8is the byte container for packed FP4 values, not INT8 quantization. The checkpoint precision map establishes tensor storage and scale geometry; it does not establish runtime kernel precision. Bridge's E2M1 unpacking and the QAT configuration provide the implementation-level interpretation of the packed expert weights. Only indexerwq_bis FP8 in this table; the entire indexer is not uniformly FP8.flowchart TD C["0731 checkpoint: MXFP4 experts / FP8 projections / BF16 / FP32"] I["Bridge import: unpack and dequantize quantized weights"] P["Trainable model parameters: BF16 plus native FP32 tensors"] Q["Routed expert weights: dynamic MXFP4 Q/DQ; BF16 temporary output"] T["TE FP8 quantization and GEMM: hybrid / blockwise recipe"] O["Adam update: FP32 main parameters and optimizer state; HDO CPU offload"] E["Bridge export: requantize updated parameters to MXFP4 / FP8 weight-scale pairs"] V["vLLM rollout / validation: quantization=fp8; KV cache=fp8"] C --> I --> P P -->|routed expert weights| Q Q --> T P -->|other TE FP8 linear paths| T T --> O O -->|update model parameters| P P -->|weight synchronization| E E --> VQAT scope and kernel.
qat.mode=mxfp4_expertsdisables all ModelOpt quantizers first, then enables only*mlp.experts*weight_quantizer, withnum_bits=(2, 1)andblock_sizes={-1: 32, "type": "dynamic", "scale_bits": (8, 0)}. Scales are computed on each call;algorithm=Nonerequires no calibration pass. Shared experts, attention, router, and all ModelOpt input/output quantizers remain disabled. This change does not implement FP4 indexer QK computation or additional KV/output-projection activation fake-quantization.In the validated ModelOpt 0.44 implementation, MXFP4 fake-quant uses
modelopt_cuda_ext_mx.fused_amax_convert→ CUDAamax_and_convert_kernel. It returns BF16 values on the MXFP4 grid without permanently packing the trainable parameters. TE then quantizes weights and activations for its FP8 GEMMs. On the validated H100 setup, this simulates MXFP4 weight error while computing the supported GEMMs in FP8; it is not native FP4 GEMM.bypass_te_fp8_assert=Trueallows this explicit composition. Direct FP8 parameter loading andfp8_paramare not enabled.Scale and rollout handling. Checkpoint E8M0 scales are distinct from runtime compute scales: the recipe sets
NVTE_FP8_BLOCK_SCALING_FP32_SCALES=1for TE andVLLM_USE_DEEP_GEMM_E8M0=0for the vLLM DeepGEMM path. Bridge exports the updated model parameters and independently recreates packed MXFP4 expert weights and FP8 projection weights with their scales. It does not export a previous forward pass's temporary fake-quant result. The generic NVFP4QATWeightExporteris skipped for this mode, androllout.qat.enable=Falsestill retains Bridge's quantized weight synchronization. The diagram describes export formats and rollout configuration, not the compute precision of every vLLM kernel.Checkpoint compatibility. Dynamic MXFP4 quantizers have no persistent calibration tensors.
preserve_mxfp4_checkpoint_methodstherefore preserves native TE/Megatron checkpoint methods while retaining the QAT forward path, with a guard rejecting persistent quantizer state. HDO resume restores optimizer main shards to the GPU before loading optimizer state. Neither fix changes the quantization recipe. Native FP32 parameters with HDO additionally require the detach fix in NVIDIA/Megatron-LM#6982, as documented in the example script.Implementation: quantization configuration, checkpoint compatibility, and 40-step QAT example.
Quantization experiment evidence
The completed H100 experiment ran 40 steps with a 4096-token response limit, validation at steps 10/20/30/40, checkpoints at steps 20/40, and optimizer-state resume between the two 20-step segments. Step-40 AIME validation accuracy was 64.21% with MXFP4 QAT, versus 64.59% for the TE FP8 control without ModelOpt QAT. These are single-run measurements, not evidence of a statistically significant difference. See the QAT run and control run.
This experiment predates the final rebase. It used the implementation before publication cleanup and Megatron
1ff25ca7ewith the equivalent local FP32-shard detach patch; the runtime patch helper is not included in this PR. These results validate that experiment, not a fresh 40-step run of the rebased head.Checklist Before Starting
[{modules}] {type}: {description}(This will be checked by the CI){modules}includefsdp,megatron,veomni,sglang,vllm,rollout,trainer,ci,training_utils,recipe,hardware,deployment,ray,worker,single_controller,misc,perf,model,algo,env,tool,ckpt,doc,data,cfg,reward,fully_async,one_step_off,like[megatron, fsdp, doc]{type}is infeat,fix,refactor,chore,test[BREAKING]to the beginning of the title.[BREAKING][fsdp, megatron] feat: dynamic batchingTest
API and Usage Example
# Add code snippet or script demonstrating how to use thisDesign & Code Changes
Checklist Before Submitting
Important
Please check all the following items before requesting a review, otherwise the reviewer might deprioritize this PR for review.
pre-commit install && pre-commit run --all-files --show-diff-on-failure --color=alwaysci-requestchannel in theverlSlack workspace. (If not accessible, please try the Feishu group (飞书群).)recipesubmodule, please also update the reference to the submodule commit viagit submodule update --remoteorcd recipe && git pull origin main.