[perf] Speed up exact MiniMax H3 MLX inference - #1792
Merged
SolitaryThinker merged 2 commits intoAug 31, 2026
Conversation
Read each BF16 tensor in one bounded file operation and expand it to FP32 in MLX before constructing the decoder-layer graph. Keep embedding lookups row-scoped and retain one resident language-model layer. On the 36 GiB M4 Max, complete layer-50 conditioning falls from about 79-82 seconds to 15-16 seconds. Reversed-order trials and same-runtime comparisons preserve the exact hidden features on MLX 0.31.2 and 0.32.2. This is an uncached conditioner gain, not a full-generation claim. Cover all BF16 storage patterns, source ownership, FP16/FP32 fallback, row bounds, short reads and invalid offsets. The 23 focused cases and configured pre-commit checks pass on the tested runtimes.
Apply the gathered AdaLN scale and shift through one reusable shapeless MLX graph. Keep the normalization, table values, row indices and output dtypes unchanged. Eight-pair real-block tests reduced latency by 2.56% on MLX 0.31.2 and 1.52% on MLX 0.32.2. Order-reversed four-step trials preserved every video and audio velocity and both final latents bit-for-bit. The compiled runs were 6.7% to 11.3% faster, although active paging makes the isolated block measurement the more stable performance result. An independent seed-2027 eager replay also preserved the final video and audio latents. Cover FP32, BF16 and FP16 hidden/table combinations and strided inputs. Focused tests pass on both runtime versions, the tiny H3 parity suite passes, and configured pre-commit checks pass.
Contributor
Merge Protections🔴 1 of 1 protections blocking · waiting on 👀 reviews and 🤖 CI
🔴 PR merge requirementsWaiting for
This rule is failing.
|
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.
Purpose
Uncached MiniMax H3 generation on Apple Silicon spends 79–82 seconds streaming and expanding the 66 GB BF16 conditioner before denoising. The H3 transformer also repeats row-expanded AdaLN scale and shift operations in every block.
This PR reduces both costs without changing the checkpoint, quantization, sampling schedule, spatial or temporal workload, conditioning values, or decoder path.
Changes
mx.compilegraph.The module documentation and comments record the streaming memory contract and explain why the BF16 cast is synchronized before layer evaluation. No user-facing option or cache format changes.
Measured results
Environment: Apple M4 Max with 36 GB unified memory, macOS 27.0 build 26A5416b. Tests used the affine INT6 group-64 H3 checkpoint at 832×480, 124 frames, four denoising steps, and no spatial or temporal fast mode.
Conditioner phase
The same 70-token speech prompt and layer-50 output were compared within each MLX runtime.
The conditioner MLX active-memory peak increases from about 1.88 GiB to 2.06 GiB. It remains well below the approximately 19.6 GiB denoise peak and does not load a full shard, embedding table, or conditioner model.
AdaLN modulation
Each real-block result is the median of eight alternating baseline/candidate pairs at packed sequence length 14,937.
Two order-reversed four-step comparisons also favored the compiled path: 393.597 versus 443.541 seconds and 366.016 versus 392.436 seconds. Those runs paged heavily, so the 6.7–11.3% full-denoise range is directional evidence; the isolated real-block medians are the stable performance claim.
A complete uncached seed-2027 generation took 524.062 seconds: 17.163 conditioning, 396.085 denoise, 109.730 video decode, 0.696 audio decode, and 0.389 mux. It produced a 5.17-second 832×480 H.264 clip with stereo AAC audio. An eager replay produced bit-identical final video and audio latents.
Test Plan
Manual full-workload validation used seeds 2026 and 2027 with 832×480, 124 frames, four steps, and the unchanged audio/video decoders.
Test Results
Review notes
The conditioner gain applies to uncached prompts. Cached prompts bypass that phase. The compiled AdaLN graph is lazy and process-local, and it preserves the original multiply-then-add expression and output dtype.
The branch is based on
620bc36dcand includes only these two performance commits. PR #1788's wide-matrix affine INT6 dispatch and PR #1789's optional spatial fast mode are already present inmainand are not duplicated here.Checklist
pre-commit run --all-filesand fixed all issuesFor model/pipeline changes: