measure(ENG-EXPERT-STREAM-DEVICE): W0e ran, the CPU arm has a live-cache number and the CUDA arm loads without generating (#1124, #1299) - #1301
Conversation
…che number and the CUDA arm loads without generating (#1124, #1299) W0a and W0e both ran on `dgx:gpu0` inside one `rc hold`, on the head of #1242. Two of the three things this row wanted arrived and the third did not, so this change records all three and claims only what was measured. W0 works where it was aimed. `--device cuda` on `Qwen3.8-2.4T-A95B UD-Q1_0` loads in 255-272 s instead of refusing, the `[expert-stream] ON` banner prints on the device arm, and that banner is the first production evidence that W0b's CUDA leg is reached and answers true on real hardware rather than on the fake platform its unit gate registers. The CUDA arm then exhausts the box inside its first forward and emits no token, seven attempts, every one the same. That is filed as #1299 and it is not the expert lane: a 64-slot 0.15 GiB arena dies exactly where an 8000-slot 18.55 GiB one does, and a 1-token prompt, whose protected set fits the arena with no in-place tower fallback at all, behaves exactly like a 5-token one. The growth is `RssAnon` while `RssFile` stays flat, so the GPU is not pinning the mapping's pages either, which was the first hypothesis and is refuted. Host anon plus swap reaches ~65 GB while the system reports ~119 GiB used, and the ~42 GiB difference is device memory this unified part does not charge to process RSS. The non-expert weights are resident twice, and about 50 GiB of that is the bf16 expansion the GDN V-head reorder already forced on `attn_qkv` and `ssm_out`. `expert-streaming.md` predicted this in prose: "Whoever takes this needs BOTH". W0 delivered the expert half. The CPU arm is measured, reproduced, and replaces the figure `BENCHMARKS.md` carried as VOID from #912 F1: 11.05 s/token steady over 29 samples, two reps, with `steps=32` and a decode-phase `exhausted` delta of 0 in the same run, which is the pairing #912 F1 lacked. Four runs across two slot counts produced byte-identical token ids. The 8000-slot pair came out 3.6x SLOWER than the 4000-slot pair, which is the wrong direction for a bigger cache, and the swap column says why: an 18.55 GiB arena does not fit beside 62 GiB of dense weights on this box, so those runs swapped and one consumed all 30 GiB of swap. That is a memory result wearing a cache result's clothes, and it is recorded as such. G0-CORRECT has no CUDA side to compare against and says so rather than reporting the CPU half as a pass. G0-LIVE passes on CPU and is not reached on CUDA. G0-SPEED reports the CPU number and no ratio. The harness lands under `benchmarks/` beside `marlin_moe_standalone.cpp`, unwired from CMake, because one generation had to yield three things no shipped command gives together: the generated token ids, a per-step arrival timestamp, and the stream counters at both ends. Its logits processor is a pure observer that edits nothing, so the argmax is the one the sampler would have taken anyway, and the prompt is fixed as token ids so both arms are fed identical bytes with no tokenizer between them. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5-1m [claude-code]
The base branch gained the architecture-term repair and eleven unrelated benchmark sections from main; this branch carries the W0e measurement. Every conflict is a record, and each is resolved by key rather than by an automatic three-way merge: the benchmark log unions two disjoint section sets, the two keyed table rows take this branch's newer state of the same key with the W0a probe fact folded in, the spec keeps the base's architecture-term paragraph and full W0a bullet and then this branch's W0e result, and the usage page keeps the base's family-restriction bullet while this branch's measured bullet supersedes its "no speed claim" placeholder. Verified after resolution: each file differs from the base-branch version in exactly one hunk, so no unrelated key moved. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
…piled `benchmarks/expert_stream_device_w0e.cpp` landed in no CMakeLists, so nothing in the project built the instrument that produced this row's only numbers. Adding the `expert-stream-device-w0e` target showed the file does not compile under the project's flags at all: three backslash continuations inside `//` comments, which `-Werror=comment` rejects. The recorded manual `g++ -O2` recipe carries no `-Werror`, so that recipe was the only thing that had ever built it, and the file would have rotted against the very C ABI it measures without anyone noticing. The target links `vllm::shared`, not `vllm::vllm`, so the harness stays a pure client of `include/vllm.h`; `ldd` shows `libvllm.so.0` and nothing internal. Build rc 0, 0 errors, 0 ENOSPC, and the binary runs and parses its own flags. The header comment's now-false "NOT WIRED INTO CMAKE" paragraph and the spec's harness section both record what happened rather than only the end state. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code]
|
Replaced by #1414. #1377 landed as a squash ( #1414 is the same eight-file delta reapplied onto This branch is left in place rather than deleted, since it holds the original review history. |
…che number and the CUDA arm loads without generating (#1124, #1299) (#1414) Replaces #1301, which cannot be merged: #1377 landed as a squash and destroyed that branch's merge base, so merging `main` into it produced thirteen conflicts including product files this change does not touch. This branch is the same eight-file delta rebuilt on `main`. W0e is the measurement W0b-W0d existed to make possible. It ran on one `rc hold` on `dgx:gpu0` against the real 369.97 GiB `Qwen3.8-2.4T-A95B UD-Q1_0`, and it split. The CPU arm is now MEASURED and replaces the VOID #912 F1 figure: **11.05 s/token steady at 4000 slots**, which is rep 2's median over 29 samples. Rep 1's median is 11.22, so the two reproduce within 1.5%. Live cache, decode-phase `exhausted` delta 0 over 31 decode steps in the same run. The 8000-slot arm is slower on every pairing of the two medians, 3.56x to 4.11x across the four available pairings and 4.05x pairing rep 1 with rep 1, and it is much less steady: the steady window's max/min ratio is 3.99x and 5.87x against 1.30x and 1.40x at 4000 slots. The cause is NOT that the arena fails to fit. 18.55 GiB of arena beside 62 GiB of dense weights is 80.55 GiB on a 119.63 GiB box, and peak RSS barely moves for the 9.27 GiB arena delta, 86.5 to 86.6 GiB. What moves is `min avail`, 16,347 to 6,941 MiB, which is about the arena delta, and peak swap, 6,883 to 30,625 MiB, all of it. The best-supported reading of that pattern is page-cache displacement: the borrowed 370 GiB expert mapping is served out of whatever memory is free, the arena takes that memory, and the reclaim pressure it creates pushes anonymous pages to swap. That is a reading of the columns rather than a proven mechanism, because this run sampled no page-cache size and no major-fault counter. The operational conclusion holds either way, and it is the one to act on: more slots is not a free knob, and the publishable figure is the 4000-slot one. The CUDA arm LOADS, which it could not do before this row, and then generates nothing: it exhausts the box inside its first forward, 0 steps, 7 attempts. The slot arena is measurably not the cause, because a 64-slot 0.15 GiB arena fails in exactly the place an 8000-slot 18.55 GiB one does. That is #1299, and it is the DENSE half of the model rather than the expert lane. No speed claim is attached to the CUDA arm and `docs/BENCHMARKS.md` says so. The harness earns its own paragraph, because it did not build. It landed in no CMakeLists, so nothing in the project compiled the instrument that produced this row's only numbers. Wiring it as the `expert-stream-device-w0e` target showed the file does not compile under the project's flags at all: three backslash continuations inside `//` comments, which `-Werror=comment` rejects. The recorded manual `g++ -O2` recipe carries no `-Werror`, so that recipe was the only thing that had ever built it, and it would have rotted against the very C ABI it measures with nobody noticing. It now builds, links `vllm::shared` so it stays a pure `include/vllm.h` client, and `ldd` shows `libvllm.so.0` and nothing internal. A fresh review returned FAIL on the first head, and the second commit repairs its six findings. The copy-paste recipe and the `--offload-config` example in `docs/USAGE.md` set 4000 slots rather than 8000, so an operator who copies them gets the arm the published number was measured on instead of the 39.98-45.40 s/token one; every place that publishes 11.05 now names 4000 beside it; the "does not fit" story above is restated as what the columns support; the spec's `forced` anchor points at `qwen3_5.cpp:5521` rather than a W4 header comment 132 lines earlier; and the #1299 row in `.agents/issue-index.md` is appended at the end of that append-only file rather than inserted in its middle. This branch is rebuilt on `main` rather than merged into it. #1377 landed as a squash, which destroyed this branch's merge base, and merging produced thirteen conflicts including product files this change does not touch. Reapplying the eight-file delta onto `main` leaves three record conflicts, each resolved by key: the benchmark log unions two disjoint sections, and the two keyed table rows take this row's newer state while keeping the keep-quant/keep-f16 mechanism #1378 corrected. Verified afterwards that every one of main's #1378 repairs survives in the spec and that nothing of main's is missing beyond the W0e status text this measurement supersedes. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code] --------- Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
W0a and W0e both ran on
dgx:gpu0inside onerc hold, on the head of #1242.Two of the three things this row wanted arrived and the third did not, so this
change records all three and claims only what was measured.
W0 works where it was aimed.
--device cudaonQwen3.8-2.4T-A95B UD-Q1_0loads in 255-272 s instead of refusing, the
[expert-stream] ONbanner printson the device arm, and that banner is the first production evidence that W0b's
CUDA leg is reached and answers true on real hardware rather than on the fake
platform its unit gate registers.
The CUDA arm then exhausts the box inside its first forward and emits no token,
seven attempts, every one the same. That is filed as #1299 and it is not the
expert lane: a 64-slot 0.15 GiB arena dies exactly where an 8000-slot 18.55 GiB
one does, and a 1-token prompt, whose protected set fits the arena with no
in-place tower fallback at all, behaves exactly like a 5-token one. The growth
is
RssAnonwhileRssFilestays flat, so the GPU is not pinning the mapping'spages either, which was the first hypothesis and is refuted. Host anon plus swap
reaches ~65 GB while the system reports ~119 GiB used, and the ~42 GiB
difference is device memory this unified part does not charge to process RSS.
The non-expert weights are resident twice, and about 50 GiB of that is the bf16
expansion the GDN V-head reorder already forced on
attn_qkvandssm_out.expert-streaming.mdpredicted this in prose: "Whoever takes this needs BOTH".W0 delivered the expert half.
The CPU arm is measured, reproduced, and replaces the figure
BENCHMARKS.mdcarried as VOID from #912 F1: 11.05 s/token steady over 29 samples, two reps,
with
steps=32and a decode-phaseexhausteddelta of 0 in the same run, whichis the pairing #912 F1 lacked. Four runs across two slot counts produced
byte-identical token ids. The 8000-slot pair came out 3.6x SLOWER than the
4000-slot pair, which is the wrong direction for a bigger cache, and the swap
column says why: an 18.55 GiB arena does not fit beside 62 GiB of dense weights
on this box, so those runs swapped and one consumed all 30 GiB of swap. That is
a memory result wearing a cache result's clothes, and it is recorded as such.
G0-CORRECT has no CUDA side to compare against and says so rather than reporting
the CPU half as a pass. G0-LIVE passes on CPU and is not reached on CUDA.
G0-SPEED reports the CPU number and no ratio.
The harness lands under
benchmarks/besidemarlin_moe_standalone.cpp,unwired from CMake, because one generation had to yield three things no shipped
command gives together: the generated token ids, a per-step arrival timestamp,
and the stream counters at both ends. Its logits processor is a pure observer
that edits nothing, so the argmax is the one the sampler would have taken
anyway, and the prompt is fixed as token ids so both arms are fed identical
bytes with no tokenizer between them.
Stacked on
row/ENG-EXPERT-STREAM-DEVICE-W0(PR #1242), because every claimhere is a claim about that branch's code and none of it should land ahead of it.
agent-ready.pyis green on all 28 record gates and every mutation suite; itstwo commit-gate SKIPs are the stacking itself (
origin/mainis not an ancestorof a branch based on #1242's head), and both gates were run explicitly over
95883dcae..HEADand reportedOK: commit trailer contractandOK: commit writing style.Issues: #1124 (the row), #1299 (filed by this measurement).
FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5-1m [claude-code]