Repository navigation
adaptive tier: --adapt-async 1 in the arena mode (one GPU, copy-in only), x1.07-1.11 cold decode on an RTX 3090 + Ryzen 5 5600X - #1904
Conversation
In the arena mode the blocking adaptive tier creates and joins a thread every verify window and the next window waits for its copies (Niko1221#1863: the time outside the decode timing breakdown). --adapt-async 1 now also runs with the arena on one GPU, not only in the resident RAM mode. The arena holds every expert, so a round is a copy-in only: no copy back, no RAM move, no exchange buffers. - gates for the arena; ArenaExpertSource::blob_at() reads a blob from the job thread without the read counter - the evicted slot is marked non-resident and uploaded before the round's copies are posted; an expert becomes resident only once its copy's event has completed - STRATA_ADAPT_ASYNC_WAIT=1 (arena default): the next tick waits for the round, so the window an expert turns GPU-resident does not depend on timing; STRATA_ADAPT_PICK_INLINE=1 (arena default): one round per window; STRATA_ADAPT_ASYNC_BATCH=N caps the copies per tick (default 0 = all); arena rounds are not capped at 96 - adapt_quiesce(): every K/V grow, kv_quiesce and the VRAM command land the round in flight (they only called apply_pending(true)); a failed round still drains its copies. This also covers the resident mode's async tier. - STRATA_DECODE_TIMING: "adapt wait X join Y, Z swaps/window"; --adapt-async help text RTX 3090 + Ryzen 5 5600X, cold prompts: x1.07-1.11 decode, faster on 12 of 12 prompts; 25.9 -> 21.6 ms per window (bench/results/2026-10-11-community-rtx3090-5600x-arena-async, docs/DETAILS.md). Opt-in (--adapt-async 1, default 0); the default path is that of v0.1.42. With the tier on, answers are not bit-exact run to run (which window first computes a swapped-in expert on the GPU). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015oFHMEgBzk7kQSqUVWoc67
…ode (one GPU, copy-in only, opt-in) In the arena mode the blocking adaptive tier creates and joins a thread every verify window and the next window waits for its copies (Niko1221#1863: the time outside the decode timing breakdown). --adapt-async 1 now also runs with the arena on one GPU, not only in the resident RAM mode. The arena holds every expert, so a round is a copy-in only: no copy back, no RAM move, no exchange buffers. - gates for the arena; ArenaExpertSource::blob_at() reads a blob from the job thread without the read counter - the evicted slot is marked non-resident and uploaded before the round's copies are posted; an expert becomes resident only once its copy's event has completed - STRATA_ADAPT_ASYNC_WAIT=1 (arena default): the next tick waits for the round, so the window an expert turns GPU-resident does not depend on timing; STRATA_ADAPT_PICK_INLINE=1 (arena default): one round per window; STRATA_ADAPT_ASYNC_BATCH=N caps the copies per tick (default 0 = all); arena rounds are not capped at 96 - adapt_quiesce(): every K/V grow, kv_quiesce and the VRAM command land the round in flight (they only called apply_pending(true)); a failed round still drains its copies. This also covers the resident mode's async tier. - STRATA_DECODE_TIMING: "adapt wait X join Y, Z swaps/window"; --adapt-async help text RTX 3090 + Ryzen 5 5600X, cold prompts: x1.07-1.11 decode, faster on 12 of 12 prompts; 25.9 -> 21.6 ms per window (bench/results/2026-10-11-community-rtx3090-5600x-arena-async, docs/DETAILS.md). Opt-in (--adapt-async 1, default 0); the default path is that of v0.1.42. With the tier on, answers are not bit-exact run to run (which window first computes a swapped-in expert on the GPU). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0157fjixQD2nRxvCvtXq66DD
…1905 pin by need, as opt-ins) into f-144-rel
|
Thanks for this, and for the report: the method (fresh server per arm, distinct prompts, paired, order reversed) is the one we use ourselves, and the fence fix in We ported it to the 0.1.44 branch with your authorship kept, as an opt-in ( One thing we did on top, in the combination with your other PR: |
Upstream 0.1.44: Apple Silicon (Metal), Qwen3.6 family, NVFP4 experts, K-quant pool rows (libstrata_kq), an image generation tab, prefill head alias, pin by need (Niko1221#1905) and --adapt-async in the arena (Niko1221#1904, which we carried: upstream's copy kept, ours dropped). Conflicts: - Niko1221#1822 (gate/up MMQ reading experts in place, -0.7% read time) dropped: it patched llama.cpp's mmq.cuh and does not combine with NVFP4's tails and w4a4 activations. moe_mmq.{hpp,cu} and the group gather in prefill.cpp are upstream's. - Niko1221#1368 kept: quantize_scatter for q8_1 activations, the per-row quantizer for NVFP4 w4a4. - expert_source: load_experts_gguf takes the pool range and pin by need's PadMap; pin by need only for a whole pack (a pool range keeps the packed, biased layout); generate.cpp turns it off on a pool PC. - verify.cpp: upstream's HostGraphLaunch inside our Niko1221#1120 prelaunch guard (an optional launcher: a prelaunched window has none). - iq_kernels: our IQ1_S (19) beside NVFP4 (40) and the Qwen3.6 downs. - generate.cpp: tail skip keeps from_coord and own layers beside NVFP4's default; batch graph limit is upstream's 64 for --batch-mtp and the pool worker's wide rows. - server.py / web: health has image_generation and pool_role; images and pool routes; tabs chat, images, monitor, pool, about. - the --prefill-help help text's "+~30% on" was a printf conversion (%%). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0157fjixQD2nRxvCvtXq66DD
…rena and Niko1221#1905 pin by need, as opt-ins) into f-144-rel
…-ins (Niko1221#1904 --adapt-async 1, Niko1221#1905 STRATA_PIN_BY_NEED)
Title
Issue: #1903
Summary
In the arena mode the blocking adaptive tier creates and joins a thread every verify window and the next window waits for its
copies: ~3.2 of 25.9 ms per window on this machine (the interval #1863 found outside the timing breakdown). This lets
--adapt-async 1run in the arena too. The arena holds every expert in RAM, so a round is a copy-in only: no copy back, no RAMmove, no exchange buffers. Opt-in; without
--adapt-async 1(and in the resident RAM mode, and on several GPUs) nothing changes.Cold A/B against the v0.1.42 tag (12 distinct prompts x 2 rounds, fresh server per arm and round, paired): x1.07, faster on
12 of 12 prompts (97.2 → 107.7 tok/s; x1.11 in an earlier run the same day, when the learned profile was younger and the tier
swapped more). One cold window: 25.9 → 21.6 ms, adapt wait 0.41 ms, join 0.
What changed
src/program/generate.cpp--adapt-asyncgates accept the arena (srcp == &arena_src) on one GPU; a layer split stays on the blocking tier.exchange = false, the source blob isArenaExpertSource::blob_at(),the RAM-move steps are skipped. The evicted slot is marked non-resident and
res_uploadruns before the round's copies areposted; an expert becomes resident only once its copy's event has completed.
STRATA_ADAPT_ASYNC_WAIT=1(default in the arena): the tick after a round waits for that round, so the window in which anexpert turns GPU-resident does not depend on timing.
STRATA_ADAPT_PICK_INLINE=1(default in the arena): the pick runs onthe host thread, one round per window.
STRATA_ADAPT_ASYNC_BATCH=Ncaps the copies posted per tick (default 0 = all;16 measured 16 % slower here). Arena rounds are as large as the blocking tier's (
--adapt-swaps, not capped at 96).kvg_ensure's quiesce lambdas),kv_quiesceand theVRAMcommand now land the round in flight(
adapt_quiesce) — they only calledapply_pending(true), so a swap still copying could write a slot just lent to the K/V.This also applies to the resident mode's asynchronous tier. A failed round still drains its copies before slots move.
STRATA_DECODE_TIMING=1: the serial--serveline addsadapt wait X join Y, Z swaps/window(part of fix: Complete the synchronous decode timing breakdown #1863).--adapt-asynchelp text.src/core/expert_source.cpp,include/strata/core/expert_source.hpp:ArenaExpertSource::blob_at(),blob()without theread counter (it runs on the job thread).
docs/DETAILS.md: the arena paragraph next to--adapt-async 1.bench/results/2026-10-11-community-rtx3090-5600x-arena-async/: method, numbers, raw data (sha256 of every answer), harness.How the default path was checked
STRATA_IQ_MT_MIN=1 --pcie-frac 0 --adapt-every 0), greedy, 6 prompts, two fresh v0.1.42 engines and one of this branch:on the 5 prompts that v0.1.42 reproduces between two of its own fresh engines, v0.1.42 and this branch without
--adapt-asyncgive the same answers byte for byte (sha256), with--expert-cache autoand with a fixed size. The 6thprompt differs between two runs of v0.1.42 itself in that mode on this machine.
host code in
generate.cpp/expert_source.cpp, no backend-specific path.Extra Notes
computes a swapped-in expert on the GPU). On this machine greedy answers already differ between two fresh engines of the
unpatched build (the CPU/GPU split of the misses depends on timing).
little left to swap: level with v0.1.42 at 56K and 117K tokens (95.3 / 97.3 and 97.0 / 96.1 tok/s).
to 65,536 cells during the conversation, no
ERR.🤖 Generated with Claude Code
https://claude.ai/code/session_015oFHMEgBzk7kQSqUVWoc67