Repository navigation
Conversation
This was referenced Oct 27, 2026
akol1
marked this pull request as ready for review
October 27, 2026 04:32
Owner
|
The Two places change the arithmetic, so the pair can't match the single Mac yet:
Stage 1 compares |
Step 1 of 6 of the two-Mac 27B series; stacked on main alone, and steps 2-6 stack on this commit. The seam exchanges whole output rows instead of K halves: rank r owns 2,560 of the 5,120 output columns (8,704 of 17,408 for the down projection), reduces over the full K on its own rank, and `pair_gather` copies whole rows in bf16 without doing any arithmetic, so no exchange rounds or sums a partial product across ranks. `pair_add_rms` keeps the rank's own part of a seam input in the fp32 stream, and a broken link surfaces as bf16 NaN `0x7FC0`. That transport is a new module, `pair_rows.zig` and `pair_rows.metal`, over `pair_rows_layout.zig`'s slots and the relay protocol unchanged. `pair.metal` and `pair.zig` stay for GLM-5.3-Flash, whose transport this series does not touch: a shipped path cannot change without an A/B against main. `simd_qmm` gains a K-chunk width: `chunks(n, whole)` lets a rank that owns output rows sum with the unsplit width's reduction tree. An unsplit caller passes 0, and `chunks(n, 0)` is `splits(n)` exactly, so its chunking and its bytes are unchanged; the tools' fp32 reference path takes the same width, and step 2 passes the split width from the paired caller. Gate 5 registers the seam's five kernels in the kernel contract, and `docs/kernel-contract.md` lists them with their NaN and tie rules.
akol1
force-pushed
the
qwen27/rank-slice
branch
2 times, most recently
from
October 27, 2026 22:37
65f2228 to
5fcfe81
Compare
Step 2 of 6, stacked on step 1 (`qwen27/pair-seam`) and main (5897e0b); step 3 stacks on this commit. A rank's layer program now carries one `Reduce` interface instead of assuming the whole matrix. Attention's o_proj and the MLP's down_proj seam stage this rank's output columns, gather the whole frame, and let the producer kernel reduce over full K on its own rank; the head seams the last row's logits and takes the pair's argmax over the whole vocab, so the picked token is the single Mac's token, not rank 0's half-vocab pick. On one Mac `reduce` is null and every seam is compiled out of the program: the single-Mac program, its digests and its tests are the ones that ran before. The rank-local K-split is fixed while the slice is: `projection.prepare` derives a tensor's split from the whole matrix's rows, not the rank's rows, so gate/up keeps sk 2 on its 8,704 rows (4 before this commit) and q keeps sk 4 on its 6,144 (8 before), and the row view points at the global split instead of re-deriving one. The embedding table stays whole on every rank — only the head is sliced — with `embedBound` reading the table's bound rather than the family's `vocab_size`; the config gains its shard parse and `config_test.zig` covers it. The session keeps the pair's pick as the round's token and surfaces `error.PairFailed` from the head seam's sentinel rather than returning `maxInt(u32)`, and the seam's `Reduce` is threaded through `forward.encodeTp`/`session`. The prompt attention kernel's signature follows the seam's reopened encoder.
akol1
force-pushed
the
qwen27/rank-slice
branch
from
October 27, 2026 22:38
5fcfe81 to
7d57101
Compare
Contributor
Author
|
Refreshed head
|
Owner
|
Thanks @akol1. Carrying the checkpoint matrix's width (
This also needs #1432's rebase. |
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.
What this changes
Step 2 of 6, stacked on step 1 (
qwen27/pair-seam) andmain(5897e0bc). Step 3 stacks on this commit.The 27B family becomes rank-aware behind one interface:
forward.Reduce(zig/src/families/qwen27/forward.zig:23) carriesrowsIn,rowsOut,pick,brokenandnext. It defaults tonull, so a one-Mac model compiles the seam out and executes the code it executed before this series.projection.preparederives a rank's row slice from the checkpoint matrix (gn), so the slice keeps the checkpoint's K split, tile and prompt tables (zig/src/families/qwen27/projection.zig); prompt rows takepromptSplitof the whole matrix, so the pair's prompt reduction is the reduction tree one Mac uses rather than a half-width tree.The split is by output rows with the full K on the rank that owns them: 12 of 24 attention heads, 2 of 4 KV heads, half of the linear attention's heads and value channels, 8,704 of the MLP's 17,408 rows, and 124,160 of the 248,320-row lm_head.
o_projanddown_projstage their own output rows, gather the peer's as whole bf16 rows, and add in the fp32 stream, so no two bf16 partials are summed. Embeddings and norms stay whole on every rank, so a token id means the same thing on both, and the embedding kernel's gather bound stays the whole 248,320-row table rather than a shard's width (config.embedBound). The head seam isargmaxover each rank's 124,160-logit half andpickover the pair, so the decided token is one Mac's argmax over all 248,320 logits;session.zigkeeps the merged top two for its cross-block tie test, and reads the pick'smaxInt(u32)sentinel aserror.PairFailedrather than as a logit.The prompt attention merge writes the rank's KV node rows (
kv_headsinQ27PromptArgs) instead of assuming the model's four.config_testpins the spans (intermediate 8,704, down columns 8,704, vocab 124,160, output rows 2,560) and the single-Mac spans stay 0;synthetic_graphruns the same graph on both ranks.Receipt
5897e0bcplus steps 1-2 (0b79f9c9,7d57101a); no MLX or PyTorch; macOS 27.0.1 on an Apple M4 Pro (Mac16,11), Metal only (applegpu_g16, no tensor units), Apple metal version 32023.921. No checkpoint: this commit's gates build the graph from a synthetic config, they do not read weights.tools/bench_concurrent.py --alone --serialortoken_shaagainst"draft": false: n/a, no serving path at this commit; step 4 records the token fixtures. The kernel change here is checked at the series head withtf-kernel-contract --rotary-accuracy <rotary.json> --only pair:SUMMARY 16 kernels: 16 pass gates 1-4, 0 fail, 0 known findings; 30 controls: 30 red as planted, 0 missed; 0 limit problems. The split itself is pinned byconfig_testand byprojection.zig's tests: a rank's slice keeps the checking matrix's K split, a fused gate-up keeps the member split rather than recomputing it from the stacked width, and a local qkv block keys neitherm5SplitnorpromptSplit, so the fallback would stand against an unsplit table.tools/bench_openai.py: n/a, nothing serves yet; step 4 measures the pair and its one-Mac reference.zig build test: 557/557 steps, exit 0.zig build test-kernel-contract: 18/18 steps, 120/120 tests.zig build dev-tools: 213/213 steps.zig fmt --check build.zig zig: clean. Lean rule: 428 problems on both5897e0bcand this tree, 0 new (tools/zig/lean_new.py, exit 0). The series head's fresh-cache suite, which includes these test steps: 565/565 steps, 8,157 passed, 47 skipped, 0 failed of 8,204.tf-qwen27-tp-checkin step 4); a two-Mac run (the serving link arrives in step 3); the full kernel corpus (stops atUNSUPPORTED gemma4 31B rounded dense: tensor units required); CUDA, HIP/RDNA, M1-M3, M5 and Windows are not here.Checklist
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo. — no serving path at this commit; step 3 refuses drafts, and step 4's fixtures are greedy so there is nothing drafted to compare.Reduceisnull.SUMMARYline is in the receipt. —attention_promptkeeps its registration with the newkv_headsargument; the filteredpairSUMMARYabove is the run that exercises it.applegpu_g16); no CUDA, HIP, M1-M3, M5 or Windows.config_test's shard spans and the split tests fail on the parent commit (noshard), and the model-requiring paths skip without a checkpoint as before.