Repository navigation
fix(inference): make online FP8 weight updates safe and unbiased - #3628
Closed
mikasenghaas wants to merge 10 commits into
Closed
mikasenghaas wants to merge 10 commits into
mikasenghaas wants to merge 10 commits into
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5748803. Configure here.
| logger.debug(f"Pausing inference engines to update weights to policy v{step}") | ||
| await asyncio.gather( | ||
| *[_admin_post(client, "/pause", params={"mode": "keep", "clear_cache": "false"}) for client in admin_clients] | ||
| *[_admin_post(client, "/pause", params={"mode": "abort", "clear_cache": "false"}) for client in admin_clients] |
There was a problem hiding this comment.
Dynamo NCCL pause still uses keep
High Severity
The Dynamo NCCL weight-update path still pauses with mode=keep. Cancelled non-streaming requests can stay alive in vLLM and block that pause indefinitely, leaving KV from the previous policy across the update.
Reviewed by Cursor Bugbot for commit 5748803. Configure here.
…FP8 weight scales Promotes the PRIME_DIAG_UE8M0_WEIGHTS diagnostic to a config field. For dequantized FP8 releases the weights already sit on the e4m3 grid under power-of-two block scales, so quantizing with those scales is exact where amax / 448 injects full e4m3 rounding error. Measured against a bf16 reference on 203k SWE tokens, combined with VLLM_USE_DEEP_GEMM_E8M0=1 it gives the lowest mismatch of every FP8 configuration tried (KL 3.5e-3 vs 5.6e-3 for fp32 scales, IPO masked fraction 0.0000 vs 0.0002) and removes the decode-step glitch tokens. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ast path vLLM 0.29.0's TritonExperts.apply fuses SiLU-and-mul with the fp8 block quantization through ops.silu_and_mul_per_block_quant, which has no clamp argument, so DeepSeek V4 Flash's swiglu_limit of 10 is dropped for every batch below 128 tokens when VLLM_USE_DEEP_GEMM_E8M0 is off. Tokens whose gate or up pre-activation exceeds the limit get a wrong expert output; this produced the deterministic glitch-token argmaxes seen in the FP8 RL runs. The patch routes apply to the clamped activation branch whenever a clamp is configured and leaves models without a clamp on the fast path. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ne FP8 weights Round-to-nearest pins a weight that starts on the e4m3 grid until the trainer has moved it half a bin, about 1000 steps at lr 1e-6, so the served policy stays at step 0 while the trainer drifts. Rounding each weight to its far neighbour with probability equal to the fractional distance makes the served weight unbiased and lets it track sub-bin updates in expectation. On-grid input rounds to nearest, so the checkpoint quantizes to identical bytes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…for bit The trainer's per-token FP8 activation cast now matches vLLM's production CUDA op, torch.ops._C.per_token_group_fp8_quant, bit for bit. Three kernels floor amax at 1e-10 and use tl.math.div_rn for both the group scale and the elementwise quotient. Triton lowers a constexpr `/` to multiply-by-reciprocal, which sits one fp32 ULP from the correctly rounded value and flipped roughly 0.1% of quantized elements by one e4m3 step; the old 1e-4 floor applied to the scale rather than to amax also corrupted every group with amax below 0.0448. On four 4096x4096 bf16 activation tensors, identical group scales went from 41-44% to 100% and identical fp8 bytes from about 99.9% to 100%: zero differing scales of 131072 groups and zero differing bytes of 16777216 elements. The weight kernel is deliberately unchanged and stays at 100%, because vLLM's weight path is itself a multiply-by-reciprocal. A new GPU test asserts the equality against the CUDA op rather than calling into vLLM from the trainer, which imports vLLM nowhere. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Member
Author
|
Superseded by the #3692 fork branch, which the DSV4F SFT run pins. |
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.


Summary
Why stochastic rounding
Round-to-nearest can pin a weight to its initial E4M3 value until training moves it by half a quantization bin. Stochastic rounding instead selects the adjacent representable value according to the fractional distance, so the served value equals the BF16 trainer value in expectation. Values already on the FP8 grid remain exact.
Validation
ruffpassesOn B300/SM103, DeepGEMM requires packed UE8M0 scales, so the validated config pairs
fp8_ue8m0_weight_scales = truewithVLLM_USE_DEEP_GEMM_E8M0=1. The older H200-style disabled setting fails during engine startup withUnsupported architecture or scaling factor types.This PR is stacked on #3625 for the uneven-shard Muon and DSV4 attention-sink fixes. The FP8 commits preserve Garrett's authorship from #3627.
Note
Medium Risk
Changes weight-update pause semantics and online FP8 quantization paths that directly affect trainer–inference policy alignment; incorrect behavior would skew rollouts rather than typical UI-only risk.
Overview
Hardens online RL weight broadcast by pausing inference with
mode=abort(orchestrator default) instead of draining in-flight work, and exposesmode/clear_cacheon the vLLM/pauseadmin route so stale rollouts cannot block updates or resume under the old policy’s KV state.Adds
inference.fp8_ue8m0_weight_scalesandinference.fp8_stochastic_weight_rounding, wired through worker env vars to vLLM patches that force power-of-two block scales and unbiased stochastic e4m3 rounding on onlineper_block_cast_to_fp8, so BF16 trainer weights round-trip dequantized checkpoints and track sub-bin updates in expectation. Trainer-side Triton FP8 casts are updated to be bit-identical to vLLM’s CUDA quantizer (RN divide, clamp, scale floor).Additional vLLM backports: DeepSeek V4 request-level tools attach to the first existing system message (matches reference encoding), and Triton MoE SwiGLU clamp is honored on the fused FP8 fast path. Multi-node SLURM templates
set -awhen sourcing.envso vars propagate intosrunchild shells.Reviewed by Cursor Bugbot for commit a3ffa1a. Bugbot is set up for automated code reviews on this repo. Configure here.