Repository navigation
Conversation
5e1fdf5 to
fff57ae
Compare
fff57ae to
25a26af
Compare
|
Thanks for the review on #2970. Pushed as |
|
Thanks @swbiggart,
No more asks on the change itself. One rebase is needed before it can land:
#2978 and #2980 touch the same usage text and pins, and #2978 the same recipe file. Whichever of those lands after this keeps both sides. You don't need to do anything about After that, we'll run
|
…lective At --tp 2 each rank ran the benchmark gather, its first collective, as soon as its own weights were in, under the collective's 30 s bound. Two ranks whose loads finished more than that apart could never start: the faster one stopped with RankTimeout and the start failed. Session.afterLoad first runs a load-ready exchange (room: the same frame, its validation and its 10-minute bound; a closed link ends it at once), then the gather. The exchange at the end of the load still runs, so the ranks now exchange ready twice. The gather stays where it was, so NCCL's buffers, the scratch and the memory plan come in the same order. A host test over a socket pair shows the first collective waits for a peer past the collective's bound and that a peer leaving ends the wait before any collective; flashnext-rank gains late and gone modes on two GPUs.
7371ef3 to
fa5e3d5
Compare
|
Rebased onto main
|
|
Thanks @swbiggart. The rebase keeps every rank mode in one usage line, the engine cleanup is registered before the load wait, and your new-head This now waits on one two-GB10 startup/serve run that we'll schedule, covering unequal load times, a peer leaving during load and token equality against main. No action needed from you; we'll handle the CHANGELOG placement.
|
What this changes
At
--tp 2, a Flash Next rank ran its first collective (the benchmark gather incuda_lanes_load.zig'sopen) assoon as its own weights were in, under the collective's 30 s bound, so ranks whose loads finished more than 30 s apart
could not start. Now each rank first runs one more load-ready exchange (
Session.room, with its 10-minute bound),then the gather; a peer that exits, fails its load or closes its link ends the wait with
RankDisconnected. No newframe, setting or bound.
4cfd95573);36be03cac(change, tests, recipe line, serving pins),c40a84b19(changelog) andfa5e3d56d(a failed load waitfrees the prompt engine: its
errdefermoves up to just afterEngine.initRank; test 3 and the pin row follow).atc overlap --json(ATC 0.9.6, 2026-11-11 12:01 UTC, before the rebases, base93a2e93ec,complete: false):"conflicts"with dsv41 metal: image prompts #1722, GLM on CUDA: the latent split's per-rank page book and owner (TF_GLM_KV_SPLIT, #1431 part 1; stacked on #1411) #2415, qwen27: slot 0 keeps its rewind point through the warm pass #2723, llama on Metal: Qwen2 checkpoints, Bimo-7B-CyberAgent's bf16 release with its q, k and v biases and YaRN at HF's rounding points #2890 and xpu: a sampled Qwen3.8-27B row draws from a top-k kept on the card #2895; every open pull request sharing a file was trial-mergedwith
git merge-tree. New conflicts:zig/tests/cuda/main.zigwith EXL3 Flash Next on CUDA: one rank, offloaded experts, sm_120 gate (1/8) #1441-EXL3 Flash Next: draft lane guard for offloaded experts (8/8) #1446 and EXL3 Flash Next: host-resident K/V on the tier (6/8) #1522 (keep their usage text,add
late|gone); the re-opened## Unreleasedheading inCHANGELOG.mdwith ricursive: Ripple-65B-Preview on native CUDA (NVFP4) #2302, ricursive: Ripple-65B-Preview's DFlash2 drafter on native CUDA #2475, ricursive: load Ripple's EXL3 packs through main's shared EXL3 code #2514, ricursive: serve Ripple-65B on two GB10s with up to 1M tokens of context #2522, ricursive: speed up Ripple-65B on two GB10s #2523,qwen27: slot 0 keeps its rewind point through the warm pass #2723, server: the last --compact-at wins (auto then a fraction kept auto) #2883, server: serve --config FILE.toml reads flags from a file #2885, llama on Metal: Qwen2 checkpoints, Bimo-7B-CyberAgent's bf16 release with its q, k and v biases and YaRN at HF's rounding points #2890 and xpu: a sampled Qwen3.8-27B row draws from a top-k kept on the card #2895. Whichever of this and CUDA (GB10): Flash Next KV in the display carveout, opt-in #2763 lands second re-pins
cuda_lanes_load.zigingradient-serving.tsv. Re-run right before this pull request opened:atc overlap --jsonat 2026-11-12 14:08 UTC on head25a26afab; everyconflictsentry is named in this section, or adds no conflict beyond those it already has with main (1), or conflicts only inCHANGELOG.md's## Unreleasedlines, as this section describes (5); each checked withgit merge-tree.Checks on this head
fa5e3d56defa745f4757fb7dc0110ed91b426b4d1da83e13d(tree equal to17f7d67d2) before the rebases onto maineab305db0(flashnext: refuse a malformed TF_FLASHNEXT_* setting by name before device work #2585there changes only how
TF_FLASHNEXT_*settings are read, incuda_lanes_load.zigtoo) and then4f8317dac000b534a2and3885dceb2(only theCHANGELOG.mdline and pin rows moved), thenab78aef90and4cfd95573(flashnext-rank: the failure modes start once both communicators are up, and timeout bounds only the collective #2976 and flashnext cuda: at --tp 2 a prompt pass reduce-scatters its routed experts' slots by rows and gathers their sums #2977 landed; this branch'slateandgonejoin flashnext cuda: at --tp 2 a prompt pass reduce-scatters its routed experts' slots by rows and gathers their sums #2977's mode list, and the twoflashnext-rankusage lines become one); none changed this branch's other lines, so everyreceipt stands, and the device modes ran again on
ab6d2ceaf, this code onab78aef90.python3 tools/zig/lean_check.py: main4cfd95573341 (inherited), this head 341, the samefindings, 0 new.
zig build test-cuda-host: this head passes on Linux x86_64 in the CUDA 13.3.1 image (exit 0; Zig prints no Build Summary without--summary).Uncached on
17f7d67d2: 379/379 steps, 6139/6178 passed, 39 skipped; flashnext module 270/270, with three newtests in
cuda_rank_start_test.zig(socket pair, not on Windows):.ready400 ms in, against a 50 ms collective bound, is awaited before the first collective.RankDisconnected, no collective.cuda_lanes_load.zigcallsr.afterLoad, notbenchmark_group.directly, and registerserrdefer own.engine.deinit();before it.Session.afterLoad; with main'scuda_lanes_load.zigput back,test 3 fails (flashnext module: 269 pass, 1 fail); with
25a26afab's order (theerrdeferafter the wait), test 3fails.
zig build test test-golden -Dcpu=apple_m1(macOS), on75a849407, this head's code on maineab305db0(the patch-id without
CHANGELOG.mdis the same): "Build Summary: 837/839 steps succeeded (1 failed);7593/7667 tests passed (73 skipped, 1 failed)". The failure,
dashboard_test"dashboard page polls the publicstats snapshot without private details", is inherited: main
eab305db0fails it on the same Mac ("BuildSummary: 837/839 steps succeeded (1 failed); 13041/13152 tests passed (110 skipped, 1 failed)").
zig fmt --check build.zig zig,git diff --check,zig build test-gradient-serving: pass on this head.late,gone(2 x RTX PRO 6000,1da83e13d): PASS (Receipt); again onab6d2ceaf, withsum: PASS(rank 0 waited 35,061 ms for
late;RankDisconnectedafter 2,956 ms forgone).late/goneon main: main'stf-cuda-testlacks them.eof,missing,timeout: unchanged code (late/gonebranch off first).bench_concurrent, prompt speed, sampled requests: the change runs once per start.Receipt
Main against branch: unpaced served starts on 2 x GB10 (200G RoCE); main
fb8fdf3d8against this change onfb8fdf3d8(cuda_rank_engine.zigbyte-identical to this head's,cuda_lanes_load.zigapart from flashnext: refuse a malformed TF_FLASHNEXT_* setting by name before device work #2585's settingreads):
RankTimeoutat 23:43:05, 31 s after its load; start failedNot a same-conditions A/B (a build ran on rank 1's host during main's start).
Device modes at
1da83e13d,tf-cuda-test flashnext-rank RANK PORT MODE, two processes, one GPU each, real NCCL,production 30 s collective bound, 2 x RTX PRO 6000 Blackwell Max-Q (PCIe Gen4):
late: rank 1 loads 35,000 ms lategone: rank 1 leaves 1,000 ms in, as a failed load does (959 ms)RankDisconnectedafter 2,961 ms (bound 10 s)Boxes it reaches: Flash Next on CUDA at
--tp 2, once per start; one-GPU Flash Next and other families unchanged.New switch? Default, accepted values, profile row: none.
Environment, with the TensorFold commit, Zig and backend toolchain, machine and GPU, checkpoint and revision: Zig
0.17.0; CUDA 13.3.1,
-Doptimize=fast -Dcpu=native -Dsm=121; NCCL 2.32.3; 2 x GB10, 121.7 GiB each, Ubuntu24.04.4, drivers 580.178.04 and 580.159.03;
nvidia/Qwen3.8-Flash-Next-NVFP4revisionfc694b54fb0174e0913e6adf86691ef85a4ead47, MTP drafts,--tp 2 --context 65536 --prompt-cache-gib 0, greedy. RTX:sm_120, driver 595.99.02.
Paths and platforms the change reaches, which I ran and which I could not: the CUDA
--tp 2rank start; ran sm_121(served) and sm_120 (device modes); not run: a served start on sm_120 (covered by GB10 and
late/gone).Exactness, from
tools/bench_concurrent.py --alone --serialortoken_shaagainst"draft": false: 3 greedy256-token requests per cell: chat
764da77fbd3fand code4e759dbd859cin every branch cell, drafted equal to"draft": falseand to a paced start of main.Main against this branch, same machine and checkpoint, posted before asking for a run on our machines (or why you
can't): the tables above; rank logs, results, runner scripts and host-check records: https://gist.github.com/swbiggart/ddb5f44cffd779ee3a0842ca2d743d2d
Decode speed before and after, from
tools/bench_openai.py: no claim (once per start). Median tok/s, code drafted /plain, chat drafted / plain: main (paced) 51.79 / 23.26, 38.09 / 23.23; branch 51.80 / 23.08, 38.26 / 23.03.
Prompt speed before and after: n/a: the change runs before the first prompt.
Licence of any new weights or drafter, or "n/a": n/a.
Checklist
The title and description match the head commit, including the receipt and the stack.
New tests fail before the change, pass after it, and skip cleanly without their dependency.
Comments and docstrings are one line. No measurements or history in the source.
No personal data, machine names, internal hosts or local paths in the diff or its commits. No AI attribution lines.
Every token still goes through the lane rounds. No serial path, and nothing that needs drafts off.
Drafted output equals
"draft": false, a resumed prompt equals a fresh one, and concurrent equals solo. (Drafted equals"draft": false; resumed and concurrent not run: no per-request state changes.)No precision traded for speed. If the bits change, the description says which sums change and why.
Decode and prompt processing are no slower than main at one stream and the widest admitted; with
--drafter, no slower than without it, greedy and sampled (not compared: once per start; one start's decode is level with main's at one stream, greedy)