Repository navigation
feat(neuron): MiniMax-H3 on the PyTorch-native neuron backend (SDK 2.33) - #154
Closed
shiyang-opensource wants to merge 8 commits into
Closed
shiyang-opensource wants to merge 8 commits into
shiyang-opensource wants to merge 8 commits into
Conversation
…ron backends The TP rewrite (head-sharded attention, split SwiGLU, column-sharded text embedder/norm_out/adaln_proj, the bounded-attention processor and the trace module) only uses difflet.ops, so it moves to difflet/models/minimax_h3/modeling_minimax_h3_tp.py. The Trainium module re-exports every name it had, so its graph is built from the same objects. The fused-SwiGLU key split becomes split_fused_swiglu_keys/ff_prefixes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NeuronMiniMaxH3TransformerApplication builds the shared H3 TP trace module on meta, loads each rank's shards (the fused SwiGLU through CheckpointSlices, the fp32 patch projections / timestep MLP / output heads on real fp32 storage) and compiles the 50 blocks and the refiner blocks per block. precomputed_adaln is on by default, so the 13B adaln_proj branch is never loaded. The masks travel as int32; at tp1 the bounded-attention processor is installed too. L1 tests (CPU, gloo): tp1/tp2/tp4 match diffusers' MiniMaxH3Transformer3DModel (fp32, atol 2e-5) with the host modulation table and with the resident branch, eager and per-block compiled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HostQwen3VLTextEncoder builds only the first 50 Qwen3-VL decoder layers (no layers 50-63, final norm, lm_head or vision tower) and captures hidden_states[50] with the Trainium text stage's tokenization and record. load_host_video_decoder / load_host_audio_decoder build the two VAEs in fp32 with the reference attention and the folded weight norm. On trn3 (fox prompt, vs the AOT stage outputs): text live rows rel_l2 9.9e-4 (bf16), mask and token count equal; video decode PSNR 73.4 dB. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With DIFFLET_BACKEND=neuron the four H3 stages keep their work files: text and both decoders run on the host as one rank, the DiT on --tp-degree torchrun ranks with the AdaLN table built once on rank 0 under <cache-dir>/minimax_h3_neuron/. compile only warms the DiT up. The registry lists neuron for minimax_h3; the stage CLI forwards --model-path to every stage on both backends. The c10 refusal tests now restrict H3's entry to trainium themselves. trn3 device 7, 256x448x124, 30 steps, seed 42: difflet generate end to end 242 s (text 23 s, DiT load+warmup 66 s, denoise 21.1 s = 716 ms/step, video VAE 69 s, audio 2.6 s); same scene as the AOT output (video PSNR 22.5 dB, audio mean -58.5 vs -58.0 dB). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NeuronMiniMaxH3VideoVaeApplication runs the 36-block ViT decoder on one core, one official 256 px tile per call (sequence padded to 128 with key bounds, blocks compiled per block, block norms in fp32). The neuron video_vae stage uses it by default (--vae-dtype fp32, or bf16); --host-vae keeps the host decode. compile now warms up the DiT and the device decoder. trn3 device 7, 256x448x124 (14 tiles): fp32 775 ms/tile, 11-14 s per clip, PSNR vs the host fp32 decode 80 dB (106.9 dB end to end); bf16 130 ms/tile, 2.3 s, 57 dB. difflet generate end to end 242 s -> 144 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Qwen3VLTextEncoderModel (models/, backend-neutral) is Qwen3-VL's language model to hidden_states[50]: the embedding and the first 50 layers with the difflet.ops TP layers (GQA q/k/v without bias, per-head q/k RMSNorm, head_dim 128, the text case of the interleaved mrope = 1-D RoPE, theta 5e6), causal and unmasked on a right-padded prompt. NeuronMiniMaxH3TextEncoderApp loads model.language_model.* (11.7 GiB/rank at tp4), skips the vision tower, lm_head, the final norm and layers 50-63, and encodes with the Trainium stage's tokenization and text.pt record. L1 (CPU, gloo): tp1/tp2/tp4 eager and tp2 compile match transformers' Qwen3VLForConditionalGeneration hidden_states[3] (fp32, 2e-5) on a tiny model. trn3: hidden_states[50] vs the AOT/NxDI encode rel_l2 9.8e-4, mask equal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…launch On the neuron backend the generate stage now encodes the prompt on the device (released before the DiT loads), denoises, and decodes the video with a decoder on every rank, the 256 px tiles spread over the ranks (decode_video_on_ranks: record the tile order, decode i % world, replay the official blending on rank 0; equal to the one-process decode). The separate device video_vae stage is gone; --host-text-encoder / --host-vae bring back the host text and video_vae stages. compile warms up all three components. trn3 device 7, 256x448x124, 30 steps: difflet generate 144 s -> 109 s (text 8.9 s, DiT 21.1 s, video decode 14.2 s -> 6.6 s); compile 70 s warm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reduce-dtype coverage test exempted MiniMax-H3 by its Trainium path; the TP rewrite now lives in models/minimax_h3/modeling_minimax_h3_tp.py and keeps the same default on purpose (the Trainium graph is pinned bit-identical). Co-Authored-By: Claude Opus 5.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
MiniMax-H3 (T2VA, 33B DiT + Qwen3-VL conditioner + video/audio VAEs) on the PyTorch-native
neuronbackend (TorchNeuron, torch-neuronx 2.14 / SDK 2.33). The AOTtrainiumbackend cannot move to SDK 2.33: neuronx-cc 2.28 removedneuronxcc.nki, which NxD 0.19 / NxDI 0.10 import. With this PR H3 runs on the current SDK without NxD/NxDI.With
DIFFLET_BACKEND=neuron(or--backend neuron),difflet generateruns H3 in one torchrun launch of--tp-degreeranks:hidden_states[50], TP-sharded (NeuronMiniMaxH3TextEncoderApplication; first 50 layers only, 11.7 GiB/rank at TP4). Released before the DiT loads.NeuronMiniMaxH3TransformerApplication, per-block compiled. The AdaLN modulation is precomputed on the host, so the 13Badaln_projbranch is never loaded (9.4 GiB/rank).NeuronMiniMaxH3VideoVaeApplication, fp32 by default). The official 256 px tiles are spread over the ranks (decode_video_on_ranks).The audio VAE and the AV mux stay on the host (
audio_vaestage).--host-text-encoderand--host-vaebring back the hosttextandvideo_vaestages.Commits
refactor(minimax-h3): the DiT TP rewrite moves tomodels/minimax_h3/modeling_minimax_h3_tp.py. The Trainium module re-exports every name, so its graph is built from the same objects. This is the only change to the Trainium path, plus--model-pathnow being forwarded to every stage on both backends.feat(neuron): the H3 DiT as a TorchNeuron application.CheckpointSlice.feat: host CPU text encoder and decoders (host_components.py), used by the--host-*paths.feat(neuron): the staged CLI on the torchrun backend.neuronforminimax_h3.neuronany more.feat(neuron): the video VAE on a NeuronCore.feat(neuron): the Qwen3-VL conditioner on the device.feat(neuron): text, DiT and video decode in one generate launch.Evidence (trn3.48xlarge, device 7 = cores 28-31, TP4, 256x448x124, 30 steps, seed 42)
trainium(SDK 2.26 stack)neuron(this PR)difflet generateend to endTrainium path unchanged: after the TP-module move, the AOT DiT was recompiled from scratch (fresh NEFF cache, 438 s) and generated from the same
text.pt. The video and audio latents are bit-identical to the pre-refactor run (max_abs0.0).Numerics vs references:
MiniMaxH3Transformer3DModel(fp32, atol 2e-5), with the host AdaLN table and with the resident branch.Qwen3VLForConditionalGeneration(fp32, 2e-5). On trn3, vs the AOT/NxDI encode: rel_l2 9.8e-4 (bf16); mask and token count equal.--vae-dtype bf16) is 57 dB and 5x faster.Not done here:
NCC_ITIN902); bf16 runs but gives 13 dB SNR and no speed-up over the host's 2.9 s.difflet generatehas no--model-pathyet; this would be a sharedcli/main.pychange.Test plan
tests/unit/backends/test_neuron_minimax_h3_{l1,text_encoder,vae}.py(CPU/gloo, run on the trn3 host; the Mac torch 2.11 lacksall_gather_single)tests/unit/cli/test_orchestrator_minimax_h3.py,tests/unit/backends/test_neuron_launch_c10.py(109 passed), registry teststests/unit/models/minimax_h3in the Trainium lock venv (32 passed, including the re-export identity test)difflet compile+difflet generate(neuron), AOT recompile bit-identity (trainium)🤖 Generated with Claude Code