Repository navigation
bench: community report, 4x RTX 3090 layer split, stock 0.1.44 against 0.1.43 with a patch series, 1 to 16 users - #2364
havok2-htwo wants to merge 1 commit into
Conversation
…t 0.1.43 with a patch series, 1 to 16 users Same-day serving comparison on one machine (4x RTX 3090 24 GB, layer split 12,25,37, Threadripper 3990X, 251 GiB RAM), Unsloth UD-IQ4_XS, 262,144-token context, text only, one run per arm: stock v0.1.44 (ed4773e, source build, 8 slots, the most it runs on this split with its default pipelined groups, without --batch-mtp) against a modified 0.1.43 with an unmerged patch series (16 slots, opt-in switches, -DSTRATA_MMQ_TAB=ON; source pinned at havok2-htwo/Strata 08830dd), each through its own serve/server.py. Aggregate output tok/s, stock / modified: 111.7 / 116.2 at 1 user, 314.4 / 399.4 at 8, 292.9 / 516.7 at 16 (short prompts), 238.1 / 406.5 at 16 with 1.2K prompts, 92.0 / 151.9 for 16 agents x 3 turns. Greedy replies byte-identical between the builds (82/82). The modified build used about 26 GiB more system RAM. v0.1.44.1 and --batch-mtp were not measured. Sanitized per-level rows, per-request reply hashes, configs, engine log excerpts, GPU samples and the scripts used. Results only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ssion and decode switches, and the 4x R9700 numbers (PR #2364 port)
…stream's new trees; the engine stays this branch's Upstream's 264 commits since 296b59d. Where both sides changed a file of the engine (src/, include/: 39 files) or CMakeLists.txt, this branch's version stays whole, and weights.cpp too (upstream's adds only STRATA_HC_REQ8's loader, which needs its header; --hc-q8 does this here). The files only upstream changed are upstream's: the GGUF reader (an all-zero compress_ratios list is a converter's placeholder, Niko1221#2396), the BF16 dequantization (the wide kernels now on by default on sm_86 too: the prompt path's dense matrices on the 3090, bitwise; prompt times unchanged), the AVX2 expert rows' exact one-token form and STRATA_PRIMARY_DEVICE's helpers (neither called here). The engine keeps its version, 0.1.43.1. Taken: - serve/: a request without sampling fields gets the model card's set for its thinking state under the config's block (Niko1221#2685; this branch's /v1/choose still reads the model's own logits); max_tokens counts the thinking (the answer keeps a quarter; "answer_room": false turns it off); Anthropic's thinking.budget_tokens is a budget too; a prompt is encoded from the last special token it shares with a recent one (Niko1221#567); a tool body is not rescanned before a closing tag; logit_bias lists normalized once; the Prometheus gauges over the window between scrapes (Niko1221#2341); a config's joined args split and its JSON errors placed (Niko1221#2267); an explicit reasoning false kept; the batch slots' turn checkpoint pick (Niko1221#2518) and STRATA_ADMIT_SHORT_FIRST. - web/: the page sends no sampling until it is changed. - setup.py, tools/, docs/, bench/results, the Metal, SYCL, HIP and Qwen3.6 trees and their tests. test_parser_call_scan declares a tool: without one this branch's parser passes the text through verbatim. Not taken (the engine files they change stay this branch's; upstream's new sources are in the tree, not built): - The cuda86 group (5a6f4ed): STRATA_QSA_ROWS, STRATA_ATTN_DAILY, STRATA_QSA_SPLIT_ATTN, STRATA_SIDE_MIXER (and its fix 477ac13), STRATA_HC_REQ8, STRATA_PROMPT_ATTN_IMMA, the grouped short-prompt gather and the cooperative top-k digit: this engine's own kernels do these (SPLIT_ATTN and SIDE_MIXER are ports of its fd23d91 and 34a35db); STRATA_B6_MMVQ_ROWS (that kernel is 1.3-3.8% of the 3090's time here); STRATA_EXPDEC, STRATA_HC_UPMIX and the once-per-token quantization of the MoE input (c675f5b): open items. 7e8485a: every KV format takes the batched window here. - The cpu group: the AVX2 router and Q5_1/Q8_0 row dots (the router runs on the GPU here, STRATA_KQ256 is off), STRATA_CPU_IQ_ALL_EXACT1 (CPUs without AVX-512), --host-core sibling and --pool-affinity measure (hybrid CPUs), the --lookup-chain cap (no such option here). - The cache group (the resident RAM mode's options, STRATA_PCIE_BALANCE, the tier's evictions under NOWAIT, the WSL K/V host copy) and fix3 (the PLE gather_batch fix Niko1221#2622: no such fast path here; the layer split's rules; the P2P probe Niko1221#2666: no peer copies here): code this engine does not have. - The conversation cache's reserve, park gain, pinned prefixes and borrowing: upstream's conversation cache is not built here (this engine has its own prompt cache; --prompt-cache-spread's and the borrowing's ideas are open items). - havok (Niko1221#2364), batch, batch-1441: batch slots, layer splits, reads beside decoding slots (one request at a time here). The pointer-table MMQ (STRATA_MMQ_TAB, STRATA_MMQ_DIRECT) and STRATA_MMQ_GROUP_SORT: open items. - sm75, rdna2, rdna34, sycl, Metal: other hardware (Niko1221#2072's split top-k and halving scorer and 6befb3d's Q6_K form: open items). The Qwen3.6 engine. Window hashes on fixed text (thinking, 1,200 tokens, --adapt-every 0, the second GPU's tier pinned) equal the previous build's on both models; the server's 862 unit tests pass (10 skipped); api_cache_test and api_stream_test pass on both models.
|
Thank you for porting the series into 0.1.45 and for the R9700 numbers. I have two follow-ups from a run on stock 0.1.45 (
In each of the three FAIL runs, the request list differs from the PASS runs by a single extra line in round 1, and that line comes from how the test counts:
In the FAIL runs, conversation A started alone on the solo path. When B arrived, A was moved into a batch slot ( Whether A starts solo in round 1 looks like the arrival race between the test's two threads. In the PASS runs the log has Suggested test fix: count one line per request, the read itself, and skip these continuation lines. A request that moves between the solo path and a slot is logged again with its prompt plus the tokens it generated so far, all of them reused but the last one (reused = prompt - 1). No real follow-up in this test reads only one token, since each new turn adds about 25 tokens: reqs = [(p, r) for p, r in reqs if r != p - 1] # drop solo<->slot continuation lines of the same request
ok = len(reqs) == 6 # was >= 6I have not re-run the changed test. Applied to the saved engine logs of these runs, the changed check passes all six stock runs and six runs of our fork's production build (MOVE on and off, three cache setups). Those six fail the current count with MOVE on and off alike: in our build A started solo in all six, so the same kind of continuation lines appear. I can send this as a small PR if you want it. Whether MOVE then deserves more than "experimental" is your call. This test is all I checked it with, and in every run it reports The merged switches on CUDA. I used the same build and arguments, with a 128 GiB / 448-slot conversation cache (
Against your R9700 table (0.1.44.1, IQ3_S, HIP; here 0.1.45, UD-IQ4_XS, CUDA), 16 slots + switches over 8 slots:
For the single-turn rows the ratios are close. The multi-turn gain is larger here. Reply identity:
In this release build Not tested: a The PR itself only carries the 0.1.44 against 0.1.43 + series comparison, which is out of date now that the code is in 0.1.45. Should I close it? |
|
Thanks for the pull request. We're resetting the tracker for 0.2.0-beta. There are more than 1,300 open issues and pull requests, too many for us to review properly, so we're closing everything that isn't being worked on right now. Closed here does not mean rejected. To reopen it takes about two minutes:
The rules are in CONTRIBUTING.md. |
This PR adds results only: the report folder
bench/results/2026-10-14-community-4x-rtx-3090-0144/and one bullet in
docs/COMMUNITY_BENCHMARKS.md. It changes no code.Hardware: 4x RTX 3090 24 GB at a 380 W limit each. PCIe: two cards at Gen3 x16, two at Gen4 x8. The rest of
the machine is a Threadripper 3990X (no AVX-512) with 251 GiB RAM and an NVMe RAID0, running Ubuntu 24.04,
driver 580.178.04 and CUDA 13.0.
Model: Unsloth UD-IQ4_XS (shards match the pins in
setup.py), with the native-experts pack and the MTP draftmade by setup. The context is 262,144 tokens with
--kv int8 --kv-resident 32768, the layer split is12,25,37,and all experts are resident in VRAM. Text only.
Configs (same day, same engine arguments, each build with its own
serve/server.py):ed4773eb, built from source with setup.py's CUDA flags. It runs 8 slots in 4 groups of 2.8 is the most 0.1.44 runs on this split with its default pipelined groups (without
--batch-mtp); with--batch-mtpand serial windows (--batch-groups 1orSTRATA_BATCH_MTP_SERIAL=1) it accepts more, which wedid not test. v0.1.44.1 (
296b59d2) came out a few hours before the run and was not measured.-DSTRATA_MMQ_TAB=ON. It runs 16 slots in 4groups of 4, with the opt-in switches listed in the README. This is the build we run in production. Source,
pinned: havok2-htwo/Strata at
08830ddf;the same commits as patches 0001-0052 in
havok2-htwo/StrataQ38FN at
4ece0caplus the last commit
08830ddf(server only).Aggregate output tok/s (stock / modified), 1 run per arm:
The greedy replies were byte-identical between the two builds for all 82 sweep requests. The README also
gives the engine's own timings:
strata serve: promptline with 1 generated token and 0 of 0 draftsLimitations:
comparison, and there both builds carry 2 rows per group-step. Even there the gap mixes the patches and switches,
the
-DSTRATA_MMQ_TAB=ONbuild option and the 0.1.43 against 0.1.44 base.--batch-mtp(also stock above 8 slots in serialwindows) and v0.1.44.1 are untested.
Two parts of the series (more than 8 slots on a layer split, and the device-to-device slot copy) would come as
separate PRs, each with its own A/B. This report does not measure either alone.
🤖 Generated with Claude Code