Repository navigation
dsv41 metal: launches of 6 to 16 rows run their FP8 projections on a matrix tile (stacked on #1720) - #2973
dsv41 metal: launches of 6 to 16 rows run their FP8 projections on a matrix tile (stacked on #1720)#2973gilby wants to merge 19 commits into
Conversation
…over Metal target.zig is the lanes' verify target: a slot's prompt, its windows of rows for several slots in one launch, keeps and rewinds, and kept prompt states (the prompt cache) whose resumed rows the reply reports as cached_tokens. boot.zig loads a release checkpoint folder and entry.zig serves it as tensorfold-dsv41 (dsv41-metal-serve). Tests serve the tiny model through LaneHost: concurrent equals solo equals serial, drafted equals draft:false, cache hits equal fresh runs, seeds and cancels.
…for the next A shared round with the plain switch at it asked no drafts and ran no head pass (core Rule.plain_streams, threaded from the family's resolved setting: 0 on CUDA, so its rounds are unchanged), and the family's speculation no longer launches a pass for a round that wide (armSpec/speculate plainRound).
…teps and the forward try's
…stays within 600 lines
…nything else by name
…treams streams decode
…er holds a rejected draft's taps
…nd the next ask catches the drafter up
…ers per row and dispatch class Six synthetic layers of the release's widths (one of each attention kind, few experts) are timed at 1-16 rows of one slot and at 4 slots x 1 row, each dispatch alone and the layer on the serving encoder, and split into FP8 rows, experts, attention and glue, with a 40-layer round weighted by kind. timing_real's report takes a launch (context and spans) so both harnesses share it.
…x tile, bit-equal to the row kernel Launches of 6 to 16 rows run the dense FP8 projections on fp8_tile.metal: 8 or 16 columns a threadgroup, K split over up to 16 simdgroups in aligned power-of-two runs of groups, each 32-wide group summed from zero in four 8-wide MMA steps in k order (the prompt tile's group root), the groups' roots and the slices' roots in the same zero-padded pair tree the row kernel uses. Every row's bits are the row kernel's one row a launch; 1-5 rows keep the row kernel (chosen by row count only), since below 6 rows it reads the weights faster. Contract: six registrations (f32, bf16, a forced 16-column form, one simdgroup, the row kernel one row a launch as replaced baseline, the release wkv fixture), four planted controls, gate-5 records with M1/M2 limits, and an equality probe over every model FP8 shape at 1-16 rows, every form, the 16/17 seam and a batch with NaN and Inf planted. Device tests: the layer's kernel by row count, and four slots of two rows each in one launch against each alone.
823af13 to
2402e6e
Compare
|
First real-weights receipt, with the contract on the M5 Ultra. One M5 Ultra 512 GB, Contract on the M5 Ultra at Greedy, aggregate tok/s, this over the stack tip:
|
|
Thanks @gilby. The exactness argument holds up in the code. In Asks:
|
|
M3 Ultra, 512 GB: the series is being re-measured now under the noise rule in #2984 (one discarded first run, base on both sides, both-under-both test); it follows in this thread.
Summary: token hashes equal to base in every cell of every table. Decode, mean over mean against base, 1 to 4 streams, T 1 and 0, chat and code: 1 stream 1.001 to 1.009, 2 streams 1.037 to 1.055, 3 streams 0.998 to 1.000, 4 streams 0.998 to 1.000. Cells under 0.98 of base: none. Kernel contract M5 Ultra, 512 GB (applegpu_g17, tensor units true), M5 Ultra full run ( M3 Ultra, 512 GB (applegpu_g15, tensor units false; macOS 26.6.2 (25G83), Metal compiler 373.7), final contract run, both runs verbatim. M3 Ultra full run ( For comparison, the base tree on the M3 Ultra (the tree at and its The full run needs a rotary sweep receipt passed with Device tests ( M5 Ultra: build exit status 0, 1137 PASS lines, no line starting with FAIL; the log ends with The base tree was not put through the device tests on either chip. Decode, Order as run: base 1, this 1, [the other head twice], this 2, base 2. Ratios: this 1 over base 1, this 2 over base 2, and mean over mean. Token hashes equal in every cell across the four arms: yes; failed / alone / serial mismatches: 0. All 16 cells are reported.
Token hashes equal to base in all four cells across the four arms: yes. The run summary flags the two T 1 cells as unstable between the repeats inside one server, base included; their token hashes are still equal across all four arms.
Cold prompts ( TTFT ratio below 1.000 is faster than base. Each cell is a single run and base ran before the heads (base at all four sizes, then the head of #2973, then the head of #2983), so these cells do not separate the change from drift.
Synthetic row timing, M5 Ultra ( Identical rows, 16 experts:
Different rows, 32 experts:
Method as run: each cell is a fresh server started just before it; a thermal-pressure check ( Not run: the full kernel contract on the M5 Ultra (it aborts, see above); the Raw JSON, server logs and driver scripts: https://gist.github.com/gilby/df7bed9a89d9c854cfe78479b4c8cb6f |
|
Thanks @gilby, this is a thorough write-up, and it answers part of ask 1.
Still open:
No hurry on any of it. Post the M3 numbers here when they're in.
|
|
M5 Ultra, 512 GB: the full kernel-contract SUMMARY that was missing above. The full run stops at registration on chips with tensor units since #2251 (#3067); with the one-line fix proposed there applied to this tree's copy, it completes on this head ( The base tree And The 57 known findings are the same 57 lines on the base tree and on this head, and none is a DeepSeek-V4.1 record: 41 are the #1009 masked-value entries of other families' attention kernels that this chip registers (Gemma 4, Spark2.5, MiniMax M3, Llama, GLM, the step kernels), and the rest are those families' prompt-attention entries, the Full logs for the four trees and the applied one-line diff: https://gist.github.com/gilby/fb5f4ae45e3089e7f742c17753623740 |
|
M3 Ultra, 512 GB: the receipt promised above, run on 2026-11-13 under the noise rule in #2984 (one discarded first run per series, base on both sides, both-under-both test).
Summary: this head gains at 2 streams and in one Cells under 0.98 of base: none.
Order as run: base 1, this 1, this 2, base 2. Ratios: this 1 over base 1, this 2 over base 2, and mean over mean. Verdict by the #2984 rule: slower only if both this runs are under both base runs and the mean gap is over 1%, faster the mirror image, otherwise within noise. Verdicts as the rule gives them: 6 faster (5 of them real gains per the paragraph above, one the Heavy-affected cell), 0 slower, 14 within noise, out of 20 cells.
End level key: Nom = Nominal, Mod = Moderate, Heavy = Heavy, Exactness: token hashes are equal across all four runs in every one of the 20 cells (all reps of each cell compared), with 0 failed requests and 0 Discarded, retried and flagged cells
Method as run: each cell is a fresh server started after the previous one was stopped and a 60 s settle, and a cell starts only when the powermetrics thermal sampler reports Nominal (the driver polls every 30 s); the level is recorded again at the end of the cell. One run per series is discarded and not in any table, base is on both sides, and the series are per stream count and temperature ( Not run: the checkpoint's pinned revision, the macOS version and the toolchain versions are not recorded; kernel-contract runs are not part of this series' data. Raw JSON, server logs and driver scripts: https://gist.github.com/gilby/c020133ac9809d5f01d5b34dd60fc308 |
…, not synthetic layer times
|
New head:
Receipts: both new commits are documentation and the CHANGELOG, so the M5 Ultra and M3 Ultra receipts and both chips' contract lines above (taken at Your ask 1 from 12 Nov 13:18 and 23:50, item by item:
Ask 4 (the rebase in the #2984 order, with the At |
|
M3 Ultra, 512 GB: the contract lines and the
Kernel contract,
The same with 32 experts and different rows (
The Raw outputs and drivers: https://gist.github.com/gilby/f956f91d5bc63f30b6ccb4ba549e061a |
What this changes
On Metal, DeepSeek-V4.1's FP8 projections ran every decode row through the row kernel, so a launch of 6 to 16 rows (a drafted verify window, or several drafted streams) paid per-row scalar work on every projection. With this change launches of 6 to 16 rows run the FP8 projections on a simdgroup matrix tile (
fp8_tile.metal), chosen by row count only; 1 to 5 rows keep the row kernel, where it is faster. A row's result is bit-identical to the row kernel's at every shape and row count, so rows at once equal one at a time and tokens are unchanged.c97d661c4); this adds two commits: a synthetic timing step at the release's widths (time-dsv41-metal-synth, no checkpoint needed), and the tile with its contract records. Two commits since review:f2241b84a(the kernel contract's entry for the tile) andff8365687(the CHANGELOG line quotes the served result on both chips).atc overlap --json: not run yet.Why it is exact: each 32-wide group root is computed as the prompt tile does it, four 8-wide steps in k order from +0; each simdgroup takes an aligned power-of-two run of groups, so its root is a subtree of the row kernel's pair tree, and the slice roots meet in that same tree. Zero padding adds x + 0 exactly, since no partial sum is ever -0. An output row depends only on its own input row. The form (8 or 16 columns, the number of simdgroups) cannot change bits, by the same argument.
What it does not do: plain rounds of 1 to 4 streams are unchanged. The per-row split measured for this change shows the experts' multi-row kernels, not FP8, dominate at 2 to 5 rows; that is a separate change.
Checks on this head
ff8365687python3 tools/zig/lean_check.py, on the base and on this head: 345 and 345, 0 new (tools/pr_check.py0 errors, 0 warnings).2402e6eb4zig build test-dsv41-metal-allpassed on the M5 Max (layer 31/31, served 8/8) and on the M3 Ultra (9/9 steps, 39/39 tests).zig build time-dsv41-metal-synth(six synthetic layers at release widths, a 40-layer round weighted by layer kind, ms): 1 row 30.3 before and after, 4 rows 45.0 and 45.0, 6 rows 68.2 to 64.9, 8 rows 78.0 to 68.0, 16 rows 148.2 to 110.1, four slots of one row 45.6 and 45.6.CHANGELOG.md), and per the order in DeepSeek-V4.1 on Metal: decode and prompt speed on M3 Ultra and M5 Ultra, token-exact (gate and order for the drafts) #2984 it is rebased onto the PR before it at landing.dsv41_fp8_tile equalityline andtime-dsv41-metal-synththere (with them, whether 6 rows stays the crossover); run list in the comment.Receipt
2402e6eb4; the two new commits are documentation.2402e6eb4on dsv41 metal: the lane target, the prompt cache and the native server over Metal #1720'sc97d661c4;deepseek-ai/DeepSeek-V4.1-Flash-1017release weights at revision1bae0e1088993b9b82de08f59de5be5a34e42170; M5 Ultra 512 GB and M3 Ultra 512 GB; Zig 0.17.0.token_sha256equal to the stack tip in every cell on both chips, 0 failed, 0--alone/--serialmismatches; the contract holds the tile bit-equal to the row kernel one row a launch.bench_openai1.001 to 1.036 (M5 Ultra), and on the M3 Ultrafibonacci-rawsampled 1.031, the rest level.Kernel contract
wkvfixture, and one declared as replacing the row kernel run one row a launch, bit-equal on all 33 shapes at gate 3). An equality probe of 4,500 launches covers every model FP8 shape in f32 and bf16, rows 1 to 16, every form, the 16/17 seam and a three-launch batch, with NaN and Inf planted in activations, codes and scales: every launch byte-equal to the row kernel one row at a time.TF_CTL 0the source is what ships.SUMMARYline and exit status, M5 Max: baseSUMMARY 89 kernels: 89 pass gates 1-4, 0 fail, 0 known findings; 186 controls: 186 red as planted, 0 missed; 0 limit problems; this headSUMMARY 95 kernels: 95 pass gates 1-4, 0 fail, 0 known findings; 190 controls: 190 red as planted, 0 missed; 0 limit problems. M5 Ultra at2402e6eb4, exit 0:--only dsv41SUMMARY 95 kernels: 95 pass gates 1-4, 0 fail, 0 known findings; 190 controls: 190 red as planted, 0 missed; 0 limit problems; full run (with the one-line fix from Kernel contract on tensor-unit Macs: the full run aborts with ControlEditMissing in the llama gemm_untransposed control since #2251 #3067) 756 pass, the same 57 known findings as base. M3 Ultra at2402e6eb4, exit 0:--only dsv4195 of 95 pass, 190 of 190 controls red; full run 545 pass, the same three knownnonfinitefindings as base. The new commits are documentation.dsv41_fp8_tile equalityprobe line from its contract run.Checklist
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo (synthetic weights, and on the release weights in the receipts).--drafter, no slower than without it, greedy and sampled