Repository navigation
Conversation
|
Thanks @jschmied, this is the follow-up we suggested on #1503, and it's done well.
No kernel or build change, and the served replies hash the same as #1503's run. CI is green and it merges cleanly with main. It lands right after #1503, as one file on top of it.
|
…m leasing The kernels already read keys and values through a slot's page table, so the pool changes only what the table holds and how large the arena is; no kernel changes. A page is 512 positions of the ten attention layers' keys and values (10 MiB, 20 KiB a token); the conv states stay a fixed part a slot (240 KiB). - Loaded.layout with engine_paged, as Dory's: the plan sets a window of pages aside for the first stream; each stream leases its prompt, its reply and one verify window at its prompt pass and gives them back when it ends. A request that cannot lease waits (LaneMemory); fits is the host's admission. - Model.attach makes the arena and the tables and conv states of the slots the plan names; forward refuses rows past a slot's pages. The idle server logs the pool's census. - TENSORFOLD_LFM2_KV_PAGES=0 keeps every stream's own window of pages, made at open. Served on the GB10 at --parallel 8, 16k: drafted == plain and concurrent == solo, also with 8 long prompts on a 52-page pool where the last waits for pages; the replies equal the fixed pages' ones.
…the pages' rows through its position A state at `at` is the slot's conv states and its keys and values at positions [0, at) of the ten attention layers: one copy a run of consecutive whole pages, then the last page's rows a layer's keys and values. It is copied behind the chunk that ends at the mark and restored into the new stream's leased pages before its next chunk, so a later turn's pass starts at its history. Lookahead 0, as the other headless families. States live in 2 MiB snapshot pages allocated once at startup inside the prompt-cache budget (`snap_ready`), as GLM's: a keep or a restore leases or reads pages and allocates nothing, and a dropped state's pages go back to the pool at once (every copy that reads or writes them is queued on the backend's one stream). The store counts held and spare pages through `snap_charged` / `snap_spare` / `snap_reuses`.
…dds no pass A chat mark inside a prompt chunk ended the chunk there, and every extra prompt pass reads the weights once more: a cold 10k chat turn, whose two marks sit in its last chunk, ran 12 passes instead of 10. Now up to four marks inside a chunk are tapped instead: the conv kernel runs once more on each mark's last row alone, writing the same y and that row's conv states into the model's tap buffer, and the keep copies those states with the K/V rows before the mark. The pass goes on to its grid line; a fifth mark still ends it. The kernel is unchanged.
…fuse anything but 0 or 1
…irst token doesn't wait for them
…hich waits for the keeps A clear, a chunk, a one-row step, a verify round and a commit each queue on the stream fenced() hands back, after the keeps' copies queued so far. A host test reads the backend's writes and fails on one queued on the prompt stream without the wait; each of the five planted that way goes red.
ccd0470 to
b64c744
Compare
|
@jschmied main moved under this and it conflicted with main in docs/environment.md zig/src/platform/environment.zig zig/src/platform/environment_test.zig (it builds on #1503, rebased first), so the landing train left it out. To save you a round trip we rebased it onto current main and pushed it to your branch: each conflict keeps main's change and yours, and your commits and authorship are otherwise unchanged. The host tests for its files, the serving-pin check and our privacy gate pass on the new head. It goes back in the landing queue once its CI is green. No other asks.
|
Stacked on #1503 (head
550690618); base main. Follows Synthena's suggestion on #1503 (comment 6806587680): one helper all five prompt-stream writes go through, and a host test that fails if a writer skips the wait. The head isccd047085, one commit; it touches onlyzig/src/families/lfm2_moe/cuda_backend.zig. Once #1503 lands, this diff is that one file.What
Lfm.fenced()(cuda_backend.zig:180) returns the prompt stream after it waits on the device for the keeps'done(cuda_snap.Pages.fence, unchanged).opening), a chunk (chunk), a one-row step (queue), a verify round (verify) and a commit (keep).Lfm.settle()on the line above and then passedx.s. That helper is gone.cuda_backend.zig:532) reads the backend's own source, up to its tests.fwd.forward(,fwd.commit(and.clearSlot(call and requires the stream argument to betry x.fenced().x.swithout the wait. Each is caught (one unfenced write) and all five are counted.fenced()test (cuda_backend.zig:564), with a fake driver:done.snap.restore. lfm2_moe CUDA: attention pages from the shared KV pool, and the prompt cache (stacked on #1492) #1503's ordering test (cuda_snap.zig:340) and its three planted orders are unchanged;cuda_snap.zigisn't touched.Shared core or LFM2 only: LFM2 only. Every other side stream joins inside the same pass: FlashNext's shared expert (
flashnext/cuda_batch_side.zigfork/join), GLM's L2 prefetch (glm/cuda_l2pf.zig), Nemotron's side, and DeepSeek-V4.1's L2 prefetch and overlapped ingests (deepseek_v41/l2pf.zig,dspark_slots_ingest.zig). None leaves work pending for later writers to fence. The other families' keeps (Dory, Gemma 4, FlashNext, GLM, Qwen3.5) copy on the prompt stream. So no second caller exists to share a helper with. If another family moves its keeps to a side stream,Sideandfencedwould move to core together.Hot path: no change to launches or kernels.
.cu,.cuhor build file changes, so every fatbin and its SASS is the same build output.Proposed CHANGELOG line, under Unreleased: "LFM2.5-24B-A2B on CUDA: every prompt-stream write that a keep reads takes its stream from one helper that waits for the keeps, and a host test fails on a write that doesn't (#NNNN, stacked on #1503)."
Verification (on
ccd047085)zig build test-lfm2-moe-cuda-host20/20.zig fmt --checkclean.x.s(try fwd.forward(x.m, x.k, x.s, chains, ...)). The test fails atcuda_backend.zig:536(expected 0, found 1, 19/20). Restored, the head is green as above.zig build -Dfixed-cpu test test-golden test-kernel-contract test-server-security test-pull-security fuzz-cortheon check-release-paths,check-native-cuda-host compile-cuda-tests,zig fmt --check,pr_checkwith lean: 694/694 steps, 3629 tests (2 more than lfm2_moe CUDA: attention pages from the shared KV pool, and the prompt cache (stacked on #1492) #1503's 3627), lean 386 vs 386 on the base (0 new),pr_check0 errors (1 warning: the CHANGELOG line is in this body).673a34b3b(lfm2_moe CUDA: attention pages from the shared KV pool, and the prompt cache (stacked on #1492) #1503's base), keeps on.GATES_OK.TENSORFOLD_LFM2_KV_PAGES=0), under pool pressure (8 long concurrent prompts) and with a 0.1 GiB cache. A restarted server's replies are equal too.d3c46363c6bb8d5dis identical on all five arms to lfm2_moe CUDA: attention pages from the shared KV pool, and the prompt cache (stacked on #1492) #1503's run on550690618.