Add MXFP8 fused-MLP overrides in torchtitan - #4257
Open
wolfcomos wants to merge 8 commits into
Open
Conversation
…ories) overrides/mxfp8_fused_swiglu.py hosts two composite autograd functions that run the whole SwiGLU MLP in MXFP8 (RCEIL e8m0 scales, block 32): dense x -> w13 GEMM -> SwiGLU -> w2 GEMM and the grouped-experts equivalent, with the activation boundary quantized either by the unified SwiGLU+MXFP8 CuTeDSL kernel (fuse_activation=True) or by standalone BF16 + cast kernels (the two modes are bitwise-identical in forward). Two @OverRide factories wire them in: mxfp8_fused_swiglu builds MXFP8FusedSwiGLU (dense FeedForward) and mxfp8_fused_grouped_experts builds MXFP8FusedGroupedExperts, swapping the token dispatcher for the padded variant (pad_multiple=128) the kernels require. Both inherit the fused-w13 parameter, stock-layout checkpoints, and sharding remaps from the existing fused_swiglu module classes. There is no silent fallback: unavailable kernels, DTensor operands, non-BF16 dtypes, or shapes violating the kernels' 128-alignment contract raise actionable errors (routing-dependent token counts remain torch._check deferred asserts under compile); the factories fail loud on non-stock configs so they cannot silently compose with the MXFP8 quantization converters. No changes to overrides/fused_swiglu.py or components/quantization. One example debugmodel flavor per model family (llama3 dense, deepseek_v3 grouped with expert_parallel_degree=2 for the padded EP dispatch). Tests: one CPU-runnable wiring suite (config-tree transforms, padded-dispatcher swap, factory fail-loud rejections, meta-device builds; the SM100 gate is patched out since hardware is irrelevant to the transforms). GPU numerics (fused-vs-unfused bitwise forward parity, reference tracking, compile with unbacked token counts, padding inertness) are validated on GB200 in NVIDIA-internal CI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
wolfcomos
requested review from
fegin,
tianyu-l,
wconstab and
wwwjn
as code owners
August 20, 2026 22:02
Rename the grouped override class MXFP8FusedGroupedExperts -> MXFP8FusedGroupedMLP and the module mxfp8_fused_swiglu.py -> mxfp8_fused_mlp.py (it hosts both the dense SwiGLU and grouped MLP composites). forward keeps the plumbing -- DTensor localization, BF16 casts, expert-offset construction, output-dtype restoration -- and delegates the complete numerical grouped MLP to the new protected _run_grouped_mlp hook, the one seam a future fully fused grouped GEMM + SwiGLU + dual MXFP8 quantization backend overrides. No behavior change: the hook passes the composite exactly the operands forward always built; the dense path, the w13 (E, F, 2, D) layout, the pad_multiple=128 dispatcher contract, and the checkpoint/init/sharding hooks are untouched. Public factory names are unchanged; only the module path in override import strings moves. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Revert mxfp8_fused_mlp.py -> mxfp8_fused_swiglu.py and MXFP8FusedGroupedMLP -> MXFP8FusedGroupedExperts (smallest diff against the original PR; override import strings and configs are byte-identical again), and describe _run_grouped_mlp accurately as the numerical/autograd backend seam: future implementations may also require backend-specific parameter layout, checkpoint hooks, dispatcher padding, and factory validation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Drop the class-docstring paragraph (the hook docstring already states the seam) and the two multi-line test comments the test names cover. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collapse the grouped path to factory -> module -> autograd Function: MXFP8FusedGroupedExperts.forward now runs _validate_grouped_inputs and _MXFP8SwiGLUGroupedMLP.apply directly, and the _run_grouped_mlp hook and the standalone mxfp8_swiglu_grouped_mlp_w13 wrapper (no external callers) are removed. A future fused backend branches on its mode inside forward. Dense path unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MXFP8FusedGroupedExperts.forward is the only caller of _validate_grouped_inputs and already guarantees plain local BF16 tensors in the module's own shapes, so the DTensor, device/ndim, dtype, and shape-consistency checks are unreachable; what remains is the environment gate, the config-dim 128-multiple gate, and the routing-dependent token-count conditions. Error messages now name MXFP8FusedGroupedExperts instead of the removed functional wrapper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
wolfcomos
added a commit
to wolfcomos/torchtitan
that referenced
this pull request
Aug 24, 2026
Rework the mxfp8_grouped_experts override to the self-contained pattern of pytorch#4257: it now targets the STOCK RoutedExperts.Config (stock GroupedExperts inner) and owns the whole routed-expert contract itself instead of piggybacking on the MXFP8 grouped-experts converter. - The factory installs the pad_multiple=256 dispatcher itself: a TorchAOTokenDispatcher.Config is retargeted in place, the stock all-to-all is swapped via swap_token_dispatcher, and anything else raises (the 256-row cuDNN FE contract is only validated for the TorchAO padded dispatcher). - No silent fallback: every gate that used to decline-and-warn now raises an actionable ValueError at config-application time (missing torchao ops, non-SM100 hardware, converter-quantized or subclassed experts, dims off the 128-alignment contract). exact=True is dropped; the subclass raise happens inside the factory. - deepseek_v3_{debugmodel,16b}_mxfp8_grouped_mlp are rebuilt standalone: dense MXFP8LinearConverter only, no grouped-experts converter; the override supplies the fused composite and the padded dispatcher. The _p256 baseline arms are untouched. - Fix a latent DTensor crash in _make_w13_init at EP>1 fresh init: each half is now initialized in place through a strided 32-block sub-view of w13 (the save hook's view), keeping shard-distinct, globally consistent draws through the DTensor RNG tracker. Plain-tensor temporaries would draw identical values on every rank (torchtitan seeds all non-PP ranks the same), silently duplicating experts across EP/FSDP shards; every in-tree w1_EFD/w3_EFD initializer is a fixed-std trunc_normal_, so the blocked sub-view geometry is safe. - Tests: decline tests become raise tests; new coverage for the subclass raise, unsupported dims, the hybridep dispatcher refusal, ops-unavailable, and 16B A/B arm knob/dispatcher parity. 18/18 unit tests green on 1xGB200; flake8 clean; 5-step EP=2 fresh-init smoke converges with the override applied on all layers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
wolfcomos
force-pushed
the
swiglu-mxfp8-upstream
branch
from
August 24, 2026 08:37
89fcb0f to
04d8f32
Compare
MXFP8FusedGroupedMLP now subclasses stock GroupedExperts directly: the FusedGroupedExperts inheritance is replaced by self-owned w13 registration, stock-layout checkpoint hooks, and param-init/sharding remap helpers, so future MXFP8 fusion paths extend this module without that dependency (none are wired here). Everything renames under the "MXFP8 fused MLP" umbrella (module, classes, factories, debugmodel flavors); the dense class keeps its small FusedSwiGLU base. Bitwise-verified on both paths (5-step deterministic NGPU=2 runs, losses and grad norms identical to the previous revision). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both override classes now keep the stock parameters (w1/w2/w3 dense, w1_EFD/w2_EDF/w3_EFD grouped) and stack the gate/up weights into the composite's w13 operand at forward time, byte-identical to the old merge-hook mapping; the module no longer depends on fused_swiglu. Ckpt-paired 2-GPU runs match the fused-param arm bitwise at print precision (grouped exactly; dense exactly once grad clipping is inert), and fresh-init state dicts match the stock modules bitwise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
Adds an opt-in override module,
torchtitan/overrides/mxfp8_fused_mlp.py, that runs a FeedForward / routed-experts MLP entirely in MXFP8 with a fused SwiGLU boundary: one composite autograd function computesw13 GEMM -> fused SwiGLU + dual MXFP8 quantization -> w2 GEMM(dense and grouped variants), using torchao's fused gated-activation kernel (pytorch/ao#4743) for the activation boundary and torchao's MXFP8 grouped/scaled-mm internals for the GEMMs. Compared to the unfused MXFP8 path, the fused boundary eliminates the standalone activation-quantization casts (1 fwd + 1 bwd fused op instead of 6 + 6 standalone cast kernels per MLP) and never materializes the BF16 post-activation tensor.The integration:
MXFP8FusedMLPandMXFP8FusedGroupedMLPsubclass the stockFeedForward/GroupedExpertsand keep stock parameters (w1/w2/w3); the two projection weights are packed into the kernel's fused layout at forward time. No parameter surgery, no state-dict hooks, no init/sharding remaps — checkpoints and fresh initialization are bitwise-identical to stock modules (asserted by a shipped test).@overridefactories:mxfp8_fused_mlp(targetsFeedForward.Config) andmxfp8_fused_grouped_mlp(targetsRoutedExperts.Config, which owns both the token dispatcher and the inner experts — the factory swaps the dispatcher to the padded variant its kernels require,pad_multiple=128).overrides/fused_swiglu.py,components/quantization/mx.py, and the quantization converters are untouched, and this module imports nothing from the BF16 fused-swiglu override. Enabling the override is the only opt-in; additional MXFP8 fusion paths (e.g. fully fused grouped MLPs) extend this module with their own composite and factory.Usage
Example flavors:
llama3_debugmodel_mxfp8_fused_mlp,deepseek_v3_debugmodel_mxfp8_fused_mlp(attention/lm_head stay BF16 — composable withMXFP8LinearConverteron those modules independently).Numerics and tests
tests/unit_tests/test_mxfp8_fused_mlp.py— 8 CPU-runnable tests (config-tree transform,apply_overrides, meta-device build, dispatcherpad_multiple, factory fail-loud, checkpoint keys == stock, and a seeded fresh-init state-dict bitwise comparison against the stock modules), validated with GPUs visible, withCUDA_VISIBLE_DEVICES="", and on stock PyPI torchao without a GPU (all 8 execute).torch.compilewith unbacked routing-dependent token counts, dispatcher pad-row/tail inertness, and profiler op-count contracts.🤖 Generated with Claude Code