Repository navigation
Conversation
The seam carries one round's partials between two Macs: pair.metal writes a frame, the host relay owns the exchange instead of spinning on device counters (which only works while both ranks share a launch group), and pair_sum completes the partial on the far rank. The payload is f32, the seam's accumulation, and simd_qmm grows the matching store. pair.zig splits into pair_layout and pair_loopback so each module stays under the 600-line rule. Nothing registered the seam before: three of the four kernels already ran under the older ABI on the shipped glm_dsa speed-up path, but there was no record and no spec, so no gate covered the kernels this stack changes. Add the four launch records, the seam spec with its four probes, the `metal pair ` route in the limits table, and the fp32-out simd_qmm variant, so the transport and family changes that follow have a SUMMARY to post. The glm_dsa call sites and the two Pipeline.load test call sites are forced by the shared signatures; the family changes themselves come later.
|
Thanks for the pair work: the transport, the watchdog and the contract records for the four new kernels are good. The four kernels pass their gates on an M3 Ultra here. One thing has to change before this stack can land, and it starts in this PR. The pair's tokens must equal the single Mac's. The seam computes each layer's o_proj (or GDN out_proj) and down_proj as two fp32 K-halves, one per rank, then rounds An exact design keeps every sum on one rank. Split o_proj, out_proj and down_proj by output rows, not by K:
No cross-rank partial sum exists then, and no tie policy is needed. It costs about two all-gathers per seam instead of one reduce, with the same weight memory per rank. GLM-5.3's two-Mac path. This rewrites the shipped glm_dsa transport: the device spin-wait becomes a host relay that reopens the encoder at every exchange, and several Checked here: the branch merges cleanly into main, |
What this changes
Adds the seam that carries one decode round's partials between two Macs and registers its four Metal kernels with the kernel contract:
pair_layoutfixes which rows of each weight a rank owns,pair_loopbackstands a peer in on one Mac,pair.metalwrites the frame and completes the partial on the far rank, and a float store variant ofsimd_qmmlets a rank write its exact part. No serving path changes here; the qwen27 wiring follows in the next pull request.Refs #1236 and #808. #1236 tracks a mixed Metal/CUDA group over RDMA; this is two Metal Macs over a socket, it leaves prefill unsplit, and the serving pull request states what it refuses.
atc overlap --jsonagainst8c36359dfinds 172 open pull requests sharing at least one file with this stack; the six it could merge-test are three clean (#1336, #1295, #1429) and three conflicting only inside the two append-only registry tables (#1377, #1391, #1394, lfm2, another contributor), so whoever lands second rebases. The rest readunknownin this partial clone.Receipt
8c36359dplus this commit (137cf631); 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 and its gates move bytes, they do not read weights.tools/bench_concurrent.py --alone --serialortoken_shaagainst"draft": false: n/a, no tokens are served by this commit. The seam's reference is float64, andtf-kernel-contract --only 'metal pair 'passes all four kernels' gates:pair add_rms3 shapes within the bound (worst 0.139 of it) and 3 edges refused, 10248 non-finite and 71672 finite outputs in their float64 classes, five runs byte-identical over 327680 bytes, and the sum stays fp32 at k 6144 where a bf16 sum would miss by 672.2x;pair sum2 shapes (worst 0.000) and 2 edges refused, five runs byte-identical over 81920 bytes;pair argmaxholds its rule (NaN loses every comparison, an all-NaN row reports the-infsentinel with id0xFFFFFFFF), five runs byte-identical over 64 bytes;pair pickcopies one rank's (value, id) word pair and reads an id of0xFFFFFFFFas a broken link, five runs byte-identical over 128 bytes.SUMMARY 4 kernels: 4 pass gates 1-4, 0 fail, 0 known findings; 0 controls: 0 red as planted, 0 missed; 0 limit problems, and the same run's static table reports265 registered Metal launches against M1-M5, 0 problems. Two caveats:--onlyfilters subjects, so the0 controlsis a scope artefact and the twoCONTROL red as plantedlines in the log are the limits table's own planted controls; and this is a scoped diagnostic, not the full qualification receipt (docs/recipes/SKILL.md), which this GPU cannot produce — see below.tools/bench_openai.py: n/a, no serving path to measure; the serving pull request carries the pair's numbers.zig build test test-goldenat this tree: 7116 passed, 45 skipped, 0 failed of 7161, with 535 of 535 build steps; the 45 skips are the image-codec and pixel cases that need libjpeg-turbo 3.1.4.1 or libwebp 1.6.0, plusSKIP qwen27-tp-check: no --model DIR; the filteredtf-kernel-contractrun quoted above is separate from that count and exits 0 withSUMMARY 4 kernels: 4 pass gates 1-4, 0 fail, 0 known findings.tf-kernel-contractcorpus stops atUNSUPPORTED gemma4 31B rounded dense: tensor units required; Gemma coverage uncheckedand exitserror: TensorUnitsRequired, so Gemma 4 31B needs a tensor-unit Mac; the rotary probes behind it want--rotary-accuracyfromtf-rotary-sweep, which this draft does not claim; CUDA, HIP/RDNA, M1-M3, M5 and Windows are not in this room, so the CIzig-windowsjob and a reviewer's CUDA box have to carry them; and there is no maintainer-agreed gate for a new tensor-parallel family —zig/gate.jsonhas no entries at8c36359dand neither Tensor parallel across Metal and CUDA ranks (Mac + NVIDIA): tracker #1236 nor Two-Mac (--speed-up) for Qwen3.8-27B, and a mid-size model that fits a pair of 128 GB Macs #808 names a threshold, so this draft asks for that decision rather than inventing one.Checklist
pairLoopbackis a test double for the far rank."draft": false, a resumed prompt equals a fresh one, and concurrent equals solo. — not reachable at this commit; the pair refuses drafts and keeps no prompt cache, and the serving pull request records why.simd_qmm'sTF_OUTfloat store, which exists so a rank writes its exact part; every bf16 store and every single-Mac sum is untouched.SUMMARYline is in the receipt. — the four launches carry a spec, a record and a probe each, themetal pairlimits route is registered, and the float store is a spec variant; Metal is the only backend in this change and its filteredSUMMARYis quoted above.127.0.0.1, and every later script in the stack reads its host and paths from arguments or the environment.