Repository navigation
perf(rec_mlx): optimize M5 Pro prefill (+40.8%), decode kernels, and GPU core scaling - #49
Open
oniisanlabs wants to merge 1 commit into
Open
oniisanlabs wants to merge 1 commit into
oniisanlabs wants to merge 1 commit into
Conversation
oniisanlabs
force-pushed
the
feat/m5-pro-optimizations
branch
from
November 3, 2026 13:49
c95e74d to
14d56d3
Compare
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
Optimizes
rec_mlxprefill and resident decode on Apple M5 Pro (applegpu_g17s) while preserving 100% bit-exact (0 ULP/mx.array_equal) parity across prefill logits, all 50 decode layer traces, all 150,144 output logits, and both greedy (resident8) and filtered (top_p/top_k) sampling:Dynamic M5 Pro Worker Scaling Across 16/18/20-Core GPU Bins (
rec_mlx/kernels/device.py):AGXAccelerator→gpu-core-countvia read-onlyctypesIOKit (<0.05 ms, fallback to18cores) and sizesworkers = head_workers = max(32, min(40, (cores * 2) // 4 * 4))while keepingmlp_workers = 32:40 / 32 / 40): Reachesgroups = 40 // 4 = 10, activating the static lock-free QKV path inkv_teams.pyinstead of the atomic ticket loop (shared_projection), and uses all 40 threadgroups for attention and the 150,144-row LM head.36 / 32 / 36): Matches 36-worker capacity and uses 36 head workers.32 / 32 / 32): Preventssync_alldeadlock on 16-core M5 Pro bins where36threadgroups exceed the16 × 2 = 32co-resident threadgroup limit.Selective Prefill Fastpath for
applegpu_g17s(rec_mlx/m4_max_prefill.py,rec_mlx/kernels/__init__.py):m4_max.FullModel(GlobalCache"causal"SDPA fastpath + compact power-of-two initialKVStorageblock allocation) andPrefillAttention(512-token windowed sliding attention) on M5 Pro, while keepingdequantize_linear=Falseandfuse_switch_glu=Falseonapplegpu_g17swhere MLX's native Metal 4quantized_matmul/gather_qmmis 35–40% faster than BF16 dequantization andflint_prefill_gate_up.L = 4,096(1,841.8 → 2,594.1 tok/s) and 12× lower initial KV allocation (1.65 GiB → 138 MiBfor 4K sessions).Decode Shader & Fast Single-Bank
KVView::address(rec_mlx/kernels/m4_max.py,rec_mlx/kernels/masked_sampling.py):kernels/m4_max.py(dot16_w197_bias23IEEE-754 magic-float unpacking + vectorized 64-bitKVView::load4) andfiltered_sampling.make_sampleron M5 Pro.if(!global || (i < 65536u*128u)) return p0 + offset + i;) and shift/mask (i >> 23,i & (65536u*128u - 1u)) toKVView::addressinkernels/m4_max.py, eliminating integer division/modulo/ternary bank resolution perload4on all sliding-window layers and global layers up to 64K context.Benchmarks (Apple M5 Pro,
applegpu_g17s, 20 GPU Cores, 48 GB Unified Memory)Prefill Throughput (
49Layers, Bit-Exactmx.array_equal)L = 1,024L = 2,048L = 4,096main(Baseline M5 Pro)2,518.6 tok/s2,090.4 tok/s1,841.8 tok/sm4_max_prefill(withPrefillLinear+PrefillSwitchGLU)1,763.8 tok/s(0.70×)1,819.3 tok/s(0.87×)1,802.5 tok/s(0.98×)GlobalCache+PrefillAttention, nativeapplegpu_g17sQMM)2,756.2 tok/s(+9.4%)2,679.3 tok/s(+28.2%)2,594.1 tok/s(+40.8%)0 ULP)Interleaved A/B Decode Throughput (
A -> B -> C -> D/D -> C -> B -> A× 4 reps)resident8,temp=0)temp=1.0, top_p=0.95, top_k=20)CTX = 512main(36/32/32)136.5 tok/s(1.00×)131.9 tok/s(1.00×)40/32/40+m4_max+ fastKVView)139.6–141.4 tok/s(+3.6%)137.2 tok/s(+4.0%)0 ULP)CTX = 8,192main(36/32/32)116.9 tok/s(1.00×)115.1 tok/s(1.00×)40/32/40+m4_max+ fastKVView)123.4 tok/s(+5.6%)116.8 tok/s(+1.5%)0 ULP)CTX = 32,768main(36/32/32)80.2 tok/s(1.00×)76.5 tok/s(1.00×)40/32/40+m4_max+ fastKVView)84.7 tok/s(+5.6%)82.7 tok/s(+8.1%)0 ULP)