Repository navigation
Conversation
…uted experts to the idle CPU pool A chunk below stream_all_min() (1,024 tokens: an agent's tool result, a test's output) streams every routed expert outside VRAM over PCIe while the decode CPU pool sits idle and the arena holds the same experts in RAM. Opt-in, STRATA_PREFILL_CPU_SHARE=auto|x: - the non-resident experts routed by at most MAXT of the chunk's tokens, fewest first, run on the pool on a thread while the GPU streams and runs the rest; their unweighted rows go to Dm's tail (as a peer GPU's do) and the combine weights them as any other row; - auto: the share measured, each layer's CPU time per expert and the GPU's per streamed expert (CUDA events around its expert work, read after the next layer's routing sync), and the next layers hand the CPU g / (c + g), where both end together - a small CPU takes a small share; - Q2_0 layers take the pool's Q2_0 kernels' activations (ActQ, as decode's), i-quant layers the native vec_dot type. Serve without batch slots and generate, one GPU. Unset (the default): no expert moves, byte-identical to v0.1.39 (IQ2_XS 600 and 2,100 tokens, fixed cache, logits and 32 tokens). RTX 5090 + 9950X3D, 600-token prompts, ms (off / auto): - UD-Q4_K_XL: 1,548 / 1,369, 1,528 / 1,296 (share 0.65; KL between 0.006); - Q2_0: 472 / 445, 491 / 448; - IQ2_XS: 493 / 481, 502 / 460, 527 / 529; 250 tokens 424 / 355, 402 / 382, 379 / 367 (KL to STRATA_PREFILL_MMQ=0 0.0053 off, 0.0080 auto); - IQ2_XS on 2 AVX2 workers (emulated): 512 / 487 (share 0.49). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZy1yKaDDiA8a7svdwaHio
Measured on RX 7900 GRE + Ryzen 7 5700X3D: short prompts get slower, not fasterRyzen 7 5700X3D (the same CPU as the #1050 measurement) but a much faster GPU: RX 7900 GRE (gfx1100), NixOS, ROCm 10.2 nightly, Qwen3.8-Flash-Next Coder IQ1_M, Short prompt (849 tokens, one chunk below
Every fixed share and the measured one is slower than off, monotonically in the share — so this is not just Engagement / diagnosis. The flag engaged as designed ( Unchanged, as claimed:
Why the sign flip: #1050's machine is an RX 6800 (gfx1030) — a far slower GPU, so Scope note: with |
|
@jase100k thank you - your host-time numbers explained it. Per streamed expert the host went from 107 us (off) to 200 us (auto, 0.47): with the CPU busy, the streaming side kept 0.53 of the experts at 1.87x the cost each (0.99), so it saved nothing and the CPU's work came on top. #1379 makes |
265 commits: the 0.1.40.2 batch (F4 verify windows, the Linux file tier Niko1221#1194, the stager wait Niko1221#1057, opt-in CPU share Niko1221#1282, Intel Arc) and the 0.1.40.3 hotfix (Intel Arc install path and A750 first answer, Windows AMD cache floor Niko1221#1376, bundled HIP runtime Niko1221#461, Docker config links Niko1221#1244, the Niko1221#1357 MTP router guard, the tokenizer hardening Niko1221#1385). main keeps 33af099 (AMD PCIe link speed/width and GPU name detection); its 34 added telemetry lines are all present after the merge.
…the share and shares only while that is faster (#1282) auto balanced the CPU's time per expert against the GPU's per streamed expert, both measured with the share on, so nothing compared a layer with and without it. On jase100k's RX 7900 GRE + Ryzen 7 5700X3D the host's time per streamed expert rose 107 -> 200 us with auto (0.47): the streaming side saved nothing (0.53 x 1.87 = 0.99) and the CPU's work came on top, -4.5%. Now every eligible layer is timed with CUDA events from before its routing sync to its combine, per non-resident expert; adjacent layers alternate no share / the measured share until three ratios are in, then auto shares while the median of the last five is below 1, with one layer in 29 in the other arm. Layers with a one-time cost and the first layer are left out. STRATA_DBG_CPU_GATE=1 prints each measurement. RTX 5090 + 9950X3D, IQ2_XS, 250 / 600 / 900 tokens against off: DMA streaming -9.8/-9.9/-10.4% -> -8.8/-9.1/-10.5%; an emulated host-copied stream -18.0/-16.7/-14.4% -> -16.1/-15.2/-13.0%; one core + one worker (where the old auto lost up to +11.5%) +1.4..+2.4% -> +2.0..+2.3%, the cost of the first measurements. Unset: byte-identical.
|
Thanks @sergqwer, and @did-technomancer for the RX 6800 numbers. This is in 0.1.41 with your authorship kept on the commit, and it is on by default on NVIDIA now: one GPU, no Final numbers, interleaved whole-engine runs, 8 rounds, medians, prompt time against the share off (8 of 8 pairs faster on each): 512 tokens -28 to -34% and 1,000 tokens -20 to -26% on an RTX 3060, a Tesla P100 and an RTX 5070; 2K and longer unchanged. The answers can differ slightly: first-token KL against off averages 0.004 (max 0.025). Two things we changed on top: the share's thread no longer calls the expert source itself (its blob() counts reads without a lock, so it raced with the prefill thread's own calls), and |
…iko1221#1282) auto は CPU と GPU のエキスパートあたりの時間を、どちらも分けた状態で測って 割合を決めていたので、分けない場合と比べていなかった。upstream の RX 7900 GRE と 5700X3D では、CPU が忙しいとストリームを出すホストの時間が 107 から 200 us に増え、 分けると 4.5% 遅かった。 対象の層ごとに、ルーティングの同期の前から combine までの時間を VRAM にないエキスパートの数で割って測る。最初は分けない層と分ける層を交互に 並べ、隣どうしの比が 3 つそろったら、直近 5 つの中央値が 1 未満のあいだだけ分ける。 29 層に 1 層は反対の側を測る。一度きりの費用がある層と最初の層は数えない。 STRATA_DBG_CPU_GATE=1 で測定を出す。決まった割合(0.4 など)のときは変わらない。
…L_CPU_GATE=1) IQ3_XXS の 1K の prefill、4 回交互の中央値で、判定ありは B70 で 844 → 833 tok/s(-1.3%)、 RTX 4070 で 296 → 283 tok/s(-4.4%)。分担しない側を試す層の分だけ遅くなり、どちらでも速くならなかった。 upstream が判定を入れたのは RX 7900 GRE と 5700X3D で分担が負けた件(Niko1221#1282)で、upstream は HIP では分担自体が既定で切。
…the share and shares only while that is faster (Niko1221#1282) auto balanced the CPU's time per expert against the GPU's per streamed expert, both measured with the share on, so nothing compared a layer with and without it. On jase100k's RX 7900 GRE + Ryzen 7 5700X3D the host's time per streamed expert rose 107 -> 200 us with auto (0.47): the streaming side saved nothing (0.53 x 1.87 = 0.99) and the CPU's work came on top, -4.5%. Now every eligible layer is timed with CUDA events from before its routing sync to its combine, per non-resident expert; adjacent layers alternate no share / the measured share until three ratios are in, then auto shares while the median of the last five is below 1, with one layer in 29 in the other arm. Layers with a one-time cost and the first layer are left out. STRATA_DBG_CPU_GATE=1 prints each measurement. RTX 5090 + 9950X3D, IQ2_XS, 250 / 600 / 900 tokens against off: DMA streaming -9.8/-9.9/-10.4% -> -8.8/-9.1/-10.5%; an emulated host-copied stream -18.0/-16.7/-14.4% -> -16.1/-15.2/-13.0%; one core + one worker (where the old auto lost up to +11.5%) +1.4..+2.4% -> +2.0..+2.3%, the cost of the first measurements. Unset: byte-identical.
Replaces #1050, which GitHub closed when
main's history was rewritten. The closing note says this was not a rejection. It is the same commit, cherry-picked onto the newmain(v0.1.40.1).A chunk below
stream_all_min()(1,024 tokens) streams every routed expert outside VRAM over PCIe. An agent's tool result, a test's output and a short follow-up are all such chunks. Meanwhile the decode CPU pool sits idle, and the arena holds the same experts in RAM.This adds an opt-in,
STRATA_PREFILL_CPU_SHARE=auto|x. Unset (the default), no expert moves and the output is byte-identical to v0.1.40.1.What it does
MAXTof the chunk's tokens, fewest first. It runs them on a thread while the GPU streams and runs the rest.Dm's tail, as a peer GPU's do (the same mechanism as--peer-device), and the combine weights them as any other row.auto: the share is measured. Each layer times the CPU thread per expert, and the GPU's expert work per streamed expert. The GPU side uses CUDA events around its expert work, read after the next layer's routing sync, because the host reaches the combine long before the GPU does; timing the host instead gave a wrong share. The next layers hand the CPUg / (c + g)of the streamed experts, the point where both sides end together. A small CPU therefore takes a small share and does not make the prompt slower.xfixes a share.ActQ, as decode's), and i-quant layers take the nativevec_dottype.Measured
On another machine, by @did-technomancer (#1050): RX 6800 16 GB (gfx1030) + Ryzen 7 5700X3D (AVX2, no AVX-512), Windows 11, ROCm, IQ3_XXS, 128K context. Short prompts (~850 tokens) read 37-45% faster, and long prompts and decode are unchanged. Their quality suite gave 22/22 with the switch on.
autoautoOn 0.1.40, here (IQ2_XS, one chunk, ms, off / auto): 600 tokens 487 / 463, 489 / 457, 491 / 485 (share 0.86-0.87); 250 tokens 386 / 357, 386 / 352, 379 / 356 (share 0.90).
On 0.1.39, here. RTX 5090 + Ryzen 9 9950X3D, generate, one chunk, ms (off / auto):
STRATA_PREFILL_MMQ=0: 0.0053 off, 0.0080 auto.stream_all_min()stays 1,024. On the fork with NVFP4's 2.76 MB experts the routed-only walk paid up to 4,096 tokens, but on Q2_0 it lost against streaming every expert, so it stays out of this PR.🤖 Generated with Claude Code
https://claude.ai/code/session_01VZy1yKaDDiA8a7svdwaHio