Repository navigation
fabric: the pipeline stage link, a TCP ring that carries each round's plan and hidden rows, with a shared key (Linux and macOS, #2005 step 1) - #2012
Conversation
|
Thanks @jschmied. An independent review on current main (d8b80bd):
Applying it: both commits apply cleanly on main d8b80bd. The lean check stays at 424 (5,063 files, against What it changes on existing paths: nothing
Failure handling
Security
Change
Small points (not blocking)
TestsThere are 17 test blocks across
It's a new module, so there's nothing for the tests to fail against on main. The author ran them on Linux aarch64 Device cells
|
|
Thanks @ashhart. Fixed in c68421b, a third commit on top (no rebase). The change:
Small points:
Checks on c68421b: |
|
@ashhart, one more commit before your Mac run: The cause:
The fix: every link socket stays non-blocking after connect and accept. The send and receive loops already poll and take partial transfers. Results:
Without the fix, any send larger than the socket buffer to a stalled peer would ignore its timeout on macOS. #2060 picks this commit up when it's rebased onto #2012. |
|
Thanks @jschmied, everything from our last review is in. Two tiny things for the body: it still says "Head commit: c68421b" and "Three commits" (it's four now, ending at |
|
Thanks @jschmied, the macOS socket fix and the |
a00b616 to
bfaae03
Compare
…und's plan and hidden rows (Linux and macOS) - fabric stage: each link proves the ring's shared key both ways before any plan or rows frame - fabric stage: a stop on a broken link hangs up instead of sending, a wildcard listen and a key file over 4 KiB are refused - fabric stage: the frame magic is 0x54534654, so its little-endian bytes on the wire read TFST, and the frame test checks them - fabric stage: a link's sockets stay non-blocking, so on macOS a send to a stalled peer keeps its deadline - fabric stage: zig fmt on secret.zig and frame.zig
|
Thank you @jschmied. This is merged into main with your commits under your own name, so you're listed as a TensorFold contributor. It ships in the next release, credited to you in the changelog and the release notes. |
…534654 (TFST), rewritten
…nd tf-qwen35-cuda stage cuda_stage.zig drives the stage link (ashhart#2012) with the protocol (ashhart#2060): at boot each stage's description and ready report go round the ring and rank 0 checks every one and the layout; each round rank 0's plan goes round (rank 0 checks the last stage's echo byte for byte), then the rows, h and r as bf16 planes. Slots is the same code on every rank: open takes a free slot at generation 0, continue keeps the previous window's first `accepted` rows (a keep advances the generation) and checks the plan's generation and position, close frees it; resume is refused until the prompt cache spans stages. Rank 0's Lead predicts each entry's position and generation, sends the plan, then applies it through Slots like every follower. tf-qwen35-cuda <model> stage <out> runs one scenario (a two-chunk prompt, greedy steps, a second stream beside it, drafted windows kept to 3, 5, 0 and 2 rows, a keep-alive) on one engine or a ring. Qwen3.8-27B MLX 4-bit on one GB10: 2 stages (0:32, 32:64) and 3 (0:20, 20:44, 44:64) give the one engine's 48 logits rows byte for byte, bf16 and fp8 KV; device bytes 16.98 GiB whole, 9.04 + 7.64 GiB in two, 6.61 + 6.03 + 5.22 GiB in three. A follower killed mid-scenario ends rank 0 with Closed 0.4 s later.
|
Thanks @jschmied! This is in TensorFold 1.2.3, out now: https://github.com/ashhart/TensorFold/releases/tag/v1.2.3 |
What this changes
This adds
zig/src/fabric/stage, the pipeline stage link from #2005. It's a TCP ring of ranks that carries each round's plan and hidden rows, builds on Linux and macOS, and uses no CUDA or Metal module. Each link proves a shared key both ways after the hello, before any plan or rows frame. Nothing calls it yet: the Qwen 27B stage mode (step 2) is the first user.fe6aeebc7), the non-blocking sockets for macOS (43ea71321) andzig fmtonsecret.zigandframe.zig(27f01d6).atc overlap --json:build.zig, which gets one added line in the test step list. Most open PRs touchbuild.zig, and they merge cleanly with this one.Why a module of its own: #2005 first proposed reusing
fabric/tp's control plane. Butfabric/tp/config.zigimportscuda(forgraph_cache), andzig/build/tp.zigbuildstponly beside a CUDA module, so a Metal process can't import it. A check on an M3 Pro confirmed thatbootstrap,fate,sockandlogcompile foraarch64-macos, and thatplanlinkfails only in its Linux CPU-pinning helpers. A module that needs only libc avoids changing the tensor-parallel code that GLM and DeepSeek-V4.1 serve with. Foldingfabric/tp/sock.zigonto this module'snet.zigcan follow once the control plane is split.Design:
0.0.0.0is refused,WildcardAddress), connects to the next rank, and accepts the one before. Rows go round the ring, back to rank 0 for the head.OtherWorld,NotNeighbour,OtherFingerprint).TF_STAGE_SECRET_FILEnames a file of 16 bytes to 4 KiB that only its owner may read (mode0600); the key is its SHA-256. When a link forms, both ends send a fresh nonce from/dev/urandom, then an HMAC-SHA256 over a label, their role, rank, world, the fingerprint and both nonces, checked in constant time. The key never crosses the wire and a proof can't be replayed. A rank without the key is refused by both neighbours (BadSecret), and a stranger that connects and talks first is refused at its first frame (BadMagic).0x54534654, so its bytes on the wire readTFST. The payload can be sent as several parts, for examplee.hande.rback to back. Kinds arehello,plan,rowsandstop. Every send and receive has a deadline.error.Brokenfrom then on), since its stream may be mid-frame.stopon a broken link hangs up both links instead of sending a header that could complete a half-sent frame. A rank that fails closes both its links, so each neighbour's next call fails and the ring ends as one. That's RFC: a layer-range (pipeline) layout across mixed nodes: one hidden row per token over Ethernet, GB10 and Mac in one model #2005's fail-fast option (b).TF_STAGE_RANK,TF_STAGE_WORLD,TF_STAGE_PEERS(host:port,..., in rank order),TF_STAGE_SECRET_FILEandTF_STAGE_TIMEOUT_S, each refused by name when missing or malformed.Checks on this head
zig build test-stagepasses 20 of 20 on the GB10 (Linux aarch64), counting 18 named test blocks and two that pull the files in. The previous head (19 of 19) also ran 20 repeats clean on the GB10 and natively on macOS 27.2 on an M3 Pro (3 of 3 runs); this head wasn't rerun on the Mac. The tests run rings of two and three ranks on loopback threads:Closed(this test fails on the previousstop);test-stage-compilebuilds the tests for aarch64 Linux and macOS.zig build test(which now includes both), the CI set (test-kernel-contract test-golden test-server-security test-pull-security fuzz-cortheon) andgit diff --checkpass.Receipt
n/a: nothing reaches inference yet. No engine, server or CLI path calls the module.
Checklist