Compare commits

...
1014 Commits
Author SHA1 Message Date
Niko1221 477ac13cbe verify: the side-projection q8_1 interleave copies need two or more columns (STRATA_SIDE_MIXER=2 on a 1-column window threw on Q2_0 packs: the queries' branch and the GDN gate branch) 2026-10-16 22:39:03 +02:00
Niko1221 c8265fce0e tests: setup's gfx1103 / gfx1150 switch sets do not copy STRATA_TOPK_REG_MIN_BLOCKS (the gfx1151 line from #2016, measured on gfx1151 only) 2026-10-16 22:39:03 +02:00
Niko1221 e6ad6c81d7 fix(HIP compat): cudaMemcpyPeer and cudaDeviceDisablePeerAccess for the #2666 peer-copy probe (peer_experts.cpp did not compile on HIP in f-145-int) 2026-10-16 22:39:02 +02:00
Niko1221 f260925adc fix(sm75 merge): stray brace after hf() in prefill/kernels.cu (#2093 #1821 resolution) 2026-10-16 22:39:02 +02:00
Niko1221 df6262f270 Merge perf-PR group sm75 (f-145-pp-sm75) 2026-10-16 10:59:08 +02:00
Niko1221 21c579727c Merge perf-PR group rdna2 (f-145-pp-rdna2) 2026-10-16 10:54:10 +02:00
Niko1221 b277412eb1 Merge perf-PR group rdna34 (f-145-pp-rdna34) 2026-10-16 10:53:17 +02:00
Niko1221 cbc6e3d8f8 Merge perf-PR group cache (f-145-pp-cache) 2026-10-16 10:53:00 +02:00
Niko1221 2f3a5d9013 Merge perf-PR group serve (f-145-pp-serve) 2026-10-16 10:51:54 +02:00
Niko1221 da6d8d9205 Merge perf-PR group batch-1441 (f-145-pp-batch-1441) 2026-10-16 10:51:15 +02:00
Niko1221 e8b1edbcb7 Merge perf-PR group batch (f-145-pp-batch) 2026-10-16 10:49:15 +02:00
Niko1221 5a6f4ed5fb Merge perf-PR group cuda86 (f-145-pp-cuda86) 2026-10-16 10:46:42 +02:00
Niko1221 926b0bbe6d Merge perf-PR group sycl (f-145-pp-sycl) 2026-10-16 10:43:56 +02:00
Niko1221 62b7d251ae Merge perf-PR group cpu (f-145-pp-cpu) 2026-10-16 10:43:55 +02:00
Niko1221 39f3670d41 docs: STRATA_KV_HOST_REGISTER and our measurements for STRATA_EXCHANGE_ROTATE (#2042) and STRATA_PCIE_BALANCE (#1548)
#1498 pins the KV host copy with cudaHostRegister under WSL; the switch forces either order. Measurements: 5 interleaved pairs on an RTX 3060, an RTX A4000 and a Tesla P100.
2026-10-16 10:18:08 +02:00
Niko1221 7ff67fe772 docs: the #2340 / #2207 Q6_K decode kernels and their switches (STRATA_MMVQ_LARGE_GRF, STRATA_Q6_PLANAR) 2026-10-16 03:46:10 +02:00
Niko1221 9691ea2763 sycl: the planar Q6_K head kernel gets the large-GRF launch at 2-8 columns on Arc A-series (#2340 + #2207)
The planar kernel of #2340 is the wide kernel's arithmetic, but it was launched without the 256-GRF mode that #2207 gives the GGUF-layout
wide kernel, so on an Alchemist card it spilled: mmvq_bench 2560 x 248320 on an A750, 4 columns, 1.78 ms (GGUF layout, large GRF) against
15.4 ms planar, 8 columns 4.8 against 48 ms. Same rule as #2207 (STRATA_MMVQ_LARGE_GRF, default on Alchemist only), same arithmetic.
2026-10-16 03:06:25 +02:00
Niko1221 a1447b678e Merge f-145-fix3: #2622 PLE gather, #2267 config args, #2644 split share, #2637 note, #2666 P2P probe, PR #2425 opt-in 2026-10-16 02:41:38 +02:00
Niko1221 31d36db678 docs: SECOND_GPU.md - the peer tier tests peer access at start, keep headroom on both cards (#2666) 2026-10-16 02:18:30 +02:00
Niko1221 3315072467 peer experts: peer access is used only if a test copy each way arrives exact (#2666)
On 2x RTX A4000 behind a host bridge cudaDeviceCanAccessPeer says 1 and cudaDeviceEnablePeerAccess succeeds, and
cudaMemcpyPeerAsync then returns success having moved nothing (1,048,576 of 1,048,576 floats wrong in both directions
in a stand-alone test; right without peer access enabled, the driver stages it). The peer prompt path trusted it: the
peer's input rows were zeros and its results never reached the primary, the first prompt's MoE output was garbage and
the logits NaN (--peer-device 1, --peer-reserve-mib 1500..2100; STRATA_PF_PEER_COMPACT is not the cause).
PeerExperts::open now copies 64 KiB each way once after enabling access; a wrong result turns peer access off again and
takes the host route (the one STRATA_PEER_NO_P2P=1 asks for), and says so. A test that cannot run keeps the old trust.

Reported by @CaptRauti on #2666 (WDDM, 2x RTX 3060: the no-P2P route is the one they ran).
2026-10-16 01:52:55 +02:00
Niko1221 194c26881a serve: Anthropic thinking.budget_tokens is a thinking budget too; docs for the answer room and the budget; test 2026-10-16 00:44:38 +02:00
Niko1221 d0e990ba78 serve: max_tokens counts the thinking - without a budget, thinking is closed early enough to leave a quarter of the cap for the answer (cap 8192 cut the thinking off with no answer); config answer_room:false opts out; tests 2026-10-16 00:38:04 +02:00
Niko1221 e863486567 web: the page sends no sampling until the user changes it, so the server's model-card defaults apply (stored 0.6 counts as not set); test (#2685) 2026-10-15 23:34:15 +02:00
Niko1221 a8091f4d2e serve: a request with no sampling gets the model card's (thinking 1.0/0.95/20; not thinking 0.7/0.8/20 + presence 1.5; Qwen3.6 too); greedy only when asked (#2685) 2026-10-15 22:35:55 +02:00
Niko1221 45f6111fc8 docs: MULTI_GPU.md - an unequal pair under layer-split auto (#2644, measured on z440 with the speed-scale seam), STRATA_SPLIT_UNIFORM (#2418) 2026-10-15 22:03:34 +02:00
mes b884451697 Layer split auto: STRATA_SPLIT_UNIFORM=1 restores the uniform miss cost
0.1.41 scaled each stage's miss term by its probed link (0391e478);
0.1.44 scales from a 4x gap against the fastest link (9d41e18b, #2007).
On an x16+x4 dual-3090 rig (26.9 vs 6.4 GB/s, 4.2x) either rule moves
auto off the balanced placement (K=27 -> K=19/K=31): decode -4..-8%,
prefill +15..+19% at 10K / -6..-9% at 90K vs 0.1.40.x at matched
calibration. Opt-in restore next to STRATA_SPLIT_LINK_ABS, default off.
2026-10-15 20:33:15 +02:00
Niko1221 4a1ef86b0a layer split auto: STRATA_SPLIT_SPEED_SCALE scales each stage's speed, a test seam for an unequal pair on equal cards (#2644) 2026-10-15 18:50:06 +02:00
Niko1221 31340f7279 docs: STRATA_FILE_CACHE_OLD_RULE (#1752) 2026-10-15 17:45:17 +02:00
Niko1221andKevinX8 1d6fd9f97a file tier: the old room rule on the gfx906 backend (#1752), STRATA_FILE_CACHE_OLD_RULE=1/0 on any Linux build
On an MI50 ROCm queues are suspended while the kernel reclaims around the HMM-tracked arena; the cached
reads of the new rule churn the page cache.  The gfx906 backend keeps the old room >= read_bytes rule;
other HIP cards keep the current rule (the PR applied it to every HIP build).

Co-authored-by: KevinX8 <[email protected]>
2026-10-15 17:45:01 +02:00
Niko1221 b386055d52 prefill_fused_iq_test: the Q2_0 / Q2_0 pair is skipped where the device does not set it up (it is the Turing opt-in's pair only) 2026-10-15 17:08:13 +02:00
Niko1221 14038ee30c serve: an explicit --pipeline-windows 2 on two stages says when the draft layer is not on the first card (#2637)
The default takes the pipelined decode on two stages only with the draft layer on the first card (mtp_first); asked
for by hand it was taken without a word, and without mtp_first the draft chain shares the last card with its
window (2x R9700: the pipeline lost to the serial loop before 0.1.44). Recommend, never force: it stays on as
asked and a note says what it costs, why mtp_first is not on (no --mtp / --spec 2+ / draft_vocab.bin, or
STRATA_MTP_STAGE0=1 to ask for it) and how to turn it off. No default output changes.

Reported by @dinesh-chander on #2637 (closed by the reporter).
2026-10-15 16:31:46 +02:00
Niko1221 3b848837fa layer split auto: a two-GPU rig whose first pick has a tiny stage tries each card's share of the room before the three-layer rule (#2644)
On RTX 4060 Ti 16 GB + RTX 3060 12 GB (48 layers, IQ3_S) the first pick was K=2 and the #1616 retry
(every stage at least 3 layers) landed on its own edge, K=3: the 3060 ran 3 layers, 12 GB idle, 452 tok/s of
prefill against 802 at 28 layers (the prompt flows through the stages as a pipeline). For two GPUs the retry
now first asks for a placement in which each stage owns at least floor(layers x its room / all rooms) layers
(split_rules::share_floors, at least 3, trimmed to fit); the three-layer rule stays the second try and the
first pick the last, and the log says which one was taken. Nothing changes where the first pick has no
one- or two-layer stage (equal cards), and three or more GPUs keep the #1616 rule alone.

Reported by @Tworks25 on #2644, with the sweep of layer_split 12..32 (PR #2643). split_rules_test gets the
reporter's rooms (14.2 GiB and 5.50 GiB) and the identical-card and degenerate cases.
2026-10-15 16:31:45 +02:00
Niko1221 f116778bd5 #1825 qsa_select: the thread-per-head prompt scorer is on for the Turing series (STRATA_SM75_PERF=1) or STRATA_SCORES_THREAD=1, not a default elsewhere
Tesla P100 (sm_60) prompt read, interleaved 5 pairs each, thread vs warp scorer: 30000 tokens 339.29 vs 335.45 tok/s (1.011) and 338.98 vs 330.20 (1.027), 60000 tokens 338.88 vs 330.15 (1.026), 5/5 pairs faster each, below the +3% bar for a new default. Same bits either way. docs line; qsa_scores_parity runs with the switch on.
2026-10-15 15:25:10 +02:00
Niko1221 b6443f3ae0 moe_fused_iq: #2145's Q2_0 gate/up fused coverage is the Turing opt-in's only (sm_80+ with STRATA_PF_FUSED=1 is bit-identical to base again)
The z440 A4000 Q2_0 gate with STRATA_PF_FUSED=1 on both arms found the residual dump different from base: gu_covered() took Q2_0 on every CUDA card and d.ok on sm_80+ now required the Q2_0 gate/up setup.
2026-10-15 15:21:02 +02:00
Niko1221 83426781d9 Revert #2223 (STRATA_NO_PCIE_GROUP=1): no gain measured on our boxes
Interleaved A/B, 6 pairs, --pcie-frac 0 vs --pcie-frac 0 + the switch, decode ALL: RTX 3060 IQ3_XXS 53.36 vs 53.16 tok/s (0.996, 3/6 pairs faster); RTX A4000 Q2_0 61.72 vs 62.17 (1.007, 4/6). The author's own +2.2% is below our +3% bar and does not reproduce on Ampere. Declined; the PR author's commit stays in the history only as this revert's parent.
2026-10-15 15:20:52 +02:00
Niko1221 8101a8903b serve: an engine option written as one entry of the config's args is split, a JSON slip is said with its place (#2267)
"--ple-io mmap" as ONE element of "args" (or "--ple-io=mmap") reached the engine as a single
argument, which it stops on ("unknown argument: --ple-io mmap"); the usual form is two entries.
The server now splits such an element into the flag and its value and says so at startup
(never one in a flag's value place). A config with a JSON mistake (a missing comma between two
args) gave a traceback; it now names the file, line and column. The slow-PLE-probe warning says
how the two entries are written in a config. --ple-io mmap, ram and direct themselves parse
correctly in the engine (checked on the 0.1.45 build).

Reported by lama7 on #2267.
2026-10-15 15:04:33 +02:00
Niko1221 36381540f9 ple: gather_batch reuses prefetched keys that were reordered or duplicated (#2622)
PleTable::gather_batch matched the Direct-mode prefetch slots by position, so rows
prefetched as A..F and gathered as D,E,F,A,B,C (or A gathered as A,A,A) were read a
second time. Each requested token now looks its key up among the prefetch slots and
decodes from the matching slot into its own output position; duplicates share a slot.
All outstanding tickets are drained on a failed collect (the first error is kept)
instead of dropping the rest. The decoded bytes are unchanged.

Reported by @hotschmoe, who also supplied the fixture and the patch; the patch is
used as proposed. ple_reader_test --selftest gets the reorder / duplicate / subset /
missing / over-the-window cases, compared against the mapped reader.
2026-10-15 14:59:12 +02:00
Niko1221 2016b7fe01 sycl: the migrated Gemm::bf16 / gr_norm* definitions take #2091's new parameters (the shared headers changed; SYCL never uses the FP16 image)
The SYCL build of the sm_75 series failed with 'out-of-line definition of bf16 does not match any declaration'
(sycl/src/prefill/gemm.dp.cpp); the four gr_* writers would have failed at link. Gemm::bf16_converts_x() answers false.
2026-10-15 09:52:43 +02:00
Niko1221 bcef7b7818 moe_fused_iq: #2145's host_astages() also for HIP (the shared launch() calls it; the HIP build of #2145 as submitted did not compile) 2026-10-15 08:53:39 +02:00
Niko1221andc3c 285e90aee2 qsa_prompt_attn: Q4_0 KV prompt attention on Turing, opt-in STRATA_PROMPT_ATTN_Q4_TC=1 (#1581, the Q4 attention part only)
Ported from c3c's #1581 (the native-IQ and VRAM-loan parts are not in this commit).  Default unchanged: Turing keeps returning false for q4_0.

Co-authored-by: c3c <[email protected]>
2026-10-15 08:53:32 +02:00
Niko1221 7f8e6f12f4 docs: the Turing (sm_75) kernel series and its switches (STRATA_SM75_PERF) 2026-10-15 08:53:32 +02:00
Niko1221 b30d09cb98 moe_fused, moe_fused_iq: the Turing opt-in (#2145) reads the compute capability through STRATA_EMULATE_CC like the other kernels 2026-10-15 08:53:32 +02:00
Niko1221 0639deff7d qsa_prompt_attn: #1821's register prefetch and shared K/V buffer are a template flag, on with STRATA_SM75_PERF=1 or STRATA_PA_V1_PREFETCH=1
The v1 kernel keeps its exact previous code (and 37.9 KB of shared memory) unless the flag is set.  launch_i8 picks the Turing
single-stage layout by the (emulated) compute capability, so the kernel and the launch agree under STRATA_EMULATE_CC.
2026-10-15 08:53:32 +02:00
Niko1221 7f1964a6cb sm_75 series: the bitwise Turing kernels (#2069-#2072 #2081 #2093 #2220-#2222) are opt-in with STRATA_SM75_PERF=1
No sm_75 card is available here to confirm the series, so the kernels that were on by default for compute capability 7.5
in the submitted PRs now follow one switch, include/strata/core/sm75_series.hpp.  Each keeps its own variable, which
wins in both directions.  The one-read prompt top-k (#2093) was on for every CUDA card as submitted; it is now Turing only
like the rest.  STRATA_EMULATE_CC=75 counts as a Turing card, so a 75-virtual build on an sm_86 GPU runs the series for tests.
2026-10-15 08:53:32 +02:00
xrip 6e76ae23fd #1825 qsa_select: four lanes per query in the Turing prompt scorer (4x fewer shared loads)
block_scores_thread_kernel gave a lane one (query, head) and the whole
128-value query head; ncu on a CMP 50HX showed it bound by the MIO pipe
(mio_throttle first): one shared-memory key load per 4 FMAs. Lane 0's
xor-shuffle tree splits into four independent quarters - c[j] sums groups j,
j+16, j+8, j+24, j+4, j+20, j+12, j+28 - which only meet at the end
(c0 + c2, c1 + c3, then their sum). Now four lanes share a query, lane j
holds quarter j of all four heads, a key load feeds four heads (16 FMAs),
and two xor shuffles finish the same tree. The same pairs in the same order,
so the same bits.

qsa_scores_parity on both cards: all 141 M scores identical to
block_scores_kernel; per call 1,024 queries at 140K 7.76 -> 6.17 ms (-20 %),
at 200K 10.78 -> 8.54 ms (-21 %), 2,048 queries at 40K 12.60 -> 11.57 ms.
agentbench 34K -> 190K: AGENT GATE PASS on the rerun (the first run diverged
at turn 2 - decode's known run-to-run variation; the rerun of the same binary
matched all 36 turns), incremental read -0.6 % median, about -1 % from 150K
up, decode unchanged.
2026-10-15 08:53:32 +02:00
xrip 33237ff367 #1825 qsa_select: prompt-path block scores with a thread per query head (Turing)
On cards without the TF32 scorer (sm_75) the prompt path scored every
(query, key block) with a whole warp: 20 shuffles and five 512-byte loads per
score. block_scores_thread_kernel gives each lane one (query, head), keeps the
128-float query head in registers, reads each key once from shared memory as
a broadcast, and adds the 32 four-value partials in the tree lane 0 of the
xor-shuffle sum computes. Float addition is commutative, so the same pairs in
the same tree give the same bits; the heads are summed 0..3 from 0.0f as
before; the tail block keeps block_scores_tail_kernel. STRATA_SCORES_THREAD=0
selects the old kernel.

Measured on 2x CMP 50HX (TU102, sm_75, unlocked to RTX 2080 clocks):
- qsa_scores_parity (new): 141 M scores bitwise identical on both cards
  (normal values, wide magnitudes with zeros, small integers with ties);
  per call 4.6-5.2x faster, e.g. 1,024 queries at 200K: 52.4 -> 10.8 ms,
  at 140K: 35.9 -> 7.8 ms. 199 registers, no spills.
- nsys, one +4.4K-token turn at 140K: block_scores_kernel was the top prompt
  kernel at 1,045 ms per card (17 %).
- agentbench, IQ3_XXS, layer split, 262144 context, 34K -> 190K (with the
  tokenizer cache): engine read per turn at 190K 9.25 -> 6.96 s (476 -> 632
  tok/s, +33 %), time to first token 10.49 -> 7.13 s (-32 %); median
  incremental read 576 -> 682 tok/s; decode unchanged (73.3 tok/s).
  AGENT GATE: all 36 turns word-for-word identical to the base run.
2026-10-15 08:53:32 +02:00
xrip 1d5319ae88 #1821 qsa_prompt_attn: int8 K/V prefetched in registers and sharing one buffer (Turing)
The Turing (v1) prompt attention kernel used 37.9 KB of shared memory per
128-thread block, so one block ran per SM (4 warps, 12.5 % of the warps an
SM can hold), and each 32-cell chunk gathered its scattered K and V rows
after the previous chunk had finished: ncu on a CMP 50HX showed
long_scoreboard (global load latency) as the top stall. For int8 K/V
(--kv int8, mode 1):
- the next chunk's K/V rows and scales are loaded into registers while the
  current chunk computes (Turing has no cp.async), then stored where the
  gather stored them;
- K is read only by the scores and V only by p.v, so they share one buffer:
  V is written over K after the scores' barrier (the softmax's barrier
  orders it before p.v). 37.9 -> 29.2 KB: two blocks per SM.
The same bytes in the same places and the same arithmetic, so the same bits.
Other KV modes keep their code. qsa_prompt_attn_parity now prints a checksum
of the new kernel's output, so two builds compare bitwise.

Measured on a CMP 50HX (sm_75), qsa_prompt_attn_parity, 2,048 queries:
int8 21.45 -> 12.91 ms at 40K (-40 %), 21.94 -> 13.31 ms at 140K (-39 %);
all output checksums (int8 and fp16, 4K/40K/140K) identical to the previous
kernel. agentbench 34K -> 190K (IQ3_XXS, layer split, 2x CMP 50HX): AGENT
GATE PASS (36 turns identical), incremental prompt read time -3.5 % (median
per-turn ratio 0.965), decode unchanged.
2026-10-15 08:53:32 +02:00
Rafa e3b3ba1c66 #2223 verify: STRATA_NO_PCIE_GROUP=1 drops the empty PCIe-share stage
With --pcie-frac 0 the pool never plans PCIe experts, yet every layer of a
verify window still runs the flag B wait, the staging copy and the grouped
launch over zero groups: six kernels, ~18 us a layer on an RTX 2080 Ti
(kernel-node nsys). STRATA_NO_PCIE_GROUP=1 records the window graph without
them; a plan with PCIe experts then stops the engine with a message.

Engine A/B on an RTX 2080 Ti (Flash-Next Q2_0, 512 tokens, two runs each, with the open sm_75
decode PRs applied): Spanish chat 87.8 -> 89.8 t/s, code 106.1 -> 108.5,
32K 78.4 -> 80.1, 128K 75.0 -> 76.8, 390K 74.7 -> 75.1.
2026-10-15 08:53:32 +02:00
Rafa 88a1c23f61 #2222 sm_75: two launches fewer per decode layer (bitwise)
Two kernel pairs of a verify window's layer run as one launch on Turing,
every byte as before:

- the plan's host-flag wait folded into its copy (143-amdk's
  wait_copy_i32_from_mapped, gfx12-only until now). STRATA_FUSE_WAIT on
  CUDA: 2 = the plan only (Turing default), 1 = also the CPU rows'
  copy_rows_from_mapped_after, which makes every row block poll the flag
  over PCIe and was -1.5 % on an RTX 2080 Ti, 0 = neither.
- native_quantize_q8_1_il: a projection input's q8_1 blocks and their
  interleaved copy (native_q8_1_interleave) in one kernel; an int of the
  copy is four codes gathered with two shuffles. Used for the GDN qkv and
  out-projection inputs and the QSA input and out-projection. STRATA_QIL=0 / 1
  forces it off / on (Turing default on).

RTX 2080 Ti, Flash-Next Q2_0, 512 tokens, two runs each: the plan fold
+0.6..+1.4 % decode, the fused quantize another +0.5..+1 % (code 108.0 ->
109.1 t/s). The fused quantize writes the same bytes as quantize +
interleave at 2560/6144/10240 inputs and 2-4 columns.
2026-10-15 08:53:32 +02:00
Rafa bd45500839 #2221 sm_75: Q2_0 matvec with one warp per four rows (bitwise)
The exact layout gives each Q2_0 row four warps, a half block per thread and a
cross-warp reduction. At the engine's 2560 inputs (40 blocks a row) 48 of the
128 threads have no chunk and the reduction dominates: the QSA attn_q
projection (2560x12288) at three columns took 80 us (~110 GB/s) on an
RTX 2080 Ti.

q2_0_warp_rows_kernel: lane l runs the chunks of the exact kernel's threads
l, 32+l, 64+l and 96+l in their loop order, adds the four sums as warp 0 adds
the other warps' partials, then the same warp_sum - every output is bit for
bit native_q2_0_mmvq_kernel's (one column) and launch_multi's exact layout
(two to four). 1/2/3/4 columns: 36.6/60/68/88 -> 24.8/31/31/37 us.

Default on sm_75 only; STRATA_Q2_WARP=0 keeps the old kernels, =1 takes this
one on any CUDA card.
2026-10-15 08:53:32 +02:00
Rafa 996b9f84f1 #2220 sm_75: QSA decode attention v3 for INT8 pools (bitwise)
attn_chunk_kernel<1> saturates the SM's shared-memory pipe on Turing: its
time grew linearly with the queries while the SMs were half empty (two
16-byte q reads per head per cell with a two-way bank conflict, and 12
warp_sums = 60 shuffles per cell).

attn_chunk_q8_v3_kernel computes the same operations in the same order:
  - the lane's slice of the 12 query heads is read into registers once;
  - the 12 lane sums are reduced with reduce12_gfx906 (16 shuffles, every
    sum warp_sum's pairs);
  - the probabilities are stored cell-major, so the value loop reads a
    cell's 12 as three 16-byte broadcasts.

RTX 2080 Ti, with the merge: 2051 selected cells, 1-4 queries
51.6/78.5/110/146 -> 34.5/41.0/73.0/84.9 us; 600 cells
45.9/74.6/105/137 -> 28.6/32.8/33.5/33.3 us. qsa_prompt_attn_parity
reports the same errors with STRATA_ATTN_V3=0 and 1.

Default on sm_75 only; STRATA_ATTN_V3=0 keeps the default kernel, =1 takes
this one on any CUDA card.
2026-10-15 08:53:32 +02:00
Rafa 9512b9c84b #2145 prefill: fused int8 experts on Turing (sm_75), opt-in
The fused prompt-expert kernels (moe_fused.cu for the Strata Q2_0 pack,
moe_fused_iq.cu native_kernel for the native packs) on sm_75, with
STRATA_PF_FUSED=1 STRATA_PF_FUSED_SM75=1:

- cp.async -> plain 16-byte copies (the barriers around them stay),
  prefetch.global.L2 kept;
- mma m16n8k32 / m16n8k16 s8 -> four / two m8n8k16 (exact int32 sums,
  the same d as the sm_80 instructions), MAGIC as the C operand;
- two activation stages on Turing (64 KB of shared memory);
- native_kernel takes Q2_0 gate/up (64-value blocks, a block per stage),
  so the canonical Q2_0 pack (Q2_0 / Q2_0 layers) runs fused; on Turing
  only that pair is set up;
- Turing, Q2_0: the two halves of a stage share the weight scale, so a
  row's dot is d (dx_0 dot_0 + dx_1 dot_1) - 11 % fewer instructions.

RTX 2080 Ti, one layer, 512 experts top 10 (prefill_fused_iq_test,
Q2_0 / Q2_0 pair added): 2048 tokens MMQ 12.98 ms -> fused 6.59 ms,
16384 tokens 55.08 -> 37.16 ms; fused vs MMQ rel RMS 2e-5, the same
error against the FP32 reference.  In the engine (canonical Q2_0 pack,
98K prompt, 16K chunks): prefill 58.3 -> 53.3 s; layer 0 expert rows vs
MMQ: median rel 1.6e-7.  Teacher-forced 2048 tokens at P = 16K / 32K /
64K: perplexity vs MMQ +3.4 % / -4.5 % / +0.6 % (FP16 path vs MMQ
+0.7 % / +0.1 % / +0.3 %) - trajectory noise, no systematic shift; the
verify phase (same tokens) 42.36 s MMQ, 42.28 s fused.
2026-10-15 08:53:32 +02:00
Niko1221 5333327bd5 metal: wrap_split_test: the note's newline 2026-10-15 07:02:42 +02:00
Niko1221 3ef8d7a09f metal: wrap_split_test reports run_icb instead of counting it (a bench path that misreads at some offsets of a single buffer too) 2026-10-15 07:02:42 +02:00
Niko1221 a35ac34944 metal: wrap_split_test also runs with --factor <= 1 (one buffer) as a control 2026-10-15 07:02:42 +02:00
Niko1221 38978a6dfd metal: wrap_split_test - a sparse file longer than maxBufferLength, wrapped in chunks, read at every chunk boundary (#2338) 2026-10-15 07:02:42 +02:00
hokar3361 8b3ec44b1d metal: wrap a model bigger than maxBufferLength as overlapping no-copy buffers (64 GB Macs keep IQ3_XXS resident); MoE kernels bound per layer 2026-10-15 07:02:42 +02:00
Niko1221andBlueKingMuch 2b296987b9 conversation cache: a match that reaches a pin=N prefix is taken instead of borrowed (#1164)
A borrow copies the donor's checkpoints up to the match, so a match that reached a pinned shared prefix gave the borrower the pin too. Such a match now takes the conversation as before. The borrow's guard is guard()/unguard()/guard_blocked(), and the refusal before evicting counts the pinned conversations along with the donor.

Rebased by hand onto 0.1.44.1 (evict_oldest() honours the guarded donor).

Co-authored-by: BlueKingMuch <[email protected]>
2026-10-15 07:02:42 +02:00
Niko1221andBlueKingMuch c9e571e057 serve: a new conversation that starts with a checkpoint of a parked one borrows it, the parked conversation stays (#1164)
Sibling subagents with the same system prompt and tools no longer cost each other their history: only the K/V up to the checkpoint and the checkpoint itself are copied into the session (conversation_snapshot_restore_prefix); the parked conversation stays where it is and is pinned while the outgoing one parks. A match on a parked conversation's live state or newest checkpoint is that conversation going on and is taken as before.

Rebased onto 0.1.44.1 by hand: the pinned shared prefix (#879) and evict_oldest() now also skip the borrowed donor, serials follow every erase, and park-gain (#2265) and the pin= sibling rule gate the outgoing park.

Co-authored-by: BlueKingMuch <[email protected]>
2026-10-15 07:02:42 +02:00
Niko1221 04e3481b99 docs: --conversation-cache-park-gain (#2265) 2026-10-15 07:02:42 +02:00
Niko1221 3d99819e38 setup: the engine builds pin -DSTRATA_MMQ_KQUANTS=ON too (465cd61d flipped it with STRATA_Q6K_EXPERTS, and a stale CMakeCache.txt keeps the old OFF the same way; found by qiuzan2001 on #2515) 2026-10-15 06:22:32 +02:00
Niko1221 dd08a7d0ec serve: pick_slot sends a chat's next turn to the slot that holds it, found by its turn checkpoint (#2518)
A client renders the history again for its next turn, without the reply the slot decoded or the assistant header,
so the slot's held stream (prompt + reply) is no start of the new prompt and pick_slot fell back to the least
recently used slot. With two chats in two slots and two next turns arriving together, whichever was read first
could take the other chat's slot, and the engine's slot copy then overwrote the cache the second turn needed
(0 tokens reused, a full prompt read). pick_slot now also counts the held tokens up to the last <|im_start|>
(where the engine takes its turn checkpoint) when the prompt agrees with them, and a pipelined layer split with one
slot per group (--batch 2 on two cards) no longer ignores what its slots hold.
2026-10-15 05:59:33 +02:00
Niko1221 c2215a2af3 docs/DETAILS.md: the elastic encoder at 196K context 2026-10-15 05:59:13 +02:00
Niko1221 5d83130cdb setup: the HIP engine build pins -DSTRATA_Q6K_EXPERTS=ON too (the same stale CMake cache as #2515 for the CUDA build); the CUDA configure line is tested (tools/test_setup_stale_stamp.py) 2026-10-15 05:59:13 +02:00
xrip a7d4b75443 serve: --prompt-cache-spread, checkpoints kept spread back from the conversation's end (opt-in)
Least recent use keeps the newest checkpoints and every turn adds one, so after a few short turns all 6 sit in the
last 1-2K tokens. An agent client that rewrites its history a few thousand tokens back then resumes from the system
prompt: on 2x CMP 50HX with the pi coding agent a 210,528-token prompt that was the same as the session for 204,349
tokens resumed at 9,525 and read 201,003 again (100 s).

With the flag the victim is the checkpoint whose removal leaves the smallest gap for its distance from the newest, so
the kept points thin out geometrically: after 200 turns of 1,000 tokens they sit 0, 1K, 3K, 8K, 43K and 200K before
the end, and an edit 6K back reads 8K again (least recent use: 200K), 42K back 43K. The same number of checkpoints, no
more RAM; never the root, the newest or a pinned one, the tail rule first, the plain policy without a candidate. The
resume is the usual exact-prefix match.

On the box: an 82,593-token conversation grown turn by turn, a turn ~6 steps back rewritten, resumed at 73,610 tokens
in 10.2 s against 40.0 s read in full; with the expert placement fixed (--adapt-swaps 0, --pcie-frac 0.17) the
greedy answer was the same text as the full read. conv_cache_test: the spread cases (a 200-turn simulation against
least recent use, the fallbacks). docs/DETAILS.md: a paragraph after the prompt cache's options.
2026-10-15 05:42:53 +02:00
Krypto-Whitehat d9cb22d287 Conversation cache: --conversation-cache-park-gain N stops a turn that grew a few hundred tokens from rewriting a whole snapshot (RTX 5090 Laptop, IQ3_XXS: 1,418 parks -> 1, 2,251.9 GB -> 3.26 GB host copy at 4.7 % read back; decode -3.4 %, inside the run-to-run spread)
A conversation that only advanced a few hundred tokens since its last park does not need a fresh 3 GB copy: the entry it would supersede still holds this conversation's prefix, and the next turn drops the copy anyway (drop_superseded). Reported in #2264 over 1,418 park events on one long single conversation.

The flag is opt-in and defaults to 0, which parks every turn exactly as before. What this adds is a way to ask for the gate without a rebuild: on the reporter's rig it is 3.26 GB instead of 9.79 GB per benchmark, the superseded class disappears, and the decode median moves -3.4 %, inside that arm's 92.2-124.1 tok/s spread.

parked_prefix_tokens() reports exactly the entries drop_superseded() would remove - it finds them the same way, by the deepest checkpoint the outgoing chain still holds - so the gate cannot name a different entry than the park would drop. conversation_cache_test covers it (7 checks; 4,226 pass).

Fixes #2264
2026-10-15 05:42:53 +02:00
BlueKingMuch 53f72571fb conversation cache: a conversation parked again keeps at most an eighth of each K/V buffer in reserve (was up to 16 MiB per buffer, 0.4-0.5 GB per conversation)
A conversation that was restored and is parked again keeps its unchanged K/V
pages and appends the new ones (92a3d5f). The appended segment reserved room
for later turns, growing geometrically up to 16 MiB - per buffer, and a parked
image has one per K/V layer and part (k, v, their scales, the indexer rows, the
draft layer). With Qwen3.8-Flash-Next (IQ3_S, int8 K/V) a 32K-token main agent
parked again took 1.49 GB instead of 0.97 GB, a 17K-token subagent 1.16 GB
instead of 0.74 GB. The cache counts that capacity against its budget, so with
2816 MiB the reserve decides which conversations are evicted.

The reserve is now at most an eighth of what the buffer held before the append
(at least 64 KiB, and at most 16 MiB as before). Small turns still fill the
reserve instead of adding a transfer each: the 4096-append test keeps its
segment bound, and 256 turns of 1 MiB onto a 16 MiB buffer take 28 segments
(17 before).

The docs said parking falls back to a full capture when the reserve would evict
another conversation; that check went in 6cd29d9. With the reserve bounded the
two captures differ by at most an eighth of the K/V, and the docs now say what
the reserve is.
2026-10-15 05:42:52 +02:00
qni-live b6dac80740 logit_bias: normalize a long list once per request instead of five times
A standing ban of a whole script (65,929 IDs) was normalized five times per request: in _openai, twice in
validate_request and twice in engine_key. About 200 ms of Python per request, whatever the answer length.

A list is now normalized once. The same object again in a request is answered from the last call; an equal list in
a later request is found by its compact JSON text, which tells False from 0 and "1" from 1 (== does not: [[7, False]]
== [[7, 0]]). Only a list that normalized without an error is stored. Lists under 64 entries skip the cache.
No change to what normalize, engine_key and validate_request return or raise.
2026-10-15 05:41:36 +02:00
f13a870d52 serve: tokenise the prompt from the last shared prefix, not from the start (#1852, #567)
PromptEncoder keeps the last prompts with their ids and resume points (one per
conversation-cache slot) and encodes only the text after the longest shared
special-token boundary; the ids equal a full encode. Rebased onto 0.1.44.1
(prepare() keeps the new `cancel` argument; forget_prompt on a context refusal;
count_tokens reads without storing). SECURITY.md notes the in-memory prompts.

Based on gputier's #1852 (8 commits) and blange48's #567.

Co-authored-by: Guillaume PUTIER <[email protected]>
Co-authored-by: benoit lange <[email protected]>
2026-10-15 05:41:24 +02:00
Niko1221 40a6220f24 docs: DEQUANT_WIDE on sm_86 also measured on the RTX A4000 2026-10-15 05:11:05 +02:00
Niko1221 abce866ebe docs: the CUDA opt-in switches ported for 0.1.45 (#2058 #2059 #2075 #1888 #1889 #1418 #1370 #1367 #1262 #1368 #1107), measured on sm_86; STRATA_DEQUANT_WIDE default on sm_86 2026-10-15 04:10:19 +02:00
Niko1221 5f843a926f dequant: the wide kernels (STRATA_DEQUANT_WIDE) are on by default on sm_86 too
Bit-identical (gate: 10/10 + exact_pp 4K/20K IDENTICAL with STRATA_DEQUANT_WIDE=1 on the RTX 3060 and the RTX A4000), and the time
to the first token of a 150 / 300 / 450-token prompt falls 12-20% on the RTX 3060 (5 of 5 pairs each), the prompt read +2.3%.
STRATA_DEQUANT_WIDE=0 turns it off. Arch-gated to the measured sm_86 and sm_61. Follow-up to #2178 (Techannel), the kernels this switches on;
the same stores are what #1525 (sergqwer) proposes for Q8_0 / IQ4_XS.
2026-10-15 02:38:49 +02:00
p3lusa 2783569494 setup: pin -DSTRATA_Q6K_EXPERTS=ON in the CUDA engine build
A build folder configured while the option's default was OFF keeps
STRATA_Q6K_EXPERTS=OFF in its CMakeCache.txt even after the default
flipped to ON (465cd61d): CMake does not rewrite an option already in
the cache, and source_hash() fingerprints the source files but not the
CMake option values, so setup recompiles the engine with the Q6_K
gate/up expert kernels still disabled. A model whose routed experts are
Q4_K/Q6_K (Unsloth UD-Q4_K_XL) then fails to load with:

  strata-q36: blk.34.experts are Q4_K/Q6_K, which the native expert
  kernels do not take (build with -DSTRATA_Q6K_EXPERTS=ON for Q6_K)

Passing -DSTRATA_Q6K_EXPERTS=ON explicitly overrides the stale cache
entry, so the engine always has the kernels its default build promises.
Same pin in the Dockerfile build for consistency. Not hardware-specific:
it is a CMake cache-staleness issue, independent of GPU/platform.
2026-10-15 02:29:55 +02:00
Niko1221 c8cab03503 docs/DETAILS.md: the image encoder on 16 GB cards, measured (#2406) 2026-10-15 01:13:31 +02:00
Niko1221 df44bcb712 Merge f-145-havok (#2364 multi-user series, opt-in) 2026-10-15 01:11:37 +02:00
Niko1221 45752724d9 setup: Flash-Next images 'yes' gets the CPU encoder on an NVIDIA card under 24 GB, --vision gpu kept with a note (#2406: the GPU encoder cost 3-5% of text speed on 16 GB cards, 35-60% on an RTX 4080 SUPER under Windows as reported); goldens re-recorded for the two 16 GB Unsloth configs 2026-10-15 01:11:37 +02:00
Niko1221 0408f0921c Merge f-145-q36speed (Qwen3.6 speed: decode/prompt kernels, bigger prompt chunk by default) 2026-10-14 22:23:29 +02:00
Niko1221 bb90c106b6 docs/QWEN36.md: speed section (kernels, measured R9700 / RTX 3060 numbers, the prompt chunk default and its KL, what was dropped) 2026-10-14 22:04:58 +02:00
Niko1221 7e8485a48b verify: a Q4_0 KV cache takes the batched verify window by default (STRATA_DF_QB_Q4=0 for the old path): the 6-token graph is 1950 nodes, not 2610, ids identical; + kv_window_parity test (#2403: a gfx1030 fault with q4_0 + KV streaming + MTP, not reproduced; cause unconfirmed) 2026-10-14 21:55:16 +02:00
Niko1221 8e2c70a132 metal: STRATA_QSA_SLOTS launchers decline (no Metal kernel); the shared verify.cpp links again 2026-10-14 21:42:05 +02:00
Niko1221 79e5cd1827 docs/BATCHING.md: more than 8 slots on a layer split, the opt-in admission and decode switches, and the 4x R9700 numbers (PR #2364 port) 2026-10-14 21:40:11 +02:00
Niko1221 f755a06d7c #2234 follow-up: the rows attention runs the default kernel's body from its own kernel (the default kernel's signature, and the pre-sm_75 / HIP function-pointer selections, stay as they were: HIP did not build); per-row calls where the per-row path runs a variant (lane-cell, pre-sm_75, gfx906)
batch_rows_parity also checks the one top-k launch over all rows against one call per row.
2026-10-14 21:38:26 +02:00
Niko1221 a08db82dbd Version 0.1.45: project version, Metal string and the setup minimum engine 2026-10-14 21:38:21 +02:00
Niko1221 55bae973fb qwen35: the prompt delta rule takes two barriers per token instead of three
The output sum of token t is done after token t + 1's first barrier (sk / sq double-buffered), off the recurrence's chain. Same arithmetic: the
3000-token prompt's logits and 8 greedy steps are bit-identical to the base engine at chunk 512 and 2048 (R9700: 913 -> 885 ms, 607 -> 573 ms).
2026-10-14 21:38:07 +02:00
Niko1221 4b348ad4b8 docs/QWEN36.md: the P100 row 2026-10-14 21:38:01 +02:00
Niko1221 34db47a8e1 setup: Qwen3.6 --parallel on small cards follows the measured cost (the slots may take 35% of the experts' room; 12 GB at 8K: 4, 16 GB at 32K: 2), and the text says the gain against one-at-a-time with drafts is small 2026-10-14 21:37:45 +02:00
Niko1221 e79156ae2e Merge f-145-q36 (Qwen3.6 start that cannot fit its buffers says so; vision_cmp --dump-ngl) 2026-10-14 21:36:20 +02:00
InB4DevOps fc27296dee serve: skip tool-body rescans until a closing tag arrives 2026-10-14 12:49:34 +02:00
InB4DevOps b145a4a2d6 serve: avoid exhaustive partial-tag suffix checks 2026-10-14 12:49:26 +02:00
Niko1221 c2947a9230 q36 engine: a hybrid start that cannot fit its buffers says so with the numbers
With many slots on a small card (8 sessions on a 12 GB RTX 3060, UD-Q6_K_XL) the sessions left too little VRAM for the hybrid
mode's staging pair, CPU-output buffer and expert slots, and the start died in a bare cudaMalloc failure. place_experts now adds
up what it is about to allocate and exits 1 with "not enough VRAM left for the hybrid experts' buffers and slots (N MiB needed,
M MiB free ...)" and the way out (fewer slots, a shorter --max-context, fewer --expert-slots). Only a start that would have
crashed changes; the placement and every answer are as before.

tools/qwen35/q36_vram_refusal.py: demanding starts (8 slots, long contexts, every expert as a slot) must reach READY or exit 1
with one of the engine's refusals, never a raw allocation failure.
2026-10-14 12:33:29 +02:00
Niko1221 739bc94881 tests: batch_rows_parity, #2234's one-launch kernels against the per-row launches (scores, decode attention, GDN window and commit), bitwise 2026-10-14 12:26:10 +02:00
bsvinay cbc1578a2f layer split overlap: off beside --pipeline-windows (#859)
--pipeline-windows runs its own overlapped decode loop with its own hand-offs, so
STRATA_SPLIT_OVERLAP now switches itself off when it is set (one log line says so).

Rebased onto main 1735d64: the early launch of the next stage keeps #871's graph
variant (the next stage's refresh_ar() runs before its capture and prelaunch, and
not again in its run() when it was prelaunched), resets the plan error word like
run()'s launch, and the chain path checks that word after its sync as well.
2026-10-14 12:26:10 +02:00
bsvinay 090b8e9f13 layer split overlap: the hand-off publish reads the test word only with STRATA_TEST_HANDOFF_DROP set
Without the hook the window graph passes no word, so the publish kernel does no
extra read of mapped memory per window.
2026-10-14 12:26:10 +02:00
bsvinay 2443c9225c layer split overlap: bound the GPU-side hand-off wait (STRATA_SPLIT_WAIT_MS)
Review on #936 (justxiami): the reading stage's wait_flag_ge spun with no bound,
so a lost publish would leave that stream spinning.

- wait_handoff: the reading stage's graph now waits with a bound (default 30 s,
  STRATA_SPLIT_WAIT_MS, 0 = unbounded, GPU clock as in gpu_stamp). On timeout it
  sets a mapped error word and returns, so the graph completes; the host checks
  the word after the window and fails it with an error that names the setting,
  instead of using a stale hand-off.
- The host's per-layer wait (20 s, #267) still normally ends a stalled window
  first; release_gpu_waits already raises the hand-in flag.
- Test hook STRATA_TEST_HANDOFF_DROP=N: the first stage's N-th window withholds
  its flag (a lost publish), to exercise both paths.

Only active with STRATA_SPLIT_OVERLAP=1; the default path is unchanged.
2026-10-14 12:26:10 +02:00
Niko1221andbsvinay 56146c4c49 layer split: overlap the stages' hand-off (STRATA_SPLIT_OVERLAP=1, opt-in)
Each verify window of a layer split runs its stages strictly in turn: stage 1 finishes, the host syncs its stream,
then stages and launches stage 2's graph. Under HIP the sync and the graph launch both sit on the critical path of
every window.

With STRATA_SPLIT_OVERLAP=1 the hand-off carries a ready word (mapped, one per hand-off buffer):
- the writing stage's graph ends with handoff_publish: the payload with volatile stores (RDNA keeps plain stores to
  mapped memory in L2), a system fence per thread, and the last block raises the flag;
- the reading stage's graph starts with wait_flag_ge(flag, 1);
- Verifier::run captures the next stage's window on this thread, then stages and launches it on a helper thread
  (prelaunch) while this thread serves its own layers; it then serves the next stage's layers directly and syncs
  the earlier stage once the chain is done;
- release_gpu_waits also raises the hand-in flag; an early return after the prelaunch releases the next stage.

Batch windows and --split-device 0 keep the serial order. Off by default.

Measured on 2x RX 7900 XTX (ROCm, Linux), Swift 1.5 IQ3_XXS, 512-token greedy answers, median of 8:
decode 53 -> 70.1 tok/s (code prompt), 45 -> 55.9 tok/s (prose prompt); greedy output byte-identical with the
flag at 0 and 1; quiz 47/51 both ways. Not measured on NVIDIA.

Split-overlap launch merged with 0.1.44 HostGraphLaunch (STRATA_VERIFY_ASYNC_LAUNCH): the launcher object is
kept in an optional so an early-launched window has none.

Co-authored-by: bsvinay <[email protected]>
2026-10-14 12:26:10 +02:00
Niko1221andSuperDistance 5d6bf8d414 batch-groups: decode and give way between the pieces of a prompt read (#2050, opt-in STRATA_PIPED_READ_PIECE), on top of #2326's concurrent read
Squash of SuperDistance's three commits of PR #2050 (decode between the pieces of a read on the pipelined groups, the
piece lines counting the rows the slots decoded meanwhile, the stall watchdog staying on for a read in pieces),
applied after #2326 here: the BYIELD give-way is #2326's give_way lambda, the concurrent block runs first and the
piece path serves a read that STRATA_PIPED_CONCURRENT leaves to it (pictures, configurations where it is off).

Co-authored-by: SuperDistance <[email protected]>
2026-10-14 12:26:10 +02:00
SuperDistance 073d079d27 batch-groups: the concurrent read's threads do not share the host thread's core on Linux
On Linux a thread inherits its creator's CPU mask, and the host thread is pinned to the one core the pool leaves it
(aux_cpus.hpp). The read's thread and the doorbell thread were created from it, so they shared that core with the host
thread that pumps the windows, and every window waited there for the doorbell of each layer: 6.1 rows/s during a read
on 4x RTX 5080, 4 stages (blange48 on #2326). Windows places the host with CPU Sets, which new threads do not inherit,
so it did not show there. Both threads now move off the host's core and the pool workers' CPUs (on an SMT machine with
the default pool: the idle sibling threads; without such CPUs, every CPU but the host's), and the threads that already
run on the host's CPU (the prompt path's copy threads, started by the first prompt) move the same way at a read.
--aux-cpus places them all when it is on. STRATA_PIPED_CONCURRENT_UNPIN=0 keeps the inherited CPUs (an A/B).

Measured on Linux (WSL2, Ubuntu 24.04, 2x RTX 5090, 4 streams, a cold 32K prompt; same binary, UNPIN=0 / default): the
slots decoded 25.9 and 23.7 rows/s during the read with the threads kept on the host's CPU (76-81 threads there), and
75.6 and 62.8 with this change; with the n-gram table in RAM (WSL's disk reads it 7x slower than Windows) 110.7 rows/s,
as on Windows (107.0). piped_read_join_bench.py (cold32k, followup, two_joiners; table in RAM, 2-3 runs each): 24-37
rows/s during the 30K+ reads kept on the host's CPU, 95-127 with this change, and 925-1,065 stream tokens during the
cold 32K join against 454-484. On Windows, STRATA_TEST_CONC_ON_HOST_CPU=1 (a test) puts both threads on the host
thread's CPU set first: 18.6 rows/s kept there, 105.4 with this change.
2026-10-14 11:58:16 +02:00
SuperDistance 0d47295f5a batch-groups: --remote-expert-opt without a helper cache does not keep the concurrent read off
The flag works only through a helper cache (--expert-cache-device1..3), and on a plain layer split it is inert
(MULTI_GPU.md, #1447), so the check looks at the helper caches themselves. #2275's rig runs a plain split with the
flag set, and the mode would have stayed off there for a cache it does not have.
2026-10-14 11:58:16 +02:00
SuperDistance 6c5c382b94 docs/BATCHING.md: reading beside the decoding slots, and what it measured
The opt-in's section: how the read and the windows share the GPUs, the doorbell thread, the give-way at a chunk, where
the mode is off. Measured against main (a0116b27) on 2x RTX 5090 in one window (main, this, this, main): the stops,
the streams' rate during the reads with the same answers every run, the joining prompts' TTFT, a question during a
read, the same randomised load on both, the doorbell thread's first wait as an A/B; 16 GB cards on each side; a weaker
host as well in #1906's shape; the default path's check; text equality.

tools/piped_read_join_bench.py, the client that measured it, is #2050's, unchanged (the same file as there).
2026-10-14 11:58:16 +02:00
SuperDistance 34b726e090 batch-groups: the concurrent read allocates nothing on its threads, keeps its checks and the watchdog, and waits on a launch
From a review of the concurrent read:
- With external serving batch_poll still finds a window that will not finish (its graph ended or failed with a layer
  to ring, or no layer rang for 20 s): the served count is read before the stream query and the ring count after it,
  at most one query a millisecond; the last ring's time is an atomic. batch_serve reads a window's row count after its
  served count, so a window launched while the doorbell thread was descheduled is not served with the last one's rows.
- #1996's pinned upload rings (0.1.43.1) grew a slot at its first larger upload, a pinned free and allocation on the
  read's thread: the drafter's records and the prompt path's routing tables reserve their slots before the read
  (PinnedRing::reserve, Prefill::reserve_uploads).
- Off, said once, where serving a doorbell makes a CUDA call (--pcie-mode dma, STRATA_FS_SLOTS, the helper caches) or
  the expert source recycles the buffers it hands out (the GGUF in place, unbuffered, STRATA_IO_PREFETCH); a prompt
  with pictures is read the usual way. The expert sources' read counters are atomics.
  The check is a pure function, concurrent_read_off (batch_read.hpp), with a test in batch_read_test.
- pump's all-idle branch turned the stall watchdog off when the last slot finished mid-read; it stays on while a prompt
  is read until the request ends.
- Between windows the doorbell thread slept 50 us, a whole timer tick on Windows (up to 15.6 ms): it now waits on a
  condition each launch notifies (STRATA_TEST_BELL_SLEEP_US=N, a test, restores the sleep for an A/B). With nothing
  decoding the main thread waits for the read's end or a line instead of sleeping. A pool failure the doorbell thread
  set is reported before pump clears the flag for the next window.
- The read's log line ends with the slots' rate and, per stage, its windows and the host time that set each up. The
  priority stream's cudaGetLastError runs only under the opt-in.
2026-10-14 11:58:15 +02:00
SuperDistance bc90e1acff batch-groups: read a prompt beside the decoding slots on a thread of its own (opt-in, experimental STRATA_PIPED_CONCURRENT)
With a layer split and --batch-groups > 1 a prompt read is one sp.run, so every decoding slot stops for the whole read
(#1906); #2050's pieces bound the stop but drain the pipeline at each piece. With STRATA_PIPED_CONCURRENT=1 the read
runs on a worker thread while the main thread keeps the groups going through the pipeline (pump) and takes BSTOP and
BYIELD meanwhile. The prompt's K/V goes to the main sessions and the slots' to their own; the windows' streams get the
device's highest priority on CUDA (STRATA_PIPED_CONCURRENT_PRIO=0 keeps the default).

- The slots' doorbells are served on a thread of their own that makes no CUDA call (Verifier::batch_serve, now
  batch_poll's per-layer service too, and set_external_serve). Two hangs found while building this, read from the
  stall dumps against the PDB, had #31's shape: the main thread waited for the driver's lock in cudaSetDevice while its
  holder waited for the GPU (a cudaFree in the drafter's prompt pass; cuBLASLt's lazy load of a GEMM module), and a
  window on that GPU waited for its doorbell.
- MtpDrafter::reserve_prefill captures the drafter's prompt graphs and sizes its records before the read.
- Prefill::stop_at_chunk: a BYIELD ends the run at its next chunk, also with no slot decoding; the pipeline is drained
  there and the part read gives way as #656 does. A read nobody waits for is not cut.
- The reader is joined on every way out (an exception too). Off beside STRATA_PREFILL_HELP and STRATA_SPLIT_MTP_BATCH,
  which allocate during a read.
2026-10-14 11:58:15 +02:00
SuperDistance a2de744653 PleTable: a lock around its reader state, so two threads can use one table
The prompt path gathers a chunk's PLE rows on its own thread and the batch windows gather theirs on the main thread,
from the same table (ss.ple.table). Today they never overlap - a prompt run's read-ahead ends with the run, and the
windows run between runs - but a prompt read beside running windows would race on the reader's tickets and the
prefetch slots. Every public method that touches them now holds a recursive mutex (gather holds it across its issue
and collect). Uncontended it is a few nanoseconds per call; nothing else changes.
2026-10-14 11:58:14 +02:00
Niko1221andruibeikaa 125025a770 prefill: --prefill-pipe, chunks sized for a layer split's pipeline (#1441, opt-in; b/a from setup's --calibrate)
Squash of ruibeikaa's six commits of PR #1441 (the first fixed b/a, then runtime-learned b/a, then calibrated b/a, the
segment planned once, --prefill-pipe 1 following STRATA_PREFILL_EQUAL), applied onto 0.1.44.1 with the conflicts in
generate.cpp (Options, BSlot, the lend's chunk with --prefill-head-alias) resolved.

Co-authored-by: ruibeikaa <[email protected]>
2026-10-14 11:52:32 +02:00
Niko1221 81ead832d6 docs: STRATA_CPU_IQ_ALL_EXACT1 (the exact one-token expert rows of #1415 and #1544), what was measured 2026-10-14 11:50:52 +02:00
Niko1221 d30f5d1042 docs (#1749): the wide top-k kernel on HIP, what it does and the switches that restore the old ones (R9700: 22.0 -> 0.93 ms per 256 queries at 524K; a 500K-token prompt +34%) 2026-10-14 11:46:11 +02:00
Niko1221 6612542e17 tools/qwen35: q36_lgcmp.py (two logits dumps: KL, top-1) and the multilingual draft-head prompts 2026-10-14 11:43:29 +02:00
Niko1221 b0f675be76 qwen35: the chunk rule counts what the chunk really costs (measured on the R9700)
A bigger chunk is only taken when the experts, the 0.77 GiB reserve and the chunk's buffers (0.5 MiB per token) still fit without giving the packed
decode copies back: 131072 cells -> 512, 100000 -> 2048, 32768 with --batch 4 -> 1024, --batch 8 -> 512 (hybrid as before).
2026-10-14 11:40:05 +02:00
Niko1221 93f0f48f10 qwen35: the prompt chunk defaults to the largest that fits (4096 .. 1024); the router and the shared gate in one product for decode batches; conv tile fix for batch rows
Prompt chunk (owner decision): with every expert in VRAM the auto rule picks 4096, 2048 or 1024 (the chunk's buffers cost ~0.5 MiB per token,
the sessions' caches 45 KB per cell and session; 1024 at most with --batch N so the other slots' windows are not held for a whole chunk), else 512.
The hybrid mode keeps 2048 and falls back to 1024 / 512 on a card with little room. STRATA_Q36_CHUNK=512 or --prefill 512 gives the old size.
R9700 pp4096: 512 3390, 1024 4495, 2048 5353, 4096 5750 tok/s. Not bit-identical to 512 (other GEMM tiles): see docs/QWEN36.md for the KL.
Decode batches of up to 8 rows take the router and the shared expert's gate in one product (rows of 257), as a single token already did.
k_conv_seq's tile mode switched off the history write for batch rows too (grid y is the group count there): fixed.
2026-10-14 11:24:15 +02:00
Niko1221 2bc0a7cafd gguf_reader: the placeholder note ends in a newline 2026-10-14 11:16:52 +02:00
Niko1221 94d189fca4 gguf_reader: an all-zero attention.compress_ratios list is a converter's placeholder and is treated as absent, with a one-line note (#2396: orcarouter Qwen3.8-Flash-Next-Uncensored GGUFs refused since 0.1.44); real lists are still checked in full 2026-10-14 11:16:26 +02:00
Niko1221 6f4697f662 qwen35: the prompt's gated delta rule loads the next token's inputs while it computes this one
k_gdn_seq_cols started every token with a chain of global loads; they are issued one token ahead now. Same arithmetic: the 3000-token
prompt's logits and the next 8 greedy steps are bit-identical to the previous engine at chunk 512 and 2048 (R9700: prompt 931 -> 902 ms
at chunk 512 together with the tiled conv, 616 -> 591 ms at 2048).
2026-10-14 11:05:46 +02:00
Niko1221 c9e7f6dd5a qwen35: faster decode kernels with the old kernels' bits (STRATA_Q36_VERIFY=1 compares them on real activations)
q36_kernels.cuh: one warp per row for the shared expert's and attention k/v Q8_0 products (grid capped at 1024 warps: 2048 rows as 2048
warps took 21 us, 5 us as 1024), shared gate+up+SwiGLU+q8_1 in one launch, k_moe_out with 1024 threads and the next layer's q8_1 image, k_add_rms
with the q8_1 image, router top-k and expert grouping in one launch. CUDA: the division / exp the --use_fast_math TUs they mirror use are spelled out.
Engine: prompt GDN conv in tiles of 16 tokens side by side (same arithmetic per token), --draft-vocab N (the MTP draft head over the first N rows only,
a draft proposes and the verify window decides: output unchanged), the packed Q8_0 default on Windows too (it was Linux only), STRATA_Q36_OLD_KERNELS=1
switches all of it off.
R9700, UD-Q4_K_XL: decode 82.5 -> 120.6 tok/s (greedy 10 prompts identical), --mtp 2 160 -> 174.
2026-10-14 10:52:17 +02:00
Niko1221 fb51ae6fbd iq_kernels: the V2K gate/up kernels take Qwen3.6-35B-A3B's expert geometry (n_embd 2048, n_ff 512, Q4_K/Q5_K gate+up, Q5_K down)
For that geometry only: the s27 gate/up kernel and the fused SwiGLU/q8_1, then the old down kernel (the new down kernel is slower at n_ff 512).
Flash-Next's shapes (2560/640) take the same paths as before; the path is still STRATA_EXPERT_V2K (default on gfx12).
2026-10-14 10:50:29 +02:00
Niko1221 c298fa559e qsa scorer (#1943): the exact four-lanes-per-query scorer is the default on gfx12; the test runs there too
The same kernel measured on an R9700 (gfx1201): qsa_scores_gfx1100_parity --full compares 223,664,777 scores and 11,895,800 ids bitwise equal
to the warp scorer (35 cases), the scorer stage with 256 queries is 3.6x faster at 131K and 4.0x at 240K, and a fresh prompt reads 8.7% faster at
131K tokens (4 of 4 pairs) and 16.4% faster at 230K (3 of 3), with identical answer tokens and byte-identical exact_pp residual dumps at 70K and 131K
tokens. So on gfx12 it is on for batches of >= 64 queries with >= 16,385 live blocks (65K cells and more) unless STRATA_SCORES_THREAD=0; gfx1100
stays the author's opt-in (STRATA_SCORES_THREAD=1). A one-time stderr line says when it engages by default.
2026-10-14 10:48:36 +02:00
Niko1221 7d3fd4b24f tests (#2147): test_setup_rocm_pins skips an index with no saved version list (the gfx1150 opt-in has none yet) 2026-10-14 10:48:36 +02:00
Niko1221 a61436c4da refill parts (#2078): not in gfx1151's default table (only gfx1151 measured it, and nothing here can gate that arch): opt-in STRATA_REFILL_PARTS=1, documented in section 5 2026-10-14 10:48:36 +02:00
Niko1221 b317c23f24 pcie (#2224): the PcieAuto share on HIP outside gfx12 is opt-in (STRATA_PCIE_FRAC_DEFAULT=auto), not a gfx1100 default: the author's gate was no-regression only and a second gfx1100 report saw it never engage 2026-10-14 10:48:36 +02:00
Niko1221 595686f6a1 hc persist (#2226): not offered on gfx11 and gfx12
The persistent read's barrier timeout uses __builtin_amdgcn_s_memrealtime, which gfx11 and gfx12 do not have (clang: "needs target feature
s-memrealtime"): the PR as ported failed to build for gfx1100, gfx1151 and gfx1200/gfx1201. On those parts the barrier compiles to an immediate
abort, fused_gr_persist_init refuses the read with a start-up line, and the default read is used. An R9700 (gfx1201) measured the read +0.7% / +1.0%
per window slower than the default in the PR thread, so nothing is lost. The silent, permanent barrier abort at run time that the same thread
describes is noted in docs/AMD_HIP.md.
2026-10-14 10:48:35 +02:00
Niko1221 44dbf66af5 Merge f-145-nv (#2347: NVFP4 on AVX2 CPUs: the pack-folder hint, setup note, docs) 2026-10-14 10:02:45 +02:00
Vop3p b2b5000952 hc persist results: ten interleaved pairs on 0.1.43.1 with no other switch (-6.6 % / -4.4 % ms per verify window at 4K / 32K, 10 of 10 pairs) 2026-10-14 09:59:02 +02:00
Vop3p cea3d61b66 tests: hc_persist_parity - the STRATA_HC_PERSIST=1 read against the default multi read at T = 1..8 (bounded 1e-4, finite, two runs bitwise), and hc_persist_default_off: with the variable unset it never runs; a skip where the card cannot hold the 80 blocks and on CUDA 2026-10-14 09:59:02 +02:00
Vop3p 6cbc15a81a STRATA_HC_PERSIST=1 (opt-in, HIP): the verifier's hyper-connection read as one persistent kernel
The verifier reads the hyper-connection twice per layer at 1-8 tokens: three small launches with two global
dependencies, the down projection on 41 blocks. Opt-in STRATA_HC_PERSIST=1 runs it as one kernel of 80 blocks with two
grid barriers on an atomic counter: the down projection split by column slices over all 80 blocks, a distributed
reduction, then the up projection and the same epilogue as gr_up_kernel.

gfx1030 (2x RX 6900 XT, layer split): the read 1.35-2.10x at 1-8 tokens; ms per verify window -4.2 % at 4K and
-2.8 % at 32K (one binary, the variable unset / set, 6 alternating rounds, every round the same way). Another summation order (not bitwise); against a
double-accumulation reference (STRATA_HC_PERSIST=3) as close as the default read.

Residency is decided by running every token count once at start-up with a 50 ms barrier timeout and comparing with
the default read; a timeout keeps the default read for that token count and larger ones, wave64 cards are refused.
One line per card says what was decided. Only the verifier's reads use it (one stream per card); the drafter's reads,
the prompt path, CUDA and SYCL are unchanged (CUDA and SYCL get two empty stubs). With the variable unset both entry
points return in their first line: the output is bitwise the same as main.

Measurements, the simulated smaller cards and a stand-alone timing tool:
bench/results/2026-10-12-hc-persist-gfx1030/.
2026-10-14 09:59:02 +02:00
2jztricks e5d91bf239 hip: add opt-in exact gfx1100 QSA prefill scorer 2026-10-14 09:59:02 +02:00
sa 82922f55e2 topk: compile the wide kernel on HIP too (it was CUDA-only; every deep context on AMD paid the ref radix)
block_topk_wide_kernel is plain shared-memory / atomicAdd code with no sm_90
feature, but its definition and the dispatch branch sat behind
#if !defined(__HIPCC__), so on AMD a context past the register kernel's reach
(about 135K cells) always fell back to the 4-pass ref radix.  The ids are
identical by construction (the same radix rule), which the bench states:
256/256 at 256 queries x 65537 blocks, 1/1 at nq=1.

Measured on a Ryzen AI Max+ 395 (gfx1151, ROCm 10.1), qsa_select_bench:
- nq=1, 131073 blocks (a decode window at 512K context): 2.24 -> 0.77 ms (2.9x)
- nq=256, 65537 blocks (a prompt batch at 262K):        3.16 -> 1.43 ms (2.2x)

End to end this moved the deep-context decode of a 512K-token prompt from
19-22 to 24-26 tok/s and the 512K prefill from 473 to 634 tok/s on that PC
(together with the split scorer of another change).  STRATA_TOPK_STREAM=0
still restores the register kernel.
2026-10-14 09:59:02 +02:00
Niko1221andZac Chen b0e88eb12f pcie: the in-window share refinement (PcieAuto) on HIP too — gfx1100 port of the XeStrata stabilization cluster's finding
Upstream aa7b0cb gates PcieAuto to CUDA single-GPU (#if !defined(STRATA_USE_HIP)); the
machinery itself is engine-generic (pool ms per missed expert + miss counts vs the probed
link rate), and this build's start-up H2D probe is already best-of-4 with a +-0.7% spread,
so the HIP exclusion was unmeasured-only, the same class as the ROUTE_TAIL_SKIP gate.
Same opt-outs as CUDA: layer splits excluded, STRATA_PCIE_FRAC_DEFAULT=old restores the
fixed start-up rule. Provenance: MistVVK/XeStrata commits 05309096/055cf9b0/c71cac34/
5952e8e7 (their measurement-stabilization cluster) demonstrated the failure mode and the
fix class; their exact subsystem is not portable (it is their own engine code).

(cherry picked from commit acb3deb0522a8fc351a4047d2bd11b8ab7a73dca)

Co-authored-by: Zac Chen <[email protected]>
2026-10-14 09:59:02 +02:00
Niko1221andonionbutties 01e1bc5c0e setup: write the gfx1150 speed switches for the opt-in install
The engine turns 18 exact (bit-identical) switches on by default on gfx1151
(src/core/arch_defaults.cpp) but keeps gfx1150 out of its arch defaults
(src/core/arch_defaults_test.cpp asserts arch_default_env("gfx1150").empty()).
A gfx1150 install gets the 17 that apply here - the gfx1151 set less
STRATA_HCD_EXACT, which copies the gfx1151 hipBLASLt table's solutions 1176 / 1177
and so does not fit beside a gfx1150 table - written into the config's "env"
beside STRATA_HIPBLASLT_TUNING.  The Radeon 890M report (docs/AMD_HIP.md;
bench/results/2026-10-07-community-gfx1150) measured the same greedy answers with
all 17 on and with all 17 off, decode +2% and prompts +3-6%.

The set is setup's own (SETUP_ENV): a re-run refreshes it, and it does not linger
after the opt-in is turned off.  A new test (tools/test_setup_strix_halo.py,
Gfx1150Switches) keeps GFX1150_SWITCHES equal to the gfx1151 arch-default table
minus STRATA_HCD_EXACT, keeps the engine's own default path for gfx1150 empty, and
checks the SETUP_ENV wiring.  Setup's suites pass (strix_halo 40, amd 36, choices 47).

Co-authored-by: onionbutties <[email protected]>
2026-10-14 09:59:02 +02:00
Niko1221andonionbutties 6f0505c69e setup: opt-in gfx1150 (Radeon 890M / 880M, Strix Point) as a unified-memory AMD card
STRATA_EXPERIMENTAL_GFX1150=1 takes the Radeon 890M / 880M iGPU (Ryzen AI 300,
Strix Point, gfx1150) as a unified-memory card like Strix Halo: it joins AMD_ARCHS
and the UMA handling (new is_uma_apu helper), with notes of its own.  The engine
already builds and runs for gfx1150 (0.1.40.2, #1217; tools/hip/gfx1150-hipblaslt-100401.txt
is calibrated on it); no release ships a ready-made Windows engine for it yet, so
a Windows user builds one (STRATA_HIP_ARCHS=gfx1150 tools\hip\build_windows.bat) and
starts setup with --prebuilt dist\.  Unset, the default path is unchanged: the test
that asserts gfx1150 is not in AMD_ARCHS (tools/test_setup_strix_halo.py) still passes.

Co-authored-by: onionbutties <[email protected]>
2026-10-14 09:59:02 +02:00
Niko1221andAlexisCarbonell d3c4a6de77 setup: write the gfx1103 exact speed switches for the opt-in install
The engine turns 18 exact (bit-identical) switches on by default on gfx1151 (src/core/arch_defaults.cpp) but keeps
gfx1103 out of its arch defaults (src/core/arch_defaults_test.cpp asserts arch_default_env("gfx1103").empty()).  A
gfx1103 install gets the 17 that apply here - the gfx1151 set less STRATA_HCD_EXACT, which copies the gfx1151
hipBLASLt table's solutions 1176 / 1177 and so does not fit beside a gfx1103 table - written into the config's
"env" beside STRATA_HIPBLASLT_TUNING.  One 780M (Ryzen 7 8745HS, 60 GB, GTT 50 GiB, ROCm 10.1, Q2_0, 4K prompt)
measured the same greedy token ids with the 17 on and with them off, +13% to +15% prompt and decode +3.2% (the
decode half alone); bench/results/2026-10-12-community-gfx1103.

The set is setup's own (SETUP_ENV): a re-run refreshes it, and it does not linger after the opt-in is turned off.
The gfx1103 note now names the native dot4 / WMMA kernels and docs/RADEON_780M.md, which documents the opt-in
build, the table and the measured numbers.  Setup's suites pass (strix_halo, rocm_pins, amd, choices: 143 tests).
Refs #1423.

Co-authored-by: AlexisCarbonell <[email protected]>
2026-10-14 09:59:02 +02:00
onionbutties 7aa71b08e5 hip: add a gfx1150 hipBLASLt 100500 tuning table (Radeon 890M)
Calibrated on a Radeon 890M (Strix Point, gfx1150) with
tools/hip/tune_hipblaslt --workspace-mib 32 over the 16 dense GEMM geometries of
the shipped gfx1150-hipblaslt-100401.txt at T = 64, 128, ..., 16384: two passes,
each row keeping the solution with the lowest mean of all six repetitions.  The
three rows slower than plain hipBLAS (the tiny bf16 N=1 K=2560 shape at T = 64,
128 and 256) are left out, so those buckets route to the nearest good row.  Every
remaining row beats plain hipBLAS: 1.07x to 16.7x per GEMM, geometric mean 5.0x.
The solution IDs are scoped to hipBLASLt 1.5.0 (version 100500, the ROCm
10.2.0a20260930 nightly the engine here was built with).
2026-10-14 09:59:02 +02:00
AlexisCarbonell 0fb72e8b0e hip: a gfx1103 hipBLASLt tuning table (Radeon 780M)
The Radeon 780M (gfx1103, RDNA3, 12 CUs) builds and runs (issue #1423), but had no hipBLASLt table, so the prompt's
dense GEMMs ran on plain hipBLAS.  This adds tools/hip/gfx1103-hipblaslt-100401.txt, calibrated on one 780M with
ROCm 10.1's hipBLASLt 1.4.1 (version number 100401) over the gfx1150 table's 144 GEMM cases at T = 64..16384 with
the engine's 32 MiB workspace.

Two tune_hipblaslt passes back to back; each row keeps the solution with the lowest median of all six repetitions,
and a row is left out when no candidate beats plain hipBLAS.  143 rows, 1.05-23.30x per GEMM, geometric mean 4.95x;
the one shape left out is bf16 N=1 K=2560 T=64 (best 0.039 ms against 0.024 ms on plain hipBLAS, sub-100 us
timings), where the engine falls back to hipBLASEx.

Measured on the 780M (Ryzen 7 8745HS, 60 GB, GTT 50 GiB, Q2_0 + MTP, 32K context): a 4K prompt read 90 tok/s on
plain hipBLAS against 187 with the table (medians of an interleaved A/B; with the gfx1103 exact switches and the
WMMA opt-ins, 277 at 4K and 272 at 32K).  hip_prefill_hipblaslt_gemm passes with it (launches=4 fallbacks=0) and
hip_prefill_hcd_exact_parity skips, because the table picks no 1176 / 1177 for the HC down GEMM - the gfx1150 table
gets the same skip, which is why STRATA_HCD_EXACT is not in the gfx1103 switch set.  Setup installs for gfx1103 only
with STRATA_EXPERIMENTAL_GFX1103=1 and then picks the table up when the installed hipBLASLt reports 1.4.1.

Docs, the community report (runs.csv, tune-summary.csv, the server config, the engine's start-up lines) and the
setup tables list carry the numbers.  Refs #1423.
2026-10-14 09:59:02 +02:00
Niko1221andlibratechw 1b1bd4b4a8 prefill: STRATA_GDN_CHUNKED=1 on gfx11, the prompt's DeltaNet recurrence in 16-token chunks on the matrix cores (opt-in)
The switch exists for CUDA (#1372) and is compiled out on HIP.  On gfx11 it now runs the WY form of the gated delta rule in
chunks of 16 tokens, every product one 16x16x16 WMMA (FP16 operands, FP32 accumulation, the state in the accumulators), with the
output norm and the z gate fused: a prep kernel for T and P of every chunk, then a scan with a block per value head.
It rounds differently from the FP32 recurrence, so it is opt-in; the default path is unchanged.  A gfx1100, gfx1101, gfx1102, gfx1150 or gfx1151 part, 64 tokens and
more, an output row stride divisible by 8 and no STRATA_GDN_REC_HEADS take it; anything else runs the existing kernels.

tests/hip/gdn_chunked.cpp: bounds on the FP16 output and the carried state against the existing recurrence over 0-16,385 tokens
(chunk and stride edges, a split request), a double-precision CPU check, and bit-identical output with the switch off or unset.
tests/hip/gdn_rec_head.cpp unsets the switch, as its variants 0 and 1 are the references there.  hip_gdn_chunked --bench and
--bench-default time this path and gfx1151's default kernels, one per process (the switch is read once).

gfx1151 (Ryzen AI Max+ 395, UD-IQ4_XS): a layer's recurrence + norm takes 1.60x less time than the default kernels at 16K and
32K tokens; a whole prompt 1.4-2.1% less at 4K-128K after a warm-up prompt (11 pairs each: 1.8-2.1% with the docs/STRIX_HALO.md section-5 switches,
1.4-1.5% without them, 10 or 11 of 11 faster); first-token KL against the default 0.006-0.007 on average, the same top token in
12 of 12 prompts.  Run on gfx1151 only; kernels.cu compiles for gfx1030, 1100, 1151, 1152 and 1201 (docs/AMD_HIP.md).

Co-authored-by: libratechw <[email protected]>
2026-10-14 09:59:02 +02:00
libratechw feeb8dc808 docs: STRATA_PF_F16=1 on gfx1151 (what it covers, the layer times, first-token KL) 2026-10-14 09:58:51 +02:00
libratechw ed160b461a tests: hip_prefill_fused_iq also runs with STRATA_PF_F16=1 STRATA_PF_F16_KQ=1 2026-10-14 09:58:51 +02:00
libratechw 0c2608ae97 prefill: STRATA_PF_F16=1 takes Q8_0 down without STRATA_PF_FUSED_KQ on gfx11
Q8_0 has no minimum term and the F16 kernel's output already differs from the int8 kernels', so the KQ opt-in is
not needed for it.  UD-IQ4_XS has five Q8_0-down layers (4 IQ3_S / Q8_0, 1 IQ4_XS / Q8_0): they left the fused path
for MMQ, and since fused_ring() asks every layer, the pack kept MMQ's buffers.  d_covered_on() is the one test, for
native_supported() and experts_native(); gfx12 keeps d_covered().

UD-IQ4_XS, gfx1151, 3 interleaved rounds, prompt tok/s (v0.1.42 / 65d809c6 with STRATA_PF_F16=1 / this):
4K 926.6 / 992.2 / 1054.8, 32K 1257.4 / 1364.6 / 1397.1, 128K 1202.0 / 1309.4 / 1333.6.
2026-10-14 09:58:51 +02:00
libratechw bd5cc1f27b prefill: the other native formats on gfx11's F16 matrix cores (STRATA_PF_F16=1)
native_f16_kernel takes the IQ gate/up formats (IQ2_XXS, IQ2_XS, IQ2_S, IQ3_XXS, IQ3_S, IQ4_XS) and the Q2_0, IQ4_NL
and Q8_0 down: load_unit / convert decode each sub-block once into an int8 weight tile in LDS with its scales as
half2, each wave turns its own rows into F16 (gufo's Q8_0 decode: sign flip, byte permute into 1024's mantissa,
one packed multiply), and the F16 WMMA accumulates all of K.  The work item, the activations staged as F16, the WMMA
loop and both epilogues move to moe_f16_common.cuh, shared with the K-quant kernels (moe_f16_kq.cu, now on it; its
output bits are unchanged).  The switch becomes STRATA_PF_F16=1 (was STRATA_PF_F16_KQ) and covers both; the K-quants
still need STRATA_PF_FUSED_KQ=1.  gfx12 keeps the int8 kernels.

hip_prefill_fused_iq (gfx1151, ROCm 7.14.1 clang 23, top 10 over 512 experts, one 128-expert launch, ms):
- IQ3_S / IQ4_NL at 16384 tokens: gate/up 11.65 -> 9.87, down 6.11 -> 4.71; layer at 8192 37.3 -> 32.2.
- every pair is faster at 4096 and 16384 (IQ2_S gate/up 14.38 -> 9.85, Q8_0 down 6.80 -> 4.79), and at 128-2048
  tokens equal or faster.
- FP32 reference rel RMS as the int8 kernels' (IQ3_S / IQ4_NL 1.456e-2 against 1.454e-2); against the int8 model
  and MMQ the F16 path sits at 2.4-2.7e-3, so both checks allow 5e-3 under STRATA_PF_F16=1 (f16_on).
- With the weights decoded to F16 in LDS (18 KB a block) gate/up was 9.83 and down 5.71.  Neither a VGPR cap nor
  dropping the sign table (4 blocks per WGP) nor decoding after the products moved gate/up; without the decode it is
  8.98, without the weight loads 9.30.
Off by default (the output differs from the int8 kernels').
2026-10-14 09:58:51 +02:00
libratechw 929010be61 prefill: gfx12 keeps the int8 kernels under STRATA_PF_F16_KQ=1
moe_f16_kq.cu's bodies are gfx11's WMMA layout (and trap on other targets); v0.1.42's gfx12 native kernels share
experts_native's launch, so the F16 path is taken only off gfx12.
2026-10-14 09:58:51 +02:00
libratechw b2492918f5 prefill: Q5_1 down on the gfx11 F16 matrix cores too (STRATA_PF_F16_KQ=1)
down_kernel takes gate/up's structure for UD-Q4_K_XL's Q5_1 down (47 of its layers): the codes and high-bit words
packed in LDS, w = q d + m per wave in F16, H staged once as F16 from its int8 blocks, FP32 outputs at the routed
rows.  The activation staging and the WMMA loop are shared with gate/up (ActStage, mma_tiles).  Q8_0 down stays on
native_w11_kernel.

hip_prefill_fused_iq (gfx1151, one layer, 16384 tokens x top 10 over 512 experts): down 7.10 -> 4.83 ms per
128-expert launch; Q4_K / Q5_1 layer 62.7 -> 53.5 ms (85.3 on the int8 kernels); FP32 reference rel RMS 1.304e-2.
2026-10-14 09:58:50 +02:00
libratechw df218bd8ae prefill: K-quant gate/up on the gfx11 F16 matrix cores (opt-in STRATA_PF_F16_KQ=1)
UD-Q4_K_XL's routed gate/up was 6/10 of the prompt-time gap to gufo on gfx1151 (128K: 23.1 s against 13.9 s).
moe_f16_kq.cu adapts gufo's paired RoutedF16GEMMKernel (97b8645f, MIT) to Strata's tables, int8 activations and H:
the Q4_K / Q5_K codes stay packed in LDS and each wave turns its own rows into F16 after the read, so the F16 WMMA
accumulates all of K in F32 with no per-block epilogue; the activations are staged once in LDS as F16 for every wave;
the epilogue writes H as int8 per 32 features for the existing down kernels.  One block per work item; two tiles of
an expert per item from 64 routed rows per expert on average.

hip_prefill_fused_iq (gfx1151, ROCm 7.14.1 clang 23, one layer, 16384 tokens x top 10 over 512 experts):
- gate/up kernel 14.63 -> 8.46 ms per 128-expert launch; Q4_K / Q5_1 layer 85.3 -> 62.7 ms, Q5_K / Q5_1 89.9 -> 66.2.
- against the FP32 reference the error is the int8 path's (rel RMS 1.305e-2 / 1.302e-2: the int8 activations
  dominate); the int8 model check allows 5e-3 under this switch (2.5e-3 measured with Q8_0 down).
- the output bits are the same with 64- and 128-row items.
Off by default; it needs STRATA_PF_FUSED=1 and STRATA_PF_FUSED_KQ=1, whose output already differs from MMQ's.
2026-10-14 09:58:50 +02:00
libratechw d573332130 prefill: refill a prompt's lent expert slots from the GGUF mapping's pieces (STRATA_REFILL_PARTS=1, gfx1151's table)
After a prompt the borrowed expert-cache slots are refilled from the experts' files.  With the GGUF read in place an
expert is three tensors, and the refill first assembled each 4 MB blob in a staging buffer (a copy on the calling thread)
and then copied that to the slot.  The pieces are contiguous in the mapping, so they can go straight to their offsets in
the slot: blob_parts() hands them out, ExpertCache::fill_slot_queued_parts copies them on the same queue.  The bytes in
the slot are the same.  Off by default; gfx1151's table turns it on.
2026-10-14 09:58:50 +02:00
Niko1221 37f2941fc2 docs/NVFP4.md: the CPU rows on a CPU without AVX-512 (AVX2 rows bit-equal to ggml's, measured on three CPUs) (#2347) 2026-10-14 09:45:18 +02:00
Niko1221 5e9bd5db4f docs/MAC.md: the M1 Max line quotes the 9,940-token prompt speed of the #2348 report, not a 24-token cold request 2026-10-14 08:05:07 +02:00
Niko1221 b1f7b4ac3a pytest: a session config home, so no test can write or migrate the user's real Strata settings (#198 data-folder migration) 2026-10-14 08:04:52 +02:00
Niko1221 3de6363749 Merge f-145-mac (the #2365 test no longer runs data_folder() for real) 2026-10-14 07:51:50 +02:00
Niko1221 98f5484c8d gr_upmix_parity: skipped (exit 77) below sm_80, where the fused read refuses by design (#1370 follow-up) 2026-10-14 07:46:45 +02:00
Niko1221andAndy Slater b558df67b4 cpu: the exact singleton rows only where ggml-cpu is itself the AVX2 build (not AVX-512, not an ISA-floor build)
STRATA_CPU_IQ_ALL_EXACT1 reproduces ggml-cpu's AVX2 single-token dot bit for bit, which only
holds if the ggml-cpu in this binary is that dot: a STRATA_ISA_FLOOR build runs ggml's AVX1/SSE
dots, and a native build on an AVX-512 CPU run with STRATA_FORCE_AVX2=1 runs its AVX-512 one.
The guard is #2215's (ggml_cpu_has_avx2 / ggml_cpu_has_avx512).

Co-authored-by: Andy Slater <[email protected]>
2026-10-14 07:20:05 +02:00
Niko1221 6eb34c7036 setup: --parallel is not offered where the card holds every expert for one session only (4 slots at 128K on a 32 GB card moved all but 15 experts per layer to the CPU: 81 tok/s against ~180) 2026-10-14 07:17:06 +02:00
Niko1221 093108c2e0 setup: the engine's own programs run with its rocm/bin on PATH (#2372: strata --families on Windows AMD showed hipblas.dll / libhipblaslt.dll not found and Qwen3.6 was refused) 2026-10-14 07:16:36 +02:00
Niko1221 8bfef49c5f q36_vision_cmp: --dump-ngl, llama.cpp's offloaded layers for a quant larger than the card 2026-10-14 07:14:54 +02:00
Niko1221andtuandat3019 10552345e9 AMD HIP: the primary ordinal, and the helper caches beside the resident RAM mode
Three changes for two-card AMD PCs whose faster card does not come first in the
runtime's enumeration (Windows HIP orders the cards itself; HIP_VISIBLE_DEVICES
only filters):

- gfx1032 (RX 6600) joins the unvalidated build list - it shares the gfx1030 /
  gfx1031 / gfx1034 dp4a path.
- STRATA_PRIMARY_DEVICE=N picks the visible ordinal the engine's own session
  runs on; it is set before any context or allocation exists.  The helper
  caches take the other visible devices, the HIP arch check and the peer tier's
  device queries follow it, and the primary's session is created on the chosen
  device.  A layer split still assumes device 0 and is refused with this set.
  Unset or 0 is upstream's behavior unchanged.
- The helper-GPU caches are allowed beside the resident RAM mode: the experts a
  helper holds are left out of the RAM copy as a split stage's are, and the two
  adaptive tiers already keep each other's experts out.  RemoteExperts::finish
  spins on its stream like PeerExperts::finish - on HIP the CUDA branch's
  cudaInitDevice(ScheduleSpin) does not exist.

Measured on an RX 6800 (16 GB, gfx1030) + RX 6600 (8 GB, gfx1032), Windows 11,
32 GB of RAM, Swift 1.5 IQ3_XXS at 160K context, the resident RAM mode with the
helper's cache left out of the copy: decode 37.5 -> 44.2 tok/s on 8K-token
requests with a 3800-slot helper; the CPU pool's share of the routed experts
falls from ~2.9 to ~0.4 entries per layer-window.

Rebased onto 296b59d2 (conflicts in generate.cpp, peer_experts.cpp, hip_backend.cmake, docs/AMD_HIP.md resolved by keeping main's code and adding the PR's).  Changes: remote_caches is kept (still used by the --batch-mtp check); the spin in RemoteExperts::finish is HIP only (CUDA keeps its cudaInitDevice(ScheduleSpin) + blocking sync).  NOT COMPILED YET, not run.

Co-authored-by: tuandat3019 <[email protected]>
2026-10-14 07:14:17 +02:00
Niko1221 e8b20f2a6e setup: NVFP4 on a CPU without AVX-512 is offered, with a note on what its CPU rows are (#2347)
The menu never hid NVFP4 on an AVX2 CPU; the engine runs a native pack's rows on AVX2 kernels that are bit-equal to
ggml's. The NVFP4 menu line and the install step now say, on a CPU with AVX2 and no AVX-512, that the CPU's share of
the experts runs on AVX2 rows (measured about as fast when memory-bound, up to ~12% slower on 4-token windows).
A note only: nothing is refused or capped. tools/test_setup_menu.py: 2 tests.
2026-10-14 07:14:11 +02:00
Vop3p eb6e0f1e4d calibrate: measure the shared-expert stream fork on AMD (STRATA_SH_STREAM, off against on) and keep it per PC
The fork stays off by default on HIP (#816, #826): an RX 6800 on Windows and 4x R9700 decode 12-45% faster without it.
The same card family on another PC goes the other way (#1272: 2x RX 6900 XT on Linux), and the output is identical
either way, so it is a per-PC choice - the open item of #1272.

- tools/calibrate.py: step 6, HIP only. With everything chosen before, the engine is started twice, with
  STRATA_SH_STREAM=0 and =1 set explicitly, two rates each; "1" is kept only when it beats "0" by more than MIN_GAIN
  (the rule of the other steps). measure() returns the choice as "env"; a failed start drops that candidate (#1337).
  start_engine takes an optional env; apply_env() sets the chosen variables and removes the others of ENV_KEYS, so an
  older calibration's choice does not linger.
- setup.py: --calibrate writes "env" into the config and the settings file; a reinstall applies a saved calibration's
  "env" the same way (a calibration saved before this step leaves "env" as it is).
- docs/AMD_HIP.md: the SH_STREAM note says calibrate measures it.
- tools/test_calibrate.py: the step runs on HIP only, keeps the fork only on a win, falls back on a failed start;
  apply_env; setup writes and later removes the variable.

Measured with the real engine (0.1.42 tag, 2x RX 6900 XT gfx1030, Linux, IQ3_S layer split, setup-style config): the
whole calibration took 982 s, the new step chose STRATA_SH_STREAM=1 (off 62.2 / 61.3, on 67.2 / 66.6 tok/s, +8.3%).
Separately, with a fixed protocol, the fork's output is byte-identical to off (4 of 4 requests, one card and the split).
2026-10-14 07:12:58 +02:00
Niko1221andxjc10 4f21be8723 hip: the FP32 tiled QSA block scorer on HIP cards (opt-in STRATA_SELECT_SIMT=1, as on CUDA), tiled 32/128/16/8 on gfx103x
The scorer of 65ce329 is plain FP32 arithmetic, so it runs on any HIP card as it is; without matrix cores the
prompt path otherwise scores on the warp kernel.  Its tiling becomes template parameters: every tiling keeps each
score's fmaf chain over k = 0..127 in order and the same relu sum over the heads, so every tiling gives the same
bytes (RX 6900 XT, qsa_select_bench at 32K and 128K: 14 tilings, also on 60 and 72 of its 80 CUs through
HSA_CU_MASK, all byte-identical to the original kernel; the fastest tiling the same at every width).  CUDA keeps
the tiling it was written with; gfx103x runs 32/128/16/8: 256 queries at 128K 2.69 ms (warp kernel) -> 0.695 ms
(the original tiling) -> 0.587 ms.  FP64 gate passed, selections identical 256/256.  On the 2x RX 6900 XT layer
split a 128K-token prompt reads 7.4% faster, 32K 0.8%.  A HIP ctest runs it at 131K.

Rebased onto 296b59d2: the docs/AMD_HIP.md conflict (main's SGEMM/rocBLAS-table bullets from the ports before it) is resolved by keeping all bullets.

Co-authored-by: xjc10 <[email protected]>
2026-10-14 07:12:53 +02:00
xjc10 4b3e4d096f rocBLAS table docs: the shipped gfx1030 table was measured on an RX 6900 XT; other gfx1030 cards can make their own with tune_rocblas (reports welcome) 2026-10-14 07:12:35 +02:00
Niko1221andxjc10 57c95d5faf hip: a rocBLAS solution table for the FP16 prompt GEMMs on gfx103x (the GDN projection 7x below 1,152 tokens; short prompts -10 to -14%)
rocBLAS picks the kernel for each FP16 product from its own table by shape, and on gfx1030 that pick is far
from the best kernel the same library holds for some shapes: N = 10240 K = 2560 (the GDN input projection)
below T = 1152 runs at 5.2 TFLOPS where the best of rocBLAS's 237 solutions for n = 799 is 6x faster (not an
alignment effect: n = 800 is as slow as 799).

tools/hip/tune_rocblas enumerates the library's solutions per shape and token bucket, checks each against the
default kernel's output and that it also runs at smaller odd token counts, and writes the winners (and
`default` rows bounding their reach) as tools/hip/<arch>-rocblas-<version>.txt; Gemm::f16_inplace runs the
table's solution for a shape (STRATA_ROCBLAS_TUNING: a file, or the directory from which the engine takes the
file of its own rocBLAS build; the version string, tweak hash included, is checked). One tiny default product
at startup opens rocBLAS's kernel library (a solution-index call before that fails although the index is
valid); a refused solution falls back to the default kernel for that call, after three refusals for good.
setup points the engine at tools/hip when a table for the card's architecture exists. Shipped: the gfx1030
table for ROCm 10.0.0's rocBLAS 5.6.0.8d1ae90e (112 rows, 76 with a solution).

Measured (RX 6900 XT, 6f32ec0 + #835 + this, temperature 0, the same answers with and without): a 799-token
prompt's GPU time 3,329 -> 2,985 ms (-10.3%), 495 tokens 2,477 -> 2,139 (-13.6%), 8,874 tokens 11,978 ->
11,459 (-4.3%); a PCIe-bound 1,108-token prompt unchanged (its saving reappeared as `wait copy`). ctest 66 of
70 (the 4 failures are outside this change); hip_prefill_rocblas_gemm, the new smoke test, passes with 0
fallbacks. Builds on #835. bench/results/2026-10-05-rdna2-rocblas-table has the per-run lines and the tuner's
summary.

(cherry picked from commit e35e103604)

Rebased onto 296b59d2: conflicts in setup.py (SETUP_ENV gained STRATA_ROCBLAS_TUNING beside the 0.1.44 entries) and docs/AMD_HIP.md (kept both sections) resolved.

Co-authored-by: xjc10 <[email protected]>
2026-10-14 07:12:35 +02:00
Benjamin Larsson 2f44bf51dd STRATA_HC_REQ8: hyper-connection projections requantized to int8 + fp32 scale per 32 at load
The rebased #704 under the name asked for there (upstream's STRATA_HC_Q8 now
reads the GGUF's Q8_0 bytes, a different thing).  Opt-in.  The four BF16 hc_*
projections per layer (1,200 MiB) are skipped by the loader and uploaded as
int8 codes with one fp32 scale per 32 values (675 MiB); the freed VRAM goes to
the expert cache.

- Q8 is a template parameter of the down/up kernels (single- and multi-token):
  the BF16 instantiations compile exactly as before, the launch sites pick the
  Q8 ones when w_down / w_up carry scales.  The inject rows stay BF16.
- The staged / v3 / upmix / PF_HCDOWN / gfx906 split paths read BF16 rows and
  are skipped for it; the prompt path expands the codes into a bf16 scratch for
  its GEMM.
- The loader seeks with 64-bit offsets.
- A layer split keeps BF16 with a warning instead of exiting.
2026-10-14 07:11:52 +02:00
Niko1221 0c808eed00 RDNA2 SGEMM prompt GEMMs (#1123) are opt-in: STRATA_RDNA2_SGEMM=1 (gfx103x) / =all (any AMD card)
Fix-up to the ported #1123 commits.  The route is not bit-identical to the native call
(the author measured at most 4.3e-6 of the largest output apart), so unset keeps the native
path on every card, gfx103x included; =1 enables it on gfx103x devices only (a mixed layer
split keeps the native call on the other cards), =all on every AMD device for A/B arms and
tests.  The buffers are no longer freed under an in-flight GEMM: the stream is synchronised
before the FP32 copies grow, as the sm_60 FP32 route does.  docs/AMD_HIP.md says so.
2026-10-14 07:11:51 +02:00
vallicgrr 6ccdb14167 prefill gemm: a padded BF16 X (ldx, STRATA_PF_PAD) keeps the native call on the RDNA2 SGEMM route 2026-10-14 07:11:04 +02:00
vallicgrr 6dffb74a1f tests: hip_prefill_gemm crosses an RDNA2 SGEMM slice boundary (T 3300, K 10240; FP16 beta 1 with a padded ldy, and BF16) 2026-10-14 07:11:04 +02:00
Niko1221andSanghunYun d7298883b8 Let the resident RAM copy follow decode routing (opt-in)
Port of PR #1838 (commit fb868db01) onto 0.1.44.1. Test file merged with #2134's foresight test (both kept). replace_resident now drops a Foresight slot for the outgoing expert while its RAM place is rewritten (#2134's copies read those places).

Co-authored-by: SanghunYun <[email protected]>
2026-10-14 07:11:02 +02:00
Niko1221andvallicgrr 62a98cd353 docs: RDNA2 prompt GEMMs as SGEMMs (measured on an RX 6800), and a Windows gfx1030 report
Rebased onto 296b59d2: the docs/AMD_HIP.md conflict (the gfx1031/gfx1150/gfx1152 bullets main gained) is resolved by keeping main's text.

Co-authored-by: vallicgrr <[email protected]>
2026-10-14 07:10:58 +02:00
Rafa ad0582c3d4 #2146 tests: pa_bench (the prompt attention on a recorded selection); STRATA_QSA_DUMP_LAYER / _STEPS
STRATA_QSA_DUMP_LAYER=i keeps one QSA layer, STRATA_QSA_DUMP_STEPS=1 appends
the steps to each record.

pa_bench: the prompt sparse attention (qsa_prompt_attn_batch) on a
recorded selection - a STRATA_QSA_DUMP record of one layer and chunk with
its steps appended - random q and int8 K/V; median time and an output
hash for A/B of kernel variants (PA_BENCH_OUT=file writes the output).
2026-10-14 07:10:57 +02:00
Rafa 5d4c786760 #2146 sm_75: v2 prompt attention in one stage, three blocks per SM (bitwise)
On Turing the v2 int8 prompt attention (STRATA_PA_V2T=1) stages the next
chunk in registers, so its second shared-memory stage bought nothing - and
at 45.6 KB a block only one fit an SM (64 KB): four warps on four
schedulers, every latency exposed (ncu: 12.5 % warps active, tensor pipe
8 %).  Smem2T: one K/V stage, and the q.k partials of cell group nt
(8 cells) written over the 512 bytes of the warp's own K slice that held
those cells (read by then, a __syncwarp between) instead of their own
8.4 KB.  19.7 KB a block: three per SM (168 registers fit three).  The
same arithmetic in the same order - bitwise the same output.

RTX 2080 Ti, a recorded 130K selection (QSA layer 5, last chunk: 15871
queries x 2051 cells, tests/cuda/pa_bench.cpp): 113.8 -> 68.5 ms, same
output hash.  Engine (Q2_0 pack, 16K chunks, fused experts): 98K prefill
53.3 -> 49.9 s, 4K 3.54 -> 3.42 s; first logits bitwise identical at 98K
and 4K, the same generated text.
2026-10-14 07:10:57 +02:00
Rafa 0410d62aa9 #2092 sm_75: the v2 int8 prompt attention with register staging instead of cp.async (STRATA_PA_V2T=1)
On Turing the int8-KV prompt attention ran v1 because v2 stages its K/V
slices with cp.async. Here a warp loads its next slice into registers and
stores it into its other stage after the current chunk (the same bytes in
the same places); the MMAs are the m16n8k8 pairs v1 already uses. Accuracy
as v1 (qsa_prompt_attn_parity vs FP64: 3.7e-6 / 4.9e-6 / 4.5e-6 / 3.8e-6 of
3.5-3.7). RTX 2080 Ti, ms per chunk v1 -> v2: 32K x 1024 queries 13.0 -> 7.6,
64K x 512 6.7 -> 4.8, 1.5K 6.2 -> 5.0, 2.1K x 256 3.2 -> 2.3. Opt-in until
the engine A/B.
2026-10-14 07:10:56 +02:00
Rafa 8bdef963cc #2091 sm_75: the hyper-connection xn16 written as the FP16 its tensor-core GEMMs read (bitwise)
With STRATA_BF16_TC the prompt path converted xn16 (T x 10240) from BF16 to
FP16 before each of its two GEMMs (down and inject), in 16M-element slices:
~2.8 s of a 130K prompt read on an RTX 2080 Ti. The four xn16 writers now
store gemm.cu's conversion of the BF16 value (bf_to_hf_conv: the same clamp
and rounding as bf16_to_f16_kernel), and Gemm::bf16(..., x_f16) skips the
conversion on the tensor-core path (same slices, same GEMMs) and converts
back to BF16 on any other. Only when the stage runs BF16 on FP16 tensor
cores, without the BF16X2 low parts or a padded xn16 stride; the MTP draft's
own read keeps BF16. STRATA_XN_F16=0 turns it off.

First logits after a 98K prompt: bitwise identical; prompt read 1431 -> 1473
tok/s; a 4K run writes the same tokens.
2026-10-14 07:10:56 +02:00
imanu d976db3454 #2081 dequant: the prompt projections' BF16 dequant with 16-byte stores on sm_75 (bit-exact; STRATA_TC_SM75=0 keeps the per-group kernel)
The per-group dequant kernel writes 2 bytes every 64 bytes; 0.1.43 coalesced only the Q8_0 path (#1720). On compute
capability 7.5 the BF16 projections of the prompt path take a kernel that writes 16 bytes per thread; the values are
the same (a conversion, no arithmetic), so the output is bit for bit the old kernel's. Other cards are untouched.
2026-10-14 07:10:51 +02:00
Niko1221andvallicgrr 8f949956b2 HIP RDNA2 (gfx103x): run the prompt path's 16-bit GEMMs as FP32 SGEMMs
The rocBLAS the engine ships has tuned gfx1030 kernels for FP16->FP16, int8 and
FP32->FP32 only; every FP16/BF16-input, FP32-output GEMM (rocBLAS HS/BS) runs a
fallback kernel at ~5 TFLOPS. Widening the inputs to FP32 is exact and SGEMM
accumulates in FP32 like the native call.

Nothing passes through FP16, so unlike STRATA_HIP_PROMPT_F16=1 (#835) the
route cannot overflow: an FP16 GEMM output above 65504 becomes inf and can
spread as NaN, while here it stays a finite FP32 value. It is slower than the
FP16 route, and not bit-identical to the native call (at most 4.3e-6 of the
largest output apart on random inputs).

RX 6800, Coder IQ1_M, fresh 12K-token prompts (4 each, A/B in one binary via
STRATA_RDNA2_SGEMM=0): prompt 312 -> 452 tok/s, GPU timeline 37.2 -> 25.5 s
(gdn 9.4 -> 2.8 s, qsa proj 3.6 -> 1.4 s, hc read 3.85 -> 2.84 s). Decode
unchanged. A 9-task code-repair benchmark: 9/9 first try on both, model time
458 -> 374 s.

Default on for gfx103x only; N < 64 keeps the native call; if the FP32
buffers cannot be allocated the native call runs.

Rebased onto 296b59d2: the conflict in Gemm::f16 and gemm.hpp (the CUDA FP16 algorithm fallback and the sm_60 STRATA_DENSE_F32 block that main gained) is resolved by keeping both; the RDNA2 call sits before the CUDA/HIP GemmEx call.

Co-authored-by: vallicgrr <[email protected]>
2026-10-14 07:10:39 +02:00
Rafa d5b80b2e65 #2093 sm_75: the prompt path's top-k with one full read of the scores (identical ids)
block_topk_wide_kernel reads a query's scores six times (four radix passes,
a count, the emit): past ~115K cells that is DRAM traffic. block_topk_sample_kernel
takes a bound from every 32nd block (the KS-th largest of those keys), reads
all blocks once keeping those at or above it, and when they hold at least
`width` cells computes block_topk_kernel's threshold, `above` and tie budget
over them and emits them in block order (bitonic sort): every block at or
above the threshold is a candidate, so the ids are the reference's.
Otherwise the query is flagged and block_topk_wide_kernel<true> runs it.
qsa_topk_parity --selftest and qsa_topk_active_parity: identical ids
(continuous, 64-level, equal scores - the last ones take the fallback).

RTX 2080 Ti, 256 prompt queries under a 512K capacity: 131K 0.51 -> 0.45 ms,
262K 0.95 -> 0.59, 400K 1.48 -> 0.71, 520K 1.84 -> 0.79. Used above 28,672
active blocks; STRATA_TOPK_SAMPLE=0 keeps the wide kernel.
2026-10-14 07:10:32 +02:00
Rafa 050229ecda #2072 sm_75: the decode QSA selection at long context, split top-k and halving scorer (bitwise)
A verify window's 1-8 queries scored and selected on a handful of SMs; at
420K cells on an RTX 2080 Ti the two took ~6 ms of a ~52 ms window.

- block_scores_halve_kernel: the decode scorer's warp sums as one
  recursive-halving reduction (each value pairs lane l with l ^ o at offsets
  16..1, the butterfly's additions operand for operand), the lane's query
  values in registers (shared-memory reads were the limit, ncu mio_throttle),
  5-8 queries as two calls of up to 4. Same bits (qsa_select_bench
  QSA_BENCH_DECODE=1 hashes, 32K-524K, 1-8 queries). 420K: 1 / 3 / 4 / 6 / 8
  queries 117 / 265 / 347 / 510 / 774 -> 101 / 118 / 125 / 238 / 255 us.
  STRATA_SCORES_HALVE=0 keeps the old kernel.
- qsa_block_topk_split: the decode top-k over chunks of 2,048 blocks in six
  launches (four radix passes into per-query global histograms, a count, the
  emit); every CTA takes each digit from the complete histogram with
  block_topk_kernel's rule, so the ids are identical (qsa_topk_parity
  --selftest: continuous, 64-level and equal scores, 2K-524K). Decode calls
  at 420K: 0.21 -> 0.033-0.064 ms; short contexts unchanged within 0.01 ms.
  STRATA_TOPK_SPLIT=0 keeps the wide kernel (=1: on any card, for tests).

Both on sm_75 only by default.
2026-10-14 07:10:28 +02:00
Rafa 3f691eb345 #2071 sm_75: STRATA_SELECT_SIMT=2, the tiled FP32 block scorer with 32 x 128 tiles
block_scores_simt2_kernel: 8 x 8 products per thread, twice the blocks per
CTA and the next K chunk in registers; every dot is the same fmaf chain over
k = 0..127 and the same relu sum, so its scores are bitwise those of
STRATA_SELECT_SIMT=1 (qsa_select_bench QSA_BENCH_HASH=1, 131K-510K).
RTX 2080 Ti, 256 queries: 131K 1.21 -> 0.95 ms, 262K 2.01 -> 1.87,
400K 3.00 -> 2.82, 510K 3.77 -> 3.57 (the warp kernel: 7.7 / 15.3 / 23.2 /
29.6 ms). Opt-in like =1 (another summation order than the warp kernel).
2026-10-14 07:10:27 +02:00
Breno Perucchi 653f011360 prefill: gather experts in groups on short prompts too (resident and staged)
Below stream_all_min() the MMQ path gathered every expert with its own launch
and, for a staged one, its own wait and release event. The staged walk now
groups like the streamed walk: its ring is STAGE_GRP (32) slots, two groups, and
it stages at most 15 entries ahead, so a group's staged slots are not refilled
before the group is gathered (one wait on its last copy, one event releasing
them all). stage_slots() counts those 32 slots wherever the ring is counted or
taken, so a prompt borrows every byte it writes.
STRATA_PREFILL_GROUP_GATHER=0 turns grouping off everywhere, as before.
2026-10-14 07:10:25 +02:00
Rafa 80872d4349 #2070 sm_75: hc up kernel with batched row loads for 3+ tokens, down token pairs for T 4/6
gr_up75_kernel: two batches of 4 rows of w_up loaded before the dots, the
token activations read once per batch, the 4 xor reductions interleaved and
the row tails held 4 rows to a uint4 - bitwise gr_up_multi_kernel (gr_parity,
gr_multi_parity, fused_gr_bench hashes). Used from 3 tokens on sm_75
(STRATA_GR_UP75). The staged down kernel takes a token group from
blockIdx.y; sm_75 runs T 4 and 6 as pairs (STRATA_GR_DOWN_TG).

fused_gr_bench cold, RTX 2080 Ti, whole read: T3 53.2 -> 50.2 us,
T4 64.1 -> 57.6, T5 76.2 -> 69.3, T6 86.1 -> 70.9; T1-2 unchanged.
2026-10-14 07:10:24 +02:00
Rafa 26855986e1 #2069 sm_75: grouped native experts default to mode 4 (down: mode 0 in windows of 4+ tokens)
native_expert_bench on real Q2_0 rows of Flash-Next, RTX 2080 Ti, bitwise
equal to mode 0 in every case: 10 groups x 1 entry 47.3 -> 41.4 us,
20 x 1 83.7 -> 71.5, 30 x 1 120.2 -> 100.2, 20 x 2 124.2 -> 111.4. The down
projection of mode 4 loses with 3+ entries per group (12 x 3 36.5 -> 40.8,
16 x 4 56.9 -> 68.9), so cap_groups > 30 keeps mode 0 for it.
STRATA_SM75_EXP=0 keeps the CUDA layout; STRATA_EXP_MODE still overrides.
2026-10-14 07:10:23 +02:00
Niko1221andsergiywith 3f2db5e2c5 decode: the adaptive tier's evictions reach the device's residency table before the next window when the tier does not wait (STRATA_ADAPT_NOWAIT=1, STRATA_ADAPT_LAG > 1)
adapt() marks an evicted expert non-resident in host_res at once; d_res follows in apply_pending, once the round's
copies have landed.  When the tier does not wait for them (STRATA_ADAPT_NOWAIT=1, or STRATA_ADAPT_LAG > 1) the next
window runs before that.  doorbell_publish_res reads d_res, sees the evicted expert as resident, and when every routed
expert of a layer looks resident it does not publish the layer's activation.  The pool plans from host_res and
computes the evicted expert on the CPU from the activation published before.  Now every verifier launch (run,
run_slot_rows, batch_launch, pl_launch; a layer split's stages too) runs a pre-launch hook.  It patches the device
tables from a list of changed entries: res_patch, a small kernel on the verifier's stream reading mapped memory; the
whole table when the list overflows or a device does not map it at the host's address.  A failed whole-table upload in
apply_pending leaves its entries to the hook.  Only where the tier does not wait.  --batch-groups with a layer split
publishes every activation instead: set_always_publish, which now also turns E-6's device plan off.
--pipeline-windows keeps its fence.  STRATA_ADAPT_EVICT_SYNC=0 restores the old behaviour.  STRATA_ADAPT_CHECKRES=1
reads the tables back before each window, compares them with host_res, and counts the layer-windows that computed a
CPU expert with no activation published.

RTX 5090, IQ2_XS, --expert-cache 12000, 32K explain, 600 tokens: NOWAIT=1 34 of 222 windows with mismatched tables
(2470 entries), 1 such layer-window -> 0 / 0 / 0; LAG=2 55 of 223 (3222 entries: every swap), 5 -> 0 / 0 / 0.  LAG=2
is reproducible (two runs of each arm, the same tokens), and the fix changes its answer from token 228.  The hook's
cost under NOWAIT (6297 slots, 3 pairs): ms a round -1.1% chat, -1.2% 32K, noise.  The default (the tier waits)
installs no hook: tokens and first-token logits identical to d5ea7133 (p2k 200 tokens, 32K explain 600).

Port of PR #1517 (commit eb4796045) onto 0.1.44.1. Conflicts with the 0.1.43 adapt overlap gate and the tail-skip kind -2 resolved; set_adapt_gate and set_always_publish kept side by side. Docs line added.

Co-authored-by: sergiywith <[email protected]>
2026-10-14 07:10:19 +02:00
Niko1221 80bed76c8a tools/test_setup_mac: the --source test no longer runs setup.data_folder() for real
The real data_folder() moves the model files of this checkout and of the data folder named in the user's settings.json into --data-dir and saves that folder as the new data folder. With a TemporaryDirectory the models are deleted on exit and settings.json is left pointing at a deleted directory (found on the M4 and on the PC: the test wrote %APPDATA%/Strata/settings.json and ~/.config/strata/settings.json). The test is about --source, so data_folder is mocked.
2026-10-14 07:10:16 +02:00
Rafa 004efd4606 #2069 sm_75: interleaved small-batch matvec table for Turing (kIlRows_75)
The 2-4 column dense projections of the verify windows ran the plain multi-column kernels on Turing, which are
bound by dp4a throughput there from 2 columns on. mmvq_il_parity --bench --emit-table on an RTX 2080 Ti (SM 1650
MHz) gives a table like the Volta/Pascal ones: IQ4_XS 2560x10240 at 4 columns 81.1 -> 37.4 us, Q4_K 74.5 -> 39.1,
the Q5_K head 1671 -> 1045 us. Bitwise equal (the decode writes the same tokens). No one-column table: the
engine's dedicated single-column kernels sum in another order, for a 0.5% gain. STRATA_SM75_IL=0 turns it off.

Q2_0 512K resident, 4K prompt: one-shot decode 52.6 -> 55.5 tok/s; serve steady state ~69 -> ~77 tok/s.
2026-10-14 07:10:01 +02:00
sergiywith af0e9d3c1b prompt attention: STRATA_PROMPT_ATTN_IMMA=1 - the int8-KV kernel on INT8 tensor cores (opt-in, closer to FP32)
prompt_attn_i8v3_kernel: QK^T and PV as mma m16n8k32 on the int8 K / V codes as stored; the other operand in three
exact 8-bit parts (q scaled per head and 64-dim group, p * v_scale per row and chunk; X = rint(x * 65536) split into
h, l signed and m unsigned bytes, a u8 x s8 MMA): 24 bits, exact int32 sums, combined in FP32.  One K and one V stage
per warp, 12-row partials, launch bounds (128, 3): ~25.5 KB, 3 blocks an SM.  sm_80+ (STRATA_PA_SM80); Turing,
Volta and HIP keep their kernels.  Unset: v2, byte-identical.

qsa_prompt_attn_parity: against FP64 IMMA 2.15e-6 - 2.64e-6, v2 2.78e-6 - 3.30e-6, the FP32 kernel 1.90e-6 - 2.51e-6.
IQ2_XS, first-token KL to the FP32 kernel (STRATA_PROMPT_ATTN_OLD=1): median 0.0027 (IMMA) against 0.013 (v2);
2K 0.0026 against 0.0248.  1.35-1.53x a launch; a 32K prompt in 8K chunks 358 -> 312 ms of attention.
2026-10-14 07:09:47 +02:00
Niko1221 f288cbfea9 F16_RANGE counters (#1149): HIP only, and the gfx906 compat layer maps cudaMemcpyFromSymbol
Fix-up to the ported #1149 commits.  The range counters and the saturating to_f16
are compiled for HIP only, so the CUDA kernels (hf_sat in the SwiGLU product, the
embedding image) stay exactly as they were, with no flag read; set_f16_range /
f16_range_read are no-ops there.  strata_hip.h (the STRATA_HIP_GFX906 compat layer,
which goes first on that backend's include path) gets the cudaMemcpyFromSymbol
mapping the HIP shim already has, so the counters also compile for gfx906.
2026-10-14 07:09:41 +02:00
Niko1221andsergiywith 04be241a5a decode: STRATA_PCIE_BALANCE=1 picks each layer's PCIe count from measured costs
The verify window reads pcie_frac of a layer's missed experts over PCIe, a share
the link probe sets; the CPU's speed does not enter it.  With a slow CPU the GPU
spins on the pool's rows: IQ2_XS with one AVX2 pool worker (emulated) runs
16.8-17.2 ms a round at the probe's 0.55.

Opt-in, STRATA_PCIE_BALANCE=1 (one GPU, no batch slots, no --pcie-frac):
- wait_flag_ge_stamped: the flag spin kernels also write the GPU clock as the
  plan arrives, as the PCIe part starts and as the GPU waits for the CPU's rows
  (no extra launch; captured only with the switch on);
- the host times its pool per step; after each window, least squares with
  forgetting fit the pool's a + c n_cpu + d n_pcie (d: the link's DRAM reads
  slowing the pool - on a DRAM-bound pool moving experts to PCIe saves nothing)
  and the GPU's g0 + g n_pcie;
- a layer then reads over PCIe the m of its misses that minimizes the longer
  side; every 64th layer that would keep them all on one side moves one, so
  both fits stay measured.

IQ2_XS, RTX 5090 + 9950X3D, chat to the end of the turn:
- one AVX2 pool worker: 16.77 / 17.17 -> 12.98 / 12.82 ms a round
  (fit: CPU 42-60 us an expert, GPU 28 us a PCIe expert; 0.8 of the misses
  move);
- the 9950X3D's 16 workers: 3 pairs 12.19 -> 12.17 (pool DRAM-bound, few move).
Off (the default) the logits and 32 tokens equal v0.1.39 (2K, fixed cache).

Port of PR #1548 (commit a513394c4) onto 0.1.44.1. Conflicts with the 0.1.43 tail skip, PCIE_MIN1 and the fused waits resolved: the fused wait+copy launches stay off while the balance stamps are on. Docs line added.

Co-authored-by: sergiywith <[email protected]>
2026-10-14 07:09:32 +02:00
sergiywith cffe31d43e prefill: opt-in STRATA_HC_UPMIX=1 on CUDA - the hyper-connection up projection with gr_mix_r as its epilogue (sm_80+)
The up GEMM of each hyper-connection read writes `gated` (T x 10240 FP32, 336 MB at an 8K chunk) and gr_mix_r reads
it back with R at ~96% of the bandwidth - only fewer bytes help.  gr_upmix_cuda_kernel (128 tokens x 32 columns x 4
streams a block, K = 320 in cp.async-staged slices of 32, BF16 mma.m16n8k16 with FP32 accumulation, the mix in
registers in gr_mix_r's order writing all its outputs) never writes or reads `gated`.  Behind the gfx11 switch;
sm_80+ per device (STRATA_EMULATE_CC honoured), chunks of >= 33 tokens; else the pair.  Unset: unchanged.

gr_upmix_parity (new ctest): bitwise the cuBLAS + gr_mix_r pair at T >= 33 on an RTX 5090 (cuBLAS 13.3), <= 1.8e-7 at
T <= 32, both as close to FP64.  1.42x / 1.81x / 2.19x the pair at 2K / 8K / 32K; IQ2_XS: an 8K prompt -4.4%, 32K
-3.9% (the hc read -19% / -24%).  Logits identical with it on (600, 2K, 32K); the 32K greedy tokens moved only through
the time-driven suffix-draft policy (identical with --suffix-draft 0).
2026-10-14 07:09:30 +02:00
Niko1221andsergiywith c675f5b787 prefill: quantize each token's MoE input once and scatter it to its k rows (the same bytes)
mmq::quantize(m.mixed, m.src_dev, ...) read and quantized every token's row of `mixed` once per routed expert (K =
10).  mmq::quantize_scatter uses llama.cpp's quantize_scatter_mmq_q8_1_cuda (the pinned quantize.cu strata_mmq
already compiles): each token quantized once, its block written to all of its rows through slot_dev, the inverse of
src_dev.  The same q8_1 bytes, so the default; STRATA_QUANT_GATHER=1 keeps the gather.  No new device code (CUDA and
HIP compile the same kernels); SYCL's prefill.cpp untouched.

prefill_mmq_scatter_test (new ctest): every MMQ q8_1 layout (D4, DS4, D2S6), T = 1..2099: 0 differing bytes.  IQ2_XS
600 / 2K / 32K and Q2_0 2K against e8ca9afd: identical first-token logits and 32 greedy tokens.  RTX 5090 (96 MB L2):
the quantizer 2x at 2K, even at 8K (the chunk's input fits in L2), 1.4-1.9x at 32K; a 32K prompt with
--prefill auto:32768: 77.5 -> 58.1 ms of quantization.

Co-authored-by: sergiywith <[email protected]>
2026-10-14 07:09:21 +02:00
Niko1221 f01b989264 sycl: mmvq_bench checks the STRATA_Q6_PLANAR copy and a gathered subset bitwise against the GGUF-layout result (#2340) 2026-10-14 07:08:52 +02:00
Francesco Albano 051b970303 cpu pool: --host-core sibling, the host on the first core's other hardware thread (hybrid CPUs too)
Windows sends a GPU's interrupts to one logical processor, usually the first,
and the host thread spins there (--host-core first, the default). --host-core
last moves it to the last physical core, but not on a hybrid CPU, whose first
core is its best P-core, so a 12th-14th gen Intel or a Core Ultra keeps the
host on logical processor 0 with the interrupts.

--host-core sibling (or STRATA_HOST_CORE=sibling) keeps the host on that same
first core but on its other hardware thread. The interrupts keep the first
logical processor, which nothing else is pinned to, and the workers keep
every other core, since they take one logical processor per core (with
--pool-affinity auto / p-cores, which also use the P-cores' siblings, the
host's sibling is taken out of their list). Without an SMT sibling it is
--host-core first. It works the same on Linux (the sibling from sysfs), where
the interrupts are usually spread anyway.

detect_cpu_topology records the host core's sibling (CpuTopology::host_sibling)
in each layout; pool_affinity_test checks, in every affinity mode, that
sibling puts the host there with no worker on its core, and that it is first
without SMT. The startup log names the placement.
2026-10-14 07:08:35 +02:00
xjc10 c211cb3ebe hip gfx103x FP16 prompt: STRATA_F16_RANGE counts what enters and leaves FP16; the range measured (outputs peak at 410 of 65504) and the FP32 route compared
The README's range check said "none beyond 65504" over 110K tokens without
the numbers. The engine now has the counter: STRATA_F16_RANGE=1 records,
per device, the largest |value| and the count beyond 65504 (or not finite)
where a value enters or leaves FP16 - the activation images (hf_sat, the
image writers' one funnel), the BF16 weights converted to FP16
(bf16_to_f16_rows) and the FP16 GEMM outputs as they are widened
(widen_rows_f16: an output rocBLAS wrote beyond the range is Inf there) -
and prints one line per prompt. Off, the cost is one flag read per value;
on, a 34.4K-token prompt read at 889.8 tok/s against 888.5. to_f16 (the
hc image for the FP16-weight GEMMs, the PLE key image) saturates like the
other image writers now, so every FP16 image is under the same rule. The
HIP shim gains cudaMemcpyFromSymbol.

Measured on one RX 6900 XT over 466K tokens in nine prompts (corpus
slices, two prompts built to push activations - delimiter floods, a token
repeated 4,000 times, 6,000-character runs, base64, five scripts - and
four batches of real requests): outputs peak at 409.5 (160x below 65504),
activations at 112.2, the BF16 weights at 11.56; nothing beyond the range,
nothing non-finite. The prompts built to push activations stayed below
the ordinary corpus. One model (GSQ-RCO IQ3_S); the table is in the
README's range section.

The README also gains the same-card comparison with #1006, which takes
these GEMMs as FP32 SGEMMs: 8.4K / 32.8K / 104K-token prompts 412 / 455 /
456 tok/s on the old path, 622 / 742 / 750 with #1006, 730 / 900 / 904
with this change (the card's FP32 rate against its FP16 rate), with the
phase times and what the SGEMM route covers that this change does not.

(cherry picked from commit e780c8581e)
2026-10-14 07:08:33 +02:00
xjc10 d0838c6c3a tests: hip_prefill_gemm runs the FP16-io prompt GEMMs (set_f16_io) on any HIP card, and its BF16 inputs are no longer zero
The test ran only the FP32-out GEMMs, so the gfx103x prompt path's FP16-out
GEMM (f16_inplace, widen_rows_f16) and bf16()'s W conversion through the
scratch were not under ctest. Every shape now runs a second time with
set_f16_io(true), forced on whatever HIP card runs the test: X as the FP16
image for the BF16 products, a scratch of 64 rows so a 96-row weight converts
in two slices (the second written at Y + 64), ldy > N, an odd N (257), T = 1,
and a beta = 1 f16() call, which keeps the FP32-out GEMM. FP16-out results are
checked against the double reference at FP16's rounding (6e-4 relative per
element plus 1e-4, rel L2 < 1e-3); the row padding and the guards around Y
must be untouched, as before. The FP32-out runs keep their tolerance.

Found while adding them: the BF16 inputs were all zero. hip_bfloat16(float)
produced data 0 in this test's build (ROCm 10.0, gfx1030; not traced further),
so the two BF16 cases passed on nothing (rel L2 printed 0). The BF16 bits are
now made by hand (round to nearest even on the float's bits); with real inputs
the BF16 cases pass at rel L2 1.9e-07 (FP32 out) and 2.2e-04 (FP16 out).

On an RX 6900 XT (gfx1030, ROCm 10.0): 11 of 11 pass.

(cherry picked from commit 4c6c9fe374)
2026-10-14 07:08:32 +02:00
libratechw b6ccf873b8 prefill: the register top-k from 16K cells of context on gfx1151 (STRATA_TOPK_REG_MIN_BLOCKS, gfx1151's table sets 4096)
On HIP a prompt batch with fewer than 7,168 blocks (28K cells of context) took the original top-k kernel, a line measured on
gfx1201 before the cooperative scan.  With the scan the register kernel is faster from about 15.5K cells on gfx1151 (2,048 queries:
original / register kernel 0.57 / 0.82 ms at 13K, 1.01 / 0.87 at 16K, 2.4 / 0.93 at 20K, 3.9 / 1.00 at 24K).  The line is now
STRATA_TOPK_REG_MIN_BLOCKS (default 7168, as before) and gfx1151's table sets 4096.  The selected cells are the same
(qsa_topk_parity, also run with the register kernel always on: ctest qsa_topk_parity_reg_always).
2026-10-14 07:08:28 +02:00
0FL01 557b79e78f test: cover exact multi-row and fused HIP paths on gfx906 2026-10-14 07:08:27 +02:00
libratechw 6ef23b8966 prefill: the QSA top-k digit by a cooperative scan (same ids)
block_topk_reg_kernel picked each radix digit with thread 0 walking up to 255 bins while the other threads waited.
Threads 0-255 now prefix-sum the bins in descending order, and the one where the count above reaches `width` takes the
digit (bin 0 when none of 255..1 does). The digit and the count above are the same, so the selected ids are the same.

Measured on a Ryzen AI Max+ 395 (gfx1151, ROCm 7.14.1), qsa_topk_parity with 2,048 queries (CTX 2048 10 <ctx> 1),
ms per call:
  32K  2.19 -> 1.11 (-49%)
  64K  2.54 -> 1.63 (-36%)
  128K 4.83 -> 3.79 (-22%)
qsa_topk_parity --selftest: 19 PASS. UD-Q4_K_XL end to end, 3 interleaved rounds: the same text in every round; the
128K prompt moved +0.2%, inside the noise, so the gain is the kernel's and not yet visible end to end.

CUDA (RTX 3060, Windows, CUDA 13.0, sm_86), same call, ms: 4K 2.12 -> 0.975, 8K 2.04 -> 1.03, 16K ~1.9 -> ~1.1, 32K ~2.0 -> 1.27, 64K 2.53 -> 2.15, 128K 7.29 -> 7.29 (no change); qsa_topk_parity --selftest passes, ids identical in every case. Not built: SYCL.
2026-10-14 07:08:23 +02:00
Niko1221andnekomario28 719b733e01 dq_q2_0: keep the Q2_0 signed-zero fix on every HIP arch/version (#1540, #1474)
The negative-scale-times-zero workaround was gated to an arch list (gfx1012 on
HIP < 7, gfx1151, gfx1200/gfx1201 since 0ff45cffb); the list only ever chased
the newest report. The workaround writes the scale's sign bit for code 1, which
is value-identical on targets whose compiler never folds: keep it on every HIP
build. Ported from PR #1540 onto the tree that already carries the gfx1200/1201
entries; the comment text is adjusted.

Co-authored-by: nekomario28 <[email protected]>
2026-10-14 07:08:23 +02:00
Xiaomi2008 1ab0fbd02a --pool-affinity measure: on a hybrid CPU, time the all and p-cores pool layouts at start and take the faster (opt-in)
The pool's default layout puts a worker on every physical core, and a layer's
experts are done when the slowest worker is. On a Core i7-13700K (8 P + 8 E
cores) the E-cores make the verify window wait, by an amount that changes from
run to run.

`--pool-affinity measure` (hybrid CPUs, native packs) times both layouts on
the pack's own experts before the pool is built: two experts of four tokens
per layer through run_split_multi_native, every layer in turn, the host
spinning ~150 us between two layers, three interleaved blocks per layout,
about a second in all. p-cores is taken unless all is more than 10% faster.
One line says what it read and took. It is one reading at start and is not
repeated.

Measured on this branch (0.1.42 + this change), Core i7-13700K, RTX 5090,
64 GB, Windows 11, Swift 1.5 IQ3_XXS, 128K context, one 8K prompt and the
same 1,500 forced tokens (--spec-follow), three interleaved rounds:
  default (all, 15 workers)   146.6 / 151.8 / 158.0 tok/s, pool 6.3-7.6 ms per window
  --pool-affinity measure     200.0 / 201.5 / 204.8 tok/s, pool 2.1-2.2 ms (read all at 16.4-17.6 ms, took p-cores)
  --pool-affinity p-cores     200.3 / 203.9 / 204.9 tok/s, pool 2.1 ms
Over four server starts of one day on 0.1.41 it read all at 14.8, 21.9 and
25.3 ms against 6.1-6.2 ms for p-cores, and once all at 6.6 ms against 8.6 ms,
where it took all.

Without the value nothing new runs: the option parses as before and the
function is not called. The layout changes no result, only where threads run.
Built for CUDA only (sm_120, CUDA 13.0.88, MSVC 14.50 with nvcc's
--allow-unsupported-compiler); HIP and SYCL were not compiled (the change is
in generate.cpp, which both build). Not measured: other hybrid CPUs, Linux.
2026-10-14 07:08:06 +02:00
aangelinsf fde1d795ef SYCL verify: batch windows keep the doorbell nodes under the lean window
0.1.43 made the decode window lean under STRATA_VERIFY_NO_HOST with the device
plan (46a77907): the doorbell publish, flag waits and plan copy are dropped
because no host answers them. capture_batch() records batch windows through the
same record_window(), so a batch graph was also recorded lean, but the host batch
path (run_slot_rows / batch_poll) still waits for each layer's doorbell unless the
stage is all-resident. On a stage with mirrored experts the graph finished with
the ring silent: "verify batch: layer 0 never rang (graph finished)", then
UR_RESULT_ERROR_UNINITIALIZED and exit 139 at the first shared window.

Leave lean off while recording a batch window (batch_rec_). The solo window
stays lean. Batch tokens are identical to a run with STRATA_VERIFY_LEAN=00.
2026-10-14 07:07:51 +02:00
W1nge ccba2d5fd3 core: write reduced helper output directly to mapped host memory 2026-10-14 07:07:49 +02:00
Zack ea08bd6e81 decode: size --lookup-chain's window cap from the cap in force, not the stale mtp_max_t
With the default --suffix-draft 3 the suffix block above already raises --spec by 2
(4 -> 6) and writes mtp_max_t = 4. The --lookup-chain block then computed
min(mtp_max_t + K, 8) = min(4 + K, 8), so with --spec 4:

  K=1 -> max(6, 5) = 6   (unchanged: the flag does nothing)
  K=2 -> max(6, 6) = 6   (unchanged: the flag does nothing)
  K=3 -> max(6, 7) = 7

Measured on 0.1.40 by reading the cap back from /metrics engine.spec after a restart
per row; K=1 and K=2 were indistinguishable from not passing the flag.

Size from the cap actually in force instead, so K adds up to K of headroom while the
kVerifyMaxT = 8 ceiling and the mtp_max_t bound on the MTP's own drafts are preserved.
Behavior is unchanged when --suffix-draft is 0 or when the cap is already at 8.
2026-10-14 07:07:36 +02:00
yjamil8 c41c0ebbd1 KV streaming under WSL: pin the K/V host copy with cudaHostRegister
Under WSL2 the NVIDIA driver caps what cudaHostAlloc(Mapped) can pin at about
1 GiB in all, so the KV streaming host copy (layer.cpp) cannot be allocated
and setup turns streaming off there: the whole KV cache must sit in VRAM,
beside the expert cache. cudaHostRegister of ordinary memory is not capped the
same way; the expert arena already registers tens of GiB with it on the same
machines (pinned.cu).

kv_host_alloc() maps anonymous memory and registers it Portable|Mapped, before
any page is touched, when /dev/dxg exists (WSL2, detected as generate.cpp's
under_wddm() does). Elsewhere cudaHostAlloc stays first. Either way the other
method is the fallback when the first is refused, and
STRATA_KV_HOST_REGISTER=1/0 forces the order. On native Linux and Windows the
behaviour is unchanged unless cudaHostAlloc is refused (by inspection; not run
there). The failure message no longer says WSL pins only 1 GiB.

Measured on one RTX 5090, Ryzen 9 9950X3D, WSL2 (157 GiB), Windows driver
591.86, IQ3_S, --max-context 1048576 --rope-scaling yarn --rope-scale 4
--kv int8 --kv-resident 32768, with this commit:
- start: "the K/V in 12.38 GiB of pinned RAM"; expert cache 11,609 slots
- tools/needle_bench.py: 4/4 found, 128K and 1M (1,015,070 prompt tokens) at
  depths 10 and 90
- decode 99-124 tok/s with 0.5-1M tokens in context (4 runs); 150-191 tok/s
  medians from 55-token prompts to 128K (single runs 113-196); prefill about
  4,200 tok/s for a cold 1M prompt
kv_stream_parity still passes; it allocates its own host pools, so it checks
the streaming kernels, which this change does not touch.

Not tested: layer split or remote experts under WSL, Docker Desktop.
setup.py still never writes --kv-resident on WSL and removes it there
(upgrade_config); until that changes it has to be added by hand.

Port of PR #1498 (commit 79b43be18).
2026-10-14 07:07:32 +02:00
Evan Lightcap f2e142f444 resident RAM mode: a budget keeps the prompt path's lend region when it has room (#1683)
pin_cache_complement set lend_from_slot = -1 whenever --resident-budget-gib was given, so the experts of the cache
slots the prompt path borrows were in neither VRAM nor RAM during a prompt and were read from the model files on every
chunk, and again when the slots were refilled - even with room left in the budget. The budget branch now appends the
lend region's experts after the ranked ones, from the last slot down (the order the borrowing takes them), while they
fit; the budget stays a hard cap, and the ones past it keep the file fallback. The start-up line reports the count, and
the lend warning names a larger budget as the remedy when one is set.

Measured on an RX 6900 XT 16 GB (HIP gfx1030), Ryzen 9 5950X, 125 GB RAM, UD-Q4_K_XL, --resident-budget-gib 71 (the
copy held all 63.47 GiB outside the cache, 7.5 GiB unused; 1,231 lent slots = 3.60 GiB), engine 0.1.42, one run per
case, greedy: file reads of the lent experts per request 0.5-2.6 GB -> 0; SSD reads per fresh 8K / 16K prompt 2.8 /
1.9 GB -> 0.3 GB; prompt-path host staging 0.8-2.1 s -> 0.06-0.5 s per request; fresh prompts 887 / 7.8K / 15.8K
tokens 180 -> 194, 633 -> 676, 677 -> 698 tok/s. Decode unchanged.

Port of PR #1896 (commit 29063eb2b).
2026-10-14 07:07:32 +02:00
Xiaomi2008 fa1d1d1ebb STRATA_EXCHANGE_ROTATE: rotation for packs whose layers differ in expert block size (spares kept per size)
Rotation hands the evicted expert's exchange buffer over as its place in the
RAM copy instead of copying the bytes there. It required one block size for
all layers and fell back to the copy path on any other pack: Swift 1.5 IQ3_S
has seven sizes (1,510,400 to 2,662,400 bytes) and IQ3_XXS nine.

A swap exchanges two experts of one layer, so the slot the promoted expert
leaves has the size the evicted one needs. ExchangeStorage now keeps its
spares per block size (initialize_sized): an exchange takes a spare of its
layer's size and hands back one of the same size. commit() refuses a spare of
another size and an expert of another layer. initialize() keeps the uniform
geometry and its checks. exchange_buffer() takes the layer; reserve_exchanges()
takes the number of trailing buffers that only stage copies (--adapt-async's
second half), kept in the largest size alone. With --adapt-async 1 a rotated
round flips in the tick that sees the copies in: there is nothing for the job
to move, so the round ends one verify window sooner.

Still opt-in (STRATA_EXCHANGE_ROTATE=1); unset, nothing changes. The exchange
allocation grows to one spare of every size per swap of a round: 1.06 GiB of
page-locked RAM on IQ3_S with --adapt-swaps 80 (1.26 GiB with --adapt-async 1)
against 0.20 and 0.40 GiB.

Measured on a Core i7-13700K, RTX 5090 32 GB, 64 GB, Windows 11, Swift 1.5
IQ3_S, 128K, --resident-experts, --adapt-every 1 --adapt-swaps 80, p-cores:
  one 8K prompt, the same 1,500 forced tokens, blocking tier, rotation off / on:
    161.6-165.1 tok/s (five runs) / 184.9-188.7 (four runs); two runs of each
    arm with the same cache size (10,681 slots) wrote identical --window-hashes
    for all 434 windows
  --serve, 23 coding-agent turns, greedy, three interleaved rounds, blocking tier:
    147.8 / 159.2 / 158.4 (the build before) -> 175.2 / 184.9 / 172.8
  the same turns with --adapt-async 1, one binary, two rounds:
    166.0 / 170.1 -> 185.6 / 182.5
The tier swaps about 30 experts per verify window on this box (44% of the
experts fit in VRAM), so the copy path moved about 50 MiB of RAM per window.

tests/core/exchange_storage_test.cpp gains a three-size case (6,144 exchanges)
and passes built alone with MSVC 14.50. Built for CUDA only (sm_120, CUDA
13.0.88, MSVC 14.50 with nvcc's --allow-unsupported-compiler); HIP and SYCL
were not compiled (expert_source.cpp and generate.cpp are built by both). Not
measured: Linux, AMD cards, a layer split.

Port of PR #2042 (commit 8db375018).
2026-10-14 07:07:31 +02:00
Katsumi Takeuchi 9de548d198 sycl opt-in: STRATA_IQ3S_WIDE=1, a wide mmvq kernel for the dense IQ3_S matrices
The multi kernel reads the dense IQ3_S matrices (attn_q, attn_gate, ssm_out, attn_k, the shared experts' gate/up)
at 76-114 GB/s on the B70. The new kernel has the shape of the Q4_K..IQ4_XS wide kernels. unitrace, one card,
IQ3_XXS, T=1: worst attn_k (512 rows) 77 -> 123 GB/s, best attn_q (12288 rows) 114 -> 307 GB/s; these matrices take
0.60 ms of kernel time per token instead of 1.36 ms.

Unset or 0: the multi kernel, output identical to main. With the option the greedy output parts from the default at
token 198 of 256 (the sub-blocks are summed in another order).
2026-10-14 07:07:25 +02:00
libratechw edf61f18e9 prefill: the VGPR-capped gfx11 fused expert kernels are on again for gfx1151 on clang 23, except IQ2_XS and Q8_0 (#1180)
Since 0.1.40.2 the waves_per_eu(8) variant of native_w11_kernel is uncapped on clang 22 and newer, because clang 22
computes wrong results with it on gfx1100. On gfx1151 with clang 23 (ROCm 7.14.1) the capped kernels give the same
bits and take less time, as alexdns1 measured in #1180. The cap now applies there again, per format
(hip_prefill_fused_iq, one layer, 2048 / 3584 / 8192 tokens, the same output bits hash in every case):
- gate/up IQ2_XXS / IQ3_XXS / IQ3_S / IQ4_XS and down Q2_0 / IQ4_NL: capped, 8-15% less time per layer.
  IQ2_S gate/up is capped too, but its LDS leaves room for 3 blocks per WGP and the compiler keeps its 238 VGPRs;
  IQ2_S / Q2_0 takes 2-4% less time from the Q2_0 down.
- IQ2_XS gate/up: not capped. Under the cap it spills 104 VGPRs and takes 61-66% more time.
- Q8_0 down: not capped. It spills 18 VGPRs and took -1.9% to +1.9% time (with Q4_K gate/up).
The test is the clang major version: other clang 23 builds are not measured, and clang 24 and newer keep the clang 22
rule. The template argument is the same in the host and every device pass; only the device pass for gfx1151 decides
the attribute (nw_capped). Other architectures, other compilers and -DSTRATA_W_LB=N behave as before: the gfx1100
disassembly is identical to before (kernel names aside). The file builds for gfx1012 / 1030 / 1100 / 1150 / 1151 /
1200 / 1201 and with STRATA_HIP_GFX906 (gfx906); no CUDA build here, and the changed lines are inside
`#if defined(__HIPCC__)`. SYCL has its own copy of this file, not touched. The path is opt-in (STRATA_PF_FUSED=1), so
default output is unchanged.

End to end on a Ryzen AI Max+ 395 (128 GB, gfx1151), UD-IQ4_XS, the section-5 switches of docs/STRIX_HALO.md with
--prefill 16384, 3 interleaved rounds of fresh servers: a 128K prompt read 1,126.1 -> 1,153.4 tok/s (+2.4%; +1.8%,
+2.4%, +2.6% per round). At 4K (868.0 -> 894.9, +3.1%) and 32K (1,182.9 -> 1,207.0, +2.0%) the medians moved too, but
within the spread of 3 runs. Decode unchanged; the same text for all 9 prompts.
2026-10-14 07:07:17 +02:00
libratechw acc94b2171 prompt attention (gfx11 / gfx12 WMMA): issue a chunk's reads before its compute
prompt_attn_wmma_kernel interleaved a chunk's global reads with its
compute: the V slice was staged first, then each 16-cell tile loaded its K
scale and fragments between the q.k WMMAs, so a wave waited on each read
in turn (a thread trace on gfx1151: 56% of the kernel's time in
s_waitcnt vmcnt, 0.4% in WMMA). The chunk's reads now go out together
(fetch), then the same compute runs on them (chunk). The values and the
order of the arithmetic are unchanged.

gfx1151, ROCm 7.14.1 SDK (clang 23), hip_prompt_attn_wmma with
STRATA_PA_FAST=1, three interleaved runs against the unchanged kernel,
ms per chunk: 32K context / 2,048 queries 12.50 -> 11.29 (-9.7%),
1,500 / 1,500 3.39 -> 3.20, 2,100 / 256 1.30 -> 1.23. The output hashes
(NEWHASH) match with STRATA_PA_FAST=1 and =0. gfx12 compiles the same
change; it was not run there.
2026-10-14 07:07:13 +02:00
Andy Slater db0b4d315c sycl/A770: wide MMVQ kernels at 2-8 columns in large-GRF mode on Arc A-series
The wide kernels (Q6_K a2 and the generic native_mmvq_wide) spill at 2-8 columns with 128
registers per thread on the A770. They now launch with grf_size<256> there. Large GRF halves the
threads resident per Xe core, so it is the default on Alchemist only (strata::intel_gpu_gen);
Battlemage and other devices, and 1 column on every device, launch the same kernels as before.
STRATA_MMVQ_LARGE_GRF=1 forces it on, =0 off.

mmvq_bench now prints a checksum of the output (FNV-1a over the float bits) so the two modes can
be compared bit for bit.

Measured on an Arc A770 16 GB (xe, oneAPI 2026.1 JIT), same day. mmvq_bench Q6_K, 2560x2560 / 2560x10240 /
10240x2560, 1-8 columns: 1 column unchanged; 2 columns 1.3-2.0x, 4 columns 2.3-3.1x, 6 columns 3.0-5.0x, 8 columns
3.7-7.4x faster (e.g. 2560x10240 at 4 columns 289.3 -> 92.9 us, 74 -> 232 GB/s of weights); checksums identical
with STRATA_MMVQ_LARGE_GRF=0 and =1 in all 15 cases. End to end, a0116b27 + #2190 + #2193 + #2203 with and
without this commit, Coder IQ1_M, 128K context, int8 KV, --resident-experts, STRATA_VERIFY_STEPPED=1, 8K prompt,
256 tokens: decode 23.47 / 23.50 / 23.73 / 23.77 -> 25.99 / 27.10 / 27.49 tok/s (+10-17%), prompt unchanged,
output ids identical where the expert placement matched. Not built or run on Battlemage.
2026-10-14 07:07:12 +02:00
yi-sudo f629fb0417 Batch decode: one launch for all rows in QSA attention and GDN recurrence (opt-in)
With --batch N the verify window ran QSA block scoring, top-k and decode
attention as one launch per row, and the GDN recurrence (window and 1-row
commit) as one launch per slot.  At 4-8 live slots these serial launches are
most of the window's cost beyond the expert reads.

Two env switches, both off by default (off = the same launches as before):

  STRATA_BATCH_ATTN_ROWS=1   block scores, top-k and decode attention for all
                             rows of the window in one launch each; every row
                             reads its own slot's indexer keys and K/V pools
                             (passed by value as kernel params, so the graph
                             captured per row layout stays valid).  A slot that
                             streams KV (kv_mode 1) keeps the per-row path.
  STRATA_BATCH_GDN_GROUPS=1  GDN recurrence in the window and the 1-row commit
                             for all slots in one launch (grid.y = slot group).
                             Conv commits stay per slot.

Same arithmetic per row: 4 concurrent temperature-0 prompts give the same
bytes with and without the switches (--batch 4 and --batch 8).

RTX PRO 6000 Blackwell, IQ3_S, all experts in VRAM, a0116b2, same day,
total tok/s (docs/BATCHING.md has the table):
  --batch 4, 4 clients: 268.4 -> 311.7
  --batch 8, 8 clients: 308.4 -> 374.8 (reserve 6144 MiB)
Window: 4 rows 14.3 -> 12.2 ms, 8 rows 24.6 -> 19.9 ms.

Built and run with CUDA 13.0 (sm_120) only.  The .cu files are also in the
HIP build, which was not built here (no ROCm).  The SYCL port has its own
copies of these files and is untouched.
2026-10-14 07:07:10 +02:00
imanu 8e68aa5879 OPUS-MTP-MMVQ multi-colonna con attivazioni riusate fra le righe del blocco (STRATA_B6_MMVQ_ROWS) e micro-bench
Q4_K, Q5_K, Q6_K e IQ4_XS: il frammento di attivazione di ogni colonna si carica una volta per blocco
di pesi e serve tutte le righe del blocco; le scale Q6_K stanno in registro. Stesso ordine di accumulo e
di riduzione: uscite identiche bit per bit al layout esatto e alla chiamata a colonna singola
(b6_mmvq_bench, memcmp su entrambe le schede). Default spento.
2026-10-14 07:07:09 +02:00
Stuart Chapin 77ddc2ff14 cpu: IQ2_S in the bit-exact singleton rows; the singleton path only below the #152 rule
Stacked on #1415. IQ2_S (type 22, 122 gathered) joins STRATA_CPU_IQ_ALL_EXACT1's list: ggml's AVX2
iq2_s dot sums the same int32 lanes as row_dot_ggml_one and ends with 0.125f * hsum_float_8.
The singleton gate now also requires nt < native_gu_mt_min, so with STRATA_IQ_MT_MIN=1 a lone token
keeps the multi-token kernel and native_expert_parity's width invariance passes with the switch on.
2026-10-14 07:07:08 +02:00
leadgtr7 6befb3d65d sycl mmvq: Q6_K decode kernels no longer ALU-bound; output heads as aligned planes; int4 activation loads
- Q6_K wide kernel (and the planar one): the six-bit offset (v - 32) was dpct's per-byte saturating char4 subtract, a per-byte loop on Xe;
  no byte can saturate, so a 4-op SWAR form is bit-exact. Q6_K dense matvecs 59.5 -> 30.8 us (1 row), 77.4 -> 45.5 us (4 rows).
- STRATA_Q6_PLANAR (default on, =0 off): the Q6_K LM head and the MTP draft head are converted at load to ql/qh/scales/d planes (same bytes, the
  GGUF-layout allocation is freed: no VRAM change) so a lane's loads are single aligned 16-byte loads; the draft head subset is gathered from the planar
  head. native_q6_k_mmvq serves every registered matrix at any column count. Bitwise equal outputs.
- ld_i4_a4: the Q8_1 activation qs (4-byte aligned) as one dword-vector load in the Q4_K / Q5_K / IQ4_XS wide kernels (Q5_K 4 rows 81 -> 68 us).
2026-10-14 07:07:08 +02:00
Niko1221 db568409fc tools: batch_test.py takes up to 32 prompts (folds in havok2-htwo's batch_test16.py and batch_test32.py) 2026-10-14 07:07:06 +02:00
InB4DevOps 8ee2005dae cpu: add bit-exact AVX2 singleton expert rows 2026-10-14 07:07:04 +02:00
KarlGrier 1a2f95c332 QSA decode attention: split each query's cells across blocks on the int8 mma path (STRATA_QSA_SPLIT_ATTN=1, opt-in)
With STRATA_QSA_SPLIT_ATTN=1 the verify window's and the draft layer's QSA attention run through the prompt path's int8
tensor-core kernel with each query's cells split among up to 20 blocks, and the splits are merged with the log-sum-exp
rescale. qsa_decode_attn_split() returns false (nothing launched) unless the KV is int8 on sm_80 or newer, or when its
partials would not fit the caller's scratch, and on HIP; the caller then keeps qsa_decode_attn_batch(). The sums run in
another order, so with the switch on the output is a rounding-level change. Unset, nothing changes.

The idea is from Eddoursul's fork (fd23d91); the kernel is written against this tree's qsa_prompt_attn.cu.
2026-10-14 07:06:38 +02:00
KarlGrier ffc30b8d76 Verify window: the mixer's input-only work on graph branches (STRATA_SIDE_MIXER=1/2, opt-in)
STRATA_SIDE_MIXER=1 runs the GDN gates and the QSA indexer (key projection, tail snapshot, query chain, block scores,
top-k) on a branch of the window's graph beside the attention's projections, joined before the recurrence and the
attention; =2 also runs the GDN gate projection and the QSA queries' chain on a second branch. A branch that projects
reads F4's interleaved copy, written on the main stream before the fork, and qkv is recorded before the branch so its grid
is dispatched first. Every result is bitwise the same as in line; STRATA_DF_BRANCH is off while this is on. Unset, the
window runs in line as before.

The idea is from Eddoursul's fork (34a35db, b063c13).
2026-10-14 07:06:34 +02:00
imanu f7eaf2de9a Verify window: the routed experts' gate/up with the group's q8_1 rows in shared memory (STRATA_EXPDEC=1, opt-in, bitwise); RTX 2080 Ti gate/up kernel -11/-23% at T 1-4, decode +1.1% on a 131k layer split
native_expert_grouped already decodes each weight part once per block, but the apply re-reads every entry's q8_1 block from global memory with 9 scattered 4-byte loads, so an extra row of the window costs ~60% of a whole expert. expdec_gu_kernel stages the group's entries in shared memory (two conflict-free 16-byte loads per call, the fp16 scale as a float), takes rb rows per block and stages the IQ3 codebooks too; the same lane does the same calls in the same order with the same operations (apply_u = apply on the block's words), so the output is bitwise the default kernels' (expdec_bench: identical on every cell, 2 cards). Gate/up IQ2_XXS/IQ2_XS/IQ3_XXS/IQ3_S/IQ2_S at n_embd 2560; the down (Q2_0, IQ4_NL) behind STRATA_EXPDEC_DOWN=1 (in the engine the Q2_0 down was ~10% slower). Knobs STRATA_EXPDEC_R/_DR/_MINB/_RB/_DRB/_MINBLK/_D20; one log line per (role, format) at the first launch. docs/EXPERTDEC.md.
2026-10-14 07:06:21 +02:00
Alex Sadleir 79376a2732 cpu: the AVX2 expert-row dots keep their accumulators in registers too
q5_1_dot and q8_0_dot in kq_avx2.cpp held their per-token sums in the same
runtime-indexed __m256 acc[MAXT] that made bf16_rows_dot_multi spill: with the
array live the compiler leaves it in memory, and every token's FMA reads and
writes a stack slot.  Both are now template <int NT>, dispatched 1..4 and, past
that, run four tokens per pass with the row's bytes re-read from L1 - the same
idiom the router change above and kq256_gu_rows already use.

Ryzen 7 9800X3D (Zen 5), GCC 15.2.0, build/native_expert_parity --synthetic
(ggml-quantized weights and activations), one thread pinned to core 0, at the
verify window's four tokens:

  Q5_1 down rows [2560 x 640]: 190-197 us -> 155-156 us  (1.24x)
  Q8_0 down rows [2560 x 640]: 135 us     -> 104 us      (1.30x)

Same sums: 0 of 36 token-sets differ in any bit against ggml's own vec_dot over
1..8 tokens, both before and after; native_expert_parity reports 0 failures.

Left alone: q4k_dot keeps its runtime-nt array.  Its token accumulators are not
what spills - the unpatched function carries 8 ymm stack ops for the sums
against 24 (q5_1) and 59 (q8_0); what q4k_dot spills is its weight-side unpack
arrays (q4l/q4h/scale_l/scale_h), which token chunking does not touch and
re-does.  The same change measured +5% at four tokens and -4..-7% at six to
eight, so it is a wash at the window and a small regression above it, and q4k is
the gate/up format that runs most.  The AVX1 path, the iq_avx2/q2_avx2 rows and
the engine's dispatch are untouched.

Backends: CUDA and HIP do not compile this file.  The SYCL port does; not built
on this machine (no icpx here) - the router change in this branch built there.

Tests: native_expert_parity --synthetic q4_K/q5_1 and q4_K/q8_0 (0 failures,
0 bits differ), iq_avx2_parity, iq_avx1_parity, q8k_quant_parity,
router_dot_parity - all exit 0.
2026-10-14 07:06:19 +02:00
Alex Sadleir 2a669f3c29 cpu: the AVX2 router dot keeps its accumulators in registers (2.1x on a Zen 3)
bf16_rows_dot_multi held its per-token sums in __m256 acc[MAXT] indexed by a
variable. With eight 256-bit accumulators live GCC also unrolled the column loop
and left the whole array in memory, so every token's FMA read and wrote a stack
slot (vmovaps 0xc0(%rsp) ... vfmadd213ps 0xe0(%rsp)). On a Ryzen 7 5700X3D one
layer's router [512 x 2560] at 4 tokens took 0.41 ms against 0.25 ms for the AVX1
copy in kq_avx1.cpp that kept its accumulators in registers, so every AVX2 CPU ran
the slower of its two kernels (router_dot_parity --cpu 2, median of 3). Pragma
GCC unroll 1 on the column loop changes nothing; the variable-indexed array is
what forces the array into memory.

Four tokens per pass, in four named accumulators. A row above four tokens is read
a second time, from L1: nt=8 measures 0.37 ms, the same as the spilled form. On
the same CPU the AVX2 kernel goes 0.41 -> 0.19 ms at 4 tokens and nt=2 0.36 ->
0.16 ms, and it now runs 1.3x ahead of the AVX1 copy instead of 1.6x behind it.
The loop body carries no stack slot any more (was 21 memory ops per iteration).

Untouched: the arithmetic and the reduction. Each token's FMA chain still runs
over the same columns in the same order and ends in the same hsum_float_8, so
every sum is bit-identical - the output for nt 1/2/4/8 at cols 2560/5120 hashes
the same before and after (FNV-1a over the whole out[]), and router_dot_parity
reports 0 failures with the AVX2 rel error unchanged at 3.16e-07.

Left alone: the expert row kernels (iq_avx2.cpp, q2_avx2.cpp, kq256_gu_rows,
kq256_rows) and the AVX1 path. The iq_avx2_parity bench over four format pairs x
1..8 tokens moved within 1.6% (noise), and the CPU parity tests (8 targets) pass.
The router stays what it was, an estimate for which experts to prefetch. CUDA and
HIP do not compile this file; the SYCL port does, and it builds there under icpx
2026.1 with no new warnings and no spills either.

The AVX1 copy in kq_avx1.cpp kept a comment saying it reads its rows "exactly as the AVX2
kernel does"; with the row loop chunked four tokens at a time that is no longer the
AVX2 kernel's shape, so the clause is dropped there.  Comment only - no code change.
2026-10-14 07:06:18 +02:00
imanu 731528beba QSA decode attention: PR #540's two-cells-per-step chunk kernel on every CUDA card and a bounded merge (STRATA_ATTN_DAILY=1, opt-in, bit-exact); parity harness
attn_chunk_kernel_pre75 (PR #540 by sskver: two cells per step with a 12-shuffle reduction, cell-major
probabilities, V loaded four at a time) is compiled in every CUDA build, not only with STRATA_EXPERIMENTAL_SM60, and
STRATA_ATTN_DAILY=1 selects it on any card for the decode attention (single query and batch: verify window and MTP
drafter) together with attn_merge_v2_kernel (Hardin22), a merge that skips the chunks the chunk kernel marks empty.
Bit for bit with the default kernels by construction: reduce12 adds the same pairs as warp_sum's butterfly at every
level, the V cells fold in the same order with the same fmaf, the masked cells stay out; the merge does the same fmaf
in the same order. Shared memory 15,872 B like the default kernel (spt shares sq's storage). STRATA_ATTN_MERGE_V2=0/1
and STRATA_ATTN_PRE75=0 switch the two halves separately. HIP unchanged.

qsa_merge_daily_parity (tests): memcmp of both kernels against the default ones on four KV formats, widths at the
chunk borders and non-resident pages; --bench times the chunk kernels back to back.
2026-10-14 07:06:09 +02:00
imanu 5b6c93987f QSA decode: the window's block scores with the queries in registers and six shuffles per block (STRATA_QSA_ROWS=1, opt-in, bitwise); RTX 2080 Ti 101 -> 55 us a call at T=4, decode +3.2/+0.1% on a 131k layer split
In a 131k decode block_scores_multi_kernel costs ~20 us more per call for every row of the verify window: not the keys (read once for all the queries) but the shared-memory and shuffle pipes, 4 x LDS.128 of the query slices and 20 shuffles per (block, query). block_scores_rows_kernel<NQ> keeps the NQ <= 4 queries' slices in registers and reduces the four heads' lane products with a scatter that keeps warp_sum's pairings (xor 16 and 8 leave one head per lane, then 4, 2, 1): every addition adds the same two operands of the same level, so scores and top-k ids are bitwise the multi kernel's. qsa_rows_bench measures the window's QSA kernels row by row and, with --rows, checks the parity (16 cases per card, 0 differ) and prints both kernels' microseconds: 2080 Ti 47/57/78/101 -> 36/38/49/55 us at T 1-4, 3060 73/109/152/194 -> 63/76/98/130. docs/QSAROWS.md.
2026-10-14 07:06:00 +02:00
Niko1221 8ccc4a0fe6 Verifier::ar_live and no Prefill::cuda_err_ in the hand-off worker (the two pieces of the unported STRATA_PIPE_OVERLAP series that STRATA_ADMIT_MERGE_FIRST and STRATA_HANDOFF_PIPE name) 2026-10-14 07:03:56 +02:00
havok2-htwo ed4fa42a80 serve: STRATA_ADMIT_SHORT_FIRST=<tokens> admits short prompts before long ones (opt-in)
New requests took the control lines in whatever order the lock fell, so a 500-token chat question could wait
behind several agent reads. With the env, a prompt of at most that many tokens goes first (arrival order within
each class); a longer one that waited STRATA_ADMIT_MAX_WAIT_S (30 s) counts as short. A request already in
acquire() gives the lines back when a shorter one came. Only the order changes, never what is read.

Ported from havok2-htwo/Strata 08830ddf onto 0.1.44.1: _take_control has no image-request line here, so its
gate is only the ordering; the first admission passes new=True.
2026-10-14 07:02:42 +02:00
Niko1221 ed7c7f339d engine: a pack folder without native_experts.txt says so before the AVX-512 refusal (#2347)
The refusal 'this CPU cannot run the expert kernel' belongs to the canonical Q2_0 pack. An NVFP4, i-quant or
Unsloth pack is a native pack (native_experts.txt in the --pack folder) and its rows have AVX2 kernels, but a
config whose --pack points at the wrong folder reads like a CPU that is too old. On a CPU without AVX-512 the
engine now says the file is missing, and where it sits when it is one level down (<pack>/pack).
2026-10-14 07:02:11 +02:00
havok2-htwo 1d9758f897 prefill: STRATA_HANDOFF_PIPE=P hands a layer split's chunk on in P pieces, gated by events, on a persistent thread
A layer split hands each prompt chunk's rows (21 MB per 512 tokens) to the next card through a pinned
host buffer: one D2H, a host stream sync, a new std::async thread, then one H2D before the next stage's
first kernel.  The 3090s here have no P2P (topo: CNS) and cudaMemcpyPeerAsync is driver-staged and
slower (3.4 ms vs 3.2 ms for D2H + H2D), so the copy stays on the host route; nsys showed 3.8-4.0 ms per
512-row hop, of which ~1-1.4 ms was the thread start alone.

With STRATA_HANDOFF_PIPE=P (2..16, opt-in; unset = unchanged):
- the sending stage records an event when its chunk's work is done and one after each of P row-piece
  downloads into the same pinned buffer, and waits on the host only for the first (on_stage_chunk's
  checkpoint parts and the error check need the state, not the copy);
- the next stage waits on the GPU for each piece's event (cross-device cudaStreamWaitEvent) before that
  piece's upload, so its uploads overlap the remaining downloads (separate PCIe links); a smaller
  receiving chunk waits for every piece, then copies as before;
- the next stage's chunks run on one worker thread per sending stage, started and pinned once, whose
  packaged_task futures carry the same results and exceptions as std::async's (it clears the CUDA error
  state after each job, as a thread's end did).  STRATA_HANDOFF_PIPE_WORKER=0 keeps std::async (A/B).

Same bytes in the same rows before the next stage's first kernel: exact.  No device memory (events only,
the existing two pinned buffers per stage).  Measured (T16-143l5, P=8): 512-row hops 3.8-4.0 -> 1.85-1.89
ms, 143-row hops 1.6 -> 1.0 ms; reads 1.2K about -1.5 %, 150 about -1 %, 9K (agent, --kv-resident) -3 %;
decode rows/s unchanged.  batch_test16/32 (greedy and temperature 0.7), batch_interleave_test and
batch_overlap_test (+ the stage fault arm) byte-/token-identical to the reference dumps; an agent-config
run with checkpoint parts byte-identical to the reference binary.
2026-10-14 07:00:13 +02:00
havok2-htwo 6959adf404 tests: qsa_slots_parity skips where a slots launcher declines by design
STRATA_SCORES_MULTI=0, the pre-sm_75 attention (STRATA_EXPERIMENTAL_SM60 builds on a
V100/P100) and the gfx906 query swizzle make qsa_block_scores_slots or
qsa_decode_attn_slots decline; the engine keeps its per-row calls there, so a decline
is no failure. A declined case prints SKIP, the test exits 77 when every case was
declined, and STRATA_SCORES_MULTI=0 skips up front.
2026-10-14 07:00:13 +02:00
havok2-htwo a71ee46cd2 verify: STRATA_QSA_SLOTS=1 runs a batch window's QSA block scores, top-k and attention as one launch over its rows
In a batch window every row reads its own slot's indexer keys and K/V, so each QSA layer ran the
selection and attention once per row: four rows (16 slots) or eight (32 slots) times qsa_block_scores,
qsa_block_topk and qsa_decode_attn_batch, each launch small (the top-k on one CTA, the attention on
cap/64 x 2 blocks).  With the switch, per window (up to 8 rows per launch):

- block_scores_slots_kernel: grid (256, rows), blockIdx.y runs the single-query block_scores_multi_kernel
  body with that row's slot keys (block_scores_multi_kernel is now a wrapper around the same body)
- qsa_block_topk over the rows in one call (it only reads the rows' scores and steps)
- attn_chunk_slots_kernel: attn_chunk_kernel's body with the row's own QsaAttnPools (an 8-entry table
  passed by value, blockIdx.z picks), then the existing batched merge

Each row is computed by the same kernel body with the same reduction order as its own call.  The
launchers decline (the per-row calls run) where that call would pick another kernel: STRATA_SCORES_MULTI=0,
the pre-sm_75 / gfx103x attention, the gfx906 query swizzle.  A streamed KV cache keeps the per-row
resolve-then-attend loop.  Default (switch off): unchanged.

Checked on 4x RTX 3090, T16-143gsc setup (layer split 12,24,37, int8 KV):
- SASS (sm_86) of every existing kernel in qsa_select.cu and of the default attn_chunk_kernel<M> and the
  merge is identical before/after; the opt-in lane-cell instantiations differ only in register allocation
- new qsa_slots_parity (ctest, also with STRATA_ATTN_LANECELL=1): fp16, int8, q4_0 and int8-K/q4_0-V
  pools, 1/2/4/8 rows of different slots with their own page tables and contexts 37..32768: scores, ids
  and attention bitwise identical to one call per row
- batch_test16/32 (greedy and t=0.7), batch_interleave_test and batch_overlap_test (STRATA_PIPE_OVERLAP=1)
  token-identical to the build without the change; with the switch off batch_test16 is byte-identical too
- batch decode rows/s (engine level, 30 s, back to back with the reference): 16 slots 683 -> 726 (+6.3 %),
  32 slots 750 -> 802 (+6.9 %); STRATA_VERIFY_PROFILE "QSA projections + attention" per stage-window
  0.89 -> 0.52 ms (16) and 1.52 -> 0.79 ms (32)

HIP: the new code uses only what the existing kernels use; SYCL has its own sources and only sees the new
declarations.  Neither was built here.
2026-10-14 07:00:13 +02:00
Niko1221 3bfa088e46 setup: Qwen3.6 offers --parallel on small cards too (the price said: a request alone ~5% slower, 4 together ~1.5x), and asks how many requests at once; Enter keeps one at a time 2026-10-14 07:00:10 +02:00
havok2-htwo 2f4fe20a9a serve: STRATA_SLOT_CKPT_MOVE honours the #879 flush (no resume from a tainted slot's checkpoint)
Upstream's non-finite flush only marks running slots `tainted`; their checkpoints stayed.  With
STRATA_SLOT_CKPT_MOVE a running slot's checkpoints are a resume source (active_source) and a slot's
moved turn checkpoint can be restored into the main session (lent_slot), so a request right after the
flush, logged as "reading this prompt from token 0", still continued from a pre-flush checkpoint.

- the flush drops a running slot's checkpoints too (only with STRATA_SLOT_CKPT_MOVE, the one reader of
  them; they go back to the checkpoint pool)
- active_source and the lent_slot search skip tainted slots

Checked with STRATA_NAN_INJECT=600 on the T16-142gsc setup (next turns of chats still running in
slots): before, the two requests after the flush resumed 1628 tokens from slots 0 and 8 ("gave back ...
its turn checkpoint"); now both read 1661 tokens from token 0.  A next turn before the flush still
resumes from its running slot.  Default path (switch off) unchanged.
2026-10-14 07:00:09 +02:00
havok2-htwo f32663a8b3 tools: batch_interleave_test runs on a pipelined batch (no give-way required there) and checks a turn checkpoint taken from a slot
On a layer split with more than one group a batch read never gives way to a
BYIELD, so step 4 always failed with 'no such free slot' and steps 5-7 never
ran.  --yield auto now expects the give-way only on a non-pipelined batch;
there D is read whole and E admitted beside it, both still equal to solo.
New step 7b: A ends in slot 1, --flush unrelated solo GENs, then F2 can only
start from slot 1's turn checkpoint.  --dump writes every token list for an
A/B of two builds.
2026-10-14 07:00:09 +02:00
havok2-htwo bec9edf1e0 prefill: decide STRATA_MMQ_GROUP_SORT per layer once, in the MMQ plan
mmq::whole_tiles walks every visible GPU and every tile width through the
MMQ config table; the sort hook called it twice for each MoE layer of each
prompt chunk, on the host path between the routed-ids download and the
expert launches.  Its verdict depends only on the layer's weight formats and
the device set, so MmqPlan now keeps it as a per-layer flag (taken only when
STRATA_MMQ_GROUP_SORT=1 and STRATA_MMQ_RESIDENT_SORT_NE is unset) and logs
how many layers qualify.  Same order, same bits; without the switch nothing
new runs.
2026-10-14 07:00:09 +02:00
havok2-htwo 69a05bfb59 verify: STRATA_BATCH_SELF_COMMIT=1 lets a one-row-per-slot batch window keep its rows itself
A pipelined batch window is followed on its stage's stream by the layout's commit graph, and the stage counts
as done only after both. When every row of the window is another slot's one token, that commit is
unconditional (each slot keeps its one row; commit_slot_prefixes allows nothing else), and most of the
graph only repeats what the window wrote: it puts each indexer tail back from its snapshot and appends the
same row again, and copies each PLE history back from the window's own snapshot of it. What it adds is the
GDN conv history and recurrence state, which the window ran without writing.

With the switch, such a window advances the GDN conv history (gdn_conv_l2_multi with commit) and state
(gdn_step_norm_multi with n_keep = 1, the kernel the commit graph runs for a one-row group) itself, as a
one-token solo window does, and takes no tail or history snapshots. No commit graph is captured for the
layout; batch_launch and commit_slot_prefixes launch none, layout_captured and ensure_batch_layouts do not
ask for one. Layouts with proposal rows (--batch-mtp) keep the commit graph. With the switch off every path
is unchanged.

Measured on 4x RTX 3090, UD-IQ4_XS, T16-142fcb (split 12,24,37), decode of 16 / 32 slots, 30 s each,
reference and new build back to back: 653.7 -> 686.0 rows/s (+4.9 %) and 714.1 -> 752.6 rows/s (+5.4 %);
the group step period 24.5 -> 23.3 ms and 44.85 -> 42.6 ms. STRATA_VERIFY_PROFILE: the window's GDN
recurrence takes 0.09 ms (16) / 0.18 ms (32) longer per stage-window with the state written in it.

batch_test16 (16 slots, a 1,200-token prompt) is token-identical to the reference dump; batch_test32
32/32 identical and its dump equal to the switch-off run; batch_overlap_test (STRATA_PIPE_OVERLAP=1) passes
and is token- and RESUME-identical to the switch-off run; batch_interleave_test parts 1-3 identical (its
part 4 fails at the same point with the reference build).
2026-10-14 07:00:08 +02:00
havok2-htwo 62fc7c8a3c prefill: STRATA_MMQ_GROUP_SORT=1 sorts the full MMQ groups by row count, keeping the partial group
STRATA_MMQ_RESIDENT_SORT_NE=1 puts a fully resident layer's experts in row-count order, so each
16-expert group's max_rows (its tile padding) is close to its experts' own. It also moves the hottest
experts into the last, partial group, whose few tiles take MMQ's stream-k split: the K boundaries move
with the group's tile count and the prompt's bits change.

The new switch sorts only order[0, n - n % 16] (mmq_resident_sort_span) and leaves the partial group's
experts, and so its rows, where they were. A full group's launch has 160 (gate/up) or 320 (down) tiles
per column tile; mmq::whole_tiles checks on every visible GPU that every such launch runs one block per
tile (tile efficiency >= 90 %, NVIDIA) and that all tile widths share the I/K tiles and SRAM layout. Then
each expert's rows get the same bits in any full group whatever its group-mates and max_rows. Where it does
not hold (e.g. 108 or 128 SMs, AMD's stream-k grid) the switch does nothing. RESIDENT_SORT_NE takes
precedence when both are set; with neither the code path is unchanged.

prefill_mmq_tab_test part 4 runs a layer's groups as prefill.cpp does (src-gathered q8_1 rows, absolute
bounds, the group's max_rows) in ID order and in both sorted orders, for IQ3_S / IQ4_XS gate/up and
IQ4_NL / Q8_0 down: with the partial group kept every token's rows are bitwise equal (16 cases); sorting
the partial group too changes 133-1881 rows per case. 890 comparisons, 0 failed (RTX 3090).

Measured on 4x RTX 3090, UD-IQ4_XS, T16-142fcb (split 12,24,37, every expert resident), read time,
medians of 6, back to back: 150-token prompt 145.8 -> 136.2 ms, 1,200-token prompt 428.6 -> 363.4 ms
(RESIDENT_SORT_NE: 134.9 / 358.6 ms). The final residuals of five prompts (300-1,200 tokens,
STRATA_PREFILL_DUMP_R_ALL every position and STRATA_PREFILL_DUMP_R fp32) are byte-identical to the
reference build; with RESIDENT_SORT_NE every row differs. batch_test16 (16 slots, a 1,200-token prompt)
is token-identical to the reference dump.
2026-10-14 06:59:57 +02:00
havok2-htwo a923889bd2 generate: review fixes for the admission switches
STRATA_SLOT_CKPT_MOVE: an active slot is a slot source only when the main
drafter's rows come along or are not drafted from (no --mtp, --batch-mtp,
or a batch admission).  The slot copy takes the main layers' cells only, so
a solo GEN beside active slots would draft from another conversation's
drafter rows below its start; it reads its prompt as with the switch off.

STRATA_CKPT_THREADS: a checkpoint thread widens its CPU mask before it
goes to the aux CPUs, so the mask the aux placement restores (a request
with aux_cpus=0) is the wide one, not the host thread's single CPU.

STRATA_ADMIT_MERGE_FIRST: a merged first window counts as one row in the
STRATA_DECODE_TIMING window statistics (its prompt rows are not decode rows).
2026-10-14 06:59:57 +02:00
havok2-htwo ca239cdabc generate: STRATA_SLOT_COPY_BATCHSYNC=1 queues the direct slot copy and synchronizes each device once
The direct slot copy (STRATA_SLOT_COPY_DIRECT) waited for each of its ~116 copies on the private copy
stream.  With the switch, conversation_checkpoint_copy and conversation_kv_copy only queue them (new
`queued` argument, default off), and the slot copy's closing sync_all is the one wait per device.  A
streamed K/V state (kv_mode != 0) has its residency refresh on the legacy stream, which is not ordered
after a non-blocking stream: conversation_detail::order_after_queued records an event on the private
stream and makes the legacy stream wait for it first.  The copies stay on the private non-blocking stream.

Same copies in the same order on one stream: tokens are identical.  Measured on 4x RTX 3090 (T16-142,
24 admissions): the slot copy takes 0.5 ms instead of 1.3 ms; batch_test16 16/16, batch_overlap_test
and batch_interleave_test token-identical to the references; a --kv-resident 20480 run with a 21K
prompt is identical with the switch off and on.
2026-10-14 06:59:57 +02:00
havok2-htwo 139d702ebd generate: STRATA_SLOT_CKPT_MOVE=1 moves a batch admission's turn checkpoint into the slot
A batch admission copied the main chain's longest checkpoint into the slot (~112 MB of host vectors, 7.6 ms, ~60 ms
on fresh pages).  With the switch, the request's own turn checkpoint (or one it took out of the slot it is admitted
to) moves instead; a root, a pinned prefix and any other checkpoint the chain shares are still copied.

The chain then no longer holds it, so the request path also looks in the slots:
- while the main session holds its tokens (live, its cells below it), a slot's checkpoint is restored on the main
  session as a chain one would be, with no K/V copy; when that slot is the one the request is admitted to, it moves
  back into the chain first (the admission drops the slot's checkpoints), else the slot keeps it and the admission
  copies it as it copied the chain's;
- an active slot's checkpoints are a slot source like an idle slot's (its windows write its cells from p on): a
  second request with the same history after the main session moved on restores instead of reading it all;
- a slot source that is the admit slot moves its checkpoint into the chain instead of copying it.

The switch also keeps the dropped checkpoints' storage as STRATA_CKPT_POOL=1 does: a moved checkpoint frees
nothing at the next prune, so without it every save faulted in fresh pages (17 -> 38-60 ms, more than the copy saved).

Off by default: nothing changes.  A session SAVE or a parked conversation right after an admission lacks the moved
turn checkpoint (the slot holds it).
2026-10-14 06:59:25 +02:00
havok2-htwo bebeb791a4 generate: STRATA_CKPT_POOL=1 saves checkpoints into dropped ones' vectors, STRATA_CKPT_THREADS=1 saves a split's parts at once
STRATA_CKPT_POOL=1 (off by default): the serve loop keeps the running-state
vectors of the checkpoints it drops (LRU eviction, the tail one, the prune at
a new request, a batch slot's old one), at most two, and the next checkpoint
or slot copy goes into them.  A save then resizes nothing: no zero-fill of
~118 MB of fresh vectors.  Every byte is overwritten by the copy.

STRATA_CKPT_THREADS=1 (off by default): a layer split's checkpoint saves the
first stage's part on the calling thread and every later stage's on a
persistent thread of its own (the copies' private streams are per thread, so
short-lived threads would leak them).  The threads leave the host thread's one
CPU first (to the aux CPUs with --aux-cpus, else to every CPU the process may
use): on it the copies only took turns.

Measured on a 4-stage split (T16, 24 batch admissions per arm): a turn
checkpoint takes 17.2 ms today, 10.4 ms with the pool and 5.6 ms with both;
the batch tests, the overlap and interleave tests and a driver run give the
same tokens with the switches on as off.
2026-10-14 06:59:13 +02:00
havok2-htwo 0cf1a9b7c8 generate: STRATA_ADMIT_MERGE_FIRST=1 reads a batch admission's last prompt tokens and its first token in one window
A batch admission read its header through the verify windows (T=4 + T=2 for the
usual 6 tokens) and then its first token in a window of the last prompt token
alone. With the switch the last windowed part leaves its last tokens (up to the
verifier's max_t, 8, the last prompt token included) to the first window: the
part's earlier tokens are read as before, the first window commits every row,
the drafter gets the rows of the prompt tokens in it as the prompt windows give
them, and only row T-1's output is emitted. Row T-1 sits at the first window's
position with the same history and Philox draw, and a row computes what it
computes in any window while every expert is in VRAM, so the token and the
state are the same.

Only for a BGEN admission with every expert of every stage in VRAM (no loan,
no swap pending, the zero-doorbell graphs), and not with --batch-mtp, the
pipelined windows, pictures, the elastic K/V, a peer device, remote caches,
foresight swaps, STRATA_LOGPOS or a checkpoint at the last token. The merged
window takes no drafter q (STRATA_SPEC_PROB), adds nothing to the draft
counts, and the "PP <n-1>" line is printed before it. Verifier::max_t() is new.

Off by default: the same path as before. Tokens (4x RTX 3090, split
12,24,36, 16 slots, STRATA_IQ_MT_MIN=1): 24 admissions of prompts of 3 to 65
tokens and chat headers with and without an assistant prefill (merged T 3 to
8), greedy, seeded and with penalties, on vs off identical; batch_test16 16/16
and equal to the earlier dump; batch_overlap_test token- and RESUME-identical;
batch_interleave_test equal; 47 sampled driver requests equal.

Measured (24 admissions, ~131 and ~1195 tokens): header windows 23.5 plus
first window 11.5 ms become one 7-token window of 27.6 ms, 7.4 ms less per
admission (send to first batch token 246.8 -> 239.4 ms short, 656.1 -> 648.5
long). A window row costs ~2.4 ms up to T=6 and ~4 ms at T=7 and 8 (T=1 11.4,
T=7 28.6, T=8 32.1 ms).
2026-10-14 06:58:52 +02:00
havok2-htwo a62bd38eba generate: STRATA_PIPE_BYIELD_NODRAIN=1 drops a BYIELD without draining the pipelined groups
A pipelined read never gives way (batch_read_piece returns 0 when piped), so a
BYIELD that reaches the main loop is for a read that has ended and is dropped.
The main loop still drained the groups for it first, as for a request, unless
STRATA_PIPE_OVERLAP was set. With the switch the BYIELD is dropped as it comes.

A BYIELD the server sends during the read is queued and taken right after BADM,
before any group is restarted, so that drain costs nothing today (0 groups in
flight, 0.0 ms). Only a BYIELD that arrives once the groups run again (the
server reads the control lines late) paid for it: measured with one sent 60 ms
after BADM, drain 26 ms with 4 groups in flight and the first rows 50 ms after
it, a 23.5 ms gap in the slots' rows and about 14 rows lost (at 576 rows/s). With
the switch the longest gap is 7.1 ms, as in plain decode.

Off by default: the same path as before. Tokens: batch_overlap_test (a BYIELD
during B's read) on vs off token- and RESUME-identical, batch_interleave_test
output byte-identical, batch_test16 16/16, and 41 sampled requests of the
admission driver (8 with a BYIELD while 4 groups were in flight) equal.
2026-10-14 06:58:39 +02:00
havok2-htwo bc761d06b1 generate: STRATA_TRACE times a batch admission's phases
One stderr line per batch admission ("strata trace: admission of slot N: ...")
splits it into the drain before BGEN, the prompt (batched read, header windows,
the checkpoints' device syncs, copies into RAM and eviction, the rest), the first
window, the slot copy, freeing the slot's old state and the copy of the turn
checkpoint into the slot. Each checkpoint gets its own line, and with pipelined
groups "first rows N ms after the admission" times the refill after BADM. A drain
for another line says how many groups were in flight and what it cost.

Only with STRATA_TRACE set; without it the log and the tokens are unchanged.

Measured (4x RTX 3090, split 12,24,36, 16 slots in 4 groups, 24 admissions):
drain 25-26, header windows 23.5, checkpoint 17.3 (sync 0.1, save 17.2), first
window 11.5, slot copy 1.3, slot freed 0.0, checkpoint copy 7.8 (60 on a slot's
first fill), refill after BADM 23.7 ms.
2026-10-14 06:58:16 +02:00
havok2-htwo 6ab4c31243 generate: more than 8 batch slots are held to 8 rows per group window once the slot sessions that fit are known
The >8-slot cap ran only before the slot sessions were carved. When fewer
sessions fit than asked for, the groups were resolved again with no row bound:
auto could pick a group of more than kVerifyMaxT slots (PGroup's rows overrun,
every window refused) and a --batch-groups N that no longer divides the slots
fell back to one serial group whose windows reach only the first 8 slots.

slots_in_windows() picks the most slots whose groups, resolved as
batch_groups::resolve does (a number given, auto, the default's one group for
--adapt-async 1), divide them with at most kVerifyMaxT rows each and at most
one group's worth per stage. It runs before the groups are resolved and again
on the slots that fit (the extra sessions are dropped like the per-stage trim);
the pump refuses a group over kVerifyMaxT rows as a safety net. The hand-off
buffers hold one row per slot only for pipelined groups, so --batch-mtp keeps
upstream's kVerifyMaxT rows. Log and comment wording without the g3 tags.
2026-10-14 06:57:02 +02:00
havok2-htwo 574dcbf9c3 docs: STRATA_MMQ_DIRECT needs -DSTRATA_MMQ_TAB=ON; its VRAM and build cost; the hack is no bound; engine exactness
- The build option is off by default and why (36-38 MiB of VRAM per GPU under EAGER, ~70% of the upstream MMQ
  instances' compile time per arch); the nine types with a pointer table.
- The skip-gather hack's 225/577 ms are no bound: it changes the routing and does less work.
- Engine exactness as measured: first-window logits (STRATA_DUMP_FIRST_LOGITS) and greedy tokens byte-identical,
  2 vs 1 vs 0, on the 4-GPU split with --prefill 2048 (the streamed walk), with 9 GB less expert cache per GPU
  (mixed in-place, copied and mid-group-flushed groups), and on one GPU with --expert-cache-per-layer.
2026-10-14 06:56:59 +02:00
havok2-htwo 02d0c23a59 docs: STRATA_MMQ_DIRECT (opt-in) and the STRATA_MMQ_TAB build option, with the measurements 2026-10-14 06:56:59 +02:00
havok2-htwo a2d979b999 prefill mmq tab: moe_mmq_tab.cuh carries ggml's MIT notice
The file mirrors parts of llama.cpp's ggml-cuda mmq.cuh; like the other
ggml-derived kernels (native_moe.cu etc.) it now includes the copyright and
permission notice the MIT license asks for. Comment only.
2026-10-14 06:56:49 +02:00
havok2-htwo c2b44ca5b8 expert cache: slot_guard() reports the guard applied; a test for slot_tail on uniform and sized caches
- ExpertCache::slot_guard() returns the guard open_sized applied (guard_, reset by close), not the request: 0 for
  uniform slots, when closed, and on SYCL, whose open_sized applies none.
- tests/core/expert_cache_slot_guard_test: slot_stride, slot_room and slot_tail on a uniform cache (empty off_,
  including the last slot) and on sized caches with and without the 256 B guard; no guard gives today's offsets;
  close and reopen.
- generate: the "+256 B guard per sized slot" line only for a sized cache; a uniform one says it has no guard.
- prefill: STRATA_MMQ_DIRECT_LOG=1 (with STRATA_MMQ_DIRECT=1) prints each stage's totals of experts read in place,
  resident and streamed after every prompt, so an engine run can show which walk read what.
2026-10-14 06:56:49 +02:00
havok2-htwo a5ad4077ef prefill mmq tab: STRATA_MMQ_TAB off by default, the nine tested types only, not on gfx906
Review fixes for the pointer-table MMQ build:
- STRATA_MMQ_TAB defaults to OFF, like STRATA_MMQ_KQUANTS: the engine loads every kernel at start
  (CUDA_MODULE_LOADING=EAGER), and the nine tab instances took 36-38 MiB of VRAM per GPU (sm_86, measured with
  a cudaMemGetInfo probe linked with and without the tab objects; equal under LAZY), with STRATA_MMQ_DIRECT unset
  too. prep_group_kernel is compiled only with STRATA_MMQ_TAB, so a build without it has the same device code as
  3adce85 (the 58 cubins and PTX of build/strata are byte-identical to engine/strata-g3b's).
- The fingerprint block and the tab TUs are skipped on STRATA_HIP_GFX906: that build compiles no .cu from here, so
  the define, the uncompiled TUs and an unlinkable prefill_mmq_tab_test no longer appear.
- Tab instances only for Q2_0 IQ2_XXS IQ2_XS IQ2_S IQ3_XXS IQ3_S IQ4_NL IQ4_XS Q8_0, the types prefill_mmq_tab_test
  checks bit for bit; Q5_0 and the K-quants (STRATA_ORCA_Q4KS_MMQ, STRATA_MMQ_KQUANTS) keep the gather.
- overread_bytes takes the largest over-read of any config, not the over-read of the largest K tile (the over-read
  is not monotonic in the tile length).
- The test fails (instead of skipping) when a tested type has no tab, checks that Q5_0/K-quants report none, and
  pins the sm_86 over-reads (0, 72, 136 B); the dead K-quant scale branch is gone.
- SYCL's moe_mmq.dp.cpp gets the STRATA_MMQ_DIRECT stubs (false/0), for a future migrated prefill.cpp.
- moe_mmq.hpp points at docs/DETAILS.md.
2026-10-14 06:56:49 +02:00
havok2-htwo 0f10feb4d2 prefill_mmq_tab_test: pad the identity row map for memcheck
MMQ loads a whole tile's ids, and its stream-k fixup one per column tile of max_rows, past an
expert's last row (upstream behaviour on both paths; the values are not used). With the map
padded, compute-sanitizer memcheck runs the whole test clean: 0 errors, 874/874 bitwise equal.
2026-10-14 06:56:49 +02:00
havok2-htwo 20f75a7474 prefill mmq tab: the table as 16 restrict kernel parameters, so the weights keep LDG.CONSTANT loads
A pointer taken from a dynamically indexed array parameter (mmq_x_tab by value) made nvcc copy
the table to local memory and read the weights through generic LD.E loads instead of
upstream's LDG.E.*.CONSTANT: the products ran 1.2-2.5x slower than upstream's in the unit test
(Q8_0 down 2.2-2.6x, IQ4_NL 1.7-2.1x, IQ3_S 1.2-1.35x), which ate most of the gather saving.
The kernel now takes x0..x15 as `const char * __restrict__` parameters (like upstream's x)
and picks an expert's with a select chain: same SASS load mix as upstream (no local memory),
kernel time within 1% of upstream over every type and J in prefill_mmq_tab_test (69.7 vs
69.3 ms in total), and still 874/874 comparisons bitwise identical.
2026-10-14 06:56:49 +02:00
havok2-htwo 7d9b50dc1a prefill: STRATA_MMQ_DIRECT=1 reads resident experts in their cache slots (pointer-table MMQ)
mmq_plan marks a native layer direct when the pointer-table MMQ covers both products, gate/up
reads nothing past its matrix, the down over-read (72 B IQ4_NL, 136 B Q8_0) fits the 256 B
guard, and the blob is exactly [gate | up | down] in MMQ's matrix sizes; it says once how many
layers qualify.

In the MoE walk (both the staged and the streamed walk) compute() takes the expert's cache slot:
a resident expert whose slot has room for the over-read (slot_tail) and a 16-byte aligned blob
is not gathered - the group's pointer tables point at its gate|up and down in the slot, and the
guard goes into the group's GuardTab. Streamed, peer and unguarded experts are gathered as
before, at compact positions c = 0..ns-1 (gather_native, or gather_native_group with its
mid-group flushes unchanged); the end-of-group flush runs even when the last entry was direct.
At the group end one prep_group launch zeroes the direct experts' guards and the tails after
position ns, replacing the two memsets; both products run with the same n, bounds, ids,
max_rows and buffers plus .tab. STRATA_MMQ_DIRECT=0 (default) and 2 run the existing body.

PrefillStats::experts_direct, said on the generate summary when non-zero.
2026-10-14 06:56:48 +02:00
havok2-htwo b82cdb1090 expert cache: a slot guard for STRATA_MMQ_DIRECT (set_slot_guard), the sizing sites use slot_stride
ExpertCache gets inline set_slot_guard / slot_guard / slot_stride / slot_room / slot_tail; the
4-argument open_sized declaration is unchanged (the SYCL engine defines it out of line against
the same header and ignores the guard). open_sized lays slots out at slot_stride(blob, guard);
blob_ stays the largest blob, so fills, verify_slot and the HIP staging read no further.
slot_tail works on uniform caches too (through slot_offset).

generate.cpp: slot_guard = Prefill::slot_guard_bytes() (mmq::direct_slot_guard(): 256 when
STRATA_MMQ_DIRECT is 1 or 2 on a pointer-table build, else 0) for native packs; the seven
round-256 slot costs (split-skip-if-fits, split placement, per-layer sum, profile sizing,
shrink_to, cache_bytes, stage sizing) use ExpertCache::slot_stride(b, slot_guard), and the
primary and stage caches get set_slot_guard before they open. Guard 0: the same arithmetic as
before, so the default layout is unchanged byte for byte.
2026-10-14 06:56:15 +02:00
havok2-htwo 86f677b4a9 prefill mmq: pointer-table MMQ (STRATA_MMQ_TAB), prep_group, the bitwise test
A Strata-side copy of llama.cpp's MMQ outer scheduler (mul_mat_q, launch_mul_mat_q,
mul_mat_q_switch_J; fallback=false only) in src/prefill/moe_mmq_tab.cuh: each expert's base
address comes from a 16-entry table passed by value instead of x + z * stride_channel_x.
The launch geometry (J, tiles, stream-k grid and k split, fixup) is computed from the same
mmq_args, and process_tile / load_tiles / vec_dot / write_back / the fixup kernel are
upstream's own templates, so the results are the same bits. Instantiated per type from
mmq_tab_instance.cu.in in strata_mmq (same flags); moe_mmq.cu sees declarations only.

CMake turns it off unless the SHA-256 of mmq.cuh's mirrored region (mul_mat_q_process_tile
through mul_mat_q_case) is a verified one: 3cf03257 (the fetched pin; the vendored tree's
mmq.cuh is byte-identical). HIP and SYCL get nothing; Product::tab is a default-null field.

Also: overread_bytes, tab_fits, direct_mode (STRATA_MMQ_DIRECT, read once, 0 unless the tab
is built), direct_slot_guard, and prep_group (one launch: zero the direct experts' guards and
the two group tails). Nothing calls them yet; the default path is unchanged.

tests/cuda/prefill_mmq_tab_test.cu (STRATA_BUILD_TESTS): 874 comparisons on an RTX 3090, all
bitwise identical - IQ3_S gate/up, IQ4_NL and Q8_0 down (1..16 experts, rows
{0,1,7,8,9,31,64,100,512,1000}, every J 8..128, stream-k fixup on and off, max_rows above the
largest count), every other instanced type, mixed direct/gathered groups (compact c != q,
mid-group flush, last entry direct); negative control: guards left as fp16 NaN give non-finite
down outputs.
2026-10-14 06:56:14 +02:00
havok2-htwo dd5443646c batch: device-to-device slot copy for admissions and slot resumes
The main sessions and the batch slot sessions of a stage live on the same device and are
carved alike, so copy_to_slot / copy_from_slot (without a checkpoint) now copy the running
state and the QSA K/V directly (conversation_checkpoint_copy, conversation_kv_copy:
the snapshot code's private non-blocking copy stream, one device sync before and after) instead of the
checkpoint/K-V image round trip through host memory with a sync per layer. Same bytes into
the same places in the same order; the residency refresh for streamed K/V is shared with
conversation_kv_restore. Opt-in: STRATA_SLOT_COPY_DIRECT=1 (default: the host path,
as upstream).

4x RTX 3090, UD-IQ4_XS, --batch 16, split 12,24,36 + --trim-stage-weights: admission copy
65.6 -> 34.0 ms average (pure copy ~8 ms); tools/batch_test16.py 16/16 and
batch_interleave_test.py (incl. next turn from its slot) identical to solo.
2026-10-14 06:55:40 +02:00
havok2-htwo ee2a907e30 batch: more than 8 slots with a layer split (8 rows per pipeline group), hand-off sized per slot
Measured on 4x RTX 3090 (UD-IQ4_XS): 16 and 32 slots decode bit-identical to solo
(tools/batch_test16.py / batch_test32.py); 16 slots 603 tok/s batch decode vs 345 with 8.

Rebased on 0.1.42: the stages' batch row check (batch_rows_error, upstream 48f2c47d) bounds
hbase + S by the hand-off rows; set_handoff_rows passes the per-slot size there (only above 8 slots).
2026-10-14 06:55:26 +02:00
Niko1221andDemetree Kallergis b8ec9bbf94 telemetry: the Mac's Monitor cards - GPU load and VRAM from IOKit, the rest said out loud
On a Mac the Monitor tab's GPU cards were empty: telemetry had NVML (NVIDIA) and the amdgpu
sysfs files (#301) and nothing else, so the Metal backend read nothing.  The Apple GPU's load
and memory are in the IOKit registry's IOAccelerator nodes (ioreg -l -w0 -r -c
IOAccelerator, 22 ms), and the device's memory budget is the same Metal property the engine
reads (metal/src/mtl_rt.mm's recommended_working_set, the engine's "GPU working set" log line
- 26,800,603,136 bytes here, which is 25.0 GiB).

_Metal (a new reader beside _Nvml and _Amd): the index'th accelerator node's PerformanceStatistics
give Device Utilization % (older chips: the renderer or the tiler) and the in-use system
memory; the total is the working set, read through the Metal framework and objc_msgSend (no
PyObjC).  The temperature and power sensors are not readable
without root (powermetrics), and an Apple Silicon GPU sits on the die, so there is no PCIe
link: the cards show a dash and static gpu_note says why, the same way #1380's note does for a
Windows AMD card.  gpu_reader takes `amd` first, so the AMD trees still read on a Mac for the
tests, and a missing selector is asked for before it is sent (an unanswered one raises an
Objective-C exception no ctypes call can catch).

Service.free_vram_mib now goes through gpu_reader instead of _Nvml directly, so the Mac gets
that reading too (it used to return None there).

Measured on an M1 Max (macOS 26.6.2): through the server, GET /metrics during a request -
gpu_name "Apple M1 Max", gpu_vram_total_mib 25559, gpu_util 74-77 % while decoding (9 % once
idle), gpu_mem_used 10.5 GiB in use of 24.96 GiB, cpu 12.6 %; the plain-text
/prometheus-format metrics carry the same series.  serve/test_server.py: MacTelemetry
(fixture registry: two accelerators, index selection, renderer/tiler fallback, a raising
runner, the note and the samples) plus AmdTelemetry, TelemetryNoDisks, Monitor and the full
serve/test_server.py (318 tests) pass on the same box.

What it leaves alone: the NVIDIA and AMD paths (a test-only gpu_reader order change on
macOS), and the web app - the cards read the series it already had.

Co-authored-by: Demetree Kallergis <[email protected]>
2026-10-14 06:52:38 +02:00
nekomario28 be225ae20c setup: honour --source on a Mac, whose hand-over skips setup.py's parser (#2363)
setup.py returns from mac_setup() before its own argparse runs, so a Mac never
sees the --source that sets STRATA_SOURCE, and the Mac parser did not define it
either: the flag the download failure recommends landed in parse_known_args'
leftovers and was dropped with "not used on a Mac".

Define it in the Mac parser and set STRATA_SOURCE from it, mirroring setup.py.
2026-10-14 06:52:38 +02:00
Niko1221andDemetree Kallergis 2e98a86344 mac docs: the two prompt opt-ins an M1 Max cannot run (measured)
Recorded with the hardware they were measured on, per the measured-numbers rule, because
neither can be fixed here: mm_gu3's fault is a threadgroup-count threshold of the
cooperative-tensor path on this GPU (the fix shape would change the M5's register-operand
GEMM), and router_route's race has no acquire atomic to fix it with on this Metal
(device-scope atomics are relaxed-only, macOS 26.6). Both are opt-in and off by default;
the engine's M1 defaults are the v2 expert GEMMs and the separate gemv + moe_route, which
run on this box.

Measured on an M1 Max (macOS 26.6.2, Q2_0): mm_gu3 with 35 threadgroups passes and 40
faults (data-independent; the engine's tile 16x32x32 SG 4 and the v3 test's 190 tiles both
fault). router_route's logits are bitwise gemv's, but two identical runs give different
ids, weights and plan.

Co-authored-by: Demetree Kallergis <[email protected]>
2026-10-14 06:52:38 +02:00
Niko1221andDemetree Kallergis ad7345311a moe_mm_parity: the default tile that did not exist, and --v3's v1 argument list
Two stale defaults, both of which kept the test from covering what the engine ships.

The default tile was TM 16 TN 64 TK 16, but the v1 kernel set only instantiates TK 64: the
default run died at pipeline creation on any GPU (measured on an M1 Max:
"mtl: no function mm_gu_42_16_64_16_2"). TK is now 64, which both the v1 and the v2 sets
instantiate, so the default run and --v2 both work; the engine's v2 tile for Q2_0
(16,64,16,2) stays reachable with --tile.

--v3 bound the v1 kernels' argument list ({W, x, H, stok, tiles, ma}) to the v3 kernels:
tiles was read as the sorted-token buffer and MmArgs as raw int2 pairs, so every stride,
n_embd and expert id was garbage. On the M1 Max that is a deterministic GPU
command-buffer error in the GEMM pass; with the right arguments the v3 kernels run, and a
separate M1 limit shows (≥40 threadgroups of mm_gu3 fault, 35 pass, data-independent)
that the engine does not hit: gu_v3 = dn_v3 = coop_k4, which is false on the M1.
v3 now binds {W, XS, HS, tiles, ma} as the engine does, fills XS for v3 too (v3 is v2's
gather plus the register-operand GEMMs), and binds HS - not H - to down3 with DSG
simdgroups.

Measured on an M1 Max (macOS 26.6.2, Q2_0, T 256, 64 experts): default (v1) PASS, rel L2
2.53e-06 vs the fp16-operand reference and 2.37e-04 vs exact; --v2 PASS, 4.42e-06 and
2.37e-04, also with the engine's tile (16,64,16,2).

Leaves alone: no kernel, engine or other test change.

Co-authored-by: Demetree Kallergis <[email protected]>
2026-10-14 06:52:38 +02:00
Niko1221andDemetree Kallergis 831ba47afd metal: the M1 Max prompt kernels - a select with a device load in the arm loses the threadgroup
qsa_attn_mm and qsa_flash (metal/kernels/qsa_prompt.metal) fill their single-simdgroup
matmul2d right inputs with

    rk[i] = id >= 0 ? half(float(kq[row * QD + k]) * float(ksc[...])) : half(0.0f);

and that shape - a select with the device load in the arm - loses the threadgroup on an M1
Max: every dispatch of the two kernels fails with
kIOGPUCommandBufferCallbackErrorInnocentVictim, deterministically, and they run only under
MTL_SHADER_VALIDATION=1. qsa_prompt_parity dispatches qsa_attn_mm the way the file intends
(it is the matrix-unit attention of a prompt chunk) and faulted on its first dispatch before
this change. The engine reaches the same fills through qsa_flash, which it dispatches under
STRATA_METAL_PROMPT_QSA=flash; its default on an M1/M4 is the fp32 qsa_attn, which never
touches these kernels - that is why the default prompt path kept running while the parity
test could not, and why this is measured on the test rather than on a request.

The row is now clamped with max(id, 0), the load is unconditional, and the select is on the
value. For an id >= 0 the value is what it was; for an id < 0 it was discarded either way, so
the results do not change.

Measured on an M1 Max (macOS 26.6.2, Metal compiler 32023): qsa_prompt_parity ALL PASS -
qsa_attn_mm vs qsa_attn rel L2 3.09e-04 (pos0 0) and 3.56e-04 (pos0 30000), qsa_flash 3.72e-04
and 4.22e-04, qsa_score_mm worst rel 2.66e-06 (T 96, within budget and with 2051 selected
cells a token); before the change the test faulted on its first dispatch and reported nothing.

The compile failure that started this - qsa_flash's cooperative_tensor copy, "cannot
initialize a parameter of type 'void *' with an rvalue of type 'const void *'" - is already
fixed in main (#2323); this change is the runtime half of the same two kernels' M1 Max
bring-up.

What it leaves alone: the COOP_K4 path (a function constant: compiled out of the M1/M4
pipelines), qsa.metal, and every host file; no CUDA, HIP or SYCL backend builds these kernels.
docs/MAC.md records the M1 Max with the measured tok/s (the hardware's medians, from the
benchmark report: chat decode 10.6, 4K prompt 223.7, 16K prompt 228.6 tok/s).

Co-authored-by: Demetree Kallergis <[email protected]>
2026-10-14 06:52:38 +02:00
Kingdon Barrett f037612bad fix(metal): the prompt's buffers get their own allocation when no arena chunk is big enough for them
stream.cpp: the standalone-mmap fallback (the prompt's buffers as their own allocation) sat inside the chunk loop behind the slot-class check, so it only ran when a chunk was big enough for the prompt's 1.60 GB of buffers. When the arena shrank below that at the start (the 24 GB M2: chunks of 0.8-1.0 GB), every chunk was skipped and the prompt stopped with 'no arena region for the prompt buffers'. Both standalone sites - a fitting chunk whose slots a class cannot spare, and no fitting chunk at all - now share standalone_region(); the fitting-chunk carve and the slot-class rule are unchanged.

This is the half of #2323 that 0.1.44.1 could not see: the hotfix's reporter ran a 96 GB M2 Max, where the arena's chunks are several GB and the prompt region always fits. On a 16-24 GB Mac running --mmap-experts, 0.1.44.1 still stops at the first prompt with 'metal prompt: no arena region for the prompt buffers'; this makes the standalone allocation run there too.

Verified on a 24 GB M2 (macOS 26.6.2, Qwen3.8-Flash-Next GSQ-RCO-Q2_0 streaming): the fallback line appears where the error used to be, prompts run end-to-end (3.7-4.1 tok/s steady in web chat, no crashes). That run predates the standalone_region() refactor, which moves the same statements into one function both call sites use.

docs/MAC.md: the small-arena note says the prompt's buffers also get their own allocation when no chunk of the arena is big enough for them.
2026-10-14 06:52:38 +02:00
Tsury e69cbfa568 fix(serve): preserve explicit false against reasoning defaults 2026-10-14 06:52:38 +02:00
nekomario28 69fe40553d tools: poll the server address the config binds, not loopback (#2330)
strata_bench starts the server on the config's `host` but polled readiness at
a hardcoded 127.0.0.1, so a LAN bind (192.168.1.10 in the report) printed
"still loading" while the server was answering on that address.

Use the configured host, mapping the wildcard binds to loopback and bracketing
IPv6 literals; an explicit --url still wins. Patch from the report, with the
mapping lifted into server_base so a test can reach it.
2026-10-14 06:52:37 +02:00
nekomario28 a091cdf681 serve: average the throughput gauges over the window between scrapes (#2341)
/metrics/prometheus exposes llamacpp:prompt_tokens_seconds and
llamacpp:predicted_tokens_seconds as averages of the cumulative totals, so an
idle server keeps advertising the speed of its last request.

llama.cpp reads those two names from a bucket it resets on every scrape ("the
gauges are averaged over the window between two scrapes", server_metrics::bucket
in tools/server/server-common.h) and reports 0 when the bucket is empty, so a
llama.cpp dashboard on Strata froze at the last value where llama.cpp decays to
0. Keep a bucket per scrape and expose its delta.
2026-10-14 06:52:37 +02:00
Niko1221 db4dd65e56 Merge f-q36-vp (Qwen3.6 parallel requests and pictures) 2026-10-14 06:51:43 +02:00
Niko1221 1a900ae160 Merge f-14412 (setup: UD-Q5_K_XL metadata-only shard check, #2346) 2026-10-14 06:51:43 +02:00
Niko1221 6ca7e92968 setup: a metadata-only GGUF shard that ends at its header is whole (#2346: Unsloth's UD-Q5_K_XL 00001 is 10,946,618 bytes, its aligned data start 10,946,624) 2026-10-14 03:17:43 +02:00
Niko1221 95eefd51f0 tools/qwen35: q36_vision_proto says to start the engine without --mtp for its cache check 2026-10-14 02:40:00 +02:00
Niko1221 1e13cbc8a5 qwen35: keep the base engine's end-of-answer accounting (hybrid text identical), a stop keeps only x, the held tokens list every accepted draft
An earlier commit capped the accepted drafts at the end of an answer; that is an exact state, but it moved the hybrid mode's expert-slot
counts, so a sequence of requests with --mtp on a card that does not hold every expert differed from the base engine from the fourth
request on (found by comparing the 10 parity prompts against the base goldens on the 12 GB card).  Now the speculative step commits what
the base engine committed; a stop seen before the state moves keeps only x (the server's hand-over of a stopped request to a batch slot then
reuses the held state: its text equals the run alone), and the held tokens list x and every accepted draft, so a conversation that continues
from them matches the state exactly.  Setup says what parallel measured on the 12 GB card; docs/QWEN36.md updated.
2026-10-14 02:28:13 +02:00
Niko1221 a7027766ff docs/QWEN36.md: the long picture, two pictures, reads beside decoding slots, the hand-over; the picture comparison takes several pictures 2026-10-14 01:54:21 +02:00
Niko1221 296b59d2f7 Merge f-1441-perf (Responses/Codex honours reasoning_effort; setup keeps the installed size on a re-run) into f-1441 2026-10-14 01:51:12 +02:00
Niko1221 3921f57eea qwen35: a conversation's held tokens match its state exactly (no drafts past the end of an answer or a stop), reads give the decoding slots windows, pictures x2 check
spec_step takes no draft past an end-of-answer token or past the room max_new leaves, and a stop asked for before the state moves keeps
only x: every token emitted but the last is in the state, so a conversation that continues from the held tokens (the server's solo ->
slot -> solo hand-over, a chat's next turn) neither misses nor reads a token twice.  Before, an answer ending inside accepted drafts left
the state ahead of the held tokens (found by tools/qwen35/q36_serve_handoff.py: the first request's text now equals its run alone).
STRATA_Q36_READ_WINDOWS sets the decode windows of the other slots between two chunks of a prompt read (default 1).  The mtmd dump takes
several pictures; the engine logs each request's reuse; a 1,024-token test picture.
2026-10-14 01:47:11 +02:00
Niko1221 0ca1dbbaa2 pool_tasks_test: skipped on a CPU without AVX (its activation quantiser is the AVX one) 2026-10-14 01:19:42 +02:00
Niko1221 944c88314b Merge f-1441-mac (Metal: gdn_step fits 512 threads, every pipeline's thread limit checked, qsa_prompt compiles on the macOS 26.3 headers; #2323) into f-1441 2026-10-14 01:19:41 +02:00
Niko1221 dd9cbce1a2 Version 0.1.44.1: project version and the setup minimum engine 2026-10-14 01:19:41 +02:00
Niko1221 9aa674edf8 serve: the illegal-instruction note says what the CPU reports (a missing AVX/AVX2/FMA/F16C, or that it has them all and the engine is at fault) 2026-10-14 01:19:41 +02:00
Niko1221 d981a51013 serve: a crashed engine start is not retried as a GPU runtime start; the start error names how the process ended (signal / NTSTATUS) and the CPU's AVX flags after an illegal instruction (#2324) 2026-10-14 01:19:41 +02:00
Niko1221 0b6fc1cec7 nvfp4 CPU rows: no static initialisers in the AVX2/AVX-512 files (an illegal instruction before main on a CPU without AVX/FMA, #2324); check_isa_guard flags AVX-class static initialisers 2026-10-14 01:19:41 +02:00
nekomario28 ab638a5684 qwen35: widen F16 by hand so upload_f32 builds on CUDA 12.1
upload_f32 runs on the host and widens F16 with
__half2float(__ushort_as_half(...)), but __ushort_as_half is a __device__
intrinsic: nvcc 12.1 and 12.4 refuse the call ("calling a __device__ function
from a __host__ function is not allowed") and q36_engine.cu does not compile.

Widen the bits here instead, the way the neighbouring bf16_to_f32 already
does for BF16.
2026-10-14 01:19:41 +02:00
Niko1221 de9115fac7 setup: run again over an installed model keeps its size; the three env entries 0.1.44 made setup's own stay the user's in a GSQ-RCO config
0.1.44 made IQ3_S the recommended Qwen size on a PC with 64 GB or more (IQ3_S: 9 to 15% slower decode than IQ3_XXS, more RAM).
SETUP.bat / --setup on a folder that already holds a model of the family now pre-selects the installed size (and --yes takes it);
the menu marks it "(installed)" next to "(recommended)", every size stays a choice, a first install takes the recommendation.

SETUP_ENV gained STRATA_MMQ_KQ, STRATA_HC_Q8 and STRATA_ROUTE_TAIL_SKIP, which setup writes for Unsloth's files only; a setup
run again dropped a user's own value of them in any other config (a hand-set STRATA_ROUTE_TAIL_SKIP=0).  They are setup's only
in an Unsloth config.
2026-10-14 01:16:56 +02:00
Niko1221 5d08c753c2 serve: the config's reasoning_effort reaches the Responses API too; reasoning_effort false is a level; serve/test_effort_paths.py pins every request form's prompt
/v1/responses (Codex) read only the Chat settings shared with apps, so the config's "reasoning_effort" (#1641) never applied
there (it always thought at xhigh); Service.effort_default() is now the one place that says which level a request that names
none gets, for the chat, Messages and Responses routes.  openai_to_messages dropped "reasoning_effort": false (an `or` between
the two fields); effort_kwargs already treats false as thinking off.

The new test renders the prompt of every way a client sets the level (OpenAI reasoning_effort / reasoning.effort /
chat_template_kwargs, Messages API output_config.effort / thinking budgets at the 2048 and 8192 limits / disabled, Responses),
the config key, the shared Chat settings and their precedence, the web app's request shape, tools and a conversation.
2026-10-14 01:16:56 +02:00
Niko1221 cfc7686c00 tools/qwen35: the Qwen3.6 pictures and parallel-requests gates (engine protocol harness, solo / batch identity, protocol edges, llama.cpp picture comparison, throughput A/B) 2026-10-14 01:11:42 +02:00
Niko1221 a9adfa5dad Qwen3.6-35B-A3B: setup asks for pictures and recommends parallel requests; docs
Setup: the images question for qwen36 (GPU encoder on an NVIDIA card of 16 GB or more, the CPU encoder otherwise, AMD under Linux on the
CPU; --vision gpu kept as asked with a note), the pinned mmproj (size and SHA-256) beside the GGUF, the vision section and --vision in
the config; --parallel N is written as asked with what a slot costs, and the recommendation is said where every expert still fits.
docs/QWEN36.md: pictures and several requests at once with the measurements.
2026-10-14 01:11:11 +02:00
Niko1221 7419037255 qwen35: --batch-mtp (each slot verifies an MTP proposal in the batch window) and a clear refusal when the slots' caches cannot fit
A slot's window carries its next token and, for the greedy slots that fit beside one row per slot, the proposal of its MTP block;
the proposals for the next window come right after the window from its own hidden states (the first from the state the prompt
left).  Grouped GDN rows (a slot's rows in sequence on its own state), verify windows and their commit run per slot; every slot's
tokens equal its solo run.  The engine also says what the sessions take and stops with the numbers when they cannot fit.
2026-10-14 01:11:11 +02:00
Niko1221 b4ef48e941 qwen35: sessions, parallel requests (--batch N) and pictures (--vision, M-RoPE) in the Qwen3.6 engine
One conversation state per session; --batch N keeps N of them and decodes one token of each in a single window (rows of
several sessions in one forward, bit-equal to the solo rows), reads a prompt between the other slots' windows and takes a
conversation over from the session that holds its start.  GENI / BGENI pictures: the encoder's rows replace the embeddings
of the <|image_pad|> cells, positions as llama.cpp's mtmd (interleaved M-RoPE 11/11/10, text after a picture continues at
p + max(nx, ny)).  tools/qwen35/q36_mtmd_dump.cpp is llama.cpp's side of the picture check.
2026-10-14 00:46:16 +02:00
Niko1221 5ce999455b Metal: gdn_step fits its launch size, every dispatch checks maxTotalThreadsPerThreadgroup, qsa_prompt compiles on macOS 26.3 (#2323) 2026-10-13 23:21:28 +02:00
Niko1221 ed4773eb7c README translations: Mac install steps and the two arena opt-ins (#1904, #1905) 2026-10-13 21:23:37 +02:00
Niko1221 2c4005cee0 README: how to install on a Mac, and how to turn on the two arena opt-ins (#1904 --adapt-async 1, #1905 STRATA_PIN_BY_NEED) 2026-10-13 21:05:49 +02:00
Niko1221 c7cbf787ab Merge f-144-ruben (RubenTorney's #1904 --adapt-async in the arena and #1905 pin by need, as opt-ins) into f-144-rel 2026-10-13 20:22:43 +02:00
Niko1221 3b788e183f docs: STRATA_ADAPT_OVERLAP never runs on a layer split, in 0.1.43 either (#2281)
0.1.43's gate already had 'not on a layer split' as its first predicate; it printed the line only when the variable was set. A default 0.1.43 split ran without the overlap, so 0.1.43.1's opt-in default changes nothing on a split. Measured on 2x A4000 (IQ3_XXS, layer split, 5 interleaved pairs): v0.1.43, v0.1.43.1 and v0.1.43.1 + STRATA_ADAPT_OVERLAP=1 decode within 0.6% of each other.
2026-10-13 19:32:36 +02:00
Niko1221 af452c1ecb pinned: load_experts_ranges with a PadMap is an overload, not a default argument - the SYCL build's own pinned.dp.cpp defines the 7-argument signature only (the b70 link failed with an undefined reference) 2026-10-13 16:52:15 +02:00
Niko1221 f087f780ed arena: pin by need - the cap's leftover goes to the pairs taken as GPU-resident (a second tier of ranges, never merged with the first: the prompt read streams whatever the adaptive tier has swapped out of the cache) 2026-10-13 15:59:05 +02:00
Niko1221 d6bd7c1d62 Merge f-mac-rel ccfe67aa (Mac memory-safety fix for big Macs) into f-144-rel 2026-10-13 15:10:49 +02:00
Niko1221 ccfe67aa07 metal_repack.py: say what F_NOCACHE does on macOS (writes uncached, reads still cached: measured) 2026-10-13 15:08:55 +02:00
Niko1221 55e1283174 arena: pin by need - blob_at (the async tier's source) follows the padded layout; no padded layout with a shared arena file (one layout for every process) 2026-10-13 14:53:19 +02:00
RubenTorney ab6bce05de arena: pin by need (STRATA_PIN_BY_NEED, opt-in) + PCIe share floor (STRATA_PCIE_MIN1, opt-in)
On Windows cudaHostRegister of the whole arena fails (the WDDM shared budget is about half the RAM) and the
sliced fallback registers the first ~30 GiB: with Qwen3.8-Flash-Next IQ3_S layers 0-31, so layers 32-47 never
get a PCIe share, while part of the registered prefix holds GPU-resident experts that DMA never reads.

STRATA_PIN_BY_NEED=1 (the arena on one GPU):
- every blob gets a page-aligned stride (PadMap in pinned.hpp, ArenaExpertSource::arena_off, +0.15 % RAM), so any
  set of blobs can be registered exactly; the loaders place each blob at its padded offset
- the expert profile's pairs past the estimated GPU-resident count are merged into ranges by rank and registered
  before any page is touched, up to STRATA_ARENA_PIN_GIB (29 GiB by default on Windows) or the first refusal
- pinned() / device_alias() / pcie_layer() work on the ranges (a blob is pinned only if wholly inside one);
  lock_resident_ranges() keeps the holes between them resident
- one start-up line: "pin by need: N ranges, X GiB pinned, Y % of the non-resident experts"

STRATA_PCIE_MIN1=1: the PCIe share (nmiss * pcie_num) >> 8 rounds to 0 at 1-2 misses per layer; with two or more
misses one goes over PCIe (when its blob is pinned).

RTX 3090 + Ryzen 5 5600X: 28.96 GiB registered = 92 % of the non-resident experts, all 48 layers with a PCIe
share; prompt read +5-7 % at 56K-117K tokens, decode level alone and +2-3 % with --adapt-async 1 and
--pcie-frac 0.6 (bench/results/2026-10-11-community-rtx3090-5600x-arena-pin-by-need, docs/DETAILS.md).

Both opt-in; without them the layout, the loaders and the sliced pin are those of v0.1.42.
2026-10-13 14:50:46 +02:00
RubenTorney 1aa0abf63a serve: --adapt-async 1 in the arena mode (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 (#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).
2026-10-13 14:50:46 +02:00
Niko1221 62be0f3843 metal stream: wire the filled arena with mlock (a file write beside the idle engine froze the M5 Max in a control run)
The GPU's own wiring of the arena ends seconds after its last command buffer, and a Metal residency set did not hold it either
(wired memory 75 -> 3 GB between requests, measured with vm_stat and a probe). Idle, the arena is ordinary anonymous memory, and a
20 GB file written beside it made macOS compress tens of GB of it: the third panic (wired 2.4 GB, file cache 50 GB, compressor 1.9M pages).
mlock keeps it wired (STRATA_METAL_WIRE_ARENA=0/1, default on from 64 GB; not when the fill stopped early). Same write, arena wired,
full speed: compressor +0.7M pages (the engine's non-arena memory), 408 pages swapped, nothing else.
docs/MAC.md: the footprint cap, the wiring and the new variables.
2026-10-13 14:04:22 +02:00
Niko1221 caac711395 setup: UD-* on a card of about 8 GB - estimate the VRAM the engine needs, write the least harmful config that starts (4-bit KV, smaller context, then no draft layer on the GPU), say so, warn that UD-Q4 is very slow there and suggest IQ3_XXS / IQ3_S; tests 2026-10-13 13:51:01 +02:00
Niko1221 e2bf3d36a2 metal: a hard cap on the engine's whole resident footprint, and no engine beside a repack (the two M5 Max watchdog panics)
Both panics (watchdogd starved 92 s) had the streaming engine at 95.3 / 89.9 GiB resident, free memory 13 MB, the compressor at 2-4M pages.
macOS keeps a file-cache floor (vm.vm_page_filecache_min, 37.2 GB on the 128 GB M5 Max) and compresses anonymous memory instead of dropping
file cache below it; the arena is anonymous and the GPU wires it only while a command buffer runs, so during the fill and when idle it is
pageable. Measured with a 1 s memory watchdog: old build + 100 GB arena, or auto arena + 40 GB file write + a 16 GB program: compressor 21k -> 4.07M
pages in 10 s, 29,000 pages swapped, pressure warn. The 67% rule counted only cx.allocated() (7.5 GB) while the process held 11-15 GB more, and
67% was too much anyway.

- arena_budget.h: footprint_cap (anonymous memory: arena + Metal buffers + what the process holds, task_info phys_footprint) = 60% of the RAM on
  a Mac of 64 GB or more (and at least the file-cache floor + 12 GB left); resident_cap (a resident pack's mapped file pages, measured: UD-Q4 resident,
  wired 91.7 GB, 40 GB write + 16 GB program, nothing compressed) = 70%; STRATA_METAL_LEAVE_SHARE for measuring. The explicit
  STRATA_METAL_ARENA_GB is kept and flagged when it is over the cap.
- window.cpp logs the planned total (arena + held + n-gram reserve against the cap) and the footprint after the fill.
- the engine refuses to start while a repack or setup's model preparation holds a lock beside the model (STRATA_METAL_IGNORE_REPACK=1 overrides).
- metal_repack.py: unbuffered write(), F_NOCACHE on the shards and the output, fsync every GiB, a pid lock (file cache stays flat; the old tool filled all 128 GB).
- setup_mac.py: no engine while preparing a model (stops setup), start() waits on a live repack lock, resident rule = the engine's resident_cap.
- tests: arena_budget_test.cpp (47 checks), tools/test_setup_mac.py (repack guard).
2026-10-13 12:47:21 +02:00
Niko1221 d54e73fad5 setup: image generation (Qwen-Image) hidden from --help (options still work); README: Apple Silicon Macs line 2026-10-13 12:31:31 +02:00
Niko1221 226e061756 Mac: link the merged tree (commit batch off on Metal, stubs for the 0.1.44 entry points, version 0.1.44-metal) 2026-10-13 12:07:31 +02:00
Niko1221 0e7a4694e5 mtp: the draft graph node listing (STRATA_VERIFY_NODES) is CUDA/HIP only; the Metal build had no cudaGraphNodeGetType (merge fallout of f-latency into the Mac branch) 2026-10-13 12:03:42 +02:00
Niko1221 6a74320caa Merge f-mac-rel (Mac Metal support) into f-144-rel 2026-10-13 11:39:25 +02:00
Niko1221 081daa3078 docs/MAC.md: final M5 numbers for UD-Q5/Q6, prompt chunks, the M4 with a small arena 2026-10-13 11:30:05 +02:00
Niko1221 d1f4f44845 metal: a streaming Mac with 96 GB or more reads prompts in chunks of 4096 (UD-Q5 on the M5 Max: 4K and 32K prompts 700 -> 1,100 tok/s warm; the decode is unchanged) 2026-10-13 11:19:48 +02:00
Niko1221 54b61dbb11 pool: STRATA_POOL_UMWAIT only on MSVC proper; the Windows HIP build (clang with the MSVC ABI) has no WAITPKG intrinsics (#2174 follow-up) 2026-10-13 10:59:31 +02:00
Niko1221 107f9b62b3 setup: Unsloth defaults (owner): STRATA_MMQ_KQ=1 for UD-Q5/Q6, STRATA_HC_Q8=1 on CUDA for the UD-* files, STRATA_ROUTE_TAIL_SKIP=0 where every expert is in RAM; golden configs re-recorded, tests 2026-10-13 10:58:40 +02:00
Niko1221 edb0870fe3 docs/MAC.md: Unsloth UD-Q4/Q5/Q6 on the M5 Max, the recommended sizes, the arena's wired cap 2026-10-13 10:50:55 +02:00
Niko1221 43d14715bd metal stream: the arena plus the engine's own buffers stay under 67% of the RAM (wired through the residency set; UD-Q6 on the 128 GB M5 Max with a 90 GB arena made macOS swap and then freeze, 84 GB ran clean) 2026-10-13 10:33:44 +02:00
Niko1221 f5a6fb47fd metal stream: a small arena gives the prompt's buffers their own allocation instead of a region of its slots (a class left under 512 slots stopped the engine with 'no free slot' at the first prompt; seen on the 32 GB M4 with 14 GB available at start) 2026-10-13 10:25:04 +02:00
Niko1221 82fa92ff33 isa guard: the NVFP4 AVX-512 row functions are wide on purpose (both callers test cpu_avx512_ok) 2026-10-13 10:21:06 +02:00
Niko1221 f3ee1819e6 setup: IQ3_S (Qwen, Swift) and UD-Q4_K_XL / UD-IQ4_XS (Unsloth) are the recommended sizes and the defaults where the RAM fits them; the largest that fits otherwise. Golden configs re-recorded 2026-10-13 10:06:10 +02:00
Niko1221 c4427238f9 setup on macOS: IQ3_S and UD-Q4_K_XL are the recommended sizes; IQ3_S stays the default where it fits, UD-Q4_K_XL is named as the higher-quality choice 2026-10-13 10:02:57 +02:00
Niko1221 201eb32ff5 setup on macOS: a big Mac that streams (UD-Q5/Q6 on 128 GB) keeps the MTP draft layer with --spec 3 and skips the experts' copy; UD-Q5/Q6 marked measured 2026-10-13 09:52:56 +02:00
Niko1221 cb88d3d2e3 isa guard knows nvfp4_avx512.cpp; check_architecture leaves other architectures to read_geometry's by-name refusal 2026-10-13 09:52:06 +02:00
Niko1221 289f8f03a7 0.1.44: version, engine minimums, strata_kq packaging, the model menu
- CMake project version 0.1.44; setup MIN_ENGINE (0, 1, 44); NVFP4_ENGINE (0, 1, 44) (UD-Q5/Q6 were already 0.1.44).
- setup: a prebuilt zip without strata_kq leaves no stale library next to the new engine (kept in .previous); the
  Dockerfile copies libstrata_kq.so into engine/.
- Model menu: families in the order Qwen (GSQ-RCO), Swift, Coder, Unsloth, NVFP4, Qwen3.6; NVFP4 is not listed on AMD
  and Intel (the Unsloth line names UD-IQ4_XS there); on NVIDIA its line says native FP4 (RTX 50) or that UD-IQ4_XS is
  faster on this card, with the download and RAM need. The Unsloth family lists its five sizes, images on.
- strata_mcp's built-in tables know the NVFP4 sizes and family. tools/test_setup_menu.py.
2026-10-13 09:34:48 +02:00
Andy Slater 65cf54355f sycl: prompt GDN recurrence with one barrier per token on Alchemist (bit-identical; A770 prompt 8K +3-5%, 32K +7%; STRATA_GDN_XE=0 for the column kernels)
Variant 6 of gdn_recurrence_variant (sycl/include/strata/prefill/gdn_xe.hpp): the column kernel's four row groups
and FMA chains in the same order, a 16-lane sub-group holding four columns x four row groups, so the cross-row-group
sums are sub-group shuffles and a token needs one work-group barrier instead of five (256 GRFs a thread).

Arc A770 16 GB (xe, oneAPI 2026.1 JIT), same day, a0116b27 + #2190 + #2193 with and without this commit:
gdn_parity recurrence 51.0 -> 24.5 ms at 8,192 tokens, 204-236 -> 110-113 ms at 32,768 (48 heads), 0 mismatches
(state, FP32, FP16). Coder IQ1_M, 128K context, int8 KV, --resident-experts: prompt 386 -> 396 / 407 tok/s at 8K,
478 / 480 -> 511 / 518 tok/s at 32K (2 runs each), the same output ids in every run.

On by default on Alchemist only (strata::intel_gpu_gen); every other card keeps the column kernels, unchanged.
STRATA_GDN_XE=0 turns it off, =1 turns it on for any Intel GPU with 16-lane sub-groups. gdn_parity compares
variant 6 with variant 0 bit for bit (state, FP32 and FP16 outputs) on any Intel GPU and skips elsewhere;
ctest -R prefill_gdn_parity runs only that part.
2026-10-13 09:28:00 +02:00
Andy Slater d4b48b3380 sycl/A770: fused GR read with more, smaller work-groups on Arc A-series
On the A770 the multi-token GR read's kernels launch too few work-groups to fill the card. With
STRATA_GR_MORE_GROUPS on:
- sliced down kernel: one work-group per (slice, row block), 80 x 6 = 480 groups instead of 80;
  every row's partial sum is computed exactly as before, only by a different group.
- gr_down_reduce: 8 slice loads in flight per step, then added one at a time, so x accumulates
  slices 0, 1, ... 79 in the same sequence of float adds as the old loop (-fp-model=precise).
- up kernel: 8 columns per group, 320 groups instead of 160 (the kernel is now templated on the
  column count; UPM_COLS stays 16 for every other user), and only group 0 writes the per-token lo
  values, which every group computes identically.

Default on Alchemist only (strata::intel_gpu_gen); Battlemage and other devices launch the same
kernels as before. STRATA_GR_MORE_GROUPS=1 forces it on, =0 off; gr_bench runs either way.

Measured on an Arc A770 16 GB (xe, oneAPI 2026.1 JIT), same day, a0116b27 + #2190 + the previous
commit (GR_PICK, large GRF), with and without this one: gr_bench 1-6 tokens 118.9-183.5 -> 94.6-148.4 us,
checksums identical for every token count; gr_multi_parity 32 cases OK with STRATA_GR_MORE_GROUPS=0 and =1.
Decode, Coder IQ1_M, 128K context, int8 KV, --resident-experts, STRATA_VERIFY_STEPPED=1, 8K prompt, 256
tokens: 22.12 / 22.35 / 22.55 / 22.65 -> 23.24 / 23.61 / 23.62 tok/s (+3-5%), output ids identical.
Not built or run on Battlemage.
2026-10-13 09:27:55 +02:00
Andy Slater e682bded4b sycl: fused GR read without the private GrMulti copy (GR_PICK); large GRF on Arc A-series only
- GR_PICK: a runtime index into the by-value kernel argument (m.a[k]) made IGC copy the whole
  GrMulti (~1.2 KB) into every work-item's private scratch (unitrace on an A770: ~40 KB private
  per SIMD32 thread in gr_up_multi / gr_down_reduce / gr_norm_split). GR_PICK picks one field with
  compile-time indices only (a chain of selects over the uniform kernel argument). Addressing
  only: the same values, read and summed in the same order, so the output is bit-identical. This
  part is on for every device; it is not measured on Battlemage.
- The sliced down kernel and the multi-token up kernel in large-GRF mode (256 registers/thread);
  at 128 the up kernel still spills ~3.4 KB/thread on the A770 (unitrace). Large GRF halves the
  threads resident per Xe core, so it is the default on Alchemist only (strata::intel_gpu_gen);
  Battlemage and other devices launch the same kernels as before. STRATA_GR_LARGE_GRF=1 forces it
  on, =0 off.

Measured on an Arc A770 16 GB (xe, Linux 7.0, oneAPI 2026.1 JIT), a0116b27 + #2190, same day:
gr_bench 1-6 tokens 205-258 us -> 119-184 us (GR_PICK alone, STRATA_GR_LARGE_GRF=0: 186-239 us),
checksums identical for every token count. Coder IQ1_M, 128K context, int8 KV, --resident-experts,
STRATA_VERIFY_STEPPED=1, 8K prompt, 256 tokens: decode 5.37 tok/s (5.88 / 5.93 with
STRATA_DOORBELL_CHECK=1 / STRATA_LEND_MIRROR=0) -> 22.12 / 22.55 / 15.60 (cold-cache run)
tok/s, 20.61 / 20.93 with STRATA_GR_LARGE_GRF=0; the window's pool phase 183-208 -> 34-35 ms
per round; output ids identical where the expert placement matched. Not built or run on
Battlemage or i915.
2026-10-13 09:27:37 +02:00
Andy Slater ddcc5f56dc sycl: size the expert cache from the DRM fdinfo when xe reports 0 free card memory (#1545)
On an Arc A770 16 GB on the xe driver, Level Zero has no ext_intel_free_memory and get_memory_info reports 0 free
with the right total. device_free_bytes() kept the 0 (the #1440 fdinfo path only replaces a figure that is too
high), so --expert-cache auto sized the caches from 0 bytes. A 0 with a known total is now read as unknown: on
Linux the card's total less this process's DRM fdinfo figure is used, the same source the A750/i915 path uses.
Anything that reports a non-zero free figure is unchanged; off Linux the 0 stands.
2026-10-13 09:26:34 +02:00
Niko1221 c106e9629a Merge f-qimage2 into f-144-rel 2026-10-13 09:23:47 +02:00
Niko1221 de4fe43b0c Merge f-qimage into f-144-rel 2026-10-13 09:23:46 +02:00
Niko1221 4cfeaa0f4f Merge f-qwen36 into f-144-rel (geometry: #2179's read_geometry guard kept for qwen4exp, Qwen3.6's family guard on top) 2026-10-13 09:23:46 +02:00
Niko1221 66db34dc40 Merge f-nvfp4 into f-144-rel 2026-10-13 09:21:19 +02:00
Niko1221 0aef10aeae Merge commit 'cf1b0edf' into f-mac-rel 2026-10-13 09:21:10 +02:00
Niko1221 075aaacdff Merge branch 'f-mac-iq3s' into f-mac-rel 2026-10-13 09:21:06 +02:00
Niko1221 322df64128 Merge f-quants into f-144-rel 2026-10-13 09:17:53 +02:00
Niko1221 9adf4e01a7 Merge f-intel-quants into f-144-rel 2026-10-13 09:17:44 +02:00
Niko1221 0b8d31013a Merge f-latency into f-144-rel 2026-10-13 09:17:44 +02:00
Niko1221 800a0904fb strata-q36: every main layer's experts in VRAM when only the MTP block's do not fit
When the main layers' experts fit but the MTP block's do not (UD-Q6_K_XL on
32 GB), the main layers are placed as in the all-in-VRAM mode (same text,
the decode graph kept) and only the MTP block's experts go to slots + the
CPU pool (its drafts). To get there when the fit is close: the packed Q8_0
decode copies are given back, the prompt chunk stays 512, and - said in the
log - the attention scores buffer shrinks to 64 MB and the VRAM reserve to
256 MiB. STRATA_Q36_NO_MTP_CPU=1 keeps the plain hybrid mode.
UD-Q6_K_XL on gfx1201: tg128 73-75 -> 80.6 (llama.cpp HIP 81.2).
2026-10-13 07:53:24 +02:00
Niko1221 9341ebd213 strata-q36 hybrid: the whole-layer prompt copy when fewer than half the experts are resident
Many small copies were slower than the one whole-layer copy on a 12 GB card
(RTX 3060, UD-Q4_K_XL at 37 of 256 resident: pp2048 1540 in runs, 1974
whole). gfx1201 UD-Q6_K_XL (205/256) and Q8_0 (176/256) keep the per-expert
copies: pp4096 3504-3588 and 3015-3079.
2026-10-13 07:39:25 +02:00
Niko1221 cf1b0edf91 Conversation cache: a picture is matched by its bytes' hash (from the server) and its grid, not by its embedding floats (#2228)
The server already keys its encoder cache by the normalized picture bytes (sha256, the .sve file
name); it now sends those keys with the request (img_keys=<hex>,..., in prompt order), and the
engine's conversation cache uses key + grid for a picture when the count matches. Without the key
(an older server) it hashes the embeddings as before. Old engines skip the unknown key.

Measured for #2228 (one 1600x1000 screenshot-like picture, strata-vision, fresh processes and
twice in one process): the CPU encoder gives the same bits on a TR PRO 3975WX at 8/15/16/32 threads
and on a Xeon E5-2643 v3 (e2357d8e...), the GPU encoder on an RTX A4000 is reproducible too
(92cf7818...), but CPU and GPU differ. So a picture's embeddings change when the encoder moves
between CPU and GPU, or after an encoder update, and no longer on its own; with the byte key the
cache's matching does not depend on that at all. CUDA/HIP and SYCL. Test: serve/test_server.py
test_pictures_are_keyed_by_their_bytes_for_the_engine.
2026-10-13 07:33:16 +02:00
Niko1221 577abb0378 strata-q36 hybrid: a streamed prompt layer copies its resident experts from their VRAM slots
The prompt's staging buffer took the whole layer from host memory over PCIe
(~19-28 GB per chunk); now the experts with a VRAM slot are copied device to
device and only the others come over PCIe, in runs of consecutive experts.
Same bytes in the staging buffer (greedy ids identical). UD-Q6_K_XL on
gfx1201 (205 of 256 experts per layer resident): pp4096 1935 -> 3511-3601.
Also: the packed Q8_0 decode copies are given back when that lets every
expert fit (STRATA_Q36_KEEP_PACKED=1 keeps them); STRATA_Q36_STREAM_ALL=1
keeps the whole-layer copy.
2026-10-13 07:30:12 +02:00
Niko1221 ee6d8baccf serve: say when a reusable state is rejected only because a picture's embeddings changed (#2228)
A checkpoint (or the live state) is reused only when the prompt starts with its tokens AND its
pictures, and a picture is its grid plus the hash of its embedding floats. In #2228 (screenshot-heavy
agent, CPU image encoder) the cache fell back to checkpoints a long way back although the client's
messages were byte-identical; one explanation is a picture encoded again with other bits. When the
deepest state whose tokens match is rejected for a picture, the engine now logs which picture and
where, once per request, so the next log tells this apart from a rewritten history. Log only; what
is reused does not change.
2026-10-13 07:20:05 +02:00
Niko1221 a0e577de95 test: a user asking for </tool_response> (or the other tool tags) verbatim gets the text, the outer-pair exception included (#2026)
47Hunter47 measured </tool_response> asked verbatim at 0/15 on 0.1.43.1 (it reached the model as
the real closer). 62185aab already marks it; this pins the cases next to the exception that keeps
a wholly wrapped tool result's outer pair: the bare closer, a request that quotes a whole pair, a
message that only starts with the opener, two closers in one sentence.
2026-10-13 07:16:25 +02:00
Niko1221 1267f093ed docs/MAC.md: the M4 numbers with 7 GB kept and the stepped arena fill 2026-10-13 06:32:51 +02:00
Niko1221 612633c3b0 metal: the streaming arena fills in 1.5 GB steps and stops at macOS's floor; available memory is free + purgeable + the clean file cache (not other programs' inactive memory); the least arena layout goes ahead instead of failing the re-check 2026-10-13 06:32:33 +02:00
Niko1221 78c5cbbc24 q36_llama_dump: STRATA_DUMP_NGL, the GPU layers for a file that does not fit the card 2026-10-13 06:23:47 +02:00
Niko1221 67bedde10e metal: the streaming arena keeps max(7 GB, 15% of the RAM) again - a server soak with 5 GB kept swapped out 93 MB while the arena filled 2026-10-13 06:22:51 +02:00
Niko1221 f9641ff85e strata-q36: Q8_0 / F16 small tensors widened at load (the Q8_0 file's ssm_alpha / ssm_beta)
Qwen3.6-35B-A3B-Q8_0.gguf stores the GDN alpha / beta projections as Q8_0;
the engine read only F32 / BF16 there and refused the file. They are now
widened to F32 at load (fp16 scale x int8, as ggml). q36_llama_dump:
STRATA_DUMP_CTX sets a smaller context / batch for files whose weights leave
no VRAM for 4096-token buffers.
2026-10-13 06:22:45 +02:00
Niko1221 77c65b797b docs/MAC.md: 32K prompts with the experts' copy and the 34-minute server soak on the M4 2026-10-13 06:21:11 +02:00
Niko1221 bb1ed8d4c0 setup: Qwen3.6 sizes recommended by RAM (UD-Q4_K_XL 32, UD-Q6_K_XL 44, Q8_0 52 GB)
The engine keeps every expert in RAM when they do not all fit in VRAM, so a
size's RAM need is its file plus room for the rest. The largest size this
PC's RAM holds is the default; any size can still be chosen (a bigger one is
asked about, as before, never refused).
2026-10-13 06:08:19 +02:00
Niko1221 5a30c2c4e8 Images (I2): NVIDIA mma.sync flash attention for the native runner, fused q/k/v GEMM
- k_attn_mma (sm_80+): m16n8k16 f16 -> f32, 8 warps x 16 queries, 64-key K/V tiles double-buffered with
  cp.async, ldmatrix (.trans for V), fp32 online softmax.  Bench on the RTX 3060 at 4096 x 4150 keys x 32
  heads: 23.7 TFLOPS vs ggml's flash_attn_ext_f16 15.4 (0.376 vs 0.577 s/step); CPU check 7e-5.
  STRATA_QI_GGML_ATTN=1 keeps ggml's.
- q, k and v of a block with one weight type load into one [3C x C] tensor: one GEMM and one activation
  quantize instead of three (STRATA_QI_NO_QKV_FUSE=1 keeps three).
- A float4 LayerNorm path with tanh(gate) once per step, off by default (STRATA_QI_FAST_LN=1): no measured gain.

RTX 3060, Q8_0 1024, seed 42, 3 interleaved rounds: steady step 2.09 s vs stock 2.61 (1.25x), denoise
17.93 s vs 22.13 (1.23x).
2026-10-13 05:53:21 +02:00
Niko1221 92ef26cd57 docs/QUANTS.md: STRATA_PROMPT_DIRECT is mixed on a PC with more file-cache room 2026-10-13 05:50:14 +02:00
Niko1221 4b703a6777 docs/MAC.md: the 4K prompt with the experts' copy on the M4 (72.9 vs 62.5 tok/s) 2026-10-13 05:39:58 +02:00
Niko1221 3d5819df3b serve: start the engine again (2, 4, 8 s apart) when it stopped inside the GPU runtime's set-up
A start right after another engine exited sometimes fails before the engine writes a line: ROCm aborts with
"terminate called after throwing an instance of 'rocr::AMD::hsa_exception'" (or the process exits with an empty
log) while the previous process's GPU queues are still being released (r9700: 1 of ~10 rapid restarts in the A/Bs,
2 of ~40 for the quants runs). Such a start - within 30 s, no engine line other than the runtime's failure, not the
engine's own error exit 1 - is retried with a message saying why; STRATA_START_RETRIES (default 3, 0 = off).
2026-10-13 05:36:26 +02:00
Niko1221 1b210929f6 docs/MAC.md: the experts' streaming copy (M4 numbers), the arena rule, vision and Unsloth UD-Q4 on Mac, the streaming switches 2026-10-13 05:32:28 +02:00
Niko1221 703e63c1e1 docs/NVFP4.md: measured in Strata - the quant yardstick against Q8_0 (beside the Unsloth and GSQ-RCO quants), the tail skip, the decode and prompt expert kernels on the RTX 5070 / 3060 / P100, the RAM-budget mode, images 2026-10-13 05:27:38 +02:00
Niko1221 9269262f13 docs/QUANTS.md: UD-IQ4_XS and the Q6_K MMQ numbers, PROMPT_DIRECT and the budget-mode I/O A/Bs, several cards; MODELS.md UD-IQ4_XS quality 2026-10-13 05:26:35 +02:00
David d8684360b8 CUDA: service CPU doorbells while instrumented graph launches block 2026-10-13 05:25:46 +02:00
Niko1221 9d41e18bd9 layer split auto (CUDA): a stage's link scales its miss cost only against the fastest stage's link and from a 4x gap on (#2007)
0.1.41 (0391e478) scaled each stage's miss term by 20 GB/s / its probed link, for 2x 4090 D
with CUDA1 on a physical x1 link (1.6 GB/s: x12, K 22 -> 38, prompt ~350 -> ~1400 tok/s).
On 2x Tesla T10 the same rule moved auto from K=23 to K=14: CUDA1 runs 34 of 48 layers, and as
the prompt path is a pipeline the slower stage sets the rate - 256K prompt 1035 -> 795 tok/s,
decode 46.8 -> 39.5; --layer-split 23 on 0.1.43 restores both (xiake-1 in #2007).

split_rules::link_miss_scale: the scale is the fastest stage's link over this stage's, applied
only from a 4x gap (a riser or chipset x1/x4 slot beside an x16 one), capped at 64. A symmetric
rig keeps the fitted formula whatever its link speed; the x1 case still gets ~x15.
STRATA_SPLIT_LINK_ABS=1 restores the 0.1.41 rule. SYCL has no link term (unchanged).
Test: split_rules_test (the x1 case, equal gen3 cards, a 2x gap, caps, unprobed stages).
Not run on the reporter's T10s: the reply asks for the 'link ... -> miss cost' lines.
2026-10-13 05:25:31 +02:00
Niko1221 02fadf4447 metal setup: a streaming Mac gets the experts' streaming copy when the disk has room for it and 10 GB more; otherwise a warning and the GGUF 2026-10-13 05:23:14 +02:00
Niko1221 c34ac7093f metal: streaming reads each expert with one request from <gguf>.experts (stream_experts.py: gate, up, down together) - M4 IQ3_XXS after 6K: 8.62 vs 7.37 tok/s, prompts 84 vs 65 tok/s, same tokens 2026-10-13 05:23:14 +02:00
Maxim Mazurok 640ac438be --prefill-head-alias (opt-in, --serve, one GPU): the output head's VRAM holds the prompt buffers while a prompt is read
The native output head is needed only to generate, the batched prompt path's buffers only to read a prompt. With the flag the head is unloaded while a prompt is read (its VRAM counted into the auto cache and the prompt path's hybrid borrowed/owned layout) and read back in before the first decode window. On an 8 GB RTX PRO 2000 Laptop (Windows, IQ3_XXS, 590 MiB reserve) the prompt chunk went from 512 to 2,048 tokens and prefill from 292.5 to 667.1 tok/s on a 29,854-token prompt; reads of up to 512 fresh tokens cost about 0.6-0.75 s more. Off by default: every new path is behind the flag. docs/PREFILL_HEAD_ALIAS.md has the measurements and limits.
2026-10-13 05:00:30 +02:00
Niko1221 903cab02b0 Images (I2): warp-per-head q/k RMSNorm+RoPE kernel (float4, no shared memory; STRATA_QI_OLD_QKV=1 keeps the old one); WMMA attention fragment layer for gfx11 and gfx12 (gfx12 off unless STRATA_QI_GFX12_ATTN=1, not run yet) 2026-10-13 04:56:52 +02:00
Niko1221 8dc89b0f4a metal: the streaming arena keeps max(5 GB, 15% of the RAM) and reserves 0.5 GB for the n-gram table read row by row
The table is read with F_NOCACHE through a bounded row cache (1M rows), so 2 GB was too much to set aside. M4 32 GB,
IQ3_XXS decode after the 6K document, 5 interleaved runs, auto arena (memory_pressure every 3 s, vm_stat swapouts):
keep 7 + 2 GB (54c0de70) 5.93 tok/s median, arena ~8.5 GB; keep 7 + 0.5 6.59 (+11%), ~10 GB; keep 5 + 0.5 7.47
(+26%), ~12 GB; the least free memory 43-57%, no swap-out in any run. The M5 Max still keeps 15% (20.6 GB).
arena_budget_test: 14 checks pass.
2026-10-13 04:56:13 +02:00
Niko1221 728097fb6f HIP: STRATA_COPY_HIP_PRIO=1 (opt-in) creates the verifier's copy stream at high priority
ROCm gives out hardware queues per priority. Sharing one with the window's stream, --pcie-mode dma's expert copies
and the host function that raises flag B queue behind the window graph that spins on that flag: on an R9700 every
dma-mode request timed out at layer 1. With its own queue dma mode runs (copies overlap the VRAM-hit compute).
2026-10-13 04:49:15 +02:00
Vladimir 8488c06bba serve: the elastic encoder's VRAM figure after the driver's counter caught up
The figure in "[strata] images: the image encoder started in N s, M MiB of VRAM" read the free VRAM right after the
cache's shrink, before the driver's counter showed it (amdgpu sysfs), so it came out low (286-362 MiB against the 1,339
measured otherwise). A 0.2 s wait before that reading, only on a start that shrank the cache.
2026-10-13 04:36:30 +02:00
Vladimir ca41a6b957 serve: the image encoder only while there are pictures ("elastic": true in the vision section)
Opt-in, with the config's "vram_elastic": the GPU encoder does not start with the server or a load. A picture's turn
makes the expert cache keep "elastic_mib" (default 2048) free on top of the reserve and starts the encoder; after
"elastic_idle_s" (default 120) without a picture a thread stops it between requests and the cache grows back to the
reserve (0 when no POST /v1/vram was made: the start's reserve left it a segment or more smaller). A POST /v1/vram
while the encoder runs stacks on its share; an unload stops it. Without "vram_elastic" the server says so and starts
the encoder as before. serve/test_vision_elastic.py pins each case; docs in VRAM_ELASTIC.md and DETAILS.md.
2026-10-13 04:36:30 +02:00
Coby Tamayo e8b4551173 rm git dep 2026-10-13 04:36:30 +02:00
Coby Tamayo a55fd1f24e rm confusing comment 2026-10-13 04:36:29 +02:00
Coby Tamayo 68140bbdee document Nix install 2026-10-13 04:36:29 +02:00
Coby Tamayo 6a99330817 rm claude-code 2026-10-13 04:36:29 +02:00
Coby Tamayo 01249588f4 Nix environment 2026-10-13 04:36:28 +02:00
bulhenvaster c046273318 setup --update: an MTP folder shared by several configs keeps the draft subset of the most recently used one (the oldest config's default subset replaced cyrillic: Russian decode 68 -> 54 tok/s on an RTX 5060 Ti + RTX 3060, IQ3_XXS)
update_install refreshed the draft subset once per installed config, newest first, so a folder that two configs
name ended with the subset of the config used longest ago. A config without "draft_vocab" (cjk) then put the
default subset over the cyrillic one of the config in use. Now the first config that names a folder decides;
separate folders and a start (which installs its own config's subset) are as before.

Checked: tools/test_setup_draft_vocab.py (3 new tests, 10 pass), test_setup_config and test_setup_configs (18 pass).
Measured on the affected install, two alternating runs each, greedy 600-token Russian story: 54.0 / 54.0 tok/s
with the default subset installed by the update, 68.7 / 68.6 with the cyrillic one (1.39 -> 1.90 tokens per window).
2026-10-13 04:36:28 +02:00
Niko1221anddvasdekis 2f335a5eab tools/windows/enable_large_pages.ps1: grant "Lock pages in memory" to the current account (#2185)
A helper for the large-page arena (#1412): run as Administrator, it adds the account to
SeLockMemoryPrivilege with secedit, says that a new logon is needed, and prints the secpol.msc
steps when it cannot run. Changed from the PR: secedit /configure is limited to
/areas USER_RIGHTS (the exported policy is not re-applied as a whole), and the description no
longer claims a speed-up we have not measured. docs/DETAILS.md points to it. Not run on our side
(no Windows box for it).

Co-authored-by: dvasdekis <[email protected]>
2026-10-13 04:36:04 +02:00
Niko1221anddvasdekis ea73bc2522 Windows HIP: hipKernelNameRefByPtr is resolved at run time (STRATA_VERIFY_NODES), so a runtime DLL without it still starts (#2183)
Some amdhip64_7.dll builds (AMD TheRock wheels / ROCm 10.2 / 7.2.4 nightly) do not export
hipKernelNameRefByPtr although their import library has it, so strata.exe failed to load with
STATUS_ENTRYPOINT_NOT_FOUND before main. It is only used to name graph nodes under
STRATA_VERIFY_NODES; on Windows it is now looked up with GetProcAddress and a missing one
leaves the node unnamed.

From #2183, its verify.cpp part only. The PR's other part (Windows HIP --pcie-mode auto as
DMA) changes the default path of every Windows AMD user and was not measured on our side; it
is left out.

Co-authored-by: dvasdekis <[email protected]>
2026-10-13 04:35:37 +02:00
Niko1221 5e54a301ef SYCL #2194: drain the other queues before every decode window on every Alchemist card (A770 on xe too), not only on i915
An Arc A770 under xe intermittently never started decoding: the main thread waits in Verifier::run's stepped serve
(queue::wait -> urQueueFinish) for a segment that never drains, xe logs nothing (#2194). The A750's same failure was
fixed by draining the other queues before each window (STRATA_WINDOW_SYNC, default 1 on i915 only). Reproduced on
the A750 by turning that off: STRATA_WINDOW_SYNC=0, STRATA_VERIFY_STEPPED=1, --resident-experts, IQ3_XXS, 4K prompt:
1 of 6 runs hung with #2194's stack; with the default drain 0 of 11 (5 unpinned, 6 with the pipelined helper pinned).
The default is now 1 on i915 or on an Alchemist device (intel_gpu_gen), 0 elsewhere; STRATA_WINDOW_SYNC overrides.
Unchanged on the A750 (i915: already 1) and on Battlemage (0). Not run on an A770 under xe (no such card here).
2026-10-13 04:33:15 +02:00
Niko1221 987548ce2c gfx12 chunk rule: with --resident-experts the RAM copy to come (every uncached expert plus the loan) counts, and the margin is 6 GiB (#2090)
The first version compared only the extra loan with the RAM available at that point, but the
resident RAM copy is pinned after it and holds the lent slots' experts too: in a 30 GB scope on
an R9700 (IQ3_XXS, --resident-experts) 30 GiB were available before the 23.35 GiB copy, so the
rule never fired. The reporter's PC thrashed with 3.4 GB left at 16384 and ran with ~6.4 GB at
8192, hence 6 GiB.
2026-10-13 04:28:32 +02:00
Niko1221 0bfa422899 setup: images for the NVFP4 packs - the original's image encoder (ISTA's mmproj, pinned by size and SHA-256), the dense GGUF as its vocabulary
Both NVFP4 packs keep Qwen's vision tower unquantized, so the image encoder every Flash-Next model uses reads pictures
for them; strata-vision opens the text model vocab-only, which is the pack's dense GGUF here.  Setup asks about images as
it does for every model (default no; --vision gpu|cpu), the encoder is the file other installs already share
(mmproj-Qwen3.8-Flash-Next-BF16.gguf at ISTA's pinned revision, 907,543,008 B, sha256 b1a82259...).

Checked end to end through the server on an RTX 5070 (budget mode, GPU encoder, 1024 image tokens): a picture with
"CODE 4217", a red square on the left and a blue circle on the right - NVFP4 answered "4217" and described both shapes,
their colours and sides correctly, as IQ3_XXS did on the same picture.  VRAM: the expert cache held 393 slots with
images (--vram-reserve-mib 2100 and the encoder) against 982 without (1500).
2026-10-13 04:18:43 +02:00
Niko1221 7d7da88177 Opt-in STRATA_PROMPT_DIRECT=1 (Linux): with the file tier read through the file cache, the prompt path's batched expert reads go unbuffered (merged O_DIRECT requests); the same bytes 2026-10-13 04:14:29 +02:00
Niko1221 1a55fc3788 gfx12: the 16384 auto prompt chunk stays at 8192 when the RAM available does not cover its extra prompt loan (#2090)
The gfx12 default (0.1.43) lets a bare --prefill auto reach 16384, which lends the prompt path
about twice the cache slots of 8192 (R9700, Swift 1.5 IQ3_XXS: 3,907 slots / 6.38 GiB against
2,068 / 3.37 GiB); the lent slots' experts are read from the RAM side during the read. On a
30 GB PC with --resident-experts 38-47K prompts went 20 GB into swap with 1.5M major faults
and the engine was killed; --prefill 8192 ran them at ~95 tok/s (bdwilton in #2090).

At start, when the engine's own 16384 ceiling is in effect, the extra slots of a 16384 loan
over an 8192 one are priced at the largest blob; if the RAM available (the cgroup or
--memory-limit-mib cap included) is below that plus 4 GiB, the ceiling stays at 8192 and a
line says why. STRATA_GFX12_CHUNK=1 keeps 16384; an explicit --prefill N / auto:N is never
touched (the 16384 default only applies to a bare auto).
2026-10-13 04:14:11 +02:00
Niko1221 b5217c8bb7 serve: the VRAM-free check at start covers a layer split's later cards too (#2192)
The 'MiB of VRAM free with everything loaded' line and its LOW warning read CUDA0 alone. In
#2192 (2x RTX 2080 Ti 22 GB, Windows, IQ3_S, --batch 4, --layer-split auto, 0.1.43) CUDA0 had
740 MiB free while CUDA1 began its window captures at 153 MiB and fell to 52; the first batch
window then never finished. Both stall dumps show the host thread inside cudaGraphLaunch called
from Verifier::run_slot_rows (the stage still 'idle': it had not reached its per-layer wait), the
pool asleep and the watchdog firing after 60 s - a page-in under WDDM while the other card's
graph spins on a host flag.

Each later card now gets its own line, and below 512 MiB a LOW warning with the
--vram-reserve-later-mib value that leaves ~768 MiB. Said, never changed.
2026-10-13 04:12:24 +02:00
Niko1221 fb654ba3e8 Windows AMD: the card's name and VRAM from the registry's display class, in the server's hardware_static and in strata_bench (#1587)
On Windows with only an AMD card neither NVML nor the amdgpu sysfs files answer, so
hardware_static.gpu_name was None and strata_bench (no nvidia-smi, no rocm-smi on Windows)
labelled the run "CPU only" although the engine ran on the card (ByteJuggler in #1587: RX 6900 XT).
telemetry.windows_display_adapters reads DriverDesc, ProviderName, DriverVersion and the memory
size from HKLM's display class (no subprocess, no vendor library); windows_amd_cards drops a
Ryzen's integrated Radeon (512 MiB here) when a real card sits beside it. hardware_static gets
the name and gpu_vram_total_mib; strata_bench uses the same list when nvidia-smi and rocm-smi
give nothing. Load, VRAM use, temperature and power stay unread on Windows AMD (that is the
reader of #1224 / #1434 / #1871). Checked against this PC's registry (RTX 5070 + the Ryzen 7600's
iGPU: both listed, the iGPU's 512 MiB read); tools/test_windows_amd_gpu.py with a fake registry.
2026-10-13 04:12:24 +02:00
Niko1221 23db5f9555 setup_intel: a layer split whose experts will likely not fit writes STRATA_VERIFY_NO_HOST=0 and says so (#1980)
The stock split shape (STRATA_STAGE_TRIM=1, 1024 MiB reserve, NO_HOST=1 from strata-sycl.sh) is
refused at the start on a 2x Arc Pro B60 24 GB pair with IQ3_XXS: the second stage is 2230-3731
experts short and the host mirror covers the first stage only. The same config with NO_HOST=0
runs at 39-50 tok/s with 0 faults (jds1-ai in #1980). When the model's experts take more than
80% of the split cards' VRAM, setup now writes NO_HOST=0 into the config (a value the user set
is kept) and prints why and how to turn it back. IQ2_XS on the same pair (74%) keeps NO_HOST=1.
Test: tools/test_setup_sycl.py test_split_short_rule.
2026-10-13 04:12:24 +02:00
Niko1221 1955774783 SYCL layer split: a REFUSED start exits cleanly, and a later stage's misses no longer read the first stage's mirror table (#1980)
- refuse_exit: after the REFUSED message the engine waits for the queued device work, flushes
  and _Exit(2)s instead of returning from main. Returning ran the stages' destructors in an
  order the UR loader did not survive: on a 2x Arc Pro B60 pair every REFUSED start segfaulted
  in libur_loader, and a trimmed one also left an xe page fault (bcs CAT error) on the second
  card that hung the next start (jds1-ai in #1980).
- resident_plan_set_mirror takes the table's length; resident_plan uses the mirror and the
  usage counts only for a residency slice inside the table they were set for. A later stage
  passes its own residency table, so the slice was taken as an offset across allocations and
  read (and counted into) another buffer: the stage-1 xe faults with STRATA_VERIFY_NO_HOST=0
  and no trim (10 of 10 requests, 0 tokens). Such a miss is now a plain miss, served by the
  host. Patch shape as jds1-ai proposed it.

Compile-checked only (no two-card Intel box here).
2026-10-13 04:12:24 +02:00
Niko1221 cb22a53e0e Adaptive overlap: the host-function signal is the Windows default, and the copy stream is flushed after the swaps are queued (#2188)
Under WDDM a stream's work sits in the driver's command buffer until a driver call flushes it.
With the stream-ordered signal the verify window only spins on a pinned int, so the last
layers' copies and their 4-byte signal copies were never submitted: the first request stopped
with "the adaptive tier's copies for layer 45 never landed" (RTX 4070 SUPER, 0.1.43.1, opt-in
STRATA_ADAPT_OVERLAP=1). STRATA_ADAPT_SIGNAL=host worked.

- Windows: the host function is the default signal; STRATA_ADAPT_SIGNAL=copy asks for the copy.
- Every platform: one cudaStreamQuery on the copy stream after the swaps and their signals are
  queued (a no-op for the results; it submits the batch under WDDM). Linux keeps the copy
  signal as before.

Needs a Windows run with STRATA_ADAPT_OVERLAP=1 STRATA_ADAPT_SIGNAL=copy to confirm the flush.
2026-10-13 04:12:24 +02:00
Niko1221 c18d4c2bd5 docs/INTEL_ARC: the auto split's headroom pick on equal cards (#1440) 2026-10-13 04:12:24 +02:00
Niko1221 8af75e1a39 dequant_wide_on: (void) on the cleared CUDA errors (HIP marks hipGetLastError nodiscard: two new warnings) (#2178 port) 2026-10-13 04:12:24 +02:00
Techannel 5025324c2b docs + bench: the Tesla P40 (sm_61) profile, the four changes and their measurements
bench/results/2026-10-12-p40-sm61-kernels: where a prompt and a decode window spend their time on a P40, the kernel
benches and parity runs, every request of the engine A/B (565-token prompt 205 -> 255 tok/s, decode 34-35 -> 37-38
tok/s; with STRATA_DENSE_F32=1 a 7K prompt 360-432 -> 464-474 tok/s), the byte comparison of the answers, and what
was not tested.  docs/OLDER_GPUS.md: the sm_61 section and switches, and two traps when measuring on such a card.
2026-10-13 04:12:24 +02:00
Techannel 2216161362 sm_61: expert mode 8 and its own interleaved-matvec tables by default (bitwise; STRATA_SM61_TABLE=0)
As sm_60 got with STRATA_SM60_TABLE, measured on a Tesla P40 (native dp4a):
- native_expert_bench, 18 groups at 2 tokens on the IQ3_S pack's layers, mode 0 -> mode 8, bitwise: IQ3_S 390 ->
  255 us, IQ3_XXS 345 -> 252, IQ2_S 290 -> 238, IQ4_XS 328 -> 261.
- kIlRows_61 / kIl1Rows_61 from three runs of mmvq_il_parity --bench --emit-table (identical but two Q3_K cells;
  a cell is non-zero only where every run gained 3%).
2026-10-13 04:12:24 +02:00
Techannel 40ba0cf93d prefill gemm: opt-in STRATA_DENSE_F32=1 on Pascal - the large dense GEMMs as cublasSgemm on FP32 copies
For FP16 operands with FP32 sums cuBLAS 12.4 has two Maxwell kernels on a Tesla P40 and picks the slow one for most
chunk sizes: qkv (10240 x 2560) runs at 7.6 TFLOPS for T 7030-7040 and at 4.3 from T 7041 (49 -> 85 ms), so a
7K-token prompt reads in 16.3 or 19.5 s by its token count.  cublasSgemm on FP32 copies runs at 8.4-9.8 TFLOPS from
T 512.  For the five shapes and the sizes the route takes, the result is bitwise the FP16 call's: gemm_f32_parity,
5,201 chunk sizes through Gemm::f16.  That is a property of the cuBLAS build (12.4.5.8 measured), hence opt-in.
2026-10-13 04:12:24 +02:00
Techannel 9c5bbc36d0 dequant: a thread per 8 values for Q4_K / Q5_K / Q6_K / IQ4_XS, sm_61's default (bitwise; Q6_K 7.2 -> 0.33 ms on a Tesla P40)
dequant_kernel's thread reads its 32-value group a byte at a time and writes 32 two-byte values one by one, 64 bytes
from its neighbour's.  On a Tesla P40 that is 10 GB/s for Q6_K, and the IQ3_S pack's dense weights cost every prompt
chunk ~0.5 s of it, whatever the chunk's length (a fifth of a 560-token prompt).  The wide kernel takes 8 values a
thread: 16-bit loads, one 16-byte store, the same expression per value.

dequant_wide_parity: 360 cases bitwise (FP16 / BF16 / FP32 out, a padded stride, row slices, sane and raw random
blocks); --bench on the P40: Q6_K 10240 x 2560 7.25 -> 0.33 ms, Q4_K 5.2x, Q5_K 3.8x, IQ4_XS 3.6x.
On by default on compute capability 6.1 only (where it was measured); STRATA_DEQUANT_WIDE=0 / =1 for any card.
2026-10-13 04:12:24 +02:00
Niko1221 27f2d16725 strata-q36: the prompt's F32 projections on a tiled split-K SGEMM
The router, the GDN alpha / beta and the shared expert's gate (n_out 1-256,
K 2048) ran on hipBLAS/cuBLAS SGEMM with 8x8 / 16x16 tiles (~10% of a
prompt). k_sgemm_nt: (16 TM) x 64 tiles, TM x 4 outputs per thread, K split
so about 128 blocks run, the partials summed in a fixed order
(deterministic). gfx1201 pp4096: 3290 -> 3455 tok/s. STRATA_Q36_BLAS_F32=1
keeps the BLAS SGEMM.
2026-10-13 02:48:23 +02:00
Niko1221 b23869bf16 strata-q36: warm-up at load; hybrid slots independent of --mtp
Warm-up: a throw-away prompt chunk, a decode step and (with drafts) a
speculative step at load make the code objects, BLAS kernels and graphs, so
the first request runs at full speed (pp4096 rep 0: ~1770 -> 3273 tok/s; a
34-token first prompt: 1032 -> 48 ms). --no-warmup skips it.

Hybrid mode with MTP exact by default: the MTP block is loaded whenever the
file has one (so the VRAM layout and the slot count do not depend on --mtp;
the prompt pass through it only runs with drafts); decode and verify rows'
routing is counted only for the rows kept; the slots are rebalanced exactly
at every 32nd position and a verify window never steps over one.
2026-10-13 02:29:01 +02:00
Niko1221 54c0de70ca metal: the streaming arena's size rule - keep max(7 GB, 15% of the RAM), the n-gram table's memory out of it, re-checked just before the arena is committed; buffers past 8 GB when 4 of 8 GB are too few
arena_budget.h: the rule as plain arithmetic, tested by metal/tests/arena_budget_test.cpp (13 checks, run on the
M4). The M5 Max froze (2026-10-13 02:08) with an 89 GB arena planned from 'available - 7 GB' beside a 50 GB n-gram
table: macOS now keeps 15% of the RAM (20.6 GB there), the table's mapped bytes (--ple-io ram) or 2 GB (read row by
row) come out too, and just before the arena is committed the free memory is asked again - less than planned: the
arena is laid out again smaller instead of failing. STRATA_METAL_KEEP_FREE_GB / STRATA_METAL_ARENA_GB override.
stream.cpp: arena buffers grow past 8 GB when 4 of 8 GB cannot hold the arena (STRATA_METAL_ARENA_CHUNK_GB).

The coordinator suggested max(12 GB, 15%); on the 32 GB M4 (Q2_0 streamed, 200 tokens, memory_pressure every 3 s)
12 GB kept cut the arena 9.4 -> 4.4 GB and decode 7.8 -> 4.8 tok/s, while 7 GB kept left macOS 55% free the whole
run (12 GB: 70%); same tokens. Hence 7 GB below ~47 GB of RAM, 15% above. Not yet run on the M5 (down).
2026-10-13 02:17:12 +02:00
Niko1221 5cf2eb2788 metal: Q6_K gate/up passes the host's expert format gate (Unsloth UD-Q5/Q6_K_XL)
iq_host.cpp (Metal's copy of the host helpers): Q6_K among the grouped gate/up formats, as mac-kern's moe_gu_14 /
mm_gu3_14 run them. Before, the engine refused UD-Q5_K_XL ('layer 2's experts are Q6_K/Q8_0 ... no GPU kernels').
2026-10-13 02:17:11 +02:00
Niko1221 14817168b6 One strata binary for both families: the Qwen3.6 engine path as a library
strata reads the --native file's architecture at the top of main() and hands
a qwen35moe model to strata::qwen35::run (src/qwen35, now the strata_qwen35
library; strata-q36 wraps the same entry point) before any Flash-Next state
exists; every other file runs exactly as before. strata --families lists the
architectures a build runs. The Qwen3.6 path takes strata's flag names where
they mean the same (--native, --max-new, --pool-workers, --no-token-graph,
--gpu, --mtp N) and skips Flash-Next-only ones in serve mode. The SYCL build
keeps refusing the family, now saying CUDA and HIP run it.

setup: Qwen3.6-35B-A3B is a family in the menu (OWN_PATH_FAMILIES,
install_own_path): size, context, the engine (checked with --families), the
pinned GGUF, its tokenizer, a config with --native/--max-context/--mtp 2 and
the start script; no pack, profile, draft layer or tuning. The engine step is
a function shared with the Flash-Next path. strata_inspect says the family
runs on CUDA and HIP.
2026-10-13 02:06:01 +02:00
Niko1221 2a0d2f5521 SYCL dense GEMV and HC read: bit-identical variants measured, kept opt-in (none reaches +3% end to end)
- dense_bench: the decode window's native_mmvq calls at the model's shapes and formats, 24 matrices per shape in one
  graph (weights from DRAM), 1-4 columns, us / GB/s and an output hash.
- STRATA_MMVQ_WIDE_K_RPW=2|4: Q4_K / Q5_K / IQ4_XS wide kernel with 2 or 4 rows per sub-group sharing each column's
  activation loads (apply split into act + dot, the same operations); every hash equal. B70, 3 columns: Q4_K
  6144x2560 56.6 -> 27.7 us, Q5_K 2560x12288 89.8 -> 75.5 us, Q6_K unaffected.
- STRATA_MMVQ_WIDE_RPW>1 and STRATA_MMVQ_PF now take the aligned Q6_K loads (they were 2-4x slower than the default
  without them); still slower than the default except Q6_K 6144x2560 at RPW 2 (50.2 -> 45.3 us).
- fused GR read: the up step's columns per block (STRATA_GR_UP_COLS 4/8/16/32/64, default 16 = before) and its T
  butterflies interleaved (STRATA_GR_UP_ILP=1); gr_bench checksums equal for all. 32 columns: 3 tokens 50.7 -> 48.9 us,
  1 token 27.5 -> 29.4; ILP slower.
Engine, B70, IQ3_S with data/expert-profile-sycl.bin, 5 interleaved pairs: STRATA_MMVQ_WIDE_K_RPW=2 STRATA_GR_UP_COLS=32
vs default: decode after a 4K prompt 54.31 -> 54.00 tok/s, story 38.41 -> 38.50, outputs identical. Defaults unchanged.
2026-10-13 02:05:09 +02:00
Niko1221 e48c803e01 native packs: the sized cache's budget counts the 256-byte slots it is filled with - an NVFP4 blob (2,764,816 B with its scale tail) got one slot fewer than asked, none at --expert-cache 1
Found by the quant yardstick (--expert-cache 1) on the NVFP4 GPTQ pack: 'pre-filled 0 of 0 slots', and the verify windows
refused to run.  Every other native format's blob is rows x row bytes with 1280 / 2560 rows, a multiple of 256, so its
budget is unchanged.
2026-10-13 01:49:34 +02:00
Niko1221 1d21b9cd6c MTP drafter on HIP: the draft stream at high priority by default on gfx1200/gfx1201 (STRATA_MTP_HIP_PRIO=0 off, =1 on other HIP cards)
ROCm gives out its hardware queues per priority level; the draft stream shared one with the verifier's, so the
draft round ran only after the commit graph the verifier had just launched. With a queue of its own the commit
runs beside the draft. R9700, UD-Q4_K_XL: draft wall 5.8 -> 3.5 ms a window (STRATA_DRAFT_TIMING).
2026-10-13 01:42:48 +02:00
Niko1221 015039e865 README translations: Unsloth's UD-Q4_K_XL to Q8_0 as in the English README 2026-10-13 01:41:10 +02:00
Niko1221 6f14e90a58 docs/QUANTS.md: every expert in RAM vs the old budget (5-pair A/B), the route tail skip's cost on the K-quant files 2026-10-13 01:38:28 +02:00
Niko1221 6f3e38100e Commit graph: every GDN layer's conv history + state, and every QSA layer's tail restore + indexer append, in one launch each (STRATA_COMMIT_BATCH, default on; =0 keeps the per-layer loop)
The per-layer commit was ~98 graph nodes; it runs between a window and the draft round, and on HIP the round
waits for it (R9700 UD-Q4_K_XL: 2.35 -> 0.65 ms GPU). Each layer's arithmetic is the per-layer call's:
gdn_parity (gdn_commit_layers vs the per-layer commit, n_keep 1-8) and qsa_parity (append_steps_layers vs
copy + append_steps, 3 scalings) are bitwise. STRATA_COMMIT_TIMING=1 prints the commit graph's GPU time.
2026-10-13 01:24:55 +02:00
Niko1221 655145426d MTP drafter: STRATA_MTP_PROFILE (stage stamps in the draft graphs), host split in STRATA_DRAFT_TIMING, draft graph node listing; STRATA_MTP_HIP_PRIO=1 opt-in (the HIP draft stream at high priority, its own hardware queue)
All measurement switches are off unless set; the default path is unchanged.
2026-10-13 01:24:54 +02:00
Niko1221 de9ea19bae setup: NVFP4 below its RAM need takes the RAM-budget mode (--resident-budget-gib, RAM less 24 GB), not the mapped experts
On the RTX 5070 PC (64 GB, Windows) --mmap-experts let the experts it read stay in the engine's working set: free RAM
fell to 0.6-4.9 GB and the memory guard stopped the engine three times (2026-10-13).  --resident-budget-gib 22 with the
same pack kept >= 22.8 GB free.  The budget mode is what setup already writes for Unsloth's files (resident_budget_gib:
40 GiB on 64 GB); the pack's experts.bin is the file the rest are read from.  test_setup_nvfp4: 64 GB -> budget 40.
2026-10-13 01:14:13 +02:00
Niko1221 c711ba071f Images (I2): setup builds the native DiT runner into sd-cli on CUDA / HIP; --image-native on|off (off by default) and the config's "native" add --model-args qwen_image_2_1_native=1 2026-10-13 01:07:28 +02:00
Niko1221 221834c6fc quant_quality: --gpu-experts N (e.g. auto) for a measurement at a real expert-cache size 2026-10-13 00:57:20 +02:00
Niko1221 31f26683c2 metal: the quant yardstick on Metal - window_logprobs from the window's head logits; head logits in every window under STRATA_LOGPOS
Verifier::window_logprobs reads the head rows through window_copy_logits under STRATA_GPU_METAL (the CUDA/HIP path
unchanged: verify.cpp's object is byte-IDENTICAL on P1004 and p620). The prompt's windows sample nothing (head
sampling off), so with STRATA_LOGPOS the Metal window computes the head anyway.

tools/quant_quality.py on the M5 Max against the Q8_0 reference (q8_0.tsv 627558d1, set.ids.json 414634dd), 4,995
positions: UD-Q4_K_XL 92.77% top-1, KL 0.0548 (p99 0.855), PPL 4.043 vs 4.052 (CUDA/HIP: 93.09% / 0.056); IQ3_S
87.85% / 0.1422 (CUDA/HIP: 87.7% / 0.144). The Metal window keeps int8 K/V (the yardstick asks fp16).
2026-10-13 00:54:44 +02:00
Niko1221 5be585a2cf Images (I2): native Qwen-Image-2.1 DiT runner inside stable-diffusion.cpp, opt-in
tools/image/sdcpp_native: a runner that replaces QwenImage21Runner::compute only (sd.cpp keeps the text
encoder, VAE, sampler and RNG), chosen with --model-args qwen_image_2_1_native=1 in CUDA / HIP builds.
- The text prefix runs once per condition (causal, the t = 0 modulation row) and leaves each layer's
  fp16 K/V; each step runs the 32 blocks on the image tokens only.
- GEMMs stay ggml graphs on the runner's backend (sd.cpp's MMQ / BLAS kernels and numerics); fused
  LayerNorm+modulate, gate+residual(+next LayerNorm), q/k RMSNorm+RoPE+fp16 K/V, SwiGLU and, on gfx11, a
  WMMA flash attention (8 waves x 16 queries, 64-key tiles, fp32 softmax) run on the backend's stream.
- apply.py copies the two files into the pinned checkout and makes two small edits (runner choice,
  SD_QI_NATIVE for CUDA / HIP builds); anything not covered falls back to the stock runner.

780M, Q8_0, seed 42: 512 2.11 s/step (stock 2.85), 1024 9.58 s/step (stock 14.2), image 96.5 s (131.8).
2026-10-13 00:52:46 +02:00
zsariboga caf1856bd9 pool: STRATA_POOL_UMWAIT=<cycles> - parked workers wait with UMONITOR/UMWAIT instead of spinning (opt-in, x86 WAITPKG, MSVC x64)
A parked pool worker watches the epoch's cache line with UMONITOR and sleeps in UMWAIT (C0.1) until the host publishes or the cycles run out. On a laptop whose CPU and GPU share one power budget the spin's power goes back to the GPU. Unset, 0, no WAITPKG or a non-MSVC build: the spin, unchanged. STRATA_POOL_UMWAIT_C02=1 picks the deeper C0.2 state, STRATA_POOL_UMWAIT_ESC=<cycles> C0.1 first and C0.2 after.
2026-10-13 00:50:45 +02:00
Shawn Jackson 8825d337c1 generate: the prompt-chunk sizing and the state fingerprint take their QSA shapes from qsa_shapes(g)
Two places upstream builds QsaShapes by hand from the geometry (chunk_bytes, added since the geometry change was
written, and the conversation-state fingerprint, in both trees). They now call qsa_shapes(g) like layer, mtp,
session, verify and prefill; for every file the guard accepts the values are the ones they built before.
2026-10-13 00:49:58 +02:00
Shawn Jackson 51329cff3c artifact: read_geometry refuses another architecture by name before reading any qwen4exp key
generate.cpp reads the geometry before anything else looks at the model, so a model of another architecture was
refused as "missing qwen4exp.block_count" where 0.1.40.2 said "architecture is 'qwen35', this engine requires
'qwen4exp'" (found running Qwen3.8-27B through --native). read_geometry now checks general.architecture first, and
check_architecture is read_geometry plus geometry_unsupported. gguf_geometry_test: a dense qwen35 file (Qwen3.8-27B's
keys) and a file without general.architecture.

Tested on gfx1151 (HIP build of this branch, Windows): the GGUF tests pass; Qwen3.8-27B UD-Q6_K_XL, Q8_0 and
HauhauCS Q4_K_P are refused by architecture in 0.5 s; Qwen3.8-Flash-Next UD-IQ4_XS, greedy, 256 tokens on three
prompts (39, 48 and 5,568 tokens), gives output identical to the installed 0.1.40.2.
2026-10-13 00:49:57 +02:00
Shawn Jackson fc72322bd1 tests: the GGUF fixture's metadata helpers set fields by name
The f32 and array members added for gguf_geometry_test left the braced Kv{...} initialisers short of the struct, which
clang's -Wextra reports as -Wmissing-field-initializers in every test that includes the fixture (MSVC /W4 does not).
make_kv() sets the key and type, and each helper sets its own value. Built with the HIP toolchain (gfx1151):
gguf_geometry_test, gguf_split_test, gguf_reader_test and native_dense_ple_key_test pass, with no warning from the
fixture.
2026-10-13 00:49:57 +02:00
Shawn Jackson f812e9a162 core: the model's geometry is read from its GGUF metadata and checked against the shape the kernels are compiled for
read_geometry (gguf_reader.hpp) fills ModelGeometry from the qwen4exp.* keys, under llama.cpp's names: layers, widths,
GDN, attention, indexer (heads, key width, pooling block from compress_ratios, top-k), rope width, hyper-connections,
experts, RMS epsilon, and the vocabulary from tokenizer.ggml.tokens. The six keys the guard always required stay
required; any other absent key keeps the compiled value. Keys that state one thing twice must agree (the interval and
compress_ratios, key and value head widths, routed and shared expert widths, ssm.inner_size and state x v heads).

check_architecture no longer hard-codes 48 / 2560 / 24 / 2: it reads the geometry and refuses a file the kernels are not
compiled for, naming the key ("qwen4exp.block_count = 40, the kernels are compiled for 48"). Only the expert count,
the experts per token (1..64) and the vocabulary may differ. ModelGeometry moves to core/geometry.hpp (no
dependencies), with kCompiledGeometry; the kernels that fix a dimension at compile time static_assert it there, in the
CUDA/HIP tree and the SYCL copies (plus qsa_prompt_attn_xmx).

generate.cpp takes the geometry and K from read_geometry, and the native embedding takes n_embd / n_vocab from it
instead of a literal 248320. The QSA kernel shapes come from one qsa_shapes(g) (layout.hpp) in layer, mtp, session,
verify and prefill, so n_rot, idx_block and idx_top_k follow the geometry too. Mirrored in sycl/.

Tested: tests/core/gguf_geometry_test.cpp (new, synthetic GGUFs) 28/28, gguf_split_test and gguf_reader_test pass,
built with MSVC /W4 /WX on Windows. `gguf_geometry_test --real` on Unsloth's Qwen3.8-Flash-Next UD-IQ4_XS shard 1
reads exactly the compiled shape and the guard accepts it. Not built here: the engine (no CUDA, HIP or oneAPI compiler
on this PC), so generate/layer/mtp/session/verify/prefill and the kernel asserts are reviewed, not compiled.
2026-10-13 00:49:57 +02:00
Niko1221 20b501743d setup: Ubuntu keeps its checked cuda-toolkit-13-0 install; Debian stops with a message when no 13.x installs (#2172 follow-up)
The Debian fallback loop ran with check=False on Ubuntu too, so a failed 13.0 install (a
network or apt lock error) went on to 13-1..13-4 and then past the loop without a word. Ubuntu
is back to the single checked install of 0.1.43; Debian tries 13-0..13-9 and fails with
guidance when none installs. Checked against NVIDIA's repos today: debian12 and ubuntu2404
carry 13-0..13-3, debian13 starts at 13-1 (up to 13-4). Two tests added.
2026-10-13 00:49:11 +02:00
Gabriel Popa fb7ee72471 setup: install the CUDA Toolkit on Debian 12/13 too, not Ubuntu only
The CUDA apt repo keyring and cuda-toolkit-13-x packages exist for
debian12/debian13 as well as ubuntu2204/ubuntu2404, so derive the repo
name from /etc/os-release instead of hardcoding ubuntu. Debian 13's
repo carries no cuda-toolkit-13-0, so try 13-0..13-5 in order (Ubuntu
still gets 13-0 first, same as before).

Checked with tools/test_setup_cuda_repo.py (4 tests, no GPU or network
needed): repo mapping for ubuntu/debian/other and the minor-version
fallback.
2026-10-13 00:48:38 +02:00
zsariboga d8a49433e3 serve: "env_to_user" (opt-in) moves opencode's <env> block into the first user message, so a new folder or day reuses the cached system prompt (11.9 -> 1.1 s first request)
opencode puts its <env> block (working directory, today's date) near the start of the system message, before ~40K characters that never change. The prefix cache only matches a prompt's start, so each new folder or day read the whole system turn again. With the switch the block goes to the front of the first user message (string or content parts), for OpenAI and Anthropic requests. Off by default; serve/test_env_to_user.py; docs/DETAILS.md.
2026-10-13 00:48:16 +02:00
SuperDistance ac21812c1a serve: a long read gives way to a short request at the next chunk, not a chunk later or never (#656)
The server sends BYIELD for a waiting request under half as long only when a PP line (or the 10 s heartbeat) arrives,
and the engine looks for it at its next boundary. Where a boundary's own PP line is the only line for a while - every
chunk of a --batch read on one GPU, and #2050's pipelined pieces - the BYIELD answers that line and reaches the engine
after it has looked: the read gives way one boundary later, or never when that was the last one it could take. It is in
time only where the engine saves a periodic checkpoint after the PP line (every 16,384 tokens by default).

_control() now also calls on_quiet() whenever the engine has been quiet for half a second (its existing poll), and the
solo and admission reads run the same check there as at a PP line. A BYIELD for a read that has ended is ignored by
the engine, as before. serve/test_parallel.py: the fake engine takes --pp-every K (a PP line and a boundary every K
chunks); a solo read and an admission must give way at their first boundary (both fail on main), and the rule (only
to a much shorter request) holds on the poll too.

Measured on one RTX 5090 (Swift 1.5 IQ3_S, --batch 4, the engine built from main), main's server and this one, two
engine starts each (M F F M): a one-line request sent 0.2-8.6 s into a cold ~33K read, with nothing else decoding and
with one stream decoding. Late (a boundary passed after the request waited): 28 of 40 runs on main, 12 of which never
gave way; 4 of 40 with this change, all requests that started waiting 0.02-0.10 s before that boundary's PP line.
Where main was late the short request's TTFT went 3.56 -> 1.70 s (nothing decoding) and 4.40 -> 1.57 s (one stream);
where main never gave way 4.60 -> 1.51 s and 7.59 -> 2.35 s. Where both gave way at the same boundary, both requests'
TTFTs were the same (medians within 0.02 s). On 2x RTX 5090 with #2050's STRATA_PIPED_READ_PIECE=8192: 6 of 12 late without
it, none with it.
2026-10-13 00:46:48 +02:00
Niko1221 9c5a45f879 SYCL layer split auto: among near-tied placements, the one that leaves its tightest card the most room (#1440)
On two equal cards every K whose caches hold all the profiled pairs predicts the same window
time, and the search kept the first one tried: the smallest K, which gives the last stage (it
also carries the MTP drafter) the most layers and lets its cache fill the card to the reserve.
2x Arc Pro B70 with IQ3_S: auto K=24, CUDA1 at 31.8 of 31.9 GiB, ~11 tok/s; --layer-split 30
~54 tok/s (agnaylor in #1440). A full xe card does not fail an allocation, it moves buffers to
system memory.

The SYCL search now scores every placement it tries with its smallest spare room (a stage's
room after its session minus every expert of its layers) and, among the placements within
STRATA_SPLIT_HEADROOM_TOL (default 0.2%) of the best predicted time, takes the one with the
most (split_rules::pick_with_headroom). A log line names both picks when it moves the split.
STRATA_SPLIT_HEADROOM=0 keeps the old pick. CUDA/HIP placement is unchanged.

Test: split_rules_test (a 48-layer two-card model of the report: plain K=24 with 664 MiB spare
on the last card, headroom K=25 with 1728 MiB; tolerance and tie rules).
2026-10-13 00:44:27 +02:00
Niko1221 62185aab77 serve: a quoted <tool_call>, <tool_response> or </tool_response> is text too (#2026 follow-up)
The three are USER_DEFINED (type 4) tokens like </tool_call> (ids 248058, 248066, 248070), so
the tokenizer matched them inside a message's text as the real call / tool-result markers.
They join TOOL_LITERAL_TAGS: inside a user, system or tool message (and the tool list) they are
encoded as ordinary text; an assistant message replaying raw call text keeps its tokens, as
for </tool_call>.

One exception keeps the template's behaviour: a user message whose whole text is
<tool_response>...</tool_response> (a client that formats tool results itself) keeps that outer
pair as the markers, since the template tells such a turn from a real question by exactly that
pair (last_query_index); the text inside is still marked.

Found by 47Hunter47 in #2026. Tests: serve/test_frontend.py QuotedToolCallCloser (every tag
and role, the assistant replay, the outer pair as string or text parts).
2026-10-13 00:40:31 +02:00
Niko1221 dbf4015069 setup on macOS: the Unsloth sizes offered (UD-Q4_K_XL measured resident on 128 GB; Q5/Q6 stream), the family's pack args (--compat-bf16 for the host's copies)
M5 Max: ./setup.sh --model UD-Q4_K_XL --vision yes: shards checked by SHA-256, repacked and verified, the pack, the
image encoder; the config it writes answers the test picture ('STRATA 42', 'Red circle / Blue square / Green
triangle').
2026-10-13 00:37:29 +02:00
Niko1221 54eb42a3f3 strata-q36: hybrid experts - VRAM slots, the CPU pool, streamed prompt layers
The routed experts are placed after the engine's buffers: all in VRAM when
they fit (unchanged), else every expert in host memory with the same number
of VRAM slots per layer (--expert-vram GiB, --expert-slots N). Batches of up
to --hybrid-rows rows run the resident experts on native_expert_grouped and
the others on the CPU ExpertPool (ggml-cpu arithmetic) side by side; bigger
prompt chunks stream each layer's experts into two staging buffers for MMQ
(prompt chunk 2048 in this mode). Slots follow the routing counts (after a
prompt, every 32 decode positions). ExpertPool's native phases split rows by
the layer's n_ff / n_embd instead of Flash-Next's constants (same values
there). STRATA_MMQ_KQ=1 by default for this family.
2026-10-13 00:36:25 +02:00
Niko1221 2fd1a5b091 metal: Unsloth UD-Q4_K_XL runs - the F32 PLE conv kernel narrowed to F16 at load (as the host loader), no zero-size HC copy buffer
ple_conv_add reads the conv kernel as half: Unsloth's file stores it F32, so it is narrowed (round to nearest even)
into its own buffer; the GSQ packs' F16 tensor is read in place as before. A file whose HC matrices are Q8_0
already makes no copies (the copy buffer was allocated with 0 bytes and the Metal allocation failed).

M5 Max, UD-Q4_K_XL resident (the repacked 82.5 GB file): greedy prompt1 identical to the CUDA reference (z440),
story first differs at token 36; MTP output equal to no MTP; decode no MTP 60.6 / 60.0, MTP --spec 2 93.9 / 74.0
tok/s; prompts 4K 1,374 / 32K 1,288 tok/s, needles found (4K, 32K). llama.cpp Metal on the same shards: 48.4 /
47.3 decode, 821 / 739 prompt.
2026-10-13 00:33:54 +02:00
Niko1221andradoslawsz 277be72a7f Foresight swap: an exchange holds the experts whose bytes it moves, so no slot is served with another expert's bytes (#2134)
With STRATA_FS_SLOTS > 0 and the resident RAM mode's adaptive exchanges, a slot copy issued
from an expert's RAM place (note_miss / the router look-ahead's predict) could land after an
exchange rewrote that place with the outgoing expert's bytes; take() then served expert Y's
bytes for expert X (FS_VERIFY: 19 BAD on clean v0.1.43, reported in #2134).

commit_exchanges, commit_copies and commit_flip now hold every staged expert (in and out) in
the swap space while their bytes move: its slot is dropped (never served again) and no copy
of it is issued until the commit is done (commit_copies holds until commit_flip, so the
asynchronous tier's half-done exchange is covered, and the rotation path too). Unlike the
patch in the issue, a dropped slot is not handed out at once: it waits the same `depth`
finished windows as any slot a window may still read, since a window planned before the
exchange can be reading it. "N dropped by exchanges" joins the swap space's report.

Foresight is opt-in; with STRATA_FS_SLOTS unset nothing here runs. Test:
file_expert_source_test --rotation-gpu (both commit paths, the depth rule, the bytes after).
Based on the analysis and patch in #2134.

Co-authored-by: radoslawsz <[email protected]>
2026-10-13 00:31:31 +02:00
Niko1221 ad8f53fa7a HIP gfx12: the bitwise grouped K-quant decode experts (STRATA_EXPERT_V2K) on by default (R9700 UD-Q4_K_XL +0.2..1.2%, the same text) 2026-10-13 00:30:33 +02:00
Niko1221 dd5f09a50e docs: QUANTS.md speed, bound, CPU pool, dense GEMV, HC and images; MODELS.md one table for Unsloth's five files (old anchors kept); UNSLOTH_Q4/Q6 status; README 2026-10-13 00:30:02 +02:00
Niko1221 6339e8610d serve: the stdin reader shares its state with main instead of borrowing main's locals (QUIT race)
The stdin reader thread is detached and captured main's stop flag, mutex, condition variable,
line queue and EOF flag by reference. The server writes QUIT and closes stdin right after it,
so the reader often wakes with EOF while main is returning: it then locked a destroyed mutex
and wrote to a destroyed deque (undefined behaviour on every platform; the Metal port aborted
on it). The state now lives in a shared_ptr that the thread holds a copy of, so it outlives
main's frame for as long as the reader runs. CUDA/HIP and SYCL engines alike; no change to
what the engine reads or answers.
2026-10-13 00:28:26 +02:00
Niko1221 f5082f41a6 Sources: no raw NUL bytes (expert_source.cpp, pinned.cu) + a test that scans for them
expert_source.cpp's Linux-only STRATA_TEST_UNMAP_GGUF check had a literal 0x00 byte as its
character constant (since 0.1.43; gcc warned "null character(s) preserved in literal"), and the
#2126 buddyinfo parser in pinned.cu got one the same way (a heredoc dropped the backslash).
Both are the escaped character now. Git took pinned.cu for a binary file because of the byte,
so it was committed with CRLF line endings; it is back to LF (no other change).

tools/test_source_nul_bytes.py fails when any tracked source file holds a NUL byte again.
2026-10-13 00:26:51 +02:00
Niko1221 12be1059df setup: images on by default for Unsloth's files where the encoder has room (NVIDIA 16 GB and more: the GPU encoder; AMD Linux with every expert in RAM: the CPU encoder); UD-Q4_K_XL's images no longer untested (run end to end on an RTX A4000 and an R9700); the yardstick keeps a config's --resident-budget-gib 2026-10-13 00:08:31 +02:00
Niko1221 3e11f786af Merge f-quants (945fee23) into f-qwen36: the K-quant CPU pool rows, libstrata_kq, the K-quant GEMV work 2026-10-12 23:48:28 +02:00
Niko1221 f29e74c721 strata-q36: FP16 prompt attention and a column-split GDN chunk kernel
Prompt chunks run the attention scores and P V as FP16 strided-batched GEMMs
with FP32 accumulation (K / V cells and Q converted per chunk, the causal
softmax writing FP16 probabilities), replacing the FP32 SGEMMs. The prompt's
delta rule splits each V head over 4 column groups (16 row groups of 8 rows,
the norm in its own kernel); decode, verify windows and commits keep one
kernel. pp4096 on gfx1201: 2557 -> 3290 tok/s.
2026-10-12 23:48:13 +02:00
Niko1221 3a639f7357 Merge branch 'f-quants' into f-intel-quants 2026-10-12 23:43:12 +02:00
Niko1221 ae02e7db17 metal: vision - image rows in the prompt, M-RoPE (qsa_prep constant 24), setup's --vision
The prefill hook hands the prompt's image rows (sp.embd_rows) to the Metal prompt paths (prompt_chain.inc, the
streaming prompt path, the 8-row windows), which take an image row in place of the token embedding.
mrope_table_set keeps the host view of the server's (t, h, w) table; every window, prompt chunk and draft round copies
the rows it reads into the window's buffer, bound at index 20 of qsa_prep with function constant 24 (mac-kern
29724e5e) - the window, both prompt paths and the draft layer. The cached window's QsaArgs are patched by the last
inline argument (the table is bound after it). setup_mac.py --vision yes: the pinned projector (SHA-256) and
strata-vision built with ggml-metal; the config gets --vision and the encoder.
missing.cpp: a crash prints its call stack and fault address.

M5 Max, Q2_0, ISTA's projector, a test picture (shapes and 'STRATA 42'): 'STRATA 42' and 'Red circle / Blue square /
Green triangle', the same answers as the HIP engine on the R9700 (p620) with the same picture and files, also
through the config setup writes. Text greedy unchanged with and without --vision (prompt1, story, the 1,662-token
chain prompt). prefill.cpp: the CUDA (P1004) and HIP (p620) objects are byte-IDENTICAL (preprocessor-only).
2026-10-12 23:36:13 +02:00
Niko1221 38436f2a44 strata-q36: decode always on the per-token GDN kernels
The greedy divergence seen with the fused single-token kernels is not a
kernel bug: fused_gdn_conv_l2 and k_conv_seq leave the same history and
differ by 1 ulp in h (FMA contraction of the 4-tap sum); the Q8_1
activation rounding turns that into a flipped near-tie (p01 token 4,
margin 0.43). KL with either is the same. Drop the switch.
2026-10-12 23:30:40 +02:00
Niko1221 58515d2b9c SYCL prompt path: the 32-value block dequantizers (Q5_1, Q8_0, Q4_0, Q4_1, Q5_0) write neighbouring values from neighbouring lanes, as vector stores
Lane tid wrote block tid % 8 of its superblock, so a sub-group's 2-byte stores landed 64 bytes apart. Lane tid now
takes block tid / 4 (the same 32 (block, part) pairs, the same values) and writes its runs with store_run. UD-Q4_K_XL's
down projections are Q5_1 and UD-Q5/Q6/Q8_0's are Q8_0, so this is most of their FP16 prompt-path dequant.

B70, dequant_bench (32 experts, gate/up + down): Q5_1 7.18 -> 2.83 ms, Q8_0 6.77 -> 3.53 ms; Q4_0 3.21, Q4_1 2.76,
Q5_0 3.74 ms after; the FP16 output hash of every type unchanged. dequant_bench lists Q4_0 / Q4_1 / Q5_0 too.
2026-10-12 23:29:06 +02:00
Niko1221 13ed803334 metal: the M4's expert tiles for the Unsloth formats (mac-kern 513fc615): decode down Q5_1 4,1,4 and Q8_0 8,1,4 without the M5 layout; v2 prompt K-quant gate/up 16_16_128_2 2026-10-12 23:19:58 +02:00
Niko1221 e65858f84f SYCL: Unsloth's expert formats decode each weight word once per grouped call (KqSplit), bitwise
The lane kernels of native_expert_grouped re-read and re-decoded a Q4_K / Q5_K / Q6_K / Q5_1 / Q8_0 expert row once
per entry of its group (the IQ formats already decode once, Multi). Each of these dots is now split into load (the
weight words and scales) and apply (the activations and the same float expression), and the group's entries go
through the existing multi-entry path in chunks of 4 and 2; every entry keeps its own k order and lane sum, so the
outputs are bitwise the per-entry kernels'. STRATA_KQ_SPLIT=0 keeps the old kernels.

B70 (bmg-g31), 2560 x 640 experts, GB/s of expert bytes, 2- / 4-token windows: Q4_K/Q5_1 362 -> 402 / 369 -> 425,
Q5_K/Q8_0 395 -> 440 / 404 -> 464, Q6_K/Q8_0 259 -> 307 / 256 -> 318, Q8_0 430 -> 479 / 429 -> 502; one token -1..2%.
Experts read from pinned host memory (the NO_HOST mirror) go from 18-19 to 23 GB/s on those windows.

Also: STRATA_KQ_GU_LANES (opt-in; the K-quant / Q8_0 gate/up lane split alone, other bits), native_grouped_parity
--kq (split vs per-entry bitwise, and a CPU float reference with ggml's dequantize_row_* for Q4_K/Q5_K/Q6_K/Q5_1/Q8_0)
and --kqbench (per format pair, device or pinned host memory), Q6_K blobs with a finite scale in that harness,
dequant_bench and kq_cpu_bench for the Unsloth formats in the SYCL build.
2026-10-12 23:19:46 +02:00
Niko1221 b55684708e strata-q36: MTP speculative decode from the GGUF nextn block
--mtp D (0..7) loads blk.<n_layers> (eh_proj, enorm/hnorm, attention + MoE
layer, shared_head_norm) and runs greedy requests as speculative steps:
D chained drafts, one verify window, commit of the accepted rows' GDN state
and conv history. Verify windows and plain decode share the per-token GDN
kernels, so the text is the plain greedy text (10 of 10 prompts identical).
Serve reports accepted/offered drafts in DONE.
2026-10-12 23:19:34 +02:00
Niko1221 e3cd071c21 Merge f-mac-kern 513fc615 (M-RoPE in qsa_prep, faster Unsloth prompt experts, M4 tile notes) 2026-10-12 23:19:10 +02:00
Niko1221 513fc615bb metal: W8<Q6_K> with ushort-pair code loads and vector field math (prompt Q6_K gate/up 14.0 -> 11.0 ms a layer at T 2048; same values) 2026-10-12 23:11:57 +02:00
Niko1221 009dc6c1dc STRATA_DRAFT_TIMING=1: where a draft round's time goes (cudaEvent pairs around the round graph and every step, host wall) 2026-10-12 23:11:00 +02:00
Niko1221 29724e5ea9 metal: K-quant / Q5_1 paired-run prompt decoders (W8) and paired mm_down3; qsa_prep M-RoPE (function constant 24)
- moe_mm.metal: W8<Q4_K / Q5_K / Q5_1 / Q6_K> (the lane's runs k and k + 16 share the sub-block's scale, min and
  high bits; 4-aligned code runs read as one uint); mm_down3 takes the paired-run decode on the COOP_K4 layout (TK
  32).  Prompt per layer at T 2048: Q4_K gate/up 10.6 -> 6.0 ms, Q5_K 15.4 -> 9.0, Q6_K 17.2 -> 14.0, Q5_1 down
  5.0 -> 3.3; the same values (moe_mm_parity v3 incl. Q2_0 and IQ3_XXS / IQ4_NL)
- qsa.metal: QSA_MROPE (function constant 24) - interleaved M-RoPE (ggml IMROPE, sections 11/11/10): buffer 20 of
  qsa_prep = int32 [cells][3] (t, h, w); rotary pair i of the row at pos_base + cell rotates by the cos/sin row
  tab[(pos_base + cell) * 3 + i % 3] (pooled indexer keys at pos_base + 4 b too).  qsa_parity QSA_MROPE=1 (random
  table vs the CPU reference) / QSA_MROPE=id (identity table: the same numbers as the plain kernel)
2026-10-12 23:10:47 +02:00
Niko1221 b1b133e55f metal: Unsloth formats in the window - the file's Q8_0 HC read in place (F32 inject: gr_down_q8f), F32 router/alpha/beta/shexp gate through gemv_0, the v2/v3 expert tile names per format; strata-vision builds on macOS
The HC read takes, per matrix, its load-time Q8_0 copy or the file's own tensor: Unsloth's Q8_0 down/up need no copy,
their F32 inject rows go to gr_down_q8f (mac-kern 945c0d24). router_route_<type> for BF16 and F32 (opt-in). The M4's
v2 prompt kernels: K-quant gate/up TK 128, Q8_0 / IQ4_XS TK 32, Q5_1 / Q8_0 / IQ4_NL down TK 32. GSQ packs unchanged:
Q2_0 prompt1/story, IQ3_XXS prompt1 and the 1,662-token chain prompt give the same tokens as before (M5 Max).
tools/vision/strata_vision.cpp: no posix_fadvise on macOS (it does not have it); strata-vision then builds there with
ggml-metal.
2026-10-12 23:08:35 +02:00
Niko1221 945fee2365 Dense Q8_0 GEMV: one row per block where measured faster (gfx1201: n_in <= 4096 with n_out >= 4096; sm_86: n_out >= 2048), the same bits as two rows 2026-10-12 23:08:31 +02:00
Niko1221 209de26e53 Merge f-mac-kern 945c0d24 (Unsloth formats: Q4_K/Q5_K/Q6_K/Q8_0 experts, Q5_1 down, F32 GEMV, HC down with F32 inject) 2026-10-12 23:02:32 +02:00
Niko1221 5ef9f4c812 q8_gemv_bench: the dense Q8_0 GEMVs at the engine's shapes, 1-6 columns, against the memory bandwidth 2026-10-12 22:59:31 +02:00
Niko1221andsergiywith 23250b5da6 setup: Unsloth's files keep every expert in RAM where they fit with 16 GiB more (the RAM budget below that); UD-Q5_K_XL, UD-Q6_K_XL and Q8_0 in the unsloth family; UD-Q4_K_XL no longer experimental or NVIDIA-only
- unsloth_budget / UNSLOTH_RESIDENT_BESIDE_GB 16, ported from sergqwer's fork (sergqwer/strata-nvfp4 3f3546f6, MIT):
  no --resident-budget-gib where the experts and 16 GiB fit the RAM (UD-IQ4_XS 71.4, UD-Q4_K_XL 87.7, UD-Q5_K_XL 107.6,
  UD-Q6_K_XL 117.7, Q8_0 135.5 GiB), the budget below that, when asked for, and on a unified-memory APU (#1715).
  The menu, --check and the install say which; the menu's default for the family is the largest file whose experts
  all fit (UD-IQ4_XS where none does).
- UD-Q5_K_XL / UD-Q6_K_XL / Q8_0: six shards each, sizes and SHA-256 pinned at 38bb39ee; "ram_gb" is the all-in-RAM
  need, below it setup asks first (default no) and says how many GiB are read from the SSD. Q5/Q6 need engine 0.1.44
  (the Q6_K expert kernels in every build); Q8_0 0.1.38.
- UD-Q4_K_XL: ran on an R9700 (docs/QUANTS.md), so #429's AMD question is gone, and it is not experimental.
- tools/strata_mcp.py mirrors the table and the verdicts. Golden configs re-recorded: only UD-Q4_K_XL on 96 GB
  (65536, --kv-resident) and 128 GB (131072) changed, as in the fork.

Tests: test_setup_unsloth Resident and BigFiles (the budget tests force the budget mode where their PC now fits every
expert), test_strata_mcp, every tools/test_setup_*.py.

Co-authored-by: sergiywith <[email protected]>
2026-10-12 22:57:14 +02:00
Niko1221 945c0d2424 metal: the Unsloth UD-Q4/5/6_K_XL formats - K-quant / Q8_0 / Q5_1 routed experts, F32 GEMV + router, Q8_0 HC read with F32 inject
- Q5_1 (type 7): ref_quant (dequant, random blocks), quant.metal fmt/deq, units.metal Dec (w = d q + m, the min
  through the unit's own x sums) / X, mma.metal DW
- decode experts (moe.metal): moe_gu_{12,13,14,8}_* (Q4_K, Q5_K, Q6_K, Q8_0), moe_down_{7,8}_* (Q5_1, Q8_0)
- prompt experts (moe_mm.metal): W4 decoders Q4_K / Q5_K / Q6_K / Q8_0 / Q5_1; mm_gu3_{12,13,14,8}_*,
  mm_down3_{7,8}_*; mm_gu2 K-quant tiles with TK 128 (16_32_128_2/4, 16_16_128_2, 32_32_128_2), Q8_0 TK >= 32;
  mm_down2_{7,8}_* (TK >= 32)
- F32 (type 0) as a format: gemv_0_*, gemvc_0_*, dq_f16_0, router_route_0
- gr.metal: gr_down_f<SG, KS, F, FI> with the inject rows in their own format: gr_down_q8f_<S>_<K> = Q8_0 down + F32
  inject (gr_down_<S>_<K>, gr_down_q8_<S>_<K> unchanged)
- parity: expert_parity, moe_mm_parity v2/v3 (every gate/up x down pair), gemv_parity / dense_mm_parity F32,
  fuse_parity router_route F32 (bitwise), gr_parity GR_Q8=1 GR_INJ_F32=1
2026-10-12 22:56:44 +02:00
Niko1221 1176eb3c5b strata-q36: the engine path for Qwen3.6-35B-A3B (serve protocol, prompt chunks, decode graph)
A driver of its own beside Flash-Next's (generate/verify/prefill untouched), built from Strata's kernels:
- weights from the GGUF: dense Q8_0 on the native MMVQ (with the packed Q8_0 copy), the routed experts
  repacked at load into native expert blobs (stride in whole blocks for MMQ), F32 norms / projections;
- the plain pre-norm residual layer driver, the residual add fused with the next norm, the MoE end
  (combine + shared-expert gate + add + next norm) in one kernel;
- GDN: the fused conv+L2 and SiLU step for a token, one-launch sequential kernels for a prompt chunk;
- attention without an indexer: split-K decode over 256-cell chunks (positions on the device, so the
  decode step is one captured graph), and for a prompt chunk scores / values as FP32 GEMMs per KV head
  with a causal softmax;
- prompt projections as FP16 GEMMs (prefill::Gemm::native), the F32 router / alpha / beta as SGEMM,
  the prompt's experts on llama.cpp's MMQ (entries sorted by expert on the device);
- decode: native router 256/8, native grouped experts (Q5_K / Q6_K downs added to the grouped
  kernels' down list for FF 512), router + shared gate in one product, alpha/beta in one launch.
- serve: READY / GEN (sampling keys) / T / PP / DONE / STOP, the held state reused when a request
  extends it; --tokens / --force / --dump-full-logits for tools/qwen35/kl.py; --bench-pp / --bench-tg.
- hip_compat cublas_v2.h: cublasSgemm / cublasSgemmStridedBatched.
2026-10-12 22:50:52 +02:00
Niko1221 1269d5fa97 setup on macOS: Unsloth UD-Q4/Q5/Q6_K_XL (not offered until their expert kernels land); the stream rule by size
setup_mac.py: the Unsloth files by name and SHA-256 (setup.py's pinned revision), repacked into one GGUF for the GPU
with every tensor verified, the n-gram table found by name, --native-dense-gguf the repacked file; setup writes
STRATA_METAL_STREAM to the config so the engine follows its choice. UD-* are behind 'missing' (the Metal expert
kernels for Q4_K/Q5_K/Q6_K/Q5_1 are in progress) and only reachable with --model.

stream.cpp: auto streams when the mapped weights + 12 GiB do not fit the GPU working set (was: experts > 60% of
it, which would have streamed UD-Q4_K_XL on the 128 GB M5 Max). M5 Max: Q2_0 stays resident (same tokens and speed);
M4 32 GB: Q2_0 streams as before.
2026-10-12 22:49:27 +02:00
Niko1221 81fefbe953 SYCL native_grouped_parity --kqbench: grouped expert calls per format pair at the model's shapes, us per call and GB/s of expert bytes 2026-10-12 22:48:38 +02:00
Niko1221 a57fa9990e metal/tools/metal_repack.py: a multi-shard GGUF as one 16 KiB-aligned GGUF for the Metal engine
Shard 1's metadata (without split.*) and every tensor but the n-gram table, byte for byte: dense first, then each
layer's routed experts together; --verify hashes every tensor (SHA-256) against its source shard. For Unsloth's
UD-*_K_XL (4-6 shards cutting through layers). Checked on Q2_0 (M5 Max): 35.05 GiB, 1,223 tensors identical,
written and verified in 33 s; the engine on it (--native-dense-gguf the same file, --ple-gguf the original shard 2)
gives the same tokens as on the original shards, prompt1 and story, at the same speed (114.2 / 107.7 tok/s).
2026-10-12 22:45:02 +02:00
Niko1221 74a78869eb nvfp4_decode_bench: NVFP4_BENCH_FILE times real blobs (an experts.bin or its head) instead of random ones 2026-10-12 22:39:47 +02:00
Niko1221 faf6c1c955 Images: Vulkan decodes in 256-pixel tiles at a quarter's overlap (the 780M's 1024x1024 VAE: 23 s instead of 45 s); docs/IMAGES.md speed table 2026-10-12 21:54:20 +02:00
Niko1221 b63e38b1ae docs/QUANTS.md: Unsloth's K-quant files and Q8_0 per role, the kernels per format and backend, the quality yardstick; UNSLOTH_Q4/Q6 notes for the Phase 1 build 2026-10-12 21:48:34 +02:00
Niko1221andsergiywith 5629161b14 mmq_expert_bench: the prompt path's routed-expert products timed at the engine's shapes, NVFP4 beside UD-IQ4_XS's IQ3_S / IQ4_NL
From sergqwer/strata-nvfp4 1688a344 (src/prefill/mmq_expert_bench.cpp), with UD-IQ4_XS's gate/up and down formats
added as comparison cases (an f16 d leads their blocks, as Q8_0's).

Co-authored-by: sergiywith <[email protected]>
2026-10-12 21:26:37 +02:00
Niko1221 6e6d4faf5b decode: NVFP4 down on 8-lane rows (4 a warp, 32 a block) - bitwise warp_sum's tree, the whole expert at 89% of the 3060's DRAM peak
row_dot_20_sub8: lane t takes k = t (+ k = t + 16 for t < 4, else + 0) and k = t + 8 (+ 0), then xor 4, 2, 1 - the
order warp_sum adds a K = 20 row in (lane i + 16, then + 8), so the result is the same bits; native_down_multi_kernel
routes TD 40 there (as IQ4_NL's K = 40 row_dot_40_sub8) and the down grid takes 32 rows a block for d_type 40.

nvfp4_decode_bench, RTX 3060, 64 distinct experts: down alone 0.260 -> 0.189 ms at 1 token (226 -> 312 GB/s, 87% of
360); the whole expert 0.626 -> 0.554 ms (89%), 2 tokens 0.686 -> 0.596, 3 0.786 -> 0.661, 4 0.910 -> 0.766 ms (from
2.261 before Split<40>).  Output hashes unchanged, nvfp4_expert_gpu_parity unchanged.
2026-10-12 21:25:17 +02:00
Niko1221 bcc2a84454 metal engine: the routed gate/up's i-quant grids from constant memory (function constant 23 on moe_gu_*; STRATA_METAL_CTAB=0 off) - IQ3_S spec 2 decode +0.7-1.0%, greedy tokens unchanged 2026-10-12 21:17:53 +02:00
Niko1221 af6738eb74 metal: MM_PROBE 7 - a repacked i-quant layout's cost (one aligned 16-byte load a lane a row a 32-group): IQ3_S prompt gate/up 9.5-10.9 -> 6.8-6.9 ms a layer 2026-10-12 21:17:53 +02:00
Niko1221 c7070a72cf kq_cpu_bench: the CPU pool's expert rows per format on T threads in GB/s of weights; tools/quant_bound.py: decode bounds from the per-layer formats; setup copies libstrata_kq next to a compiled engine 2026-10-12 21:16:33 +02:00
Niko1221 546d767543 decode: NVFP4 experts decode each weight part once per call for every token of the window (Split<40>), its UE4M3 scales from bits, down on 16-lane rows - bitwise the same, 1.14-2.5x
The ported NVFP4 decode experts had no Split, so they took the per-entry kernels: every weight was decoded again for
every token of a verify window, and the kernel slowed almost linearly with the tokens per expert.  Measured with
nvfp4_decode_bench on the RTX 3060 (64 distinct experts, sm_86, CUDA 13.4; best of 50):

| tokens per expert | before | after | |
|---|---:|---:|---:|
| 1 | 0.714 ms (248 GB/s) | 0.626 ms (283 GB/s) | 1.14x |
| 2 | 1.200 ms | 0.686 ms | 1.75x |
| 3 | 1.730 ms | 0.786 ms | 2.20x |
| 4 | 2.261 ms | 0.910 ms | 2.48x |

(UD-IQ4_XS's IQ3_S / IQ4_NL experts, 15% fewer bytes: 0.512 / 0.578 / - / 0.814 ms.)

- Split<40>: vec_dot_nvfp4_q8_1 split into load (the E2M1 codes through kvalues_fp4, the two sub-block scales) and
  apply (the dp4a chain and the float expression in the same order), so the multi-entry kernels apply one decode to
  up to four tokens.  The multi kernels now apply the NVFP4 tail scales on their outputs as the per-entry kernels do
  (s_gate / s_up on gate/up, s_down on down; x * 1.0f for every other format, which is exact).
- ue4m3_to_f32_half builds the value from its bits instead of two ldexpf and branches: equal for all 256 bytes
  (nvfp4_decode_bench checks them).
- down: NVFP4's rows are K = 20 calls at n_ff 640, as Q2_0's, so they take row_dot_20_sub16 (2 rows a warp, 16 rows a
  block) instead of one 20-of-32-lane row a warp: down 0.361 -> 0.260 ms at 1 token.  Its addition tree is
  warp_sum's (lane i + lane i+16 first), bitwise.

Bit for bit: the output hash of every case above equals the per-entry kernels' (STRATA_OLD_IQ_MMVQ=1);
nvfp4_expert_gpu_parity on real GPTQ blobs unchanged (1.088-1.168%).  Other formats: only the store multiplies by a
1.0f scale, and the down launch grid changes for d_type 40 alone.
2026-10-12 21:13:50 +02:00
Niko1221 8cc41f3ac6 nvfp4_decode_bench: the decode experts' weight bandwidth on random blobs of any format pair, with an output hash
nvfp4_decode_bench [gu_type d_type] [groups] [tokens per group] [iters]: native_expert_grouped on distinct random
blobs (64 x 2.76 MB, far past L2), best/mean time, weight GB/s against the card's DRAM peak, and an FNV hash of the
output so a kernel change can be checked bit for bit.  NVFP4_BENCH_PHASE=1|2 times gate/up or down alone.  Also an
exhaustive check of the UE4M3 decode built from bits against the ldexpf form (all 256 bytes).
2026-10-12 21:13:50 +02:00
Niko1221 de81ac91f4 Qwen3.6 T1: SiLU-gated GDN step and a 256/8 router in the native kernels; q36ref runs on them
- fused_gdn_step_norm_silu: the fused GDN step with the SiLU output gate (Qwen3.6), a compile-time
  template flag; fused_gdn_step_norm (Flash-Next, sigmoid) is the same kernel instantiated as before.
- native_router_topk(n_expert, k): 512/10 goes to the existing pinned top-10 kernels unchanged; 256/8
  is a templated copy of the same topk-moe contract.
- strata-q36ref --kernels strata (default): native MMVQ (q8_1) for every quantized matmul, dense and
  per routed expert (Q4_K/Q5_K/Q6_K/Q8_0), the fused GDN conv+L2 and SiLU step, the native router;
  --kernels plain keeps the reference kernels.
- kl.py: answer-only statistics beside all steps, llama.cpp's logits cached between runs.
2026-10-12 21:11:03 +02:00
Niko1221 c43c9ac948 Merge commit '450c82f5' into f-mac-iq3s 2026-10-12 21:07:47 +02:00
Niko1221 465cd61dfb Formats cost nothing unless used: Q6_K gate/up experts in the normal build; the K-quant MMQ prompt kernels on by default, on CUDA as their own library (strata_kq) opened only for a model with these experts and STRATA_MMQ_KQ=1 2026-10-12 21:04:17 +02:00
Niko1221 450c82f5e2 metal: IQ3_S pack work - QUANT_CTAB (constant-memory i-quant grids, function constant 23), mm_gu4 / mm_gu5 probes
- quant.metal: QUANT_CTAB (function constant 23): the IQ3_XXS / IQ3_S / IQ2_XXS / IQ2_XS / IQ2_S grids and the sign
  table read from ggml-common's constant arrays, no threadgroup copy (same values).  Decode moe_gu: 3-7% faster
  (IQ3_S-pack T2 window 14.96 -> 14.79 ms, 3 of 3); token_chain default (CHAIN_CTAB=0 off).  Prompt mm_gu3: slower
  (kept off)
- moe_mm.metal: mm_gu4 (decoded operand shared by MS 16-row token tiles): IQ3_S 9.5 -> 8.6 ms, IQ3_XXS equal, Q2_0
  slower; mm_gu5 (weight blocks staged in threadgroup memory, coalesced): slower (12.9-20.6 ms); W8 templated on the
  address space for IQ3_S / IQ3_XXS / IQ2_S; probes MM_PROBE 5 (loads only: as slow as the full decode)
- moe.metal MOE_PROBE (function constant 22; no table load)
- finding: the prompt i-quant decode is bound by its scattered small device loads (2-7 a 4-value run, 8 rows a load
  instruction), not by the grid lookups or the ALU
2026-10-12 21:03:58 +02:00
Niko1221andsergiywith fab8c10547 setup: the NVFP4 family - sergqwer's ready-made packs (GPTQ default, NVIDIA's checkpoint second), pinned and SHA-256-checked
--family nvfp4 --model NVFP4 | NVFP4-NVIDIA (MODEL-UPDATE Phase 4).  The files come from the packs' Hugging Face
repositories at the commits the fork's setup pins (NVFP4_REPOS: Maximilian228/Qwen3.8-Flash-Next-NVFP4-GPTQ-Strata
640a1db9, ...-NVIDIA-NVFP4-Strata cca8f7fe), each checked against its size and SHA-256; nothing is converted on the
PC and no file is mirrored.  The FP8 n-gram table and the BF16 embedding are the same file in both: a second install
links them.  The MTP draft layer is setup's own, as for every model.  The engine gets the fork's model flags
(--native and --native-dense-gguf on the dense GGUF, --ple-gguf, --embd-gguf); the rest of setup's choices (context,
KV, the low-RAM mode on the pack's experts.bin) are the usual ones: 96 GB keeps every expert in RAM, 64 GB with a
32 GB card the resident low-RAM mode.  NVIDIA only: on AMD setup stops and names UD-IQ4_XS (the HIP engine has no
NVFP4 kernels).  Images: off for these packs.  A ready-made engine older than NVFP4_ENGINE (0.1.47, to be set at
release) is replaced by one compiled from this source.

Tests: tools/test_setup_nvfp4.py (fetch from a file:// mirror with SHA-256 checks, the shared file linked, a wrong
file refused, the config name read back, mocked installs on 128/96/64 GB, AMD refused); test_setup_pins covers the
new table.  Every tools/test_setup_*.py passes.

Co-authored-by: sergiywith <[email protected]>
2026-10-12 20:53:31 +02:00
Niko1221 0d3553fc8f Quant yardstick: tools/quant_quality.py (teacher-forced top-1 agreement and KL against Q8_0 on a fixed 5x1000-token set) and tools/quant_formats.py (per-role tensor formats from GGUF headers, local or HF range requests) 2026-10-12 20:48:37 +02:00
Niko1221 5c6bdf6175 NVFP4 port: the SYCL tree takes the new defaulted args (no NVFP4 there); the 12x -> 12xa rewrite works on CMake < 3.29
- sycl: iq_dequant_f16 / iq_dequant_gu_f16 / moe_combine accept the NVFP4 scale arguments the shared headers now
  declare (refused if ever given: the SYCL port has no NVFP4 experts), and the no-MMQ stubs match the new mmq
  signatures (the calls were ambiguous with the defaulted ones).
- CMake: list(TRANSFORM ... REPLACE) with \2 of an optional group failed on CMake 3.28 for a plain "120"; two
  rewrites, one per form.
2026-10-12 20:43:44 +02:00
Niko1221 3a020d58c7 Qwen3.6 T1: strata-q36ref, the reference path, and its llama.cpp parity tools
- src/qwen35/q36ref.cu (target strata-q36ref, CUDA and HIP): Qwen3.6-35B-A3B on one GPU, the whole
  model resident, one token at a time with fp32 activations: plain pre-norm residual, GDN with the
  SiLU output gate (32 V heads over 16 K heads, conv 8192), dense gated attention (16 Q / 2 KV x 256,
  NEOX RoPE over 64 dims), softmax top-8 router over 256 experts with the sigmoid shared-expert gate,
  every weight read in its GGUF form (F32/F16/BF16/Q8_0/Q4_K/Q5_K/Q6_K). --act q8 (default) rounds the
  activations of quantized matmuls as llama.cpp's GPU path does; --force / --dump-full-logits for
  teacher-forced KL; --dump-layers / --dump-logits for parity.
- tools/qwen35/: q36_llama_dump.cpp (llama.cpp's side through the eval callback), parity.py
  (greedy answers + per-layer error), compare_dumps.py (two runs, e.g. the GPU-vs-CPU floor), kl.py
  (teacher-forced KL against llama.cpp HIP with the CPU backend as the floor), parity_prompts.json.
2026-10-12 20:41:17 +02:00
Niko1221 e000fe5d9c Expert arena: say at once that huge pages were skipped (#2126) 2026-10-12 20:37:22 +02:00
Niko1221 6b395578a2 Expert arena: MADV_HUGEPAGE is not requested when free 2 MiB blocks cover less than half of it (direct compaction stalled a 62 GB box's load at 100% system time); STRATA_ARENA_THP=1 asks anyway (#2126) 2026-10-12 20:37:21 +02:00
Niko1221 8e2c57be78 NVFP4 port: the SYCL build compiles the NVFP4 CPU rows (native_expert.cpp calls them); mmq_nvfp4_parity gets -mf16c on GCC/Clang
The fork was built with MSVC only: on Linux its parity tool's F16C rounding helper failed to inline without the
target flag, and the SYCL tree's own list of CPU expert sources lacked nvfp4_avx512.cpp / nvfp4_avx2.cpp.
2026-10-12 20:35:14 +02:00
Niko1221andsergiywith 55e2072c99 serve: the route tail skip is not a default with NVFP4 experts (STRATA_ROUTE_TAIL_SKIP=7 opts in)
Port of sergqwer/strata-nvfp4 c83625c3 (the rule for NVFP4 experts in any layer) onto 0.1.43's default, with its
#1884 nearly-all-cached exception kept.  On the fork's qwen-nvfp4-gptq pack the skip moved the answers by
teacher-forced KL 0.035 against it off, about the GPTQ quantization's own error against an all-Q8_0 reference
(0.038), for +11.5% decode (RTX 5090, the fork's measurement).  Packs without NVFP4 experts keep the default
unchanged.  The final default is the owner's, from our own 3060 A/B and KL against Q8_0.

Co-authored-by: sergiywith <[email protected]>
2026-10-12 20:35:14 +02:00
sergiywith b766cde631 cpu: NVFP4 expert rows in 256-bit lanes for CPUs without AVX-512
Without AVX-512 (Zen 2/3, Intel 12th-14th gen) the pool's NVFP4 rows went
through ggml-cpu's vec_dot, which re-decodes a row's blocks for every token of
a window.  nvfp4_256_* decode a 64-value block once and apply it to up to 8
tokens.  Each token's arithmetic is ggml_vec_dot_nvfp4_q8_0's AVX2 path step
for step (vpsignb, vpmaddubsw + vpmaddwd, the same FMA order, hsum_float_8),
so every row is bit-equal to it: an AVX2 CPU computes what it did before.

nvfp4_avx512_parity checks both kernels, whichever this CPU runs (the AVX2
rows must also be bit-equal; 0 differing rows of 1..9 tokens against the
portable and the native ggml-cpu builds), and is now a ctest
(nvfp4_cpu_parity).  One expert's gate+up, Zen 5 core: 1.12x ggml at one
token, 2.00x at 4, 2.35x at 8; under DRAM load (--bw) with 6 threads 47.3
against 24.0 GB/s at 4 tokens, 26.6 against 12.0 at 8.  Chat decode on the
RTX 5090 with STRATA_FORCE_AVX2=1 and 6 pool workers: 16.5-16.9 ms a round
against 17.3-17.5 (pool 6.6-6.8 against 7.2-7.3 ms).

STRATA_NO_NVFP4_256=1 falls back to ggml-cpu.

(cherry picked from commit 0c859e15f89054a376db7458bfb298e3e6c81f22 of sergqwer/strata-nvfp4)
2026-10-12 20:30:13 +02:00
sergiywith f72f203d91 prefill: the CPU rows' row_sd ones sized on their own - 0.1.42 takes the rows buffer once at its largest, which left them unallocated
Upstream's 04dbe561 allocates cpu_rows at its largest before the walk; the fork's allocation of cpu_ones (row_sd 1 for
the CPU's rows on an NVFP4 pack, b59f5dda) sat inside the reallocation that then never ran, so a staged chunk with the
CPU share copied from a null host pointer: "prefill moe_combine: invalid argument" (2K prompt, qwen-nvfp4-gptq).

(cherry picked from commit 52b272ebb92c9ef49029314da1a695d38f570d88 of sergqwer/strata-nvfp4)
2026-10-12 20:30:13 +02:00
sergiywith 77c6991d18 prefill: the CPU share on NVFP4 experts - the CPU's rows take row_sd 1 (upstream's CPU share is the base)
Was 640df4f0, the fork's CPU share.  Upstream 0.1.40.2 took it (978d3558, with 667f2eca's blobs taken on the
prefill thread and 4322e241's STRATA_DBG_NAN rows; opt-in there), so the port keeps upstream's code and adds only
what an NVFP4 pack needs: the CPU's rows carry s_down already, so their row_sd entries are 1 (cpu_ones, pinned
beside cpu_rows).

Port note: the release loop keeps 0.1.43's steps_up / tok_up / up_ring releases.

(cherry picked from commit a0c2ca233ac8fe8ec9d342bd319c93404791fa15 of sergqwer/strata-nvfp4)
2026-10-12 20:30:13 +02:00
sergiywith f235e394c1 Mixed expert formats: an NVFP4 projection beside another format in the same expert (e.g. NVFP4 gate/up + Q8_0 down)
- The blob keeps its {s_gate, s_up, s_down, 0} tail whenever any projection is NVFP4; the other projection's scale is
  exactly 1.0, and every path (GPU decode, CPU pool, prompt path) already multiplies by the tail, so 1.0 is exact.
  native_expert_layout (GPU) and native_fmt (CPU) no longer require NVFP4 in all three projections.
- tools/iq_pack.py writes such blobs (1.0 for a non-NVFP4 projection, .scale tensors only for the NVFP4 ones).
- native_expert_parity: the synthetic NVFP4 blob gets its tail (it was left zero, so every NVFP4 synthetic expert
  computed 0 and failed), non-unit for NVFP4, 1.0 for the other projection, and the reference applies it.
  nvfp4/q8_0, q8_0/nvfp4, nvfp4/nvfp4 and q8_0/q8_0 pass: CPU and GPU within 1e-7, ~1.2% from the float reference
  (activation rounding).

(cherry picked from commit 473c0959141b36d28e7a2eb16005f8c8a4e3c8d0 of sergqwer/strata-nvfp4)
2026-10-12 20:29:54 +02:00
sergiywith 37216b6e52 Prompt path: the MMQ group gather (upstream since 0.1.38) carries NVFP4 tails and zeroes the MMQ tail
0.1.38 took the fork's group gather without the NVFP4 parts: each expert's 16-byte scale tail now goes to its
group slot and the group's last flush zeroes the MMQ tail, in the same launch (as #353 on 0.1.38).

(cherry picked from commit 8f2193f028940b9a6d270203b640562435937a7a of sergqwer/strata-nvfp4)
2026-10-12 20:29:54 +02:00
sergiywith e51b4379dc NVFP4 routed experts: converter, pack, decode, prompt path, AVX-512 CPU rows
A ModelOpt NVFP4 checkpoint of Qwen3.8-Flash-Next (its routed experts NVFP4, group 16) runs on the native path.
Rebased on 0.1.31: NVFP4 is type 40 in the per-role format lists (STRATA_GU_FMTS / STRATA_D_FMTS / STRATA_MMVQ_FMTS)
beside Q4_K/Q5_K/Q5_1/Q8_0, and 0.1.31's dq_q8_0 serves both.

- tools/nvfp4_convert.py: llama.cpp's converter with the engine's type policy (BF16 control projections, Q8_0 native
  tensors and token embedding, no PLE table); tools/nvfp4_verify.py / nvfp4_verify_gguf.py prove the experts bit for
  bit.
- tools/iq_pack.py: expert_layout() gives NVFP4 blobs a 16-byte tail {s_gate, s_up, s_down, 0} (the per-expert
  weight_scale_2), so every consumer that moves whole blobs moves the scales; an NVFP4 pack always writes experts.bin
  (the GGUF has no tails, so the in-place GGUF read does not apply).
- decode: NVFP4 in the native expert kernels (q8_1, UE4M3/E2M1 decoded in software, bit-identical to ggml); each scale
  on its own projection's FP32 output (folding s_down into up put the hidden into FP16's subnormals).
- CPU pool: AVX-512 NVFP4 rows (1.8-3.7x ggml-cpu's), ggml-cpu elsewhere.
- prompt path: llama.cpp MMQ - W4A8 by default (int8 MMQ with Blackwell's FP4 MMA hidden, mmq_nvfp4_w4a8.cu), W4A4
  and FP16 through STRATA_PREFILL_NVFP4; the scales applied where they are read.
- CMake: the architectures stay as given. Only mmq_nvfp4_w4a4.cu (the FP4 x FP4 kernel and its FP4 activation
  quantizer, symbols renamed) is built with 12x -> 12xa in strata_mmq_w4a4; without its image W4A4 falls back to W4A8.
  strata.exe: 55 sm_120 cubins + 1 sm_120a.
- 0.25 of the missed experts over PCIe for NVFP4 packs (their blobs are 2.76 MB).
- Parity tools (mmq_nvfp4_parity, nvfp4_avx512_parity, nvfp4_expert_gpu_parity); HIP guards; docs/NVFP4.md.

Checked on this rebase (RTX 5090): the parity tools as before (decode experts 1.09-1.16%, MMQ W4A8 0.53%, W4A4 8.6%
- the same numbers as the 120a-everywhere build); IQ2_XS 128 greedy tokens identical to 0.1.31 main; the NVFP4 pack
against the 0.1.29-based build at the same expert-cache size: identical tokens on a 24-token and an 8K prompt, in W4A8
and in W4A4 (prefill 4,231 / 4,583 tok/s on 8K).

Port note: the PCIe share base for NVFP4 packs (0.25) sits beside 0.1.43's PcieAuto start values.

(cherry picked from commit 1f8a12858cc4ed80a977767afef6b6c3a754ac63 of sergqwer/strata-nvfp4)
2026-10-12 20:29:45 +02:00
Niko1221 0601072dfc test_setup_strix_halo: gfx1103 is in the gfx11 WMMA list since the 780M change 2026-10-12 20:19:49 +02:00
Niko1221 a5b3b6c27b Image generation: Qwen-Image-2.1-Turbo through stable-diffusion.cpp (POST /v1/images/generations)
- serve/images.py: OpenAI's images API (prompt, size, n, response_format b64_json|url) plus seed and steps; one
  sd-cli process per request with the model card's arguments (8 steps, CFG 1, euler, Turbo's sigmas,
  --diffusion-fa), the PNGs returned unchanged.  The job takes the service's turn (one job at a time on the GPU)
  and the config's gpu_policy says what the text engine does meanwhile: keep, shrink (--vram-elastic), unload
  (its conversation saved to a session file and restored after the next start), auto.
- setup.py --images qwen-image (--image-quant, --image-backend, --image-gpu-policy): sd.cpp 2988060 + its ggml
  as zips, built for CUDA / HIP / Vulkan (LunarG SDK into third_party when the PC has no Vulkan dev files) / CPU;
  DiT quant by GPU memory (Q4_K_M <= 8 GB, Q6_K <= 12, Q8_0 above), VAE and the Qwen3-VL-8B UD-Q4_K_XL text
  encoder at pinned revisions, each checked against the Hub's SHA-256.  tools/image/install.py adds it to an
  existing install.
- Web page: an Images tab when the server has image generation.
- docs/IMAGES.md; tests: serve/test_images.py, tools/test_qimage.py.
2026-10-12 20:18:33 +02:00
Niko1221 852e0657c6 setup on macOS: rebuild the engine when its sources change (a digest of the source files, not the git commit: an unzipped copy has none); the Mac's own words for the sizes 2026-10-12 20:06:02 +02:00
Niko1221 ceab2ce2b4 docs/MAC.md: Strata on a Mac - what it needs, memory per pack, setup, the measured numbers (M5 Max resident, M4 32 GB streaming), quality, limits, switches 2026-10-12 20:03:23 +02:00
Niko1221 93d7ceb91d setup on macOS: IQ3_S offered (recommended from 110 GB), streaming Macs configured without MTP
IQ3_S runs on Metal since mac-kern's IQ4_XS kernels: recommended from 110 GB (Apple's 128 GB Macs), IQ3_XXS where it
fits resident, then Q2_0. A pack that does not fit Metal's share of the memory streams its experts from the SSD (the
engine decides, f-mac-ssd): setup says so with the M4 numbers, writes --suffix-draft 0 and no --mtp (one token per
step, measured faster there) and does not fetch the draft layer.
2026-10-12 20:02:39 +02:00
Niko1221 ff0546db26 metal: serve - a new conversation resets the decode window; conversation checkpoints hold the window's state
session_zero and conversation_checkpoint_save/restore go to the Metal window under STRATA_GPU_METAL (the running
state lives there, not in the session's buffers): reset zeroes its GDN recurrences and conv histories, PLE history
and indexer tails (and the draft layer's); a checkpoint holds the same set, after the pending fold. Before this a
new request carried the last conversation's state (M5 Max, Q2_0: an unrelated request after a story answered
differently from a fresh engine; now the same), and on a streaming Mac the session buffers it zeroed or copied had
been given back (the engine stopped).

Checked on the M5 Max (resident) and the M4 (streaming): an unrelated request after another equals a fresh
engine's answer; a three-turn conversation reuses 35 / 73 of its tokens and its second answer equals a fresh
engine's. Shared files: session.cpp and conversation_state.cpp preprocess IDENTICAL and their objects are byte-
IDENTICAL on CUDA (P1004) and HIP (p620). Also: IQ4_XS's v2 prompt tile (_16_64_32_2), and a call stack when a
given-back allocation is touched.
2026-10-12 20:02:39 +02:00
Niko1221 14ba7a627a Model families: Qwen3.6-35B-A3B (qwen35moe) recognised, geometry and layout from the GGUF, no engine path yet
- ModelFamily from general.architecture (qwen4exp, qwen35moe); the architecture guard accepts both, the
  engine's guard (native dense/head, --native) refuses Qwen3.6 with "recognised, not run yet".
- ModelGeometry moved to core/geometry.hpp (+ family, shared-expert FFN, in-file MTP layers, vocab);
  geometry_from_gguf reads every shape key, checked against the compiled kernels (Flash-Next files give
  exactly the defaults; expert count and top-k stay run-time sizes).
- Per-family tensor layout tables (GDN / attention / nextn MTP block, hyper-connections or plain
  pre-norm, indexer or none) and a GGUF directory check; MXFP4 block size in the reader.
- setup: --family qwen36 downloads unsloth/Qwen3.6-35B-A3B-MTP-GGUF (pinned 5bc3e238, size + SHA-256)
  UD-Q4_K_XL / UD-Q6_K_XL / Q8_0 (+ mmproj) and says the engine does not run it yet; serve's default
  model name per family; strata_inspect recognises qwen35moe.
- Tests: model_family_test (synthetic, --real for headers), test_setup_qwen36, serve/test_family_name.
2026-10-12 19:58:28 +02:00
Niko1221 f5914a1818 metal: IQ3_XXS prompt decode probes (MM_PROBE 3: no table lookups, 4: computed signs) - the grid/sign threadgroup lookups are 2.5 of 6.6 ms a layer; computed signs are slower (7.0-7.6 -> 7.7-8.3) 2026-10-12 19:45:09 +02:00
Niko1221 b6a2dacd86 Merge f-mac-kern b6480437 (IQ4_XS expert kernels: IQ3_S on Metal) 2026-10-12 19:42:48 +02:00
Niko1221 93e582d087 Merge f-mac-ssd f0609f40 (expert streaming from the SSD for Macs whose memory cannot hold the pack)
Conflicts in metal/src/engine/window.cpp resolved: the stream's next-layer routing guess beside router_route
(opt-in); the cached window through the stream's segmented run, the kernel profile off while streaming; host reads of
the weights through W_ (the mapped file, or the dense weights in memory when streaming), also in prompt_chain.inc;
the drafter's prompt rows batched, from either prompt path. The prompt: resident -> prompt_chain.inc, streaming ->
the stream's prompt path (it streams each layer's experts for the chunk); STRATA_METAL_PROMPT=window: 8-row windows.

M5 Max: Q2_0 prompt1/story and IQ3_XXS prompt1 with MTP equal to the no-MTP references; the 1,662-token prompt
through prompt_chain.inc equal to before; Q2_0 streamed (STRATA_METAL_STREAM=1) equal to resident on prompt1. The
1,662-token prompt streamed (the stream's prompt kernels: chunks of 1024, flash QSA) first differs at token 21 of 60
from the resident prompt_chain.inc path (different kernels and chunking).
2026-10-12 19:42:48 +02:00
Niko1221 b6480437d2 metal: IQ4_XS routed-expert gate/up for decode (moe_gu_23_*) and prompt (mm_gu3 W4<IQ4_XS>, mm_gu2 TK >= 32 tiles) - the IQ3_S pack's one IQ4_XS layer; parity on the M5 and the M4 2026-10-12 19:41:13 +02:00
Niko1221 5565a347de metal: M4 window GEMV probes - gemv_x (x staged in threadgroup memory), GEMV_PROBE (function constant 9)
- gemv.metal: gemv_x<F,LPR,NR,SG> = gemv (KS 1) with the window's prepared x staged in threadgroup memory (bitwise
  the same arithmetic); GEMV_PROBE 1/2/3 bench probes (skip later tokens' x loads / combine; rows-outer order)
- units.metal: X<F>::load templated on the pointer's address space (device or threadgroup), same arithmetic
- gemv_parity: GEMV_X=1 sweeps gemvx_*, GEMV_PROBE passes the probe
- M4 finding: a window token's cost is the fp32 combine (1 FMA a weight a token), at ~0.85 T FMA/s (near the M4's
  peak); the x loads are ~6 us of the ~30-60 us a token, and staging x in threadgroup memory does not help
2026-10-12 19:38:29 +02:00
Niko1221 37c3b38c26 setup on macOS: --mmap-experts in the config (what the Metal engine does; the server's start text then says the experts are mapped, not loaded) 2026-10-12 19:38:09 +02:00
Niko1221 a9edff4f80 setup on macOS: metal/setup_mac.py (Apple Silicon, the Metal engine built from source)
setup.py hands a darwin run to metal/setup_mac.py (nothing else changes on a PC); setup.sh fetches a pinned
standalone Python 3.12 into .python on a Mac without Python 3.10+ (no sudo, no Homebrew). The Mac setup checks the
chip, unified memory, macOS (15+) and the Command Line Tools; recommends the pack by memory (IQ3_XXS from ~96 GB,
Q2_0 below; IQ3_S only with --model: the Metal expert kernels lack its IQ4_XS experts); builds the engine with pip's
cmake/ninja, Apple's metal-cpp (pinned SHA-256) and llama.cpp's ggml at the pinned commit; prepares the native pack
and the MTP draft layer; writes strata-<model>.json (backend metal, --spec 2) and run-<model>.sh; starts
serve/server.py. tools/test_setup_mac.py: 10 tests with sysctl/sw_vers/xcode-select mocked.

On the M5 Max (m1002): ./setup.sh --model Q2_0 --gguf-dir ... --yes from a fresh copy: Python fetched, engine built,
pack and config written in 29 s (models already downloaded); the server answered /v1/models, the chat page,
streamed /v1/chat/completions and /v1/messages (Q2_0, 112-121 tok/s). python -m pytest serve -q on the Mac: 705
passed, 11 skipped.
2026-10-12 19:37:54 +02:00
Niko1221 a5d17ab0e3 metal: the draft vocabulary beside the draft layer (<mtp>/rt/draft_vocab.bin, setup's --draft-vocab) 2026-10-12 19:37:54 +02:00
Niko1221 b66c61984b metal: serve ends cleanly after QUIT (Metal-only _Exit)
The stdin reader (a detached thread) can take in_mu after the serve scope destroyed it, when the server closes the
pipe after QUIT; on macOS that lock throws and the engine ended with an abort. Inside #if STRATA_GPU_METAL: flush
and _Exit(0) after the QUIT profile save. HIP (p620): generate.cpp preprocesses IDENTICAL and its object is
byte-IDENTICAL against the gated tree (P2003 was unreachable for the CUDA compare; the change is preprocessor-only).
2026-10-12 19:37:53 +02:00
Niko1221 818845ea10 Merge commit 'a0116b27' into f-144-int 2026-10-12 19:34:25 +02:00
Niko1221 e30cffb8f8 metal: stubs.cpp regenerated without cvec() (now in missing.cpp) 2026-10-12 19:15:57 +02:00
Niko1221 f33434836a metal: serve - the empty control vector on Metal; a call stack on terminate
The serve loop asks cvec() every request: Metal returns the empty one (no --control-vector-scaled on Metal yet)
instead of the stub that stopped the engine; stubs.cpp regenerated without it. An uncaught exception now prints its
call stack (backtrace_symbols_fd) before the abort.
2026-10-12 19:15:16 +02:00
Niko1221 389c24eebd metal: router_route (mac-kern 3f9ca996) in the window, opt-in STRATA_METAL_ROUTE=1
The BF16 router GEMV and moe_route as one dispatch beside the shared expert's GEMVs. Greedy output unchanged (Q2_0,
IQ3_XXS, both prompts, on and off). Not the default: in this window the router GEMV already runs beside the
shared GEMVs, and the T2 window measured 13.035 ms GPU with it vs 13.027 without (the fused kernel alone 0.615 ms
vs 0.566 for the two); end to end, --spec 2, 3 interleaved pairs, off -> on: Q2_0 113.61 -> 113.28 / 107.50 ->
106.97, IQ3_XXS 103.51 -> 103.07 / 96.19 -> 96.02 tok/s.
2026-10-12 19:15:11 +02:00
Niko1221 be49de3e34 Merge f-mac-kern 3f9ca996 (router_route, gemv_cat, gr_norm_comb, Q3_K packed loads) 2026-10-12 18:56:48 +02:00
Niko1221 3f9ca99632 metal: decode T=2 items - router GEMV + moe_route in one dispatch (router_route), gemv_cat, gr_norm_comb, Q3_K packed loads
- router.metal (new): router_route<F> - the router GEMV rows as gemv's (LPR 32, KS 1) with 512-thread threadgroups,
  the last threadgroup to finish (device counter, device-scope fences) runs moe_route's body and resets the counter;
  logits / ids / w / plan bitwise gemv + moe_route.  token_chain default (CHAIN_ROUTE=0: separate): T2 13.08 -> 12.93 ms
- gemv.metal gemv_cat: two same-format matrices over one x in one dispatch (ssm_alpha + ssm_beta), bitwise; no gain
  in graph mode (CHAIN_ALBE opt-in)
- gr2.metal gr_norm_comb: the MoE combine folded into gr_norm, bitwise; +0.6 ms at T2 (CHAIN_COMB opt-in, not kept)
- units.metal Dec<Q3_K>: qs / hmask as packed_ushort4 loads (same values): T2 2560->10240 33.8 -> 32.2 us
- tests/fuse_parity: the three fusions bitwise for 1..4 tokens
2026-10-12 18:51:19 +02:00
Niko1221 38cb85a8c3 metal: gdn_step's partial commit in the window (opt-in STRATA_METAL_PARTIAL=1)
With it a verify window of T > 1 commits its first row in place (commit = 0x100 | 1, mac-kern 56526aed): commit(1)
needs no fold, commit(n) folds rows 1..n-1; a prompt window commits all its rows in the step. Greedy output equal
to no MTP (Q2_0, IQ3_XXS, both prompts, --spec 2 and 4, the window prompt path).

Not the default: M5 Max, --spec 2, 3 interleaved pairs, off -> on: Q2_0 113.35 -> 113.24 / 106.98 -> 106.75,
IQ3_XXS 103.53 -> 102.71 / 96.18 -> 95.88 tok/s. The in-place state write (36 x 3 MB) costs every window; the
fold it saves is only the rounds with no accepted draft (24-36% at --spec 2).
2026-10-12 18:45:58 +02:00
Niko1221 3bbfa9e6e1 Merge f-mac-kern 56526aed (gdn_step partial commit) 2026-10-12 18:40:05 +02:00
Niko1221 56526aedc2 metal: gdn_step partial commit (commit = 0x100 | k): the state and conv history after the first k window tokens
- gdn.metal: with commit = 0x100 | k (1 <= k <= GDN_NTOK) the state is written in place and the conv history to
  hist_out right after token k - 1, while every token's y is still computed; commit = 1 / 0 unchanged (the full
  commit now writes at the last token inside the loop - same values, same speed)
- gdn_parity: the partial commits are bitwise a k-token commit's state and history, and y bitwise the verify window's
  (k = 1 .. ntok - 1, ntok 2..4); gr_parity GR_DOWN=SG_KS picks gr_down's variant (sweep: 10.1-11.8 us at T 2, none
  better than 8_8 by more than 7%)
2026-10-12 18:39:03 +02:00
Niko1221 39acb889cd metal: test tooling - STRATA_METAL_KPROF=T (the GPU time of each kernel class of a T-token window, alone)
Once, after the 20th cached window of T tokens with the head: the window's dispatches grouped by pipeline and weight
role, each group run by itself (7 runs, median). Profiling only: the reruns move the state, so the text after it
is not meant to be read.
2026-10-12 18:31:58 +02:00
Niko1221 4eca56f46a metal: --spec defaults to 2 on Metal builds (an explicit --spec N wins)
Owner decision. Only the Options default under STRATA_GPU_METAL; CUDA/HIP/SYCL keep 0: on P2003 the CUDA
generate.cpp translation unit preprocesses IDENTICAL and its object is byte-IDENTICAL.

M5 Max, MTP, 200 tokens, greedy output equal to no MTP in every run: Q2_0 114.0 / 107.9 tok/s (prompt1 / story,
--suffix-draft 0; was 112.0 / 86.2 at --spec 4), 119.5 / 108.2 with the default suffix drafter; IQ3_XXS 103.5 /
96.9, 108.9 / 97.0 (was 110.2 / 87.4).
2026-10-12 18:30:51 +02:00
Niko1221 f0609f40d4 Merge f-mac-kern 272bbbbd 2026-10-12 18:26:09 +02:00
Niko1221 54405425e0 metal: token_chain's --fuse in the decode window (GDN y prep in the step, no QSA selection within the budget)
The GDN step writes the prepared y planes (no xprep dispatch per GDN layer); a window whose context is within the
2,051-cell budget skips the QSA score and top-k (qids_ holds the identity, restored after a selecting window; the
cached encode is keyed by it). STRATA_METAL_FUSE=0: off.

M5 Max, Q2_0, 200 tokens, 3 interleaved pairs: no MTP 85.1 -> 87.4 (prompt1) and 85.2 -> 87.3 (story); MTP 110.7 ->
112.0 and 85.3 -> 86.2 tok/s; tokens identical on and off and equal to the no-MTP reference.
2026-10-12 18:24:20 +02:00
Niko1221 a26122339f Merge f-mac-kern 272bbbbd (M4 QSA prompt attention, mm_gu3 paired-run decode, chunked GDN scan) 2026-10-12 18:20:49 +02:00
Niko1221 f159858146 metal: the prompt through mac-kern's prompt kernels (prefill hook)
prompt_chain.inc: tests/prompt_chain.cpp's chain (6f6c555b) into the decode window's own state - fp16 GEMMs on the
matrix units, grouped expert GEMMs, the GDN prompt scan, QSA K/V and indexer keys into the window's caches - plus
the PLE block after layer 0, every row's final residual for the drafter (its prompt rows in one command buffer),
the history parity, RoPE table and pending fold. Chunks of 2048 rows (STRATA_METAL_PROMPT_CHUNK); COOP_K4 picks
the register-operand kernels on the M5 and the older ones elsewhere. The 8-row-window path stays as the fallback
(STRATA_METAL_PROMPT=window, and prompts under STRATA_METAL_PROMPT_MIN = 32 rows).

M5 Max: Q2_0 4K/32K prompts 1,434/1,462 tok/s (window path 190/174), IQ3_XXS 1,260/1,240. Teacher-forced KL of
the chain's prompt vs the window path's, 28 prompts: 0.0004 (top-1 99.4-99.6%); needles 4K-32K x 10/50/90: the
same answers as the window path (12/12, both models).
2026-10-12 18:20:40 +02:00
Niko1221 b174c71f86 metal stream: a prompt's buffers live in a region of the expert arena (held only while a prompt runs; the arena is anonymous memory wrapped no-copy); 7 GB kept for macOS 2026-10-12 18:04:19 +02:00
Niko1221 8b91c64483 metal stream: size classes merged (<= 15% slot waste; 3 for the IQ3_XXS mix), each holding a prompt layer; misses never evict a wanted slot (pinned first); read-ahead depth / LRU place by expert size (measured) 2026-10-12 17:46:30 +02:00
Niko1221 272bbbbd4a metal: chunked GDN scan (WY form, chunks of 32) - correct, slower in scalar fp32 than gdn_scan_r; kept, not used
- gdn_prompt.metal: gdn_cprep (per head and chunk: gates in log space, A, forward substitution for U and W),
  gdn_cstate (per head and 32 state columns: the chunks in order), gdn_cout (the intra-chunk output)
- gdn_prompt_parity: CB -100 = the chunked form; y 3e-7, state 2e-7 vs the decode step; 7.4 ms vs 1.9 ms at T 2048
  (cprep 1.5, cstate 4.7, cout 1.4) - it needs the matrix units to pay off
2026-10-12 17:32:53 +02:00
Niko1221 072c19f60f metal: mm_gu3 paired-run decode without the runtime layout check (Q2_0 gate/up 4.9 -> 3.5 ms a layer); SLC prefetch probe
- moe_mm.metal: the paired-run (k, k + 16) decode is taken on the COOP_K4 layout unconditionally (coop_probe now
  checks that pairing on both tiles used); the runtime per-element check cost ~30%.  The MMA-only ceiling of mm_gu3
  (MM_PROBE=1: no decode) is 2.45 ms a layer = 55 TFLOP/s useful, so the decode is what is left.  Measured and not
  kept: fp16-math Q2_0 decode (slower), a W8<Q2_0> sharing the block scale (slower than two W4)
- glue.metal slc_touch + token_chain CHAIN_PREFETCH: the next HC read's weights touched concurrently with the first
  projection GEMV after a read; measured +0.83 ms a token (10.46 -> 11.29, 3 of 3 interleaved) - not kept, opt-in
2026-10-12 17:23:39 +02:00
Niko1221 41ffe3eef6 metal: prompts on the matrix units in the engine (prompt_chain's chunk on the window's state), SSD-streamed
A prompt of 64+ tokens runs in chunks (STRATA_METAL_PROMPT_CHUNK, default 1024 streaming / 2048 resident) through
mac-kern's prompt kernels (fp16 GEMMs, the GDN scan, QSA over the chunk, grouped expert GEMMs v2 on the M4, v3 on the
M5), the PLE block for T rows, on the decode window's GDN / K/V / PLE state; the draft layer's prompt K/V read the
chunk's final rows.  Streaming: the expert GEMMs address arena slots (function constant 20 in moe_mm.metal too), a
chunk's handshake puts the layer's experts in place and streams the next layer's non-resident experts into the LRU
tail behind the compute (the decode-hot experts stay); slots in use by the running layer are pinned.  The host
code's own device weight copies are given back on a streaming Mac (purge_device_allocations).
STRATA_METAL_PROMPT_GEMM=0 / _MIN, STRATA_METAL_PROMPT_EXPERTS=v2|v3, STRATA_METAL_PROMPT_QSA=v1|flash.
2026-10-12 17:18:46 +02:00
Niko1221 d9f4b16006 Merge f-mac-kern dbc2e2fd (M4 QSA prompt fixes) 2026-10-12 16:58:49 +02:00
Niko1221 e00b29862b metal stream: read-ahead two layers ahead (STRATA_METAL_PREFETCH2), most likely first; leave-one-class-out timing (STRATA_METAL_SKIP), window timings per T, STRATA_METAL_GEMV_NR, runtime allocation log 2026-10-12 16:58:49 +02:00
Niko1221 dbc2e2fd8f metal: QSA prompt attention correct on the M4 (K = 32 runs, threadgroup-staged store, fresh per-chunk accumulator)
- qsa_attn_mm: the P V matmul in K = 32 cell runs (K = 64 runs computed garbage on the M4), the output through
  threadgroup memory (a direct matmul2d store into 258-float rows lost the threadgroup on the M4); also faster on the
  M5 (8.1 -> 7.4 ms at pos 0)
- qsa_flash: the same K = 32 runs (was a hang on the M4) and a fresh per-chunk accumulator folded into the running
  one (on the M4 a run does not accumulate into elements rescaled in place); now about equal to attn_mm + merge on
  the M5 (9.4 vs 9.5 ms at pos 0, 20.1 vs 20.3 at 30000) and the prompt_chain default there (PC_QSA=flash|mm|v1);
  the M4 defaults to v1 attention (faster there) with the GEMM score
- qsa_attn_mm bisection probe (function constant 8, QSA_STOP), qsa_prompt_parity QSA_DEBUG / pipeline report;
  coop_layout prints the destination layout too
2026-10-12 16:57:55 +02:00
Niko1221 6294f3468f Merge f-mac-compat 68387f1a 2026-10-12 16:51:03 +02:00
Niko1221 a6e55d062e metal: SSD-streaming expert arena for Macs whose memory cannot hold the model (the M4 32 GB)
The dense weights are read into one resident buffer; the routed experts live in an arena of slots filled from the
GGUF with F_NOCACHE preads (several pieces of an expert in flight); the window runs in 48 segments with a shared-event
handshake after each layer's router (mtl_rt run_graph_seg), where the host puts the missing experts in place (LRU)
and reads ahead the experts the next layer's router predicts from this layer's FFN input.  The expert kernels address
slots through smap (function constant 20); the resident path is unchanged.  STRATA_METAL_STREAM=auto|1|0.
2026-10-12 16:50:18 +02:00
Niko1221 68387f1a08 Merge f-mac-kern 6f6c555b (prompt experts / QSA on matrix-unit operands, COOP_K4) 2026-10-12 16:45:43 +02:00
Niko1221 6f6c555b17 metal: COOP_K4 (function constant 7) - per-element right-input decode for GPUs without the M5's layout (the M4)
- moe_mm.metal mm_gu3/mm_down3 and qsa_prompt.metal qsa_attn_mm/qsa_flash: with COOP_K4 = false every element is
  decoded on its own (the M4 holds runs of 2 n at one k); the experts are correct on the M4 that way
- tests/coop_probe.h: probes the layout (COOP_K4=0/1 overrides); moe_mm_parity, qsa_prompt_parity, prompt_chain
  set the constant; prompt_chain defaults to experts v2 and QSA v1 without it (faster / correct on the M4)
- qsa_prompt_parity: NaN-fills the partials before the matrix-unit run (a kernel that writes nothing shows),
  line-buffered output, QSA_NOFLASH
2026-10-12 16:36:08 +02:00
Niko1221 994ccdf451 metal: test tooling - STRATA_METAL_LOGPOS (teacher-forced rows for the KL harness) and STRATA_METAL_PROFILE
STRATA_METAL_LOGPOS=<path>: per decode position of one-token windows, the log-probability of the token that came
next (with --spec-follow, the forced text) and the top 64, in phaseA-tests cuda_kl.py's row format.
STRATA_METAL_PROFILE=1: per window size, host time before the GPU, run_graph wall vs GPU time, commit and draft
round times, printed when the window goes away. Both off unless set.
2026-10-12 16:35:15 +02:00
Niko1221 1f4b6b3615 metal: the GDN fold of a commit runs at the start of the next window
commit(n) after a window of several tokens no longer submits its own command buffer: the fold of the kept prefix is
encoded first in the next window's (cached per pending count). Nothing reads the GDN state in between.
STRATA_METAL_LAZY_FOLD=0 folds at commit as before.

M5 Max, Q2_0, MTP --spec 4, 200 tokens, 3 interleaved pairs: commit 0.87 -> 0.05 ms a round; prompt1 109.25 ->
110.21 tok/s, story 83.99 -> 85.14 (medians); greedy output equal to no MTP, lazy and not.
2026-10-12 16:35:03 +02:00
Niko1221 a0116b2782 Layer split + --batch: the default pipeline wins over --batch-mtp (STRATA_BATCH_MTP_SERIAL=1 or --batch-groups 1 keeps the serial MTP windows) (#2038)
0.1.42 let --batch-mtp run on a layer split and made the --batch-groups auto default give way to it: one serial group. On
2x RTX A4000 (IQ3_XXS, 3 pairs) four streams aggregated 62.2 tok/s against 92.7 on 0.1.41's pipelined groups (-33%, 0/3 pairs
faster), two streams 55.7 against 71.4 (-22%). With --batch-groups 2 (which turns --batch-mtp off) 88.3 and 71.1. The start-up
line says why --batch-mtp is off and how to keep it. --adapt-async 1 still gives one group. Solo decode and the answers are
untouched.
2026-10-12 16:00:57 +02:00
Niko1221 9bdfcd7166 metal: QSA score as an fp32 GEMM, paired-run i-quant decoders (W8), qsa_flash (measured slower), one gate/up tile
- qsa_prompt.metal: qsa_score_mm (fp32 MPP, relu-sum epilogue, the tail block scalar; 6.2 -> 1.1 ms at pos 30000,
  T 2048), qsa_flash (whole attention a threadgroup with an online softmax, fp16 out; correct but 27.6 ms vs 20.9 for
  attn_mm + merge - not used)
- moe_mm.metal: W8<F> decodes a lane's two runs of a 32-group with one read of the group's scale/sign fields;
  IQ3_XXS gate/up 9.3 -> 6.7 ms a layer
- prompt_chain: PC_QSA=mm uses qsa_score_mm too; gate/up 16,32,32,4 for every format; breakdown sees the far
  chunk's classes
2026-10-12 15:47:30 +02:00
Niko1221 026d7cd4a1 metal: the MTP draft round in one command buffer; catch-up embeddings fixed
msl/mtp_chain.metal: mtp_pick (the pick through the draft vocabulary and its softmax probability) and mtp_embed_F
(the picked token's embedding row through mac-kern's unit decoders), so every draft step of a round runs in one
command buffer. At load the GPU embedding is checked against the host's dequant (max |diff| 0 on Q3_K and IQ3_S;
any difference falls back to a command buffer per step). STRATA_METAL_MTP_CHAIN=0 keeps the per-step path.

Fix: with accepted drafts (a > 0) draft 0's embedding overwrote the catch-up's row 0 before the GPU read it; draft
0's row now goes to memb_ row a. The dense attention's cell list is per step.

M5 Max, 200 tokens, --spec 4, greedy output equal to no MTP in every run: Q2_0 109.5 / 84.4 tok/s (was 101.4 /
80.0), IQ3_XXS 107.9 / 86.0 (was 101.5 / 82.8).
2026-10-12 15:07:25 +02:00
Niko1221 8bf827b940 metal: the MTP draft layer's BF16 matrices in Q8_0 (STRATA_METAL_MTP_Q8=0 keeps BF16)
Drafts only; the verify window decides every token. M5 Max, 200 tokens, --spec 4: greedy output equal to the
no-MTP runs on Q2_0 and IQ3_XXS, both prompts. Q2_0 101.4 / 80.0 tok/s (was 101.2 / 79.4), IQ3_XXS 101.5 / 82.8
(was 96.4 / 81.2).
2026-10-12 15:01:21 +02:00
Niko1221 b507277646 metal: the MTP drafter, the prompt path through the window, the PLE block and the Q8_0 HC read on the GPU
- MTP (src/core/mtp.cpp hook under STRATA_GPU_METAL: load / bind / prefill / draft / draft_first): the draft layer
  of mtp.hpp on mac-kern's kernels, from the MTP GGUF (tools/mtp_pack.py, beside --mtp's rt dir; the F32 norms
  folded to 1 + w as tools/mtp_rt.py does): input branches (msl/mtp.metal: rms, strided xprep, stream combine),
  the three HC reads, K/V and indexer keys through qsa_prep into its own cache, dense attention over the last
  2,051 cells, the MoE (fused gate_up experts), the final mixer and the head over data/draft_vocab.bin's subset
  (STRATA_METAL_DRAFT_VOCAB=full: the whole head).  One command buffer per draft step (the next step's embedding
  is dequantized on the host).  Greedy output with MTP equals the output without it, token for token (Q2_0, two
  prompts, BF16 and Q8_0 HC); acceptance equals the HIP engine's on the same prompts (124 of 228; 104 of 291 vs 285).
- Prefill (src/prefill/prefill.cpp hook): init brings up the decode window, run reads the prompt through windows
  of 8 rows (no head) and feeds on_chunk (the MTP's K/V); draft_kv declines.  Prompt windows of 8 rows give the
  same tokens as one-token windows.  generate.cpp's own Metal prompt loop is gone again (--prefill auto as on the
  PC).  One window per process (the prompt path may bring it up before the Verifier).
- msl/ple.metal: the PLE block's norms, gate, conv and residual update on the GPU (same tokens as the CPU version).
- The HC read in Q8_0 by default (the owner's decision; STRATA_HC_Q8=0: BF16): the down / up / inject matrices
  quantized at load (290 matrices, 680 MB, 70 ms), read by gr_down_q8 / gr_up_q8.
- The encoded window is cached per (T, head, history parity) and only its positions are patched per window.
- f-mac-kern merged up to 4775d233.

M5 Max, Q2_0, greedy, 200 tokens: Q8_0 HC 85 tok/s without MTP; with MTP 101 tok/s (acceptance 0.54) and 79 tok/s
(acceptance 0.36, a prompt the drafter does badly on everywhere: HIP 71 tok/s there).
2026-10-12 14:55:46 +02:00
Niko1221 aea8d64bcc metal: prompt experts and QSA attention on matrix-unit register operands (v3), prompt_chain defaults to them
- moe_mm.metal: mm_gu3 / mm_down3 - weights decoded per lane straight into matmul2d's right-input cooperative tensor
  (single-simdgroup scope, no threadgroup staging or barriers in the K loop); W4<F> 4-value decoders for Q2_0,
  IQ3_XXS, IQ2_XXS, IQ2_XS, IQ2_S, IQ3_S, IQ4_NL (quant.metal's deq arithmetic)
- qsa_prompt.metal: qsa_attn_mm (S = Q K^T and P V as single-simdgroup matmuls, int8 K/V decoded into the right
  input; same partials as qsa_attn, so qsa_merge is unchanged), qsa_q_f16
- tests: qsa_prompt_parity, coop_layout (the cooperative tensors' element layout), moe_mm_parity --v3;
  prompt_chain PC_GU / PC_DN / PC_QSA switches (defaults v3 / v3 / mm)
2026-10-12 14:54:56 +02:00
Oleksandr Dovhoselets 85f839d80c hip: gfx103x creates the MTP drafter's side stream again (#2055)
#1240 stopped creating the drafter's branch stream and its two events on HIP: nothing uses them there, and an R9700
lost prompt speed with them. On gfx103x the stream's existence alone makes prompts read faster. RX 6800, Windows,
STRATA_HIP_PROMPT_F16=1, IQ3_XXS, two runs each: a 7.9K-token prompt at 798-808 tok/s with the stream and 584-596
without, a 30.4K-token one at 855-863 against 553-600; all of it is in the prompt path's "wait copy" phase. The two
events change nothing, so they stay out.

gfx103x creates the stream; other HIP cards do not, as before. STRATA_MTP_SIDE_STREAM=1 / =0 forces either. CUDA is
unchanged. Measured on one card under Windows only.
2026-10-12 14:34:18 +02:00
Niko1221 017a672ae1 bench: the server the bench starts runs without --expert-profile-save, so it never saves a profile learned from its short prompts over the user's (#2088) 2026-10-12 14:21:19 +02:00
Niko1221 682ae446a2 Merge f-mac-kern (Q8_0 HC default in the chain, prompt kernels) 2026-10-12 13:35:43 +02:00
Niko1221 4775d23372 metal: Q8_0 HC read the default in token_chain (STRATA_HC_Q8=0 = exact BF16); prompt chain, GDN prompt scan, fused HC prompt read
- token_chain: the HC read defaults to the Q8_0 copies through the 3-dispatch read (q8_3); STRATA_HC_Q8=0 selects
  the exact BF16 path (--hc still overrides)
- prompt.metal: route_topk, gr_epi_down/up, swiglu_h, moe_out, gr_norm_h (fp16 xn), gemm_hc_up (the HC up GEMM with
  the mixing epilogue; w_up rows interleaved by dq_f16's new perm field)
- gdn_prompt.metal: gdn_pre (parallel conv/norms/gates) -> gdn_scan_r (state scan, one barrier a token) -> gdn_post
- dense_mm.metal: DqArgs gains `perm` (4th field)
- moe_mm.metal: mm_scan zero-fills the unused simdgroup slots; indirect grids for gather/gate-up/down in meta;
  MM_PROBE bench constant (function constant 5: pipelines of mm_gu2 need it set)
- tests: prompt_chain (whole prompt in chunks, class breakdown), prompt_parity, gdn_prompt_parity; mm_bench tiles
2026-10-12 13:33:12 +02:00
Niko1221 cf00b0d031 metal: windows of several tokens (verify + commit of the kept prefix), experts read in place
- window.cpp: a window of 2..8 tokens runs the GDN steps without committing; the projections it feeds them are
  kept per layer, and commit(n) folds the kept prefix into the state (gdn_step over n tokens with commit, the same
  kernel: bitwise the window's trajectory) and turns the conv-history ping-pong.  K/V and indexer cells past the
  prefix are rewritten when those positions run again, before anything reads them; the PLE history keeps the n
  rows.  Checked: greedy output with suffix drafts (windows up to 4, 50 of 59 drafts kept) is the same token for
  token as one-token windows.
- generate.cpp (Metal only): --mmap-experts by default (the GGUF shards in place; the window reads them itself):
  the 31.6 GB expert arena is not loaded any more (RSS 74 -> 40 GB, the rest is the mapped shard)
- stubs.cpp regenerated (256 entry points left as stubs)

IQ3_XXS vs the CUDA engine (P1004, f-mac, same flags, --kv int8): 200 of 200 tokens equal on the capital
prompt, 124 on a story; following CUDA's tokens 3 of 200 picks differ, at margins 0.07-0.23 (near ties).
2026-10-12 13:25:08 +02:00
Niko1221 4468e0e62c Prompt loan: say when a chunk's loan is larger than the auto chunk's (#2090) 2026-10-12 13:20:17 +02:00
Niko1221 af6affb871 Prompt loan: a request's smaller chunk can need more slots than the auto chunk's region (a chunk at or below small_max gets 0.1.39's bigger ring), so the loan starts where the chunk needs it and a chunk that still cannot be lent is halved, instead of ending the engine (#2090) 2026-10-12 13:20:17 +02:00
Niko1221 a86aa74763 Tests: STRATA_TEST_PINNED_SHARE sets the pinned share the prompt ring rule reads (#2090 repro) 2026-10-12 13:20:17 +02:00
Niko1221 5d76056a4a metal: the engine runs on the M5 Max - the shared host loop over a Metal decode window (C3, first greedy answers)
The Metal build of `strata` is the shared host code (src/, unchanged except preprocessor-only Metal/arm64 branches)
over two Metal-only parts in metal/src/engine:
- window.cpp: the decode window, the one backend hook (Verifier::init/run/commit/copy_logits under
  STRATA_GPU_METAL).  It is mac-kern's chain on the model GGUF itself (shard 1 mmapped and wrapped no-copy, every
  weight read in place: no upload, no expert cache): HC reads, GDN/QSA mixers with their own state (recurrence,
  conv history ping-pong, int8 K/V, indexer), router + plan, routed and shared experts, combine, the final mixer,
  the LM head and the greedy pick, encoded as one dependency graph.  The embedding is dequantized on the CPU into
  the shared buffer; the PLE rows come from the shared table reader, their projections run on the GPU and the
  block's norms / gate / conv on the CPU between two command buffers.  One-token windows (--mtp-max-t 1) for now.
- host helpers copied from the CUDA kernel files the host code reads while it starts (format tables, sizes, path
  switches, the RoPE table/config); every other kernel entry point is a generated stub that stops with its name
  (stubs.cpp, tools/gen_stubs.py, from clang's AST of our headers).

Shared host code, all inside #if STRATA_GPU_METAL / __APPLE__ / __aarch64__ (the PC objects do not change):
- verify.hpp/.cpp: the hook (an opaque window pointer; init/run/commit/wait_commit/copy_logits hand over)
- generate.cpp: no x86 ISA refusal; a native pack without --prefill reads its prompt through one-token windows;
  the model shard handed to the window
- device.cu: the poison fill through the allocation's CPU view; pool_affinity_linux.hpp: a macOS branch (no
  pinning); expert_layout.cpp: no xgetbv asm on arm64
metal/include/metal_compat: cpuid.h (all zero on arm64), linux/mman.h (no hugetlb/THP: the fallback taken).

M5 Max, Q2_0, greedy, "What is the capital of France?": "The capital of France is Paris." - the same 36 first
tokens as the HIP engine (R9700, same flags) on that prompt and 39 on a story prompt, then near-tie flips
(margins 0.08-0.41 when following the HIP tokens); decode 74-75 tok/s.
2026-10-12 13:18:11 +02:00
Niko1221 7f3bed34ea Merge f-mac-kern (prompt-path probes, grouped expert GEMM, dense prompt GEMM) 2026-10-12 13:05:00 +02:00
Niko1221 773b44b922 metal: prompt path - MPP matrix throughput probe, grouped routed-expert GEMM, dense prompt GEMM
- kernels/mm_bench.metal + tests/mm_bench: M5 Max MetalPerformancePrimitives matmul2d fp16/bf16 62-65 TFLOP/s
  (64x64 tiles), fp32 15, simdgroup_matrix half 14.
- kernels/moe_mm.metal: deterministic GPU plan (block histograms, scan, stable placement; padded per-expert tiles),
  activation gather to fp16, mm_gu2 (gate+up+SwiGLU) / mm_down2 with weights dequantized (ref_quant arithmetic)
  into threadgroup memory and matmul2d in multiply_accumulate mode, mm_combine. tests/moe_mm_parity: Q2_0 and the
  IQ3_XXS-pack formats vs a reference with the same fp16 operands (1e-6..4e-5; vs exact float 2e-4..5e-4).
  T=2048, 512 experts, per layer: Q2_0 8.0 ms = 25 TFLOP/s = 3.9 us a token (~5,300 tok/s experts only);
  IQ3_XXS gate/up + IQ4_NL down 14.5 ms. The tile idea (dequantized weights from threadgroup memory under matmul2d)
  follows yibie/strata-mlx's tile_matmul (MIT); the code is ours.
- kernels/dense_mm.metal: dq_f16 (any dense format to fp16 once a chunk), act_f16, gemm_f16 (MPP): 64-65 TFLOP/s
  on the GDN/QSA shapes for 2048 tokens, dequantization ~4% of it; tests/dense_mm_parity (12 formats).
2026-10-12 13:03:25 +02:00
Niko1221 e4f80af46d Merge f-mac-kern (the Metal kernel tree) into f-mac-compat
metal/CMakeLists.txt holds both: mac-kern's runtime face, kernels and parity programs as they are, and the device
runtime + the engine build (taken from ../src through include/metal_compat) when METAL_CPP_DIR is given.
runtime_hello is kept out of the kernel tree's test glob.
2026-10-12 12:47:00 +02:00
Niko1221 ac36e3d4c0 metal: Q8_0 HC through the 3-dispatch read (gr_down/gr_up templated on the format) - the best HC variant
- gr.metal: gr_down_f<SG, KS, F> / gr_up_f<F> for BF16 (the old names) and Q8_0 (gr_down_q8_*, gr_up_q8);
  tests/gr_parity GR_Q8=1: vs double on the dequantized Q8_0 weights, 1/3/8 tokens, M5 Max and M4 pass.
- token_chain --hc q8_3. M5 Max, --fuse --graph, interleaved, 2 rounds: Q2_0 1 token 11.62 (BF16) / 10.59 (Q8_0,
  2 dispatches) / 10.38 ms (Q8_0, 3); 3 tokens 16.78 / 17.21 / 16.24-16.31. IQ3_XXS 1 token 12.85 / 11.87 / 11.68;
  3 tokens 17.88 / 18.59 / 17.47-17.51. The 2-dispatch read's gain was all Q8_0; its kernels are slower than the
  3-dispatch ones at windows. M4 HC read: Q8_0 85 us vs BF16 141-144 us.
2026-10-12 12:44:42 +02:00
Niko1221 5f18e8dcf8 metal: gemv_pair (shared expert gate + up + SwiGLU in one dispatch), raw-activation Q2_0 GEMV; pair measured slower
- gemv.metal: gemv_pair<F1, F2> for the packs' gate/up format pairs (tests/pair_parity: 8 pairs x 1/3/8 tokens vs
  double, 1.4e-7..2.6e-7) and GV_SET(T_Q2_0R).
- token_chain CHAIN_PAIR=1: interleaved A/B, 3 pairs, Q8_0 HC --fuse --graph: 10.60-10.61 ms without vs 10.71-10.72
  with (3 tokens 17.23-17.25 vs 17.31-17.33): two concurrent GEMVs and the SwiGLU win; opt-in only.
2026-10-12 12:33:59 +02:00
Niko1221 4e5ea96d23 metal: persistent-kernel probe (grid barrier between phases): correct only with device-scope fences, not faster
kernels/gridbar.metal + tests/gridbar_bench: phases of a streaming read separated by an atomic grid barrier vs by
dispatch boundaries (M5 Max). Without atomic_thread_fence(device, seq_cst) the phases read other threadgroups'
stale writes; with it 0 stale reads. Speed: 4.5 MiB phases 10.3 us (10 threadgroups) vs 9.9 us a dispatch, 30-34 us
with 20-40 threadgroups; 0.5 MiB phases 1.5 vs 2.2 us. Not pursued.
2026-10-12 12:30:33 +02:00
Niko1221 f1c5a6772c macOS platform guards in the host files (C2): every host source under src/ now compiles for Metal
All under __APPLE__ / STRATA_GPU_METAL, so the Linux and Windows code is unchanged:
- direct_file.cpp: no O_DIRECT on macOS; F_NOCACHE after open keeps the reads out of the buffer cache
- memory.cpp: F_RDADVISE is the read-ahead hint where posix_fadvise(WILLNEED) is used
- expert_source.cpp: available memory from host_statistics64 (free + inactive + purgeable); the posix_fadvise of a
  released expert layer is skipped (the madvise before it already released the mapping)
- generate.cpp: <sys/sysmacros.h> is not on macOS (major/minor come from <sys/types.h>); the CUDA toolkit mismatch
  check is CUDA's
- vmm.cpp: the cuMem* virtual memory stays CUDA's (Metal takes the HIP branch: elastic K/V off)
- prefill.cpp: std::max<size_t> where size_t and uint64_t meet (the same type on Linux, distinct on macOS)
2026-10-12 12:29:27 +02:00
Niko1221 ae84bcdc14 metal: GDN step templated on the row blocks (8: no gain), token_chain expert tiles by environment
- gdn.metal: gdn_step_t<IB>; gdn_step8 (1024 threads, 16 state rows a thread) passes and is not faster than
  gdn_step (16.3 vs 16.4 us commit, n=1): the state write after the compute is what a commit adds.
- token_chain: CHAIN_GU / CHAIN_DN / CHAIN_DN4 select the routed-expert tiles; measured in the chain (Q8_0 HC,
  --fuse, --graph): gate/up 32,1,4 stays; the Q2_0 down 8,1,4 over 8,2,4 (10.63 vs 10.67 ms, 3 tokens 17.23 vs
  17.50 ms), now the default.
2026-10-12 12:27:11 +02:00
Niko1221 a691e31b27 metal: QSA top-k v2 (parallel digit scan, range emission); attention variants measured
- kernels/qsa2.metal: qsa_topk2 - the same selection (ids exact at contexts 700..33000): the radix digit found by a
  parallel suffix scan of the 256 bins, cells emitted from contiguous block ranges after one scan. 23 -> 8.2 us at
  8K, 54 -> 14.5 us at 32K; token_chain (Q8_0 HC, --fuse, --graph, interleaved): 8K 11.40 -> 11.00 ms,
  32K 11.90 -> 11.27 ms.
- qsa_attn2 (chunks of 32, head groups) and qsa_attn3 (lane per cell for q.k): both pass, neither beats qsa_attn at
  the full budget (21-24 us, nearly independent of the cell count: a latency chain); QSA_ATTN selects, default 1.
- Read yibie/strata-mlx's OPTIMIZATION_RECORD/ROADMAP (MIT) before this round: its finding that merging kernels cut
  the kernel count 43% for 15% of the time matches ours.
2026-10-12 12:21:22 +02:00
Niko1221 79b98c82b7 metal: simdgroup-matrix GEMV for windows (exact, measured slower; kept as a reference path)
kernels/mma.metal: 8-row tiles dequantized with ref_quant's arithmetic into threadgroup memory, x loaded transposed
from device memory, simdgroup_multiply_accumulate; tests/mma_parity: 12 formats pass vs double, every token of a
window bitwise a one-token call. Speed (M5 Max): 60-190 GB/s for 1, 3 and 8 tokens alike, against the per-lane
GEMV's 400-595 GB/s at 1 token and 70-230 at 8: the dequantization through threadgroup memory (~8 B a weight) is
the limit. Only Q2_0 at 8 tokens is faster (115 vs 126 us). Not used by token_chain.
2026-10-12 12:15:03 +02:00
Niko1221 dca7c38405 metal: GDN step writes the prepared activations of its output; token_chain --fuse / --fold-comb
- gdn.metal: GdnArgs.plane: the step writes y as the raw plane plus the other planes and the per-16 sums, so the
  out projection needs no prep dispatch.
- gr2.metal: gr_down3 can form bo as the MoE combine itself (GrArgs3.comb).
- token_chain --fuse: the GDN prep in the step, no QSA score/top-k dispatch while the context fits the 2051 budget.
  Q8_0 HC, --graph: 10.71 -> 10.49 ms (1 token), 17.13 -> 16.86 ms (3); BF16 2-dispatch 11.91 -> 11.65 ms.
  --fold-comb (the combine in the next HC read) is slower: 10.49 -> 11.22 ms; off.
2026-10-12 12:08:33 +02:00
Niko1221 3c6eeb0049 metal: two-dispatch hyper-connection read (per-stream norm in the down kernel), Q8_0 HC option
- kernels/gr2.metal: gr_down3 (grid row blocks x streams: each threadgroup forms its stream's R', norm and xn in
  threadgroup memory, writes per-stream partial dots; R' ping-pong, never in place) and gr_up3 (lo from the
  partials, xn on the fly); BF16 or Q8_0 weights. tests/gr2_parity: both formats vs double on their own weights,
  prepared planes bitwise = xprep; Q8_0 moves the read's output by 1.2e-3 relative.
- ref_quant: quantize_q8_0 (ggml's reference rounding), used for the load-time Q8_0 copies (STRATA_HC_Q8's form).
- token_chain --hc 3|2|q8. M5 Max, Q2_0, --graph: 1 token 12.00 / 11.91 / 10.71 ms; 3 tokens 17.21 / 18.02 /
  17.13 ms.
2026-10-12 12:04:34 +02:00
Niko1221 bf4b79abda metal: the Metal runtime behind a CUDA-name compat layer (the HIP model), so the host files build for Metal unchanged
MAC-PLAN Phase 1, compat design (the alternative to renaming the host calls, f-mac-design S1-S4).
metal/include/metal_compat goes first on the Metal build's include path, as include/strata/hip_compat does on HIP:
its cuda_runtime.h gives the ~70 CUDA runtime names of the Phase 1 inventory (types, constants, calls) on Metal,
each forwarding to metal/src/gpu/runtime.cpp (metal-cpp: gpuAddress device pointers in one residency set, streams =
queue + command buffer + shared-event timeline, graphs = recorded dispatch lists), and immintrin.h gives _mm_pause /
_mm_sfence on arm64.  The CUDA / HIP / SYCL builds never see metal/.

Shared files: four preprocessor conditions also exclude STRATA_GPU_METAL from CUDA-only blocks (the cuMem*
segmented expert cache, the STRATA_VERIFY_NODES graph listing, the MTP stream priority, cudaInitDevice of the remote
experts); nothing else in src/ changes, so the PC objects are byte-identical.

On the M5 Max: runtime_hello passes with the unchanged src/core/graph.cpp, and graph, expert_cache, weights,
native_head, native_dense, layer, verify, mtp and session compile for Metal as they are (-fsyntax-only); prefill,
expert_source and generate stop only at macOS platform items (std::max of size_t vs uint64_t, posix_fadvise /
_SC_AVPHYS_PAGES, sys/sysmacros.h).
2026-10-12 11:53:32 +02:00
Niko1221 99614041ba metal: GDN commit writes the conv history to a second buffer; GEMV parity on real GGUF tensors
- gdn.metal: a q/k conv channel is read at the start of three threadgroups (value heads h, h + 16, h + 32) while
  its owner wrote it back in place at its end: on the 10-core M4 the threadgroups run in waves and the later ones
  read the new history (gdn_parity failed there, passed on the M5 Max where all 48 start together). The committed
  history now goes to hist_out (the caller swaps); gdn_parity checks determinism too. Passes on both Macs.
- gemv_parity --gguf: one real tensor per format of a GGUF (experts: expert 0) vs double; Q2_0 file: 11 formats
  pass, rel L2 8e-8..2.7e-7.
2026-10-12 11:51:56 +02:00
Niko1221 e03c0fa43b metal: whole-model decode step on real GGUF weights (token_chain), dependency-graph encoding
- src/gguf_lite: a minimal GGUF v3 reader; the file is mmapped and wrapped no-copy as one MTLBuffer.
- moe.metal addresses experts by gate/up/down offsets and strides (a pack blob or the GGUF's three tensors).
- kernels/glue.metal: the shared expert's SwiGLU (prepared activations) and the combine with its sigmoid gate.
- tests/token_chain: every layer of the model with its own formats, all kernels in one command buffer.
  M5 Max, Q2_0, context 1000: 12.83 ms a token (serial encoder), 12.01 ms with --graph (a concurrent encoder,
  barriers only at true dependencies); a 3-token window 18.42 / 17.23 ms. Bound: 7.27 ms.
- mtl_rt: run_graph (concurrent encoder, Dispatch::barrier).
2026-10-12 11:48:27 +02:00
Niko1221 6d94e2e409 metal: QSA decode (prep, block scores, top-k, split-K attention, gated merge) and the greedy sampler
- kernels/qsa.metal: q/k RMSNorm + NEOX RoPE (host table), int8 KV append (fp16 scale per 64), the indexer's raw
  tail / pooled block keys / dead key, ReLU-sum block scores with the +1e9 tail, a cell-level radix top-2051
  (ties to the lowest cell, ascending), split-K GQA attention over the selection, log-sum-exp merge * sigmoid(gate)
  written as prepared activations; tests/qsa_parity stage by stage (ids exact; contexts 700..9001).
- kernels/sample.metal: two-stage argmax, ties to the lowest id; tests/sample_parity.
2026-10-12 11:38:40 +02:00
Niko1221 89edfd7c3b metal: fused GDN layer step (conv, L2 norms, gates, delta rule, output norm) for a window, commit/verify
kernels/gdn.metal: one threadgroup per value head, the head's state in registers across the window's tokens;
commit writes state + conv history back, verify does not; tests/gdn_parity vs double (1.7e-7), verify leaves the
state untouched, the first m outputs of a longer window are bitwise a window of m (the fold).
2026-10-12 11:31:39 +02:00
Niko1221 dffa167fcd metal: hyper-connection read, router tail + plan, expert kernels specialised per group size
- kernels/gr.metal: gr_norm (folds the previous write, per-stream RMSNorm), gr_down (down + inject rows, silu/hc
  epilogue, K split), gr_up (gated mean over the streams, writes the prepared activations); tests/gr_parity vs double.
- moe.metal: moe_route = native_router.cu's softmax/top-10/renormalisation and the plan in one threadgroup
  (tests/route_parity: ids exact incl. ties, weights 2e-7); moe_gu/moe_down switch once per threadgroup into a body
  specialised for the group's entry count (the predicated 8-way loop cost 2x); Q2_0 down reads raw activations
  (T_Q2_0R) so no prep dispatch is needed.
- mtl_rt: warm() before timings (the GPU starts at idle clocks).
2026-10-12 11:27:33 +02:00
Niko1221 7b022f1fb8 metal: dense GEMV for every pack format, prepared activations, window-size specialisation
- kernels/units.metal: per-format unit decoders (Q2_0, Q3_K..Q6_K with the mask trick, IQ4 via a byte->half2
  codebook table, BF16, generic for the rest) and one combine for all; xprep writes the pre-scaled activations
  and per-16 sums once per input vector.
- kernels/gemv.metal: y = W x for 1..8 tokens in one pass over the weights, NTOK a function constant, optional
  K split across simdgroups; tests/gemv_parity: parity vs double for 12 formats x 20 tile shapes, every token of
  a window bitwise equal to a one-token call, and the bench on the packs' projection shapes.
- moe.metal on the same decoders; mtl_rt compiles with safe math by default (no reassociation; measured free).
- tests/alu_bench: instruction rates (fp32/fp16 FMA, int, convert, threadgroup/device/constant gathers).
2026-10-12 11:17:02 +02:00
Niko1221 8b271f24b5 STRATA_TRACE=2: wait for the device at each startup mark and name the first step after which it reports an error (#2013) 2026-10-12 11:05:03 +02:00
Niko1221 665d484236 SYCL: resident_stage_swaps copies the evicted expert back to its exchange buffer again (#2014)
The dpct migration had dropped the cudaMemcpyAsync D2H and the stream sync, so the resident RAM mode with adaptive swaps committed
whatever the exchange buffer held as the evicted expert (lost expert, wrong weights on a later CPU read). STRATA_CHECK_SWAPS=1 is a
test aid: it compares each staged buffer with the model file and audits the RAM copy at the end of a run.
2026-10-12 11:05:03 +02:00
Niko1221 ad9eb89079 metal: standalone Metal kernel tree - runtime face, bandwidth/dispatch probes, grouped routed-expert kernels
metal/ is its own CMake project (macOS only), nothing in src/ or include/ changes. MSL is compiled at run time
(the Command Line Tools have no offline metal compiler) with ggml-common.h prepended for the i-quant grids.

- src/mtl_rt.*: a C++ face over Metal (buffers, pipelines with function constants, serial/concurrent encoders,
  indirect dispatch, indirect command buffers, GPU timing).
- src/ref_quant.*: CPU reference dequantizers for Q2_0, Q4_0, Q5_0, Q8_0, Q3_K..Q6_K, IQ2_XXS/XS/S, IQ3_XXS/S,
  IQ4_NL/XS, BF16, F16; checked bitwise against gguf-py (tests/ref_dump + tools/check_ref.py: 17/17 equal).
- kernels/quant.metal: the formats as per-lane units (decode once, dot with every token of the window).
- kernels/moe.metal: moe_plan (top-k -> groups by expert, deterministic, writes the indirect grids), moe_gu
  (gate+up+SwiGLU, grouped), moe_down, moe_combine; tests/expert_parity: parity vs double and the bench.
- tests/rt_bench: M5 Max streaming read ~585 GB/s, ~0.85 us per dependent dispatch, ~170 us commit+wait.
2026-10-12 10:42:59 +02:00
Niko1221 0613cc00bc Stall report: an MTP draft wait is named (it read as the verify window before it); docs: the free VRAM moves after startup, and a stall in "request" can be the OS paging the parked conversation (#2049 #2065) 2026-10-12 10:39:47 +02:00
Niko1221 3804b43f19 Parking a conversation beats the watchdog: its checkpoint and K/V copies report progress, the stage is named, Windows counts hard page faults as file-tier activity, and the stall report and each request say how little VRAM is free (#2049 #2065) 2026-10-12 10:39:47 +02:00
Niko1221 798f3006bb Tests: STRATA_TEST_SLOW_COPY_US makes a parked conversation's checkpoint copy as slow as paged-out memory (for the #2049 repro) 2026-10-12 10:39:47 +02:00
Niko1221 905a60588b bench and monitor: name the GPUs the engine uses - mixed cards one by one in the report, the server's own card when it is not an NVIDIA one, the Intel reader first on the SYCL server (#2062 #2001) 2026-10-12 10:39:47 +02:00
Niko1221 17d8a171da CMake: STRATA_NATIVE_EXPERTS is defined with the other options, before the GPU section reads it, so the first configure registers the four native-expert tests (#2027) 2026-10-12 10:39:47 +02:00
Niko1221 6956f6052c setup: --calibrate with --model/--family tunes that installed model, an uninstalled one is an error, --calibrate with --setup/--check or nothing installed says it does nothing (#2036) 2026-10-12 10:39:47 +02:00
Niko1221 873a0d66b6 serve: a client that leaves while its pictures are downloaded, waiting for the turn or encoded stops the preparation: cancel exists before prepare() (#1999) 2026-10-12 10:39:47 +02:00
Niko1221 de603bb8bd serve: tool_call_recovery reads a declared tool's JSON call in a Markdown fence inside <tool_call> (#2037) 2026-10-12 10:39:47 +02:00
Niko1221 a683000875 serve: a quoted </tool_call> in a message is text, not the end-of-call token (#2026) 2026-10-12 10:39:47 +02:00
Niko1221 d320fecc85 serve: the adaptive overlap's off line printed (null) after the hint (a null reason went to %s) 2026-10-12 10:10:26 +02:00
Niko1221 d1ab65a18b setup: a BUILD.json is trusted only beside an engine binary of the source's version; a build that leaves the old binary is neither stamped nor installed (#2054) 2026-10-12 09:46:02 +02:00
Niko1221 0cf3d51030 ple: the slow-direct probe only warns on every platform (#2040: a SATA SSD tops out under the NVMe-calibrated 15K rows/s bar and mmap was 7x slower there); STRATA_PLE_AUTO_MMAP=1 keeps the 0.1.42 switch 2026-10-12 09:44:07 +02:00
Krypto-Whitehat 661ff29339 STRATA_ADAPT_OVERLAP: opt-in on every backend (RTX 5090 Laptop, Linux CUDA: 84.6 vs 106.6 tok/s decode median with it, 5 generations of 256 tokens from one build); log the state in both directions
Linux CUDA had it on by default since 0.1.43, measured on an RTX A4000 (+5.5..8.3% decode) and a Tesla P100 (+4.4%). An RTX 5090 Laptop with a native IQ3_XXS pack and --expert-cache-per-layer decodes 21% slower with it, and the overlap is the default only there. The switch is now =1 turns it on everywhere, and the startup log names the state (with the reason when it cannot run), so a decode-rate drop is not the only way to see it.

Unchanged: the copy path, the gate predicates and the tokens (same tokens with or without it).

Fixes #2010
2026-10-12 09:43:30 +02:00
Niko1221 b59e69c7bb gfx12 (RDNA4): STRATA_HC_Q8 is on by default (STRATA_HC_Q8=0 or STRATA_GFX12_DEFAULTS=0 turns it off; other cards unchanged). Droppable: R9700 decode +2.5 to +4%, KL 0.0003-0.0010 over the noise floor 2026-10-12 09:40:08 +02:00
Niko1221 ee9263ee38 sycl: NativeDense::hc_q8_requested() is declared by the shared header since STRATA_HC_Q8; the port's file defines it (the anonymous helper of the same name was hidden by the member, link error) 2026-10-12 08:01:06 +02:00
Niko1221 24d972e542 Multi-GPU: draft layer on the first card in the pipelined decode (default on gfx12), pipeline default from two stages, 8192 prompt chunks on a split, PcieAuto in the pipelined loop
On 2x/4x R9700 the drafter's chain and the last stage's window shared a card and slowed each other (window 13 -> 27 ms) in most engine starts; the draft layer now loads on the first card (STRATA_MTP_STAGE0=0 keeps the old place). Exact flags, tokens identical: 2 cards code +21%, 3 cards +19%, 4 cards +22% over the serial loop. A split reads prompts in 8192 chunks (STRATA_SPLIT_CHUNK16K=1 keeps 16384): 16K prompt +36..53%, 32K +18..29%, same tokens. STRATA_PCIE_AUTO_SPLIT=1 now also runs in the pipelined loop (opt-in).
2026-10-12 07:40:49 +02:00
Niko1221 2d47caa44a STRATA_HC_Q8: the prompt path's scratch is ordered by an event across streams (batch serving), the session read has its own pair 2026-10-12 07:40:49 +02:00
Niko1221 446bec512d STRATA_HC_Q8: the dequantization scratch of hc_bf16_view is allocated at load (per device), never on first use, so a graph capture cannot meet an allocation 2026-10-12 07:40:49 +02:00
Niko1221 b60aab1ba2 STRATA_HC_Q8=1: no bf16 copy of the layers' hyper-connection down/up projections (single GPU): they are quantized to Q8_0 from the pack file at load and left out of the arena; the prompt path and the single-token read dequantize a half's two matrices into a per-stream scratch 2026-10-12 07:40:49 +02:00
Niko1221 485984fdb8 fused_gr_bench: hash of the Q8 read's outputs and q8_1 image 2026-10-12 07:40:49 +02:00
Niko1221 0a379a1f62 STRATA_HC_Q8=1 on a bf16 pack: the hyper-connection down/up projections are quantized to Q8_0 on the GPU at load and read by the Q8 multi read; Q8 up kernel with 32-column blocks that quantize their own q8_1 group (HIP); bench: cold Q8 arm and Q8-vs-bf16 error check 2026-10-12 07:40:49 +02:00
Niko1221 34458600ab gfx1103 (Radeon 780M) joins the gfx11 WMMA kernels: decode x1.53, same answers
gfx1103 was missing from the gfx11 matrix-core lists, so the 780M ran the portable verify-window and prompt kernels. Added to the
compile-time lists and gfx_arch_is_gfx11_wmma(). Radeon 780M, Q2_0, 5 interleaved pairs: decode (code) 11.96 -> 18.25 tok/s,
same token ids; prompts unchanged. hip_prefill_wmma_gemm_parity passes on gfx1103 (3520 cases). Identity gate (defaults off,
mg_norepeat 10/10 against the portable build, exact_pp 4K/20K residual dumps identical).
2026-10-12 07:40:49 +02:00
Niko1221 24efc6e333 sycl/src/kernels/xmx_int8_bench.cpp: DPAS int8 vs FP16 expert GEMM microbench (standalone, not in the build) 2026-10-12 07:40:49 +02:00
Niko1221 3d6f1718ff SYCL: --expert-profile-save from the device routing counts under STRATA_VERIFY_NO_HOST (opt-in)
The serve path counts every routed expert on the device when a save path and a mirror exist; the saved ranking mixes the counts with the start ranking (prior worth 800k routed entries, STRATA_PROFILE_PRIOR_ENTRIES). Exact: placement is fixed under NO_HOST, the file applies at the next start. B70, IQ3_S: code +13..19% vs the xe default profile, prose -18%.
2026-10-12 07:40:49 +02:00
Niko1221 88892dbde4 Version 0.1.43.1: project version and the setup minimum engine 2026-10-12 02:12:36 +02:00
Niko1221 7bab660bf8 Prompt path: every pageable async host-to-device copy goes up through pinned bounce slots (#1996)
0.1.43 moved the QSA step records and the batched token ids to a pinned buffer (#1712). A 4-hour multi-slot load on 2x RX 7900 XTX (parallel 4, vision plus long
prompts, layer split) still faulted after 31 minutes, with the picture rows, the draft tokens and bounds and the non-mapped routing tables still going up from
caller memory. PinnedRing (include/strata/core/pinned_ring.hpp) is a ring of four pinned slots with one event each: the bytes are copied into the next slot after
the copy that last read it is done, the DMA runs from the slot, and the caller may change its source on return. No pinned RAM (or STRATA_TEST_PAGEABLE=1): the
copy is made from the caller's memory and the stream is waited for. A failed upload is returned and reported.

Moved onto it: the picture's embedding rows (gathered per run into one slot), the draft K/V step's tokens and bounds, the PLE rows' pageable fallback, the
non-mapped branch's routed-id download and slot/src/bounds uploads, the peer device's src and bounds tables, and the drafter's prompt records (mtp.cpp).
Copies from pinned arenas and cudaHostAlloc buffers are unchanged. Same bytes reach the GPU, so answers are identical.

The analysis of which copies are still pageable, and the bounce-slot-per-event idea, are mantovaniluca91's (patch C on #1712). This is our own form of it.
2026-10-12 02:11:56 +02:00
Niko1221 38032f546e Watchdog: a file tier busy within the last 10 s keeps the I/O allowance (a thrashing host has silent seconds), and Windows measures it too (bytes read + page faults); before, a 46 GB box's 20K prompt was stopped after ~90 s of page-ins (#1407 #1984 #1971) 2026-10-12 01:26:31 +02:00
Niko1221 ccc4be9165 bench: report only the GPUs the engine uses (#1985)
collect_machine listed every nvidia-smi card. It now takes the bench's --gpu, else the config's gpu (or --gpu in its args); with none given it names the one card the server reports instead of all of them.
2026-10-11 23:44:07 +02:00
Niko1221 c7838c529f serve: honour a failing before_load hook (503 + Retry-After), configurable timeout, /unload?wait=1 (#1997)
ensure_loaded logged 'loading anyway' for a before_load command that failed and co-loaded two models onto one GPU. A non-zero exit or a timeout now leaves the model unloaded and answers 503 with Retry-After (before_load_ignore_failure restores the old behaviour); before_load_timeout_s sets the 120 s limit; POST /unload?wait=1 (or wait=<s>) waits for the running turn instead of answering busy.
2026-10-11 23:44:07 +02:00
Niko1221 c5fa1b58a7 serve: an engine refusal of a BGEN slot (#1994) tries another slot instead of a permanent 400
The engine answered 'ERR BGEN: no such free slot' when its view of a slot differed from the server's; the server turned the ERR into an HTTP 400 and the conversation, drawn to the same slot by its held prefix, got it again on every turn. Now the refused slot is parked (busy, no owner) for SLOT_PARK_S, the request waits for / takes another slot, and after BGEN_REFUSALS_MAX refusals it ends with a retryable 503.
2026-10-11 23:44:07 +02:00
Niko1221 00e7d0c4cc SYCL: refuse STRATA_VERIFY_NO_HOST when a later layer-split stage is short of VRAM (#1980); setup_intel writes STRATA_STAGE_TRIM=1 for a split
The host mirror and the unmirrored count cover the first stage only; a later stage whose cache lacks experts has no mirror entry and, under NO_HOST, no host answers for them (device lost at the first verify window on 2x Arc Pro B60). The start now refuses with the existing wording, or logs the count when NO_HOST is off.
2026-10-11 23:26:45 +02:00
Niko1221 62497bff92 ple: --ple-io mmap prompt gather prefetches its rows a window ahead; on Windows the slow-direct probe warns and keeps direct unless STRATA_PLE_AUTO_MMAP=1 (#1984 #1971)
The mapped gather_batch took 16 serial demand faults per token from a cold table with no progress mark; the first chunk of a prompt only has layer 0 to hide it behind, so the stall watchdog stopped the engine. Rows are now hinted 4096 at a time (PrefetchVirtualMemory / MADV_WILLNEED). Answers are unchanged. The 0.1.42 auto-switch to mmap on Windows is opt-in until it is measured there.
2026-10-11 23:26:44 +02:00
Niko1221 9ba1d8deb6 docs: STRATA_ADAPT_SIGNAL 2026-10-11 23:00:49 +02:00
Niko1221 25e0a2ef79 Adaptive overlap: tell each layer's landing with a stream-ordered copy into pinned memory, not a host function
The per-layer host function made the overlap depend on the driver's callback thread being scheduled: with the pool's
workers spinning on every other CPU it still cost 7 ms per window on a 20-core desktop even with the thread on all CPUs
(RTX 3060, Core Ultra 7 265: 46.5 tok/s with the warmed callbacks against 56.5 with the overlap off). The copy stream now
ends each layer's copies with a 4-byte device-to-host copy of the layer number into a pinned int the gate polls; same stream
order, no host thread. STRATA_ADAPT_SIGNAL=host brings the host functions back. Swaps, residency and answers are unchanged.
2026-10-11 23:00:41 +02:00
Niko1221 0e20d9aee9 Start the GPU host-callback thread before the host is pinned, by default (STRATA_ADAPT_CALLBACK_WARMUP=0 turns it off)
On Linux the CUDA (and HIP) runtime creates its host-callback thread lazily, at the first cudaLaunchHostFunc, and a new
thread inherits the creator's CPU mask. The decoding host pins itself to one CPU (SessionLoopScratch::init), so a thread
created after that - which the adaptive overlap's per-layer callbacks did - ran on the host's CPU and fought the host's
spin-wait: ~1000 us instead of ~4 us per callback, decode 2-4x slower with STRATA_ADAPT_OVERLAP on (#1964, #1975).
oal's warm-up (one no-op callback + sync before ExpertPool) is now unconditional on Linux; the answers, swaps and
residency are untouched. Windows CPU Sets are per thread and not inherited, so Windows is unchanged.
2026-10-11 21:05:23 +02:00
Olav Lindekleiv c08fd90262 generate: warm CUDA callbacks before host-core pinning (opt-in) 2026-10-11 20:59:23 +02:00
Niko1221 7695859aa1 Canonical Q2_0 pack: the measured PCIe share is opt-in on Windows (STRATA_PCIE_AUTO_CANON=1); RTX 5070: code +2.5%, a short answer -3.3%, 5 pairs 2026-10-11 16:19:59 +02:00
Niko1221 7c035d729f STRATA_ADAPT_OVERLAP: opt-in on Windows (RTX 5070, Q2_0: story -2.6%, code -2.1% with it, 5 pairs; IQ3_XXS neutral); Linux CUDA keeps it on 2026-10-11 14:34:41 +02:00
Niko1221 0d0f106d5a docs/MULTI_GPU.md: the default pipeline's tokens are the serial loop's up to CPU rounding (4x R9700, default flags: 10 of 10 prompts matched over 160 tokens) 2026-10-11 14:08:31 +02:00
Niko1221 60abf63edc HIP layer split: the route tail skip's default stays off from 60% of the experts cached (90% elsewhere); measured on 2x R9700: Q2_0 story -6.2% at 70%, -1.8% at 60%, IQ3_S about 0 at 60% 2026-10-11 12:35:58 +02:00
Niko1221 003ea8c678 Merge PR #1892 (lask3802): the --serve NaN guard (non-finite head logits drop the caches and re-read from token 0; STRATA_NAN_GUARD=0 off); bitwise identical otherwise, cost under 0.2% 2026-10-11 12:01:30 +02:00
lask3802 f332a85570 Non-finite logits (#879): a guard with self-healing
Rarely a window's logits become NaN and the reply degenerates into token 0
('!') repeated (#606); the poison sits in the conversation's K/V and
recurrent state, so with the prompt cache every later turn stays poisoned
until it is read again from token 0. The q8_1 clamps (2b726ba, f6601bf,
7a0e302) remove the overflows found so far; this guard catches whatever
cause is left, and drops the poisoned state instead of serving it again.

On by default, as a fix: STRATA_NAN_GUARD=0 turns it off. It only reads
flags, so an answer without a NaN is the one the engine gives with the
guard off (compared byte for byte on a GPU, below).

Engine:
- every verify-window graph checks its head logits beside the greedy pick
  (logits_nonfinite_rows: 16 blocks a row, one flag word each, into mapped
  memory); Verifier::note_nonfinite reads them after the sync the window
  already does (run, run_slot_rows, batch_poll, pl_finish). No extra sync.
  With STRATA_NAN_GUARD=0 no kernel is recorded.
- --serve: a flagged window emits none of its tokens, one stderr line names
  the position and row, and the request ends with `DONE ... nonfinite` (a
  batch slot: `BDONE <slot> <n> nonfinite`; an admission: BADM <slot> 0).
  The next request first drops the live session, every checkpoint, every
  parked conversation (ConversationCache::clear) and every idle slot, and
  reads its prompt from token 0; a slot still running then finishes its
  reply and is not kept as a cache after it. A request that ends on it does
  not keep its conversation live (#1620's cancelled-read path is skipped
  for it).
  Covered: the serial decode loop (one GPU or a layer split), the
  --pipeline-windows decode loop of a layer split, the prompt's short tail
  (read_windows, and read_windows_pl with --pipeline-windows), and both
  batch-slot loops (run_slot_rows, and the --batch-groups pipeline's
  batch_poll). Not covered: the one-shot command line (no --serve) and the
  SYCL port in sycl/, which has its own verify.cpp and generate.cpp.
- STRATA_NAN_INJECT=<n>[,<n>...] (debug): the n-th window the guard checks
  reports row 0 as non-finite.

Server: EngineNonFinite on that finish. A request that has sent nothing yet
is sent again once (its usage is the retry's: the failed pass's DONE is
dropped); a reply that had started ends as "length"; a second fire on the
retry ends with an error (503 before an answer, an error event in a
stream). With replicas the router forgets what that replica held.
repeat_stop_tokens stays as the backstop.

Checks: serve tests (python -m unittest discover -s serve -t . -p
"test_*.py": 697 tests, OK, 11 skipped; NonFiniteLogits,
test_nonfinite_in_batch_mode and test_nonfinite_forgets_the_replica are
new). ctest with CUDA_VISIBLE_DEVICES=-1: 24 pass (conversation_cache_test
with clear() among them), 3 skip for want of a GPU, and the 43 GPU parity
tests were not run on a GPU. Built for CUDA 13.0 on Linux (GCC, sm_75 +
sm_86); generate.cpp, verify.cpp and verify_kernels.cu compile with
MSVC 2022 + CUDA 13.0, and conversation_cache_test and conv_cache_test
pass there; built for HIP (ROCm 7.0, gfx1100, compile only) and SYCL
(oneAPI 2026.1.1; it takes only the new declaration in verify_kernels.hpp
and the new inline ConversationCache::clear(), and calls neither).

On a GPU (RTX 3080, RVN IQ3_S, strata.service's one-GPU config):
- Answers, guard on vs STRATA_NAN_GUARD=0, at fixed expert sets
  (--pcie-frac 0 --adapt-every 0 --adapt-swaps 0 --mtp-max-t 1
  --suffix-draft 0, STRATA_IQ_MT_MIN=1 STRATA_PREFILL_CPU_SHARE=0), a chat
  replay of 2 x 4 turns on a 16K-token system prompt: byte-identical in 3
  pairs (one with STRATA_ROUTE_TAIL_SKIP=0, one with STRATA_SH_STREAM=0),
  and two guard-on runs 8 of 8. One more guard-off run differed from every
  other run from its first answer, and a second guard-off run matched the
  guard-on runs: a difference between runs of this config, not the guard.
- Cost, Nsight Systems: logits_nonfinite_kernel 424 launches, 4.77 us on
  average (7.78 us at most), 2.0 ms against 21.6 s of decode: 0.009%.
- STRATA_NAN_INJECT=1,60: the first window of a new chat flagged, the
  server sent the request again from token 0 and the client saw one normal
  answer; the 60th, mid-reply in the next turn, ended that reply as
  "length" after 58 tokens; the turn after it reused 0 cached tokens and
  answered normally. The engine logged exactly the two injected windows.
2026-10-11 12:01:22 +02:00
Niko1221 248dbee5b8 Merge PR #1737 (Ethan): route-resident swap one warp per token; bitwise equal to the scalar kernel, opt-in STRATA_ROUTE_RESIDENT decode +1.6-2.4% (R9700 32 GB) / +5.7-7.8% (16 GB-eq) 2026-10-11 11:22:28 +02:00
Ethan 115f62b00a route-resident parity: the swap against a scalar reference
route_resident_k is one warp per token and the form it replaced walked all 512 experts on a single
thread.  Nothing in the tree checked that the two land on the same expert and leave the same ids,
weights and counters, and the option's whole justification is that it moves misses across PCIe and not
the model.

src/kernels/route_resident_parity.cu: 240 random cases over 1 to 8 tokens, a 40-84% resident table,
random rank windows, margins from -0.5 to 1.5, and half the cases rounding the logits onto a coarse
grid so the tie rule (the smallest expert index wins) is exercised.  Half the cases get the router's
own top-10 and half get ids with repeats, which is what the already-picked test is for.  The reference
is the spec written out plainly - a serial walk with the same comparisons - and not a copy of the
kernel this branch replaced; it runs on the device so that expf, and so the softmax bits, are the same
function on both sides.

ids and the four counters have to match bit for bit.  The weights are a softmax ratio and this
reference is a second compilation of it, so they are compared within 8 ulp and the worst seen is
reported; the kernel itself is bit-identical to the serial form it replaced, which was measured with
both kernels side by side in one translation unit.  A case that swaps nothing still has to leave the
weights untouched, which the sentinel they start from checks, and the test fails if no case swapped at
all.

    route_resident_parity: 240 cases, 205 with swaps (2004 swaps), 0 mismatches, weights within 6 ulp

Registered in ctest next to the other router parity tests, TIMEOUT 120.
2026-10-11 10:52:44 +02:00
Ethan 33fd01b413 route-resident: one warp per token in the swap kernel
The swap kernel is the only work STRATA_ROUTE_RESIDENT adds to a window, and it was written as one
thread per token: with a verify window of 1 to 8 rows that is up to 8 threads of a block, each doing,
per rank in [lo, hi], a 512-expert scan with a ten-way "already picked" test inside it.  On this
machine that is about 4 x 512 x 12 scalar operations running on six threads, on the critical stream,
once per layer, and it shows up as its own cost in the window.

STRATA_VERIFY_PROFILE, three legs in one session, same prompts, same expert cache (8083 slots, one
learned profile), medians of the per-window stage table:

    configuration                        hc-read1+router   waitB    ms/window   pcie_e
    option off                                2.25          9.30      21.85      1.87
    option on, one thread per token           5.00          5.01      21.97      1.00
    option on, this commit                    2.58          4.87      19.75      0.95

The option redirects about a miss per layer-window away from PCIe and saves 4.3 ms of waiting for it;
the serial swap spends 2.75 ms back, which is why the option measured as a wash.  In the warp form the
swap costs 0.33 ms, so the waiting it saved stays saved.

End to end, twelve matched pairs of engine restarts, nine decode samples a leg, three greedy 150-token
prompts, the learned expert profile copied back before every leg so both arms start from the same
8083-slot cache.  The first six pairs ran the unpatched build first, the last six the patched build
first, so a within-pair order effect would show up as the two halves disagreeing:

    pair  order   decode unpatched   patched    delta    ms/window unpatched   patched    delta
     1    A->B         104.1          115.7     +11.1%         18.64          17.01      -8.7%
     2    A->B         103.5          107.4      +3.8%         18.47          18.12      -1.9%
     3    A->B         111.4          107.7      -3.3%         17.71          18.26      +3.1%
     4    A->B         101.4          113.0     +11.4%         19.11          17.03     -10.9%
     5    A->B         105.8          107.6      +1.7%         19.05          18.05      -5.2%
     6    A->B         104.8          105.6      +0.8%         18.60          17.83      -4.1%
     7    B->A         106.6          113.4      +6.4%         18.70          17.16      -8.2%
     8    B->A         103.1          110.2      +6.9%         18.14          17.29      -4.7%
     9    B->A         106.9          111.5      +4.3%         17.91          17.26      -3.6%
    10    B->A         104.3          114.7     +10.0%         17.81          17.11      -3.9%
    11    B->A         108.3          115.9      +7.0%         18.47          16.61     -10.1%
    12    B->A         104.5          113.6      +8.7%         18.43          17.76      -3.6%

    twelve legs each:   unpatched  decode median 104.7 (101.4-111.4)   ms/window median 18.47 (17.71-19.11)
                        this commit decode median 112.2 (105.6-115.9)  ms/window median 17.27 (16.61-18.26)

    decode      median +6.6%   mean +5.7%   faster in 11 of 12 pairs   (sign test p = 0.006)
    ms/window   median -4.4%   mean -5.2%   shorter in 11 of 12 pairs  (sign test p = 0.006)
    first six pairs: +2.7% decode, -4.7% window     last six: +7.0% decode, -4.3% window

pcie_e, the engine's own count of experts per layer-window that cross PCIe, is the same in both arms
(leg medians 0.63 against 0.64), so the same experts are routed and the difference is the kernel.

The swap's cost, and so its removal, scales with the tail experts the option actually redirects.  Four
more pairs with a 4000-slot cache instead of the automatic 8083 (pcie_e 1.83 against 1.78, i.e. about
three times the traffic of the series above), two pairs each way:

    pair  order   decode unpatched   patched    delta    ms/window unpatched   patched    delta
     1    X->Y          83.8           92.0      +9.8%         21.94          20.60      -6.1%
     2    Y->X          84.6           92.5      +9.3%         23.97          20.53     -14.4%
     3    X->Y          82.2           85.5      +4.0%         23.69          22.65      -4.4%
     4    Y->X          81.0           87.7      +8.3%         24.54          22.21      -9.5%

    decode median +8.8%, ms/window median -7.8%, 4 of 4 pairs, both orders.

What this changes is the shape, not the choice.  One warp per token: lane j reads experts j, j+32, ...
(coalesced instead of a serial walk), the warp reduces to the best logit in a shuffle tree, and the
ranks are still visited in order, because a swap changes the set already picked.  The choice is the
same bits: a strictly greater logit wins, the smallest expert index breaks ties, the already-picked
test runs against the ids as they are at that rank, a token with no swap keeps the router's weights
untouched, and the softmax is the same expression.

Parity.  400 random cases - half of them built with many equal logits, random lo/hi, margins from
-0.5 to 1.5, 1 to 8 tokens, about 60% of the experts resident, routed ids with repeats - compare the
two implementations bit for bit on the ids, on the weights (their raw bits) and on the four counters.
The harness carries both kernels side by side; 0 mismatches.

For context, the option's price is the margin's and not the kernel's, and this commit does not touch
it.  Teacher-forced log-probabilities over 7677 positions of one 7.6k-token text (technical prose,
source code and Chinese), top-64, against the same text with the option off:

    margin   argmax same   KL (top-64)   teacher-forced loss   perplexity
    off      -             0.000         3.2033                -
    0.25     84.9%         0.235         3.2238                +0.6%
    0.50     83.0%         0.293         3.4360                +7.3%
    1.00     63.5%         1.001         4.7751                +49%

Two runs with the option off are bit-identical, so that spread is the option and not the machine.
0.25 keeps nearly all of the waitB saving for a fraction of the distortion; the default 1.0 is not
worth its price.

Tests: the parity harness is a standalone .cu (both kernels, the random cases, the bit comparison).
Happy to wire it into the test suite next to the other kernel tests if you want it in the tree.
2026-10-11 10:52:44 +02:00
Niko1221 5ef500d48f Merge f-1712: the prompt chunk's step records and token ids go up from a pinned buffer (#1712) 2026-10-11 10:51:53 +02:00
Niko1221 46d22108ec HIP layer split: the route tail skip's default stays off from 70% of the experts cached (90% elsewhere); 2x R9700 16 GB-eq Q2_0 story -6.1% with it at 73% 2026-10-11 10:46:14 +02:00
Niko1221 a5f82ab77d Merge f-143-dense (via the trial merge 94f6d18d): CUDA sm_86 Q3_K interleaved kernel and one column; bitwise exact, A4000 decode +2.0-2.7% 2026-10-11 10:22:39 +02:00
Niko1221 2eba71548d Merge f-143-intel: B70 prompt and decode speed (copy engine, wide kv_append, no GEMM staging on bmg, lend mirror, fused dequant, lean verify graph, the xe expert ranking); same output tokens, B70 4K prompt 8.5 -> 3.3 s (128K config), decode +14-21% on prompts outside the ranking's corpus 2026-10-11 09:27:15 +02:00
Niko1221 b97a36a49a prefill: the chunk's step records and token ids go up from a pinned buffer, not pageable memory (#1712)
The QSA step records of a chunk were uploaded with an unchecked cudaMemcpyAsync from a
std::vector.  On gfx1100 the first text prompt after a picture one read garbage records
(5 of 5 faults on a two-request repro, 0 of 5 with a pinned, event-guarded source).  The
token id upload has the same shape and now takes the same path; both check the result.

Reported and traced by mantovaniluca91, #1712.
2026-10-11 09:16:52 +02:00
Niko1221 4d4f8bd50b docs/INTEL.md: server latency numbers 2026-10-11 09:10:59 +02:00
Niko1221 94f6d18d54 Merge f-143-dense: CUDA sm_86 Q3_K on the interleaved path and one column (STRATA_MMVQ_IL_Q3K=0 / STRATA_MMVQ_IL_T1=0 off) 2026-10-11 09:06:29 +02:00
Niko1221 3d5c16efe0 docs/INTEL.md: the 0.1.43 prompt and decode speed changes on the B70 2026-10-11 08:27:12 +02:00
Niko1221 8cb26e6095 SYCL: data/expert-profile-sycl.bin, the experts' ranking for a card on xe, built with make_profile_mix.py from the routing of 45 varied prompts and eight document summaries; setup_intel writes it instead of the shipped profile there (i915 keeps the shipped one). B70: +5..64% decode (mean +21%) on 12 unseen prompts, the same tokens. The copy-engine queue is Battlemage-only by default (it hung the A750's prompt) 2026-10-11 08:25:30 +02:00
Niko1221 ddd84269e4 Merge f-143-amdmg: --pipeline-windows 2 by default on gfx12 layer splits of 3+ stages (exact; 4x R9700 code +7-12%, 4K +9-11%, 32K +8-19%); STRATA_PCIE_AUTO_SPLIT=1 opt-in 2026-10-11 08:18:26 +02:00
Niko1221 b03304d934 HIP: --pipeline-windows 2 is on by default for gfx12 layer splits of 3+ stages (STRATA_PIPELINE_AUTO=0 / --pipeline-windows 0 off); STRATA_PCIE_AUTO_SPLIT=1 (opt-in) refines a two-stage split's PCIe shares per stage 2026-10-11 08:16:49 +02:00
Niko1221 218df14283 SYCL copy engine: one queue per device (a layer split asks once per card) 2026-10-11 07:58:41 +02:00
Niko1221 9e3ba42755 tools: make_profile_mix.py (an expert profile from several routing traces, each trace counting the same, with weights), collect_profile_traces.py (the traces of bench/profile_corpus.json's 45 varied prompts through the engine) 2026-10-11 07:58:34 +02:00
Niko1221 46a77907bb SYCL decode window: under STRATA_VERIFY_NO_HOST with the device plan the graph drops the nodes nobody answers (doorbell publish, three flag waits, the plan copy, the PCIe-share group and its staging); -2% decode on a B70, same tokens (STRATA_VERIFY_LEAN=0 turns it off) 2026-10-11 06:51:51 +02:00
Niko1221 331b591b36 Merge f-143-amdk: gfx12 decode node cuts (HC norm from registers, host-flag wait folded into the copy, HC up kernel owning its q8_1 groups, hit counts in the combine); bitwise exact, +1.6-2.0% decode 2026-10-11 06:01:01 +02:00
Niko1221 a9917a5524 gfx12 decode: the HC up kernel owns whole q8_1 groups and writes its consumer's image itself (STRATA_QFUSE_HC, no atomics), moe_hit_add folded into the combine (STRATA_FUSE_HITS); STRATA_FUSE_CONVAB (conv + a/b in one launch, opt-in, measured slower) 2026-10-11 05:59:48 +02:00
Niko1221 beba872b86 SYCL: the experts in the prompt loan's slots (the cache's last 10%, at most 1,200) are mirrored in pinned memory too, so the lent slots are refilled by DMA, not by a single-threaded GGUF read: 930 slots 916 -> 84 ms (STRATA_LEND_MIRROR=0 turns it off) 2026-10-11 05:53:27 +02:00
Niko1221 7a07f2811a SYCL prompt path: no GEMM operand staging on Battlemage (STRATA_SYCL_GEMM_STAGE=1 brings it back): the A770 oneMKL bug (operands past 4 GiB) did not show on a B70, first-token logits are byte-identical at 4K and 49K, and the 10 MB copy per expert was ~10% of a prompt 2026-10-11 05:44:57 +02:00
Niko1221 5a0df89817 SYCL prompt path: kv_append writes the host KV copy and the staging pool 4 bytes a lane (STRATA_KV_WIDE_HOST=0: the 1-byte stores): with --kv-resident the 1-byte stores into pinned host memory ran at ~30 MB/s, 2 s of a 4K prompt on a B70 2026-10-11 05:30:32 +02:00
Niko1221 cd5660593e SYCL copy engine: the stager's issued-flag is a copy, not a fill kernel (a copy-only command list runs no kernel: the driver aborted the lent-slot prompt of the 128K config) 2026-10-11 05:30:32 +02:00
Niko1221 751095962c SYCL prompt path: an expert's gate/up and down dequantized in one launch (iq_dequant_expert_f16, the same values; STRATA_PF_DQ_FUSED=0: two launches), -2% on a B70 4K prompt 2026-10-11 04:45:51 +02:00
Niko1221 7fc02cb5c2 gfx12 decode: the split HC norm from registers (-1.8 us a read), the host-flag waits folded into the copies that follow them (-2 nodes a layer); STRATA_VERIFY_NODES lists the window graph on HIP; the stage profile splits the FFN-side HC read; STRATA_DUMMY_NODES=k measures what an empty graph node costs 2026-10-11 04:04:07 +02:00
Niko1221 bb519f5bca bench: fused_gr_bench cold-weight mode with the norm/down/up split and an output hash; router_chain_bench (router GEMV, top-10 and doorbell per layer in a graph) 2026-10-11 04:04:07 +02:00
Niko1221 01fe68ddab SYCL: the prompt path's expert copies run on the GPU's copy engine (an immediate command list on the copy-only queue group, wrapped as a SYCL queue); the Level Zero v2 adapter ran them on the compute engine, ~13% of a B70 prompt. STRATA_COPY_ENGINE=0 turns it off 2026-10-11 04:00:52 +02:00
Niko1221 70f9c41772 SYCL: the grouped XMX expert kernels on Battlemage (STRATA_PF_XMX=1/2, opt-in): sub-group 16, joint_matrix 8x16x16, built for AOT bmg and lnl (STRATA_XMX_SG16); Alchemist keeps 8x8x16 2026-10-11 04:00:40 +02:00
Niko1221 5008962499 SYCL: STRATA_USAGE_DUMP=PATH counts every routed expert in the device plan (an atomic per entry) and writes the counts in --dump-routing format; a measurement of how much residency matters under STRATA_VERIFY_NO_HOST 2026-10-11 04:00:40 +02:00
Niko1221 195d379125 CUDA sm_86: Q3_K on the interleaved 2-4 column path and one column on the same kernel, sm_86 table (STRATA_MMVQ_IL_Q3K=0 / STRATA_MMVQ_IL_T1=0 turn them off)
IlQ3K runs q3_q8_dot_impl's arithmetic with the scales and signed values done once per chunk; bitwise native_mmvq's output
for T 1-4 and rows 1/2/4 (mmvq_il_parity). Q2_0 pack: the Q3_K multi-column kernels were 14% of GPU kernel time; the new kernel
takes 2560x10240 at 4 columns from 120 to 70 us on an RTX A4000. The shared table (sm_80+/sm_120) is unchanged.
2026-10-11 03:03:31 +02:00
Niko1221 da3fe1f119 mmvq_il_parity: the engine's real shapes, one column, Q3_K, MMVQ_IL_ONLY filter, table emit by worst ratio; fused_gr_bench: engine's staged read, L2-cold weights, GB/s 2026-10-11 03:03:31 +02:00
Niko1221 7c3fc48e86 Merge f-143-q2pcie: measured PCIe share for the canonical Q2_0 pack on CUDA (conflict with the gfx12 PcieAuto default resolved: one pf_old, canonical pack CUDA only) 2026-10-11 02:24:23 +02:00
Niko1221 ab97f17415 PcieAuto for the canonical pack: probe the link and refine the share from the CPU pool's speed (CUDA; start value stays 0.2; STRATA_PCIE_FRAC_DEFAULT=old and --pcie-frac keep it fixed) 2026-10-11 01:49:53 +02:00
Niko1221 c69adca61f Version 0.1.43: project version and the setup minimum engine; DETAILS lines for the gfx12 defaults 2026-10-11 01:49:39 +02:00
Niko1221 f5a0126762 Merge f-143-amd: gfx12 decode defaults 2026-10-11 01:49:18 +02:00
Niko1221 bf1e083f8a Merge f-143-amdpp: gfx12 chunk rule and PF_FUSED default 2026-10-11 01:49:17 +02:00
Niko1221 4ad4a25877 Merge f-143-kernels: P100 sm_60 tables 2026-10-11 01:49:17 +02:00
Niko1221 b5e040da40 Merge f-143-prefetch: adapt overlap default-on CUDA 2026-10-11 01:49:13 +02:00
Niko1221 85d90002b6 serve: a slot request that ends at its stop token reads its BDONE before it leaves, so its decode time and tokens are the slot leg's (#1869) 2026-10-11 00:56:31 +02:00
Niko1221 7475df931a HIP: the measured PCIe share (PcieAuto) is the default on gfx1200/gfx1201; STRATA_PCIE_FRAC_DEFAULT=old opts out; other AMD parts unchanged 2026-10-11 00:42:35 +02:00
Niko1221 ad2aef7648 HIP: STRATA_ROUTE_TAIL_SKIP=7 is the default on gfx1200/gfx1201 under the CUDA rules (#1884 cached-share line included); other AMD parts unchanged 2026-10-11 00:42:25 +02:00
Niko1221 606eb1080c generate: decode_defaults_arch_ok() (gfx1200/gfx1201 on HIP, always on CUDA) for the HIP decode defaults 2026-10-11 00:42:09 +02:00
Niko1221 5f9bbf61c2 serve: a request moved from the solo path to a batch slot keeps the solo leg's prompt figures, decode time and tokens (#1869, #1870) 2026-10-11 00:34:36 +02:00
Niko1221 5a66924d8d gfx12: the fused int8 prompt experts are on by default for IQ3_S and IQ3_XXS packs; STRATA_PF_FUSED=0 turns them off 2026-10-11 00:19:22 +02:00
Niko1221 cf09057a86 gfx12 (Linux): a bare --prefill auto may take 16384-token chunks; explicit --prefill N, auto:N and STRATA_PREFILL_AUTO_MAX are untouched; STRATA_GFX12_CHUNK=0 or STRATA_GFX12_DEFAULTS=0 keeps 8192 2026-10-10 23:50:49 +02:00
Niko1221 0d761d99aa Resident RAM mode overlap: opt-in (STRATA_ADAPT_OVERLAP_RESIDENT=1); exact, +7.0% on an A4000, -2.6% on a RAM-bound 3060 box 2026-10-10 23:00:37 +02:00
Niko1221 6ab541f625 CUDA: the tail-skip default stays off when 90% or more of the experts are in the GPU cache (#1884); STRATA_TAIL_SKIP_MAX_CACHED moves the line 2026-10-10 22:16:48 +02:00
Niko1221 2eaeda2e4b STRATA_ADAPT_OVERLAP in the resident RAM mode: soft_commit_exchanges makes a staged evicted expert look committed (pinned, device alias into its exchange buffer) while in's RAM place stays the copy source 2026-10-10 22:14:33 +02:00
Niko1221 8c34c475da STRATA_ADAPT_OVERLAP_SLOW_US: test hook that slows the adaptive copies so the windows wait for them 2026-10-10 22:12:27 +02:00
Niko1221 0636c4642f serve: a request handed from a batch slot back to the solo path keeps the slot leg's decode time and tokens (#1869); timings.prompt_n is what the engine read, the rest is cache_n (#1870) 2026-10-10 22:05:52 +02:00
Niko1221 cd78501359 strata_bench: skip the agent session when the context is below ~10K instead of sending a request that fails with HTTP 400 2026-10-10 22:00:17 +02:00
Niko1221 f95f2eabbd STRATA_ADAPT_OVERLAP on by default for CUDA (=0 turns it off), docs; the h2d copy-engine microbenchmark 2026-10-10 20:37:02 +02:00
Niko1221 e7558f8c5f CUDA sm_60: expert mode 8 (grid and activations in shared memory, SwiGLU fused) is the Tesla P100's default, STRATA_SM60_TABLE=0 or STRATA_EXP_MODE=0 turns it off
Bitwise equal to the CUDA layout on all 48 layers at 1-4 tokens a group (native_expert_bench); a 28-group VRAM call 17.6 -> 15.5 ms over the layers at T=1, 24.1 -> 22.6 at T=2, even at T=3, +2.6% at T=4.
2026-10-10 20:01:31 +02:00
Niko1221 9ef4484248 STRATA_ADAPT_OVERLAP=1 (opt-in): the adaptive tier's copies land while the next decode window runs, a layer waits for its own copies 2026-10-10 18:49:32 +02:00
Niko1221 e5387d41ec CUDA sm_60: interleaved 2-4 column GEMV with a Pascal rows table (P100), STRATA_SM60_TABLE=0 turns it off
Bitwise equal to native_mmvq (mmvq_il_parity, T 2-4, rows 1/2/4); table read off mmvq_il_parity --bench --emit-table on a Tesla P100 (three identical runs).
2026-10-10 18:39:38 +02:00
Niko1221 86070e7845 STRATA_TRACE: VRAM marks after the context, the pack weights, the session and the head (the 0.1.43 VRAM audit) 2026-10-10 18:30:35 +02:00
Niko1221 885f9f7016 Version 0.1.42.1: project version and the setup minimum engine 2026-10-10 18:24:47 +02:00
Niko1221 00cc68e77a Merge f-142d-bench into f-1421 2026-10-10 18:24:33 +02:00
Niko1221 bccef1cf81 Merge f-142d-numa into f-1421 2026-10-10 18:24:33 +02:00
Niko1221 02a4216fea Merge f-142d-unmap into f-1421 2026-10-10 18:24:33 +02:00
Niko1221 61b3fb5dd3 Merge f-142-pciefrac into f-142 2026-10-10 14:49:37 +02:00
Niko1221 0e9af37041 docs/DETAILS: the PCIe share set from the CPU pool's speed (CUDA, single GPU); measurements and opt-outs 2026-10-10 14:48:49 +02:00
Niko1221 c2cbf8c112 Merge f-142c-triage into f-142 2026-10-10 13:54:32 +02:00
Niko1221 407ea8192a Merge f-142c-small into f-142 2026-10-10 13:54:28 +02:00
Niko1221 879096d66c Benchmark: backend wording, run time text 2026-10-10 13:46:55 +02:00
Niko1221 ed5536ea88 file_expert_source_test: fix the cache-hint test string 2026-10-10 13:35:47 +02:00
Niko1221 6b8c2e74d7 Benchmark: prompt sizes calibrated by slope, agent re-read counts only earlier turns, no doubled quant in the folder name 2026-10-10 13:25:09 +02:00
Niko1221 dfaebd9d9f Benchmark mode: BENCH.bat / bench.sh and tools/strata_bench.py measure an install through the HTTP API and write a community report 2026-10-10 13:17:12 +02:00
Niko1221 52a2dd10ac Windows GGUF-in-place: close every GGUF shard view once the file tier reads unbuffered (NTFS serializes unbuffered reads of a mapped file) 2026-10-10 13:13:17 +02:00
Niko1221 8c80a3ba12 Start-up after another model: judge pinning by the emptiest NUMA node, say how much is file cache when RAM is short, opt-in STRATA_DROP_CACHE_ON_EXIT 2026-10-10 13:12:47 +02:00
Niko1221 aa7b0cb13e CUDA: the default --pcie-frac is refined in the first decode windows from the CPU pool's measured speed (single GPU, no --pcie-frac); STRATA_PCIE_FRAC_DEFAULT=old keeps the start-up rule 2026-10-10 13:01:46 +02:00
Niko1221 d3e9106e1d tools tests: follow #1792 (no version range without CUDA, STRATA_VCVARS), and the effort-end test no longer collides on a case-insensitive disk 2026-10-10 11:11:20 +02:00
Niko1221 0ae808f37d tools tests: the llama.cpp archive test passes a plain path (a file:// URI with a drive letter is not found on Windows) 2026-10-10 11:04:37 +02:00
Niko1221 a02cacbb3d docs: card order keeps the config's order for cards within 5% (#1760) 2026-10-10 11:02:19 +02:00
Niko1221 f63a57e726 prefill gemm: BF16 on Pascal/Volta converts the weight in tiles when the conversion buffers do not fit, instead of falling through to the raw BF16 cuBLAS call (#1757) 2026-10-10 11:02:14 +02:00
Niko1221 184012cac4 serve: cards whose speed scores are within 5% keep the config's card order (#1760) 2026-10-10 11:02:14 +02:00
Niko1221 47cb731026 serve: telemetry test for the AMD PCIe link (#1733): the reader gains the pcie_* keys, and the hop walk is tested 2026-10-10 10:51:32 +02:00
Niko1221 4d0d11f72d bench: COMMUNITY.md rows and the docs list entries for #1739 #1751 #1784 #1793 #1799 #1802 #1811 2026-10-10 10:47:13 +02:00
duncanmcqueen 27528ca53d docs: Intel Arc A770 decode speed investigation record (PR #1765; local paths removed) 2026-10-10 10:47:13 +02:00
Mitsuasa513 83b2b676dd bench: community report, Radeon Pro VII 16 GB (gfx906), ROCm 6.2 (PR #1793; build and server logs left out) 2026-10-10 10:47:13 +02:00
Hcl192088 d5400b54f5 bench: community report, RTX 4070 12 GB, IQ2_XS, modified engine (PR #1739; hostname redacted) 2026-10-10 10:47:13 +02:00
kgmkm 3bfc708d07 bench: community report, RTX 5060 Ti (WSL2), IQ3_S, engine 0.1.41 (PR #1751) 2026-10-10 10:47:13 +02:00
VykosX 432a45c708 bench: community report, RTX 5060 Ti / Xeon E5-2680 v4 (PR #1784) 2026-10-10 10:47:13 +02:00
gun-powder 80ea56af12 bench: community report, 2x Tesla P40, IQ3_S, 131K (PR #1799) 2026-10-10 10:47:13 +02:00
isoux35 7f980b5bd2 bench: community report, RX 9060 XT 16 GB, IQ2_XS and IQ3_XXS (PR #1802) 2026-10-10 10:47:12 +02:00
Daniel Spitzer c50a217a99 bench: community report, RX 9070 16 GB, IQ3_XXS, engine 0.1.41 (PR #1811) 2026-10-10 10:47:12 +02:00
Niko1221 70ac6dd41f serve: repeat_penalty / repeat_last_n (llama.cpp's names) for the config's sampling block and for requests (#1819) 2026-10-10 10:45:03 +02:00
Niko1221 2ea10c2e9a sycl: iq_parity and ple_parity are registered as the top-level build does (#1795) 2026-10-10 10:44:09 +02:00
architectds 6b392641af verify: service returns before any CUDA call while nothing has rung
The pipelined decode loop asks both stages' windows for service millions of times a second while they wait on their
doorbells, and every call switched the device (OnDevice: cudaGetDevice and two cudaSetDevice) before finding nothing
to do. On a 0.1.41 split (RTX 3060 + RTX 5070 Ti, Windows) the host stalled inside one of those cudaSetDevice calls
after 919 million loop passes, with both stages' windows waiting on it (stall dump: the serving thread in cudart from
Verifier::service, every other engine thread idle). Now a call with nothing rung, no WDDM flush due (2 ms) and no
timeout due returns 0 first - the same answer the loop below gives - so the driver is called only to serve a layer,
to flush, or to time out.
2026-10-10 10:43:10 +02:00
Niko1221 093edf2474 build: guard the CUDA::cuda_driver link for the HIP stand-in targets 2026-10-10 10:43:10 +02:00
Kurokosama b0eb396528 serve/web: add a favicon to the web app and the API Monitor
The pages had no <link rel="icon"> and serve/web had no icon file, so browsers asked for
/favicon.ico, got a 404 and showed the default blank icon in the tab.

serve/web/favicon.svg is the layer stack the app already uses (serve/web/sprite.svg, i-layers),
redrawn on a 32-unit viewBox so it stays legible at 16 px, in the existing accent token #10b981.

Checked: curl /web/favicon.svg -> 200 image/svg+xml, both pages come back with the icon link,
and the icon rendered at 16/32/48/64 px in Chrome.
2026-10-10 10:42:55 +02:00
phoenixclyde 7f3c0da241 telemetry: the Monitor's PCIe tile had no link for AMD cards on Linux
_Nvml.read() reports pcie_gen, pcie_gen_max, pcie_width and the two
throughput counters; _Amd.read() (the amdgpu sysfs reader from #301)
reports none of them, so on Linux the Monitor's PCIe tile shows only
dashes while the NVIDIA tile fills in.

This adds the link the card actually gets: the narrowest and slowest hop
between the root port and the card, from each hop's max_link_speed and
max_link_width.  A card that negotiates Gen4 on its own hop but sits
behind a Gen3 root port really runs at Gen3, and that is the number a
bandwidth budget needs.  pcie_own_gen keeps the card's own hop aside so
the gap is visible, and pcie_path reports how many hops could be read --
the bottleneck is only claimed when all of them could, because a kernel
or a container that hides part of /sys/devices would otherwise report the
card's own hop as the whole path.

Measured on one MI50 32 GB in a Gen3 x16 slot (lspci: the root port at
00:02.0 runs at 8 GT/s x16, the bridge above the card is downgraded, and
the card's own hop negotiates 16 GT/s), /metrics reports pcie_gen 3,
pcie_gen_max 3, pcie_own_gen 4, pcie_width 16 and pcie_path 4/4.

Throughput is deliberately left out: amdgpu's pcie_bw is three counters
whose documented use is a total, not a direction, while _Nvml's
pcie_rx_mb is receive-only, so filling that name from pcie_bw would
label a combined figure as one direction.  Happy to follow up separately
if you want the tile to show a rate.

Hardware the numbers come from: one Radeon Instinct MI50 32 GB (gfx906,
PCI 1002:66a1, VBIOS 113-D1631711-100) on a Xeon E5-2696 v4 (Broadwell,
no AVX-512), in a PCIe 3.0 x16 slot, 128 GB RAM, Ubuntu, kernel
7.0.0-34-generic, ROCm 7.14 in a container.
2026-10-10 10:42:55 +02:00
phoenixclyde dc0ee3acf7 prefill: the gfx906 build reached the CUDA branch of arm_cpu_share
Prefill::arm_cpu_share() asks "is this AMD?" with
#if !defined(STRATA_USE_HIP), but the gfx906 compat build (PR #638)
compiles as HIP *without* STRATA_USE_HIP -- see src/core/expert_cache.cpp
:5-6, which guards the same question with
#if defined(STRATA_USE_HIP) || defined(STRATA_HIP_GFX906).

On gfx906 the CUDA branch is therefore live: the CPU share is armed by
default for chunks below 1,024 tokens and prints its banner, against this
file's own note at :161 ("the layer split, batch slots and HIP stay off").
Seven other sites already carry the || defined(STRATA_HIP_GFX906) form.

Measured on one MI50 32 GB (gfx906), CLI generate, a 4-token prompt, one
binary with one set of weights and one config, only the environment
differing, power saving off:

  default  experts streamed 309 (295 by DMA, host 174.0 ms), resident 607,
           on the CPU 197 (share 0.90)          prefill 928.3 ms
  =0       experts streamed 506 (492 by DMA, host 177.3 ms), resident 606,
           on the CPU 0 (share 0.00)            prefill 929.5 ms

Output token ids are identical (271 248068 198 760) and the 0.13%
difference is inside this machine's run-to-run spread (1.2-1.7%), so on
this card the share engages and buys nothing.  #1595 and #1729 report the
default costing on CUDA; this is the mechanism that turns it on for AMD.

CUDA and SYCL do not define STRATA_HIP_GFX906, so the added check is a
no-op there and nothing on those backends changes.

Hardware the numbers come from: Xeon E5-2696 v4 (Broadwell, 22C/44T, no
AVX-512), one Radeon Instinct MI50 32 GB (gfx906, PCI 1002:66a1, VBIOS
113-D1631711-100, 34,342,961,152 B of VRAM), PCIe 3.0 x16 effective (the
root port runs 8 GT/s x16 and the bridge above the card is downgraded;
the card's own hop negotiates 16 GT/s, about 15.75 GB/s end to end),
128 GB RAM, Ubuntu, kernel 7.0.0-34-generic, ROCm 7.14 in a container,
built with -DSTRATA_HIP_GFX906=ON and -DCMAKE_HIP_ARCHITECTURES=gfx906.
2026-10-10 10:42:55 +02:00
phoenixclyde 6a7c6f8275 web: the unlabelled sparklines were scaled by their own noise
spark(id, values, max) sets the axis top to max(|max|, the series' own
maximum, 1e-9).  gpu_util, temperature, cpu, vram and power pass an
explicit maximum, but the pcie, tok/s, prefill and disk cards do not, so
those axes zoom onto whatever the series happens to hold.

An idle amdgpu pcie counter reads 0.01-0.02 MB/s (50 packets x 256 B per
second), and that becomes a full-amplitude square wave in the Monitor
while the tile's own text says 0.0 MB/s.  Measured in the live DOM: the
pcie line's y values are only {4.0, 30.0}, i.e. the baseline and the top.

A floor of 1 only ever lowers the axis - the series maximum still wins -
so a real burst keeps its scale, and the cards that pass a maximum are
untouched.
2026-10-10 10:42:55 +02:00
chaog992 031fddc62c tools tests: test_amd_is_not_asked mocks the Linux HIP engine build too (it wrote sys.prefix/.strata-rocm.json)
IQ4XS.test_amd_is_not_asked mocks get_prebuilt_hip, the engine setup.main takes on Windows. On Linux setup.main
compiles the HIP engine instead (build_engine_hip), which the test did not mock. Without a usable system ROCm 7, as
on the tested machine, rocm_root then fetched AMD's ROCm index
(https://rocm.nightlies.amd.com/v2/gfx120X-all/rocm/), wrote Path(sys.prefix)/.strata-rocm.json and tried to run
<python dir>/rocm-sdk. Where sys.prefix is not writable (the system Python) that is a PermissionError. Where it is
(a venv), the test passed while setup.main stopped at the ROCm step with exit code 1, and a stamp with the same
version and index can make a later setup in that venv skip the ROCm install.

The test now mocks build_engine_hip the same way, so on Linux setup.main runs to the end (exit code 0) with no
network request, no subprocess and no write outside the test's temp folder. setup.py is unchanged; the Windows path
never reaches build_engine_hip, so it runs as before.

Tests: python3 -m unittest tools.test_setup_unsloth (WSL2): with the system Python 3.12.3 FAILED (errors=1) before,
38 tests OK after; in venvs on 3.10.22, 3.12.3, 3.13.7 and 3.14.8 OK before and after, and no stamp after. With the
system Python the other 27 tools/test_setup_*.py files give the same results as before.
2026-10-10 10:42:55 +02:00
Hugua700 db5b1f19d6 setup: find_vcvars() without CUDA asks vswhere for no version range (#881)
The `[16.0,18.0)` range is CUDA 13's requirement, but it was applied to every caller: with the
only Visual Studio installed being 2026 (version 18), vswhere finds nothing and find_vcvars()
returns None.  That makes the CPU image encoder unbuildable on such a machine - build_vision_cpu()
cannot run - so --vision cpu stays unreachable there even with the gate in hip_vision() open.

#985 relaxed the range for CUDA 13.3+ by adding `cuda_v`, which is right for CUDA callers.  A
caller with no CUDA now passes nothing and gets no range, which is what
tools/hip/build_windows.bat already does when it calls vswhere directly.

- `cuda_v is None` -> no -version argument at all.  CUDA callers are unchanged: cuda_v=(13, 0)
  still refuses VS 18, cuda_v=(13, 3) still takes it.
- STRATA_VCVARS=<vcvars64.bat> picks an install by hand, for a vswhere that cannot be used.

Verified on the RX 6800M / gfx1031 machine of #881 (Windows 11, Chinese locale, the only C++ tools
are Visual Studio 2026 / 18.4.11605):

  find_vcvars()               -> <VS 18>\VC\Auxiliary\Build\vcvars64.bat
  find_vcvars(cuda_v=(13, 0)) -> None
  find_vcvars(cuda_v=(13, 3)) -> <VS 18>\VC\Auxiliary\Build\vcvars64.bat
2026-10-10 10:42:55 +02:00
leadgtr7 7650292cfd sycl mtp: slot drafters copy the shared draft head's type, as src/core/mtp.cpp does since #1110
With a draft-vocab head (rt/draft_vocab.bin) the slot drafters of --batch-mtp share the main drafter's head but kept
dhead_type_ at -1, so the first draft_first() of a batch admission threw 'mtp: unsupported native MMVQ GGML type'
and the engine exited (#1121). The CUDA source got this line in #1110; the SYCL port did not.
2026-10-10 10:42:55 +02:00
David d73108c7e8 build: link CUDA MMQ error reporting to the driver API 2026-10-10 10:42:55 +02:00
GRAB Racem 253e09f18d serve: the reasoning loop check also sees a loop written as one long word (#1753)
A periodic loop emitted as digits (a 24k-digit string cycling an 11-digit
pattern) is a single word to the word count and never one token twice
(the tokenizer has no multi-digit tokens), so both #606 and #728 passed
it and the run burned the whole reasoning budget.  The reasoning's last
2,048 chars are now checked for a period of at most 64 chars, and a
periodic tail reads as full coverage.  The opt-in path only: the default
path and the word count are unchanged.
2026-10-10 10:42:44 +02:00
leadgtr7 b9cba34bc2 serve: effort_position "end" reads the SYCL engine binary, not its launcher script, for --tail-role-token
With the Intel port the configured exe is sycl/serve/strata-sycl.sh, a shell script that runs the repo's
STRATA_SYCL_BIN (default build-sycl-aot/strata) in a container. effort_end_args looked for --tail-role-token in the
script, never found it, and fell back to the top-of-prompt effort with "needs engine 0.1.39 or newer", even on a
0.1.41 engine that has the option. engine_binary() resolves the launcher to the binary it runs; any other exe is read
as before. tools/test_effort_end_args.py covers both paths.
2026-10-10 10:42:44 +02:00
nekomario28 72843d4ca9 sycl: use the source version for setup model checks
The SYCL project declaration uses a CMake variable, not a literal
version. Reuse setup's parser so the stub no longer reports version 0.
2026-10-10 10:42:44 +02:00
Hulk 153416719d fix(setup): discard damaged llama.cpp source archives 2026-10-10 10:42:44 +02:00
Niko1221 cdbf458684 Version 0.1.42: project version and the setup minimum engine (0.1.41.1 was not released; its fixes are in 0.1.42) 2026-10-10 01:23:45 +02:00
Niko1221 d5f319bffc Merge f-142-cuda-p1r into f-142 (inert lookahead stats, cache-policy replay tool, docs) 2026-10-10 01:23:07 +02:00
Niko1221 136d33cdc3 Merge f-142-tailskip into f-142 (STRATA_ROUTE_TAIL_SKIP=7 default on CUDA serve) 2026-10-10 01:23:07 +02:00
Niko1221 7bbfab810b docs/DETAILS: the tail skip default (KL, task check, speeds, opt-out); start-up line wording 2026-10-10 01:22:27 +02:00
Niko1221 51cc86291b docs: STRATA_LOOKAHEAD_STATS and tools/replay_cache_policy.py 2026-10-09 23:10:26 +02:00
Niko1221 b4e3407bd2 STRATA_ROUTE_TAIL_SKIP=7 on by default on CUDA serve (=0 off): single GPU and layer splits; not with every expert in VRAM, --batch slots, a peer or helper GPU, HIP; one start-up line names the opt-out 2026-10-09 22:52:22 +02:00
Niko1221 223655ac91 replay_cache_policy: policy options on the command line 2026-10-09 21:09:03 +02:00
Niko1221 9462c58287 tools/replay_cache_policy.py: replay a --dump-routing trace through the adaptive expert tier's policy offline 2026-10-09 21:08:49 +02:00
Niko1221 b02a03d97c Look-ahead stats: vote-ranked top-M coverage of the misses and of the PCIe share 2026-10-09 20:47:12 +02:00
Niko1221 1d735110ae Router look-ahead stats: report the predictor thread's time per window 2026-10-09 20:47:12 +02:00
Niko1221 e247c61127 Router look-ahead: STRATA_LOOKAHEAD_STATS scores each layer's prediction against the real routing (measurement only) 2026-10-09 20:47:12 +02:00
Niko1221 8b0c241ca0 sycl: build q2_avx1.cpp and iq_avx1.cpp (the AVX1 expert rows native_expert.cpp calls; the SYCL strata target failed to link without them) 2026-10-09 19:09:54 +02:00
Niko1221 3ff62ec140 docs: batch-MTP on a layer split with all experts in VRAM lost 21.9% (2x R9700); it pays only when the experts do not fit 2026-10-09 18:58:08 +02:00
Niko1221 7a4bc813ba conversation_transfer_test: wrap the calls of the non-blocking copy helper 2026-10-09 18:57:40 +02:00
Niko1221 a6346cdcea conversation snapshot/checkpoint copies: private non-blocking stream instead of the legacy stream (HIP capture conflict) 2026-10-09 18:57:40 +02:00
Niko1221 bb930bc8be Merge f-142b-amd into f-142 2026-10-09 18:57:36 +02:00
Niko1221 5a90e36cb3 Merge f-142b-intel into f-142 2026-10-09 18:57:36 +02:00
Niko1221 54d7f7d7c5 Merge f-142b-cuda into f-142 2026-10-09 18:57:36 +02:00
Niko1221 6e1085c1de Merge f-142b-serve into f-142 2026-10-09 18:57:35 +02:00
Niko1221 ca2730b14b docs: PF_FUSED KL re-check on IQ3_S / IQ3_XXS / Q2_0 (stays opt-in) 2026-10-09 18:11:08 +02:00
Niko1221 0b3139ec18 gfx906 build: refuse a wave32 card at start with a message (#1728); docs: community-tested, opt-in note 2026-10-09 18:11:01 +02:00
Niko1221 e33edd05bf bench #1726: keep the reporter's background-workload list complete (a desktop chat app was open) 2026-10-09 16:51:42 +02:00
Andrey Bash 354f982118 gfx906: add opt-in reduce12 QSA score reduction
Follow query-swizzle #1661 with the existing reduce-scatter pairing for
12 heads. Keep default paths and softmax/value/merge unchanged. Public
component parity and timing passed; model evidence uses frozen stack.
2026-10-09 16:48:03 +02:00
Andrey Bash 254f5aeca9 docs(gfx906): record 200K and API qualification for the combined candidate
Record archived-control output parity, verified candidate process, tools, CPU vision and cache restoration. No fresh 200K speed comparison or production promotion is claimed.
2026-10-09 16:48:03 +02:00
Andrey Bash 94bf9e5870 perf(gfx906): add guarded opt-in query LDS swizzle for batched QSA
Preserve FP operation order and invert a bijective shared-query layout at its vector loads. Limit the path to the current gfx906 wave64 device, INT8 pools and warp scoring. Default remains off.

Add deterministic GPU parity/timing and host-guard probes, plus scoped component and model receipts. The clean upstream build passed both-card byte checks; model gains are recorded separately on the frozen experimental stack.
2026-10-09 16:48:03 +02:00
Niko1221andmaxious 3540500232 sycl: the PCIe probe's pinned source (PR #1669) only on a layer split; a single card keeps the pageable source
Pinned memory reads the link 1.7x faster (A750 10.3 -> 17.2 GB/s, B70 13.6 -> 25.6), which moves the derived default pcie_frac
(A750 0.28 -> 0.47) and cost 10% of decode there (median 12.07 -> 10.67 tok/s, 4 of 5 interleaved pairs slower). The B70 is unchanged
(0.37 -> 0.55, 31.4 vs 31.4). The fault the PR fixes is a layer split's.

Co-authored-by: maxious <[email protected]>
2026-10-09 16:45:52 +02:00
Niko1221 a084fd2d72 serve: opt-in prevent_sleep keeps Windows awake while a request is running or queued (#1727) 2026-10-09 16:45:37 +02:00
Niko1221 392841e586 bench: COMMUNITY.md rows and the docs list entry for #1722 #1725 #1726; AI-tool mentions removed from the #1722 and #1726 READMEs 2026-10-09 16:44:46 +02:00
mgeldi 3971f78c98 bench: RTX 5090 Swift IQ3_XXS 1M tuning and native NVMe restore (PR #1722) 2026-10-09 16:44:46 +02:00
libratechw c82d2c16f6 bench: community report, RTX 3060 12 GB, Flash-Next Q2_0/IQ2_XS/IQ3_XXS/IQ3_S, engine 0.1.41 (PR #1725) 2026-10-09 16:44:46 +02:00
Enky 31946c78b9 bench: community report, RTX 5080 16 GB + Xeon w7-2475X, UD-IQ4_XS at a 786K context (YaRN x3), engine 0.1.41 (PR #1726) 2026-10-09 16:44:46 +02:00
Katsumi Takeuchi 9310d3bdf8 sycl serve: _pump routes --batch slot lines (BT/BDONE) and ends on a fatal line, as serve/server.py
server_intel.py replaces StrataEngine._pump to keep LP lines beside their token, but its copy predates --batch: the
slots' BT / BDONE lines went to the main queue, so with "parallel" every request stopped after one token. It also
missed the fatal-line handling and last_err. Both are now as in serve/server.py's _pump.
2026-10-09 16:44:40 +02:00
Katsumi Takeuchi 10be33ff9a sycl: with STRATA_VERIFY_NO_HOST and a mirror, adaptive swaps are off (they left experts in neither)
The host mirror holds the experts missing from VRAM at the start. An adaptive swap moves an expert that was resident
then out of VRAM, so it is in neither; the device plan then waits for the host to serve it, and with
STRATA_VERIFY_NO_HOST (the xe default in strata-sycl.sh) nobody does. Seen after a --batch window, whose host path
counts the misses the tier swaps on: the next single request on one card gave token 0 ("!!!!") at 0.8-1.3 tok/s.
The start already refuses experts in neither under NO_HOST; this keeps that true after the start.
2026-10-09 16:44:39 +02:00
Eli Elgaev e910e41034 dequant: coalesced Q8_0 path (four threads per block, 16-byte stores)
The prompt path dequantizes each dense Q8_0 projection (GDN qkv/gate/out,
QSA q/k/v/out, shared expert, hc) into the GEMM scratch before cuBLAS.
dequant_kernel runs one thread per 32-value block, so a warp's 2-byte
stores land 64 bytes apart: about 70 GB/s of writes on a V100.

dequant_q8_0_kernel gives each block to four threads, 8 values each,
written with 16-byte stores: a warp reads 8 consecutive blocks and writes
512 consecutive bytes. The arithmetic per value is unchanged (d * q), so
the output is the same bits. It is used for Q8_0 when the output rows are
contiguous (ld == cols) and the pointers are aligned (blocks to 2 bytes,
output to 16); everything else takes dequant_kernel as before.

V100-SXM2-16GB, every 2-D Q8_0 tensor of Qwen3.8-Flash-Next UD-Q4_K_XL
(498 tensors), each call timed on its own:

  attn_qkv 10240 x 2560, FP16   0.740 -> 0.106 ms   (70 -> 495 GB/s written)
  attn_q   12288 x 2560, FP16   0.887 -> 0.126 ms
  ssm_out   2560 x 6144, FP16   0.451 -> 0.065 ms
  all 498 tensors, FP16        138.5 -> 20.4 ms
  all 498 tensors, BF16        140.8 -> 20.5 ms
  all 498 tensors, FP32        190.9 -> 35.4 ms

An FNV-1a hash over all outputs is equal before and after for FP32, BF16
and FP16. Whole prompts on 4x V100 (where this was first used), 4,096-token
chunks: 18K 4,537 -> 4,708, 65K 6,540 -> 6,766, 123K 6,783 -> 6,985 tok/s.
2026-10-09 16:43:30 +02:00
bossman aab7e30d01 cpu: iq_avx1 - IQ4_XS gate/up stays on ggml's generic dot (the 128-bit grid kernel measures 0.7-1.0x against its auto-vectorized generic on an E5-2470 v2; the kernel stays built and parity-tested, only the dispatch declines it) 2026-10-09 16:29:59 +02:00
bossman dd7b0b5f07 cpu: AVX1 128-bit expert kernels (iq_avx1) - the i-quant rows on CPUs with no AVX2
The whole i-quant family (IQ3_XXS, IQ3_S, IQ2_S, IQ4_XS gate/up, IQ4_NL down) and the
fork's Q2_0 down have x86 dots only under __AVX2__ in ggml-cpu; on an AVX1 floor
(STRATA_ISA_FLOOR=avx, issues #595/#623/#1375: Xeon E5 v1-v2, and AVX-512-only packs)
the CPU-computed experts fall to the scalar _generic dots.  iq_avx1.cpp is the older
CPUs' copy of iq_avx2.cpp in the kq_avx1.cpp pattern: a separate TU compiled
-msse4.2 -mavx -mno-avx2 -mno-fma -mno-f16c, gated at runtime behind cpu_avx1_ok() and
only when AVX2 is absent, so no mainstream path changes.  128-bit integer lanes
(pshufb/sign/maddubs are SSSE3), 256-bit float accumulation, software half-to-float,
no gathers (the Fmt32 non-gather path), one IEEE mul per value like the AVX-2 copy.
Plus q8k_quant_avx1, the byte-identical Q8_K activation quantizer in SSE4.2/AVX1.

iq_avx1_parity: all six formats, nt=1..8, bit-exact across widths (#152) and within
1e-5 aggregate of ggml's generic dots; q8k_quant_parity now checks the AVX1 copy too.
gu rows take the AVX-2 mt_min policy (STRATA_IQ_MT_MIN), down rows always; kill switch
STRATA_NO_IQ128=1.  E5-2470 v2 (Ivy Bridge): 1.2-3.1x per expert at nt>=2, 2.0x on the
Q8_K quantizer; serve prefill +36-41%, warm decode 22-25 -> 46 tok/s.

Known pre-existing gap found while testing: pool_tasks_test SIGILLs on non-AVX-512
machines even on a clean tree (it predates the ISA floor and is not gated).
2026-10-09 16:29:59 +02:00
bossman 7b14a443ee cpu: q2_avx1 - the Q2_0 rows and the Q8_1 quantizer for CPUs with AVX but no AVX2 (fixes #1699)
q2_rows_any and act_quant_any had two rungs, AVX-512 and AVX2, and the else branch
checked nothing: an AVX-only CPU was handed AVX2 code and died with SIGILL (found on
an E5-2470 v2; pool_tasks_test and q2_bitplane_parity crash on a clean tree, and any
future caller inherits the trap).  The third rung: q2_avx1.cpp in the iq_avx1.cpp
containment pattern (-msse4.2 -mavx -mno-avx2 -mno-fma -mno-f16c, a #error guard,
called only behind cpu_avx1_ok() && !cpu_avx2_ok()).  128-bit integer lanes (maddubs,
madd), 256-bit float accumulation, software fp16 scales; the legacy kernel keeps the
AVX-2 kernel's lane pairing and reduction tree (its FMA becomes a mul+add, last bits),
and the bit-plane kernel and its image builder port as-is (pure SSE).  The AVX-2 and
AVX-512 paths are untouched.  q2_bitplane_parity now runs on the AVX-2 pair where the
CPU has AVX2 and on the AVX1 pair below it, and skips cleanly without AVX.

E5-2470 v2: pool_tasks_test 168 bitwise comparisons pass, q2_bitplane_parity PASS -
both SIGILL'd before.
2026-10-09 16:29:59 +02:00
Niko1221 72a67c8e90 sycl: the grouped XMX kernels (sub-group 8, joint_matrix 8x8x16) are Arc A-series only: an AOT build for Xe2 / Xe-HPC leaves them out (STRATA_NO_DG2_XMX), STRATA_PF_XMX is ignored with a message on Battlemage, and xmx_group_parity skips there
PR #1711 as posted made the Arc Pro B70 AOT build (bmg-g31) fail to link: the backend compiler rejects the sub-group 8 kernel.
2026-10-09 16:01:57 +02:00
Niko1221 115e8ce334 Windows HIP: the auto cache's 2560 MiB reserve floor also covers 16 GB cards (they report 15.9 GiB) (#1709; Windows HIP test pending) 2026-10-09 15:50:58 +02:00
W1nge 268647d2ec prefill: take expert blobs from a helper's VRAM cache when it holds them
A helper GPU's expert cache already holds a copy of the blobs the prompt path
streams, and the helpers compute nothing while a prompt is read on a serial
request path. Add RemotePrefillSource, an ExpertSource that wraps the file
source and asks the helpers first: a blob a helper holds is copied
cache-to-host on that helper's own stream, misses are merged into one call to
the fallback's existing batched reads, and every other decision is forwarded
unchanged.

Opt-in through STRATA_PREFILL_HELPER_SOURCE; it applies only where the serve
path is serial (one GPU, no layer split, no batch slots) and the prompt path
streams every expert the main card does not hold. Same-day A/B on an
11-request fixture: 91.5 s -> 65.7 s of prefill (-28.3%) and 92.1 GB (64.8%)
fewer bytes read from the files.
2026-10-09 15:49:23 +02:00
Niko1221 acee40a597 serve: a sampling field sent as a numeric string is read and used, not a 400; only values that cannot be read as the right type are refused (#1663) 2026-10-09 15:43:57 +02:00
Niko1221 40bdd86d6d serve: content parts the server does not read (tool_reference, document, search_result, server tool blocks, file, audio) are left out as before, with a debug line, not a 400 (#1664)
Real clients send them next to text the model can answer from.
2026-10-09 15:37:32 +02:00
Niko1221 a6ae247561 serve: a reasoning_effort key in the run config sets the thinking level of requests that name none; --reasoning-effort in args is lifted into it with a note (#1641) 2026-10-09 15:36:37 +02:00
Niko1221 ccd0062fa8 bench: drop the tool-attribution line from the 2x RTX 3080 report (the numbers are the submitter's) 2026-10-09 15:36:37 +02:00
Niko1221 5267eb6565 docs: COMMUNITY_BENCHMARKS.md lists the three new reports once, after the existing ones 2026-10-09 15:36:36 +02:00
Niko1221 4ed0ed68d7 bench: COMMUNITY.md rows for the community folders ported from #1638 #1647 #1655 #1681 #1692 #1695 #1716 #1717 #1657 #1640; the 6900 XT 0.1.40.1 row now has the numbers #1657 added 2026-10-09 15:36:36 +02:00
zihaomu 22b3b80970 bench: single R9700 performance report (PR #1638) 2026-10-09 15:36:36 +02:00
noon-at-cgn 9a06a54aa8 bench: community report, 2x RTX 3080 20 GB, UD-Q4_K_XL, 2 x 262K lanes in a 512K pool (PR #1640) 2026-10-09 15:36:36 +02:00
Mitsuasa513 3c2eb23a00 bench: community report, a Tesla V100 (sm_70) confirms the opt-in Volta decode kernels (PR #1647) 2026-10-09 15:36:36 +02:00
Cass 2d49e6178d bench: community report, 4x RX 7900 XT (gfx1100), Flash-Next IQ3_S at 262K, five opt-ins off vs on, engine 0.1.41 (PR #1655) 2026-10-09 15:36:36 +02:00
Vop3p fed30695a1 bench: community report, 2x RX 6900 XT (gfx1030) + Ryzen 5 5600X, IQ3_S at 131K on 0.1.41 (PR #1657) 2026-10-09 15:36:36 +02:00
KarlGrier c8250a09b4 bench: community report, RTX 5080 16 GB + RTX 4060 Ti 8 GB (helper cache), IQ3_S at 4K / 32K / 128K on 0.1.41 (PR #1681) 2026-10-09 15:36:36 +02:00
David 5d7b7b6719 bench: existing RoPE vs YaRN at 512K and 1M, with setup guide (PR #1692) 2026-10-09 15:36:36 +02:00
Your Name a43b94c4c4 bench: P4 prefill 78.8 -> 114.8 tok/s with existing auto sizing; expert reuse roofline (PR #1695) 2026-10-09 15:36:36 +02:00
nsbradley88 257b6c2b4c bench: community report, Strix Halo laptop (Radeon 8060S, 70 W), v0.1.41, UD-IQ4_XS (PR #1716) 2026-10-09 15:36:36 +02:00
libratechw 1fe02e5de2 bench: community report, Radeon 8060S (gfx1151) on a Ryzen AI Max+ 395, UD-IQ4_XS, engine 0.1.41 (PR #1717) 2026-10-09 15:36:36 +02:00
Moge800 e651c0cd16 docs: improve Japanese README wording and readability 2026-10-09 15:36:36 +02:00
nekomario28 cc75882480 docs: STRATA_PREFILL_CPU_SHARE=auto is not repeatable run to run (#1684)
The share is picked from wall-clock timings, so the same short-prompt
request can split the experts differently each run and the answer moves
in its last bits - a resumed conversation's re-read need not match its
first (31 of 1,536 teacher-forced argmax tokens differed in the
reporter's test).  A fixed share repeats; 0 gives a run without it
byte-for-byte.
2026-10-09 15:36:36 +02:00
Niko1221 92507aac38 setup: on a unified-memory APU write the expert cache as a number that leaves the OS its RAM, not auto (#1715) 2026-10-09 15:24:07 +02:00
LeGeRyChEeSe 66aaed2119 tools/agent_turns_bench.py: decode A/B on coding-agent turns over this repository, per-turn ratios
Five simulated agent sessions over the repository's own files (system prompt, four tools, real files as tool
results, at most 2000 lines per read): 23 turns from ~2.5K to ~100K tokens, consecutive turns sharing their prefix.
Arms as ab_engine.py takes them; rounds mirror the arm order on fresh servers; prints the median of the per-turn
decode ratios to the first arm and the turns it won. Nothing personal and nothing downloaded.
2026-10-09 15:23:32 +02:00
LeGeRyChEeSe 65268d9961 STRATA_ROUTE_TAIL_SKIP=R: missed experts routed only at rank >= R are neither copied nor computed
A missed expert that every token of the verify window routes at rank R or lower in weight contributes zero
(no renormalisation): less PCIe traffic and CPU expert work. Counted in the request log. Opt-in, changes
the output.
2026-10-09 15:23:32 +02:00
LeGeRyChEeSe 2de9ae061f STRATA_ROUTE_PRIOR=lambda: cache-conditioned routing in verify windows (opt-in, changes the output)
The top-10 is picked again with a logit bonus lambda for the experts resident in VRAM; the weights stay the
router's probabilities renormalised over the 10 picked. After 'Mixture of Cache-Conditional Experts'
(arXiv 2412.00099), without training. Complements STRATA_ROUTE_RESIDENT (a tail swap within a margin):
every rank can move, by an amount the logits decide.
2026-10-09 15:23:32 +02:00
sergiywith f04ab568fe Resident RAM mode on Windows: the GPU cache's fill and the RAM copy read experts.bin unbuffered, the view closed meanwhile
With --resident-experts (setup's low-RAM mode when the experts the GPU does not hold fit the RAM) the start copies
the profile fill of the GPU cache and the RAM copy (pin_cache_complement) through the mapped view of experts.bin.
Every page it touches sits in the process working set beside the page-locked copy until #467's trim after the fill
and the VirtualUnlock after the copy: on a PC short of RAM that pages other memory out, and the copies run at the
page-fault rate (~0.85 GB/s here).

FileExpertSource::begin_startup_unbuffered closes the view, the section and the buffered handle, opens the
unbuffered handles (open_direct) and reads the first blob both ways; if the open fails or the two differ, the view is
mapped again and the start copies through it as before.  The fill (prefetch_pairs) and the copy (pin_cache_complement)
then take their existing unbuffered paths (read_direct: requests merged up to 32 MiB).  end_startup_unbuffered maps
the view again (map_view, the size checked) and closes the unbuffered handles and the stage buffers, so the file tier
is chosen as before.  Same bytes in the same places.

Windows and experts.bin only: the call is under _WIN32, and the GGUF in place, an unbuffered file tier and runs
without a RAM copy are unchanged.  STRATA_STARTUP_UNBUFFERED=0 gives the mapped copy back; STRATA_VERIFY_COMPLEMENT=1
prints checksums of the filled cache slots and of the RAM copy.  pin_cache_complement no longer VirtualUnlocks the
range of a closed view.

IQ2_XS (33 GiB experts.bin), RTX 5090, Samsung 9100 PRO, --resident-experts --expert-cache auto (~15,200 slots, a
16.4 GiB RAM copy), interleaved against fb58e0db:
- 21 GiB available (a RAM ballast; #467's 32 GB PC had 20.7 GiB), 6 pairs: ready 42.5 -> 9.6 s (chat), 40.7 -> 10.2 s
  (32K); the fill 842 -> 6,914 MB/s, the copy 13.7 -> 3.3 s; lowest available 0.25 -> 4.5 GiB; pages written out
  ~60,000 -> 579-3,340; 3 of 12 base starts held available RAM under 1 GiB for 2 s, none of 12 here.
- 128 GB: peak working set 32.6 -> 18.3 GiB; a restart with the file cached 13.6 -> 8.3 s; the 32K prompt and decode
  unchanged.
- Same bits: p2k 200 tokens and first-token logits, 32K 64 / 256 tokens, as fb58e0db; STRATA_VERIFY_COMPLEMENT=1
  checksums identical to STRATA_STARTUP_UNBUFFERED=0 (12,595 and 15,438 slots).
2026-10-09 15:23:14 +02:00
Niko1221andRealScaniX 1a62f6df6e serve: a tool set that comes back in another order keeps the order it was first seen in, so the prompt prefix and its cache survive (#1624)
Based on RealScaniX's sorted-by-name change; the first request of a set stays byte for byte as the client sent it.

Co-authored-by: RealScaniX <[email protected]>
2026-10-09 15:23:02 +02:00
W1nge 29d93c6407 test: keep vision device isolation independent of local GPU order 2026-10-09 15:22:14 +02:00
chaog992 efaa87aba2 tools tests: align test_setup_risk's WSL mock with install() (the KV-streaming rule test failed inside WSL)
RulesAgreeWithTheWrittenConfig.test_the_streaming_rule_is_the_flag_setup_writes runs setup.main() through
test_setup_golden's install(), which mocks is_wsl() to False, and then asked setup.kv_streaming_wanted() outside
that mock. Inside WSL the real is_wsl() is True, so the rule answered "no streaming" while the config setup wrote
for the mocked PC has --kv-resident, and the test failed at its first 131072 case (Q2_0, int8, auto). With is_wsl()
the same on both sides, setup and the rule agree in all 54 cases, inside WSL and out.

The test method now runs under the same is_wsl mock as install(), the test-only fix the unsloth tests got for #974
(d1ec32b). setup.py is unchanged; where is_wsl() is already False (Windows, native Linux) the test runs as before.

Tests: python3 tools/test_setup_risk.py (WSL2, Python 3.12.3: was FAILED (failures=1), now 40 tests OK); the other
27 tools/test_setup_*.py files give the same results as before.
2026-10-09 15:22:14 +02:00
hash13 bafc8dd556 monitor: show prefill rate in recent requests 2026-10-09 15:22:13 +02:00
zeevo 95452866b2 add a prometheus metrics endpoint 2026-10-09 15:22:01 +02:00
midagedev 1f6958c13b serve: a sampling field of the wrong type is a 400 that names it
A request with "temperature": "0.7", "top_k": 40.0 or "seed": true was
answered 200 and sampled greedy: the value replaced the configured
default in run()'s merge, then sampling_keys dropped it as not a number.
check_request_sampling refuses it by name before anything is sent, as
POST /settings and the run config already do. Only types are checked;
ranges, null fields and in-type values behave as before.
2026-10-09 15:21:45 +02:00
Niko1221 fbc60ee157 logit_bias: leave the contributor's raw receipts out of the tree, point the doc at the reproduction script 2026-10-09 15:21:38 +02:00
midagedev 5804094b2f serve: a content part the server does not read is a 400 on chat and messages, as on responses
A chat "file" or "input_audio" part, and a messages "document" block
(also inside a tool_result), were dropped without a word: the request got
a 200 and the model answered about a file it never saw. _check_parts
refuses them while the request is converted, naming the type and where
it sits, with /v1/responses' wording. Text, images, thinking, tool_use
and tool_result read as before; redacted_thinking is still dropped; a
chat "refusal" part reads as its text, as on /v1/responses.
2026-10-09 15:21:32 +02:00
David 18e7487e52 docs: demonstrate Hello token bias with measured before and after requests 2026-10-09 15:21:30 +02:00
David dcc6f756cc fix(api): apply request logit biases in CUDA and HIP sampling 2026-10-09 15:21:29 +02:00
Niko1221 52f548f45a server: death_note scans the last 256 KB for the watchdog line, so a long verify trace cannot hide it (#1705) 2026-10-09 15:20:31 +02:00
CC-David-CC c81f99849e fix: defer pipelined one-token commits to the host verdict 2026-10-09 15:20:28 +02:00
ruibeikaa dc9b219944 prefill: let native-layout packs take STRATA_MMQ_RESIDENT_SORT_NE
The row-count sort of a fully resident layer's experts skipped native-layout packs, though slot/src/off are
built the same way for both layouts. 4x GP100 (sm_60): 1.2K prompt 7.27 -> 5.32 s, 35K 63.3 -> 54.1 s, the
same bits. The switch stays opt-in.
2026-10-09 15:20:05 +02:00
sergiywith d0336684e5 kv-grow: kvg_trim uploads the residency table with res_put, which waits for the copy
kvg_trim refilled the slots the K/V gave back and then uploaded host_res with a plain cudaMemcpy from pageable memory.
That returns once the table is staged, before its DMA lands, and nothing after it waited for stream 0: the next
request's session_zero syncs main_stream only, and a prompt part of --short-read tokens or fewer goes straight to
ver.run, whose graph reads hits_.d_res on the verifier's cudaStreamNonBlocking stream. res_put (#550) is the upload
every other residency change uses: the same copy, then cudaStreamSynchronize(nullptr).

kvg_ensure's upload needs nothing: qsa_kv_elastic_grow ends in cudaDeviceSynchronize before anything reads the table.
Only --kv-grow (opt-in) runs kvg_trim, so the default path is unchanged.
2026-10-09 15:20:05 +02:00
nekomario28 14b9dd2e52 serve: keep-alive while a tool call's held-back argument is generated (#1666)
With stream_tools an array or object argument is held until it is whole,
so a large one (a measured 66 KB edit_file call) left the stream silent
for minutes while tokens were generated - a client's idle timeout then
ended a healthy request (Forge's is 120 s).

The token loop now tracks when anything last went out and sends the
engine's own keep-alive ping after KEEPALIVE_S (10 s) of silence - the
same ping the quiet-engine heartbeat sends, so clients already ignore it.
The reporter's reproduction measured a 27.8 s longest gap on a 7 KB
array (minutes on the 66 KB one); with this change it is 10.0 s and the
call arrives intact.

Change and live measurements from the issue; adds the ping-cadence unit
test (a patched clock over a held-back <tool_call>).
2026-10-09 15:19:48 +02:00
Niko1221andjkuepker 3a55dfd253 HIP: STRATA_HEAD_MIX_MULTI and STRATA_ONE_TOKEN_COMMIT as opt-ins (=1), default stays off (#1479)
Patch from the issue by jkuepker.

Co-authored-by: jkuepker <[email protected]>
2026-10-09 15:19:04 +02:00
Niko1221 00b14af827 sycl: #1710 stays opt-in: STRATA_SYCL_A770_FAST=1 gates the fast router, the paired payload stores and the paired mapped read; plain payload stores (i915, stepped window) are never paired
The default router, publish and copy_or_zero kernels are the f-142 ones. The probes set the variable (and
STRATA_DOORBELL_CHECK=1 for publish_res, which copies x only on a miss otherwise).
2026-10-09 15:18:03 +02:00
duncanmcqueen 174c74c07f sycl: add experimental A770 router and mapped-transfer tuning
Port the fork's fast router with a bracketed reciprocal and serial fallback. Add bitwise comparisons against the existing router, including ties, NaN tails and the forced serial path. On the A770's 256-expert/top-10 shape, measured host submission plus execution fell from 395 to 119 us per call.

Pair activation payload stores and mapped result reads into 64-bit uncached transfers, preserving the checksum and unaligned/odd-tail fallback. Register router and payload probes with CTest. The two probes, elementwise_parity and router_top10_parity passed on the A770.

Add the fork's opt-in host-clock stage profiler for further investigation. Profiling remains experimental: enabled runs encountered a payload-arrival timeout, and review flagged concurrent atomic host writes versus non-atomic device clock reads as a synchronization concern. The profiler is not needed for normal inference.

With CPU-computed misses, cache borrowing and an 8.98 GiB VRAM cache, unprofiled Coder IQ1_M runs generated 128 tokens at 11.9-13.5 tok/s and returned final arithmetic answer 41. These runs retained 128K context capacity but used short prompts; the 20 tok/s goal has not been achieved.
2026-10-09 15:17:50 +02:00
midagedev e85567b617 generate, mtp: near the context's end the spec window and its drafts stay inside it
The admission checks prompt + max_new <= max_context, but the spec loop
opened every window at S_mtp rows, so a request that fits ended with
"ran out of context" (rc 2) once p + S passed the end, and printed
nothing. The window now takes only the rows the context still holds.
MtpDrafter::draft wrote draft j at cell p + a + j for every step, past
max_cells near the end, where the page table has no entry; it now drafts
only the cells that exist. Far from the end nothing changes.
2026-10-09 15:17:33 +02:00
saikiran-rs 730700126b verify: initialize remote expert helper state in both batch paths 2026-10-09 15:17:33 +02:00
nekomario28 092fc3c5c6 setup: pass CC/CXX/CUDAHOSTCXX to the CUDA build's cmake (#1645)
CUDA 12 refuses a GCC newer than 14, and the docs already tell the user
to run CXX=g++-14 ./setup.sh - but the environment only reaches CMake on
a build folder's FIRST configure, so on a retry (or the encoder's own
folder) the flag never landed: the reporter's run died at the last step.

host_compiler_defs() maps them onto -DCMAKE_C_COMPILER /
-DCMAKE_CXX_COMPILER / -DCMAKE_CUDA_HOST_COMPILER for the engine and the
CUDA image encoder; CUDAHOSTCXX defaults to CXX, as CMake's does.  A
C++-only build (the CPU encoder) is not given the CUDA one.
2026-10-09 15:17:13 +02:00
noon-at-cgn 2eafe7f90d docs: the adaptive tier in batch windows - measured on 2x RTX 3080 20 GB, tier on, blocking, frozen and off 2026-10-09 15:16:22 +02:00
Andy Slater c2d008bc80 sycl: stepped verify window - CPU experts served between graph segments, cached host buffers and plain payload stores
STRATA_VERIFY_STEPPED=1 (Arc A-series): the doorbell window is captured as graph segments ending at each layer's
publish; the host serves the CPU experts between segments, pipelined with the plan copy + VRAM groups on a helper
thread pinned to the host thread's SMT sibling. No kernel then reads a host store while it runs and no host reads a
kernel store while it runs, so the window's mapped buffers are ordinary host USM and the publishes use plain stores
(STRATA_VERIFY_HOST_UNCACHED=1 keeps both uncached). A770, Coder IQ1_M, 8K prompt: GPU wait per window ~70 -> ~43 ms,
decode 22.8-25.0 -> 31.8-32.5 tok/s; 32K 27.2 tok/s.
2026-10-09 15:16:22 +02:00
noon-at-cgn b5d520313a batch-groups: --adapt-async 1 also keeps the 0.1.41 auto default at one group (said once)
The pipelined slot groups never run the adaptive tier, so --adapt-async 1 with --batch on a layer split and no
--batch-groups resolves auto to one group, like --batch-mtp (batch_groups.hpp, batch_groups_test); --batch-groups G
or auto given on the command line is honoured and turns --adapt-async off through the existing gate.
2026-10-09 15:16:22 +02:00
noon-at-cgn 495dc43690 batch: tick the asynchronous adaptive tier (--adapt-async 1) between batch windows; --adapt-min-gain
batch_step advances the async round one step per window (never between a prompt's chunks), commands drain the round in
flight before they run, a round with nothing to swap ends at its first step, and --adapt-min-gain sets the bar a swap
must clear (default 1.5, as before) for both tiers. --adapt-async is no longer refused with --batch slots (still with
--batch-groups).
2026-10-09 15:16:22 +02:00
noon-at-cgn e989c67194 batch: the adaptive VRAM expert tier keeps adapting in batch windows; per-stage timing in the strata batch line
batch_step now runs adapt() every --adapt-every windows on a thread beside the commit and the drafts, lands the swaps
(apply_pending) before the window ends, and pauses while a prompt holds a loan of cache slots. The timing line adds the
adaptive tier's rounds/swaps and wait, each stage's GPU-reach wait and pool time, and the VRAM/PCIe/CPU entry split.
2026-10-09 15:16:22 +02:00
noon-at-cgn de71d7bef4 docs: batch MTP on a layer split - measured on 2x RTX 3080 20 GB (0.1.41 build and the earlier 0.1.40.3 runs), with what was not measured 2026-10-09 15:16:16 +02:00
noon-at-cgn f90bec6f44 batch-mtp: not with helper expert caches on a layer split (not run); docs say how it meets --batch-groups
The 0.1.41 default --batch-groups auto, the pipelined path's lack of slot drafts and the helper-cache refusal are
written down in docs/BATCHING.md (the limits list and the --batch-mtp paragraph).
2026-10-09 15:16:16 +02:00
noon-at-cgn cb6c549c8a batch-groups: the 0.1.41 auto default gives way to --batch-mtp (one group, said once)
--batch-groups auto became the default for a layer split with --batch >= 2, but the --batch-mtp gate ran before
the groups were resolved: it saw 1 group, kept batch-MTP on, and the groups were then raised to 2 - pipelined groups
do not run the slots' MTP drafts (#1413). The resolution is now a pure helper (include/strata/program/batch_groups.hpp,
CPU test src/program/batch_groups_test.cpp): with --batch-mtp and no --batch-groups the default is one group and
the log says why; --batch-groups N (N > 1) or --batch-groups auto given on the command line pipelines the groups and
turns --batch-mtp off, as before.
2026-10-09 15:16:16 +02:00
noon-at-cgn 70fc0ba46d batch-mtp: log the accepted proposals in the batch summary 2026-10-09 15:16:16 +02:00
noon-at-cgn 48f2c47d54 batch-mtp: work with a layer split (slot drafters on the last stage's GPU, grouped slot rows through every stage)
- generate.cpp: --batch-mtp accepted with a layer split on separate GPUs (refused with --batch-groups); slot drafters
  load from the last stage's slot sessions under the last stage's device guard and bind to its weights/head; their
  residual buffers, row copy (async on the drafter's stream) and draft-KV copies run on the drafter's device; every
  stage verifier gets the 8-row window size and the batch graph limit; slot-drafter logits are not charged to CUDA0.
- verify.cpp: stage_batch's layout rules move to include/strata/core/batch_rows.hpp (CPU test batch_rows_test); grouped
  rows are allowed on a stage that hands rows on, the hand-off bound is kVerifyMaxT rows.
- docs/BATCHING.md, --batch-mtp help text.
2026-10-09 15:16:16 +02:00
sergiywith c396dc9c39 setup: the page-file warning advises a fixed size, and says why when Windows is set to grow the file
Step 1 warns below 4 GB of page file (issue #60) and advised "Set it to System managed". In #60 that did not help:
"System managed" and 4096-32768 MB still ran out of commit, and a fixed 64 GB worked - a page file Windows grows on
demand may not grow in time while WDDM charges the card's memory to the commit.

- The advice is a fixed size: Custom size, the same initial and maximum size, 65536 MB (PAGE_FILE_FIXED_MB).
- page_file_setting() reads the Virtual memory setting (PagingFiles; "?:" is the drive in ExistingPageFiles). When a
  file is system-managed or its initial size is below its maximum, the warning says that it grows on demand and that
  a growing page file may not keep up (#60).
- page_file_gb() still counts only what is there for sure: the commit limit minus RAM, as before, or a file's
  configured initial size when that is larger (within its drive's free space). Never the maximum or what a
  system-managed file may grow to. The 4 GB threshold is unchanged.
- docs/AI_SETUP.md and docs/DETAILS.md give the same advice.
- tools/test_setup_page_file.py: the parsing, the reading, the advice, and step 1 under --check on the golden
  harness's 32 GB PC (registry, drives and GlobalMemoryStatusEx mocked; runs on Linux too).
2026-10-09 15:16:03 +02:00
SuperLee 52c743d550 mcp: let the swift family take IQ3_S too; docs
The MCP server's FALLBACK_MODELS carries its own copy of the model
table, so #1688's setup.py fix leaves the MCP install path rejecting
--family swift --model IQ3_S. Drop the families gate there as well,
flip the validation test, and update the three doc lines that say
IQ3_S is original-model-only.

Measured on an RTX 3090 pair (engine 0.1.40.3, Swift IQ3_S, 200K
context, MTP spec on): 91-137 tok/s decode, expert cache hit rate
96-99%, KV streaming 98.6-99.6% VRAM hits.
2026-10-09 15:15:53 +02:00
nekomario28 614053a4d7 setup: let the swift family take IQ3_S (#1651)
UkisAI published a Swift 1.5 IQ3_S tier on 2026-10-08; the
"Swift 1.5 has no IQ3_S" restriction is stale.  Both shards match the
family's file pattern exactly (names/sizes/SHA-256 verified against the
Hub listing), the shard count and the shared BF16 mmproj are unchanged,
so it takes the same path the other Swift tiers already use.
2026-10-09 15:15:53 +02:00
Andy Slater 0e583707a5 sycl: grouped XMX passes the decoder thread that writes [o, o+8) for the run-of-8 IQ decoders
The IQ2/IQ3/IQ4_NL/IQ1_M decoders now write values [8 tid, 8 tid + 8) of a superblock (coalesced runs, as Q2_0
already did); iq_xmx_grouped still passed the IQ4_XS-style (sub-run, 32-block) index for them, so the B tile held
the wrong values (xmx_group_parity relerr 7-17 on types 18/20/21/22).  All six types back to ~1e-6.
2026-10-09 15:15:25 +02:00
Andy Slater ce60cc373f sycl/A770 prefill: grouped XMX expert GEMM (opt-in STRATA_PF_XMX=1/2)
- xmx_moe: joint_matrix FP16 GEMM over a group of up to 16 experts per launch (grf 256).
  Standalone vs oneMKL on uneven routing: down 1.75-6x, gate/up 0.8-3x (oneMKL kept above
  STRATA_PF_XMX_GU_MAX=250 tokens/expert).
- STRATA_PF_XMX=2: iq_xmx_grouped decodes IQ3_XXS/IQ3_S/IQ2_S/IQ4_XS gate/up and IQ4_NL/Q2_0
  down rows in-kernel (no FP16 staging); xmx_group_parity: rel err < 2e-6 vs dequant+oneMKL.
- End to end (8K/32K prompt, A770): +2-5% only; default off.
2026-10-09 15:15:25 +02:00
W1nge 538ef3aa5b prefill gemm: run a failing FP16 shape on a fixed cuBLAS algorithm; the default one fails once a second device's context exists (issue #1650) 2026-10-09 15:15:06 +02:00
Cass 553b0b788c pipeline-windows: overlap three or more layer-split stages; HIP drafter scratch race
--pipeline-windows 2 now runs on any layer split with two or more stages. Every
stage but the last is a front stage: the guessed window follows the verified
one through them one card behind (an odd verifier and an odd hand-off on every
boundary, a pair of GDN snapshots on every front stage, commits and the undo
per stage), and only the last stage waits for the verdict. The pipelined prompt
read (--pipeline-windows 1) and --adapt-async stay two-stage.

HIP: the draft layer's per-row gr_read used the last stage's session scratch
(ss.block.gr), which that stage's verifier also uses in lm_head_mix. A chain
launched at a verdict and the next window's last stage can run on the card at
once after a guess that held, and the window's head then read a clobbered mix.
The draft layer now carves its own GrWorkspace.

Measured on 4x RX 7900 XT (Flash-Next GSQ-RCO IQ3_S, split 12,24,36, every
expert in VRAM, greedy, reasoning off): decode 59.4 -> 67.6 tok/s at 4K and
51.8 -> 65.6 at 32K. Greedy text identical to the serial loop on four prompts
with STRATA_IQ_MT_MIN=1 --pcie-frac 0 --adapt-every 0, also with every guess
forced wrong. Debug knob STRATA_PIPELINE_SPEC_DEPTH. Two-stage path not re-run
on two cards.
2026-10-09 15:14:37 +02:00
Alex Sadleir 7e940789e6 Clean up comments in generate.cpp
Removed comments regarding memory allocation issues and synchronization behavior.
2026-10-09 15:14:19 +02:00
maxious 4340476438 sycl: pin the PCIe probe's source buffer
probe_pcie_h2d_gbps: a pageable 256 MiB source made the copy engine fault
inside the driver's bounce path on a layer split (755x bcs VM_NOT_FOUND at
the fixed VA 0xffffc001ffa10000, L4 = the region never mapped for that VM,
intermittent on fresh boots, wedging the whole load in both the 0.1.40
port and 0.1.41). Pin the source (sycl::malloc_host) and free it with the
matching sycl::free. Validated: two consecutive loads reached the window
without the wedge.

All the split-fault instrumentation (guard watch, stage stamps and the
STRATA_STAGE_WAIT serial gate, terminate dumps, coredump grabbers) lives
on scratch/split-fault-instruments.
2026-10-09 15:14:19 +02:00
Katsumi Takeuchi c98902a657 sycl: MtpDrafter's queue defaults to nullptr, so a run without --mtp no longer crashes at exit
dpct turned `cudaStream_t cs_ = nullptr` into `&dpct::get_in_order_queue()`: a drafter that never loads keeps it, and
its destructor destroys the device's default queue (exit 139, sometimes UR_RESULT_ERROR_UNINITIALIZED, after the output).
Arc Pro B70 at fb58e0d without --mtp: 3 of 3 runs crashed before, 0 of 3 after; output unchanged with and without --mtp.
2026-10-09 15:14:19 +02:00
Niko1221 04dbe56145 CPU prefill share: skip the default when host memory is short, and never fail a chat on its buffers
0.1.41 report (RTX 5090, tight RAM): chats failed and the engine restarted until STRATA_PREFILL_CPU_SHARE=0.
- share_rules: default_share_memory_verdict. The default is not armed when the RAM this process can get
  (cgroup-aware) is below the share's buffers + 3 GiB, when the Windows commit left is below buffers + 4 GiB,
  or when the experts it would read are file pages the free RAM cannot keep. One log line says why and that
  STRATA_PREFILL_CPU_SHARE=auto turns it on anyway. An explicit setting is kept and only warns.
- prefill: the share's two pinned buffers are taken once at their largest (an expert takes at most MAXT
  tokens' rows); a failed allocation ends the share for the run instead of failing the request.
- unit test, docs/DETAILS.md.
2026-10-09 15:10:32 +02:00
Niko1221 65d97b0ab6 memory_guard_test: build on Windows (process.h getpid instead of unistd.h) 2026-10-09 15:00:53 +02:00
Niko1221 abbd0ea9aa sycl prefill: bytes_needed* take the src flag like the shared header (merge of the multi-GPU stream) 2026-10-09 15:00:53 +02:00
Niko1221 76790f277a test_slots: compare the relative save dir through realpath (8.3 temp dir names on Windows) 2026-10-09 14:47:49 +02:00
Niko1221 3d247dd49c Cap a thinking budget at max_tokens less an answer reserve, so the reply is not cut off while still thinking (#984) 2026-10-09 14:47:32 +02:00
Niko1221 bce19db445 Progress line shows the thinking budget, not max_tokens, while one applies (#984) 2026-10-09 14:47:31 +02:00
Niko1221 5a6ef1d768 Merge branch 'f-142-amd' into f-142
# Conflicts:
#	serve/server.py
2026-10-09 14:47:31 +02:00
Niko1221 3fb23b146a Merge branch 'f-142-intel' into f-142 2026-10-09 14:47:08 +02:00
Niko1221 43b105a753 Merge branch 'f-142-mgpu' into f-142
# Conflicts:
#	src/program/generate.cpp
2026-10-09 14:47:08 +02:00
Niko1221 e85f56209c Merge branch 'f-142-engine2' into f-142
# Conflicts:
#	src/core/conversation_memory.cpp
2026-10-09 14:46:54 +02:00
Niko1221 760007e311 Merge branch 'f-142-carry' into f-142
# Conflicts:
#	src/program/generate.cpp
2026-10-09 14:46:36 +02:00
Niko1221 f5aa356f14 Merge branch 'f-142-small' into f-142 2026-10-09 14:46:18 +02:00
Niko1221 2dc6eeae42 Merge branch 'f-1411' into f-142 2026-10-09 14:46:18 +02:00
Niko1221 b70bc033b5 sycl: plain payload stores on the i915 driver (the uncached hint is for xe); STRATA_DOORBELL_PLAIN overrides 2026-10-09 14:08:15 +02:00
Niko1221 f583670cab sycl: Alchemist own-buffers prompt path only on cards with >= 12 GiB; the payload copy stays conditional unless STRATA_DOORBELL_CHECK=1 (A750 A/B, PR #1602) 2026-10-09 13:09:03 +02:00
Niko1221 68d66b117f memory_guard_test: a .. component in the cgroup path falls back without a cap 2026-10-09 12:38:17 +02:00
Niko1221 b0531c8dad memory_guard_test: memory.current "max" without a cap falls back too 2026-10-09 12:37:43 +02:00
Niko1221 c9680eeff6 memory guard: unusable cgroup files without --memory-limit-mib fall back to MemAvailable with one warning; with the flag the sample stays unknown 2026-10-09 12:37:05 +02:00
Niko1221 399a75c8ad tools: batch_groups_cache_test.py reads the engine log only 2026-10-09 11:51:43 +02:00
Niko1221 da6f23f8e9 ple: print the direct-read probe's rate when it is fine 2026-10-09 11:21:33 +02:00
Niko1221 3157c78935 sycl: the doorbell payload checksum wait is opt-in (STRATA_DOORBELL_CHECK=1): on an Arc A750 it cost 17% of decode (#1606, PR #1602) 2026-10-09 11:15:36 +02:00
Niko1221 5025d63a22 sycl: STRATA_SYCL_JIT_STATELESS option for the JIT build's 64-bit-address flag (default ON, as in #1602) 2026-10-09 11:15:35 +02:00
Niko1221 7609cc18a1 arch_defaults gfx12: drop STRATA_HCD_EXACT (inert without the gfx1151 tuning table, and noisy); five prompt switches, measured +0.8/+1.6/+1.8% at 4K/16K/32K on an R9700 (IQ3_S) 2026-10-09 10:51:41 +02:00
Niko1221 31ffa153c6 tools: session_pressure_test.py and batch_groups_cache_test.py 2026-10-09 10:30:16 +02:00
Niko1221 22a893d0c6 Version 0.1.41.1: project version and the setup minimum engine 2026-10-09 10:24:42 +02:00
Niko1221 8bf203f56b STRATA_ROUTE_RESIDENT: per-GPU counters owned by the verifier (#1578)
The counter block was one process-wide cudaMalloc on whichever device was current at the first Verifier::init, unreachable from
the other stage's kernels on a layer split without P2P. Each verifier now takes its own device's block in init (outside graph
capture), keeps the pointer, and a launch never picks by the host thread's device; a failed allocation runs without counters.
The exit report prints one block per GPU when there are several (single GPU: the same lines as before). The reporter's rare
fault with --pipeline-windows 2 after this fix is not reproduced here (needs two GPUs).

STRATA_ROUTE_RESIDENT_MTP=1 (experimental, opt-in, changes the output): the MTP draft's router gets the same residency bias,
with the last layer's residency row as its table (single GPU).
2026-10-09 10:11:10 +02:00
Niko1221 56354964d8 Stage buffers: fence the lent-slot refill copies too (#1237)
The refills of the slots a prompt borrowed (and the VRAM-resize refill) queue hundreds of cudaMemcpyAsync out of blob_stable()
pointers, which for a GGUF source are the recycled stage buffers. With STRATA_STAGE_PIN=1 the 257th assembly overwrote a
buffer whose copy had not run: IQ3_XXS lowmem (budget 12) decoded token id 0 after a 4096-token prompt. Each queued copy now
records the fence of its buffer. exact_pp 4096 and 20000 tokens with STRATA_STAGE_PIN=1: EXACT.
2026-10-09 10:11:10 +02:00
Niko1221 0650f31670 tools: cancel_park_test.py, a cancelled request must not lose the conversation it restored (#1620) 2026-10-09 10:01:59 +02:00
Niko1221 caba015bff serve: a parallel request is never neither running nor queued (#1603)
A busy slot flag with no owner kept every later request waiting for a slot nothing
would free, and a request waiting for the fifo (a load, an image encode, /v1/vram)
was counted nowhere. Now: slots have owners (claims / BDONE waits) and an ownerless
busy flag is freed after 3 s; the request waiting for a slot is counted
(admitting) and, past the stall time, named in the log; a parallel request on a
loaded engine no longer takes the fifo, and one that waits for it stays queued.
Tests with the fake engine.
2026-10-09 03:31:47 +02:00
Niko1221 5728828a84 Windows HIP: a bare --prefill auto stops at 6144; commit-limit check at serve start (#1630, #1607)
On an RX 7900 XTX the first long prompt at 8192-token chunks charged ~70 GB of
commit and the engine died (0xC0000409); 7500 and below were flat. A bare auto
now stops at 6144 on Windows HIP builds. A chunk the user names stays, with a
warning from 8192 up.

Windows: the serve start prints the commit left and warns when the planned host
allocations plus a 4 GiB floor do not fit; the conversation cache's admission
reads min(available RAM, available commit).
2026-10-09 03:31:47 +02:00
Niko1221 eaaa237e85 CPU prefill share: not armed by default when the cache holds every expert (#1595)
With every expert resident nothing streams, so the share has nothing to take and
only moves the staged-chunk limit (+4.8% at 1,000 tokens on a V100). An explicit
STRATA_PREFILL_CPU_SHARE is honoured as before; the default is unchanged where
experts are not all resident.
2026-10-09 03:31:47 +02:00
Niko1221 1c6c82ef4f layer split auto: avoid a one- or two-layer stage (#1616)
A stage with one layer holds a handful of expert slots (a 12 GB 3060: 512), and the
prompt chunk of every card in the pipeline is clamped to what that cache can lend.
When the pick has such a stage, search again among placements that give every
stage at least three layers; keep the new pick and print both and why. With none
startable the first pick stays. Identical cards pick balanced stages and never
reach the second search.
2026-10-09 03:31:47 +02:00
Niko1221 316097d2d9 sycl: recognise a Battlemage / Alchemist card by the PCI id in a name like 'Intel(R) Graphics [0xe223]' 2026-10-09 03:31:16 +02:00
Niko1221 793ca909c1 iq_multi_parity: an independent mmvq reference for the grouped expert kernels (the old-vs-new comparison was the same kernels by default) 2026-10-09 03:31:16 +02:00
noon-at-cgn 1aa4198804 docs: replace the evidence placeholder in the memory guard section with the measured result 2026-10-09 03:28:31 +02:00
noon-at-cgn daa765524d memory guard: parking and session save/restore read the RAM the engine really has (--memory-limit-mib)
available_host_bytes() = min(MemAvailable, the room under every cgroup limit above the engine, the operator's cap).
Parking and session save/restore read MemAvailable alone: in a container whose real limit sits on a parent cgroup it
cannot see, MemAvailable is stale (about 25 GiB shown when about 1 GiB was left) and the engine was OOM-killed.

conversation_available_memory() is replaced by available_host_bytes() / sample_host_memory() (the SYCL port's
generate.cpp too). The cgroup term covers memory.max and memory.high (v2) and memory.limit_in_bytes (v1) of the
process's group and every visible ancestor, with clean inactive file cache credited; an unparsable cgroup file makes the
sample unknown (fail closed). --memory-limit-mib / STRATA_MEMORY_LIMIT_MIB names the total RAM the container or cgroup
may use. Refusals say how much was available and from which source; one start-up line reports the limit.
tests/core/memory_guard_test.cpp runs on fixture directories (CPU only). Docs: DETAILS.md.
2026-10-09 03:28:31 +02:00
tuandat3019 bbb74cfca4 serve: wait for measured RAM before retrying reclaimed SAVE 2026-10-09 03:27:49 +02:00
tuandat3019 73ed39ae8e serve: optionally reclaim host caches before SAVE admission 2026-10-09 03:27:49 +02:00
Niko1221 8824e217c4 serve: a request cancelled between two prompt windows keeps the conversation it restored as the live one (#1620) 2026-10-09 03:27:49 +02:00
Niko1221 152292b633 tests: the AVX2 warning test of the docker entrypoint 2026-10-09 03:21:46 +02:00
Hulk 71eaee17b9 spec: re-probe stale full chains when shorter chains pay
A profitable shorter chained lookup returned before the stale full-size check, so the full chain could stay excluded for good
although the policy re-probes stale sizes in the other selection paths (#1252). Check a confident stale full size before
returning the profitable shorter chain. The 300-round policy, the EMA, the header and plain lookup are unchanged; a regression
test covers the bounded re-probe spacing and the MTP confidence gate.
2026-10-09 03:18:07 +02:00
sergiywith a26fcbcdba prefill: bytes_needed sizes the MoE buffers for the layout init picks (with or without an expert source)
0.1.39 took this PR's first part with #583 (the xn / grs count, STRATA_RING_BYTES). What is left: bytes_needed
counted the fused layout's smaller MoE buffers for every caller (fused_layout(T, true)), while init takes them only
when it gets an ExpertSource (fused_layout(T, m.src != nullptr)). A prompt path without one was lent fewer bytes than
its unfused buffers take. bytes_needed, bytes_needed_no_ring and (0.1.40) bytes_needed_owned - STRATA_OWNED_PRICE=exact's
sizing - now take the same src the callers pass to init.
2026-10-09 03:17:42 +02:00
Niko1221 8bb250d846 Layer split auto: warn on a near tie between two different splits on a mixed pair (#1428)
When the best split and a different one (boundaries at least 3 layers away, startable) are within 4% predicted decode window
(STRATA_SPLIT_NEAR_TIE_PCT, 0 = off) and the cards differ in speed or link, print the other K and --layer-split K. The model
prices decode only, not the prompt. Print only: the choice is unchanged.
2026-10-09 03:17:32 +02:00
Niko1221 cec7e2b1f6 --batch on a layer split: a BYIELD is taken even when no slot is decoding
A prompt read on a layer split with no slot decoding was one run, so the BYIELD of the batch_interleave_test step 4 was
dropped at the end of the read; the long prompt kept its slot and the next BGEN failed with 'ERR BGEN: no such free slot'
(pre-existing since 0.1.40.4). That read now goes in pieces of STRATA_BATCH_YIELD_CHUNKS chunks (default 8, 0 = one run), the
same chunks a single run reads, with the yield check between pieces. batch_read_piece holds the arithmetic; batch_read_test covers it.
2026-10-09 03:17:31 +02:00
Niko1221 9f5504d8a1 tests: test_ready_timeout is skipped on Windows, where its .cmd wrapper keeps the pipe open after the kill 2026-10-09 03:17:23 +02:00
Niko1221 f71c5307c6 Stage buffers: fence a pinned buffer's queued copy before the buffer is recycled (#1237)
A page-locked stage buffer is the source of the cache fill's cudaMemcpyAsync, which the DMA reads after the call has
returned; a pageable one is staged by the driver before it returns. The pool recycles a buffer after kStageAge layers or 256
assemblies, so a 4096-token prompt read (up to ~500 distinct experts per layer) could overwrite a buffer whose copy had not run
yet: the corrupted IQ3_S decode of #1237. note_async_read(blob, stream) records an event per pinned buffer after each queued
copy (hit-path fill, peer fill, remote-expert swap); claim_stage waits for it before it hands the buffer out again.
Pageable buffers and every other source are unchanged. STRATA_STAGE_PIN stays opt-in.
2026-10-09 03:17:17 +02:00
Niko1221 8d276c1997 Data-parallel replicas (opt-in): N engines on their own card groups behind one server, requests spread least-loaded and a conversation routed back to its replica; replicas in the config, --replicas in the server and setup 2026-10-09 03:15:34 +02:00
Niko1221 438019e36a hip: gfx1152 (Radeon 860M / 840M) in the unvalidated architecture list, like gfx1150 (#1625) 2026-10-09 03:15:13 +02:00
Niko1221 df29e3b2e6 prefill: guard std::atomic::wait/notify_all with __cpp_lib_atomic_wait so a GCC 10 build spins as before #1057 (#1488) 2026-10-09 03:15:13 +02:00
Niko1221 0ff45cffb2 hip: the Q2_0 signed-zero fix also on gfx1200/gfx1201 (ROCm 7.10), where hip_q2_zero failed (#1474) 2026-10-09 03:15:13 +02:00
Niko1221 3d6793a408 tests: expert_cache_segmented_test skips on a HIP build, where --vram-elastic is CUDA-only (#1475) 2026-10-09 03:15:12 +02:00
Niko1221 9d64b93a0f docker: warn, not stop, on a host CPU without AVX2 (#1584) 2026-10-09 03:15:12 +02:00
Niko1221 224bb6f899 setup: an engine update compiles for the cards the installed models use, not the biggest one (#1485) 2026-10-09 03:15:12 +02:00
Niko1221 598df11158 setup: --gpus when starting an installed model on a PC with AMD cards and no NVIDIA ones names the AMD cards (#1594) 2026-10-09 03:15:12 +02:00
BlueKingMuch 0d613031a9 serve: a </think> the reasoning quotes stays reasoning instead of ending it (#537)
The reasoning ended at the first </think> in the output, also when the model only
quotes the tag while it thinks (`</think>`, "</think>\n\n2" from a test). The rest
of the thinking then came back as the answer, and a tool call quoted in it could
be run.

A </think> right after a quote or backtick and followed by anything but a line
break is now reasoning text; the end of the thinking is followed by a line break
and ends it as before. Until the character after such a tag arrives, the tag is
held like a partial one, so streamed and whole outputs agree. If the turn ends
right after it, it was the end of the thinking: a forced tool call still opens
there, and the #1053 retry is not triggered, as before.
2026-10-09 03:15:12 +02:00
William Charbonneau Perrier 624070c5df Conversation cache: --conversation-cache-min-tokens parks only conversations of at least N tokens
Parking happens on a switch and every parked conversation costs one of
--conversation-cache-slots whatever its length.  A client that interleaves
short side requests (an agent's tool-result follow-ups, often under 1k tokens)
with one long conversation therefore spends the cache on the side requests and,
once it is full, evicts the long one oldest-first - the reuse it wanted.

Measured on an RTX 4070 SUPER / 32 GB / Q2_0, --conversation-cache-slots 2,
one 19,198-token conversation interleaved with three ~700-token requests, then
the same conversation again:

  min 0      skip nothing, side requests park, L is evicted
             re-send L: 0 reused + 19198 read in 41,059 ms   (wall 41.4 s)
  min 12288  skip parking (703 tokens, below the 12288 minimum) x3
             re-send L: 19193 reused + 5 read in 135 ms      (wall 0.3 s, 304x)

The default 0 keeps the previous behaviour, so nothing changes without the flag:
wants() answers for the length alone and the gate stays enabled() && wants(),
exactly as the existing byte-budget and RAM-floor skips are.  The check runs
before make_room(), so a skipped park neither evicts nor stores anything, and it
returns the same non-error path those skips take.

Tests: conversation_cache_test covers the inclusive boundary, 0, a negative that
never reaches the CLI, and that a disabled cache still answers for length; both
faults were reintroduced by hand to confirm the checks fail on them.
2026-10-09 03:15:12 +02:00
Niko1221 875d6a922a serve: a request waiting for the single turn sends keep-alives, and gives its place up when cancelled (#1619) 2026-10-09 03:15:12 +02:00
Niko1221 30017336ed ple: when the default --ple-io direct measures slow at start (cold random-row probe), use mmap; an explicit direct only warns (#1425 #1549 #1629) 2026-10-09 03:14:18 +02:00
Niko1221 6c9bbc8147 sycl: spin bound for a B-series card found from the device (Windows/OpenCL has no sysfs driver): 20,000 reads, 2,000,000 when drafting without --mtp (#1473 #1397) 2026-10-09 03:14:18 +02:00
Alex Gorevski 7d771bb028 Group a launcher's allowed CPUs by physical core and split them between independent instances (serve/cpu_affinity.py, from #1436) 2026-10-09 03:10:24 +02:00
jkuepker a257e0198e docs: gfx12 (R9700) native WMMA prompt experts: switch, measurements; gfx12 in the comments
AMD_HIP.md, RDNA4 speed switches: STRATA_PF_FUSED=1 now runs the native
IQ packs' prompt experts on the int8-WMMA kernels on gfx1200 / gfx1201.
Says that it is opt-in and why (it rounds differently, so it is not an
arch default), that STRATA_PF_FUSED_NATIVE=0 turns the native path off,
the start-up line it prints, the R9700 measurements (prompt time, kernel
vs MMQ, first-token KL against the FP16 path, retrieval checks), and
what was not run (gfx1200, Windows, K-quant packs).

DETAILS.md: the STRATA_PF_FUSED=1 sentence says where the native kernels
run on HIP.  CMakeLists.txt and gfx_arch.hpp: the comments that said the
native prompt-expert kernels are gfx11 only now include gfx12 (comments
only, no build change).
2026-10-09 03:06:58 +02:00
jkuepker 7969a6ec93 HIP gfx12: native int8-WMMA prompt experts on gfx1200/gfx1201 (opt-in STRATA_PF_FUSED=1, #1277)
The native IQ / K-quant prompt-expert kernels (moe_fused_iq.cu,
native_w11_kernel) were gfx11-only; on RDNA4 a pack with
STRATA_PF_FUSED=1 silently kept the MMQ path.  They now compile and run
on gfx1200 / gfx1201.  Still opt-in: STRATA_PF_FUSED=1 stays off by
default (it changes rounding, so it is not an arch_defaults switch), and
STRATA_PF_FUSED_NATIVE=0 still turns the native kernels off.

Compile gating
- STRATA_NAT_W12 for __gfx1200__ / __gfx1201__, STRATA_NAT_WMMA for
  either family.  The kernel calls the _gfx12 spelling of the iu8 WMMA
  builtin (the un-suffixed one does not compile there).  Any other
  target keeps the trapping body.

Kernel (same arithmetic, other lane layout)
- gfx12 WMMA fragments are 8 int8 per lane and the two lane halves hold
  different k (8*hi .. 8*hi+7), not a replica as on gfx11: B and A are
  loaded as uint2 at the matching offsets, and every 16-value k step is
  still one WMMA, so the per-16 scales of the IQ2_S / IQ2_XS paths are
  untouched.
- A lane's 8 accumulator rows are consecutive (8*hi + i), so a feature's
  gate and up are in the same lane: SwiGLU needs no __shfl_xor, and the
  down tile is stored as two float4 per lane.  NW_DROW(i, hi) gives the
  row of element i for the per-row scales.

Host side
- gfx_arch_is_gfx12_wmma(): exact gfx1200 / gfx1201 match, never a
  prefix, like the gfx11 helper.
- dev_info() takes the gfx11 list or gfx12, and also checks that the
  kernel the build loaded is the real one: the trap stub (a
  gfx12-generic or SPIR-V build on a listed card) declares no LDS and
  still passes hipFuncGetAttributes and the occupancy query.
- native_supported() reads the STRATA_PF_FUSED=1 opt-in itself:
  fused::available() / requested() belong to the Q2_0 pack's
  expert_w11_kernel, which is not ported and stays false on gfx12.  Off
  gfx12 the result is what it was.  prefill.cpp fused_ring() follows:
  a native pack asks native_supported() alone (it implied enabled()
  before), so on gfx12 it gets the fused buffer layout and ring.
- Grid factor per format: gfx12 holds 3 blocks per WGP for IQ2_S / IQ2_XS
  gate/up (LDS and VGPRs), 4 for the rest.  The occupancy API cannot say
  (it models 64 KB of LDS per multiprocessor), so it is a small table;
  STRATA_PF_OCC_W=N overrides it.  gfx11 keeps 4.
- experts_native() refuses a dm that is not 16-byte aligned on gfx12
  (the float4 stores); the prompt path's buffers always are.
- moe_fused.cu compares the gfx11 list with the helper instead of the
  "gfx11" prefix (no change on any listed part).

Tests (prefill_fused_iq_test)
- Runs on gfx12 (the skip gate also asks native_supported()), covers the
  other four pairs of the Coder IQ1_M pack, S20_E sets the expert count,
  and the real-shape check of fused against MMQ is now rel RMS <= 1e-3
  and worst row <= 2e-2 instead of rel RMS <= 0.05.

Measured on a Radeon AI PRO R9700 (gfx1201), Coder IQ1_M pack:
- parity: all 10 IQ pairs plus Q4_K / Q5_K pass, rel RMS <= 9.1e-5.
- kernels vs MMQ, 48 layers: 1.48x / 1.20x / 1.14x at 4K / 16K / 32K.
- prompt speed in the engine (server-reported, alternating starts per
  arm): 4K +12% to +19% depending on the start, 16K +8.3%, 32K +8.5%.
- first-token KL against the FP16 prompt path is 1.10x MMQ's (48 prompts
  of 4K), top-1 agreement 48/48; 4/4 long-context retrieval checks.
Not run on gfx11 or CUDA hardware here.
2026-10-09 03:06:58 +02:00
noon-at-cgn 425fc48a82 docs: replace the evidence placeholder in the split MTP-batch paragraph with the measured result 2026-10-09 03:06:46 +02:00
CYoung83 5fde38470a gguf_reader: open a tensor-less shard that ends before its aligned data start
unsloth/Qwen3.8-Flash-Next-GGUF UD-Q5_K_XL shard 1 holds metadata only and
is 10,946,618 bytes; its 32-byte-aligned data start is 10,946,624, so the
engine refused it with 'GGUF: data section starts past EOF'. llama.cpp's
gguf-py reads the same file (0 tensors, data_offset 10,946,624).

A file with tensors is still refused. A file without them gets data_start
clamped to the file size, so file_size() - data_start() stays 0 in the
payload checks downstream.
2026-10-09 03:06:46 +02:00
Niko1221 dd106e7de5 arch_defaults: gfx1200/gfx1201 get the six exact prompt switches of the gfx1151 table (decode half stays off); STRATA_GFX12_DEFAULTS=0 opts out (#1478) 2026-10-09 03:06:46 +02:00
noon-at-cgn a22a0e8c46 split: batched draft-layer prompt K/V on the last stage (STRATA_SPLIT_MTP_BATCH=1, opt-in)
On one GPU the prompt path computes the draft layer's K/V for each chunk in batches (Prefill::draft_kv, E-9). A layer
split always ran the drafter's own per-group pass instead, because the drafter sits on the last stage. With
STRATA_SPLIT_MTP_BATCH=1 the last stage's prompt path runs E-9 there. Default off: the default path is unchanged.

The drafter's K/V come from Q8_1 x Q8_0 MMQ instead of its own mmvq, so its drafts can differ; the target's tokens are
decided by the verify window.

Prefill::draft_kv says why it declined (optional out-parameter, also in the SYCL port's prefill.cpp), and the split
logs once what the variable did. Which path runs is a pure header (include/strata/program/draft_kv_plan.hpp) with a
CPU test. tools/split_mtp_batch_parity.py compares the greedy texts of the two arms on a live server. Docs: MULTI_GPU.md.
2026-10-09 03:06:46 +02:00
CYoung83 de21371b8a gguf_reader_test: a tensor-less file that ends before its aligned data start
Two synthetic cases: no tensors and the file ends at its header (should
open; data_start() clamped to the file size), and one tensor with the same
truncation (still refused). The first fails on 0.1.40.3: unsloth's
UD-Q5_K_XL shard 1 is that case.
2026-10-09 03:06:46 +02:00
noon-at-cgn 12019dc4a3 docs: replace the evidence placeholder in the thread-placement section with the measured result 2026-10-09 03:06:46 +02:00
noon-at-cgn 91f1e85dd1 --aux-cpus: put the engine's threads that are neither pool workers nor the host on spare CPUs (Linux, off by default)
Header-only placement (include/strata/platform/aux_cpus.hpp): the spare CPU set (the host core's SMT siblings, then
CPUs of physical cores with no worker; never a CPU that shares a core with a worker), the list parser, threads the
engine creates pin themselves, threads somebody else created (the CUDA driver's) are moved by a sweep over
/proc/self/task after the pool exists and at every request; pool workers and the host thread are never moved.
--aux-cpus off|auto|LIST / STRATA_AUX_CPUS; per request strata_tune aux_cpus=0|1 (serve/server.py).
Default off: the hooks do nothing. tests/platform/aux_cpus_test covers the derivation and live threads (CPU only).
2026-10-09 03:06:46 +02:00
noon-at-cgn f47349002c docs: replace the evidence placeholder in the lend-sizing paragraph with the measured result 2026-10-09 03:06:43 +02:00
noon-at-cgn d3fb3e6f75 split: decide STRATA_SPLIT_RING before sizing the lend regions; log borrowed vs RAM-kept slots
Builds on #1190. The layer split sized its lend regions (the RAM copies of the experts the prompt path borrows) with
Prefill::bytes_needed before the split's ring override was applied (Prefill::set_ring_override says it must be set
before any bytes_needed), so with STRATA_SPLIT_RING=384 the prompt path borrowed 5396 slots and the copy kept 4662.
The override is now decided first (decide_split_ring); include/strata/program/split_ring.hpp holds the pure helpers
(split_ring_slots, split_lend_slots - the scan's own tail-slot arithmetic, now one function for the region and the
borrow), src/program/split_ring_test.cpp covers them on the CPU. A start line reports borrowed vs kept slots and warns
when kept < borrowed. Docs: MULTI_GPU.md.
2026-10-09 03:06:43 +02:00
Evan 51d55a9ab4 generate: size every part's lend region for a layer split by the serve scan's own arithmetic (auto ceiling or the explicit chunk, the 128-slot floor, the auto percentage cap), #340's own-buffer rule deciding which parts lend nothing - and hand them to the resident copy before it pins 2026-10-09 03:06:39 +02:00
Evan aea9dc3ed8 resident split: pin_cache_complement keeps each stage's lend region in the RAM copy too (stage_lend_regions, append_stage_lend_regions) - the experts the prompt path borrows under a split streamed from the mapped files through page faults (3.7 GiB read for one 73K prompt, 1.5 s of a 3.9 s chunk on host staging, 2026-10-06 rig); one budget caps complement and regions, experts past it keep the file fallback 2026-10-09 03:06:39 +02:00
Vadim Shevchenko 3afbe5f7c2 setup: UD-Q4_K_XL / UD-IQ4_XS keep their RAM budget on a layer split (#642)
Engine 0.1.40 (fe9c10ca, #848) keeps the resident RAM copy on a layer split -
every stage's cache left out of it, the rest ranked by the whole expert
profile - and --resident-budget-gib runs through the same code
(pin_cache_complement), so the old engine refusal of the budget on a split is
gone. setup.py's split_mmap() got the matching exemption (43c8cfa9), but the
budget's three paths still assumed the old engine (#498):

- split_budget(): a start of a budget config on several GPUs deleted
  --resident-budget-gib (and asked for ~135 GB of RAM below that);
- offer_together(): a budget config was offered both cards only with ~135 GB
  of RAM, and "on both it has no budget";
- unsloth_together() / q4_split at install: --gpus, or "2" when asked, dropped
  the budget, and an explicit --resident-budget-gib kept one GPU.

From RESIDENT_SPLIT_ENGINE the budget is kept in all three, at any RAM. The
recommendations stay as they were (the golden configs are unchanged): one GPU
by default at install, "n" by default when a start offers both cards, --yes
alone one GPU; the split is taken only when asked for.

Tests: the #498 tests run with MIN_ENGINE pinned before RESIDENT_SPLIT_ENGINE
(as test_setup_risk's StartOnSeveralGpus does for #642), three new ones run the
kept budget; tools/test_setup_*.py on Linux: 421 tests, the 2 failures of
test_setup_engine_hash are the same without this change (no ready-made 0.1.41
engine to download in the test box).

Measured with engine 0.1.41 on an RTX 3090 (x16) + RTX 3080 Ti (x4), 91 GB of
RAM, UD-Q4_K_XL, budget 64 GiB: the auto split gives the x4 card layers 0-1
(678 slots) and the 3090 layers 2-47 (4,182 slots); 57.6 GiB of experts in RAM,
no file-tier reads per request; decode 45.0 / 45.1 tok/s (two runs) against
38.4 on the 3090 alone, a 20K prompt in ~18 s on both. Answers checked by hand.
2026-10-09 03:06:38 +02:00
Destrayon 1decc04efe setup: skip a cmake/ninja on PATH that does not run, for the one next to this Python
A pip launcher whose Python was removed stays on PATH ('ninja --version'
fails) and stopped every build there, though setup had just installed a
working copy in .venv.
2026-10-09 03:06:34 +02:00
BonifacioCalindoro 573642fc4c Fix PowerShell 5.1 command shown by UPDATE.bat
UPDATE.bat currently prints a command using `&&` for users to copy and
run manually. `&&` is not supported by Windows PowerShell 5.1, which
is still included with Windows 11.

Print the two Git commands separately instead.
2026-10-09 03:06:33 +02:00
nekomario28 9aba7baa28 sycl: keep the null-stream sentinel a sentinel in Verifier (#1555)
dpct migrated cudaStream_t ext_stream_ = nullptr to a pointer to the
in-order queue, evaluated at construction on whichever device is current.
Two places then misread it: init() compared ext_stream_ against the
*init-time* device's in-order queue, so a stage built on one device and
init'ed on another adopted the constructing device's queue
(cross-context submit failures, UR_RESULT_ERROR_DEVICE_LOST); teardown's
'cs_ != ext_stream_' ownership test drifted the same way.

Restore the CUDA contract: nullptr means 'no stream until set_stream()',
matching include/strata/core/verify.hpp:319 and src/core/verify.cpp:604.
2026-10-09 03:06:31 +02:00
duncanmcqueen 0b063ce804 sycl: fix the GEMM staging scratch lifetime and unregister freed allocations
Follow-up to the >4 GiB GEMM staging.

- gemm_stage freed its scratch as soon as a larger operand arrived, but the
  in-order queue is asynchronous: a previous staged GEMM could still read the
  buffer.  Wait for the queue before the free.
- The staging used dpct::get_in_order_queue() while the GEMM runs on the
  descriptor's queue (strata::q_of(stream_)); pass the descriptor's queue so
  the copy is ordered before the GEMM for a non-default stream, and so two
  Gemm objects on different queues do not share the thread_local scratch.
- Staging that could not allocate fell silently back to the direct (wrong)
  GEMM; it now says so.
- device_alloc_map had no unregister, so a freed cache base left a stale
  entry that device_offset_end could mis-attribute after the VA was reused.
  Add device_alloc_unregister and call it where the expert cache frees base_.
2026-10-09 03:06:31 +02:00
duncanmcqueen edff903d7a sycl: setup picks the Intel card by PCI id and configures Alchemist
setup reads the Intel cards from sysfs but to_sycl() decided the expert
mode from the driver alone, so a card's device id was thrown away and an
A-series on xe (the A770) could not be told from a Battlemage.  Carry the
PCI device id through intel_gpus() into to_sycl(), and treat every
Alchemist id (A770/A750/A580/A380/A310/A770M) as an A-series: it has no
FP64 hardware, so its config carries the driver's FP64 emulation (a kernel
on the sampled path declares double and is refused without it).

On i915 (the A750) the experts still load into a CPU-computed RAM arena
(--mmap-experts + STRATA_VERIFY_NO_HOST=0) - a single pinned host
allocation past ~3 GiB fails on that die.  On xe (the A770) the A-series
now takes the ordinary streamed path: the mirror is built in chunks (so
the >3 GiB limit is not hit) and the build passes
-ze-opt-greater-than-4GB-buffer-required, so the prompt path is correct
past the cache's 4 GiB.  tools/test_setup_sycl.py passes.
2026-10-09 03:06:31 +02:00
duncanmcqueen defadd6e0e sycl: build Alchemist kernels for allocations past 4 GiB
On an Arc A770 every prompt answered "!!!!" (token 0). The experts in the
last 0.46 GiB of the 4.46 GiB VRAM expert cache dequantized to NaN in the
prompt path. The slots' bytes were right (a memcpy read back equal to the
GGUF, and a fresh copy dequantized clean); only kernels reading them in place
got wrong bytes. In a JIT build IGC addresses kernel pointer arguments as a
32-bit offset from the allocation's base.

The JIT (non-AOT) build now passes -ze-opt-greater-than-4GB-buffer-required
to the spir64 backend, in the same argument as the divide/sqrt option (CMake
drops a repeated -Xsycl-target-backend=spir64). Measured on the A770, Coder
IQ1_M, --stream-experts: prompts of 73-542 tokens have 0 non-finite values
under STRATA_DBG_NAN=1, and the 542-token prompt answers right. The AOT build
is unchanged. Speed cost not measured.
2026-10-09 03:06:31 +02:00
duncanmcqueen 56efb70939 sycl: stage oneMKL GEMM operands that lie more than 4 GiB into their allocation
oneMKL's GEMM reads the last, partial tile of an operand from the wrong
place when that operand lies more than 4 GiB into its device allocation
(measured on an Arc A770, oneMKL 2026.1: a BF16 B past 4 GiB gave its last
21 columns wrong, none below 4 GiB). The prompt path's GEMMs meet this:
their buffers come from the top of the multi-GiB expert cache / prefill
region. This is the leading explanation for the A770's garbage on prompts
longer than a few dozen tokens - it repros with every expert
device-resident, so it is not the CPU handshake.

Register every big device allocation (malloc_device_guarded, and the
segmented expert cache's reserved VA) in a small registry, add
device_offset_end(ptr, bytes), and in Gemm::bf16 / Gemm::f16 copy either
operand into a scratch buffer of the queue's own (a fresh allocation, so
at offset 0) when its end lies past 4 GiB, then run the GEMM on the staged
operand. STRATA_SYCL_GEMM_NO_STAGE=1 is the negative control.

Not validated end to end: the run that showed the garbage was an
all-resident mirror, which no longer fits in this machine's RAM, and the
runnable --mmap-experts config crashes on this A770 with or without the
staging (exit 139, UR_RESULT_ERROR_DEVICE_LOST - verified a separate,
pre-existing fault with the negative control), so the staging has not yet
been shown to change an answer.
2026-10-09 03:06:31 +02:00
duncanmcqueen 18ee03e55c sycl: add the doorbell payload checksum
The decode handshake publishes a payload (the layer's activations, the
routed expert ids and weights) and then rings a sequence number the host
polls. The fences alone do not order the ring after the payload stores:
measured on an Arc A770, 14 of 2,832 rings in one run became visible
before the last activation store, so the CPU expert pool sometimes
computed on a partly stale payload. This is the fix the port's own
comments call for (elementwise.hpp: "the host can observe the ring and
then read a payload that has not landed").

The publish kernels now write, next to the sequence number, the ring it
belongs to and a checksum of the payload (the wrapping sum of every 32-bit
word mixed with its position, murmur3's finalizer - a plain sum missed a
reordering, [3,7] -> [7,3], of the expert ids) in a per-ring slot modulo 4,
and the payload is stored with the uncached write hint (a plain store to
host USM reaches the host only when the kernel ends on xe). The host waits
for the whole payload (doorbell_wait_payload) before the pool reads it, in
session_loop and both verify-window loops; the checksum is accepted in
either publish shape (with or without the routing weights), so a variant's
choice need not be plumbed to the reader. The sequence word grows from 1 to
9 mapped words (layer.cpp, verify.cpp) and the ring slot is reset with it.

Note this is a robustness fix, not the cure for the A770's garbage on
longer prompts: that one repros with every expert device-resident (no CPU
handshake) and points at oneMKL's >4 GiB operand bug, which needs the BLAS
staging the CUDA/HIP shims have.
2026-10-09 03:06:31 +02:00
duncanmcqueen 0d9d8541f4 sycl: keep Alchemist's prompt path on its own buffers
At a long context this port borrows expert-cache slots for the prompt
path. Those buffers are carved from the top of the ~10 GiB expert-cache
allocation, and oneMKL's BF16 GEMM reads a wrong tile when an operand lies
more than 4 GiB into its allocation (docs/INTEL.md). The borrowed operands
hit that, so from the first full prefill chunk the router read garbage.

Measured on an Arc A770: a 236-token prompt failed with "prefill: routed
id out of range", and a 452-token one segfaulted the engine (exit 139),
on both the mirrored and mmap configurations. With the prompt path on its
own buffers (its own allocation, reserved exactly by owned_prefill_mib)
and an automatic chunk capped at 2048 tokens, 452 / 1,748 / 3,476-token
prefill chunks ran to completion with no prefill failure (prompt reads
22 (cold) / 676 / 835 tok/s). Whether the *answers* of that configuration
are correct is a separate, still-open issue: the base port has no doorbell
payload checksum and its longer-prompt path garbles on some inputs, with
or without borrowing.

Scoped to Alchemist (PCI device ids, the same table setup_intel.py uses):
Battlemage's long prompts were measured correct with borrowing, so it
keeps the old default. --prefill-borrow still borrows, for testing a
future BLAS staging fix (the fix that lets borrowing return, as the
CUDA/HIP shims already stage).
2026-10-09 03:06:31 +02:00
duncanmcqueen e02bd9955e sycl: chunk the expert mirror and raise memlock in the wrapper
Two Alchemist (Arc A-series) fixes for the streamed-expert mirror:

- gguf_expert_source: a single sycl::malloc_host past ~3 GiB fails on DG2,
  so the mirror (thousands of experts, tens of GiB) could not be built on
  an A770 at all. It is now allocated in <=2 GiB chunks; the per-(layer,
  expert) address, the layer's first blob and close() use the chunk
  pointers. A cleanup guard frees every chunk on an allocation failure,
  a failed read, or any exception; the read phase is unchanged.
- strata-sycl.sh: docker's default memlock is 8 MiB, far below what pinning
  the mirror or the resident arena needs; pass --ulimit memlock=-1.

Measured on an Arc A770: the Coder IQ1_M (8,474 experts missing VRAM,
16.15 GiB) mirrors and the engine starts; before, it refused with
"8474 experts are neither in VRAM nor mirrored".
2026-10-09 03:06:31 +02:00
duncanmcqueen 9c790e3dde sycl: publish the doorbell with the uncached write hint
The decode handshake publishes a ring sequence the host polls while the
window graph still runs. On an Arc (xe) a system-scope atomic store, even
with a release fence, is served from the GPU's cache and reaches the host
only when the kernel ends, so a host polling mid-window never sees the
ring. That is why the verify window had to wait for the whole graph
(STRATA_VERIFY_NO_HOST) and every expert had to be device-resident or in
the pinned mirror.

STRATA_DOORBELL_ATOMIC_LOAD already fixes the load side the same way; this
does the store side with the Intel uncached L1+L3 write hint. The release
fence stays (ordering only: a later payload store follows the ring).

Measured with sycl/probe/doorbell_store.cpp on an Arc A770: the host sees
the store at 230 ms with the kernel running to 2030 ms; with the old atomic
store it sees it at 2038 ms, exactly when the kernel ends (exit code 3).
-DSTRATA_DOORBELL_ATOMIC_STORE restores the atomic store.

This is a prerequisite for running with the CPU expert pool on xe (the
per-layer handshake); it does not by itself fix longer-prompt prefill.
2026-10-09 03:06:31 +02:00
Evan 7a7c568b9a resident split: a test that the RAM copy keeps each stage's lend region (red: FileExpertSource has no stage_lend_regions, and no append_stage_lend_regions) 2026-10-09 03:06:15 +02:00
Chen Cheng 8e9d3d0a19 serve: the hardware sampler keeps running where psutil finds no disk counters
psutil.disk_io_counters() returns None when it finds no disk (Modal's gVisor
has no /proc/diskstats; psutil's docs say Windows can need `diskperf -y`).
_disk() then raised AttributeError at the first sample and the sampler thread
ended: /metrics' hardware stayed empty, the Monitor tab had nothing to show,
and the frozen-engine check's gpu_busy() read a GPU load of 0. It now returns
no disk reading and the other readings go on.
2026-10-09 03:04:22 +02:00
InB4DevOps 2a91a14414 serve: compact streamed line fragments into blocks 2026-10-09 03:04:22 +02:00
InB4DevOps ac1df2c416 tokenizer: initialize caches once per instance 2026-10-09 03:04:21 +02:00
InB4DevOps b2b94e3f6f tokenizer: sweep protected spans in match order 2026-10-09 03:04:21 +02:00
Hulk 8c6b1cc5b5 Limit body framing fix to incomplete chunked trailers 2026-10-09 03:04:21 +02:00
Hulk d467b3d2bb Reject incomplete HTTP request body framing 2026-10-09 03:04:21 +02:00
Hulk 2bf1d07c05 fix(serve): make context overflow errors recognizable 2026-10-09 03:04:21 +02:00
nekomario28 32a2439de0 serve: answer the request that hit the READY timeout (#1527)
The READY-read timeout from #1317 kills the engine, but the request that
was loading it ended with no response: the RuntimeError from __init__
matched none of the request path's handlers, and on a lazy first start
restart()'s finally crashed on slot_cv (created only after READY), so a
misleading 400 masked the failure instead.

- raise EngineDied (still RuntimeError) for the start failure, so the
  request ends 503 'did not report READY ...; the next request restarts
  it' on the load, restart and /v1/load paths alike
- skip the slot_cv wakeup when a lazy first start never created it

serve/test_ready_timeout.py covers both paths with silent fake engines:
the lazy load (unfixed: 400) and a restart that never reports READY
(unfixed: connection closed with no answer).
2026-10-09 03:04:14 +02:00
nekomario28 efe3bfcf87 serve: keep the given card order when the reorder starves the last stage (#1576)
#1352 orders an auto layer split faster-card-last because the last stage
runs the head, the draft layer and the verify. On a VRAM-asymmetric pair
that rule can put the heaviest stage on the card least able to hold it:
the reporter's 12 GB 4070 Ti ended up with 31 layers + head + verify and
a 3 GiB expert cache (decode ~58 -> ~44 tok/s, the 'card this small'
warning on).

Skip the reorder when it would put the last stage on a card with less
total VRAM than the one the config placed there (NVML / amdgpu sysfs;
unreadable cards keep the reorder).  scores/vrams stay injectable for
tests.
2026-10-09 03:03:14 +02:00
Niko1221 fb58e0dbc8 Stage buffers: pinning is opt-in (STRATA_STAGE_PIN=1); on by default it corrupted IQ3_S decode after a long prompt in the release gate 2026-10-08 12:25:39 +02:00
Niko1221 982b8cf515 stage pin: no cudaErrorNotSupported (it is not in the HIP compat layer); same behaviour 2026-10-08 10:17:21 +02:00
Niko1221 69342e8e6c Merge main (v0.1.40.4) into f-141
# Conflicts:
#	CMakeLists.txt
#	setup.py
2026-10-08 10:07:12 +02:00
Niko1221 459bf63537 tests: drop the duplicate test_pipeline_windows_wins left by the merge; the hotfix-tag test no longer assumes a four-number MIN_ENGINE 2026-10-08 10:03:44 +02:00
Niko1221 0a45d54b2f Version 0.1.41: MIN_ENGINE 0.1.41 2026-10-08 09:59:53 +02:00
Niko1221 9b5e9ab13a 0.1.41 merge cleanups: bench key placeholder, B65 README author text, calibration time text, fixups.py regenerates the run-time spin bound 2026-10-08 09:58:59 +02:00
Niko1221 e5c5739ae0 Merge f-141-research: STRATA_DBG_FEAT and ROUTE_OVERRIDE debug hooks (env-gated) 2026-10-08 09:57:02 +02:00
Niko1221 ed13c9a10f Merge f-141-routeres: route-resident experts (opt-in, experimental) 2026-10-08 09:56:56 +02:00
Niko1221 b0bc4a70f4 Merge f-141-conc: --batch-groups auto for layer-split batches, #857 fix, listen backlog
# Conflicts:
#	src/program/generate.cpp
2026-10-08 09:56:56 +02:00
Niko1221 4aca10c5a0 Merge f-141-mgpu: no-P2P path (opt-in), #794, #793, peer knobs 2026-10-08 09:56:29 +02:00
Niko1221 a00d889383 Merge f-141-amdintel: AMD and Intel work, watchdog file-tier tolerance, ports
# Conflicts:
#	bench/results/COMMUNITY.md
2026-10-08 09:56:29 +02:00
Niko1221 ef80713032 Merge f-141-fixb: Python, docs and bench fixes and ports
# Conflicts:
#	setup.py
2026-10-08 09:56:13 +02:00
Niko1221 e50c5946c7 Merge f-141-fixa: Pascal decode regression (#1469), clamps, SYCL multi-card and spin bound 2026-10-08 09:55:58 +02:00
Niko1221 c27998f5ac Merge f-141-cuda: foresight, GDN chunked, per-arch tables, stage pin, CUDA bug fixes
# Conflicts:
#	docs/DETAILS.md
2026-10-08 09:55:41 +02:00
Niko1221 073e2fe28d Merge f-141-quick: CPU prefill share, file tier batched reads, tokenizer cache, server hardening, small fixes 2026-10-08 09:55:28 +02:00
Niko1221 5df35dcb47 Experimental STRATA_ROUTE_RESIDENT: residency-biased routing in verify windows (opt-in, changes the output) 2026-10-08 07:54:09 +02:00
Niko1221 c34dd57143 serve: STRATA_HTTP_BACKLOG, test with 60 simultaneous connections 2026-10-08 07:32:43 +02:00
Niko1221 6674a0065f Version 0.1.40.4: MIN_ENGINE 0.1.40.4; Pascal sm_61 decode back to 0.1.40 speed (#1469) 2026-10-08 07:23:15 +02:00
Niko1221 ca001df571 batch: a layer split with --batch pipelines one group per stage by default (--batch-groups 1 opts out); server listen backlog 256 (30-40 simultaneous clients got connection resets) 2026-10-08 07:10:59 +02:00
Niko1221 55dee8ed84 prompt buffers (#1454): keep counting the bytes bo shares with emb unless STRATA_EMB_REUSE_ACCOUNT=1
The VRAM reuse stays, but bytes_needed_impl counts bo again by default, so the auto chunk and the borrowed cache slots
are those of 0.1.40.3 and the prompt residuals stay byte-identical (on the RTX 3060 the planner otherwise picked a
6656-token chunk instead of 6400). STRATA_EMB_REUSE_ACCOUNT=1 lets the planner use the saved bytes (+3.9% prompt there);
documented in docs/DETAILS.md.
2026-10-08 04:44:49 +02:00
Niko1221 41a5a5488d SYCL expert cache (#1440): a one-GPU run keeps the free-memory figure it had
The previous change skipped the DRM-fdinfo subtraction whenever the driver reported usage. On a single Arc Pro B70 that
made the expert cache 12168 slots instead of 11338 (23.09 vs 21.52 GiB), so a one-GPU run was not unchanged. The
subtraction is now skipped only when the process sees more than one GPU (where it double-counts the other card) and the
driver does not report the whole card as free.
2026-10-08 03:49:18 +02:00
Niko1221 a79e7225af SYCL doorbell spin bound chosen per device at run time (#1397)
The bound of the device's spins on host flags was a build constant: 20,000 reads for a bmg AOT build, 2,000,000
for anything else. A B70 built without AOT (SPIR-V, JIT: the Windows/OpenCL build, or a Linux build with no AOT
target) got the A750-sized bound. The issue reports a 37% drop in decode between 0.1.40.2 and 0.1.40.3. On a Linux B70 JIT build the two bounds decode
alike (--spec 2, 3 pairs: 19.4 vs 19.5 tok/s), so this makes the bound independent of the AOT flag but is not shown to be that drop's cause.

spin_max(queue) decides per device: 20,000 under the xe driver (the B-series on Linux), 2,000,000 elsewhere (the i915
A-series needs it for the host's per-layer expert work; a Windows/OpenCL B-series build measured faster with the long bound).
STRATA_SPIN_MAX=<reads> overrides it at run time; -DSTRATA_SYCL_SPIN_MAX=<reads> still fixes one bound for the
whole build. The three waiting kernels take the bound as an argument.
2026-10-08 03:40:09 +02:00
Niko1221andcrobe201 a85347811a SYCL layer split (#1440): the host mirror keeps to the first stage's layers; the fdinfo free-memory fallback only where the driver reports the whole card free
- generate.cpp: with a layer split the host mirror walked the later stages' layers too (#1054, fixed in #1111 but
  lost in the re-migration): 20 GiB of pinned RAM for experts the other card holds, or one 39 GiB pinned allocation
  that fails. Both loops stop at the first stage's last layer.
- expert_cache.cpp: device_free_bytes() subtracted the DRM bytes of every card of the process from the card it asked
  about, so on a layer split the second card was charged the first one's cache and its expert cache would not open.
  The fallback is for drivers that report the whole card as free (Arc A750/i915); it now runs only then.

Reported by crobe201 with both diffs; MaineTim confirmed the second on 2x B60.

Co-authored-by: crobe201 <[email protected]>
2026-10-08 03:07:50 +02:00
W1nge ccd657a296 cuda: retain HC norm products in existing scratch 2026-10-08 03:07:20 +02:00
W1nge 199fd1d5d8 prefill: reuse embedding storage for half outputs 2026-10-08 03:07:20 +02:00
Niko1221andMatthew Hines e372d4ffd9 q8_1 emit sites (#1448): clamp the scale and quantize against it, as the other producers do
The three sites fixed by the previous commit stored a clamped (d, sum) but still
quantized against the unclamped d, so an overflowing block stored int8 values
that no longer matched its stored scale. They now use q8_1_finite(d) and
q8_1_quant like native_quantize_q8_1_kernel, the swiglu quantizer and the CPU
pool. A block whose amax is finite and below 8.3M is stored bit for bit as
before.

Co-authored-by: Matthew Hines <[email protected]>
2026-10-08 03:02:42 +02:00
Matthew Hines 7a0e30235c #606: clamp the three unclamped q8_1 scale/sum emit sites via q8_1_ds
Three kernels still emit the (d, sum) pair of a q8_1 activation block
with a raw make_half2(d, sum), bypassing the finite helper the rest of
the tree uses (q8_1_finite.hpp, from 19de7f4 / f6601bf):

  fused_gr.cu   gr_q8_tail                 - the fused gate-reduce tail (QFUSE)
  verify_kernels.cu  gdn_q8_1_store        - the batched GDN verify store (QFUSE)
  iq_kernels.cu  s26_swiglu_q8_1_kernel   - the S26 swiglu path

A block whose amax overflows (or that reads a non-finite input) emits
d = inf/NaN; fp16 makes the pair NaN (or the pathological (0,0)). Nothing
downstream tests for it: a NaN scale poisons the fp16 dot of the quantized
activation and every sum downstream of it, and a fully non-finite logit
row ends at the sampler's all-NaN fallback - vocabulary id 0, the '!'
face of the degeneration reported in #606. Same defect class already
fixed at the other emit sites; these three were missed.

q8_1_ds() clamps both halves into the fp16-finite range (finite d,
non-negative finite sum - the sum is a mean of |x|), producing for the
GPU paths the same bits the CPU pool and the clamped GPU sites produce
for the same block. A clamp at the producer, content-blind: nothing
downstream of it is model-text-aware.

Criteria and the wider carried-state RCA: docs/Q8_1_FINITE_DS.md and
docs/DEGENERATION_RCA.md.
2026-10-08 03:02:28 +02:00
Niko1221 fbb362425c Pascal decode: keep __restrict__ and drop the PDL prefetch below sm_70 (#1469, #1470)
2e4ddf6 (the #904 port) removed __restrict__ from the activation pointers of
native_quantize_q8_1_kernel, bf16_f32_mmvf_multi_kernel and
native_mmvq_multi_kernel on every CUDA architecture, and turned on the weight
prefetch before pdl_wait(). Both only matter for PDL (sm_90+). On sm_61 the
missing restrict loses the read-only data path (LDG.CI) and decode halves
(36.4 -> 17.7 tok/s on a Tesla P40, 32-36 -> 17.7-18.6 on a GTX 1080 + 1070).

STRATA_PDL_RESTRICT is __restrict__ and kPdlPrefetch false again for
__CUDA_ARCH__ < 700 in the device pass. sm_70 and newer compile to the same
SASS as before (cuobjdump -sass of native_mmvq.cu and native_bf16.cu at sm_70,
86, 90 and 120 is identical); the host pass is unchanged.

Reported and bisected by paulhothersall and lineape.
2026-10-08 02:58:45 +02:00
Niko1221 c788e2aa72 Pascal decode: keep __restrict__ and drop the PDL prefetch below sm_70 (#1469, #1470)
2e4ddf6 (the #904 port) removed __restrict__ from the activation pointers of
native_quantize_q8_1_kernel, bf16_f32_mmvf_multi_kernel and
native_mmvq_multi_kernel on every CUDA architecture, and turned on the weight
prefetch before pdl_wait(). Both only matter for PDL (sm_90+). On sm_61 the
missing restrict loses the read-only data path (LDG.CI) and decode halves
(36.4 -> 17.7 tok/s on a Tesla P40, 32-36 -> 17.7-18.6 on a GTX 1080 + 1070).

STRATA_PDL_RESTRICT is __restrict__ and kPdlPrefetch false again for
__CUDA_ARCH__ < 700 in the device pass. sm_70 and newer compile to the same
SASS as before (cuobjdump -sass of native_mmvq.cu and native_bf16.cu at sm_70,
86, 90 and 120 is identical); the host pass is unchanged.

Reported and bisected by paulhothersall and lineape.
2026-10-08 02:58:44 +02:00
Niko1221 6c51a295b4 research: opt-in prefill hooks STRATA_DBG_FEAT (routing + hidden-state dump) and STRATA_DBG_ROUTE_OVERRIDE (not default-path) 2026-10-08 02:50:46 +02:00
Niko1221 9386089d80 docs: Lock pages in memory takes effect at the next logon (#1412) 2026-10-08 02:42:07 +02:00
paulhothersall 53c9baff07 docs: a short Contributing section in AGENTS.md and a test-requests list 2026-10-08 02:37:03 +02:00
Niko1221 5343e878a1 mtp: drop the duplicate dhead_type_ line from #1329 (f-141 already copies it); the batch-mtp test recipe stays 2026-10-08 02:36:53 +02:00
Ethan d1e93c02bf sweep: the round line prints that round's draw, not the median through it
Found while running it against a live engine: the line said 0.35 as 48.7 on round 3 while the three draws were 57.0, 48.7 and 35.5, because it printed the running median. Reading a sweep's drift is the whole point of the line, so it has to be the draw. The medians and the ranges are still in the line below it.
2026-10-08 02:36:32 +02:00
Ethan d1990da1a6 calibrate: the sweep visits every value in every round instead of once
Phase 1 measures each PCIe share once and takes the maximum, with the three prompts of that rate all at the one
setting.  Neighbours cannot be ordered that way: on this box 0.75 through 0.95 come out at 72.7, 69.0, 71.0 and
71.9, which is 0.2% apart, while the same settings moved 8-28% between engine starts.  A value that was worth a
real gain can lose its single sample and never be measured again, because phase 1's winner is the share phase 2
then sweeps spec_min_p at, and the confirm step only puts that one resulting pair against the default.

sweep() measures every value SWEEP_ROUNDS times inside the one engine start, one round visiting all of them and
every other round in reverse order, and the winners come from the medians.  Drift inside a sweep then lands on
every value the same number of times, and one bad sample cannot decide.  The same function runs phase 2, and the
confirm step uses the same round count instead of its own.

Cost: the sweep multiplies by SWEEP_ROUNDS, 3 by default.  A rate is three prompts of 128 tokens, so on this box
(six values, 95-100 tok/s) phase 1 goes from about 40 s to about 120 s, on a run that already loads the model more
than once.  A machine whose two leaders stay inside each other's noise can raise the constant.

Not in this change: phase 4 needs a restart per worker count and stays sequential, so a count is still taken from
one measurement each.

Tests: python -m unittest tools.test_calibrate (the stand-in engine is a pure function of the tune keys, so the
medians and the winners are the same as before); tools.test_setup_config and tools.test_setup_golden
2026-10-08 02:36:32 +02:00
Ethan fe0df23120 calibrate: the PCIe share sweep reaches 1.0, where no expert goes to the CPU pool
PCIE_FRACS stops at 0.75, so setup --calibrate never measures the value that takes the CPU pool out of the decode
window completely. 1.0 is a separate operating point rather than 0.75 carried further: the share is applied as
m = (nmiss * pcie_num) >> 8, so at any value below 1.0 at least one miss still goes to the CPU pool, and only at
1.0 does every non-resident expert come over PCIe. A CPU expert sits on the layer's critical path while the GPU
waits for it, and on a slow CPU that is the whole difference.

On a Core Ultra 9 290HX Plus with an RTX 5090 Laptop on PCIe 5.0 x16, 0.55 gives 51.1 tok/s against 71.3 at 1.0,
with cpu_exp falling from 1.06 to 0.00 per layer-window and the window time falling by the 11.3 ms of PCIe waiting
plus the CPU's expert time. A sequential sweep puts 1.0 at 78.8 against 72.7 for 0.75 and 51.5 for 0.35.

0.9 is added beside 1.0 so a machine where 1.0 is too much gets an interior point. pick() keeps the default unless a
candidate beats it by MIN_GAIN, so this cannot make a calibration worse. The cost is one rate per value, about 8 s
here.

Tests: python -m unittest tools.test_calibrate; tools.test_setup_config and tools.test_setup_golden
2026-10-08 02:36:23 +02:00
zetlaw e0f6da57f5 Fix shared MTP draft head type for batch slots 2026-10-08 02:36:23 +02:00
Alekperov Fuad 0d994dfb9c setup: link the engine against the toolkit whose nvcc builds it (CUDAToolkit_ROOT)
With a second toolkit beside the distribution's one, CMake compiled with the chosen nvcc but took cudart and cuBLAS from /usr (Ubuntu 24.04, STRATA_NVCC=/opt/cuda-13.0/bin/nvcc: the engine needed libcudart.so.12 while built with the 13.0 headers). Pass CUDAToolkit_ROOT for the engine and the CUDA image encoder; the distribution's own /usr/bin/nvcc keeps CMake's search as before.
2026-10-08 02:36:22 +02:00
MIDHAT NASHAR bee3b1947c test: make checkpoint byte fixtures valid under MSVC 2026-10-08 02:35:37 +02:00
phoenixclyde a732a19b6f hip/gfx906: the tree does not build (q6_k MMQ instance and cudaEventBlockingSync)
Two gfx906 build failures on v0.1.40.2. Both are one-line gates that know
about the wave32 HIP backend but not about STRATA_HIP_GFX906 -- the same
class as #808 and #1083. Neither is fixed on main (e8ca9afd03).

1) src/prefill/prefill.cpp:399 builds an event with
   cudaEventDisableTiming | cudaEventBlockingSync, but the gfx906 compat
   header include/strata/platform/hip_compat/strata_hip.h maps only
   cudaEventDisableTiming and cudaEventDefault. The wave32 header
   include/strata/hip_compat/cuda_runtime.h:39 has the mapping.
   -> add #define cudaEventBlockingSync hipEventBlockingSync there.

   A diff of the whole set of cuda* defines between the two headers lists
   one other name the gfx906 header lacks, cudaDevAttrIntegrated, and that
   one is already gated upstream (#if defined(__linux__) &&
   !defined(STRATA_HIP_GFX906) in src/core/expert_cache.cpp:31), so it is
   deliberately not touched here.

2) Link error: undefined symbol
   void mul_mat_q_case<(ggml_type)14>(ggml_backend_cuda_context&, mmq_args const&, ihipStream_t*)
   (14 = GGML_TYPE_Q6_K).
   src/prefill/moe_mmq.cu:219 calls it under
   #if defined(__HIPCC__) || defined(STRATA_Q6K_EXPERTS), so any HIP
   compilation references it; mmq.cuh declares the case as an extern
   template, so the definition must come from
   template-instances/mmq-instance-q6_k.cu. The CUDA branch of
   CMakeLists.txt adds that file only under STRATA_Q6K_EXPERTS.
   STRATA_HIP_GFX906=ON forces STRATA_ENABLE_CUDA=ON, so gfx906 takes the
   CUDA branch while its .cu files are compiled as HIP.
   -> widen the gate: STRATA_Q6K_EXPERTS OR STRATA_HIP_GFX906.
   This adds one MMQ instance to the static library. It does not enable
   STRATA_Q6K_EXPERTS (the grouped Q6_K expert kernels that allocate extra
   VRAM), and STRATA_HIP_GFX906 is only ever ON in the gfx906 build, so
   CUDA and wave32 builds are untouched.

Verified on a single Instinct MI50 32 GB (gfx906, wave64), ROCm/HIP 7.14,
-DSTRATA_HIP_GFX906=ON -DCMAKE_HIP_ARCHITECTURES=gfx906
-DSTRATA_MMQ_KQUANTS=ON:

- the engine builds and serves UD-IQ4_XS (Qwen3.8-Flash-Next) end to end:
  /v1/models, chat completions, tool calls, MTP drafts accepted;
- nm -C shows mul_mat_q_case<(ggml_type)14> in the binary (13 instances:
  7 8 12 13 14 16 17 18 20 21 22 23 42);
- change 2 is load-bearing: removing mmq-instance-q6_k.cu.o from
  libstrata_mmq.a and relinking with the same link command line fails with
  exactly the undefined symbol above (the archive holds one U reference
  and that one W definition), while the untouched archive relinks cleanly.
2026-10-08 02:35:37 +02:00
Niko1221 9bf626ff67 bench: COMMUNITY.md rows for the ten community folders ported from #1429 #1432 #1433 #1443 #1452 #1459 #1460 #1462 #1467 2026-10-08 02:34:58 +02:00
Dmitry f4e2c89c55 bench: community report - RTX 4090, Flash-Next IQ3_XXS at 204800, engine 0.1.40.3
Two variants of the same sweep (code-explanation prompts and Russian prose) on
one PC and one server config, engine 0.1.40.3 built from source for sm_89.
Each folder carries the 0.1.40.2 run, the 0.1.40 baseline and an
identical-binary control run so the noise band is in the report.

Result: no measurable change from 0.1.40.2 on this machine.
2026-10-08 02:34:06 +02:00
wolffahrer baa55adc4c bench: RTX 5090 Laptop GPU follow-up for 0.1.40.2 and 0.1.40.3
Same laptop, model files, configuration and scripts as the 0.1.40.1
entry (2026-10-06-community-rtx-5090-laptop, #1263); only the Strata
version changed. Raw data for 0.1.40.3, medians for 0.1.40.2 in the
README. Decode and prompt throughput unchanged within run-to-run
variation, all needles found, coding check 10/10 on 0.1.40.3. A 0/10
coding check on 0.1.40.2 is traced to a greedy reasoning loop that
occurs in 0.1.40.1 as well (re-runs documented). Results only, no
engine changes.
2026-10-08 02:34:05 +02:00
xWinIcex 654aa2edbe Add community benchmark: RTX 5080 in Docker Desktop on Windows (WSL2)
Coder IQ1_M, one RTX 5080 16 GB, the repository's own Dockerfile and entrypoint
on a Windows host (Docker Desktop 4.84.0 / WSL2), two context limits on the same
loaded model: 131,072 and 65,536.

- Speed: three runs at each of 4,096 / 8,192 / 16,384 / 32,768 / 65,536 /
  130,560 prompt tokens (128K limit) and at 4,096 / 8,192 / 16,384 / 32,768 /
  65,024 (64K limit), greedy, reasoning off, 256-token output cap, zero reused
  prompt tokens in all 33 runs.
- Correctness: tools/needle_bench.py 9 of 9 (32k/64k/128k) at the 128K limit and
  6 of 6 at the 64K limit, plus a vision check with the encoder on the CPU.
- Provenance: all three model files SHA-256-verified against the repository's
  published LFS oids at the pinned revision; MTP manifest and inventory included.
- Environment: Docker Desktop's default WSL2 memory cap makes setup.py read ~31 GB
  of a 64 GB host and silently select the low-RAM mode; the report documents the
  .wslconfig change used instead. Also documents the 8-token headroom a request
  needs (prompt + max_tokens + 8 <= max_context) and the engine's own VRAM warning
  at a 128K context on a 16 GB card.

Results-only; no engine changes.
2026-10-08 02:34:04 +02:00
saikiran-rs 244f113c96 bench: mixed AMD helper layout at1M, long-output and quality results 2026-10-08 02:34:02 +02:00
aleesposito85 69391129fe bench: community report, Tesla V100 32 GB + P100 16 GB expert-helper (mixed Volta/Pascal), Flash-Next IQ3_XXS (#1079) 2026-10-08 02:34:01 +02:00
rvannos 47e9552be7 Add benchmark results for 2x RTX 4000 configuration
Added detailed benchmark results for dual NVIDIA Quadro RTX 4000 setup, including performance metrics, hardware specifications, and observations.
2026-10-08 02:34:01 +02:00
Sophie Andreikina df53228251 community bench: RTX 5090 + RTX PRO 4000 Blackwell, UD-Q4_K_XL helper cache, engine 0.1.40.3 2026-10-08 02:33:57 +02:00
timnevits 6fff95b8a6 bench: Arc Pro B65 Gen4 results on v0.1.40.2 2026-10-08 02:33:56 +02:00
shrisha e905bf9946 bench: 2x TITAN RTX (sm_75) at Strata v0.1.40.3, IQ3_S, 262K
Nine files following docs/COMMUNITY_BENCHMARKS.md. Engine v0.1.40.3
(tag d5ea713) built from source for sm_75, IQ3_S at the model native
262,144-token window, with --vision and --reasoning-budget-tokens 12000.

Three runs each at 4,096 / 32,768 / 128,000 prompt tokens: decode
70.9 / 77.3 / 71.1 tok/s, prompt 868.9 / 1548.9 / 1626.9 tok/s, medians
in the index and full ranges in the report. needle_bench 6/6 at 32k and
128k. Records that NVLink is present but unused by the engine, so a bridge
on consumer boards is not worth buying.
2026-10-08 02:33:55 +02:00
Alex GorevskiandCopilot 86b283e1eb docs: record RTX 8000 existing runtime switch measurements
Document opt-in architecture limits, prompt/decode trade-offs, numeric caveats and negative tuning results without changing kernels or defaults.

Co-authored-by: Copilot <[email protected]>
Copilot-Session: a7c2bcbb-4264-4eb2-879d-c71a90285b0b
2026-10-08 02:33:19 +02:00
Lech Najdek f4ce5ac07f OLDER_GPUS.md: fill the P100 row with the 2x P100 IQ3_S measurements (#1157) 2026-10-08 02:33:16 +02:00
Niko1221 37338cadf1 setup: warn on a non-Default GPU compute mode; vision encoder start error names the busy/unavailable cause (#1445) 2026-10-08 02:31:56 +02:00
Niko1221andadambenhassen 54d26589ca setup: --remote-expert-opt only beside a helper cache; docs: --pipeline-windows and --adapt-async combine (#1447)
The flag acts only on --expert-cache-device1..3; a plain layer split got a no-op flag that the docs listed as a reason
for the pipeline and the async tier to switch off. Built on f-141-quick's #1352 pipeline-windows rule (same hunk).
MULTI_GPU.md: the two combine (only STRATA_PIPELINE_ADAPT_ASYNC=0 turns async off); adds the 2x3090 table.

Co-authored-by: adambenhassen <[email protected]>
2026-10-08 02:28:41 +02:00
Ron Forrester dd667967b9 serve: a tool call written <function= NAME> is the call NAME
The function name was everything between `<function=` and `>`, untrimmed. A model that writes a space after the `=`
(seen from Qwen3.8-Flash-Next IQ2_XS in Zed's agent panel) got:

- inside the thinking: the name " capture" matched no declared tool, so the #804 rescue kept the call as reasoning
  text; the reply ended with finish_reason "stop" and no tool_calls, and the agent stopped mid-task;
- after the thinking: a call named " capture", which the client does not know, its arguments typed without the
  tool's schema.

The name is now stripped where the call is parsed (parse_tool_call), where the #804 rescue checks it against the
declared tools, and where a finished call looks up its schema (_finish_call). A name with surrounding whitespace is
never meaningful, so no text becomes a call that was not one: the #804/#1058 rules still decide whether a call
inside the thinking is an act.

serve/test_tool_name_space.py: both places, streamed and not, fed in 3-character pieces; fails 4/4 before, passes
after. test_reasoning_rescue, test_reasoning_tools and test_frontend unchanged and passing.
2026-10-08 02:25:52 +02:00
Niko1221 c85b7c87b9 sm_70 (PR 1401): the Volta table, expert mode 8 and the fast norm/up are opt-in with STRATA_SM70_TABLE=1 until confirmed on a V100; default sm_70 behaviour as in 0.1.40.3 2026-10-08 01:24:59 +02:00
Niko1221 162ce64eff prefill: the CPU share is on by default on CUDA, one GPU, no batch slots, chunks below 1024 tokens (STRATA_PREFILL_CPU_SHARE=0 turns it off); start line; docs 2026-10-08 01:06:02 +02:00
Niko1221 eb98c622e4 docs: measured numbers for STRATA_STAGE_PIN, STRATA_ADAPT_LAG, STRATA_GDN_CHUNKED 2026-10-08 01:04:50 +02:00
Niko1221 fc8444367d batch pipeline: a pipelined slot is a cache again, so a request left alone goes back to the solo path (#857) 2026-10-08 00:27:40 +02:00
Niko1221 5aee72b107 serve: the frozen-engine check does not end an engine whose GPU is busy (telemetry reading) 2026-10-08 00:27:08 +02:00
Niko1221 d2e3f1c9dd Stage buffers: pinned by default while the host has 3 GiB of RAM to spare (STRATA_STAGE_PIN=0 off, =1 always); docs: the 0.1.41 opt-in switches; DETAILS: several API keys, the frozen-engine check 2026-10-08 00:01:29 +02:00
Niko1221 421e163a30 serve: STRATA_DUMP_FIRST_LOGITS also writes each request's first-window logits (<path>.<n>), to compare prompt paths by KL 2026-10-07 22:55:42 +02:00
Niko1221 21d4165b16 tests: --batch-groups auto follows the engine's INFO batch_groups 2026-10-07 22:25:11 +02:00
Niko1221 886bc47742 docs: --batch-groups auto in BATCHING.md 2026-10-07 22:23:40 +02:00
Niko1221 aa19d0d395 docs: stager profile for a warm GGUF read in place (#1353) 2026-10-07 21:37:19 +02:00
Niko1221 b2c5b22131 docs/INTEL.md: the A750 sampled path needs no FP64 emulation (measured) 2026-10-07 21:24:46 +02:00
Niko1221 ff3bda728d fix: newline in the batch-groups auto log line 2026-10-07 21:21:44 +02:00
Niko1221 67fba9c1fc serve: card order on AMD/Linux too (KFD topology: SIMDs x clock) 2026-10-07 21:19:17 +02:00
Niko1221 786b3ca016 serve: card order on AMD/Linux too (KFD topology: SIMDs x clock) 2026-10-07 21:19:07 +02:00
adonizm 0b030b96fc prefill: batched unbuffered expert reads in the stager; close the experts.bin view once reads are unbuffered
NTFS serves unbuffered reads of a mapped file one at a time (WD SN580: 2 MiB reads at QD32
2.35 GB/s mapped vs 3.57 GB/s unmapped). With the file tier unbuffered (--resident-budget-gib
or STRATA_UNBUFFERED_LOAD=1) the mapped view is only a fallback after startup, so it is closed
(STRATA_KEEP_MAPPING=1 keeps it). The prompt path's stager claims runs of consecutive jobs and
reads them with one read_direct batch (STRATA_STAGER_BATCH, default 8 for file-backed blobs).

RTX 5070 Ti, 32 GB RAM, IQ3_XXS, 47.6K prompt, --resident-budget-gib 18 --prefill auto:32768:
1260 -> 1370 tok/s (batch 8) -> 1669 tok/s (view closed).

Ported from #833 onto the rewritten main. Two fixes on the way: unmapped_ is declared on every
platform (mapped_blob reads it outside the Windows block, so Linux did not compile), and
copy_blobs asks resident_blob, which follows the exchange rotation (STRATA_EXCHANGE_ROTATE).
2026-10-07 21:18:06 +02:00
Niko1221 d9621d1e23 serve: a request with no free slot gives the control lines back while it waits (long, long, short under parallel: 2 deadlocked: the slot a yielded read held needed the lines); regression test 2026-10-07 21:15:34 +02:00
Niko1221 039f9e9018 serve: malformed-shape bodies get a 400 with the traceback logged, a body-size cap (256 MiB, STRATA_MAX_BODY_MIB) and a bad Content-Length are answered before the read; engine warns on --batch-groups with --batch-mtp (#1413) 2026-10-07 21:08:03 +02:00
Niko1221 1bf6344cb3 Concurrency stage 1: --batch-groups auto (one pipeline group per GPU stage), INFO batch_groups; tools/serve_load.py load generator 2026-10-07 21:07:59 +02:00
Niko1221 f346dc6b0c tokenizer: remember the ids of repeated pre-tokenizer pieces (a resent 89K-token agent prompt encodes in 0.07 s instead of 0.32 s; same ids) 2026-10-07 21:05:33 +02:00
Niko1221 dfa26c19c9 tests: qsa_select_bench accuracy floor 1e-5 of the score scale (the fast scorer sits at 1e-6 against FP64; warp kernel 7e-8) 2026-10-07 21:02:45 +02:00
Niko1221 bad9a8f22e serve tests: a stopped server stops its hardware sampler (21 samplers leaked after test_responses skewed test_parallel's timing) 2026-10-07 21:00:39 +02:00
Niko1221 533667d06d fix the escape in the watchdog IO note (#1407) 2026-10-07 20:58:08 +02:00
Niko1221 37fa9f7817 sycl: the sampler's launchers no longer require FP64 (dpct left aspect::fp64 checks; samp_acc_t is float by default), so a sampled token no longer needs Intel's FP64 emulation on an A750 2026-10-07 20:56:08 +02:00
Niko1221 125f6ff05f native_mmvq, mmvq_il_parity, generate: fix newline escapes in messages 2026-10-07 20:50:30 +02:00
Niko1221 b7dd070d96 strata --version; build warnings: weights.cpp index scanf formats, qsa_layer unused variables and one-line statements, ignored cudaFreeHost results 2026-10-07 20:47:36 +02:00
Niko1221 ef362cc4ab One prefetch design (#1348): the router look-ahead feeds the Foresight swap space (ForesightSwap::predict, STRATA_FS_AHEAD), slot state under a mutex 2026-10-07 20:47:21 +02:00
Niko1221 b9aa4558a4 setup: checksum verified line, .previous keeps its BUILD.json; update scripts drop the backup branch when the move fails 2026-10-07 20:46:11 +02:00
Niko1221 d7f039992a sycl: expert dequant stores coalesced (lane tid writes the tid-th 16-byte run), bench dequant_bench; IQ3_S 200 -> 423 GB/s of writes on the B70, output bit-identical 2026-10-07 20:43:21 +02:00
NoxestNoz b04507c12f bench/results: V100 decode kernels (GPU work per verify window 22.8 -> 21.2 ms); docs/NVIDIA_V100.md: the decode side; tools/ab_engine.py 2026-10-07 20:42:39 +02:00
NoxestNoz aaa323fec5 fused_gr: Volta runs gfx906's latency-hidden norm/up (STRATA_GR_FAST), which now also writes the QFUSE q8_1 tail
The fast kernels build for CUDA; sm_70 defaults to them, other CUDA cards keep
the plain ones.  gr_up_fast_kernel ends with gr_q8_tail like gr_up_multi_kernel,
so STRATA_QFUSE gets its q8_1 image from it too.  In the engine (staged read)
only the up projection changes: hc-read0's up 1.08 -> 0.96 ms per window on a
V100-SXM2.  fused_gr_bench bitwise, gr_multi_parity OK.
2026-10-07 20:42:39 +02:00
NoxestNoz e509ba5e3d native_mmvq: the interleaved 2-4 column kernel on Volta, with a rows table read off a V100
Read off mmvq_il_parity --bench on a V100-SXM2-32GB with the table's own rule
(every measured shape of a class at least 3% faster, else native_mmvq).  At 3
columns: the Q5_K head 1094 -> 821 us, Q6_K 12288 rows 68.9 -> 47.9 us, Q4_K
10240 rows 43.9 -> 32.5 us.  Bitwise native_mmvq's output (mmvq_il_parity OK).
2026-10-07 20:42:39 +02:00
NoxestNoz f6330507db iq_kernels: Volta runs the routed experts in gfx906's expert mode 8 (bitwise the CUDA layout)
The AMD grouped-expert layouts (STRATA_EXP_MODE) now build for CUDA too.  sm_70
defaults to mode 8 - the codebook grid and the group's q8_1 activations in
shared memory, SwiGLU + q8_1 fused into the gate/up epilogue - every other CUDA
card keeps mode 0.  On CUDA, IQ2_XXS gate/up joins the shared-memory kernels,
a format without one falls back to the CUDA layout (not R2), and a strided call
(the verify window's PCIe call) keeps the CUDA layout.

V100-SXM2, setup's IQ2_XS, a verify window's VRAM call (28 groups): IQ2_S
gate/up layers 180 -> 150 us at 3 tokens, IQ2_XXS 170 -> 134 us; bitwise mode
0's output on all 48 layers (native_expert_bench), native_grouped_parity 0
failures in modes 0/2/7/8.
2026-10-07 20:41:10 +02:00
Niko1221 51d1ef4b8a Stage buffers: STRATA_STAGE_PIN switch (default decided by the A/B) 2026-10-07 20:40:45 +02:00
Zhong Uncle 475912c62a perf(expert): the stage buffers the cache fill copies from, pinned with cudaHostAlloc
A staged blob (the GGUF role slices assembled into one buffer) is handed to
ExpertCache::fill_slot's cudaMemcpyAsync as-is.  From a pageable buffer the
driver stages every copy through an internal bounce buffer - an extra copy at
a fraction of the transfer rate, on the calling thread - so the admit path,
the profile prefill and the lent-slot refills all pay it per expert.  Allocate
the pool's buffers with cudaHostAlloc instead, falling back to pageable for a
buffer when the driver refuses (pinned memory is scarce on the small-RAM
machines this path serves).
2026-10-07 20:40:45 +02:00
Niko1221 311c983964 serve: a config with a vision section but no --vision in its args starts the engine with images (#1322) 2026-10-07 20:39:21 +02:00
architectds ed6a02cdb3 docs: the CPU share up to 3,072-token chunks, from mapped experts, on a split - and what it measured
DETAILS.md's STRATA_PREFILL_CPU_SHARE section: chunks below 3,072 tokens are staged when it is on
(STRATA_PREFILL_CPU_SHARE_MAX=1024 keeps the old limit), the experts the CPU may take (the arena, the
page-locked copy, the mapped experts.bin's pages), the layer split, and a table measured on an RTX 5070 Ti
alone and an RTX 3060 + RTX 5070 Ti split (PCIe 3.0 x8, DDR4-3200, --mmap-experts): 512-token prompts
-49% / -41%, 3,000-token -22% / -24%; a recorded 100K-token coding conversation on the two cards 137.4 ->
130.6 s.
2026-10-07 20:39:12 +02:00
architectds 92bce20e4b prefill: the CPU share up to 3,072-token chunks, from mapped experts too, and on a layer split's stages
STRATA_PREFILL_CPU_SHARE handed the CPU pool its share of a chunk below 1,024 tokens only, only experts in
page-locked RAM, and only on one GPU.  With it set:

- the chunks staged after their routing (the only ones the share applies to) go up to
  STRATA_PREFILL_CPU_SHARE_MAX tokens (default 3072, at least 1024) instead of 1024; Prefill::arm_cpu_share
  sets the limit before any loan is sized, and init sets it too;
- an expert whose blob the CPU reads from RAM without assembling it (the arena's unpinned part, the mapped
  experts.bin's pages) can go to the CPU, not only a page-locked one; the blob pointers are taken when the
  experts are chosen, and one without a stable blob stays on the GPU;
- on a layer split every stage has the pool (serve, no --batch), and one stage at a time takes it for a
  chunk while the other reads its chunk on the GPU alone.

Unset, nothing changes.
2026-10-07 20:39:00 +02:00
sergiywith f2a3b946e9 prefill: STRATA_PREFILL_CPU_SHARE=auto times layers with and without 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.
2026-10-07 20:38:56 +02:00
Niko1221 804dc7c326 setup: no --remote-expert-opt beside --pipeline-windows (the first turns the second off); docs: card order (#1352) 2026-10-07 20:38:27 +02:00
Niko1221 ae083aebbf calibrate: a later engine start that fails drops that candidate and keeps the earlier measurements (#1337) 2026-10-07 20:37:56 +02:00
Niko1221 be8db787c2 serve: card order for an auto layer split, faster card last (SMs x clock), gpu_order as_given opts out (#1352) 2026-10-07 20:37:35 +02:00
Niko1221 f60a12d407 conversation_cache_test: fix check call 2026-10-07 20:37:20 +02:00
Niko1221 f2e07afbf1 serve: the #29 watchdog waits (up to 10x, STRATA_WATCHDOG_IO_S) while the OS is still reading the file tier (#1407) 2026-10-07 20:37:15 +02:00
Niko1221 9b4336a225 conversation_cache_test: evict_oldest with pinned entries 2026-10-07 20:37:15 +02:00
alanthinker 940011dad9 serve: a full conversation cache evicts to pass the physical-RAM gate instead of dropping the snapshot
The parking path has two gates in series: make_room() balances the cache's own budget, then conversation_memory_admit() checks the host's free RAM against the snapshot plus --conversation-cache-min-free-mib. The second was final: a failure dropped the snapshot even though the cache held conversations whose RAM it could have, and the next request read its whole prompt again (270k tokens, 96 s, measured by the reporter in #1347).

Evict the least recently active parked conversations until the gate admits the snapshot, bounded by the slot count; entries that hold a pinned shared prefix are not evicted. The failure line says how many were evicted and how many remain.

Reported with the fix by alanthinker in #1347.
2026-10-07 20:37:05 +02:00
Niko1221 d7932123e1 serve: #1317 part 2 quick watchdog for a frozen engine (90 s silent, no CPU or disk work; STRATA_ENGINE_STALL_S); #1344 several API keys (comma list or config list) 2026-10-07 20:36:40 +02:00
Niko1221 f23913a0ac tests: expert_multi_test skip message had a literal newline in its string 2026-10-07 20:33:49 +02:00
Niko1221 f780961c44 fix the escape in the lend-coverage warning (#1389) 2026-10-07 20:32:56 +02:00
Go Kudo 61a76de08d hip: hipBLASLt tuning table for gfx1150 (Radeon 890M, ROCm 7.14.1 / hipBLASLt 100401)
The 16 dense GEMM geometries a Qwen3.8-Flash-Next prompt logs on a Radeon 890M (gfx1150, Strix Point) at
T = 64 .. 16384, 144 rows, calibrated with tools/hip/tune_hipblaslt.cpp against AMD's TheRock ROCm 7.14.1 for
gfx1150 (hipBLASLt 1.4.1 cd957402). Two passes back to back; each row keeps the solution with the lowest median of
all six repetitions (a single repetition stalled now and then, and the tool's mean-of-three picks differed in 26 rows
between the passes).

Every row beats plain hipBLAS, 1.55-22.6x per GEMM. End to end on GSQ-RCO IQ3_XXS, three interleaved rounds: prompts
read 1.5-1.7x faster (3.6K tokens 124 -> 216 tok/s, 7K 130 -> 226 tok/s), decode unchanged; hip_prefill_hipblaslt_gemm
passes with it and a server run logged no fallbacks. Setup does not install for gfx1150, so the table is set by hand
(STRATA_HIPBLASLT_TUNING). Method and data: bench/results/2026-10-07-community-gfx1150.
2026-10-07 20:32:04 +02:00
Chen Cheng a0181802b0 generate: say that CUDA_LAUNCH_BLOCKING=1 hangs the verify windows (#1341 #964)
A verify window's graph waits on the GPU for flags the host raises once
cudaGraphLaunch has returned. A blocking launch returns only when the
graph has finished, so with CUDA_LAUNCH_BLOCKING=1 the first window after
a prompt never ends and the watchdog stops the engine, whatever the prompt
length, GPU count or --pipeline-windows. The engine now says so at start,
and the watchdog's line names it. Nothing changes without the variable.
2026-10-07 20:31:54 +02:00
Niko1221 2d6c6ae5ce MMVQ_IL rows table per architecture: kIlArch hook, STRATA_MMVQ_IL_ROWS override, mmvq_il_parity --emit-table, the sm_89 method 2026-10-07 20:31:41 +02:00
Niko1221 83a7dbc0f1 prefill: the stager takes the RAM profile when the GGUF experts' pages are in the page cache (#1353) 2026-10-07 20:29:45 +02:00
Niko1221andblange48 2c7c02ab72 serve: with pipelined groups, a request fills a hole below a busy slot of its group first (#793)
A pipelined group's window spans its slots up to its last busy one, and the engine keeps no pipelined slot as a
conversation cache, so the least-recently-used pick left leading holes ([_ B]) that cost a whole row each.  pick_slot
now fills such a hole first, then follows the spreading order.  The engine reports INFO batch_groups so the server
knows the groups really run pipelined.  serve/test_slot_alloc.py covers the allocator.

Co-authored-by: blange48 <[email protected]>
2026-10-07 20:29:09 +02:00
shy 0391e478ce split: the auto placement sees each stage's PCIe link
The miss cost (190 ms per unit of routed mass, fitted on x16 links) is one
constant for every stage, so --layer-split auto cannot see an asymmetric
pair: on 2x 4090 D with CUDA1 on a physical x1 link (1.6 GB/s measured) it
gives that card 26 layers (K=22) and reads a 29K prompt at ~350 tok/s.

Probe each stage's link inside the search (probe_pcie_h2d_gbps; the
stage-setup probes are skipped when --pcie-frac is given, and the search
needs the reading either way) and scale that stage's miss term by
clamp(20 GB/s / bw, 1, 64).  20 GB/s is pcie_frac_for_gbps' x16 reference;
the lower clamp keeps a symmetric machine on the exact formula the sweep's
K was fitted with (every scale 1.0 -> the objective is unchanged).

With it, auto picks the fit-in-cache boundary on that machine (K=38: the
narrow card's cache holds all of its layers' pairs, zero streaming there)
and reads the same prompt at ~1410 tok/s, ~4x.

The 190 ms mixes the decode CPU-pool cost with the prompt link cost;
scaling the whole per-stage term is the first-order fix (splitting the
constant would need a fresh fit on both a narrow and a wide link).
2026-10-07 20:28:02 +02:00
Niko1221 85a108a751 gdn_rec_parity: same STRATA_GDN_CHUNKED=2 SM-count bypass as the engine copy 2026-10-07 20:27:55 +02:00
Andy 0c7eb37d1b Foresight swap: slots copied in but never used again become reusable once landed (they leaked as 'loading') 2026-10-07 20:26:47 +02:00
Andy 44f650f972 Foresight swap: STRATA_FS_VERIFY test mode (read every landed slot back, compare with its source) 2026-10-07 20:26:47 +02:00
Andy 14f9e4c50b Foresight swap space: per-layer VRAM slots refilled on their own stream with recently missed experts, served as GPU groups at the pool's existing per-layer decision (STRATA_FS_SLOTS, off by default) 2026-10-07 20:26:47 +02:00
Niko1221 b92a44bfc7 peer: STRATA_PEER_NO_P2P=1 test knob (pretend the pair has no P2P) 2026-10-07 20:25:14 +02:00
Niko1221 f0880b3251 STRATA_GDN_CHUNKED=2: skip the 128-SM test so the chunked recurrence can be measured on smaller cards 2026-10-07 20:25:11 +02:00
Jim Routh 8d6e8ca3fc docs: STRATA_PREFILL_STREAM_MIN=128 in the gfx1151 fast configuration
STRATA_PF_FUSED=1 reaches only chunks of stream_all_min() tokens or more (1,024, measured on a discrete card); a
smaller read runs its experts through MMQ. On Strix Halo every expert is resident and MMQ is ~3x slower on a
~1,000-token read, the size of an agent's turn: 441 / 855-token reads 3.1 / 4.0 s -> 0.9 / 1.2 s, a 12-turn agent
replay 3.4 -> 2.1 s per turn (C2T8, --no-prefill-borrow). It changes bits (the fused path's output, which reads of
1,024+ tokens already get), so section 5: teacher-forced KL against today's path 0.016 on reads under 1,024, the same
as fused vs MMQ on longer reads (0.019); reads of 1,024+ unchanged (KL 0).
2026-10-07 20:25:01 +02:00
alexdns1 94f9d169af hip: gfx1151 hipBLASLt tuning table (hipBLASLt 1.4.0)
Setup installs the ROCm 7.14.0a20260608 wheels for gfx1151 since 0.1.40.2 (#1267); their hipBLASLt is 1.4.0
(100400), which neither gfx1151 table matched, so setup's engine read the prompt through plain hipBLAS.
tune_hipblaslt --workspace-mib 32 on the 100401 table's 90 shapes, on a Ryzen AI Max+ 395 (Radeon 8060S, gfx1151,
128 GB, Fedora 44, kernel 7.2.8) with those wheels: 3.1-14.1x faster than plain hipBLAS per shape (median 6.2x).
hip_prefill_hipblaslt_gemm and hip_prefill_hcd_exact_parity pass with it (fallbacks=0); HIP ctest 61 of 62
(ple_parity needs the Q2_0 fixture). setup picks it up with no code change.
2026-10-07 20:25:01 +02:00
Niko1221 14d9d2e1a5 Warn when the prompt path's lend coverage is short; document STRATA_RESIDENT_HEADROOM_GIB and the long-prompt method (#1389)
Below N of N lendable slots the uncovered experts are read from the pack during a long prompt (reporter: 18% uncovered = -26% prompt speed on gfx1100). A WARNING line now says so, and docs/AMD_HIP.md documents the headroom knob and the levers from the report. No behaviour change otherwise.
2026-10-07 20:25:01 +02:00
sergiywith 0f78032fdc DeltaNet recurrence: STRATA_GDN_CHUNKED=1 - the prompt's recurrence in 32-token chunks (opt-in, 1.8x faster, other bits)
The gated delta rule in the WY form flash-linear-attention uses, all FP32: gdn_chunk_prep_kernel forms k.k / q.k and
T = (I + A)^-1 for every chunk of a 2048-token super-block at once; gdn_chunk_scan_kernel (128 blocks, a key head x
16 value columns each) walks the chunks with its state slice in registers.  Every exponent <= 0 (the gates are
negative).  The scratch (25.6 MB) is allocated once per device: freed and reallocated per call it cost more host time
than the kernels saved on short prompts.  sm_80+, >= 128 SMs, enough shared memory, chunks of >= 128 tokens; else
gdn_rec_kh_kernel.  Unset: unchanged.

gdn_rec_parity: against gdn_rec_kh_kernel <= 1.13e-6 (T = 1..4099, 8192, 32768, a non-zero starting state); against
an FP64 recurrence <= 1.05e-6 (the sequential kernel <= 3.2e-7) - FP32 rounding; 199 restarts of 7 shapes bit for
bit (NaN-filled scratch between).  RTX 5090: 1.81x the recurrence at 2K-32K; IQ2_XS: the recurrence phase of a 32K
prompt 520-532 -> 306-334 ms (-210 ms, -3.7%), 8K -2.1..-3.6%; first-token KL 0.0016-0.0152, 1.15-1.83x a harmless
control arm (STRATA_PROMPT_ATTN_V1), the same top token.
2026-10-07 20:24:14 +02:00
Thig 59ea77e5b3 prefill: the no-P2P hand-off copies on a stream of their own
The MoE input and the routing weights go to host memory on a stream beside the primary's compute stream, so its
own experts start at once instead of behind the copies over its link (mixed_h and w are rewritten only after this
layer's combine, which waits for the peer).  STRATA_PF_PEER_XSTREAM=0: the compute stream.  With
STRATA_PF_PEER_RING=160, prompt tok/s: 100K 1,854 -> 1,918; 8K and 3.4K unchanged.
2026-10-07 20:24:05 +02:00
ThigandEddoursul da0024fed1 prefill: the peer's per-token sums in one launch per group instead of one per expert
Each group's tokens and their row lists (in the experts' order) are built on the host from the rows' pairs and
uploaded once per layer; peer_gather_add is eddoursul/Strata's moe_gather_add with the weight looked up through
the row's pair, so the sums are bitwise those of the per-expert launches.  STRATA_PF_PEER_GATHER=0: per expert.
Prompt tok/s against the per-expert launches: 3.4K 825 -> 832, 8K 1,468 -> 1,500, 100K 1,821 -> 1,858.

Co-Authored-By: Eddoursul <[email protected]>
2026-10-07 20:24:05 +02:00
ThigandEddoursul 550159fc59 prefill: the no-P2P sums mode's two transfers in FP16
The MoE input goes out as the FFN input's existing FP16 image (mixed_h) and the per-token sums come back as
FP16, saturated at +-65504 (eddoursul/Strata f8de703's FP16 input, 2acfac4's sums_to_f16): half the bytes over
the primary's link both ways.  STRATA_PF_PEER_F16=0: FP32.

Peer stream 0.6, prompt tok/s: 3.4K 805 -> 831, 8K 1,284 -> 1,495, 100K 1,578 -> 1,855 (the share off: 1,712).
The 8K and 3.4K answers stay byte-identical to the share off.

Co-Authored-By: Eddoursul <[email protected]>
2026-10-07 20:24:05 +02:00
ThigandEddoursul f4bfedc5ce prefill: the no-P2P peer share sends each token's weighted sum back instead of its rows
The design is eddoursul/Strata's second-GPU prompt path (f8de703, 2acfac4, e8ade66): the second GPU adds its
experts' rows into each token's weighted sum and the first GPU's combine adds that to its own experts' rows.
Over the host route the peer scatter-adds its rows into per-token sums (peer_scatter_add, after the fork's
moe_scatter_add: one launch per expert in a fixed order, so the sums are repeatable) and sends T x N floats
back instead of rows_peer x N (up to K = 10 times more); moe_combine_peer adds them to the primary's rows.  The
2a row buffers are not allocated (3.4 GB of pinned RAM at 32K-token chunks).  STRATA_PF_PEER_SUMS=0: rows.

Same setup, peer stream 0.6, prompt tok/s against the share off: 3.4K 332 -> 805, 8K 762 -> 1,284, 100K
1,712 -> 1,578.  The 8K and 3.4K answers are byte-identical to the share off (greedy, 256 / 3,221 tokens).

Co-Authored-By: Eddoursul <[email protected]>
2026-10-07 20:24:05 +02:00
Thig 81af1da0b1 prefill: --peer-device's prompt share without P2P, through the layer split helper's mapped host route
set_peer refused a peer that cannot access the primary directly, so on GPU pairs without P2P (most GeForce
pairs) the prompt path stayed on the primary GPU.  Without P2P the share now takes the route the layer split's
helper already uses: the activations and the result rows through mapped pinned host buffers read by copy
kernels, with the compact group buffers (the layer-sized path copies over P2P only).  STRATA_PF_PEER_HOST=0
restores the refusal.

RTX 3090 (PCIe 4.0 x4) + RTX 3080 Ti (x16), no P2P, UD-Q4_K_XL, --prefill auto:32768, peer stream 0.35 / 1.0,
prompt tok/s against the share off: 3.4K 332 -> 492 / 551, 8K 763 -> 907 / 776, 100K 1,713 -> 1,072 / 734.
The peer's rows coming back over the primary's x4 link cost more than they save on long prompts; the next
commit sends sums instead.
2026-10-07 20:24:05 +02:00
Niko1221 344ea1cd4b tools: check_isa_guard flags std:: instantiations only inside the wide-ISA objects 2026-10-07 20:23:53 +02:00
Niko1221 f02c244628 tests: expert_multi_test skips on a CPU without the AVX-512 kernel's features 2026-10-07 20:23:53 +02:00
Niko1221 90dd021a70 tests: AVX2 dispatch never enters wider code (#795)
- tools/check_isa_guard.py disassembles the CPU kernels (objdump + nm on the Linux kernel library, capstone + the /MAP
  file of a linked binary on Windows) and fails when a function holding AVX-512 / AVX-VNNI-class instructions is
  not a kernel of a wide-ISA file: a weak or COMDAT copy (the linker may pick it for every caller), a std:: /
  template instantiation, a probe or helper that every CPU runs, or code in another object.  MSVC's own
  `__isa_available` vectorizer guard is accepted.  ctest isa_guard_check runs it; exit 77 (skip) when the tools
  are missing.
- -DSTRATA_SDE=<sde> adds sde_{hsw,adl}_* tests: the CPU parity tests on an emulated Haswell (AVX2 only) and Alder
  Lake (AVX-VNNI, no AVX-512); SDE stops at the first instruction the chip lacks.
- tools/test_check_isa_guard.py: unit tests of the policy.
2026-10-07 20:23:53 +02:00
Niko1221 680d499291 cpu: keep the AVX-512 probe and the "supported?" helpers out of the wide-ISA files (#795)
expert.cpp and iq_avx512.cpp are compiled for AVX-512, iq_avx2.cpp and kq_avx2.cpp for AVX2, and a file compiled
that way may use the wide ISA anywhere in its code.  Code that every CPU runs was still defined in them:

- cpu_features, CpuFeatures::reason, cpu_require_expert_support (the function that finds out whether the CPU has
  AVX-512) and expert_set_oracle_q8_0 / expert_oracle_q8_0_enabled (the first call of every generate, on any CPU)
  were in expert.cpp;
- iq512_supported, iq256_supported and kq256_supported (a comparison native_gu_rows asks before it has checked
  what the CPU can run) were in the kernel files; iq512_supported was called on every AVX2-only CPU for every
  gate/up call.

They now live in expert_layout.cpp and native_expert.cpp, which are built for the baseline.  No kernel changes;
the compiled code of the moved functions is identical, so default output is byte-identical.
2026-10-07 20:23:53 +02:00
1303 changed files with 276077 additions and 3411 deletions

No files matched your search

+3
View File
@@ -7,3 +7,6 @@ bench/prompts/** -text
# copies of real packs' native_experts.txt, parsed byte for byte by tests/core/expert_layout_test.cpp
tests/data/native_experts/** -text
# the quant yardstick's text set: tokenized byte for byte (set.ids.json), never convert its line endings
data/quant_quality/** -text
+3
View File
@@ -61,3 +61,6 @@ build-vision-cuda12.bat
/.ccache/
/.rocm-win/
# local Windows HIP packaging output
dist-hip/
+13
View File
@@ -21,3 +21,16 @@ offers the same steps as tools.
`tools/test_setup_amd.py`, `tools/test_setup_choices.py`).
- Keep the docs' style: plain words, measured numbers with what they were measured on, no claims without a
measurement.
## Contributing a change or report
- Search the open issues and pull requests first, and add to a thread that already covers your point.
- Open an issue with the form that fits (bug report, feature request or question).
- One change per pull request. Say what it changes and what it leaves alone.
- A new feature is opt-in, and the default path stays byte-identical to the last release. Say how you checked.
- Build every backend a file touches (CUDA, HIP, SYCL) before asking for review.
- Change a default only where you measured it faster, and show the numbers with what they were measured on.
- A report from hardware the maintainers do not have is welcome. Follow
[docs/COMMUNITY_BENCHMARKS.md](docs/COMMUNITY_BENCHMARKS.md), compare against a same-day run of the build you are
testing, and say what you did not test.
- Open test requests and the hardware that is wanted are listed in [docs/TEST_REQUESTS.md](docs/TEST_REQUESTS.md).
+16
View File
@@ -0,0 +1,16 @@
@echo off
rem Benchmark this Strata install the way it is used and write a report you can share (docs/COMMUNITY_BENCHMARKS.md).
rem It starts the model with your settings (or uses the one already running), takes about 10 minutes and changes nothing.
rem Options: --clients 4 (several requests at once), --long (a 32K prompt), --compare <older results folder>.
setlocal
title Strata - benchmark
cd /d "%~dp0"
if not exist ".venv\Scripts\python.exe" (
echo Strata is not set up here yet: run START-HERE.bat first.
pause
exit /b 1
)
".venv\Scripts\python.exe" tools\strata_bench.py %*
set "RC=%ERRORLEVEL%"
pause
exit /b %RC%
+523 -24
View File
@@ -8,7 +8,7 @@
# below refuses anything older: silently building for a pre-Ampere arch would produce a binary that runs
# and is wrong about its own performance, which is the worst of both outcomes.
cmake_minimum_required(VERSION 3.24)
project(strata VERSION 0.1.40.3 LANGUAGES CXX)
project(strata VERSION 0.1.45 LANGUAGES CXX)
# EXPERIMENTAL: the Intel Arc engine, the SYCL port in sycl/ (PR #423; icpx + oneMKL, docs/INTEL_ARC.md). It is its
# own project that takes the unported sources from src/; with this on, nothing below is configured.
option(STRATA_ENABLE_SYCL "EXPERIMENTAL: build the Intel Arc (SYCL) engine from sycl/ - docs/INTEL_ARC.md" OFF)
@@ -70,18 +70,30 @@ if(STRATA_HIP_GFX906)
endif()
option(STRATA_ENABLE_HIP "Build the HIP targets for wave32 AMD GPUs (gfx1100, gfx1201; gfx1012/gfx1030 unvalidated)" OFF)
option(STRATA_PREFILL_MMQ "Build the optional GGML MMQ prefill path for HIP" OFF)
# CUDA: MMQ prompt kernels for Q4_K / Q5_K / Q5_1 (Unsloth's UD-Q4_K_XL experts). Off by default: the engine loads
# every kernel when it starts (CUDA_MODULE_LOADING=EAGER), so these took ~5 MB of VRAM - 1-3 expert slots - from every
# model, and the UD-Q4_K_XL prompt is SSD-bound with or without them (docs/UNSLOTH_Q4.md)
option(STRATA_MMQ_KQUANTS "Build the MMQ prompt kernels for Q4_K / Q5_K / Q5_1 / Q6_K: the CUDA experts of Unsloth's UD-Q4_K_XL, and on HIP the dense GGUF projections (STRATA_DENSE_MMQ)" OFF)
# CUDA: Q6_K gate/up in the grouped expert kernels (Unsloth's UD-Q6_K_XL, docs/UNSLOTH_Q6.md). Off by default: every
# grouped-kernel instance is loaded when the engine starts (CUDA_MODULE_LOADING=EAGER), so one more costs VRAM that
# every other model would lose as expert slots (PR #860 review)
option(STRATA_Q6K_EXPERTS "Build the Q6_K gate/up grouped expert kernels (UD-Q6_K_XL)" OFF)
# MMQ prompt kernels for Q4_K / Q5_K / Q5_1 / Q6_K (Unsloth's UD-Q4/Q5/Q6_K_XL experts; on HIP also the dense GGUF
# projections, STRATA_DENSE_MMQ). On by default since MODEL-UPDATE Phase 1: on CUDA they are their own library
# (strata_kq, loaded only for a model with these formats: the engine loads every kernel of its own binary at start,
# CUDA_MODULE_LOADING=EAGER, and these took ~3.8 MB of VRAM - 3 IQ3_XXS expert slots on a P100 - from every model); on
# HIP a code object loads on first use, so they cost other models nothing there (R9700: the same slots). Used at run
# time with STRATA_MMQ_KQ=1 (opt-in: it changes the prompt's rounding against the FP16 path).
option(STRATA_MMQ_KQUANTS "Build the MMQ prompt kernels for Q4_K / Q5_K / Q5_1 / Q6_K: the experts of Unsloth's K-quant files, and on HIP the dense GGUF projections (STRATA_DENSE_MMQ)" ON)
# Q6_K gate/up in the grouped expert kernels (Unsloth's UD-Q6_K_XL, and layer 2 of UD-Q5_K_XL; docs/QUANTS.md). On by
# default since MODEL-UPDATE Phase 1: one more instance per grouped kernel in iq_kernels.cu, +19 KB of sm_60 code,
# measured to leave every expert-cache slot count as it was (P100, R9700). -DSTRATA_Q6K_EXPERTS=OFF drops it.
option(STRATA_Q6K_EXPERTS "Build the Q6_K gate/up grouped expert kernels (UD-Q6_K_XL, UD-Q5_K_XL)" ON)
if(STRATA_Q6K_EXPERTS)
add_compile_definitions(STRATA_Q6K_EXPERTS=1)
endif()
option(STRATA_ORCA_Q4KS_MMQ "Build the GGML Q5_0 MMQ instance for OrcaRouter Q4_K_S" OFF)
# CUDA: the pointer-table MMQ behind STRATA_MMQ_DIRECT=1 (the prompt path's MMQ reads resident experts in their cache
# slots through a Strata-side copy of llama.cpp's MMQ scheduler, src/prefill/moe_mmq_tab.cuh). Off by default, like
# the K-quant options above: the engine loads every kernel when it starts (CUDA_MODULE_LOADING=EAGER), and these nine
# instances (+15 MB of binary) take 36-38 MiB of VRAM per GPU on sm_86 - expert slots every model would lose, with
# STRATA_MMQ_DIRECT unset too. They also add ~70% of the upstream MMQ instances' compile time per CUDA arch (175 s
# of CPU for the nine at sm_86 alone). Off, the build's device code is byte for byte the one without this feature. CUDA
# only (not HIP, not gfx906); switched off at configure time when the llama.cpp tree's mmq.cuh is not one the copy
# was verified against.
option(STRATA_MMQ_TAB "Build the pointer-table prompt MMQ for STRATA_MMQ_DIRECT=1 (CUDA; ~37 MiB VRAM per GPU)" OFF)
if(STRATA_PREFILL_MMQ AND NOT STRATA_ENABLE_HIP)
message(FATAL_ERROR "STRATA_PREFILL_MMQ requires STRATA_ENABLE_HIP=ON")
endif()
@@ -99,6 +111,9 @@ endif()
option(STRATA_BUILD_TESTS "Build the test suite" ${_strata_tests_default})
option(STRATA_BUILD_CONVERSATION_TESTS "Build standalone conversation cache tests" OFF)
option(STRATA_WERROR "Treat compiler warnings as errors" OFF)
# #2027: defined here, before the GPU section reads it to register the native-expert tests (it was defined at the
# native-experts section far below, so a first configure registered four tests fewer than the second)
option(STRATA_NATIVE_EXPERTS "Native (IQ) expert support through ggml-cpu" ON)
if(STRATA_BUILD_CONVERSATION_TESTS)
enable_testing()
@@ -114,6 +129,9 @@ if(STRATA_BUILD_CONVERSATION_TESTS)
add_executable(conversation_file_test src/core/conversation_file_test.cpp src/core/conversation_file.cpp)
target_include_directories(conversation_file_test PRIVATE include)
add_test(NAME conversation_file_test COMMAND conversation_file_test)
add_executable(session_save_reclaim_test src/core/session_save_reclaim_test.cpp src/core/conversation_file.cpp)
target_include_directories(session_save_reclaim_test PRIVATE include)
add_test(NAME session_save_reclaim_test COMMAND session_save_reclaim_test)
endif()
if(STRATA_HIP_GFX906)
@@ -236,6 +254,9 @@ target_link_libraries(strata-dequant PRIVATE strata_artifact)
# this file is now nothing but the CLI entry point, and its inherited guard spells that as a "selftest"
target_compile_definitions(strata-dequant PRIVATE STRATA_DEQUANT_SELFTEST)
if(STRATA_BUILD_TESTS)
add_executable(logit_bias_test src/core/logit_bias_test.cpp)
target_include_directories(logit_bias_test PRIVATE include)
add_test(NAME logit_bias_test COMMAND logit_bias_test)
# the reader refuses a duplicate tensor name at open, naming it (a synthetic GGUF: no model, no GPU)
add_executable(gguf_reader_test src/artifact/gguf_reader_test.cpp)
target_link_libraries(gguf_reader_test PRIVATE strata_artifact)
@@ -244,12 +265,39 @@ if(STRATA_BUILD_TESTS)
add_executable(gguf_split_test tests/core/gguf_split_test.cpp)
target_link_libraries(gguf_split_test PRIVATE strata_artifact)
add_test(NAME gguf_split_test COMMAND gguf_split_test)
# the model families (qwen4exp, qwen35moe): the guards, the geometry from metadata, the layout tables (synthetic)
add_executable(model_family_test tests/core/model_family_test.cpp)
target_link_libraries(model_family_test PRIVATE strata_artifact)
add_test(NAME model_family_test COMMAND model_family_test)
# how --batch cuts a prompt read into pieces (a layer split with no slot decoding must still reach a BYIELD)
add_executable(batch_read_test tests/program/batch_read_test.cpp)
target_include_directories(batch_read_test PRIVATE include)
add_test(NAME batch_read_test COMMAND batch_read_test)
# the model's geometry from its metadata, and the check against the kernels' compiled shape (synthetic)
add_executable(gguf_geometry_test tests/core/gguf_geometry_test.cpp)
target_link_libraries(gguf_geometry_test PRIVATE strata_artifact)
add_test(NAME gguf_geometry_test COMMAND gguf_geometry_test)
# the hipBLASLt tuning header's architecture gate: RDNA4 siblings share solution IDs, RDNA3 siblings share
# theirs, cross-family pairs and version mismatches stay rejected (synthetic tables: no model, no GPU)
add_executable(tuning_header_arch_family_test tests/prefill/tuning_header_arch_family_test.cpp)
target_include_directories(tuning_header_arch_family_test PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/prefill")
add_test(NAME tuning_header_arch_family_test COMMAND tuning_header_arch_family_test)
# the auto layer split's minimum stage size (#1616): header-only rule, no GPU
add_executable(split_rules_test tests/program/split_rules_test.cpp)
target_include_directories(split_rules_test PRIVATE include)
add_test(NAME split_rules_test COMMAND split_rules_test)
# the default CPU prefill share is not armed when every expert is resident (#1595): header-only rule, no GPU
add_executable(share_rules_test tests/prefill/share_rules_test.cpp)
target_include_directories(share_rules_test PRIVATE include)
add_test(NAME share_rules_test COMMAND share_rules_test)
# the Windows HIP auto prefill chunk cap (#1630) and the commit-limit verdict (#1607): header-only, no GPU
add_executable(host_limits_test tests/platform/host_limits_test.cpp)
target_include_directories(host_limits_test PRIVATE include)
add_test(NAME host_limits_test COMMAND host_limits_test)
endif()
# ---- strata_plan ----------------------------------------------------------
@@ -329,6 +377,7 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
src/kernels/cuda/native_gdn.cu
src/kernels/cuda/native_gr_postops.cu
src/kernels/cuda/native_router.cu
src/kernels/cuda/route_prior.cu
src/kernels/cuda/native_gdn_preprocess.cu
src/kernels/cuda/native_qsa.cu
src/kernels/cuda/native_rope.cu
@@ -353,6 +402,21 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
src/ngram/ple_reader.cpp
src/platform/direct_file.cpp)
target_link_libraries(strata_kernels PUBLIC strata_core strata_artifact)
# Exact gfx1100 prompt scorer (PR1825 method port): optional standalone test,
# also available where the published source omits tests/.
option(STRATA_PARITY_GFX1100_QSA_SCORES "Build the exact gfx1100 QSA score/ID check" OFF)
if(STRATA_ENABLE_HIP AND (STRATA_BUILD_TESTS OR STRATA_PARITY_GFX1100_QSA_SCORES))
set_source_files_properties(src/kernels/cuda/qsa_scores_gfx1100_test.cu
src/kernels/qsa_scores_gfx1100_parity.cpp PROPERTIES LANGUAGE HIP)
add_executable(qsa_scores_gfx1100_parity src/kernels/qsa_scores_gfx1100_parity.cpp
src/kernels/cuda/qsa_scores_gfx1100_test.cu)
target_include_directories(qsa_scores_gfx1100_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(qsa_scores_gfx1100_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
enable_testing()
add_test(NAME qsa_scores_gfx1100_parity COMMAND qsa_scores_gfx1100_parity --full)
set_tests_properties(qsa_scores_gfx1100_parity PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 180
ENVIRONMENT "STRATA_SCORES_THREAD=1;STRATA_SCORES_THREAD_TRACE=1")
endif()
# perf-review D-1: the tensor-core prompt attention vs the FP32 kernel and FP64 (GPU, synthetic, no model); with
# the tests, or alone with -DSTRATA_PARITY_PROMPT_ATTN=ON. CUDA only: HIP compiles the tensor-core kernel out.
if((STRATA_BUILD_TESTS OR STRATA_PARITY_PROMPT_ATTN) AND STRATA_ENABLE_CUDA)
@@ -368,6 +432,40 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_link_libraries(qsa_topk_active_parity PRIVATE strata_kernels CUDA::cudart)
add_test(NAME qsa_topk_active_parity COMMAND qsa_topk_active_parity)
set_tests_properties(qsa_topk_active_parity PROPERTIES SKIP_RETURN_CODE 77)
# STRATA_QSA_SLOTS: a batch window's scores, top-k and attention as one launch over rows of different slots
# against one call per row, bitwise (synthetic, no model)
add_executable(qsa_slots_parity src/kernels/qsa_slots_parity.cpp)
target_include_directories(qsa_slots_parity PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
target_link_libraries(qsa_slots_parity PRIVATE strata_kernels CUDA::cudart)
add_test(NAME qsa_slots_parity COMMAND qsa_slots_parity)
add_test(NAME qsa_slots_parity_lanecell COMMAND qsa_slots_parity)
set_tests_properties(qsa_slots_parity qsa_slots_parity_lanecell PROPERTIES SKIP_RETURN_CODE 77)
set_tests_properties(qsa_slots_parity_lanecell PROPERTIES ENVIRONMENT "STRATA_ATTN_LANECELL=1")
# fork: the Daily's decode attention (STRATA_ATTN_DAILY=1: PR #540's chunk kernel on every card and the bounded
# merge) against upstream's kernels, bitwise; the production entries checked with the variable off and on
add_executable(qsa_merge_daily_parity src/kernels/qsa_merge_daily_parity.cpp)
target_include_directories(qsa_merge_daily_parity PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
target_link_libraries(qsa_merge_daily_parity PRIVATE strata_kernels CUDA::cudart)
add_test(NAME qsa_merge_daily_parity_default COMMAND qsa_merge_daily_parity)
add_test(NAME qsa_merge_daily_parity_daily COMMAND qsa_merge_daily_parity)
set_tests_properties(qsa_merge_daily_parity_default PROPERTIES ENVIRONMENT "STRATA_ATTN_DAILY=0"
SKIP_RETURN_CODE 77)
set_tests_properties(qsa_merge_daily_parity_daily PROPERTIES ENVIRONMENT "STRATA_ATTN_DAILY=1"
SKIP_RETURN_CODE 77)
# the prompt path's block scores on the thread-per-head kernel (Turing) against the warp kernel, bitwise
add_executable(qsa_scores_parity src/kernels/qsa_scores_parity.cpp)
target_include_directories(qsa_scores_parity PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
target_link_libraries(qsa_scores_parity PRIVATE strata_kernels CUDA::cudart)
add_test(NAME qsa_scores_parity COMMAND qsa_scores_parity)
set_tests_properties(qsa_scores_parity PROPERTIES SKIP_RETURN_CODE 77 ENVIRONMENT "STRATA_SCORES_THREAD=1")
endif()
# QSAROWS (docs/QSAROWS.md): what the T rows of a verification window cost in a QSA layer's decode kernels at a long
# context (block scores, top-k, attention over each row's selection, indexer append), row by row; GPU, synthetic, no
# model. Not in the default build: `cmake --build <dir> --target qsa_rows_bench`.
if(STRATA_ENABLE_CUDA)
add_executable(qsa_rows_bench EXCLUDE_FROM_ALL src/kernels/qsa_rows_bench.cpp)
target_include_directories(qsa_rows_bench PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
target_link_libraries(qsa_rows_bench PRIVATE strata_kernels CUDA::cudart)
endif()
# the QSA selection (block scores on the warp kernel and the tensor-core one, top-k): a GPU bench with a
# scorer-vs-scorer comparison and an FP64 accuracy gate (synthetic, no model); the ctest runs a 32K context under a
@@ -377,6 +475,9 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
set_source_files_properties(src/kernels/qsa_select_bench.cpp PROPERTIES LANGUAGE HIP)
target_link_libraries(qsa_select_bench PRIVATE strata_kernels strata_hip_runtime)
add_test(NAME qsa_select_bench COMMAND qsa_select_bench 32768 256 3 262144)
# the FP32 tiled scorer (STRATA_SELECT_SIMT=1) on HIP: FP64 gate and selections against the warp kernel at 131K
add_test(NAME qsa_select_bench_fp32_tiled COMMAND qsa_select_bench 131072 256 3 262144)
set_tests_properties(qsa_select_bench_fp32_tiled PROPERTIES ENVIRONMENT "STRATA_SELECT_SIMT=1")
endif()
# the same on CUDA: the tensor-core scorer (sm_80+) or the FP32 tiled one (below sm_80, and forced on any card by
# STRATA_QSA_WARP=1 in the second test) against the warp kernel and FP64, at 32K and 131K
@@ -388,6 +489,11 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
add_test(NAME qsa_select_bench_fp32_tiled COMMAND qsa_select_bench 131072 256 3 262144)
set_tests_properties(qsa_select_bench_fp32_tiled PROPERTIES ENVIRONMENT "STRATA_QSA_WARP=1;STRATA_SELECT_SIMT=1")
endif()
if(STRATA_BUILD_TESTS AND STRATA_ENABLE_CUDA) # the prompt attention on a recorded selection (STRATA_QSA_DUMP)
add_executable(pa_bench tests/cuda/pa_bench.cpp)
target_include_directories(pa_bench PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})
target_link_libraries(pa_bench PRIVATE strata_kernels CUDA::cudart)
endif()
# plan v0.3 P6: llama.cpp's block layouts and codebook grids for the i-quant formats (MIT, third_party/ggml)
target_include_directories(strata_kernels PRIVATE third_party/ggml)
# Match the pinned llama.cpp CUDA arithmetic contract for this adapter only.
@@ -450,6 +556,13 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
src/core/arch_defaults.cpp src/core/vmm.cpp src/core/conversation_file.cpp)
target_include_directories(strata_engine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(strata_engine PUBLIC strata_core strata_kernels strata_kernels_cpu ${_strata_gpu_runtime_target})
if(STRATA_BUILD_TESTS AND STRATA_ENABLE_CUDA AND NOT STRATA_HIP_GFX906)
add_executable(host_graph_launch_test tests/core/host_graph_launch_test.cu)
target_include_directories(host_graph_launch_test PRIVATE include)
target_link_libraries(host_graph_launch_test PRIVATE CUDA::cudart Threads::Threads)
add_test(NAME host_graph_launch_test COMMAND host_graph_launch_test)
set_tests_properties(host_graph_launch_test PROPERTIES TIMEOUT 30)
endif()
if(STRATA_BUILD_TESTS AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/core/exchange_storage_test.cpp")
add_executable(exchange_storage_test tests/core/exchange_storage_test.cpp)
target_include_directories(exchange_storage_test PRIVATE include)
@@ -458,6 +571,15 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
set_tests_properties(exchange_storage_test PROPERTIES TIMEOUT 60)
endif()
# available_host_bytes(): MemAvailable, cgroup limits and the operator's --memory-limit-mib cap on fixture directories
# - no GPU, no CUDA
if(STRATA_BUILD_TESTS AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/core/memory_guard_test.cpp")
add_executable(memory_guard_test tests/core/memory_guard_test.cpp src/core/conversation_memory.cpp)
target_include_directories(memory_guard_test PRIVATE include)
add_test(NAME memory_guard_test COMMAND memory_guard_test)
set_tests_properties(memory_guard_test PROPERTIES TIMEOUT 60)
endif()
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/core/file_expert_source_test.cpp")
enable_testing()
add_executable(file_expert_source_test tests/core/file_expert_source_test.cpp)
@@ -468,6 +590,21 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_link_libraries(vmm_test PRIVATE strata_engine)
add_test(NAME vmm_test COMMAND vmm_test)
set_tests_properties(vmm_test PROPERTIES TIMEOUT 60)
# The resident RAM mode with a layer split: the copy keeps each stage's lend region, and the experts the
# prompt path borrows are served from RAM (the file source reads none of them). The device calls are
# wrapped - conversation_transfer_test's pattern - and `pin = false` keeps the copy pageable, so this
# runs on a CPU-only PC.
if(NOT STRATA_ENABLE_HIP AND UNIX AND NOT APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
add_executable(split_lend_complement_test tests/core/split_lend_complement_test.cpp)
target_link_libraries(split_lend_complement_test PRIVATE strata_engine)
target_link_options(split_lend_complement_test PRIVATE
-Wl,--wrap=cudaMalloc -Wl,--wrap=cudaFree -Wl,--wrap=cudaMemset -Wl,--wrap=cudaMemcpy
-Wl,--wrap=cudaMemcpyAsync -Wl,--wrap=cudaStreamSynchronize -Wl,--wrap=cudaDeviceSynchronize
-Wl,--wrap=cudaGetLastError -Wl,--wrap=cudaGetDevice -Wl,--wrap=cudaSetDevice
-Wl,--wrap=cudaMemGetInfo -Wl,--wrap=cudaHostAlloc -Wl,--wrap=cudaFreeHost)
add_test(NAME split_lend_complement_test COMMAND split_lend_complement_test)
set_tests_properties(split_lend_complement_test PROPERTIES ENVIRONMENT "CUDA_VISIBLE_DEVICES=-1" TIMEOUT 120)
endif()
endif()
# #477: the learned expert profile (--expert-profile-save): its order and make_profile.py's file format (CPU only)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/core/expert_profile_save_test.cpp")
@@ -506,6 +643,12 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_link_libraries(expert_cache_segmented_test PRIVATE strata_engine)
add_test(NAME expert_cache_segmented_test COMMAND expert_cache_segmented_test)
set_tests_properties(expert_cache_segmented_test PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 60)
# STRATA_MMQ_DIRECT: slot_guard / slot_room / slot_tail on the uniform and the sized cache, and the default
# (no guard) sized layout unchanged
add_executable(expert_cache_slot_guard_test tests/core/expert_cache_slot_guard_test.cpp)
target_link_libraries(expert_cache_slot_guard_test PRIVATE strata_engine)
add_test(NAME expert_cache_slot_guard_test COMMAND expert_cache_slot_guard_test)
set_tests_properties(expert_cache_slot_guard_test PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 60)
endif()
if(STRATA_BUILD_CONVERSATION_TESTS)
add_executable(conversation_snapshot_test src/core/conversation_snapshot_test.cpp)
@@ -520,7 +663,9 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
add_executable(conversation_transfer_test src/core/conversation_validation_test.cpp)
target_compile_definitions(conversation_transfer_test PRIVATE CONVERSATION_TEST_TRANSFERS)
target_link_options(conversation_transfer_test PRIVATE
-Wl,--wrap=cudaMemcpy -Wl,--wrap=cudaDeviceSynchronize -Wl,--wrap=cudaGetLastError)
-Wl,--wrap=cudaMemcpy -Wl,--wrap=cudaMemcpyAsync -Wl,--wrap=cudaStreamSynchronize
-Wl,--wrap=cudaGetDevice -Wl,--wrap=cudaStreamCreateWithFlags
-Wl,--wrap=cudaDeviceSynchronize -Wl,--wrap=cudaGetLastError)
target_link_libraries(conversation_transfer_test PRIVATE strata_engine)
add_test(NAME conversation_transfer_test COMMAND conversation_transfer_test)
set_tests_properties(conversation_transfer_test PROPERTIES ENVIRONMENT "CUDA_VISIBLE_DEVICES=-1" TIMEOUT 120)
@@ -545,11 +690,40 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
add_executable(tune_hipblaslt tools/hip/tune_hipblaslt.cpp)
target_link_libraries(tune_hipblaslt PRIVATE hip::host roc::hipblas roc::hipblaslt)
endif()
if(STRATA_ENABLE_HIP AND STRATA_ROCBLAS_AVAILABLE)
# the prompt path's rocBLAS solution table (STRATA_ROCBLAS_TUNING; tools/hip/tune_rocblas makes one)
target_compile_definitions(strata_prefill PRIVATE STRATA_ROCBLAS_AVAILABLE=1)
target_link_libraries(strata_prefill PRIVATE roc::rocblas)
add_executable(tune_rocblas tools/hip/tune_rocblas.cpp)
target_link_libraries(tune_rocblas PRIVATE hip::host roc::rocblas)
endif()
add_executable(strata src/program/generate.cpp)
target_include_directories(strata PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(strata PRIVATE strata_engine strata_prefill strata_spec ${_strata_gpu_runtime_target})
# NEW-MODELS-PLAN.md T1: Qwen3.6-35B-A3B's reference path (one GPU, the model resident, plain kernels), checked
# against llama.cpp by tools/qwen35/; the engine itself does not run the family yet
add_executable(strata-q36ref src/qwen35/q36ref.cu)
target_include_directories(strata-q36ref PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ${_strata_gpu_include_directories})
target_link_libraries(strata-q36ref PRIVATE strata_kernels strata_warnings ${_strata_gpu_runtime_target})
# the engine path for the same family (serve protocol, prompt chunks, decode graph): src/qwen35/q36_engine.cu, a
# library that `strata` switches to for a qwen35moe model (the family switch at the top of its main) and that
# strata-q36 wraps on its own
add_library(strata_qwen35 STATIC src/qwen35/q36_engine.cu)
target_include_directories(strata_qwen35 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(strata_qwen35 PRIVATE strata_prefill strata_kernels strata_warnings ${_strata_gpu_runtime_target})
if(STRATA_NATIVE_EXPERTS)
# the hybrid mode (experts that do not all fit in VRAM): the CPU expert pool on ggml-cpu's arithmetic
target_link_libraries(strata_qwen35 PRIVATE strata_kernels_cpu)
target_compile_definitions(strata_qwen35 PRIVATE STRATA_Q36_CPU_POOL=1)
endif()
add_executable(strata-q36 src/qwen35/q36_main.cpp)
target_link_libraries(strata-q36 PRIVATE strata_qwen35 ${_strata_gpu_runtime_target})
target_link_libraries(strata PRIVATE strata_qwen35)
target_compile_definitions(strata PRIVATE STRATA_HAVE_QWEN35=1)
if(STRATA_ENABLE_HIP)
enable_testing()
set(_strata_hip_tests)
@@ -607,6 +781,12 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_link_libraries(hip_gdn_rec_head PRIVATE strata_prefill strata_hip_runtime)
add_test(NAME hip_gdn_rec_head COMMAND hip_gdn_rec_head)
list(APPEND _strata_hip_tests hip_gdn_rec_head)
add_executable(hip_gdn_chunked tests/hip/gdn_chunked.cpp)
target_link_libraries(hip_gdn_chunked PRIVATE strata_prefill strata_hip_runtime)
add_test(NAME hip_gdn_chunked COMMAND hip_gdn_chunked)
add_test(NAME hip_gdn_chunked_off COMMAND hip_gdn_chunked --off)
add_test(NAME hip_gdn_chunked_default COMMAND hip_gdn_chunked --default)
list(APPEND _strata_hip_tests hip_gdn_chunked hip_gdn_chunked_off hip_gdn_chunked_default)
# #313: the RDNA3 / RDNA3.5 WMMA dense GEMMs (opt-in STRATA_WMMA_GEMM=1) against a reference
add_executable(hip_prefill_wmma_gemm_parity tests/hip/prefill_wmma_gemm_parity.cpp)
target_include_directories(hip_prefill_wmma_gemm_parity PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/prefill")
@@ -639,6 +819,15 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
set_tests_properties(hip_prefill_hipblaslt_gemm PROPERTIES TIMEOUT 120 SKIP_RETURN_CODE 77)
list(APPEND _strata_hip_tests hip_prefill_hipblaslt_gemm)
endif()
if(STRATA_ROCBLAS_AVAILABLE)
# the rocBLAS solution table of the FP16-out prompt GEMMs (gfx103x): opt-in, skips without STRATA_ROCBLAS_TUNING
add_executable(hip_prefill_rocblas_gemm tests/hip/prefill_rocblas_gemm.cpp)
target_include_directories(hip_prefill_rocblas_gemm PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src/prefill")
target_link_libraries(hip_prefill_rocblas_gemm PRIVATE strata_prefill strata_hip_runtime roc::rocblas roc::hipblas)
add_test(NAME hip_prefill_rocblas_gemm COMMAND hip_prefill_rocblas_gemm)
set_tests_properties(hip_prefill_rocblas_gemm PROPERTIES TIMEOUT 120 SKIP_RETURN_CODE 77)
list(APPEND _strata_hip_tests hip_prefill_rocblas_gemm)
endif()
if(_strata_hip_tests)
set_tests_properties(${_strata_hip_tests} PROPERTIES TIMEOUT 60)
endif()
@@ -648,6 +837,9 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
if(TARGET hip_prefill_hipblaslt_gemm)
set_tests_properties(hip_prefill_hipblaslt_gemm PROPERTIES TIMEOUT 120 SKIP_RETURN_CODE 77)
endif()
if(TARGET hip_prefill_rocblas_gemm)
set_tests_properties(hip_prefill_rocblas_gemm PROPERTIES TIMEOUT 120 SKIP_RETURN_CODE 77)
endif()
endif()
add_executable(dequant_s2_parity src/kernels/dequant_s2_parity.cpp)
@@ -727,6 +919,12 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_include_directories(mmvq_il_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(mmvq_il_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME mmvq_il_parity COMMAND mmvq_il_parity)
# the wide dequant kernels (a thread per 8 values; sm_61's default), bitwise vs the per-group ones (GPU, synthetic,
# no model; --bench adds old/new timings)
add_executable(dequant_wide_parity src/kernels/dequant_wide_parity.cpp)
target_include_directories(dequant_wide_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(dequant_wide_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME dequant_wide_parity COMMAND dequant_wide_parity)
endif()
# programmatic dependent launch (pdl.hpp) in a captured verify-shaped chain: bitwise vs ordinary launches over
# replays with poisoned buffers, and only kernel-to-kernel programmatic edges (GPU, synthetic, no model; the edges
@@ -766,6 +964,18 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
add_executable(gemm_bf16_parity src/prefill/gemm_bf16_parity.cu)
target_link_libraries(gemm_bf16_parity PRIVATE strata_prefill )
add_test(NAME gemm_bf16_parity COMMAND gemm_bf16_parity)
# Pascal, opt-in STRATA_DENSE_F32=1: the dense projections' FP16 GEMMs as cublasSgemm on FP32 copies, bitwise vs
# the cuBLAS FP16 call over a sweep of chunk sizes (GPU, synthetic, no model; --full sweeps every size, --bench
# adds timings). Not a ctest: whether the two agree is a property of the cuBLAS build, which this checks.
add_executable(gemm_f32_parity src/prefill/gemm_f32_parity.cu)
target_link_libraries(gemm_f32_parity PRIVATE strata_prefill )
# the hyper-connection read's fused up projection + mix (gr_upmix, STRATA_HC_UPMIX) against cuBLAS + gr_mix_r,
# bitwise where cuBLAS sums K in the same order, else within FP32 rounding and as close to FP64 (GPU, synthetic,
# no model; --bench adds timings)
add_executable(gr_upmix_parity src/prefill/gr_upmix_parity.cu)
target_link_libraries(gr_upmix_parity PRIVATE strata_prefill )
add_test(NAME gr_upmix_parity COMMAND gr_upmix_parity)
set_tests_properties(gr_upmix_parity PROPERTIES SKIP_RETURN_CODE 77)
endif()
# native_expert_grouped's group stride and fused SwiGLU + q8_1, bitwise vs the launches before them (GPU, synthetic,
# no model; --bench adds v1/new timings of a window's 48 calls in a graph)
@@ -773,6 +983,21 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_include_directories(native_grouped_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(native_grouped_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME native_grouped_parity COMMAND native_grouped_parity)
add_executable(mmvf_rows_parity src/kernels/mmvf_rows_parity.cpp)
target_include_directories(mmvf_rows_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(mmvf_rows_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME mmvf_rows_parity COMMAND mmvf_rows_parity)
set_tests_properties(mmvf_rows_parity PROPERTIES ENVIRONMENT "STRATA_MMVF_ROWS=1" TIMEOUT 120)
if(STRATA_HIP_GFX906)
add_test(NAME native_grouped_fused_parity COMMAND native_grouped_parity)
set_tests_properties(native_grouped_fused_parity PROPERTIES
ENVIRONMENT "STRATA_HIP_SWIGLU_FUSED=1;STRATA_EXP_MODE=7" TIMEOUT 120)
add_executable(gfx906_gdn_rec_head tests/hip/gdn_rec_head.cpp)
target_include_directories(gfx906_gdn_rec_head PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(gfx906_gdn_rec_head PRIVATE strata_prefill ${_strata_gpu_runtime_target})
add_test(NAME gfx906_gdn_rec_head COMMAND gfx906_gdn_rec_head)
set_tests_properties(gfx906_gdn_rec_head PROPERTIES TIMEOUT 120)
endif()
add_executable(shared_expert_parity src/kernels/shared_expert_parity.cpp)
target_include_directories(shared_expert_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(shared_expert_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
@@ -788,6 +1013,15 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
add_executable(fused_gr_bench src/kernels/fused_gr_bench.cpp)
target_include_directories(fused_gr_bench PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(fused_gr_bench PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_executable(router_chain_bench src/kernels/router_chain_bench.cpp)
target_include_directories(router_chain_bench PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(router_chain_bench PRIVATE strata_kernels ${_strata_gpu_runtime_target})
# B6: the dense projections' time per verify row at the model's shapes, default vs STRATA_B6_MMVQ_ROWS, bitwise
if(STRATA_ENABLE_CUDA)
add_executable(b6_mmvq_bench src/kernels/b6_mmvq_bench.cpp)
target_include_directories(b6_mmvq_bench PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(b6_mmvq_bench PRIVATE strata_kernels ${_strata_gpu_runtime_target})
endif()
add_executable(gr_parity src/kernels/gr_parity.cpp)
target_include_directories(gr_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(gr_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
@@ -844,6 +1078,14 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_link_libraries(route_window_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME route_window_parity COMMAND route_window_parity)
# STRATA_ROUTE_RESIDENT's swap: the warp-per-token kernel against a scalar reference of the same semantics,
# bitwise on the ids, the weights and the four counters (GPU, synthetic, no model)
add_executable(route_resident_parity src/kernels/route_resident_parity.cu)
target_include_directories(route_resident_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(route_resident_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME route_resident_parity COMMAND route_resident_parity)
set_tests_properties(route_resident_parity PROPERTIES TIMEOUT 120)
add_executable(router_top10_parity src/kernels/router_top10_parity.cpp)
target_include_directories(router_top10_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(router_top10_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
@@ -868,6 +1110,13 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_include_directories(gr_multi_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(gr_multi_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME gr_multi_parity COMMAND gr_multi_parity)
# STRATA_HC_PERSIST=1: the persistent hyper-connection read against the default multi read (bounded, two runs bitwise),
# and with the variable unset it never runs (a skip where the card cannot hold its 80 blocks, and on CUDA)
add_executable(hc_persist_parity src/kernels/hc_persist_parity.cpp)
target_include_directories(hc_persist_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(hc_persist_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME hc_persist_parity COMMAND hc_persist_parity)
add_test(NAME hc_persist_default_off COMMAND hc_persist_parity --off)
if(STRATA_HIP_GFX906)
# the S6 router (STRATA_HIP_ROUTER_FAST=1 on gfx906) against the portable kernel, bitwise, on wave64
add_executable(hip_router_fast tests/hip/router_fast.cpp)
@@ -906,6 +1155,9 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_include_directories(qsa_topk_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(qsa_topk_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME qsa_topk_parity COMMAND qsa_topk_parity --selftest)
# the register kernel from the smallest prompt batch (the line gfx1151 moves to 4096 blocks): same ids at every case
add_test(NAME qsa_topk_parity_reg_always COMMAND qsa_topk_parity --selftest)
set_tests_properties(qsa_topk_parity_reg_always PROPERTIES ENVIRONMENT "STRATA_TOPK_REG_MIN_BLOCKS=0")
# ---- P2.S4: the PLE n-gram hash, the IQ4_NL table read, and the PLE block ----
# `ngram.cpp` is host-only but lives in `strata_kernels` because `ple.cu` shares its geometry constants, and
@@ -936,6 +1188,13 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_link_libraries(kv_stream_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME kv_stream_parity COMMAND kv_stream_parity)
# #2403: the verify window's KV calls on a streamed layer and on a ring (steps appends with the host copy, batched
# resolve + attention, plain launches and graph replays), q4_0 / int8 / K8V4 (GPU, synthetic, no model).
add_executable(kv_window_parity src/kernels/kv_window_parity.cpp)
target_include_directories(kv_window_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(kv_window_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME kv_window_parity COMMAND kv_window_parity)
# PR #120: the hybrid K8V4 KV (INT8 K + rotated Q4_0 V) vs host references (GPU, synthetic, no model).
add_executable(kv_hybrid_parity src/kernels/kv_hybrid_parity.cpp)
target_include_directories(kv_hybrid_parity PRIVATE ${_strata_gpu_include_directories})
@@ -952,6 +1211,11 @@ if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
target_include_directories(verify_batch_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(verify_batch_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME verify_batch_parity COMMAND verify_batch_parity)
# #2234: the batch window's one-launch-for-all-rows kernels vs the per-row launches, bitwise (GPU, synthetic)
add_executable(batch_rows_parity src/kernels/batch_rows_parity.cpp)
target_include_directories(batch_rows_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(batch_rows_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
add_test(NAME batch_rows_parity COMMAND batch_rows_parity)
add_executable(cvec_parity src/kernels/cvec_parity.cpp)
target_include_directories(cvec_parity PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(cvec_parity PRIVATE strata_kernels ${_strata_gpu_runtime_target})
@@ -1060,10 +1324,18 @@ if(STRATA_BUILD_TESTS OR STRATA_BUILD_CONVERSATION_TESTS)
add_executable(message_boundary_test src/program/message_boundary_test.cpp)
target_include_directories(message_boundary_test PRIVATE include)
add_test(NAME message_boundary_test COMMAND message_boundary_test)
# a layer split's ring override and the lend slots sized with it: the RAM copy must keep every borrowed slot (CPU)
add_executable(split_ring_test src/program/split_ring_test.cpp)
target_include_directories(split_ring_test PRIVATE include)
add_test(NAME split_ring_test COMMAND split_ring_test)
# the serve loop's conversation-cache retention policy (header-only, no library to link)
add_executable(conv_cache_test src/program/conv_cache_test.cpp)
target_include_directories(conv_cache_test PRIVATE include)
add_test(NAME conv_cache_test COMMAND conv_cache_test)
# which path computes the draft layer's prompt K/V, and STRATA_SPLIT_MTP_BATCH's parsing (header-only, CPU)
add_executable(draft_kv_plan_test src/program/draft_kv_plan_test.cpp)
target_include_directories(draft_kv_plan_test PRIVATE include)
add_test(NAME draft_kv_plan_test COMMAND draft_kv_plan_test)
# coupled draft sampling's counter and penalty-ring arithmetic (header-only, CPU)
add_executable(coupled_draft_test src/core/coupled_draft_test.cpp)
target_include_directories(coupled_draft_test PRIVATE include)
@@ -1076,6 +1348,14 @@ if(STRATA_BUILD_TESTS OR STRATA_BUILD_CONVERSATION_TESTS)
add_executable(bf16_bits_test src/kernels/bf16_bits_test.cpp)
target_include_directories(bf16_bits_test PRIVATE include)
add_test(NAME bf16_bits_test COMMAND bf16_bits_test)
# the batch window's row layout (a slot's group of proposed rows, the layer split's hand-off capacity; header-only, CPU)
add_executable(batch_rows_test tests/core/batch_rows_test.cpp)
target_include_directories(batch_rows_test PRIVATE include)
add_test(NAME batch_rows_test COMMAND batch_rows_test)
# how many pipelined slot groups --batch runs with: the 0.1.41 default, and --batch-mtp keeping it serial (header-only, CPU)
add_executable(batch_groups_test src/program/batch_groups_test.cpp)
target_include_directories(batch_groups_test PRIVATE include)
add_test(NAME batch_groups_test COMMAND batch_groups_test)
endif()
add_library(strata_kernels_cpu STATIC src/kernels/cpu/expert.cpp src/kernels/cpu/pool.cpp
@@ -1128,7 +1408,6 @@ target_link_libraries(strata_kernels_cpu PUBLIC Threads::Threads)
# The CPU computes a native expert with ggml-cpu's own dot products (`ggml_get_type_traits_cpu`), so an IQ
# weight means exactly what it means in llama.cpp. ggml is built static from a llama.cpp checkout: a local one
# with -DSTRATA_GGML_DIR=..., otherwise the pinned upstream commit (third_party/ggml/VERSION.txt).
option(STRATA_NATIVE_EXPERTS "Native (IQ) expert support through ggml-cpu" ON)
set(STRATA_GGML_DIR "" CACHE PATH "llama.cpp checkout to take ggml from (empty: fetch the pinned commit)")
if(STRATA_PREFILL_MMQ AND NOT STRATA_NATIVE_EXPERTS)
message(FATAL_ERROR "STRATA_PREFILL_MMQ requires STRATA_NATIVE_EXPERTS=ON for GGML sources")
@@ -1187,20 +1466,38 @@ if(STRATA_NATIVE_EXPERTS)
# one-pass static linking has no cycle to resolve)
target_sources(strata_kernels_cpu PRIVATE src/kernels/cpu/native_expert.cpp src/kernels/cpu/iq_avx512.cpp
src/kernels/cpu/iq_avx2.cpp src/kernels/cpu/kq_avx2.cpp
src/kernels/cpu/kq_avx1.cpp)
src/kernels/cpu/kq_avx1.cpp src/kernels/cpu/q2_avx1.cpp src/kernels/cpu/iq_avx1.cpp
src/kernels/cpu/nvfp4_avx512.cpp src/kernels/cpu/nvfp4_avx2.cpp)
target_include_directories(strata_kernels_cpu PRIVATE third_party/ggml)
if(MSVC)
set_source_files_properties(src/kernels/cpu/iq_avx512.cpp PROPERTIES COMPILE_OPTIONS "/arch:AVX512")
set_source_files_properties(src/kernels/cpu/iq_avx512.cpp src/kernels/cpu/nvfp4_avx512.cpp
PROPERTIES COMPILE_OPTIONS "/arch:AVX512")
set_source_files_properties(src/kernels/cpu/iq_avx2.cpp PROPERTIES COMPILE_OPTIONS "/arch:AVX2")
set_source_files_properties(src/kernels/cpu/kq_avx2.cpp PROPERTIES COMPILE_OPTIONS "/arch:AVX2")
set_source_files_properties(src/kernels/cpu/nvfp4_avx2.cpp PROPERTIES COMPILE_OPTIONS "/arch:AVX2")
# the router lookahead's AVX1 dot (older CPUs; called behind cpu_avx1_ok): no FMA, no 256-bit integer ops
set_source_files_properties(src/kernels/cpu/kq_avx1.cpp PROPERTIES COMPILE_OPTIONS "/arch:AVX")
# the older CPUs' Q2_0 rows and activation quantizer (q2_avx1.cpp, issue #1699): 128-bit integer lanes,
# no FMA/F16C, its own #error guard; called only behind cpu_avx1_ok() && !cpu_avx2_ok()
set_source_files_properties(src/kernels/cpu/q2_avx1.cpp PROPERTIES COMPILE_OPTIONS "/arch:AVX")
# the older CPUs' i-quant expert rows (iq_avx1.hpp): 128-bit SSSE3/SSE2 integer, SSE2 float, no FMA/F16C
set_source_files_properties(src/kernels/cpu/iq_avx1.cpp PROPERTIES COMPILE_OPTIONS "/arch:AVX")
else()
set_source_files_properties(src/kernels/cpu/iq_avx512.cpp PROPERTIES COMPILE_OPTIONS
set_source_files_properties(src/kernels/cpu/iq_avx512.cpp src/kernels/cpu/nvfp4_avx512.cpp PROPERTIES COMPILE_OPTIONS
"-mavx512f;-mavx512bw;-mavx512vl;-mavx512dq;-mavx512vnni;-mavx512vbmi;-mf16c;-mfma")
set_source_files_properties(src/kernels/cpu/iq_avx2.cpp PROPERTIES COMPILE_OPTIONS "-mavx2;-mfma;-mf16c")
set_source_files_properties(src/kernels/cpu/kq_avx2.cpp PROPERTIES COMPILE_OPTIONS "-mavx2;-mfma;-mf16c")
set_source_files_properties(src/kernels/cpu/nvfp4_avx2.cpp PROPERTIES COMPILE_OPTIONS "-mavx2;-mfma;-mf16c")
set_source_files_properties(src/kernels/cpu/kq_avx1.cpp PROPERTIES COMPILE_OPTIONS "-mavx")
# the older CPUs' Q2_0 rows and activation quantizer (q2_avx1.cpp, issue #1699): SSE4.2 + AVX with
# AVX2/FMA/F16C explicitly off, so a -march=native build host cannot leak AVX2 code into the file that
# runs on a Sandy Bridge Xeon
set_source_files_properties(src/kernels/cpu/q2_avx1.cpp PROPERTIES COMPILE_OPTIONS
"-msse4.2;-mavx;-mno-avx2;-mno-fma;-mno-f16c")
# the older CPUs' i-quant expert rows (iq_avx1.hpp): SSE4.2 + AVX with AVX2/FMA/F16C explicitly off, so a
# -march=native build host cannot leak AVX2 code into the file that runs on a Sandy Bridge Xeon
set_source_files_properties(src/kernels/cpu/iq_avx1.cpp PROPERTIES COMPILE_OPTIONS
"-msse4.2;-mavx;-mno-avx2;-mno-fma;-mno-f16c")
endif()
set_property(SOURCE src/kernels/cpu/iq_avx2.cpp APPEND PROPERTY COMPILE_DEFINITIONS ${_strata_avxvnni})
if(STRATA_ISA_FLOOR STREQUAL "avx")
@@ -1231,10 +1528,21 @@ if(STRATA_NATIVE_EXPERTS)
# against ggml-cpu's dot, on random blocks; --bench: ms per expert on one thread, the weights streamed from DRAM
add_executable(iq_avx2_parity src/kernels/cpu/iq_avx2_parity.cpp)
target_link_libraries(iq_avx2_parity PRIVATE strata_kernels_cpu)
# MODEL-UPDATE: the pool's expert rows per format on T threads against the RAM bandwidth (a benchmark, no test)
add_executable(kq_cpu_bench src/kernels/cpu/kq_cpu_bench.cpp)
target_link_libraries(kq_cpu_bench PRIVATE strata_kernels_cpu)
if(STRATA_BUILD_TESTS)
add_test(NAME iq_avx2_parity COMMAND iq_avx2_parity)
add_test(NAME iq_avx2_parity_iq3s_mt1 COMMAND ${CMAKE_COMMAND} -E env STRATA_IQ3S_MT1=1 $<TARGET_FILE:iq_avx2_parity>)
endif()
# the older CPUs' AVX1 expert rows (iq_avx1.cpp) against ggml-cpu's dots and against their own one-token
# rows at every width; --bench: ms per expert, the weights streamed from DRAM. Runs on any AVX CPU:
# on an AVX2 machine it checks the older-CPU path as an AVX-only machine would run it.
add_executable(iq_avx1_parity src/kernels/cpu/iq_avx1_parity.cpp)
target_link_libraries(iq_avx1_parity PRIVATE strata_kernels_cpu)
if(STRATA_BUILD_TESTS)
add_test(NAME iq_avx1_parity COMMAND iq_avx1_parity)
endif()
# the AVX-2 Q8_K activation quantizer against ggml's, byte for byte (--bench: its time)
add_executable(q8k_quant_parity src/kernels/cpu/q8k_quant_parity.cpp)
target_link_libraries(q8k_quant_parity PRIVATE strata_kernels_cpu)
@@ -1260,30 +1568,125 @@ if(STRATA_NATIVE_EXPERTS)
# #136: the Q2_0 pack's prompt experts on Strata's own int8 kernels (moe_fused.cu, opt-in STRATA_PF_FUSED=1; CUDA
# only: the HIP branch below keeps MMQ, and an sm_75 device or an sm_75-only build reports them unavailable)
add_library(strata_mmq STATIC src/prefill/moe_mmq.cu src/prefill/moe_fused.cu src/prefill/moe_fused_iq.cu
src/prefill/mmq_nvfp4_w4a8.cu
src/prefill/ggml_cuda_host.cu ${_strata_mmq}/quantize.cu)
# q8_0: the drafter's matrices (E-9); STRATA_ORCA_Q4KS_MMQ adds q5_0 (#296, in _strata_mmq_types), and
# STRATA_MMQ_KQUANTS q4_k q5_k q5_1, the experts of Unsloth's UD-Q4_K_XL (docs/UNSLOTH_Q4.md; the dispatch
# follows eddoursul/Strata 7706c1b); q6_k is HIP only
# STRATA_MMQ_KQUANTS q4_k q5_k q5_1 q6_k, the experts of Unsloth's UD-Q4/Q5/Q6_K_XL (docs/QUANTS.md; the dispatch
# follows eddoursul/Strata 7706c1b). MODEL-UPDATE Phase 1: on CUDA they are a library of their own, strata_kq
# (below), loaded only for a model with these experts: the engine loads every kernel of its own binary at start
# (CUDA_MODULE_LOADING=EAGER), and these four took ~3.8 MB of VRAM (3 expert slots of IQ3_XXS on a P100) from every
# model. gfx906 (HIP: code objects load on first use) keeps them in strata_mmq.
set(_strata_mmq_cuda_types ${_strata_mmq_types})
if(STRATA_MMQ_KQUANTS)
list(APPEND _strata_mmq_cuda_types q4_k q5_k q5_1)
if(STRATA_Q6K_EXPERTS) # UD-Q6_K_XL gate/up (docs/UNSLOTH_Q6.md)
list(APPEND _strata_mmq_cuda_types q6_k)
endif()
set(_strata_kq_types q4_k q5_k q5_1 q6_k)
set(_strata_kq_dso OFF)
if(STRATA_MMQ_KQUANTS AND STRATA_HIP_GFX906)
list(APPEND _strata_mmq_cuda_types ${_strata_kq_types})
elseif(STRATA_MMQ_KQUANTS)
set(_strata_kq_dso ON)
endif()
foreach(_t IN LISTS _strata_mmq_cuda_types)
target_sources(strata_mmq PRIVATE ${_strata_mmq}/template-instances/mmq-instance-${_t}.cu)
endforeach()
# NVFP4: W4A8 (default) in mmq_nvfp4_w4a8.cu with the plain architectures; the opt-in W4A4 needs RTX 50's FP4 MMA,
# which exists only in the arch-specific target, so its one unit alone is built with 12x -> 12xa (the default
# binary is unchanged and runs on sm_121; a card without that image falls back to W4A8 at run time)
set(_strata_w4a4_archs ${CMAKE_CUDA_ARCHITECTURES})
# (two steps: CMake before 3.29 rejects a \2 whose optional group did not match, "120" alone)
list(TRANSFORM _strata_w4a4_archs REPLACE "^(12[0-9])$" "\\1a")
list(TRANSFORM _strata_w4a4_archs REPLACE "^(12[0-9])-(real|virtual)$" "\\1a-\\2")
add_library(strata_mmq_w4a4 STATIC src/prefill/mmq_nvfp4_w4a4.cu)
set_target_properties(strata_mmq_w4a4 PROPERTIES CUDA_ARCHITECTURES "${_strata_w4a4_archs}")
target_include_directories(strata_mmq_w4a4 PRIVATE ${_strata_gg}/include ${_strata_gg}/src ${_strata_mmq})
target_compile_options(strata_mmq_w4a4 PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--extended-lambda -use_fast_math>)
if(MSVC)
target_compile_options(strata_mmq_w4a4 PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/bigobj>)
endif()
target_link_libraries(strata_mmq_w4a4 PUBLIC ggml-base ${_strata_gpu_runtime_target})
target_link_libraries(strata_mmq PRIVATE strata_mmq_w4a4)
# STRATA_MMQ_TAB: the pointer-table copy of MMQ's scheduler mirrors mmq.cuh from mul_mat_q_process_tile through
# mul_mat_q_case (struct mmq_args included). A fingerprint of that text instead of a compile probe: nothing is
# compiled at configure time, and a llama.cpp tree with another scheduler turns the feature off instead of
# failing the build. _strata_mmq_tab_known: the hashes moe_mmq_tab.cuh was verified against (3cf03257, the
# fetched pin; the vendored third_party/llama.cpp tree has the same mmq.cuh).
set(_strata_mmq_tab_on OFF)
if(STRATA_MMQ_TAB AND NOT STRATA_HIP_GFX906) # gfx906 compiles no .cu from here (its HIP glob): no tab at all
set(_strata_mmq_tab_known 36e4dc716c504470ec09cc0852d29a6ac5eace257f6e5e72db3805ca4f043eb0)
set(_strata_mmq_tab_hash "")
if(EXISTS ${_strata_mmq}/mmq.cuh)
file(READ ${_strata_mmq}/mmq.cuh _strata_mmq_src)
string(REPLACE "\r\n" "\n" _strata_mmq_src "${_strata_mmq_src}")
string(FIND "${_strata_mmq_src}" "static __device__ __forceinline__ void mul_mat_q_process_tile" _strata_tab_a)
string(FIND "${_strata_mmq_src}" "#define DECL_MMQ_CASE" _strata_tab_b)
if(_strata_tab_a GREATER -1 AND _strata_tab_b GREATER _strata_tab_a)
math(EXPR _strata_tab_len "${_strata_tab_b} - ${_strata_tab_a}")
string(SUBSTRING "${_strata_mmq_src}" ${_strata_tab_a} ${_strata_tab_len} _strata_tab_region)
string(SHA256 _strata_mmq_tab_hash "${_strata_tab_region}")
endif()
unset(_strata_mmq_src)
unset(_strata_tab_region)
endif()
if(_strata_mmq_tab_hash AND _strata_mmq_tab_hash IN_LIST _strata_mmq_tab_known)
set(_strata_mmq_tab_on ON)
else()
message(STATUS "STRATA_MMQ_TAB off: mmq.cuh differs from the mirrored scheduler (${_strata_mmq_tab_hash})")
endif()
endif()
if(_strata_mmq_tab_on)
set(_strata_tab_cuh ${CMAKE_CURRENT_SOURCE_DIR}/src/prefill/moe_mmq_tab.cuh)
# the native packs' nine types, the ones prefill_mmq_tab_test checks bit for bit; the optional Q5_0 / K-quant
# instances (STRATA_ORCA_Q4KS_MMQ, STRATA_MMQ_KQUANTS) get no pointer table and keep the gather
set(_strata_mmq_tab_types q2_0 iq2_xxs iq2_xs iq2_s iq3_xxs iq3_s iq4_nl iq4_xs q8_0)
foreach(_t IN LISTS _strata_mmq_tab_types)
string(TOUPPER ${_t} _strata_tab_T)
configure_file(src/prefill/mmq_tab_instance.cu.in ${CMAKE_BINARY_DIR}/mmq_tab/mmq-tab-${_t}.cu @ONLY)
target_sources(strata_mmq PRIVATE ${CMAKE_BINARY_DIR}/mmq_tab/mmq-tab-${_t}.cu)
endforeach()
target_compile_definitions(strata_mmq PRIVATE STRATA_MMQ_TAB=1)
message(STATUS "STRATA_MMQ_TAB on: pointer-table MMQ for ${_strata_mmq_tab_types}")
endif()
target_include_directories(strata_mmq PRIVATE ${_strata_gg}/include ${_strata_gg}/src ${_strata_mmq}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_compile_options(strata_mmq PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--extended-lambda -use_fast_math>)
if(MSVC)
target_compile_options(strata_mmq PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/bigobj>)
endif()
# GGML's CUDA error reporting calls cuGetErrorString from the driver API.
target_link_libraries(strata_mmq PUBLIC ggml-base ${_strata_gpu_runtime_target})
if(TARGET CUDA::cuda_driver) # not in the HIP (gfx906) build, whose CUDA::cudart is a stand-in
target_link_libraries(strata_mmq PUBLIC CUDA::cuda_driver)
endif()
if(STRATA_MMQ_KQUANTS)
target_compile_definitions(strata_mmq PRIVATE STRATA_MMQ_KQUANTS=1)
endif()
if(_strata_kq_dso)
# strata_kq: the K-quant MMQ instances with their own copy of ggml_cuda_host.cu's symbols and the static CUDA
# runtime, next to the engine (libstrata_kq.so / strata_kq.dll); moe_mmq.cu opens it when a model asks for one
# of these formats (STRATA_MMQ_KQ=1). Without the file the engine runs them on the FP16 prompt path, as before.
target_compile_definitions(strata_mmq PRIVATE STRATA_KQ_DSO=1)
target_sources(strata_mmq PRIVATE src/prefill/mmq_kq_loader.cpp)
if(NOT WIN32)
target_link_libraries(strata_mmq PUBLIC ${CMAKE_DL_LIBS})
endif()
add_library(strata_kq SHARED src/prefill/mmq_kq_lib.cu src/prefill/ggml_cuda_host.cu)
foreach(_t IN LISTS _strata_kq_types)
target_sources(strata_kq PRIVATE ${_strata_mmq}/template-instances/mmq-instance-${_t}.cu)
endforeach()
target_include_directories(strata_kq PRIVATE ${_strata_gg}/include ${_strata_gg}/src ${_strata_mmq}
${CMAKE_CURRENT_SOURCE_DIR}/include)
target_compile_options(strata_kq PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--extended-lambda -use_fast_math>)
if(MSVC)
target_compile_options(strata_kq PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/bigobj>)
endif()
set_target_properties(strata_kq PROPERTIES CUDA_RUNTIME_LIBRARY Static POSITION_INDEPENDENT_CODE ON
CXX_VISIBILITY_PRESET hidden CUDA_VISIBILITY_PRESET hidden)
# ggml-base is static: position-independent so a shared library can hold it (the same code otherwise)
set_target_properties(ggml-base PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(strata_kq PRIVATE ggml-base)
if(TARGET CUDA::cuda_driver)
target_link_libraries(strata_kq PRIVATE CUDA::cuda_driver)
endif()
add_dependencies(strata_mmq strata_kq)
endif()
if(STRATA_ORCA_Q4KS_MMQ)
target_compile_definitions(strata_mmq PRIVATE STRATA_ORCA_Q4KS_MMQ=1)
endif()
@@ -1300,14 +1703,37 @@ if(STRATA_NATIVE_EXPERTS)
target_link_libraries(prefill_fused_iq_test PRIVATE strata_mmq ggml-base ${_strata_gpu_runtime_target})
add_test(NAME prefill_fused_iq_test COMMAND prefill_fused_iq_test)
set_tests_properties(prefill_fused_iq_test PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 600)
# the MoE input quantized per token and scattered to its rows (mmq::quantize_scatter) against the per-row
# gather: the same q8_1 bytes for every MMQ layout (--bench: both at 2K, 8K and 32K tokens)
add_executable(prefill_mmq_scatter_test tests/cuda/prefill_mmq_scatter_test.cpp)
target_link_libraries(prefill_mmq_scatter_test PRIVATE strata_mmq ggml-base ${_strata_gpu_runtime_target})
add_test(NAME prefill_mmq_scatter_test COMMAND prefill_mmq_scatter_test)
set_tests_properties(prefill_mmq_scatter_test PROPERTIES TIMEOUT 120)
endif()
if(STRATA_BUILD_TESTS AND _strata_mmq_tab_on)
# STRATA_MMQ_DIRECT: the pointer-table MMQ bit for bit against the gathered MMQ (exit 77 below sm_80)
add_executable(prefill_mmq_tab_test tests/cuda/prefill_mmq_tab_test.cu)
target_link_libraries(prefill_mmq_tab_test PRIVATE strata_mmq ggml-base ${_strata_gpu_runtime_target})
add_test(NAME prefill_mmq_tab_test COMMAND prefill_mmq_tab_test)
set_tests_properties(prefill_mmq_tab_test PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 600)
endif()
if(STRATA_BUILD_TESTS AND STRATA_MMQ_KQUANTS)
# the UD-Q4_K_XL expert formats through MMQ against ggml's dequantized weights (synthetic, a few seconds)
add_executable(prefill_mmq_kquant_test tests/cuda/prefill_mmq_kquant_test.cpp)
target_link_libraries(prefill_mmq_kquant_test PRIVATE strata_mmq ggml-base ${_strata_gpu_runtime_target})
add_test(NAME prefill_mmq_kquant_test COMMAND prefill_mmq_kquant_test)
set_tests_properties(prefill_mmq_kquant_test PROPERTIES TIMEOUT 120)
# the K-quant MMQ is opt-in at run time (STRATA_MMQ_KQ=1), and on CUDA it is strata_kq next to the test
set_tests_properties(prefill_mmq_kquant_test PROPERTIES TIMEOUT 120 ENVIRONMENT STRATA_MMQ_KQ=1)
endif()
# the NVFP4 expert products (w4a8 / w4a4, STRATA_PREFILL_NVFP4) against a double-precision reference
add_executable(mmq_nvfp4_parity src/prefill/mmq_nvfp4_parity.cpp)
target_link_libraries(mmq_nvfp4_parity PRIVATE strata_mmq ggml-base CUDA::cudart)
if(NOT MSVC) # its FP16 rounding helper uses the F16C intrinsics (GCC/Clang need the target flag)
target_compile_options(mmq_nvfp4_parity PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-mf16c>)
endif()
# the routed-expert products (MMQ) timed at the prompt path's shapes (16 experts a launch)
add_executable(mmq_expert_bench src/prefill/mmq_expert_bench.cpp)
target_link_libraries(mmq_expert_bench PRIVATE strata_mmq ggml-base CUDA::cudart)
elseif(STRATA_PREFILL_MMQ)
# Compile only the pinned GGML MMQ and activation-quantizer sources used by prefill. This uses
# common.cuh's native HIP path without enabling a second GGML HIP backend.
@@ -1320,11 +1746,12 @@ if(STRATA_NATIVE_EXPERTS)
if(NOT EXISTS "${_strata_mmq}/common.cuh" OR NOT EXISTS "${_strata_mmq}/quantize.cu")
message(FATAL_ERROR "The selected GGML source is missing the ggml-cuda MMQ sources: ${_strata_mmq}")
endif()
# Aurora: moe_fused.cu's and moe_fused_iq.cu's gfx11 WMMA kernels for the prompt experts (opt-in STRATA_PF_FUSED=1)
# Aurora: moe_fused.cu's gfx11 and moe_fused_iq.cu's gfx11 / gfx12 WMMA kernels for the prompt experts (opt-in STRATA_PF_FUSED=1)
set(_strata_mmq_sources
src/prefill/moe_mmq.cu
src/prefill/moe_fused.cu
src/prefill/moe_fused_iq.cu
src/prefill/moe_f16_kq.cu
src/prefill/ggml_cuda_host.cu
"${_strata_mmq}/quantize.cu")
if(STRATA_MMQ_KQUANTS)
@@ -1337,7 +1764,7 @@ if(STRATA_NATIVE_EXPERTS)
endforeach()
set_source_files_properties(${_strata_mmq_sources} PROPERTIES LANGUAGE HIP)
# moe_fused.cu is Strata's own CUDA-shaped source: it takes the HIP compat headers, ggml's MMQ sources do not
set_source_files_properties(src/prefill/moe_fused.cu src/prefill/moe_fused_iq.cu
set_source_files_properties(src/prefill/moe_fused.cu src/prefill/moe_fused_iq.cu src/prefill/moe_f16_kq.cu
PROPERTIES INCLUDE_DIRECTORIES "${STRATA_HIP_COMPAT_INCLUDE_DIR}")
add_library(strata_mmq STATIC ${_strata_mmq_sources})
target_include_directories(strata_mmq
@@ -1365,6 +1792,9 @@ if(STRATA_NATIVE_EXPERTS)
target_link_libraries(hip_prefill_fused_iq PRIVATE strata_mmq ggml-base strata_hip_runtime)
add_test(NAME hip_prefill_fused_iq COMMAND hip_prefill_fused_iq)
set_tests_properties(hip_prefill_fused_iq PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 600)
# the same binary on F16 weights (gfx11: the covered formats take moe_f16_kq.cu / native_f16_kernel; elsewhere it is the default run again)
add_test(NAME hip_prefill_fused_iq_f16 COMMAND hip_prefill_fused_iq)
set_tests_properties(hip_prefill_fused_iq_f16 PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 600 ENVIRONMENT "STRATA_PF_F16=1;STRATA_PF_F16_KQ=1")
list(APPEND _strata_hip_tests hip_prefill_fused_iq)
# Numerical diagnostic: synthetic layouts by default, optional first-expert IQ3_XXS/IQ4_NL check with a pack.
@@ -1380,6 +1810,18 @@ if(STRATA_NATIVE_EXPERTS)
add_executable(hip_ple_iq4 tests/hip/ple_iq4.cpp)
target_link_libraries(hip_ple_iq4 PRIVATE strata_kernels strata_hip_runtime ggml-base)
endif()
# the NVFP4 AVX-512 and AVX2 rows vs ggml-cpu's vec_dot, and their speed (CPU only; optional arg: a pack's experts.bin)
add_executable(nvfp4_avx512_parity src/kernels/cpu/nvfp4_avx512_parity.cpp)
target_link_libraries(nvfp4_avx512_parity PRIVATE strata_kernels_cpu)
add_test(NAME nvfp4_cpu_parity COMMAND nvfp4_avx512_parity) # random blocks; the AVX2 rows bit-equal to ggml's
set_tests_properties(nvfp4_cpu_parity PROPERTIES TIMEOUT 120)
if(STRATA_ENABLE_CUDA) # the NVFP4 decode kernels vs ggml's reference
add_executable(nvfp4_expert_gpu_parity src/kernels/nvfp4_expert_gpu_parity.cpp)
target_link_libraries(nvfp4_expert_gpu_parity PRIVATE strata_kernels ggml-base CUDA::cudart)
# the decode experts' weight bandwidth on random blobs of a format pair, and an output hash (bit-for-bit checks)
add_executable(nvfp4_decode_bench src/kernels/nvfp4_decode_bench.cpp)
target_link_libraries(nvfp4_decode_bench PRIVATE strata_kernels CUDA::cudart)
endif()
if(STRATA_ENABLE_CUDA OR STRATA_ENABLE_HIP)
add_executable(native_expert_parity src/kernels/native_expert_parity.cpp)
target_include_directories(native_expert_parity PRIVATE ${_strata_gpu_include_directories})
@@ -1387,6 +1829,17 @@ if(STRATA_NATIVE_EXPERTS)
add_executable(native_expert_bench src/kernels/native_expert_bench.cpp)
target_include_directories(native_expert_bench PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(native_expert_bench PRIVATE strata_kernels strata_kernels_cpu strata_artifact ${_strata_gpu_runtime_target})
# MODEL-UPDATE: the dense Q8_0 GEMVs at the engine's shapes against the memory bandwidth (a benchmark, no test)
add_executable(q8_gemv_bench src/kernels/q8_gemv_bench.cpp)
target_include_directories(q8_gemv_bench PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(q8_gemv_bench PRIVATE strata_kernels ${_strata_gpu_runtime_target})
if(STRATA_ENABLE_CUDA)
# EXPDEC (docs/EXPERTDEC.md): the grouped experts' default kernels against STRATA_EXPDEC=1 at T = 1..4, bit for bit
# and in microseconds, on synthetic blobs read cold from DRAM
add_executable(expdec_bench EXCLUDE_FROM_ALL src/kernels/expdec_bench.cpp)
target_include_directories(expdec_bench PRIVATE ${_strata_gpu_include_directories})
target_link_libraries(expdec_bench PRIVATE strata_kernels ${_strata_gpu_runtime_target})
endif()
if(STRATA_BUILD_TESTS AND STRATA_ENABLE_CUDA)
# Unsloth UD-Q4_K_XL's three expert pairs (and Q8_0 alone, its embedding) on synthetic ggml-quantized weights
# at 2560/640: GPU and CPU experts against the float reference, GPU dequantizers against to_float.
@@ -1454,6 +1907,7 @@ if(STRATA_BUILD_TESTS)
add_executable(expert_multi_test src/kernels/cpu/expert_multi_test.cpp)
target_link_libraries(expert_multi_test PRIVATE strata_kernels_cpu)
add_test(NAME expert_multi_test COMMAND expert_multi_test)
set_tests_properties(expert_multi_test PROPERTIES SKIP_RETURN_CODE 77) # no AVX-512: skipped
# PR #706: the opt-in AVX-2 Q2_0 bit-plane kernel (STRATA_Q2_BITPLANE=1) against the legacy one, bitwise alone/window
if(STRATA_BUILD_TESTS AND CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64|x86_64|x64|X86")
@@ -1478,12 +1932,52 @@ if(STRATA_BUILD_TESTS)
target_link_libraries(pool_stress PRIVATE strata_kernels_cpu)
add_test(NAME pool_stress COMMAND pool_stress 20)
# #795: nothing an AVX2-only CPU can reach may hold AVX-512 / AVX-VNNI-class instructions. (1) the linked test binary
# (every CPU kernel file plus ggml-cpu; on Linux, the kernel library) is disassembled and any function with such instructions must be a kernel of
# a wide-ISA file, not a weak / COMDAT copy and not a probe or helper that every CPU runs; (2) with -DSTRATA_SDE=<sde>
# (Intel SDE) the CPU tests run on an emulated AVX2-only Haswell and on an Alder Lake (AVX-VNNI, no AVX-512): SDE stops
# at the first instruction the chip does not have.
if(TARGET iq_avx2_parity)
find_package(Python3 QUIET COMPONENTS Interpreter)
if(Python3_Interpreter_FOUND)
if(MSVC)
target_link_options(iq_avx2_parity PRIVATE /MAP)
add_test(NAME isa_guard_check COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/check_isa_guard.py
$<TARGET_FILE:iq_avx2_parity> --map $<TARGET_FILE_DIR:iq_avx2_parity>/iq_avx2_parity.map)
else()
# the library, not the binary: a Linux source build compiles ggml-cpu for the build machine on purpose
add_test(NAME isa_guard_check COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/check_isa_guard.py
$<TARGET_FILE:strata_kernels_cpu>)
endif()
set_tests_properties(isa_guard_check PROPERTIES SKIP_RETURN_CODE 77 TIMEOUT 600)
endif()
endif()
set(STRATA_SDE "" CACHE FILEPATH "Intel SDE (sde / sde64): also run the CPU tests on an emulated AVX2-only and an AVX-VNNI-only CPU")
if(STRATA_SDE AND TARGET iq_avx2_parity)
foreach(_chip hsw adl)
foreach(_t iq_avx2_parity q8k_quant_parity router_dot_parity pool_tasks_test q2_bitplane_parity)
if(TARGET ${_t})
add_test(NAME sde_${_chip}_${_t} COMMAND ${STRATA_SDE} -${_chip} -- $<TARGET_FILE:${_t}>)
set_tests_properties(sde_${_chip}_${_t} PROPERTIES TIMEOUT 900)
endif()
endforeach()
if(TARGET q2_bitplane_parity)
set_tests_properties(sde_${_chip}_q2_bitplane_parity PROPERTIES ENVIRONMENT "STRATA_Q2_BITPLANE=1")
endif()
endforeach()
endif()
if(UNIX AND NOT APPLE)
add_executable(direct_file_async_test tests/platform/direct_file_async.cpp src/platform/direct_file.cpp)
target_include_directories(direct_file_async_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(direct_file_async_test PRIVATE Threads::Threads)
add_test(NAME direct_file_async_test COMMAND direct_file_async_test)
endif()
# --aux-cpus: the CPU-set derivation (pure) and the placement of live threads; header-only, no GPU
add_executable(aux_cpus_test tests/platform/aux_cpus_test.cpp)
target_include_directories(aux_cpus_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(aux_cpus_test PRIVATE Threads::Threads)
add_test(NAME aux_cpus_test COMMAND aux_cpus_test)
endif()
if(STRATA_BUILD_TESTS)
@@ -1505,3 +1999,8 @@ if(STRATA_HIP_GFX906)
endif()
set_source_files_properties(${_strata_cu} PROPERTIES LANGUAGE HIP)
endif()
if(STRATA_HIP_GFX906)
add_executable(gfx906_qsa_query_swizzle_probe bench/gfx906_qsa_query_swizzle_probe.cpp)
target_link_libraries(gfx906_qsa_query_swizzle_probe PRIVATE strata_kernels ${_strata_gpu_runtime_target})
endif()
+3 -1
View File
@@ -79,7 +79,7 @@ arch = os.environ.get("CUDA_ARCHITECTURES", "75;80;86;89;120").strip().strip('"'
vision = "gpu" if os.environ.get("BUILD_VISION", "1") == "1" else "none"
setup.cmake_build(setup.ROOT, setup.ROOT / "build", "strata",
["-DSTRATA_ENABLE_CUDA=ON", "-DSTRATA_BUILD_TESTS=OFF",
["-DSTRATA_ENABLE_CUDA=ON", "-DSTRATA_Q6K_EXPERTS=ON", "-DSTRATA_MMQ_KQUANTS=ON", "-DSTRATA_BUILD_TESTS=OFF",
f"-DCMAKE_CUDA_ARCHITECTURES={arch}", f"-DCMAKE_CUDA_COMPILER={nvcc}",
f"-DSTRATA_GGML_DIR={llama}"], None, "build-strata.bat")
if vision != "none":
@@ -90,6 +90,8 @@ if vision != "none":
eng = setup.ROOT / "engine"
eng.mkdir(exist_ok=True)
shutil.copy2(setup.ROOT / "build" / setup.EXE, eng / setup.EXE)
if (setup.ROOT / "build" / setup.KQ_LIB).exists(): # the K-quant MMQ prompt library (UD-Q4/Q5/Q6_K_XL files)
shutil.copy2(setup.ROOT / "build" / setup.KQ_LIB, eng / setup.KQ_LIB)
if vision != "none":
shutil.copy2(setup.ROOT / "build-vision" / "bin" / setup.VEXE, eng / setup.VEXE)
bindir = pathlib.Path(nvcc).parent
+20 -3
View File
@@ -92,6 +92,8 @@ startet er es und sagt dir, wie du deine Apps verbindest. KI-Tools können Strat
[Lade Strata herunter](https://github.com/Niko1221/Strata/archive/refs/heads/main.zip) und entpacke es (oder nutze
`git clone`). **Windows:** Doppelklick auf **`START-HERE.bat`**. **Linux:** Führe im Strata-Ordner **`./setup.sh`** aus.
**Mac (Apple Silicon, M1 bis M5, macOS 15 oder neuer):** Installiere einmal Apples Command Line Tools (`xcode-select --install` im Terminal; Xcode selbst brauchst du nicht). Öffne dann das Terminal im Strata-Ordner und führe **`./setup.sh`** aus. Es baut die Mac-Engine auf deinem Mac (etwa 7 Minuten), stellt dieselben Fragen, lädt das Modell und startet es. Beim nächsten Mal startet `./setup.sh` sofort. Welche Größe zu deinem Mac passt und wie schnell es ist: [docs/MAC.md](docs/MAC.md).
Die Schritte sind für NVIDIA und AMD gleich. Der Installer erkennt deine Karte und richtet die passende Engine
dafür ein. Er stellt dir ein paar Fragen:
@@ -133,9 +135,10 @@ stark komprimiert. Kleinere Größen sind schneller. Größere sind etwas klüge
- **[Unsloth UD-IQ4_XS](docs/MODELS.md#unsloth-ud-iq4_xs):** die ~4-Bit-Version von Unsloth, in der Qualität
zwischen IQ3_S und UD-Q4_K_XL. 94 GB Download. Mit weniger als ~80 GB RAM liest Strata einen Teil davon während
der Antwort von der SSD, dort ist es also langsamer (eine NVMe-SSD hilft).
- **[Unsloth UD-Q4_K_XL](docs/MODELS.md#unsloth-ud-q4_k_xl-experimental)** (experimentell): am nächsten am vollen
Modell. Aber Strata liest das meiste davon während der Antwort von der SSD, deshalb schreibt es auf einem PC mit
64 GB nur 7-8.5 Tokens/s.
- **[Unsloth UD-Q4_K_XL, UD-Q5_K_XL, UD-Q6_K_XL und Q8_0](docs/MODELS.md#unsloths-files-ud-iq4_xs-to-q8_0):** 4 bis 8 Bit, näher am vollen Modell
(93-95 % das gleiche nächste Token wie Q8_0). Schnell, wenn alle Experten in den RAM passen (~88 GB für UD-Q4_K_XL
bis ~136 GB für Q8_0); mit weniger RAM liest Strata einen Teil davon während der Antwort von der SSD, was viel
langsamer ist (7-8.5 Tokens/s für UD-Q4_K_XL auf einem PC mit 64 GB).
- **[OrcaRouter's Uncensored IQ3_XXS](docs/MODELS.md#orcarouter-uncensored-iq3_xxs):** Das richtest du von Hand
ein. Es steht nicht im Menü des Installers.
@@ -169,6 +172,20 @@ hinzuzufügen, starte `SETUP.bat` (Linux: `./setup.sh --setup`).
Mehr: [wo deine Chats gespeichert werden](docs/INSTALL.md#where-things-are-stored), [die API](docs/DETAILS.md#using-it).
### Optional: mehr Tempo mit einer Grafikkarte, wenn das ganze Modell in den RAM passt
Zwei Opt-in-Einstellungen (von RubenTorney, #1904 und #1905). Sie helfen, wenn du eine Grafikkarte nutzt und dein RAM alle Experten hält (Stratas Arena-Modus, zum Beispiel Q2_0 oder IQ3_XXS auf einem PC mit 64 GB). Öffne deine Konfiguration `strata-<model>.json` im Strata-Datenordner ([wo](docs/INSTALL.md#where-things-are-stored)) und füge hinzu:
- **Schnellere Ausgabe:** `"--adapt-async", "1"` in die Liste `"args"`. Der Experten-Cache wird dann in einem Hilfs-Thread aktualisiert, statt die Antwort anzuhalten. Gemessen auf einer RTX 5070 (Windows, Q2_0): +4-5 % Ausgabe, +7-10 % bei Code und langen Dokumenten. Antworten können leicht vom Standard abweichen (sie bleiben von Lauf zu Lauf gleich).
- **Schnelleres Prompt-Lesen unter Windows:** `"STRATA_PIN_BY_NEED": "1"` im Block `"env"`. Windows kann nur etwa den halben RAM für die Grafikkarte sperren; damit werden zuerst die Experten gesperrt, die die Karte wirklich braucht. Gemessen auf der RTX 5070: +4,4 % Prompt-Lesen.
```json
"args": [ ..., "--adapt-async", "1" ],
"env": { "STRATA_PIN_BY_NEED": "1" }
```
Starte Strata danach neu (`START-HERE.bat` oder `./setup.sh`). Zum Rückgängigmachen entferne die beiden Einträge.
## Etwas ist schiefgelaufen?
- **Mein PC ist beim ersten Start von Strata eingefroren.** Das ist normal, während das Modell lädt. Warte und
+20 -3
View File
@@ -90,6 +90,8 @@ cómo conectar tus aplicaciones. Las herramientas de IA también pueden instalar
[Descarga Strata](https://github.com/Niko1221/Strata/archive/refs/heads/main.zip) y descomprímelo (o usa `git clone`).
**Windows:** haz doble clic en **`START-HERE.bat`**. **Linux:** ejecuta **`./setup.sh`** en la carpeta de Strata.
**Mac (Apple Silicon, M1 a M5, macOS 15 o posterior):** instala una vez las Command Line Tools de Apple (`xcode-select --install` en Terminal; no hace falta Xcode). Luego abre Terminal en la carpeta de Strata y ejecuta **`./setup.sh`**. Compila el motor de Mac en tu Mac (unos 7 minutos), hace las mismas preguntas, descarga el modelo y lo arranca. La próxima vez, `./setup.sh` arranca enseguida. Qué tamaño cabe en tu Mac y qué velocidad tiene: [docs/MAC.md](docs/MAC.md).
Los pasos son los mismos para NVIDIA y AMD. El instalador detecta tu tarjeta y prepara el motor adecuado para ella.
Te hace unas pocas preguntas:
@@ -130,9 +132,10 @@ tamaños pequeños son más rápidos. Los grandes son algo más inteligentes.
- **[Unsloth UD-IQ4_XS](docs/MODELS.md#unsloth-ud-iq4_xs):** la versión de ~4 bits de Unsloth, entre IQ3_S y
UD-Q4_K_XL en calidad. Una descarga de 94 GB. Con menos de ~80 GB de RAM, Strata lee una parte desde el SSD
mientras responde, así que ahí es más lento (un SSD NVMe ayuda).
- **[Unsloth UD-Q4_K_XL](docs/MODELS.md#unsloth-ud-q4_k_xl-experimental)** (experimental): el más parecido al modelo
completo. Pero Strata lee la mayor parte desde el SSD mientras responde, así que solo escribe 7-8.5 tokens/s en un
PC con 64 GB.
- **[Unsloth UD-Q4_K_XL, UD-Q5_K_XL, UD-Q6_K_XL y Q8_0](docs/MODELS.md#unsloths-files-ud-iq4_xs-to-q8_0):** de 4 a 8 bits, más cerca del modelo completo
(93-95 % el mismo token siguiente que Q8_0). Rápidos cuando todos los expertos caben en la RAM (~88 GB para
UD-Q4_K_XL hasta ~136 GB para Q8_0); con menos RAM, Strata lee una parte desde el SSD mientras responde, lo que es
mucho más lento (7-8.5 tokens/s para UD-Q4_K_XL en un PC con 64 GB).
- **[OrcaRouter's Uncensored IQ3_XXS](docs/MODELS.md#orcarouter-uncensored-iq3_xxs):** se instala a mano. No está en
el menú del instalador.
@@ -164,6 +167,20 @@ Tamaños, descargas y qué cabe dónde: [docs/MODELS.md](docs/MODELS.md). Para a
Más: [dónde se guardan tus chats](docs/INSTALL.md#where-things-are-stored), [la API](docs/DETAILS.md#using-it).
### Opcional: más velocidad con una sola tarjeta cuando todo el modelo cabe en la RAM
Dos ajustes opcionales (de RubenTorney, #1904 y #1905). Ayudan si usas una tarjeta gráfica y tu RAM guarda todos los expertos (el modo arena de Strata, por ejemplo Q2_0 o IQ3_XXS en un PC con 64 GB). Abre tu configuración `strata-<model>.json` en la carpeta de datos de Strata ([dónde](docs/INSTALL.md#where-things-are-stored)) y añade:
- **Generación más rápida:** `"--adapt-async", "1"` en la lista `"args"`. La caché de expertos se actualiza entonces en un hilo auxiliar en vez de pausar la respuesta. Medido en una RTX 5070 (Windows, Q2_0): +4-5 % de generación, +7-10 % en código y documentos largos. Las respuestas pueden diferir un poco de las por defecto (son iguales de una ejecución a otra).
- **Lectura del prompt más rápida en Windows:** `"STRATA_PIN_BY_NEED": "1"` en el bloque `"env"`. Windows solo puede bloquear cerca de la mitad de la RAM para la tarjeta; esto bloquea primero los expertos que la tarjeta necesita de verdad. Medido en la RTX 5070: +4,4 % en la lectura del prompt.
```json
"args": [ ..., "--adapt-async", "1" ],
"env": { "STRATA_PIN_BY_NEED": "1" }
```
Reinicia Strata (`START-HERE.bat` o `./setup.sh`) después del cambio. Para deshacerlo, quita las dos entradas.
## ¿Algo salió mal?
- **Mi PC se congeló la primera vez que arrancó Strata.** Es normal mientras carga el modelo. Espera y no cierres la
+20 -3
View File
@@ -90,6 +90,8 @@ arrêter Strata grâce à son [serveur MCP](docs/MCP_SERVER.md).
[Téléchargez Strata](https://github.com/Niko1221/Strata/archive/refs/heads/main.zip) et décompressez-le (ou faites un `git clone`).
**Windows :** double-cliquez sur **`START-HERE.bat`**. **Linux :** lancez **`./setup.sh`** dans le dossier Strata.
**Mac (Apple Silicon, M1 à M5, macOS 15 ou plus récent) :** installez une fois les Command Line Tools d'Apple (`xcode-select --install` dans le Terminal ; Xcode lui-même n'est pas nécessaire). Ouvrez ensuite le Terminal dans le dossier Strata et lancez **`./setup.sh`**. Il compile le moteur Mac sur votre Mac (environ 7 minutes), pose les mêmes questions, télécharge le modèle et le démarre. La fois suivante, `./setup.sh` démarre tout de suite. Quelle taille convient à votre Mac et sa vitesse : [docs/MAC.md](docs/MAC.md).
Les étapes sont les mêmes pour NVIDIA et AMD. L'installateur détecte votre carte et installe le bon moteur pour elle.
Il vous pose quelques questions :
@@ -130,9 +132,10 @@ compressées. Les petites tailles sont plus rapides. Les grandes sont un peu plu
- **[Unsloth UD-IQ4_XS](docs/MODELS.md#unsloth-ud-iq4_xs)** : la version ~4 bits d'Unsloth, entre IQ3_S et
UD-Q4_K_XL en qualité. Un téléchargement de 94 Go. Avec moins de ~80 Go de RAM, Strata en lit une partie depuis
le SSD pendant qu'il répond, il y est donc plus lent (un SSD NVMe aide).
- **[Unsloth UD-Q4_K_XL](docs/MODELS.md#unsloth-ud-q4_k_xl-experimental)** (expérimental) : le plus proche du modèle
complet. Mais Strata en lit la plus grande partie depuis le SSD pendant qu'il répond, donc il n'écrit que
7-8.5 tokens/s sur un PC avec 64 Go.
- **[Unsloth UD-Q4_K_XL, UD-Q5_K_XL, UD-Q6_K_XL et Q8_0](docs/MODELS.md#unsloths-files-ud-iq4_xs-to-q8_0) :** de 4 à 8 bits, plus proches du modèle
complet (93-95 % le même token suivant que Q8_0). Rapides quand tous les experts tiennent dans la RAM (~88 Go pour
UD-Q4_K_XL jusqu'à ~136 Go pour Q8_0) ; avec moins de RAM, Strata en lit une partie depuis le SSD pendant qu'il
répond, ce qui est bien plus lent (7-8.5 tokens/s pour UD-Q4_K_XL sur un PC avec 64 Go).
- **[OrcaRouter's Uncensored IQ3_XXS](docs/MODELS.md#orcarouter-uncensored-iq3_xxs) :** vous l'installez à la main.
Il n'est pas dans le menu de l'installateur.
@@ -167,6 +170,20 @@ tard, lancez `SETUP.bat` (Linux : `./setup.sh --setup`).
Plus d'infos : [où sont stockées vos discussions](docs/INSTALL.md#where-things-are-stored), [l'API](docs/DETAILS.md#using-it).
### Optionnel : plus de vitesse sur une seule carte quand tout le modèle tient en RAM
Deux réglages optionnels (de RubenTorney, #1904 et #1905). Ils aident si vous utilisez une seule carte graphique et que votre RAM contient tous les experts (le mode arena de Strata, par exemple Q2_0 ou IQ3_XXS sur un PC de 64 Go). Ouvrez votre configuration `strata-<model>.json` dans le dossier de données de Strata ([où](docs/INSTALL.md#where-things-are-stored)) et ajoutez :
- **Génération plus rapide :** `"--adapt-async", "1"` dans la liste `"args"`. Le cache d'experts est alors mis à jour dans un thread auxiliaire au lieu de mettre la réponse en pause. Mesuré sur une RTX 5070 (Windows, Q2_0) : +4-5 % de génération, +7-10 % sur le code et les longs documents. Les réponses peuvent légèrement différer de celles par défaut (elles restent identiques d'une exécution à l'autre).
- **Lecture du prompt plus rapide sous Windows :** `"STRATA_PIN_BY_NEED": "1"` dans le bloc `"env"`. Windows ne peut verrouiller qu'environ la moitié de la RAM pour la carte ; ce réglage verrouille d'abord les experts dont la carte a vraiment besoin. Mesuré sur la RTX 5070 : +4,4 % en lecture du prompt.
```json
"args": [ ..., "--adapt-async", "1" ],
"env": { "STRATA_PIN_BY_NEED": "1" }
```
Redémarrez Strata (`START-HERE.bat` ou `./setup.sh`) après la modification. Pour annuler, retirez les deux entrées.
## Un problème ?
- **Mon PC s'est figé au premier démarrage de Strata.** C'est normal pendant le chargement du modèle. Attendez, et ne
+133 -115
View File
@@ -3,28 +3,28 @@
[English](README.md) · [简体中文](README.zh-CN.md) · **日本語** · [Deutsch](README.de.md) · [Français](README.fr.md) · [Español](README.es.md) · [Português](README.pt-BR.md)
<p align="center"><b>1,250 億パラメータの AI モデルを、手元のゲーミング PC で動かす</b><br>
NVIDIA または AMD のグラフィックカード(12 GB 以上) · Windows または Linux · 無料のオープンソース</p>
NVIDIA または AMD のグラフィックカード(12 GB 以上) · Windows または Linux · 無料・オープンソース</p>
<p align="center"><a href="https://github.com/Niko1221/Strata/releases/download/v0.1.10/Pagoda.mp4"><img src="docs/media/pagoda-preview.webp" width="720" alt="Strata のモデルが書いたボクセルの五重塔の庭。ブラウザで動いている様子"></a><br>
<sub>ボクセルの五重塔の庭。1 回のプロンプトで作成し、RTX 5070 上の Strata(IQ3_S、128K コンテキスト)で実行 ·
<a href="https://github.com/Niko1221/Strata/releases/download/v0.1.10/Pagoda.mp4">動画全体(49 秒)</a></sub></p>
<p align="center"><a href="https://github.com/Niko1221/Strata/releases/download/v0.1.10/Pagoda.mp4"><img src="docs/media/pagoda-preview.webp" width="720" alt="Strata で生成した、五重塔のある庭。ボクセルで表現され、ブラウザーで動作している"></a><br>
<sub>五重塔のある庭をボクセルで表現。RTX 5070 で動かした Strata(IQ3_S、コンテキスト長 128K)に、1 回のプロンプトで作成を依頼 ·
<a href="https://github.com/Niko1221/Strata/releases/download/v0.1.10/Pagoda.mp4">動画を見る(全編 49 秒)</a></sub></p>
Strata は **[Qwen3.8-Flash-Next](https://huggingface.co/Qwen/Qwen3.8-Flash-Next)** を普通の PC で動かします。
これは大きくて賢い AI モデルで、ふつうはサーバーが必要です。チャットをしたり、コードを書いたり、画像を読んだりできます。
アプリやコーディングエージェントとも連携します。データが PC の外に出ることはありません。
Strata を使うと、**[Qwen3.8-Flash-Next](https://huggingface.co/Qwen/Qwen3.8-Flash-Next)** を一般的な PC で動かせます。
通常はサーバーを必要とする大規模で高性能な AI モデルで、チャットやコードの生成、画像の読み取りができます。
アプリやコーディングエージェントとも連携でき、データは PC の外に送信されません。
## どのくらい速い?
ごく普通のゲーミング PC 2 台で測りました。1 トークンは英単語のおよそ ¾ です。
一般的なゲーミング PC 2 台で速度を測定しました。英語の場合、1 トークンはおよそ ¾ 語に相当します。
- **回答の書き出し:** 短いチャットで返答が表示される速さです。毎秒 60 トークンあれば、読むより速く表示されます。
- **プロンプトの読み込み:** 送った内容を取り込む速さです(ここでは 32K トークンの文書、コード、またはチャット履歴)。
- **生成速度:** 短いチャットで回答を生成する速度です。毎秒 60 トークンなら、人が読むよりも速く文章が表示されます。
- **プロンプトの読み込み:** 入力した内容を読み込む速度です。ここでは、文書やコード、チャット履歴など 32K トークン分を読み込ませています。
<table>
<tr><th>NVIDIA: RTX 5070 (12 GB), Ryzen 5 7600, 64 GB RAM</th><th>AMD: RX 9070 XT (16 GB), Ryzen 9 3900X, 47 GB RAM</th></tr>
<tr><td>
| サイズ | 回答の書き出し | プロンプトの読み込み |
| モデルサイズ | 生成速度 | プロンプトの読み込み |
| --- | ---: | ---: |
| **Q2_0** | 94 tokens/s | 2,650 tokens/s |
| **IQ2_XS** | 79 tokens/s | 2,090 tokens/s |
@@ -34,7 +34,7 @@ Strata は **[Qwen3.8-Flash-Next](https://huggingface.co/Qwen/Qwen3.8-Flash-Next
</td><td>
| サイズ | 回答の書き出し | プロンプトの読み込み |
| モデルサイズ | 生成速度 | プロンプトの読み込み |
| --- | ---: | ---: |
| **Q2_0** | 60 tokens/s | 1,160 tokens/s |
| **IQ2_XS** | 52 tokens/s | 1,110 tokens/s |
@@ -43,169 +43,187 @@ Strata は **[Qwen3.8-Flash-Next](https://huggingface.co/Qwen/Qwen3.8-Flash-Next
</td></tr>
</table>
NVIDIA:Q2_0 はエンジン 0.1.36、ほかの行は 0.1.26 で測定(回答 4K、プロンプト 32K)。表の全体は
[DETAILS.md](docs/DETAILS.md#speed-measured) にあります。VRAM が多いカードほど速くなります。RTX 3090(24 GB)なら
毎秒およそ 100-140 トークンで書き出せるはずです。長いチャットやほかのカードについて:[モデルごとの速度](docs/MODELS.md#how-fast-is-each-size)、
[コミュニティの測定結果](docs/COMMUNITY_BENCHMARKS.md)。
NVIDIA の測定には、Q2_0 のみエンジン 0.1.36、それ以外は 0.1.26 を使用しています(回答 4K、プロンプト 32K)。測定結果の詳細は
[DETAILS.md](docs/DETAILS.md#speed-measured) をご覧ください。VRAM の容量が大きいカードほど高速で、RTX 3090(24 GB)なら
毎秒およそ 100-140 トークンの生成速度が見込めます。長いチャットや他のカードでの性能については、[モデルごとの速度](docs/MODELS.md#how-fast-is-each-size)や
[コミュニティの測定結果](docs/COMMUNITY_BENCHMARKS.md)を参照してください。
<p align="center"><a href="https://buymeacoffee.com/strataengine"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="50"></a><br>
<sub>Strata は無料です。あなたの PC でうまく動いたら、コーヒー 1 杯の支援が開発を続ける力になります。</sub></p>
<sub>Strata は無料で使えます。お使いの PC で快適に動いたら、コーヒー 1 杯分のご支援が開発を続ける励みになります。</sub></p>
## 必要なもの
| | |
| --- | --- |
| **グラフィックカード** | **NVIDIA** GeForce RTX 20、30、40、50 シリーズ、または **AMD** Radeon RX 7900 XT / XTX、RX 7800 XT / 7700 XT、RX 9060 XT、RX 9070 / 9070 XT、Radeon AI PRO R9700、RX 6800 / 6900 シリーズ。**VRAM 12 GB 以上**が必要です。 |
| **RAM** | 32 GB 以上。RAM の量で[使えるモデル](#どのモデルを選べばいい)が決まります。64 GB あればすべてのサイズが動きます。 |
| **ディスク** | 空き容量が約 80 GB。できれば SSD を使ってください。初回の起動がずっと速くなります。 |
| **OS** | Windows 10 / 11 または Linux。NVIDIA または AMD の最新のグラフィックドライバー。 |
| **RAM** | 32 GB 以上。[利用できるモデル](#どのモデルを選べばいい)は RAM の容量によって異なります。64 GB あれば、どのサイズも利用できます。 |
| **ディスク** | 約 80 GB の空き容量。SSD を使うと初回の起動が大幅に速くなるため、おすすめです。 |
| **OS** | Windows 10 / 11 または Linux。NVIDIA または AMD の最新のグラフィックドライバーも必要です。 |
ほかに必要なものはすべてインストーラーが用意します。2 枚や 3 枚のカードでモデルを分担することもできます([マルチ GPU](docs/MULTI_GPU.md))。
その他の必要なソフトウェアは、インストーラーが用意します。2 枚または 3 枚のカードにモデルを分散させることもできます([マルチ GPU](docs/MULTI_GPU.md))。
試験的なサポート。コミュニティのメンバーが自分のマシンで書き、テストしたものです:
以下のハードウェアにも試験的に対応しています。いずれもコミュニティのメンバーが手元のマシンで実装・テストしたものです。
- **古いグラフィックカード**(Tesla P40 / V100、GTX 10、Radeon VII / MI50、RX 6700 XT、RX 5500 XT):[Older GPUs](docs/OLDER_GPUS.md)。
- **Intel Arc**(Linux でソースからビルド):[Intel Arc](docs/INTEL_ARC.md)。
- **AMD Ryzen AI Max(Strix Halo)**(Linux でソースからビルド):[Strix Halo](docs/STRIX_HALO.md)。
- **AVX2 のない古いプロセッサー**:動きますが、遅いです。[Older CPUs](docs/INSTALL.md#older-cpus-experimental)。
- **旧世代のグラフィックカード**(Tesla P40 / V100、GTX 10、Radeon VII / MI50、RX 6700 XT、RX 5500 XT):[旧世代 GPU の対応状況](docs/OLDER_GPUS.md)。
- **Intel Arc**(Linux でソースからビルド):[Intel Arc の対応状況](docs/INTEL_ARC.md)。
- **AMD Ryzen AI Max(Strix Halo)**(Linux でソースからビルド):[Strix Halo の対応状況](docs/STRIX_HALO.md)。
- **AVX2 非対応の旧世代 CPU**:動作しますが、速度は遅くなります。[旧世代 CPU の対応状況](docs/INSTALL.md#older-cpus-experimental)を参照してください。
全リスト:[docs/INSTALL.md](docs/INSTALL.md#what-you-need)。
必要な環境の一覧は、[docs/INSTALL.md](docs/INSTALL.md#what-you-need)をご覧ください。
## インストール
### AI にセットアップしてもらう
AI コーディングアシスタント(Claude Code、Cursor、Codex、GitHub Copilot など)を使っていますか? これを貼り付けてください:
Claude Code、Cursor、Codex、GitHub Copilot などの AI コーディングアシスタントを使っている場合は、次の文を貼り付けてください。
```text
Set up Strata on this PC for me: https://github.com/Niko1221/Strata - follow docs/AI_SETUP.md in that repository.
```
AI がグラフィックカード、RAM、ディスクを調べて、合うモデルを選びます。それからインストールして起動し、
アプリのつなぎ方を教えてくれます。AI ツールは Strata の [MCP サーバー](docs/MCP_SERVER.md) を通じて、
Strata のインストール、起動、停止もできます。
AI がグラフィックカード、RAM、ディスクを確認して、PC に合ったモデルを選びます。インストールと起動を行い、
アプリとの接続方法も案内します。また、Strata の [MCP サーバー](docs/MCP_SERVER.md) を使えば、
AI ツールから Strata のインストール・起動・停止を行えます。
### 自分でやる
[Strata をダウンロード](https://github.com/Niko1221/Strata/archive/refs/heads/main.zip)して展開します(または `git clone` します)。
**Windows:** **`START-HERE.bat`** をダブルクリック。**Linux:** Strata フォルダーで **`./setup.sh`** を実行します。
[Strata をダウンロード](https://github.com/Niko1221/Strata/archive/refs/heads/main.zip)して展開します(`git clone` でも構いません)。
**Windows:** **`START-HERE.bat`** をダブルクリックします。**Linux:** Strata フォルダーで **`./setup.sh`** を実行します。
手順は NVIDIA でも AMD でも同じです。インストーラーがカードを見つけて、それに合うエンジンを用意します。
いくつか質問があります:
**Mac(Apple シリコン、M1〜M5、macOS 15 以降):** まず一度だけ Apple の Command Line Tools をインストールします(ターミナルで `xcode-select --install`。Xcode 本体は不要です)。次に Strata フォルダーでターミナルを開き、**`./setup.sh`** を実行します。Mac 用エンジンをお使いの Mac 上でビルドし(約 7 分)、同じ質問をしてからモデルをダウンロードして起動します。次回からは `./setup.sh` ですぐに起動します。どのサイズが Mac に合うかと速度:[docs/MAC.md](docs/MAC.md)。
- どのモデルを、どのサイズで使うか
- コンテキストをどのくらいにするか(モデルが覚えておけるテキストの量)
- 画像を読ませるかどうか
NVIDIA でも AMD でも手順は同じです。インストーラーがカードを検出し、対応するエンジンを用意します。
続いて、次の項目を設定します。
毎回 Enter を押せば、おすすめの答えになります。そのあとモデル(約 70 GB)をダウンロードして起動します。
ダウンロードが止まったら、もう一度実行してください。続きから再開します。ブラウザーで Strata アプリが
`http://127.0.0.1:8080` に開きます。
- 使用するモデルとサイズ
- コンテキストの長さ(モデルが覚えておけるテキストの量)
- 画像を読み取る機能を使うかどうか
> **モデルの起動中、1-3 分ほど PC が重くなったり、反応しなくなったりすることがあります**(初回がいちばん長いです)。
> Strata は 35-55 GB を RAM に読み込み、その一部をグラフィックカード用に固定します。これは正常です。
> ウィンドウを閉じずに待ってください。Strata が何をしているかはウィンドウに表示されます。
各項目で Enter を押すと、推奨設定が選ばれます。設定が終わるとモデル(約 70 GB)をダウンロードし、起動します。
ダウンロードが途中で止まった場合は、もう一度実行すると続きから再開できます。起動が完了すると、ブラウザーで
`http://127.0.0.1:8080` が開き、Strata の画面が表示されます。
**次回からは** `START-HERE.bat`(または `./setup.sh`)をもう一度実行します。すぐに起動し、同じものを 2 回ダウンロードすることはありません。
モデルを止めるときはウィンドウを閉じます。`UPDATE.bat`(`./update.sh`)を使うと、Strata を起動せずに更新できます。
更新、Docker、複数のカード、ファイルの保存場所、すべてのオプションについて:[docs/INSTALL.md](docs/INSTALL.md)。
> **モデルの起動中は、1-3 分ほど PC の動作が遅くなったり、応答しなくなったりすることがあります**(初回は特に時間がかかります)。
> Strata が 35-55 GB のデータを RAM に読み込み、その一部をグラフィックカード用に固定(ピン留め)しているためです。
> 正常な動作なので、ウィンドウに表示される処理状況を確認しながら、閉じずにお待ちください。
**次回からは** `START-HERE.bat`(または `./setup.sh`)を実行するだけですぐに起動できます。2 回目以降は、ダウンロード済みのファイルを再度取得する必要はありません。
モデルを停止するにはウィンドウを閉じてください。`UPDATE.bat`(`./update.sh`)を使うと、Strata を起動せずに更新できます。
更新方法や Docker、複数のカードの使い方、ファイルの保存先、各種オプションについては、[docs/INSTALL.md](docs/INSTALL.md)をご覧ください。
## どのモデルを選べばいい
インストーラーが RAM に合わせてひとつ勧めます。同じモデルにも、圧縮の強さが違う複数のサイズがあります。
小さいサイズほど速く、大きいサイズほど少し賢くなります。
インストーラーが RAM の容量に合ったモデルをおすすめします。同じモデルでも、圧縮率によって複数のサイズが用意されています。
サイズが小さいほど高速に動作し、大きいほど回答の品質が少し高くなります。
| RAM | 選ぶもの | 理由 |
| RAM | おすすめのモデル | 選ぶ理由 |
| --- | --- | --- |
| **32 GB** | **Coder** | 32 GB に収まり、コード向けに作られている(24 GB のカードなら Q2_0 と IQ2_XS も動く) |
| **48 GB** | **IQ2_XS**(または最速の Q2_0) | 大きいサイズは収まらない |
| **64 GB** | **IQ2_XS**(おすすめ)、または IQ3_XXS / IQ3_S | すべてのサイズが収まる。IQ3_S がいちばん賢く、いちばん遅い |
| **96 GB 以上** | **IQ3_S**、または Unsloth の UD-IQ4_XS(約 4-bit) | ほかのものを全部開いたままでも、最大のサイズが入る余裕がある |
| **32 GB** | **Coder** | 32 GB で動作するコーディング向けモデル(24 GB のカードがあれば Q2_0 と IQ2_XS も動作) |
| **48 GB** | **IQ2_XS**(速度優先なら Q2_0) | これより大きいサイズはメモリに収まらない |
| **64 GB** | **IQ2_XS**(おすすめ)、または IQ3_XXS / IQ3_S | どのサイズも利用可能。IQ3_S は回答の品質が最も高い一方、速度は最も遅い |
| **96 GB 以上** | **IQ3_S**、または Unsloth の UD-IQ4_XS(約 4-bit) | 他のアプリを開いたままでも、最大サイズのモデルを動かせるだけの余裕がある |
- **[Coder](docs/MODELS.md#coder):** エキスパートを半分取り除いたコーディング向け版です。フルモデルの SWE-bench Verified スコアの
91% に届き(作者による測定)、32 GB の RAM に収まります。コード以外では弱く、中国語などの CJK のテキストも苦手です(#438)。
そうした用途には、すべてのエキスパートを残している Q2_0、IQ2_XS、IQ3_S を選んでください。
- **[Swift 1.5](docs/MODELS.md#swift-15):** 答える前に考える時間がずっと短いファインチューン版です。
ほぼ同じ品質のまま、答えが早く返ってきます。
- **[Unsloth UD-IQ4_XS](docs/MODELS.md#unsloth-ud-iq4_xs):** Unsloth の約 4-bit 版で、品質は IQ3_S と UD-Q4_K_XL の間です。
ダウンロードは 94 GB。RAM が約 80 GB 未満だと、答えている間に Strata がその一部を SSD から読むので遅くなります(NVMe SSD が有効です)。
- **[Unsloth UD-Q4_K_XL](docs/MODELS.md#unsloth-ud-q4_k_xl-experimental)**(試験的):フルモデルにいちばん近いものです。
ただし答えている間、Strata はその大部分を SSD から読むので、64 GB の PC では毎秒 7-8.5 トークンしか書き出せません。
- **[OrcaRouter's Uncensored IQ3_XXS](docs/MODELS.md#orcarouter-uncensored-iq3_xxs):** 手動でセットアップします。
インストーラーのメニューにはありません。
- **[Coder](docs/MODELS.md#coder):** エキスパートを半分に減らしたコーディング向けモデルです。SWE-bench Verified ではフルモデルのスコアの
91% を達成しており(開発者による測定)、32 GB の RAM で動作します。ただし、コード以外の用途では性能が劣り、中国語などの CJK 言語の処理も苦手です(#438)。
こうした用途には、すべてのエキスパートを残した Q2_0、IQ2_XS、IQ3_S を選んでください。
- **[Swift 1.5](docs/MODELS.md#swift-15):** 回答前の思考時間が大幅に短くなるようファインチューニングしたモデルです。
回答の品質をほぼ保ったまま、より短い時間で答えが返ってきます。
- **[Unsloth UD-IQ4_XS](docs/MODELS.md#unsloth-ud-iq4_xs):** Unsloth による約 4-bit のモデルです。回答の品質は IQ3_S と UD-Q4_K_XL の中間です。
ダウンロード容量は 94 GB です。RAM が約 80 GB 未満の場合、回答の生成中にモデルの一部を SSD から読み込むため、速度が落ちます(NVMe SSD を使うと改善します)。
- **[Unsloth UD-Q4_K_XL / UD-Q5_K_XL / UD-Q6_K_XL / Q8_0](docs/MODELS.md#unsloths-files-ud-iq4_xs-to-q8_0):** 4〜8 ビットで、フルモデルにより近いモデルです
(次のトークンが Q8_0 と一致する割合は 93〜95%)。すべてのエキスパートが RAM に収まる場合(UD-Q4_K_XL で約 88 GB、
Q8_0 で約 136 GB)は高速です。RAM が足りない場合は回答の生成中に一部を SSD から読み込むため、大幅に遅くなります
(RAM が 64 GB の PC で UD-Q4_K_XL は毎秒 7-8.5 トークン程度)。
- **[OrcaRouter's Uncensored IQ3_XXS](docs/MODELS.md#orcarouter-uncensored-iq3_xxs):** 手動でのセットアップが必要です。
インストーラーのメニューからは選べません。
サイズ、ダウンロード、どれがどこに収まるかについて:[docs/MODELS.md](docs/MODELS.md)。あとで別のモデルを追加するには
`SETUP.bat`(Linux:`./setup.sh --setup`)を実行します。
各サイズのダウンロード情報や必要なメモリ容量は、[docs/MODELS.md](docs/MODELS.md)をご覧ください。後から別のモデルを追加する場合は、
`SETUP.bat`(Linux:`./setup.sh --setup`)を実行してください。
## 使い方
<p align="center"><img src="docs/media/runpagoda.png" width="900" alt="Strata アプリの Monitor タブと、その横で動くコーディングエージェント"><br>
<sub>Strata アプリの <b>Monitor</b>(左)。コーディングエージェントが動画の五重塔の庭を書いているところ(右)</sub></p>
<p align="center"><img src="docs/media/runpagoda.png" width="900" alt="Strata の Monitor タブ(左)と、コードを生成するコーディングエージェント(右)"><br>
<sub>動画に登場する五重塔の庭を作成中の画面。左が Strata の <b>Monitor</b>、右がコードを生成しているコーディングエージェント</sub></p>
- **ブラウザーで:** `http://127.0.0.1:8080` を開きます。**Chat**、モデルと GPU/CPU/RAM の様子をリアルタイムで見る **Monitor**、
設定とアドレスが載った **About** があります。
- **アプリやコーディングエージェントから:** 「OpenAI-compatible」プロバイダーを追加し、ベース URL に
**`http://127.0.0.1:8080/v1`** を指定します。API キーとモデル名は何でもかまいません。
- Anthropic の API を使うアプリ:`http://127.0.0.1:8080/v1/messages`(Claude Code:
`ANTHROPIC_BASE_URL=http://127.0.0.1:8080`)。
- Codex CLI など OpenAI Responses API を使うアプリ:`/v1/responses`
- **ブラウザーで使う:** `http://127.0.0.1:8080` を開きます。チャット用の **Chat**、モデルや GPU/CPU/RAM の状態をリアルタイムで確認できる **Monitor**、
設定や接続先のアドレスを確認できる **About** の各タブがあります。
- **アプリやコーディングエージェントと連携する:** 「OpenAI-compatible」プロバイダーを追加し、ベース URL に
**`http://127.0.0.1:8080/v1`** を指定します。API キーとモデル名には任意の値を指定できます。
- Anthropic API を使うアプリ:`http://127.0.0.1:8080/v1/messages`(Claude Code では
`ANTHROPIC_BASE_URL=http://127.0.0.1:8080` を設定)。
- Codex CLI など、OpenAI Responses API を使うアプリ:`/v1/responses`
([設定方法](docs/DETAILS.md#the-responses-api-and-codex-cli))。
- **思考(Thinking):** チャットのメニュー、またはアプリの「reasoning effort」で **off、low、medium、high** を選びます。
off がいちばん速く、high は難しい質問に向いています。
- **画像:** セットアップで「Images?」に yes と答えます。そのあとチャットで **Picture** をクリックするか、アプリで画像を添付します。
AMD のカードは、Linux ではプロセッサーを使って画像を読みます。Windows ではまだ読めません。
- **スマートフォンや別の PC から:** `START-HERE.bat --setup --host 0.0.0.0 --api-key <secret>`。キーは必ず設定してください。
- **リクエストは 1 つずつ:** 初期設定では Strata は 1 つのリクエストに答え、ほかは待ちます。複数に同時に答えるには
`"parallel": 2` を設定します([BATCHING.md](docs/BATCHING.md))。12 GB のカードでは、それぞれの回答が遅くなります。
- **長いプロンプト:** Strata はチャットの最初のメッセージをすべて読みます。30,000 トークンあたり約 1 分かかります。
2 通目以降のメッセージは数秒で始まります。
- **思考(Thinking)の設定:** チャットのメニュー、または連携先アプリの「reasoning effort」で **off、low、medium、high** から選びます。
off が最も速く、難しい質問には high が向いています。
- **画像を読み取る:** セットアップ時に「Images?」で yes を選びます。その後、チャットの **Picture** ボタンをクリックするか、連携先のアプリで画像を添付してください。
AMD のカードを使う場合、Linux では CPU で画像を読み取ります。Windows ではまだ画像の読み取りに対応していません。
- **スマートフォンや別の PC から使う:** `START-HERE.bat --setup --host 0.0.0.0 --api-key <secret>` で起動します。API キーは必ず設定してください。
- **リクエストは 1 つずつ:** 標準設定では 1 つずつ処理し、それ以外のリクエストは順番を待ちます。同時に処理するには、
`"parallel": 2` を設定してください([BATCHING.md](docs/BATCHING.md))。12 GB のカードでは、リクエストごとの回答速度が落ちます。
- **長いプロンプトを送る:** チャットの最初のメッセージは全文を読み込むため、30,000 トークンあたり約 1 分かかります。
2 通目以降は数秒で応答が始まります。
詳しくは:[チャットの保存場所](docs/INSTALL.md#where-things-are-stored)、[API](docs/DETAILS.md#using-it)。
[チャットの保存場所](docs/INSTALL.md#where-things-are-stored)や[API の詳細](docs/DETAILS.md#using-it)も参照してください。
### オプション:モデル全体が RAM に収まる場合、GPU 1 枚でさらに高速化
2 つのオプトイン設定です(RubenTorney 氏による #1904 と #1905)。GPU を 1 枚使い、RAM にすべてのエキスパートが収まる場合(Strata の arena モード。例:64 GB の PC で Q2_0 や IQ3_XXS)に効果があります。Strata のデータフォルダーにある設定ファイル `strata-<model>.json`([場所](docs/INSTALL.md#where-things-are-stored))を開き、次を追加します:
- **生成の高速化:** `"args"` リストに `"--adapt-async", "1"`。エキスパートキャッシュの更新が回答を止めずに補助スレッドで行われます。RTX 5070(Windows、Q2_0)での実測:生成 +4〜5%、コードや長文では +7〜10%。回答はデフォルトとわずかに異なる場合があります(実行ごとには同じです)。
- **Windows でのプロンプト読み込みの高速化:** `"env"` ブロックに `"STRATA_PIN_BY_NEED": "1"`。Windows はGPU 用に RAM の約半分しか固定できないため、この設定で GPU が本当に必要とするエキスパートから先に固定します。RTX 5070 での実測:プロンプト読み込み +4.4%。
```json
"args": [ ..., "--adapt-async", "1" ],
"env": { "STRATA_PIN_BY_NEED": "1" }
```
変更後は Strata を再起動してください(`START-HERE.bat` または `./setup.sh`)。元に戻すには、2 つの項目を削除します。
## うまくいかないとき
- **Strata の初回起動で PC が固まった。** モデルの読み込み中はよくあることです。ウィンドウを閉じずに待ってください。
10 分たっても固まったまま? PC を再起動し、ほかのプログラムを閉じてもう一度試すか、小さいサイズを選んでください。
- **ダウンロードやインストールの途中で止まった。** `START-HERE.bat`(または `./setup.sh`)をもう一度実行してください。
止まったところから続きます。
- **とても遅く、ディスクのランプが点滅し続ける。または「the engine stopped unexpectedly」と表示される。** PC の空き RAM が
足りません。ほかのプログラムを閉じるか(ブラウザーは多く使います)、小さいサイズ(Q2_0 または IQ2_XS)を選んでください。
- **ポート 8080 がすでに使われていると表示される。** Strata はもう動いています。そのウィンドウを探してください。
- **初回起動時に PC が応答しなくなる。** モデルの読み込み中は、一時的に応答しなくなることがあります。ウィンドウを閉じずにお待ちください。
10 分たっても応答しない場合は、PC を再起動して他のアプリを閉じてからやり直すか、モデルのサイズを小さくしてください。
- **ダウンロードやインストールが途中で止まる。** `START-HERE.bat`(または `./setup.sh`)をもう一度実行してください。
中断したところから再開できます。
- **動作が極端に遅く、ディスクのアクセスランプが点滅し続ける。または「the engine stopped unexpectedly」と表示される。** RAM の空き容量が不足しています。
ブラウザーなど、RAM を多く使う他のアプリを閉じるか、小さいモデル(Q2_0 または IQ2_XS)を選んでください。
- **ポート 8080 が使用中と表示される。** Strata がすでに起動しています。起動済みのウィンドウを探してください。
ほかの問題と解決方法:[docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md)。それでも解決しない場合は
[issue](https://github.com/Niko1221/Strata/issues) を作成し、Strata フォルダーにある `strata-<model>.log` を添付してください。
セキュリティの問題を見つけたら、非公開で報告してください:[SECURITY.md](SECURITY.md)。
その他の問題と対処方法は、[docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md)をご覧ください。解決しない場合は
[Issue](https://github.com/Niko1221/Strata/issues) を作成し、Strata フォルダー内の `strata-<model>.log` を添付してください。
セキュリティ上の問題は、[SECURITY.md](SECURITY.md)の手順に従って非公開で報告してください。
## しくみ
このようなモデルは、ふつう数百ギガバイトのグラフィックメモリを持つサーバーで動きます。あなたのグラフィックカードは
12-24 GB です。Strata は **PC 全体で作業を分担する** ことで、モデルを収めています。台所を思い浮かべてください。
いつも使う道具は調理台に置き、残りは食料庫にしまっておきます。
この規模のモデルは通常、数百ギガバイトの GPU メモリを搭載したサーバーで動かします。一方、手元のグラフィックカードのメモリは
12-24 GB 程度です。Strata は **PC 全体で処理を分担する** ことで、こうした環境でもモデルを動かせるようにしています。
台所で、よく使うものは調理台に置き、それ以外は食品庫にしまっておくような仕組みです。
<p align="center"><img src="docs/media/how-it-works.svg" width="860" alt="モデルの 24,576 個のエキスパート:よく使うものはグラフィックカードに、すべては RAM に、ルックアップテーブルは SSD に"></p>
<p align="center"><img src="docs/media/how-it-works.svg" width="860" alt="24,576 個のエキスパートのうち、よく使うものをグラフィックカードに配置。全エキスパートは RAM に、ルックアップテーブルは SSD に保持"></p>
- **モデルは 24,576 個の小さな専門家(「エキスパート」)のチームです。** 1 語ごとに必要なのはそのうち 10 個だけです。
- **グラフィックカード** は、よく使われる数千個のエキスパートを持ちます。**RAM** はすべてのエキスパートを持ち、
**プロセッサー** が残りを同時に処理します。**SSD** は大きなルックアップテーブルを持ちます。
- **モデルは「エキスパート」と呼ばれる 24,576 個の小さな処理単位から構成されています。** 1 語の生成に必要なのは、このうち 10 個だけです。
- **グラフィックカード** に、使用頻度の高い数千個のエキスパートを置きます。**RAM** にはすべてのエキスパートを保持し、
**CPU** が残りの処理を並行して担当します。**SSD** には大きなルックアップテーブルを保存します。
<p align="center"><img src="docs/media/guess-and-check.svg" width="860" alt="小さなヘルパーが次の単語を予想し、大きなモデルがまとめて確認して正しいものを残す"></p>
<p align="center"><img src="docs/media/guess-and-check.svg" width="860" alt="小さな補助モデルが次の数語を予測し、大きなモデルがまとめて検証。正しい予測だけを採用する"></p>
- **予想してから確認:** 小さなヘルパーが次の数語を予想します。大きなモデルがそれをまとめて確認します。
答えは同じまま、1.6-1.8x 早く返ってきます。
- **長いテキストは大きなまとまりで読みます**(一度に最大 8,192 トークン)。速さは毎秒 1,000 トークン以上です。
- **予測してから検証:** 小さな補助モデルが次の数語を予測し、大きなモデルがまとめて検証します。
回答を変えずに、生成速度を 1.6-1.8 倍に高められます。
- **長いテキストはまとめて読み込みます**(一度に最大 8,192 トークン)。読み込み速度は毎秒 1,000 トークンを超えます。
もっと詳しい説明:[docs/HOW_IT_WORKS.md](docs/HOW_IT_WORKS.md)。各部分とその数値:
[詳細](docs/DETAILS.md#how-it-works)と[論文](docs/paper/Strata-Paper.pdf)。
仕組みについては、[docs/HOW_IT_WORKS.md](docs/HOW_IT_WORKS.md)で詳しく説明しています。各処理の詳細や測定値は、
[技術資料](docs/DETAILS.md#how-it-works)と[論文](docs/paper/Strata-Paper.pdf)をご覧ください。
## クレジットとライセンス
モデルは Qwen チームの [Qwen3.8-Flash-Next](https://huggingface.co/Qwen/Qwen3.8-Flash-Next) です。
圧縮は [ISTA-DASLab](https://huggingface.co/ISTA-DASLab/Qwen3.8-Flash-Next-GSQ-RCO-GGUF)、UkisAI(Swift 1.5)、
Unsloth によるものです。Strata は [llama.cpp / ggml](https://github.com/ggml-org/llama.cpp) の一部を使っています。すべてのクレジット:
[docs/HOW_IT_WORKS.md](docs/HOW_IT_WORKS.md#credits)。Strata は [MIT License](LICENSE) のオープンソースです。一部のパーツと
すべてのモデルには、それぞれ独自のライセンスがあります([どれか](docs/HOW_IT_WORKS.md#license))。
使用しているモデルは、Qwen チームが開発した [Qwen3.8-Flash-Next](https://huggingface.co/Qwen/Qwen3.8-Flash-Next) です。
[ISTA-DASLab](https://huggingface.co/ISTA-DASLab/Qwen3.8-Flash-Next-GSQ-RCO-GGUF)、UkisAI(Swift 1.5)、Unsloth が提供する圧縮版を利用しています。
Strata は [llama.cpp / ggml](https://github.com/ggml-org/llama.cpp) の一部も使用しています。クレジットの一覧は
[docs/HOW_IT_WORKS.md](docs/HOW_IT_WORKS.md#credits)をご覧ください。Strata は [MIT License](LICENSE) で公開されていますが、一部の構成要素と
各モデルには、それぞれ別のライセンスが適用されます([ライセンスの詳細](docs/HOW_IT_WORKS.md#license))。
## Strata を支援する
Strata は無料のオープンソースです。役に立ったら、開発を支援していただけます:
Strata は無料で使えるオープンソースソフトウェアです。役に立ったら、開発へのご支援をお願いします。
<p align="center"><a href="https://buymeacoffee.com/strataengine"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="50"></a></p>
+33 -2
View File
@@ -66,6 +66,7 @@ Experimental, written and tested by community members on their own machines:
- **Older graphics cards** (Tesla P40 / V100, GTX 10, Radeon VII / MI50, RX 6700 XT, RX 5500 XT): [Older GPUs](docs/OLDER_GPUS.md).
- **Intel Arc**, built from source on Linux: [Intel Arc](docs/INTEL_ARC.md).
- **Apple Silicon Macs (M1 to M5)**, built from source by `./setup.sh` (the Metal engine): [Mac](docs/MAC.md).
- **AMD Ryzen AI Max (Strix Halo)**, built from source on Linux: [Strix Halo](docs/STRIX_HALO.md).
- **Older processors without AVX2**: they work, but slowly. [Older CPUs](docs/INSTALL.md#older-cpus-experimental).
@@ -90,6 +91,12 @@ you how to connect your apps. AI tools can also install, start and stop Strata t
[Download Strata](https://github.com/Niko1221/Strata/archive/refs/heads/main.zip) and unzip it (or `git clone` it).
**Windows:** double-click **`START-HERE.bat`**. **Linux:** run **`./setup.sh`** in the Strata folder.
**Mac (Apple Silicon, M1 to M5, macOS 15 or newer):** install Apple's Command Line Tools once
(`xcode-select --install` in Terminal; Xcode itself is not needed). Then open Terminal in the Strata folder and run
**`./setup.sh`**. It builds the Mac engine on your Mac (about 7 minutes), asks the same questions, downloads the model
and starts it. Next time, `./setup.sh` starts it right away. Which size fits your Mac and how fast it is:
[docs/MAC.md](docs/MAC.md).
The steps are the same for NVIDIA and AMD. The installer finds your card and sets up the right engine for it. It
asks you a few questions:
@@ -109,6 +116,8 @@ download stops, run it again: it continues where it left off. Your browser opens
its window to stop the model. `UPDATE.bat` (`./update.sh`) updates Strata without starting it. Updating, Docker,
several cards, where the files go and every option: [docs/INSTALL.md](docs/INSTALL.md).
**Is it fast on your PC?** Run `BENCH.bat` (`./bench.sh`): about 5-10 minutes, it measures chat, 4K/16K prompts and an agent-style session with your own settings and writes a report to share ([how](docs/COMMUNITY_BENCHMARKS.md#run-the-benchmark)).
## Which model should I pick?
The installer recommends one for your RAM. The same model comes in several sizes, compressed more or less. Smaller
@@ -129,8 +138,10 @@ sizes are faster. Larger sizes are a bit smarter.
- **[Unsloth UD-IQ4_XS](docs/MODELS.md#unsloth-ud-iq4_xs):** Unsloth's ~4-bit version, between IQ3_S and
UD-Q4_K_XL in quality. A 94 GB download. With less than ~80 GB of RAM, Strata reads part of it from the SSD
while it answers, so it is slower there (an NVMe SSD helps).
- **[Unsloth UD-Q4_K_XL](docs/MODELS.md#unsloth-ud-q4_k_xl-experimental)** (experimental): the closest to the full
model. But Strata reads most of it from the SSD while it answers, so it writes only 7-8.5 tokens/s on a 64 GB PC.
- **[Unsloth UD-Q4_K_XL, UD-Q5_K_XL, UD-Q6_K_XL and Q8_0](docs/MODELS.md#unsloths-files-ud-iq4_xs-to-q8_0):**
4- to 8-bit, closer to the full model (93-95% the same next token as Q8_0). Fast where every expert fits in RAM
(~88 GB for UD-Q4_K_XL up to ~136 GB for Q8_0); with less RAM Strata reads part of them from the SSD while it
answers, which is much slower (7-8.5 tokens/s for UD-Q4_K_XL on a 64 GB PC).
- **[OrcaRouter's Uncensored IQ3_XXS](docs/MODELS.md#orcarouter-uncensored-iq3_xxs):** you set it up by hand. It is
not in the installer's menu.
@@ -162,6 +173,26 @@ Sizes, downloads and what fits where: [docs/MODELS.md](docs/MODELS.md). To add a
More: [where your chats are stored](docs/INSTALL.md#where-things-are-stored), [the API](docs/DETAILS.md#using-it).
### Optional: more speed on one card when the whole model fits in RAM
Two opt-in settings (by RubenTorney, #1904 and #1905). They help when you run one graphics card and your RAM holds
every expert (Strata's arena mode, for example Q2_0 or IQ3_XXS on a 64 GB PC). Open your config,
`strata-<model>.json` in the Strata data folder ([where](docs/INSTALL.md#where-things-are-stored)), and add:
- **Faster decode:** `"--adapt-async", "1"` to the `"args"` list. The expert cache then updates on a helper thread
instead of pausing the answer. Measured on an RTX 5070 (Windows, Q2_0): +4-5% decode, +7-10% on code and long
documents. Answers can differ slightly from the default (they stay the same from run to run).
- **Faster prompt reading on Windows:** `"STRATA_PIN_BY_NEED": "1"` in the `"env"` block. Windows can lock only about
half the RAM for the graphics card; this locks the experts the card actually needs first. Measured on the RTX 5070:
+4.4% prompt reading.
```json
"args": [ ..., "--adapt-async", "1" ],
"env": { "STRATA_PIN_BY_NEED": "1" }
```
Restart Strata (`START-HERE.bat` or `./setup.sh`) after the change. To undo, remove the two entries.
## Something went wrong?
- **My PC froze the first time Strata started.** This is normal while it loads the model. Wait, and don't close the
+20 -3
View File
@@ -90,6 +90,8 @@ conectar seus apps. Ferramentas de IA também podem instalar, iniciar e parar o
[Baixe o Strata](https://github.com/Niko1221/Strata/archive/refs/heads/main.zip) e descompacte (ou use `git clone`).
**Windows:** clique duas vezes em **`START-HERE.bat`**. **Linux:** rode **`./setup.sh`** na pasta do Strata.
**Mac (Apple Silicon, M1 a M5, macOS 15 ou mais recente):** instale uma vez as Command Line Tools da Apple (`xcode-select --install` no Terminal; o Xcode em si não é necessário). Depois abra o Terminal na pasta do Strata e rode **`./setup.sh`**. Ele compila o motor do Mac no seu Mac (uns 7 minutos), faz as mesmas perguntas, baixa o modelo e o inicia. Da próxima vez, `./setup.sh` inicia na hora. Qual tamanho cabe no seu Mac e qual a velocidade: [docs/MAC.md](docs/MAC.md).
Os passos são os mesmos para NVIDIA e AMD. O instalador encontra sua placa e configura o engine certo para ela.
Ele faz algumas perguntas:
@@ -130,9 +132,10 @@ Os tamanhos menores são mais rápidos. Os maiores são um pouco mais inteligent
- **[Unsloth UD-IQ4_XS](docs/MODELS.md#unsloth-ud-iq4_xs):** a versão de ~4 bits da Unsloth, entre IQ3_S e
UD-Q4_K_XL em qualidade. Um download de 94 GB. Com menos de ~80 GB de RAM, o Strata lê uma parte dele do SSD
enquanto responde, então ali ele fica mais lento (um SSD NVMe ajuda).
- **[Unsloth UD-Q4_K_XL](docs/MODELS.md#unsloth-ud-q4_k_xl-experimental)** (experimental): o mais próximo do modelo
completo. Mas o Strata lê a maior parte dele do SSD enquanto responde, então ele escreve só 7-8.5 tokens/s num PC
com 64 GB.
- **[Unsloth UD-Q4_K_XL, UD-Q5_K_XL, UD-Q6_K_XL e Q8_0](docs/MODELS.md#unsloths-files-ud-iq4_xs-to-q8_0):** de 4 a 8 bits, mais próximos do modelo
completo (93-95% o mesmo próximo token que o Q8_0). Rápidos quando todos os especialistas cabem na RAM (~88 GB para
o UD-Q4_K_XL até ~136 GB para o Q8_0); com menos RAM, o Strata lê uma parte do SSD enquanto responde, o que é bem
mais lento (7-8.5 tokens/s para o UD-Q4_K_XL num PC com 64 GB).
- **[OrcaRouter's Uncensored IQ3_XXS](docs/MODELS.md#orcarouter-uncensored-iq3_xxs):** você configura à mão. Ele
não está no menu do instalador.
@@ -165,6 +168,20 @@ Tamanhos, downloads e o que cabe onde: [docs/MODELS.md](docs/MODELS.md). Para ad
Mais: [onde suas conversas ficam salvas](docs/INSTALL.md#where-things-are-stored), [a API](docs/DETAILS.md#using-it).
### Opcional: mais velocidade com uma placa quando o modelo inteiro cabe na RAM
Duas configurações opcionais (de RubenTorney, #1904 e #1905). Elas ajudam quando você usa uma placa de vídeo e sua RAM guarda todos os experts (o modo arena do Strata, por exemplo Q2_0 ou IQ3_XXS num PC com 64 GB). Abra sua configuração `strata-<model>.json` na pasta de dados do Strata ([onde](docs/INSTALL.md#where-things-are-stored)) e adicione:
- **Geração mais rápida:** `"--adapt-async", "1"` na lista `"args"`. O cache de experts passa a ser atualizado numa thread auxiliar em vez de pausar a resposta. Medido numa RTX 5070 (Windows, Q2_0): +4-5% de geração, +7-10% em código e documentos longos. As respostas podem diferir um pouco do padrão (ficam iguais de uma execução para outra).
- **Leitura do prompt mais rápida no Windows:** `"STRATA_PIN_BY_NEED": "1"` no bloco `"env"`. O Windows só consegue travar cerca de metade da RAM para a placa; isto trava primeiro os experts de que a placa realmente precisa. Medido na RTX 5070: +4,4% na leitura do prompt.
```json
"args": [ ..., "--adapt-async", "1" ],
"env": { "STRATA_PIN_BY_NEED": "1" }
```
Reinicie o Strata (`START-HERE.bat` ou `./setup.sh`) depois da mudança. Para desfazer, remova as duas entradas.
## Algo deu errado?
- **Meu PC travou na primeira vez que o Strata iniciou.** Isso é normal enquanto ele carrega o modelo. Espere e não
+19 -2
View File
@@ -88,6 +88,8 @@ Strata 的 [MCP 服务器](docs/MCP_SERVER.md)来安装、启动和停止 Strata
[下载 Strata](https://github.com/Niko1221/Strata/archive/refs/heads/main.zip) 并解压(或者用 `git clone`)。
**Windows:** 双击 **`START-HERE.bat`**。**Linux:** 在 Strata 文件夹里运行 **`./setup.sh`**。
**Mac(Apple 芯片,M1 到 M5,macOS 15 或更新版本):** 先安装一次 Apple 的 Command Line Tools(在终端里运行 `xcode-select --install`;不需要 Xcode 本身)。然后在 Strata 文件夹里打开终端,运行 **`./setup.sh`**。它会在你的 Mac 上编译 Mac 版引擎(大约 7 分钟),问同样的问题,下载模型并启动。下次运行 `./setup.sh` 会马上启动。哪个大小适合你的 Mac、速度如何:[docs/MAC.md](docs/MAC.md)。
NVIDIA 和 AMD 的步骤完全一样。安装程序会识别你的显卡,并装好对应的引擎。它会问你几个问题:
- 用哪个模型、哪个规格,
@@ -122,8 +124,9 @@ NVIDIA 和 AMD 的步骤完全一样。安装程序会识别你的显卡,并
- **[Swift 1.5](docs/MODELS.md#swift-15):** 一个微调版本,回答前思考的时间短得多。你能更早拿到答案,质量基本不变。
- **[Unsloth UD-IQ4_XS](docs/MODELS.md#unsloth-ud-iq4_xs):** Unsloth 的约 4-bit 版本,质量介于 IQ3_S 和 UD-Q4_K_XL 之间。
下载 94 GB。内存少于约 80 GB 时,Strata 回答时要从 SSD 读取其中一部分,所以会更慢(NVMe SSD 有帮助)。
- **[Unsloth UD-Q4_K_XL](docs/MODELS.md#unsloth-ud-q4_k_xl-experimental)**(实验性):最接近完整模型。但 Strata
回答时要从 SSD 读取其中大部分内容,所以在 64 GB 的电脑上每秒只能写 7-8.5 个 token。
- **[Unsloth UD-Q4_K_XL、UD-Q5_K_XL、UD-Q6_K_XL 和 Q8_0](docs/MODELS.md#unsloths-files-ud-iq4_xs-to-q8_0):** 4 到 8 位,更接近完整模型(下一个 token
与 Q8_0 相同的比例为 93-95%)。所有专家都能放进内存时速度很快(UD-Q4_K_XL 约需 88 GB,Q8_0 约需 136 GB);内存不够时,
Strata 回答时要从 SSD 读取一部分,会慢很多(64 GB 的电脑上 UD-Q4_K_XL 每秒 7-8.5 个 token)。
- **[OrcaRouter 的 Uncensored IQ3_XXS](docs/MODELS.md#orcarouter-uncensored-iq3_xxs):** 需要手动设置,不在安装程序的菜单里。
规格、下载以及各配置能装下什么:[docs/MODELS.md](docs/MODELS.md)。以后想再添加模型,运行
@@ -153,6 +156,20 @@ NVIDIA 和 AMD 的步骤完全一样。安装程序会识别你的显卡,并
更多:[聊天记录存在哪里](docs/INSTALL.md#where-things-are-stored)、[API](docs/DETAILS.md#using-it)。
### 可选:整个模型都能放进内存时,单卡再提速
两个可选设置(来自 RubenTorney 的 #1904 和 #1905)。适用于只用一张显卡、并且内存能放下所有专家的情况(Strata 的 arena 模式,例如 64 GB 电脑上的 Q2_0 或 IQ3_XXS)。打开 Strata 数据文件夹里的配置文件 `strata-<model>.json`([在哪里](docs/INSTALL.md#where-things-are-stored)),加入:
- **生成更快:** 在 `"args"` 列表里加 `"--adapt-async", "1"`。专家缓存改在辅助线程里更新,不再暂停回答。在 RTX 5070(Windows,Q2_0)上实测:生成 +4-5%,代码和长文档 +7-10%。回答可能与默认设置略有不同(但每次运行都一样)。
- **Windows 上读取提示更快:** 在 `"env"` 块里加 `"STRATA_PIN_BY_NEED": "1"`。Windows 只能为显卡锁定大约一半的内存;这个设置会先锁定显卡真正需要的专家。在 RTX 5070 上实测:读取提示 +4.4%。
```json
"args": [ ..., "--adapt-async", "1" ],
"env": { "STRATA_PIN_BY_NEED": "1" }
```
修改后重启 Strata(`START-HERE.bat` 或 `./setup.sh`)。要撤销,删掉这两项即可。
## 出问题了?
- **Strata 第一次启动时电脑卡死了。** 加载模型时这是正常的。请耐心等待,不要关闭窗口。
+3 -1
View File
@@ -39,6 +39,8 @@ this PC only. The details and every setting are in [docs/DETAILS.md](docs/DETAIL
- **MCP tools** are opt-in: only the servers you put in the run config, only for requests from Strata's own page
that ask for them. They run with your user's rights, and the model decides when to call them.
- **The request monitor** (`/api-monitor`, which keeps the last prompts and answers in memory) is off unless
`"api_monitor": true` is set.
`"api_monitor": true` is set. Apart from it, the server keeps in its process memory the text and tokens of its
last few prompts, whatever `"api_monitor"` says, to encode the next turn faster; no endpoint shows them, and they
are gone when the server stops.
Strata has not had an outside security audit yet.
+3 -1
View File
@@ -32,7 +32,8 @@ rem All of it in one block: cmd reads a .bat file while it runs it, and the git
if defined DIRTY (
echo You have local changes to tracked files here, so nothing was touched. To move to the new history
echo yourself ^(your untracked files, models and settings stay where they are^):
echo git branch pre-cleanup-backup ^&^& git stash push
echo git branch pre-cleanup-backup
echo git stash push
echo git checkout -B main origin/main
echo then run UPDATE.bat again.
pause
@@ -50,6 +51,7 @@ rem All of it in one block: cmd reads a .bat file while it runs it, and the git
)
call git checkout -q -B %%BR%% origin/main
if errorlevel 1 (
call git branch -D %%BK%% >nul 2>nul
echo.
echo Could not move to the new history ^(the reason is above^): nothing was updated. By hand:
echo git checkout -B main origin/main
Executable
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
# Benchmark this Strata install the way it is used and write a report you can share (docs/COMMUNITY_BENCHMARKS.md).
# It starts the model with your settings (or uses the one already running), takes about 10 minutes and changes nothing.
# Options: --clients 4 (several requests at once), --long (a 32K prompt), --compare <older results folder>.
cd "$(dirname "$0")" || exit 1
if [ -x .venv/bin/python ]; then
exec .venv/bin/python tools/strata_bench.py "$@"
fi
echo "Strata is not set up here yet: run ./setup.sh first."
exit 1
+284
View File
@@ -0,0 +1,284 @@
// Standalone HIP INT8 QSA query-LDS-swizzle component probe.
// Adapted from the cell-probability probe; input generation and full-byte dump are unchanged.
// Build/link in the project with strata_kernels + hip::host (or its HIP runtime target).
// Usage: gfx906_qsa_query_swizzle_probe [nq=32] [ctx=65536] [reps=20] [output.bin] [--masked-pages]
// Output path may instead be supplied by STRATA_QSA_PROBE_OUT. It is required.
// Run candidate environment settings in SEPARATE processes: the dispatcher caches them.
// No prompt-attention entry point, architecture skip, model loading, or repository writes.
#include "strata/kernels/qsa.hpp"
#include "strata/kernels/qsa_decode_attn.hpp"
#include <hip/hip_runtime.h>
#include <algorithm>
#include <cerrno>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <exception>
#include <limits>
#include <numeric>
#include <vector>
namespace k = strata::kernels;
namespace {
constexpr int64_t kBatch = 32;
constexpr size_t kGuard = 64;
constexpr uint64_t kSeed = 0x7161736150524f42ull;
[[noreturn]] void fail(const char* why) {
std::fprintf(stderr, "qsa_query_swizzle_probe: %s\n", why);
std::exit(2);
}
void ck(hipError_t e, const char* what) {
if (e != hipSuccess) {
std::fprintf(stderr, "%s: %s\n", what, hipGetErrorString(e));
std::exit(2);
}
}
#define HIP_CHECK(x) ck((x), #x)
// Fixed integer generator and exact binary fractions avoid library-dependent
// normal distributions and never inspect the candidate environment setting.
struct Rng {
uint64_t state = kSeed;
uint32_t next() {
state ^= state >> 12;
state ^= state << 25;
state ^= state >> 27;
return uint32_t((state * 2685821657736338717ull) >> 32);
}
size_t below(size_t n) { return size_t(next()) % n; }
template <class T> void shuffle(std::vector<T>& v) {
for (size_t n = v.size(); n > 1; --n) std::swap(v[n - 1], v[below(n)]);
}
};
template <class T> struct Device {
T* p = nullptr;
explicit Device(size_t n) { HIP_CHECK(hipMalloc(reinterpret_cast<void**>(&p), n * sizeof(T))); }
explicit Device(const std::vector<T>& v) : Device(v.size()) {
HIP_CHECK(hipMemcpy(p, v.data(), v.size() * sizeof(T), hipMemcpyHostToDevice));
}
~Device() { if (p) (void) hipFree(p); }
Device(const Device&) = delete;
Device& operator=(const Device&) = delete;
};
uint64_t hash_bytes(uint64_t hash, const void* ptr, size_t bytes) {
const auto* p = static_cast<const unsigned char*>(ptr);
for (size_t i = 0; i < bytes; ++i) hash = (hash ^ p[i]) * 1099511628211ull;
return hash;
}
template <class T> void hash_vector(uint64_t& hash, const std::vector<T>& v) {
hash = hash_bytes(hash, v.data(), v.size() * sizeof(T));
}
int64_t positive(const char* text) {
errno = 0;
char* end = nullptr;
const long long n = std::strtoll(text, &end, 10);
if (errno || end == text || *end || n <= 0 || n > INT32_MAX)
fail("nq, ctx, and reps must be positive int32 values");
return int64_t(n);
}
const char* env(const char* name) {
const char* value = std::getenv(name);
return value ? value : "<unset>";
}
std::vector<float> read_checked(const Device<float>& storage, size_t count) {
std::vector<float> host(count + 2 * kGuard);
HIP_CHECK(hipMemcpy(host.data(), storage.p, host.size() * sizeof(float), hipMemcpyDeviceToHost));
for (size_t i = 0; i < host.size(); ++i) {
if (i >= kGuard && i < kGuard + count) {
if (!std::isfinite(host[i])) {
std::fprintf(stderr, "nonfinite or unwritten output at float %zu\n", i - kGuard);
fail("output check failed");
}
} else {
uint32_t bits;
std::memcpy(&bits, &host[i], sizeof(bits));
if (bits != UINT32_MAX) fail("output guard changed");
}
}
return std::vector<float>(host.begin() + kGuard, host.begin() + kGuard + count);
}
int run(int64_t nq, int64_t ctx, int reps, const char* output, bool masked) {
if (ctx < nq) fail("ctx must be >= nq (query positions are ctx-nq through ctx-1)");
const char* lane = std::getenv("STRATA_ATTN_LANECELL");
if (lane && lane[0] == '1') fail("unset STRATA_ATTN_LANECELL or set it to 0 for this probe");
static_assert(sizeof(float) == 4 && std::numeric_limits<float>::is_iec559,
"probe requires IEEE binary32 output");
const k::QsaShapes s = k::qsa_real_shapes();
// Match prefill.cpp: use the model's actual 4-cell page layout.
if (s.n_head != 24 || s.n_head_kv != 2 || s.head_dim != 256 || s.page_size != 4)
fail("unexpected model geometry");
const int64_t hd = s.head_dim, nh = s.n_head, nkvh = s.n_head_kv, ps = s.page_size;
const int64_t pages = (ctx + ps - 1) / ps, rows = pages * nkvh * ps;
const int64_t cap = k::qsa_selection_width(ctx, s);
const size_t count = size_t(nq) * size_t(nh * hd);
Rng rng;
std::vector<int8_t> kq(size_t(rows * hd)), vq(kq.size());
std::vector<uint16_t> ks(size_t(rows * (hd / 64))), vs(ks.size());
for (auto* v : {&kq, &vq})
for (auto& x : *v) x = int8_t(int(rng.next() % 255) - 127);
// Positive finite binary16 scales, directly encoded: [2^-8, 2^-5).
for (auto* v : {&ks, &vs})
for (auto& x : *v) x = uint16_t(0x1c00u + rng.next() % 0x0c00u);
std::vector<int32_t> table(size_t(pages), 0);
std::iota(table.begin(), table.end(), 0);
rng.shuffle(table);
const auto physical = table;
if (masked)
for (int64_t page = 1; page < pages; page += 3) table[size_t(page)] = -1;
// The decode kernel reads ids[c0+t] only for t<n_here, and returns before
// reading IDs for empty chunks. Unused row slots are nevertheless zeroed;
// a final 64-cell initialized guard also avoids an exact allocation end.
// cap remains the actual row stride; no per-row padding is passed as cap.
std::vector<int32_t> ids(size_t(nq * cap) + kGuard, 0);
std::vector<int32_t> steps(size_t(nq * k::kStepCount), 0);
std::vector<float> query(count);
for (auto& x : query) x = float(int(rng.next() % 4096) - 2048) * (1.0f / 1024.0f);
std::vector<int32_t> old_cells;
for (int64_t i = 0; i < nq; ++i) {
const int64_t pos = ctx - nq + i, nkv = pos + 1;
const int64_t width = k::qsa_selection_width(nkv, s);
k::qsa_step_fill(steps.data() + i * k::kStepCount, pos, s);
int32_t* sel = ids.data() + i * cap;
if (width == nkv) {
std::iota(sel, sel + width, 0);
} else {
// Same selection pattern as qsa_prompt_attn_parity: a recent
// 512-cell window plus a sorted older set drifting ~3% per query.
constexpr int64_t recent = 512;
const int64_t older = width - recent;
if (int64_t(old_cells.size()) != older) {
std::vector<int32_t> all(size_t(nkv - recent), 0);
std::iota(all.begin(), all.end(), 0);
rng.shuffle(all);
old_cells.assign(all.begin(), all.begin() + older);
} else {
for (int64_t r = 0; r < older / 32; ++r) {
const int32_t cell = int32_t(rng.below(size_t(nkv - recent)));
if (std::find(old_cells.begin(), old_cells.end(), cell) == old_cells.end())
old_cells[rng.below(size_t(older))] = cell;
}
}
std::copy(old_cells.begin(), old_cells.end(), sel);
std::iota(sel + older, sel + width, int32_t(nkv - recent));
std::sort(sel, sel + width);
}
bool valid_page = false;
for (int64_t c = 0; c < width; ++c) {
if (sel[c] < 0 || sel[c] >= nkv || (c && sel[c - 1] >= sel[c]))
fail("selection must be unique, sorted, and causal");
valid_page |= table[size_t(sel[c] / ps)] >= 0;
}
// Restore a selected logical page if necessary, never allow an
// all-masked query to make a vacuous zero-output equality check pass.
if (!valid_page) {
const size_t page = size_t(sel[0] / ps);
table[page] = physical[page];
}
}
size_t masked_selected = 0;
for (int64_t i = 0; i < nq; ++i)
for (int32_t c = 0; c < steps[size_t(i * k::kStepCount + k::kStepWidth)]; ++c)
masked_selected += table[size_t(ids[size_t(i * cap + c)] / ps)] < 0;
uint64_t input_hash = 14695981039346656037ull;
hash_vector(input_hash, kq); hash_vector(input_hash, vq);
hash_vector(input_hash, ks); hash_vector(input_hash, vs);
hash_vector(input_hash, table); hash_vector(input_hash, ids);
hash_vector(input_hash, steps); hash_vector(input_hash, query);
Device<int8_t> dk(kq), dv(vq);
Device<uint16_t> dks(ks), dvs(vs);
Device<int32_t> dtable(table), dids(ids), dsteps(steps);
Device<float> dq(query), dout(count + 2 * kGuard);
const uint64_t stride = k::qsa_decode_attn_scratch_floats(cap, s);
Device<float> scratch(size_t(std::min(kBatch, nq)) * size_t(stride));
k::QsaAttnPools pools;
pools.k_q = dk.p; pools.v_q = dv.p; pools.k_scale = dks.p; pools.v_scale = dvs.p;
pools.page_table = dtable.p;
HIP_CHECK(hipMemset(dout.p, 0xff, (count + 2 * kGuard) * sizeof(float)));
HIP_CHECK(hipMemset(scratch.p, 0xff, size_t(std::min(kBatch, nq)) * size_t(stride) * sizeof(float)));
auto launch = [&] {
for (int64_t t = 0; t < nq; t += kBatch)
k::qsa_decode_attn_batch(dq.p + t * nh * hd, pools, dids.p + t * cap,
dsteps.p + t * k::kStepCount, cap, s, scratch.p, dout.p + kGuard + t * nh * hd,
std::min(kBatch, nq - t), nullptr);
HIP_CHECK(hipGetLastError());
};
launch();
HIP_CHECK(hipDeviceSynchronize());
const auto first = read_checked(dout, count);
constexpr int warmups = 3;
for (int i = 0; i < warmups; ++i) launch();
HIP_CHECK(hipDeviceSynchronize());
hipEvent_t begin = nullptr, end = nullptr;
HIP_CHECK(hipEventCreate(&begin)); HIP_CHECK(hipEventCreate(&end));
std::vector<float> times(size_t(reps), 0.0f);
for (int i = 0; i < reps; ++i) {
// Excluded from event duration; the last timed invocation must also
// overwrite every logical output element instead of inheriting it.
HIP_CHECK(hipMemsetAsync(dout.p + kGuard, 0xff, count * sizeof(float), nullptr));
HIP_CHECK(hipEventRecord(begin, nullptr));
launch();
HIP_CHECK(hipEventRecord(end, nullptr));
HIP_CHECK(hipEventSynchronize(end));
HIP_CHECK(hipEventElapsedTime(&times[size_t(i)], begin, end));
}
const auto result = read_checked(dout, count);
if (std::memcmp(first.data(), result.data(), count * sizeof(float)) != 0)
fail("first and final invocation differ byte-for-byte within this process");
const uint64_t output_hash = hash_bytes(14695981039346656037ull, result.data(), count * sizeof(float));
std::FILE* file = std::fopen(output, "wb");
if (!file) fail("cannot open output file");
const size_t written = std::fwrite(result.data(), sizeof(float), count, file);
const int close_status = std::fclose(file);
if (written != count || close_status != 0) fail("cannot write complete output file");
std::sort(times.begin(), times.end());
const float median = reps % 2 ? times[size_t(reps / 2)]
: 0.5f * (times[size_t(reps / 2 - 1)] + times[size_t(reps / 2)]);
int device = 0;
hipDeviceProp_t prop{};
HIP_CHECK(hipGetDevice(&device)); HIP_CHECK(hipGetDeviceProperties(&prop, device));
std::printf("device=%s arch=%s nq=%lld ctx=%lld cap=%lld page_size=%lld batch=%lld reps=%d warmups=%d\n",
prop.name, prop.gcnArchName, (long long)nq, (long long)ctx, (long long)cap,
(long long)ps, (long long)kBatch, reps, warmups);
std::printf("QUERY_SWIZZLE=%s LANECELL=%s seed=%016llx masked_pages=%zu masked_selected=%zu\n",
env("STRATA_GFX906_ATTN_QUERY_SWIZZLE"), env("STRATA_ATTN_LANECELL"), (unsigned long long)kSeed,
size_t(std::count(table.begin(), table.end(), -1)), masked_selected);
std::printf("INPUT_FNV1A64=%016llx OUTPUT_FNV1A64=%016llx output_floats=%zu output_bytes=%zu\n",
(unsigned long long)input_hash, (unsigned long long)output_hash, count, count * sizeof(float));
std::printf("PASS finite_written_guards_and_repeat median_ms=%.6f min_ms=%.6f max_ms=%.6f us_per_query=%.6f output=%s\n",
median, times.front(), times.back(), double(median) * 1000.0 / double(nq), output);
HIP_CHECK(hipEventDestroy(begin)); HIP_CHECK(hipEventDestroy(end));
return 0;
}
} // namespace
int main(int argc, char** argv) {
try {
std::vector<const char*> args;
bool masked = false;
for (int i = 1; i < argc; ++i) {
if (std::strcmp(argv[i], "--masked-pages") == 0) masked = true;
else args.push_back(argv[i]);
}
if (args.size() > 4) fail("usage: probe [nq] [ctx] [reps] [output.bin] [--masked-pages]");
const int64_t nq = args.size() > 0 ? positive(args[0]) : 32;
const int64_t ctx = args.size() > 1 ? positive(args[1]) : 65536;
const int reps = args.size() > 2 ? int(positive(args[2])) : 20;
const char* output = args.size() > 3 ? args[3] : std::getenv("STRATA_QSA_PROBE_OUT");
if (!output || !*output) fail("pass output.bin as fourth positional argument or set STRATA_QSA_PROBE_OUT");
return run(nq, ctx, reps, output, masked);
} catch (const std::exception& e) {
std::fprintf(stderr, "qsa_query_swizzle_probe: %s\n", e.what());
return 2;
}
}
+67
View File
@@ -0,0 +1,67 @@
// Linux/x86 CUDA reproducer for #1975. Run "lazy" and "warm" as separate processes.
// See bench/results/2026-10-11-rtx-5090-callback-affinity/README.md for the build command.
#include <cuda_runtime_api.h>
#include <sched.h>
#include <unistd.h>
#include <algorithm>
#include <atomic>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
struct State {
std::atomic<bool> done{false};
cpu_set_t mask{};
};
static void callback(void* p) {
auto* s = (State*) p;
sched_getaffinity(0, sizeof s->mask, &s->mask);
s->done.store(true, std::memory_order_release);
}
static void check(cudaError_t e) {
if (e != cudaSuccess) {
std::fprintf(stderr, "%s\n", cudaGetErrorString(e));
std::exit(1);
}
}
int main(int argc, char** argv) {
const bool warm = argc > 1 && std::strcmp(argv[1], "warm") == 0;
cudaStream_t stream;
check(cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking));
State state;
if (warm) {
check(cudaLaunchHostFunc(stream, callback, &state));
check(cudaStreamSynchronize(stream));
}
cpu_set_t host;
CPU_ZERO(&host);
CPU_SET(0, &host);
if (sched_setaffinity(0, sizeof host, &host) != 0) {
std::perror("sched_setaffinity");
return 1;
}
std::vector<double> times;
for (int i = 0; i < 200; ++i) {
state.done.store(false, std::memory_order_release);
const auto start = std::chrono::steady_clock::now();
check(cudaLaunchHostFunc(stream, callback, &state));
while (!state.done.load(std::memory_order_acquire)) {
asm volatile("pause");
if (std::chrono::steady_clock::now() - start > std::chrono::seconds(5)) return 2;
}
times.push_back(std::chrono::duration<double, std::micro>(std::chrono::steady_clock::now() - start).count());
}
std::sort(times.begin(), times.end());
std::printf("%s: callback affinity:", warm ? "before pin warm-up" : "after pin lazy creation");
for (int i = 0; i < CPU_SETSIZE; ++i)
if (CPU_ISSET(i, &state.mask)) std::printf(" %d", i);
std::printf("; median %.2f us, p95 %.2f us\n", times[100], times[190]);
check(cudaStreamSynchronize(stream));
check(cudaStreamDestroy(stream));
}
+47
View File
@@ -0,0 +1,47 @@
[
{"d":"code","p":"Write a Python function that merges two sorted lists into one sorted list without using sort(). Include type hints and a short docstring."},
{"d":"code","p":"Implement an LRU cache in Python using OrderedDict with get and put methods, and write three unit tests with pytest."},
{"d":"code","p":"Write a JavaScript function debounce(fn, wait) and explain how it differs from throttle, with a small usage example."},
{"d":"code","p":"Write a C++ class template for a fixed-capacity ring buffer with push, pop and size, using std::array. Mention thread-safety."},
{"d":"code","p":"Show a Rust function that reads a file line by line, counts word frequencies in a HashMap and prints the top 5 words."},
{"d":"code","p":"Write a Go HTTP handler that returns JSON {\"status\":\"ok\"} and a middleware that logs the request duration."},
{"d":"code","p":"Write a SQL query that returns the top 3 customers by total order value per country from tables customers(id,country) and orders(id,customer_id,amount)."},
{"d":"code","p":"Write a bash script that finds all files larger than 100 MB under /var/log, sorted by size, and prints them in human readable form."},
{"d":"code","p":"Explain this Python error and how to fix it:\nTraceback (most recent call last):\n File \"app.py\", line 12, in <module>\n print(data['users'][0]['name'])\nKeyError: 'users'"},
{"d":"code","p":"Refactor this function to be more readable:\ndef f(a):\n r=[]\n for i in range(len(a)):\n if a[i]%2==0:\n r.append(a[i]*a[i])\n return r"},
{"d":"code","p":"Write a regular expression that matches ISO 8601 dates like 2026-10-11 and explain each part."},
{"d":"code","p":"Write a TypeScript interface for a paginated API response and a generic fetch helper that validates the shape at runtime."},
{"d":"math","p":"A train leaves a station at 9:15 and travels at 80 km/h. A second train leaves the same station at 10:00 on the same track at 120 km/h. At what time does the second catch the first? Show the steps."},
{"d":"math","p":"Prove that the sum of the first n odd numbers is n squared, using induction."},
{"d":"math","p":"Solve the system: 3x + 2y = 16 and x - y = 2. Then check the solution."},
{"d":"math","p":"What is the probability of getting exactly two heads in five fair coin flips? Explain the formula you use."},
{"d":"reason","p":"Three friends, Ann, Ben and Cara, each own exactly one of a cat, a dog and a parrot. Ann does not own the dog. Ben owns neither the cat nor the parrot. Who owns what? Explain your reasoning."},
{"d":"reason","p":"I have a 3 liter jug and a 5 liter jug and unlimited water. How can I measure exactly 4 liters?"},
{"d":"chat","p":"I have a job interview tomorrow for a junior data analyst role and I am nervous. Can you give me practical advice?"},
{"d":"chat","p":"What are some good ways to learn a new language as an adult with only 30 minutes a day?"},
{"d":"chat","p":"Recommend a weekly meal prep plan for someone who wants high protein, vegetarian meals on a budget."},
{"d":"chat","p":"My laptop gets very hot and the fan is loud when I open many browser tabs. What can I check?"},
{"d":"creative","p":"Write a short story (about 300 words) about a lighthouse keeper who discovers that the light attracts something other than ships."},
{"d":"creative","p":"Write a poem about autumn rain in the style of a haiku sequence, five stanzas."},
{"d":"creative","p":"Describe a bustling night market in a fantasy city, using all five senses."},
{"d":"science","p":"Explain how a transformer neural network processes a sentence, from tokens to the next-token prediction, for a software engineer who has not studied machine learning."},
{"d":"science","p":"Why is the sky blue and sunsets red? Explain Rayleigh scattering without heavy math."},
{"d":"science","p":"Explain how CRISPR-Cas9 edits a gene, and name two ethical concerns."},
{"d":"history","p":"Summarize the causes and consequences of the fall of the Western Roman Empire in a few paragraphs."},
{"d":"history","p":"Compare the economic policies of the New Deal with those of the Reagan era."},
{"d":"law","p":"Explain the difference between a trademark, a copyright and a patent, with one everyday example of each."},
{"d":"business","p":"Draft a polite email to a customer whose order is delayed by two weeks, offering a 10 percent discount and a new delivery date."},
{"d":"business","p":"Write a one-page project proposal outline for migrating a small company's file server to a cloud storage service."},
{"d":"data","p":"Create a markdown table comparing PostgreSQL, MySQL and SQLite on concurrency, typical use cases, licensing and scaling."},
{"d":"data","p":"Return a JSON object describing a fictional book with fields title, author, year, genres (array) and a nested publisher object. Only output JSON."},
{"d":"tool","p":"You are an assistant with a tool get_weather(city, unit). The user asks: 'Do I need an umbrella in Hamburg tomorrow?' Write the tool call you would make as JSON and then explain what you would tell the user once you get the result."},
{"d":"summ","p":"Summarize in three bullet points: Photosynthesis converts light energy into chemical energy. In the light-dependent reactions, chlorophyll absorbs photons and splits water, releasing oxygen and producing ATP and NADPH. In the Calvin cycle, these carriers drive the fixation of carbon dioxide into sugars. The rate of photosynthesis depends on light intensity, carbon dioxide concentration and temperature."},
{"d":"fr","p":"Explique en français comment fonctionne un moteur à combustion à quatre temps, avec des phrases simples."},
{"d":"de","p":"Schreibe eine kurze, freundliche E-Mail auf Deutsch, in der du einen Termin beim Zahnarzt von Dienstag auf Donnerstag verschiebst."},
{"d":"es","p":"Dame una receta sencilla de tortilla española y explica los errores más comunes al hacerla."},
{"d":"zh","p":"请用中文解释什么是区块链,并举一个日常生活中的例子。"},
{"d":"ja","p":"日本語で、初心者向けにPythonのリスト内包表記を説明してください。"},
{"d":"ru","p":"Объясни простыми словами, чем отличается процесс от потока в операционной системе."},
{"d":"trivia","p":"Who wrote 'The Master and Margarita', and what is the novel about? Answer in a short paragraph."},
{"d":"essay","p":"Write a balanced essay of about 350 words on whether remote work is better than office work for software teams."}
]
@@ -53,14 +53,57 @@ Both cards, cold server per run, one 8,275- and one 33,586-token prompt of repos
Decode is the same within the noise in both setups (these short answers: 51-58 tok/s split, 36-42 helper).
## Against the FP32 route (#1006), same card (2026-10-06)
#1006 takes the same gfx103x GEMMs the other way: both inputs widened to FP32 and the product as SGEMM (exact widening,
FP32 accumulate, `STRATA_RDNA2_SGEMM=0` for the old path). Built at its `63a92c2` and run next to this change's build
(`6add1a7`, `main` + this) on one RX 6900 XT: the same model and arguments as above, three prompts from one corpus, cold
server per arm, temperature 0, 8 tokens answered, `STRATA_PREFILL_TIMING=1`. The old path here is #1006's branch with
its switch off. One run per cell; a second cold run of this change's arm repeated it within 1.3%.
| prompt tokens | old path | #1006 (SGEMM) | this change (FP16 HGEMM) |
| ---: | ---: | ---: | ---: |
| 8,368 | 412 tok/s | 622 tok/s (+51%) | 730 tok/s (+77%) |
| 32,813 | 455 tok/s | 742 tok/s (+63%) | 900 tok/s (+98%) |
| 104,412 | 456 tok/s | 750 tok/s (+65%) | 904 tok/s (+98%) |
The 32,813-token prompt's GPU timeline, the phases these GEMMs sit in (old / SGEMM / FP16): gdn 22.0 -> 6.2 -> 4.0 s,
qsa proj 8.6 -> 3.2 -> 2.1 s, hc read 8.1 -> 6.1 -> 4.4 s, router+shared 4.0 -> 2.5 -> 0.7 s; `wait copy` is 1.0 s in
all three (PCIe 4.0 x8), so the GEMMs are not hidden behind the expert stream here. Per call this is the card's FP32
rate against its FP16 rate: the N 10240 x K 2560 projection at ~15 TFLOPS as SGEMM (#1006's 27.7 ms at T 8192) and
37.7 as HGEMM, about 2x on the GEMM itself, 17-21% on the prompt. What the SGEMM route has that this change does not:
no FP16 output rounding, `beta != 0` and N < 64 covered. The three arms gave the same answer on each prompt.
## Range check
FP16 ends at 65504 where BF16 reaches 3.4e38, so the precondition is that nothing the prompt path feeds these GEMMs or gets
out of them leaves FP16's range. Measured on 0.1.38 with a diagnostic counter (not part of this change) over 33.7K tokens of
English docs, 43.3K of Chinese logs and 32.4K of C++ on one card: every BF16 GEMM's X and W and every FP16 output - **0**
values beyond 65504, **0** infinities. Non-zero |x| < 6.1e-5 (FP16's subnormal band): 0.008-1.8% of X, 0.1-0.9% of W.
Out-of-range values would still be finite: the activation writers saturate to +-65504 (`hf_sat`, as the FP16 images
already did), a NaN stays a NaN.
out of them leaves FP16's range. The engine now counts it: `STRATA_F16_RANGE=1` records, per device, the largest |value|
and the count beyond 65504 (or not finite) at the three places a value enters or leaves FP16 - the activation images
(`hf_sat`, every image writer's one funnel), the BF16 weights converted to FP16 (`bf16_to_f16_rows`) and the FP16 GEMM
outputs as they are widened (`widen_rows_f16`; an output rocBLAS wrote beyond the range is Inf there, not saturated) -
and prints one line per prompt (`strata f16 range: ...`). Off, the cost is one flag read per value; on, a 34.4K-token
prompt read at 889.8 tok/s against 888.5 without it.
Measured on one card over 466K tokens in nine prompts: three 32-34K slices of the earlier corpus (English docs, Chinese
logs, C++), two prompts (118K and 64K tokens) built to push activations - delimiter floods (`<|im_start|>`, 200 newlines,
500 spaces), one token repeated 4,000 times, 6,000-character runs, 18-digit numbers, 20K characters of base64, emoji and
Japanese / Russian / Arabic / Hindi text, 2,000 SQL lines - and four batches (40-49K tokens) of real requests recorded
from this machine's API:
| | activation images, max abs | BF16 weights, max abs | FP16 GEMM outputs, max abs | beyond 65504 / not finite |
| --- | ---: | ---: | ---: | ---: |
| corpus slices (3) | 84.0 / 103.4 / 112.2 | 11.56 | 387.0 / 392.0 / 391.5 | 0 |
| built to push (2) | 76.6 / 99.0 | 11.56 | 409.5 / 399.2 | 0 |
| real requests (4) | 73.9 - 92.7 | 11.56 | 374.2 - 382.5 | 0 |
The largest output is 409.5, 160x below 65504; the largest activation 112, 580x below. The prompts built to push
activations did not: their maxima are below the ordinary corpus's. Offline, the pack's dense BF16 tensors (484 in the
first GGUF shard) peak at 8.56 (`hc_ffn_up`); 11.56 is in the second shard (the PLE). This is one model (GSQ-RCO IQ3_S);
the other models setup installs are fine-tunes of the same architecture, so the headroom is the same kind of number
there but has not been measured. Out-of-range activations would still be finite: the image writers saturate to
+-65504 (`hf_sat`), a NaN stays a NaN; an out-of-range GEMM output would be Inf, which is what the counter is for.
`to_f16` (the hc image for the FP16-weight GEMMs and the PLE key image) saturates and counts too now, so every FP16
image writer is under the same rule; three of the prompts rerun with it in gave the same maxima.
## Distribution check (teacher-forced)
@@ -130,6 +173,12 @@ would need `STRATA_HIP_PROMPT_F16=0`.
row from its end; `Gemm::bf16` converts W row slices to FP16 through the existing dequantization scratch (as
`native()` does) and takes X as the FP16 image. `bf16x2_mode()` is 0 there (the BF16 low part has no FP16 meaning).
- No new device memory, no host sync, no fallback branch; CUDA builds are unchanged (`#if defined(__HIPCC__)`).
- `hip_prefill_gemm` (ctest) runs its shapes a second time with `set_f16_io(true)` on any HIP card: X as the FP16 image
for the BF16 products, a scratch of 64 rows so a 96-row weight converts in two slices, `ldy > N`, an odd N, T = 1 and
a `beta = 1` f16() call (which keeps the FP32-out GEMM). The FP16-out results are checked against the double reference
at FP16's rounding (6e-4 relative per element, rel L2 < 1e-3); row padding and the guards around Y must be untouched.
The test's BF16 inputs are now made by hand: `hip_bfloat16(float)` produced 0 in this build, so the two BF16 cases had
passed on all-zero inputs (rel L2 printed 0); with real inputs they pass at 1.9e-07 (FP32 out) and 2.2e-04 (FP16 out).
## Limits
@@ -0,0 +1,80 @@
# RX 6900 XT (gfx1030): rocBLAS's kernel choice for the FP16 prompt GEMMs, and a solution table (2026-10-05)
On gfx103x the prompt path's dense GEMMs run through rocBLAS as FP16 in -> FP16 out (#835). rocBLAS picks the kernel
for each product from its own table by shape, and for some shapes that pick is far from the best kernel the same library
holds. The clearest case is the GDN input projection, N = 10240, K = 2560: below T = 1152 tokens rocBLAS's choice runs at
5.2-5.3 TFLOPS (n = 682 ... 1120, measured with `rocblas_gemm_ex` on this card, 8.1 ms at n = 799), at T = 1152 it jumps
to 38 TFLOPS (1.6 ms), and the best of the 237 solutions `rocblas_gemm_ex_get_solutions` lists for n = 799 runs it in
1.36 ms. It is not an alignment effect (n = 800 is as slow as 799). In the engine's own phase timing this is why the
"gdn" phase of a 799-token prompt (445 ms) was nearly as long as that of an 8,874-token one (1,345 ms).
`tools/hip/tune_rocblas.cpp` enumerates rocBLAS's solutions per shape and token bucket, times them, checks the fastest
against the default kernel's output and writes the winners as a table; `Gemm::f16_inplace` runs the table's solution for
a shape in place of rocBLAS's choice (`STRATA_ROCBLAS_TUNING`; docs/AMD_HIP.md, "rocBLAS table"). The table shipped,
`tools/hip/gfx1030-rocblas-5.6.0.8d1ae90e.txt`, is calibrated against rocBLAS 5.6.0.8d1ae90e (ROCm 10.0.0,
`/opt/rocm/lib`); its indices are valid for that build only, and the engine refuses any other.
## Rig
- AMD Radeon RX 6900 XT 16 GB (gfx1030), PCIe 4.0 x8, one card of two (`HIP_VISIBLE_DEVICES` as setup sets it); AMD
Ryzen 5 5600X (6 cores, AVX2), 128 GB DDR4-3200; Ubuntu 26.04, kernel 7.0.0-38-generic, ROCm 10.0.0 (HIP 7.15.26333).
Note that a HIP build on this Ubuntu links Ubuntu's own `librocblas5` (a 5.1 build, package 7.1.0-1ubuntu4) unless
`lib_dirs` (`/opt/rocm/lib`) puts ROCm's first: the engine runs below had `lib_dirs` set, as setup's configuration does.
rocBLAS 5.1's default kernel for the shape above is as slow (8.1 ms at n = 799, measured too); its solution indices
differ, so it would need its own table.
- Model: Qwen3.8-Flash-Next GSQ-RCO IQ3_S (2 shards, `--native`), MTP draft, `--kv int8 --kv-resident 32768
--max-context 131072 --expert-cache auto --prefill auto --spec 4 --spec-min-p 0.5 --adapt-every 100000` (the last the
#884 workaround; it does not touch the prompt path).
- Engine: `6f32ec0` (0.1.39) + #835 + this change, `-DSTRATA_ENABLE_HIP=ON -DCMAKE_HIP_ARCHITECTURES=gfx1030
-DSTRATA_PREFILL_MMQ=ON`. #849 is not in this build, so the `qsa attn` phase is the slow pre-#849 kernel here (the same
in both arms).
## Table
`tune_rocblas --tuning-out ...` with the defaults: the engine's 14 FP16 dense shapes (ldy = N) at T = 256, 512, 768,
1024, 1536, 2048, 4096, 8192; 112 rows, 76 with a solution that beat the default by at least 5% and also ran at T-1,
T-37, T-63 and T/2+1 (a kernel can refuse a token count it was not measured at), `default` for the other 36.
[tune-summary.txt](tune-summary.txt) is the tool's per-case output (default ms, best solution, gain). The large gains
are at small T: N = 10240 K = 2560 at T = 256 ... 1024, 7.0-7.8x; N = 12288 K = 2560 at T = 256, 5.8x; N = 6144 K =
2560 at T = 256 / 512, 3.6-3.8x; N = 2560 K = 6144 at T = 256, 4.5x; N = 320 K = 10240 (`hc read`), 2.5-8.7x across the
buckets. At T >= 2048 most shapes keep the default (1.0-1.2x where a solution still wins).
## Method
One server per arm, the same binary; `STRATA_PREFILL_TIMING=1` (the engine's prompt-phase timing),
`STRATA_ROCBLAS_VERBOSE=1`; the on arm with `STRATA_ROCBLAS_TUNING` pointing at the directory holding the table. Four
prompts from four different offsets of one text (no prefix reuse between them), "Reply with one word", `max_tokens` 8,
temperature 0; the answer text compared between arms. The GPU timeline is the engine's `strata prefill timing` line; the
per-phase numbers are its phases ([timing-off.txt](timing-off.txt), [timing-on.txt](timing-on.txt)). One run per arm; the off
arm repeated an earlier run of the same prompts the same day (with the table's first version) to within 10 ms on every
prompt, and the on arm's gains repeated within 100 ms.
## Results
| prompt tokens (read) | arm | GPU timeline ms | gdn | hc read | wait copy | answer |
| ---: | --- | ---: | ---: | ---: | ---: | --- |
| 806 (799) | default | 3,329 | 443 | 270 | 1,376 | Estimated |
| 806 (799) | **table** | **2,985** | 177 | 77 | 1,384 | Estimated |
| 502 (495) | default | 2,477 | 365 | 81 | 1,077 | Incomplete |
| 502 (495) | **table** | **2,139** | 146 | 52 | 1,075 | Incomplete |
| 1,115 (1,108) | default | 3,391 | 598 | 158 | 1,144 | Incomplete |
| 1,115 (1,108) | table | 3,395 | 201 | 99 | 1,637 | Incomplete |
| 8,881 (8,874) | default | 11,978 | 1,346 | 1,200 | 1,683 | Strata |
| 8,881 (8,874) | **table** | **11,459** | 1,128 | 898 | 1,670 | Strata |
- 799 tokens: -10.3%; 495 tokens: -13.6%; 8,874 tokens: -4.3% (the 682-token tail chunk's projections, and `hc read`
at both chunks).
- 1,108 tokens: no change. Its GDN time fell by 397 ms and `wait copy` rose by 493 ms: that prompt is bound by the
experts' PCIe transfer, and a faster GEMM only brings the GPU to the wait sooner. Which prompts are copy-bound depends
on how many distinct experts they touch, not on their length alone.
- The answers are the same in all four pairs. The tuner checked each solution it kept against the default kernel's FP16
output (relative L2 within 2e-3, no element beyond 4 FP16 ulps of the largest output, nothing written outside the
N x T result); in the engine's run no solution was refused (0 fallbacks over 52 shape-and-T combinations served).
- Decode does not use these GEMMs; not measured here.
## Limits
One machine, one card, one model; one run per arm, four prompts. The table is for one rocBLAS build; another build (or
ROCm's 5.1 packaged by Ubuntu) needs `tune_rocblas` run against it. Prompts above ~1,150 tokens gain only through their
tail chunk and `hc read`, and copy-bound prompts gain nothing. Whether other gfx103x cards (gfx1031 / gfx1032) share
rocBLAS's gfx1030 kernel table was not checked; the engine's architecture check would refuse this table on them.
@@ -0,0 +1,9 @@
strata serve: prompt chunk auto: 8192 tokens, a 384-slot ring
strata prefill timing: 799 tokens, GPU timeline 3329 ms, wall 3339 ms, host staging 55 ms: embed+steps 5 (0.2%) hc read 270 (8.1%) gdn 443 (13.3%) qsa proj 91 (2.7%) qsa indexer 0 (0.0%) qsa select 1 (0.0%) qsa attn 50 (1.5%) router+shared 44 (1.3%) host grouping 12 (0.3%) gather 11 (0.3%) wait copy 1376 (41.3%) dequant 415 (12.5%) gemm gate/up 311 (9.3%) gemm down 155 (4.6%) combine 18 (0.5%) ple 10 (0.3%) kv stage 0 (0.0%) gdn conv+gates 5 (0.1%) gdn recurrence 35 (1.0%) gdn out proj 78 (2.3%)
strata serve: prompt 806 tokens = 0 reused + 806 read in 3635 ms (221.7 tok/s), 2 generated in 140 ms (14.3 tok/s), drafts accepted 3 of 3, 1 checkpoints
strata prefill timing: 495 tokens, GPU timeline 2477 ms, wall 2479 ms, host staging 107 ms: embed+steps 0 (0.0%) hc read 81 (3.3%) gdn 365 (14.7%) qsa proj 83 (3.4%) qsa indexer 0 (0.0%) qsa select 0 (0.0%) qsa attn 24 (1.0%) router+shared 77 (3.1%) host grouping 15 (0.6%) gather 3 (0.1%) wait copy 1077 (43.5%) dequant 319 (12.9%) gemm gate/up 223 (9.0%) gemm down 109 (4.4%) combine 10 (0.4%) ple 6 (0.2%) kv stage 0 (0.0%) gdn conv+gates 3 (0.1%) gdn recurrence 20 (0.8%) gdn out proj 61 (2.5%)
strata serve: prompt 502 tokens = 0 reused + 502 read in 2667 ms (188.2 tok/s), 2 generated in 114 ms (17.5 tok/s), drafts accepted 3 of 3, 1 checkpoints
strata prefill timing: 1108 tokens, GPU timeline 3391 ms, wall 3396 ms, host staging 184 ms: embed+steps 3 (0.1%) hc read 158 (4.7%) gdn 598 (17.6%) qsa proj 117 (3.5%) qsa indexer 0 (0.0%) qsa select 2 (0.0%) qsa attn 88 (2.6%) router+shared 53 (1.6%) host grouping 14 (0.4%) gather 7 (0.2%) wait copy 1144 (33.7%) dequant 454 (13.4%) gemm gate/up 358 (10.6%) gemm down 179 (5.3%) combine 26 (0.8%) ple 14 (0.4%) kv stage 0 (0.0%) gdn conv+gates 12 (0.3%) gdn recurrence 55 (1.6%) gdn out proj 109 (3.2%)
strata serve: prompt 1115 tokens = 0 reused + 1115 read in 3676 ms (303.3 tok/s), 2 generated in 115 ms (17.4 tok/s), drafts accepted 3 of 3, 1 checkpoints
strata prefill timing: 8874 tokens, GPU timeline 11978 ms, wall 11981 ms, host staging 336 ms: embed+steps 38 (0.3%) hc read 1200 (10.0%) gdn 1346 (11.2%) qsa proj 597 (5.0%) qsa indexer 1 (0.0%) qsa select 62 (0.5%) qsa attn 1897 (15.8%) router+shared 228 (1.9%) host grouping 42 (0.3%) gather 56 (0.5%) wait copy 1683 (14.1%) dequant 854 (7.1%) gemm gate/up 1428 (11.9%) gemm down 706 (5.9%) combine 768 (6.4%) ple 34 (0.3%) kv stage 8 (0.1%) gdn conv+gates 92 (0.8%) gdn recurrence 491 (4.1%) gdn out proj 447 (3.7%)
strata serve: prompt 8881 tokens = 0 reused + 8881 read in 12470 ms (712.2 tok/s), 3 generated in 117 ms (25.7 tok/s), drafts accepted 3 of 3, 1 checkpoints
@@ -0,0 +1,9 @@
strata serve: prompt chunk auto: 8192 tokens, a 384-slot ring
strata prefill timing: 799 tokens, GPU timeline 2985 ms, wall 2994 ms, host staging 58 ms: embed+steps 5 (0.2%) hc read 77 (2.6%) gdn 177 (5.9%) qsa proj 89 (3.0%) qsa indexer 0 (0.0%) qsa select 1 (0.0%) qsa attn 51 (1.7%) router+shared 156 (5.2%) host grouping 12 (0.4%) gather 14 (0.5%) wait copy 1384 (46.4%) dequant 414 (13.9%) gemm gate/up 313 (10.5%) gemm down 154 (5.2%) combine 18 (0.6%) ple 3 (0.1%) kv stage 0 (0.0%) gdn conv+gates 5 (0.2%) gdn recurrence 35 (1.2%) gdn out proj 78 (2.6%)
strata serve: prompt 806 tokens = 0 reused + 806 read in 3296 ms (244.5 tok/s), 2 generated in 140 ms (14.3 tok/s), drafts accepted 3 of 3, 1 checkpoints
strata prefill timing: 495 tokens, GPU timeline 2139 ms, wall 2142 ms, host staging 98 ms: embed+steps 0 (0.0%) hc read 52 (2.5%) gdn 146 (6.8%) qsa proj 66 (3.1%) qsa indexer 0 (0.0%) qsa select 0 (0.0%) qsa attn 24 (1.1%) router+shared 29 (1.3%) host grouping 10 (0.5%) gather 3 (0.2%) wait copy 1075 (50.3%) dequant 318 (14.9%) gemm gate/up 222 (10.4%) gemm down 109 (5.1%) combine 10 (0.5%) ple 2 (0.1%) kv stage 0 (0.0%) gdn conv+gates 3 (0.1%) gdn recurrence 20 (0.9%) gdn out proj 50 (2.3%)
strata serve: prompt 502 tokens = 0 reused + 502 read in 2336 ms (214.9 tok/s), 2 generated in 124 ms (16.1 tok/s), drafts accepted 3 of 3, 1 checkpoints
strata prefill timing: 1108 tokens, GPU timeline 3395 ms, wall 3399 ms, host staging 176 ms: embed+steps 3 (0.1%) hc read 99 (2.9%) gdn 201 (5.9%) qsa proj 109 (3.2%) qsa indexer 0 (0.0%) qsa select 2 (0.0%) qsa attn 88 (2.6%) router+shared 51 (1.5%) host grouping 12 (0.4%) gather 7 (0.2%) wait copy 1637 (48.2%) dequant 448 (13.2%) gemm gate/up 360 (10.6%) gemm down 179 (5.3%) combine 26 (0.8%) ple 3 (0.1%) kv stage 0 (0.0%) gdn conv+gates 11 (0.3%) gdn recurrence 54 (1.6%) gdn out proj 102 (3.0%)
strata serve: prompt 1115 tokens = 0 reused + 1115 read in 3685 ms (302.6 tok/s), 2 generated in 115 ms (17.4 tok/s), drafts accepted 3 of 3, 1 checkpoints
strata prefill timing: 8874 tokens, GPU timeline 11459 ms, wall 11461 ms, host staging 329 ms: embed+steps 39 (0.3%) hc read 898 (7.8%) gdn 1128 (9.8%) qsa proj 595 (5.2%) qsa indexer 1 (0.0%) qsa select 62 (0.5%) qsa attn 1901 (16.6%) router+shared 214 (1.9%) host grouping 41 (0.4%) gather 56 (0.5%) wait copy 1670 (14.6%) dequant 860 (7.5%) gemm gate/up 1434 (12.5%) gemm down 710 (6.2%) combine 783 (6.8%) ple 28 (0.2%) kv stage 8 (0.1%) gdn conv+gates 92 (0.8%) gdn recurrence 492 (4.3%) gdn out proj 447 (3.9%)
strata serve: prompt 8881 tokens = 0 reused + 8881 read in 11952 ms (743.0 tok/s), 3 generated in 155 ms (19.3 tok/s), drafts accepted 3 of 3, 1 checkpoints
@@ -0,0 +1,226 @@
meta device_arch=gfx1030 rocblas_version=5.6.0.8d1ae90e shapes=112 min_gain=1.050
case T=256 N=10240 K=2560 ldy=10240 default_ms=2.3582 default_padding_writes=0
best T=256 N=10240 K=2560 ldy=10240 solution=-1086327703 ms=0.3478 default_ms=2.3582 gain=6.78
case T=512 N=10240 K=2560 ldy=10240 default_ms=4.9305 default_padding_writes=0
best T=512 N=10240 K=2560 ldy=10240 solution=-1086327703 ms=0.6744 default_ms=4.9305 gain=7.31
case T=768 N=10240 K=2560 ldy=10240 default_ms=7.5687 default_padding_writes=0
best T=768 N=10240 K=2560 ldy=10240 solution=-1086327719 ms=1.0134 default_ms=7.5687 gain=7.47
case T=1024 N=10240 K=2560 ldy=10240 default_ms=10.1879 default_padding_writes=0
best T=1024 N=10240 K=2560 ldy=10240 solution=-1086327687 ms=1.4093 default_ms=10.1879 gain=7.23
case T=1536 N=10240 K=2560 ldy=10240 default_ms=1.9304 default_padding_writes=0
keep_default T=1536 N=10240 K=2560 ldy=10240 (237 solutions; best 1.9404 ms vs default 1.9304)
case T=2048 N=10240 K=2560 ldy=10240 default_ms=2.5629 default_padding_writes=0
keep_default T=2048 N=10240 K=2560 ldy=10240 (237 solutions; best 2.5848 ms vs default 2.5629)
case T=4096 N=10240 K=2560 ldy=10240 default_ms=5.2270 default_padding_writes=0
keep_default T=4096 N=10240 K=2560 ldy=10240 (237 solutions; best 5.5127 ms vs default 5.2270)
case T=8192 N=10240 K=2560 ldy=10240 default_ms=12.2560 default_padding_writes=0
keep_default T=8192 N=10240 K=2560 ldy=10240 (237 solutions; best 12.1342 ms vs default 12.2560)
case T=256 N=12288 K=2560 ldy=12288 default_ms=3.0070 default_padding_writes=0
best T=256 N=12288 K=2560 ldy=12288 solution=-1086327718 ms=0.5044 default_ms=3.0070 gain=5.96
case T=512 N=12288 K=2560 ldy=12288 default_ms=1.0101 default_padding_writes=0
best T=512 N=12288 K=2560 ldy=12288 solution=-1086327703 ms=0.8314 default_ms=1.0101 gain=1.21
case T=768 N=12288 K=2560 ldy=12288 default_ms=1.5441 default_padding_writes=0
best T=768 N=12288 K=2560 ldy=12288 solution=-1086327703 ms=1.3048 default_ms=1.5441 gain=1.18
case T=1024 N=12288 K=2560 ldy=12288 default_ms=1.8461 default_padding_writes=0
best T=1024 N=12288 K=2560 ldy=12288 solution=-1086327687 ms=1.6263 default_ms=1.8461 gain=1.14
case T=1536 N=12288 K=2560 ldy=12288 default_ms=2.6097 default_padding_writes=0
best T=1536 N=12288 K=2560 ldy=12288 solution=-1086327687 ms=2.4141 default_ms=2.6097 gain=1.08
case T=2048 N=12288 K=2560 ldy=12288 default_ms=3.3976 default_padding_writes=0
best T=2048 N=12288 K=2560 ldy=12288 solution=-1086327687 ms=3.2127 default_ms=3.3976 gain=1.06
case T=4096 N=12288 K=2560 ldy=12288 default_ms=6.8017 default_padding_writes=0
keep_default T=4096 N=12288 K=2560 ldy=12288 (237 solutions; best 6.8216 ms vs default 6.8017)
case T=8192 N=12288 K=2560 ldy=12288 default_ms=14.3542 default_padding_writes=0
keep_default T=8192 N=12288 K=2560 ldy=12288 (237 solutions; best 14.9711 ms vs default 14.3542)
case T=256 N=6144 K=2560 ldy=6144 default_ms=0.9801 default_padding_writes=0
best T=256 N=6144 K=2560 ldy=6144 solution=-1086327717 ms=0.2813 default_ms=0.9801 gain=3.48
case T=512 N=6144 K=2560 ldy=6144 default_ms=1.8331 default_padding_writes=0
best T=512 N=6144 K=2560 ldy=6144 solution=-1086327703 ms=0.5097 default_ms=1.8331 gain=3.60
case T=768 N=6144 K=2560 ldy=6144 default_ms=0.6667 default_padding_writes=0
keep_default T=768 N=6144 K=2560 ldy=6144 (237 solutions; best 0.6687 ms vs default 0.6667)
case T=1024 N=6144 K=2560 ldy=6144 default_ms=0.8296 default_padding_writes=0
keep_default T=1024 N=6144 K=2560 ldy=6144 (237 solutions; best 0.8873 ms vs default 0.8296)
case T=1536 N=6144 K=2560 ldy=6144 default_ms=1.2994 default_padding_writes=0
keep_default T=1536 N=6144 K=2560 ldy=6144 (237 solutions; best 1.3967 ms vs default 1.2994)
case T=2048 N=6144 K=2560 ldy=6144 default_ms=2.4454 default_padding_writes=0
best T=2048 N=6144 K=2560 ldy=6144 solution=-1086327687 ms=1.6310 default_ms=2.4454 gain=1.50
case T=4096 N=6144 K=2560 ldy=6144 default_ms=3.2071 default_padding_writes=0
keep_default T=4096 N=6144 K=2560 ldy=6144 (237 solutions; best 3.2142 ms vs default 3.2071)
case T=8192 N=6144 K=2560 ldy=6144 default_ms=6.3302 default_padding_writes=0
keep_default T=8192 N=6144 K=2560 ldy=6144 (237 solutions; best 6.7397 ms vs default 6.3302)
case T=256 N=2560 K=6144 ldy=2560 default_ms=1.3017 default_padding_writes=0
best T=256 N=2560 K=6144 ldy=2560 solution=-1086327764 ms=0.2927 default_ms=1.3017 gain=4.45
case T=512 N=2560 K=6144 ldy=2560 default_ms=1.2293 default_padding_writes=0
best T=512 N=2560 K=6144 ldy=2560 solution=-1086327719 ms=0.4751 default_ms=1.2293 gain=2.59
case T=768 N=2560 K=6144 ldy=2560 default_ms=0.7950 default_padding_writes=0
keep_default T=768 N=2560 K=6144 ldy=2560 (275 solutions; best 0.7770 ms vs default 0.7950)
case T=1024 N=2560 K=6144 ldy=2560 default_ms=1.0164 default_padding_writes=0
best T=1024 N=2560 K=6144 ldy=2560 solution=-1086327719 ms=0.8868 default_ms=1.0164 gain=1.15
case T=1536 N=2560 K=6144 ldy=2560 default_ms=1.5987 default_padding_writes=0
best T=1536 N=2560 K=6144 ldy=2560 solution=-1086327703 ms=1.4385 default_ms=1.5987 gain=1.11
case T=2048 N=2560 K=6144 ldy=2560 default_ms=1.8388 default_padding_writes=0
keep_default T=2048 N=2560 K=6144 ldy=2560 (237 solutions; best 1.8535 ms vs default 1.8388)
case T=4096 N=2560 K=6144 ldy=2560 default_ms=3.4526 default_padding_writes=0
keep_default T=4096 N=2560 K=6144 ldy=2560 (237 solutions; best 3.7885 ms vs default 3.4526)
case T=8192 N=2560 K=6144 ldy=2560 default_ms=7.1451 default_padding_writes=0
keep_default T=8192 N=2560 K=6144 ldy=2560 (237 solutions; best 8.2445 ms vs default 7.1451)
case T=256 N=2560 K=640 ldy=2560 default_ms=0.0435 default_padding_writes=0
best T=256 N=2560 K=640 ldy=2560 solution=-1086327695 ms=0.0385 default_ms=0.0435 gain=1.13
case T=512 N=2560 K=640 ldy=2560 default_ms=0.0729 default_padding_writes=0
best T=512 N=2560 K=640 ldy=2560 solution=-1086327711 ms=0.0594 default_ms=0.0729 gain=1.23
case T=768 N=2560 K=640 ldy=2560 default_ms=0.0965 default_padding_writes=0
best T=768 N=2560 K=640 ldy=2560 solution=-1086327694 ms=0.0798 default_ms=0.0965 gain=1.21
case T=1024 N=2560 K=640 ldy=2560 default_ms=0.1084 default_padding_writes=0
best T=1024 N=2560 K=640 ldy=2560 solution=-1086327709 ms=0.0945 default_ms=0.1084 gain=1.15
case T=1536 N=2560 K=640 ldy=2560 default_ms=0.1569 default_padding_writes=0
best T=1536 N=2560 K=640 ldy=2560 solution=-1086327713 ms=0.1383 default_ms=0.1569 gain=1.13
case T=2048 N=2560 K=640 ldy=2560 default_ms=0.1833 default_padding_writes=0
keep_default T=2048 N=2560 K=640 ldy=2560 (237 solutions; best 0.1776 ms vs default 0.1833)
case T=4096 N=2560 K=640 ldy=2560 default_ms=0.3481 default_padding_writes=0
keep_default T=4096 N=2560 K=640 ldy=2560 (237 solutions; best 0.3392 ms vs default 0.3481)
case T=8192 N=2560 K=640 ldy=2560 default_ms=0.6858 default_padding_writes=0
keep_default T=8192 N=2560 K=640 ldy=2560 (237 solutions; best 0.6570 ms vs default 0.6858)
case T=256 N=2560 K=2560 ldy=2560 default_ms=0.1292 default_padding_writes=0
keep_default T=256 N=2560 K=2560 ldy=2560 (275 solutions; best 0.1254 ms vs default 0.1292)
case T=512 N=2560 K=2560 ldy=2560 default_ms=0.2150 default_padding_writes=0
best T=512 N=2560 K=2560 ldy=2560 solution=-1086327719 ms=0.2046 default_ms=0.2150 gain=1.05
case T=768 N=2560 K=2560 ldy=2560 default_ms=0.3035 default_padding_writes=0
keep_default T=768 N=2560 K=2560 ldy=2560 (275 solutions; best 0.3088 ms vs default 0.3035)
case T=1024 N=2560 K=2560 ldy=2560 default_ms=0.4164 default_padding_writes=0
best T=1024 N=2560 K=2560 ldy=2560 solution=-1086327719 ms=0.3567 default_ms=0.4164 gain=1.17
case T=1536 N=2560 K=2560 ldy=2560 default_ms=0.5242 default_padding_writes=0
keep_default T=1536 N=2560 K=2560 ldy=2560 (237 solutions; best 0.5240 ms vs default 0.5242)
case T=2048 N=2560 K=2560 ldy=2560 default_ms=0.6880 default_padding_writes=0
keep_default T=2048 N=2560 K=2560 ldy=2560 (237 solutions; best 0.6871 ms vs default 0.6880)
case T=4096 N=2560 K=2560 ldy=2560 default_ms=1.5527 default_padding_writes=0
best T=4096 N=2560 K=2560 ldy=2560 solution=-1086327703 ms=1.3273 default_ms=1.5527 gain=1.17
case T=8192 N=2560 K=2560 ldy=2560 default_ms=2.8199 default_padding_writes=0
best T=8192 N=2560 K=2560 ldy=2560 solution=-1086327703 ms=2.6153 default_ms=2.8199 gain=1.08
case T=256 N=640 K=2560 ldy=640 default_ms=0.1526 default_padding_writes=0
best T=256 N=640 K=2560 ldy=640 solution=-1086327725 ms=0.0563 default_ms=0.1526 gain=2.71
case T=512 N=640 K=2560 ldy=640 default_ms=0.2008 default_padding_writes=0
best T=512 N=640 K=2560 ldy=640 solution=-1086327724 ms=0.0830 default_ms=0.2008 gain=2.42
case T=768 N=640 K=2560 ldy=640 default_ms=0.1659 default_padding_writes=0
best T=768 N=640 K=2560 ldy=640 solution=-1086327723 ms=0.1138 default_ms=0.1659 gain=1.46
case T=1024 N=640 K=2560 ldy=640 default_ms=0.2067 default_padding_writes=0
best T=1024 N=640 K=2560 ldy=640 solution=-1086327764 ms=0.1255 default_ms=0.2067 gain=1.65
case T=1536 N=640 K=2560 ldy=640 default_ms=0.2841 default_padding_writes=0
best T=1536 N=640 K=2560 ldy=640 solution=-1086327719 ms=0.2013 default_ms=0.2841 gain=1.41
case T=2048 N=640 K=2560 ldy=640 default_ms=0.2173 default_padding_writes=0
best T=2048 N=640 K=2560 ldy=640 solution=-1086327703 ms=0.2062 default_ms=0.2173 gain=1.05
case T=4096 N=640 K=2560 ldy=640 default_ms=0.3467 default_padding_writes=0
keep_default T=4096 N=640 K=2560 ldy=640 (237 solutions; best 0.3515 ms vs default 0.3467)
case T=8192 N=640 K=2560 ldy=640 default_ms=0.6892 default_padding_writes=0
keep_default T=8192 N=640 K=2560 ldy=640 (237 solutions; best 0.6712 ms vs default 0.6892)
case T=256 N=512 K=2560 ldy=512 default_ms=0.1569 default_padding_writes=0
best T=256 N=512 K=2560 ldy=512 solution=-1086327769 ms=0.0474 default_ms=0.1569 gain=3.31
case T=512 N=512 K=2560 ldy=512 default_ms=0.2025 default_padding_writes=0
best T=512 N=512 K=2560 ldy=512 solution=-1086327722 ms=0.0734 default_ms=0.2025 gain=2.76
case T=768 N=512 K=2560 ldy=512 default_ms=0.1474 default_padding_writes=0
best T=768 N=512 K=2560 ldy=512 solution=-1086327774 ms=0.0978 default_ms=0.1474 gain=1.51
case T=1024 N=512 K=2560 ldy=512 default_ms=0.1552 default_padding_writes=0
best T=1024 N=512 K=2560 ldy=512 solution=-1086327722 ms=0.1194 default_ms=0.1552 gain=1.30
case T=1536 N=512 K=2560 ldy=512 default_ms=0.2222 default_padding_writes=0
best T=1536 N=512 K=2560 ldy=512 solution=-1086327768 ms=0.1703 default_ms=0.2222 gain=1.30
case T=2048 N=512 K=2560 ldy=512 default_ms=0.2122 default_padding_writes=0
keep_default T=2048 N=512 K=2560 ldy=512 (275 solutions; best 0.2031 ms vs default 0.2122)
case T=4096 N=512 K=2560 ldy=512 default_ms=0.3443 default_padding_writes=0
keep_default T=4096 N=512 K=2560 ldy=512 (275 solutions; best 0.3530 ms vs default 0.3443)
case T=8192 N=512 K=2560 ldy=512 default_ms=0.6643 default_padding_writes=0
keep_default T=8192 N=512 K=2560 ldy=512 (237 solutions; best 0.6684 ms vs default 0.6643)
case T=256 N=128 K=2560 ldy=128 default_ms=0.0608 default_padding_writes=0
best T=256 N=128 K=2560 ldy=128 solution=-1086327780 ms=0.0371 default_ms=0.0608 gain=1.64
case T=512 N=128 K=2560 ldy=128 default_ms=0.1992 default_padding_writes=0
best T=512 N=128 K=2560 ldy=128 solution=-1086327780 ms=0.0377 default_ms=0.1992 gain=5.28
case T=768 N=128 K=2560 ldy=128 default_ms=0.1137 default_padding_writes=0
best T=768 N=128 K=2560 ldy=128 solution=-1086327780 ms=0.0452 default_ms=0.1137 gain=2.52
case T=1024 N=128 K=2560 ldy=128 default_ms=0.1180 default_padding_writes=0
best T=1024 N=128 K=2560 ldy=128 solution=-1086327774 ms=0.0493 default_ms=0.1180 gain=2.40
case T=1536 N=128 K=2560 ldy=128 default_ms=0.1520 default_padding_writes=0
best T=1536 N=128 K=2560 ldy=128 solution=-1086327772 ms=0.0664 default_ms=0.1520 gain=2.29
case T=2048 N=128 K=2560 ldy=128 default_ms=0.1242 default_padding_writes=0
best T=2048 N=128 K=2560 ldy=128 solution=-1086327768 ms=0.0753 default_ms=0.1242 gain=1.65
case T=4096 N=128 K=2560 ldy=128 default_ms=0.1512 default_padding_writes=0
best T=4096 N=128 K=2560 ldy=128 solution=-1086327764 ms=0.1248 default_ms=0.1512 gain=1.21
case T=8192 N=128 K=2560 ldy=128 default_ms=0.2066 default_padding_writes=0
keep_default T=8192 N=128 K=2560 ldy=128 (275 solutions; best 0.2036 ms vs default 0.2066)
case T=256 N=48 K=2560 ldy=48 default_ms=0.0456 default_padding_writes=0
best T=256 N=48 K=2560 ldy=48 solution=-1086327840 ms=0.0208 default_ms=0.0456 gain=2.19
case T=512 N=48 K=2560 ldy=48 default_ms=0.2023 default_padding_writes=0
best T=512 N=48 K=2560 ldy=48 solution=-1086327781 ms=0.0387 default_ms=0.2023 gain=5.23
case T=768 N=48 K=2560 ldy=48 default_ms=0.1029 default_padding_writes=0
best T=768 N=48 K=2560 ldy=48 solution=-1086327779 ms=0.0418 default_ms=0.1029 gain=2.47
case T=1024 N=48 K=2560 ldy=48 default_ms=0.1078 default_padding_writes=0
best T=1024 N=48 K=2560 ldy=48 solution=-1086327779 ms=0.0439 default_ms=0.1078 gain=2.46
case T=1536 N=48 K=2560 ldy=48 default_ms=0.1125 default_padding_writes=0
best T=1536 N=48 K=2560 ldy=48 solution=-1086327776 ms=0.0512 default_ms=0.1125 gain=2.20
case T=2048 N=48 K=2560 ldy=48 default_ms=0.1210 default_padding_writes=0
best T=2048 N=48 K=2560 ldy=48 solution=-1086327779 ms=0.0565 default_ms=0.1210 gain=2.14
case T=4096 N=48 K=2560 ldy=48 default_ms=0.1865 default_padding_writes=0
best T=4096 N=48 K=2560 ldy=48 solution=-1086327736 ms=0.0972 default_ms=0.1865 gain=1.92
case T=8192 N=48 K=2560 ldy=48 default_ms=0.2047 default_padding_writes=0
best T=8192 N=48 K=2560 ldy=48 solution=-1086327762 ms=0.1489 default_ms=0.2047 gain=1.37
case T=256 N=320 K=10240 ldy=320 default_ms=0.4283 default_padding_writes=0
best T=256 N=320 K=10240 ldy=320 solution=-1086327781 ms=0.1325 default_ms=0.4283 gain=3.23
case T=512 N=320 K=10240 ldy=320 default_ms=0.4971 default_padding_writes=0
best T=512 N=320 K=10240 ldy=320 solution=-1086327769 ms=0.2001 default_ms=0.4971 gain=2.48
case T=768 N=320 K=10240 ldy=320 default_ms=0.8265 default_padding_writes=0
best T=768 N=320 K=10240 ldy=320 solution=-1086327722 ms=0.2416 default_ms=0.8265 gain=3.42
case T=1024 N=320 K=10240 ldy=320 default_ms=1.1697 default_padding_writes=0
best T=1024 N=320 K=10240 ldy=320 solution=-1086327773 ms=0.3623 default_ms=1.1697 gain=3.23
case T=1536 N=320 K=10240 ldy=320 default_ms=1.6087 default_padding_writes=0
best T=1536 N=320 K=10240 ldy=320 solution=-1086327738 ms=0.4669 default_ms=1.6087 gain=3.45
case T=2048 N=320 K=10240 ldy=320 default_ms=2.1792 default_padding_writes=0
best T=2048 N=320 K=10240 ldy=320 solution=-1086327724 ms=0.6335 default_ms=2.1792 gain=3.44
case T=4096 N=320 K=10240 ldy=320 default_ms=9.6169 default_padding_writes=0
best T=4096 N=320 K=10240 ldy=320 solution=-1086327717 ms=1.1841 default_ms=9.6169 gain=8.12
case T=8192 N=320 K=10240 ldy=320 default_ms=2.2651 default_padding_writes=0
keep_default T=8192 N=320 K=10240 ldy=320 (237 solutions; best 2.3719 ms vs default 2.2651)
case T=256 N=10240 K=320 ldy=10240 default_ms=0.0584 default_padding_writes=0
best T=256 N=10240 K=320 ldy=10240 solution=-1086327694 ms=0.0556 default_ms=0.0584 gain=1.05
case T=512 N=10240 K=320 ldy=10240 default_ms=0.0980 default_padding_writes=0
keep_default T=512 N=10240 K=320 ldy=10240 (237 solutions; best 0.0964 ms vs default 0.0980)
case T=768 N=10240 K=320 ldy=10240 default_ms=0.1398 default_padding_writes=0
keep_default T=768 N=10240 K=320 ldy=10240 (237 solutions; best 0.1377 ms vs default 0.1398)
case T=1024 N=10240 K=320 ldy=10240 default_ms=0.1815 default_padding_writes=0
keep_default T=1024 N=10240 K=320 ldy=10240 (237 solutions; best 0.1806 ms vs default 0.1815)
case T=1536 N=10240 K=320 ldy=10240 default_ms=0.2626 default_padding_writes=0
keep_default T=1536 N=10240 K=320 ldy=10240 (237 solutions; best 0.2625 ms vs default 0.2626)
case T=2048 N=10240 K=320 ldy=10240 default_ms=0.3437 default_padding_writes=0
keep_default T=2048 N=10240 K=320 ldy=10240 (237 solutions; best 0.3432 ms vs default 0.3437)
case T=4096 N=10240 K=320 ldy=10240 default_ms=0.6693 default_padding_writes=0
keep_default T=4096 N=10240 K=320 ldy=10240 (237 solutions; best 0.6686 ms vs default 0.6693)
case T=8192 N=10240 K=320 ldy=10240 default_ms=1.3531 default_padding_writes=0
keep_default T=8192 N=10240 K=320 ldy=10240 (237 solutions; best 1.3274 ms vs default 1.3531)
case T=256 N=4 K=10240 ldy=4 default_ms=0.1050 default_padding_writes=0
best T=256 N=4 K=10240 ldy=4 solution=-1086327846 ms=0.0503 default_ms=0.1050 gain=2.09
case T=512 N=4 K=10240 ldy=4 default_ms=0.2470 default_padding_writes=0
best T=512 N=4 K=10240 ldy=4 solution=-1086327840 ms=0.0544 default_ms=0.2470 gain=4.54
case T=768 N=4 K=10240 ldy=4 default_ms=0.2539 default_padding_writes=0
best T=768 N=4 K=10240 ldy=4 solution=-1086327840 ms=0.0610 default_ms=0.2539 gain=4.16
case T=1024 N=4 K=10240 ldy=4 default_ms=0.2553 default_padding_writes=0
best T=1024 N=4 K=10240 ldy=4 solution=-1086327850 ms=0.0801 default_ms=0.2553 gain=3.19
case T=1536 N=4 K=10240 ldy=4 default_ms=0.2556 default_padding_writes=0
best T=1536 N=4 K=10240 ldy=4 solution=-1086327840 ms=0.1116 default_ms=0.2556 gain=2.29
case T=2048 N=4 K=10240 ldy=4 default_ms=0.3051 default_padding_writes=0
best T=2048 N=4 K=10240 ldy=4 solution=-1086327815 ms=0.1429 default_ms=0.3051 gain=2.14
case T=4096 N=4 K=10240 ldy=4 default_ms=0.4891 default_padding_writes=0
best T=4096 N=4 K=10240 ldy=4 solution=-1086327922 ms=0.2538 default_ms=0.4891 gain=1.93
case T=8192 N=4 K=10240 ldy=4 default_ms=1.1681 default_padding_writes=0
best T=8192 N=4 K=10240 ldy=4 solution=-1086327922 ms=0.4845 default_ms=1.1681 gain=2.41
case T=256 N=1 K=2560 ldy=1 default_ms=0.0433 default_padding_writes=0
best T=256 N=1 K=2560 ldy=1 solution=-9 ms=0.0081 default_ms=0.0433 gain=5.33
case T=512 N=1 K=2560 ldy=1 default_ms=0.2000 default_padding_writes=0
best T=512 N=1 K=2560 ldy=1 solution=-9 ms=0.0107 default_ms=0.2000 gain=18.63
case T=768 N=1 K=2560 ldy=1 default_ms=0.0865 default_padding_writes=0
best T=768 N=1 K=2560 ldy=1 solution=-9 ms=0.0125 default_ms=0.0865 gain=6.90
case T=1024 N=1 K=2560 ldy=1 default_ms=0.0914 default_padding_writes=0
best T=1024 N=1 K=2560 ldy=1 solution=-9 ms=0.0167 default_ms=0.0914 gain=5.49
case T=1536 N=1 K=2560 ldy=1 default_ms=0.0931 default_padding_writes=0
best T=1536 N=1 K=2560 ldy=1 solution=-9 ms=0.0197 default_ms=0.0931 gain=4.72
case T=2048 N=1 K=2560 ldy=1 default_ms=0.1200 default_padding_writes=0
best T=2048 N=1 K=2560 ldy=1 solution=-9 ms=0.0307 default_ms=0.1200 gain=3.92
case T=4096 N=1 K=2560 ldy=1 default_ms=0.0734 default_padding_writes=0
best T=4096 N=1 K=2560 ldy=1 solution=-9 ms=0.0415 default_ms=0.0734 gain=1.77
case T=8192 N=1 K=2560 ldy=1 default_ms=0.2007 default_padding_writes=0
best T=8192 N=1 K=2560 ldy=1 solution=-9 ms=0.0728 default_ms=0.2007 gain=2.76
wrote 112 rows (76 with a solution) to table-5.6-v2.txt
@@ -0,0 +1,74 @@
# Community benchmark: 2x NVIDIA Quadro RTX 4000 8 GB, Xeon E5-2620 v3, 64 GB RAM
Measured on 2026-10-07 by [Ryan V](https://github.com/rvannos) on an unprivileged Proxmox LXC container environment. This tests the **125B Mixture-of-Experts model** (`Swift-Qwen3.8-Flash-Next` IQ2_XS) with a 131,072-token context window, layer split across dual NVIDIA Quadro RTX 4000 GPUs, and expert cache tiering between GPU VRAM and host DDR4 RAM.
The system was evaluated both on synthetic generation sweeps and as the core inference engine of a live production pipeline (**Gridiron Gemini Data Orchestrator**), which continuously ingests and synthesizes 45,000 to 62,000-token NFL podcast transcripts.
Prompt reading speeds reached **126.3 to 249.2 tok/s** on 73,000–74,600 token prompts, with sustained decode generation at **18.1 to 23.2 tok/s** across 500–1,100 generated tokens (expert cache hit rates 48–53%).
---
## Hardware and Software
- **GPUs:** 2x NVIDIA Quadro RTX 4000 8 GB GDDR6 (TU104, Turing Tensor Cores, Flash Attention). 125 W power limit per card. Both cards on PCIe 3.0 x16. Persistence mode enabled.
- **CPU and RAM:** Dual Intel Xeon E5-2620 v3 @ 2.40GHz (Haswell-EP, 12 cores / 24 threads total, AVX2). 64 GB DDR4-2133 ECC Registered host RAM (62.8 GiB reported by Linux); 48 GB RAM (49,152 MiB) and 12 vCPUs allocated to Container 114.
- **Storage:** Enterprise NVMe SSD storage pool.
- **OS and Runtime:** Proxmox VE 9.2.5 (Kernel 7.0.14-6-pve), unprivileged Debian 13 (Trixie) LXC container. NVIDIA driver 580.142, CUDA 13.0.
- **Engine:** Strata engine version 0.1.38 (`main`), release binary with native CUDA backend.
- **Co-located Workloads:** GPU 0 co-hosts WhisperX (isolated to GPU 0, idle at 150 MiB); GPU 1 co-hosts F5-TTS (parked in CPU RAM at 0 MB VRAM when idle). Shared VRAM loan protocols release GPU allocations during audio batches.
---
## Model and Configuration
**Model:** `Swift-Qwen3.8-Flash-Next` (125B MoE, IQ2_XS quantization).
- Native base weights: `Swift-Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00001-of-00002.gguf`
- Quantized expert shards: `Swift-Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00002-of-00002.gguf`
- Multimodal Vision Projector: `mmproj-Swift-Qwen3.8-Flash-Next-BF16.gguf` (866 MB BF16 ViT on GPU 0 with an automated 5-minute idle watchdog).
- Expert profile: `data/expert-profile.bin`.
- Speculative Draft: MTP runtime (`/opt/Strata-data/mtp/rt`).
**Configuration (`strata-swift-iq2_xs.json`):**
- Context limit: 131,072 tokens (`--max-context 131072`)
- KV Cache: `--kv q4_0 --kv-resident 32768` (32,768 KV cells resident in VRAM, remainder streamed dynamically)
- GPU mapping: `"gpu": [0, 1]`, `layer_split: auto`
- Expert Cache: `--expert-cache auto`, `--vram-reserve-mib 700`
- Prefill: `--prefill auto`
- Speculative Drafting: `--spec 4 --spec-min-p 0.5`
- Vision: On-demand GPU 0 execution with 300s idle auto-unload (`idle_s: 300`)
---
## Measured Performance
### 1. High-Context Ingestion & Generation Sweeps
Measurements captured directly from the engine runtime log under deep-context workloads:
| Prompt Tokens | Reused Tokens | Fresh Tokens Read | Prefill Speed | Generated Tokens | Generation Time | Decode Speed | Expert Cache Hit Rate | KV VRAM Hit Rate |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| **73,416** | 0 | 73,416 | **249.2 tok/s** | 814 | 38.38 s | **21.2 tok/s** | 52.5% | 97.70% |
| **74,110** | 73,411 | 699 | **126.3 tok/s** | 566 | 24.84 s | **22.8 tok/s** | 48.2% | 97.84% |
| **74,641** | 74,105 | 536 | **99.9 tok/s** | 271 | 14.94 s | **18.1 tok/s** | 52.5% | 98.07% |
| **72,891** | 71,733 | 1,158 | **139.1 tok/s** | 397 | 17.55 s | **22.6 tok/s** | 52.6% | 98.63% |
### 2. Real-World Production Pipeline Comparison (Data Orchestrator)
Prior to deploying Strata 125B MoE, the pipeline ran **Gemma 4 12B** (Dense) on a single GPU. Here is the operational delta recorded across production podcast dossier ingestions:
| Metric | Gemma 4 12B (Dense, 1x GPU) | Strata 125B MoE (Dual GPU) | Impact / Delta |
| :--- | :--- | :--- | :--- |
| **Model Size** | 12B Dense | 125B MoE | **10.4× Parameter Scale** |
| **Zero-Tag Extraction Failures** | 5 of 15 episodes (33.3% failure) | 0 of 6 episodes (0.0% failure) | **100% Extraction Reliability** |
| **Avg. Validated Tags / Dossier** | 15.4 tags | 24.5 tags (max 25 cap) | **+59.1% Entity Density** |
| **Leftover Unmapped Speaker IDs** | 814 across 15 files | 160 across 6 files | **78% Reduction in Unmapped IDs** |
| **60,000+ Token Full Ingestion** | Failed (Context fatigue / broken JSON) | 60,927 prompt tokens in single pass | **Zero Dropouts** |
| **2-Host Dialogue Script Generation** | 180s+ (frequent timeouts / truncation) | 81.6s (1,103 words, 21 turns) | **2.2× Speedup** |
---
## Observations & Takeaways
1. **VRAM Efficiency**: Layer splitting across dual 8GB Quadro RTX 4000s allowed Strata to fit dense base weights and 2,473 resident experts directly in VRAM (~6.8 GB per card), while offloading the remaining 33 GB expert arena to host DDR4 RAM with >97% KV VRAM hit rates.
2. **Context Stability**: Processing massive 60k–75k token audio transcripts without JSON truncation or context dropouts eliminated the pipeline's primary reliability bottleneck.
3. **Speculative Decoding on Turing**: Even on older Turing architecture (Quadro RTX 4000), 4-step speculative drafting maintained consistent 18–23 tok/s decode generation.
@@ -0,0 +1,117 @@
# Build and reproduce
Measured engine: official `v0.1.40.2`, commit
`e8ca9afd03d839d4f8dbbe82dffce7f8a3bafd7a`, **no local patches**.
Native SYCL Release/SPIR-V JIT, not AOT; oneAPI DPC++ 2026.1.0, oneMKL and
llama.cpp/ggml `3cf03257f219afbe7334045ff7c6a06ac68c627d`.
Compiler options include `-O3 -DNDEBUG -std=c++20 -fsycl`, per-kernel device-code
split, 32-lane subgroups, precise FP and correctly rounded FP32 divide/sqrt.
Exact CMake options are in build.json. Measured binary SHA256:
`8ca822304881a259412656ae7ba63fdb9d8e2c31ce18d9f3149bc8a57448f311`.
A rebuild's hash can depend on paths/toolchain.
With a compatible oneAPI/compiler/MKL installation already available, in an
isolated checkout:
```sh
git checkout e8ca9afd03d839d4f8dbbe82dffce7f8a3bafd7a
export STRATA_ROOT="$PWD"
export REPORT=/absolute/path/to/this/report
git clone https://github.com/ggml-org/llama.cpp.git /absolute/path/to/llama.cpp
git -C /absolute/path/to/llama.cpp checkout 3cf03257f219afbe7334045ff7c6a06ac68c627d
export STRATA_GGUF_PY=/absolute/path/to/llama.cpp/gguf-py
source /opt/intel/oneapi/setvars.sh
python3 -m venv .venv-b65
.venv-b65/bin/pip install -r requirements.txt
export PATH="$STRATA_ROOT/.venv-b65/bin:$PATH"
cmake -S sycl -B build-sycl -G Ninja \
-DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx \
-DSTRATA_GGML_DIR=/absolute/path/to/llama.cpp -DCMAKE_BUILD_TYPE=Release
cmake --build build-sycl -j4
```
The portable scripts require Python 3.11+ (`hashlib.file_digest`); the measured
host used Python 3.14.4, with dependency versions listed in system.json. Install neither a driver nor another runtime to reproduce
this report's software comparison. Choose a working compatible driver for your
own system and record its version.
## Retained artifacts
Both GGUF shards are original full 512-expert IQ2_XS from
`ISTA-DASLab/Qwen3.8-Flash-Next-GSQ-RCO-GGUF@ed59f92082b1e93c0e96d60a8b11aab089b52f09`,
under `IQ2_XS/`. The dense pack/tokenizer were **retained, not repacked for the
new release**. They were prepared by `tools/iq_pack.py` at Strata commit
`6f32ec070f23ced9f50e704d854d775da52591ab` (script SHA256
`0a79ac86f63d9b36371d37643952592770fe5cc2e4e45fff0c63f5c023c6de26`).
Use that preparation checkout when reproducing the exact artifacts. The release
adds two native PLE formats to that tool's format set; do not assume a fresh
release pack has the recorded hashes.
The original Q2_0 MTP draft is from
`Qwen/Qwen3.8-Flash-Next@de4b8e4d43b917e7706784d8bb445c9af86a3540`.
`prepare-mtp.py` uses upstream verification of all 31 tensors and forbids a
floating-main fallback. The MTP pack/runtime preparation tools match the
original preparation versions. No custom draft vocabulary or ranking;
`data/expert-profile.bin` matches this release byte for byte.
```sh
export BENCH_ASSETS=/absolute/path/to/benchmark-assets
export PREPARATION_ROOT=/absolute/path/to/strata-preparation-checkout
git clone https://github.com/Niko1221/Strata.git "$PREPARATION_ROOT"
git -C "$PREPARATION_ROOT" fetch origin 6f32ec070f23ced9f50e704d854d775da52591ab
git -C "$PREPARATION_ROOT" checkout --detach FETCH_HEAD
python "$PREPARATION_ROOT/tools/iq_pack.py" \
--gguf "$BENCH_ASSETS/models/IQ2_XS/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00001-of-00002.gguf" \
--out "$BENCH_ASSETS/pack"
python "$REPORT/prepare-mtp.py" --source "$STRATA_ROOT" --assets "$BENCH_ASSETS"
export MODEL_DIR="$BENCH_ASSETS/models/IQ2_XS"
export PACK_DIR="$BENCH_ASSETS/pack"
export MTP_DIR="$BENCH_ASSETS/mtp-rt"
export EXPERT_PROFILE="$STRATA_ROOT/data/expert-profile.bin"
```
Verify sizes/hashes against artifacts.json. On the measured host, large artifacts
were previously hashed and root-sealed; ownership and sealed inode/mtime/size
were rechecked. Engine/profile/environment were freshly SHA256-checked.
No large model or pack is included in this PR.
## Run
Use an independent bounded supervisor with exclusive GPU ownership, enough
pinned-memory allowance and RAM-backed logs. The measured host disabled swap,
core dumps and crash capture during generation, restoring services and capture
after verified cleanup. These portable scripts do not configure those host
policies or stop other model owners.
```sh
export ONEAPI_DEVICE_SELECTOR=level_zero:0 SYCL_CACHE_PERSISTENT=0
export SYCL_PROGRAM_COMPILE_OPTIONS=-cl-fp32-correctly-rounded-divide-sqrt
export STRATA_MIRROR_MIB=16384 STRATA_VERIFY_DEVICE_PLAN=1 STRATA_VERIFY_NO_HOST=1
export STRATA_WARM_GRAPHS=0
export STRATA_STAGER_THREADS=4 OMP_NUM_THREADS=4 MKL_NUM_THREADS=4
unset STRATA_DBG_NAN STRATA_VERIFY_EAGER STRATA_QFUSE STRATA_DECODE_TIMING STRATA_PLE_TRACE
sudo install -d -m700 -o "$(id -un)" /run/strata-community
python "$REPORT/benchmark.py" --source "$STRATA_ROOT" \
--profile "$REPORT/profile-8k-512.json" --ram /run/strata-community \
--out /absolute/path/to/new-main-512 --runs 3
export STRATA_TEST_RAM=/run/strata-community
export STRATA_TEST_PROFILE="$REPORT/profile-8k-512.json"
export BENCH_OUTPUT=/absolute/path/to/new-public-512
python "$REPORT/public-fixtures.py" matched
```
Repeat with `profile-8k-4096.json` and `profile-262k-512.json`, using distinct
output directories. The input shapes and output caps stay unchanged at 262K;
that suite measures the larger configured memory budget, not a full-window prompt. Profiles expand
the exported path variables. Main fixtures/instructions are embedded in
benchmark.py. Public token-ID fixtures are `benchy-short.ids` and
`benchy-long.ids`; the helper also retains the same task-shaping library in
frozen-community.py. It adds `STRATA_TRACE=1`, matching the measured public suite.
Both suites store counts/timings/hashes, not generated text. Keep native logs in
RAM through clean QUIT and delayed-fault observation, then remove them.
Report fields use seconds for `ttft_s`/`total_s`, milliseconds for native
`prompt_ms`/`decode_ms`, and tokens/s for `prompt_tps`/`decode_tps`. Main suite
`measured=false` rows are warmups or canaries. Public-suite canaries are excluded
from tables. Decode is `generated*1000/decode_ms`; prompt is
`prompt_read*1000/prompt_ms`. Request elapsed time is never used as decode time.
@@ -0,0 +1,51 @@
# Scope of validation
The unmodified release builds all 199 native targets. Its complete registered
CTest suite reports 30 tests: 26 pass, four fail. These failures were retained
and investigated before model benchmarks:
| Test | Finding |
| --- | --- |
| `iq_parity` | CTest supplies `--selftest`, which this program treats as a fixture directory. A separate run against the available actual IQ fixtures passes. Native GGUF expert oracles across eight layers also pass. |
| `ple_parity` | The standalone Q2_0 fixture is unavailable. This case remains unqualified. The measured profile uses original IQ2_XS/native model artifacts. |
| `gr_parity` | Ordinary/native GR subchecks pass. Opt-in QFUSE and multi-QFUSE checks fail because the SYCL implementations explicitly return false. `STRATA_QFUSE` is absent in these measurements. |
| `s2_expert_grouped_parity` | Old/new grouped kernels differ bitwise in four cases. All CPU-oracle comparisons report zero rows outside tolerance, with worst normalized error no greater than 1.03e-7. This path is used by the drafter, so independent exact target-only/one-draft/MTP4 model-stream checks were required. |
Those model-stream checks pass independently for both prefill profiles. No
engine code was patched or numeric tolerance relaxed. This does not qualify
other models, formats or optional fused paths.
An earlier CTest attempt refused to run because its log directory was owned by
root. Only `Testing/Temporary` ownership was repaired; the build and binary
remained root-owned. That pre-execution refusal and the classified full-suite
failures are excluded from performance summaries. No hardware fault occurred
in either attempt; recovery was checked before continuing.
A controller progress-file read race also stopped a queued phase before its
payload started. Atomic progress-file replacement fixed it and passed a
concurrent-read check. The failed controller receipts were preserved; no
native test or benchmark had to be repeated because of that failure.
A subsequent pre-install audit encountered the restored UI's health listener
before it was ready. The controller stopped before installation; a bounded
transport-readiness check fixed that sequencing issue. Full idle recovery
passed before continuing. This did not invalidate or repeat any benchmark.
Each 8K profile passes 21 native checks and 24 API checks, including cancellation,
restart, tools, queued isolation and near-8K capacity. Reference checks compare
actual token streams, not only successful loading or fluent text. Benchmark
repeats within each profile match exactly. Different prefill sizes can change
long continuations, so their decode-rate difference is not a pure kernel
comparison. Arithmetic accuracy is recorded separately from runtime validity.
The 262K profile separately passes five native reference checks and 12 API
checks at progressive and full context, including exact speculative/reference
agreement and overflow rejection. Full-window timings are individual capacity
checks, separate from the three-run matched-input benchmarks.
Independent guards enforce exclusive GPU ownership, Gen4 x16, zero watched
PCIe errors, 30.5 GiB resident-VRAM ceiling, 32 GiB host-memory margin, an 80 GiB
cgroup with no swap, bounded execution and sensor-specific thermal margins.
Content/logs/configuration live in RAM; core dumps, persistent SYCL cache and
crash capture during generation are disabled. Cleanup verifies payload exit
before deleting RAM content and restoring normal services/crash capture.
Only numeric/hashes are attached. `qualification.json` gives sample counts,
observed peaks/minima and fault counts for each successful phase.
@@ -0,0 +1,132 @@
# Arc Pro B65: Strata v0.1.40.2 on PCIe Gen4
Measured on 2026-10-07 by timnevits. **Official upstream release**, commit
`e8ca9afd03d839d4f8dbbe82dffce7f8a3bafd7a`, with **no local engine patches**.
The measurements come from my B65 hardware.
Both memory profiles pass their bounded correctness checks. With the same 7K inputs, the 8K/prefill-512 profile delivers **43.49 decode tok/s**, versus **42.38** with the 262K/prefill-512 profile (-2.6%). The 8K/prefill-4096 profile reduces median 7K TTFT from **22.23 to 8.47 seconds**, with decode tradeoffs below.
## Hardware and configuration
One Intel Arc Pro B65, 32 GiB VRAM (`8086:e222`), **Gen4 x16**, 200 W cap;
i5-12600K, 128 GB DDR4-3200, Samsung 980 NVMe. Other model owners were stopped.
Ubuntu 26.04.1, kernel 7.0.0-38, xe/NEO 26.22.38646.7, Level Zero 1.28.6.
Native Release/JIT build with existing oneAPI 2026.1.0 and oneMKL, precise FP,
correctly rounded divide/sqrt and 32-lane subgroups. The tagged engine labels
itself `0.1.40-sycl`; the commit and binary hash identify this build.
Exact metadata: [system.json](system.json), [build.json](build.json).
Original **full 512-expert Flash-Next IQ2_XS**, not Coder:
`ISTA-DASLab/Qwen3.8-Flash-Next-GSQ-RCO-GGUF` at
`ed59f92082b1e93c0e96d60a8b11aab089b52f09`. Original Q2_0 MTP pack from
`Qwen/Qwen3.8-Flash-Next@de4b8e4d43b917e7706784d8bb445c9af86a3540`.
[artifacts.json](artifacts.json) identifies both shards, retained dense pack,
tokenizer/template, draft and expert ranking. Ranking matches the release
byte for byte. The model has a native 262144-token window. The tables compare **8192 and
262152 native context allocations (8K/262K profiles)**, using matched short and 7K inputs. The API reserves eight verification slots,
leaving 8184 and 262144 usable combined tokens respectively. No model, quantization, driver, compiler or ranking changes
between configurations.
One request, INT8 resident KV, four workers, automatic hot
expert cache and streaming experts. Every missing expert is in a protected
pinned host mirror (16 GiB cap). `STRATA_VERIFY_NO_HOST=1` keeps computation
on the GPU, including direct reads from that mirror. Native verify/commit
graphs, MTP window 4/max 4/min-p 0.5 (up to three drafts). Thinking off,
greedy/seed 17; prompt, conversation and suffix caches, short-read and expert
adaptation off. `STRATA_DBG_NAN` and QFUSE absent. Allocation alias checking
keeps its upstream default. The two 8K profiles reserve 3072 MiB and differ only in prefill batch size:
[512](profile-8k-512.json), [4096](profile-8k-4096.json). The
[262K profile](profile-262k-512.json) uses prefill 512, reserve 4096 MiB and
explicit `--no-prefill-borrow`, preserving the smaller window's implicit
no-borrow policy. It reserves more KV and has fewer hot expert slots; this is
a comparison of the complete memory profiles, not context as a single variable.
[environment.json](environment.json) is shared.
Actual startup allocations below are identical across each profile's three main
runs. Expert slots count per-layer experts, rather than the model's 512 experts
per MoE layer. They help explain the memory/performance tradeoff.
| Profile | Hot expert slots | Hot cache MiB | Pinned missing-expert mirror GiB | Free VRAM at startup MiB |
| --- | ---: | ---: | ---: | ---: |
| 8K / 512 | 17881 | 24588 | 9.01 | 3197 |
| 8K / 4096 | 16160 | 22207 | 11.33 | 4237 |
| 262K / 512 | 14388 | 19761 | 13.72 | 4185 |
## Three-run results
Main suite: **three fresh processes per profile**, five fixed tasks at each
of 512 and 7000 input tokens, 640 generated tokens. An unmeasured full-shape
warmup precedes each input tier. Tasks cover code, prose, inventory and incident
planning; padding precedes the instruction. Each profile has 48 total requests,
30 measured. For each table row, take the median of five tasks within each run,
then the median and range of those three run medians. Individual cells are
available in the raw data.
Public-fixture suite: three fresh processes per profile, 2185-token request
first, then 20-token request, 256 outputs each, followed by an isolation canary.
No separate warmup; any first-request cost stays in its measurement. This is
9 total requests/6 measured per profile. Its prompts and output lengths differ
from the main suite.
| Native context allocation | Prefill | Input/workload | Output | Runs | Prompt tok/s | Decode tok/s | TTFT seconds |
| ---: | ---: | --- | ---: | ---: | --- | --- | --- |
| 8192 | 512 | 512, five tasks | 640 | 3 | 352.37 (352.28–352.81) | 45.01 (44.99–45.02) | 1.486 (1.485–1.487) |
| 8192 | 512 | 7000, five tasks | 640 | 3 | 315.44 (315.31–315.46) | 43.49 (43.49–43.49) | 22.226 (22.225–22.236) |
| 8192 | 512 | 20, public fixture | 256 | 3 | 54.60 (54.56–54.61) | 54.48 (54.47–54.49) | 0.400 (0.400–0.401) |
| 8192 | 512 | 2185, public fixture | 256 | 3 | 323.36 (323.30–323.43) | 49.72 (49.72–49.72) | 6.817 (6.816–6.818) |
| 8192 | 4096 | 512, five tasks | 640 | 3 | 330.92 (330.88–331.11) | 44.64 (44.61–44.65) | 1.581 (1.580–1.581) |
| 8192 | 4096 | 7000, five tasks | 640 | 3 | 830.00 (829.93–830.03) | 42.92 (42.92–42.92) | 8.469 (8.469–8.469) |
| 8192 | 4096 | 20, public fixture | 256 | 3 | 50.13 (50.11–50.19) | 53.51 (53.50–53.51) | 0.434 (0.433–0.434) |
| 8192 | 4096 | 2185, public fixture | 256 | 3 | 722.72 (582.42–723.77) | 47.40 (47.40–47.43) | 3.085 (3.081–3.813) |
| 262152 | 512 | 512, five tasks | 640 | 3 | 320.56 (318.13–320.72) | 43.51 (42.96–43.51) | 1.631 (1.631–1.644) |
| 262152 | 512 | 7000, five tasks | 640 | 3 | 287.80 (285.05–287.80) | 42.38 (41.87–42.40) | 24.357 (24.357–24.593) |
| 262152 | 512 | 20, public fixture | 256 | 3 | 49.02 (48.83–49.14) | 51.53 (50.52–51.53) | 0.444 (0.443–0.446) |
| 262152 | 512 | 2185, public fixture | 256 | 3 | 302.43 (300.92–302.91) | 48.95 (48.52–48.95) | 7.285 (7.281–7.331) |
Values are median (range). Loading/startup is timed separately and excluded
from request timings; the OS weight-file cache stays warm. Fixed expert
placement, **zero prompt reuse**, no adaptation. Prompt/decode rates use the
engine's separate token counts and durations. TTFT measures request start to
first native emitted token. Raw native timing lines, counts, draft acceptance,
input/output hashes and elapsed times: [results.json](results.json),
[CSV](results.csv), [summary](summary.json), [lifecycle](lifecycle.json).
Generated content is discarded; only numeric/hash receipts persist.
Prefill 4096 cuts the 7K TTFT median by 61.9%, but all five long continuations differ from batch 512 and the largest measured 7K decode-cell regression is 16.2%. It is an optional prefill-latency tradeoff, not an overall decode improvement. We keep batch 512 for normal serving. With batch 512, the larger memory profile's 7K TTFT is 24.36s versus 22.23s; 10/10 matched main benchmark cells have identical output hashes across the two memory profiles. See raw per-workload data before generalizing the aggregate.
## Validation and limits
Both 8K profiles pass **21 native reference checks** and **24 API/lifecycle
checks**, including exact target-only/one-draft/MTP4 agreement on the tested
256-output workloads, tools, queued isolation, near-8K recall, 640 outputs,
cancellation during long prefill and restart. Same-profile benchmark repeats
match exactly and all successful native processes exit 0 after graceful QUIT.
The 262K profile separately passes five native checks (target-only/MTP4 at
32K and full, one draft at 32K), with exact 128-token agreement, and 12 API
checks including progressive/full recall, a repeated full request and overflow
rejection. Full-window timing is capacity evidence, separate from the three-run
matched-input tables. These are bounded runtime checks, not broad quality or
roleplay qualification.
[Full-window receipts](full-window-checks.json) keep native and API/SSE timings
separate.
The full registered kernel suite is **26 pass / 4 fail**. Available actual IQ
fixtures and native GGUF checks over eight layers pass. The remaining
registration/fixture, unsupported QFUSE and grouped-S2 bitwise failures are
explained in [QUALIFICATION.md](QUALIFICATION.md), with numeric/reference
receipts in [qualification.json](qualification.json),
[native-reference.json](native-reference.json) and [api-checks.json](api-checks.json).
No claim that the whole kernel suite passes.
Independent GPU, PCIe, memory and thermal guards remain active. Successful runs
have no resets, PCIe errors, swap-out or OOM; peaks are recorded in qualification.json.
Failed qualification attempts are excluded from throughput. Both previously
local mirror safety fixes are upstream: incomplete coverage refuses startup,
and pinned mirror memory is freed before QUIT exit.
The qualified installed profile uses 262144 usable API tokens, prefill 512 and a 4096 MiB reserve. Routed pre/post-reboot full-window, tool, authorization and queued-isolation checks, graceful unload/restart, retained-model recovery and actual Pi chat/read-tool checks pass. Fresh full-window prefill remains about 15–16 minutes; capacity does not imply low latency or broad long-context quality. This report is pinned to v0.1.40.2; v0.1.40.3 was released during testing and is not measured here.
[BUILD.md](BUILD.md) gives exact preparation and portable reproduction steps.
[Portable fixture audit](portable-fixture-audit.json) verifies that the published
drivers produce the measured main inputs and public token fixtures, without
sending another inference request.
@@ -0,0 +1,14 @@
| Native context allocation | Prefill | Input/workload | Output | Runs | Prompt tok/s | Decode tok/s | TTFT seconds |
| ---: | ---: | --- | ---: | ---: | --- | --- | --- |
| 8192 | 512 | 512, five tasks | 640 | 3 | 352.37 (352.28–352.81) | 45.01 (44.99–45.02) | 1.486 (1.485–1.487) |
| 8192 | 512 | 7000, five tasks | 640 | 3 | 315.44 (315.31–315.46) | 43.49 (43.49–43.49) | 22.226 (22.225–22.236) |
| 8192 | 512 | 20, public fixture | 256 | 3 | 54.60 (54.56–54.61) | 54.48 (54.47–54.49) | 0.400 (0.400–0.401) |
| 8192 | 512 | 2185, public fixture | 256 | 3 | 323.36 (323.30–323.43) | 49.72 (49.72–49.72) | 6.817 (6.816–6.818) |
| 8192 | 4096 | 512, five tasks | 640 | 3 | 330.92 (330.88–331.11) | 44.64 (44.61–44.65) | 1.581 (1.580–1.581) |
| 8192 | 4096 | 7000, five tasks | 640 | 3 | 830.00 (829.93–830.03) | 42.92 (42.92–42.92) | 8.469 (8.469–8.469) |
| 8192 | 4096 | 20, public fixture | 256 | 3 | 50.13 (50.11–50.19) | 53.51 (53.50–53.51) | 0.434 (0.433–0.434) |
| 8192 | 4096 | 2185, public fixture | 256 | 3 | 722.72 (582.42–723.77) | 47.40 (47.40–47.43) | 3.085 (3.081–3.813) |
| 262152 | 512 | 512, five tasks | 640 | 3 | 320.56 (318.13–320.72) | 43.51 (42.96–43.51) | 1.631 (1.631–1.644) |
| 262152 | 512 | 7000, five tasks | 640 | 3 | 287.80 (285.05–287.80) | 42.38 (41.87–42.40) | 24.357 (24.357–24.593) |
| 262152 | 512 | 20, public fixture | 256 | 3 | 49.02 (48.83–49.14) | 51.53 (50.52–51.53) | 0.444 (0.443–0.446) |
| 262152 | 512 | 2185, public fixture | 256 | 3 | 302.43 (300.92–302.91) | 48.95 (48.52–48.95) | 7.285 (7.281–7.331) |
@@ -0,0 +1,9 @@
# Trimmed files
Ported from PR #1432 for 0.1.41. Raw dumps over 100 KB and binary files were left out to keep the repository small; the README, summaries, configs and per-run results are unchanged. The files below were in the original PR.
1 files, 0.3 MB:
| file | bytes | why |
|---|---:|---|
| `results.json` | 282,662 | raw dump over 100 KB |
@@ -0,0 +1,412 @@
{
"8k-512": {
"failure": null,
"passed": 24,
"requests": 24,
"authentication_checked": true,
"loopback_port": 18110,
"profile": {
"engine": "strata",
"exe": "$BENCH_ROOT/build-sycl/strata",
"args": [
"--pack",
"$PACK_DIR",
"--native",
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00001-of-00002.gguf",
"--ple-gguf",
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00002-of-00002.gguf",
"--expert-profile",
"$EXPERT_PROFILE",
"--expert-cache",
"auto",
"--stream-experts",
"--pcie-frac",
"1",
"--prefill",
"512",
"--spec",
"4",
"--mtp-max-t",
"4",
"--suffix-draft",
"0",
"--mtp",
"$MTP_DIR",
"--max-context",
"8192",
"--kv",
"int8",
"--vram-reserve-mib",
"3072",
"--adapt-every",
"0",
"--adapt-swaps",
"0",
"--pool-workers",
"4",
"--prompt-cache",
"0",
"--prompt-cache-every",
"0",
"--conversation-cache-mib",
"0",
"--short-read",
"0",
"--spec-min-p",
"0.5"
],
"cwd": "$STRATA_ROOT",
"tokenizer": "$PACK_DIR/tokenizer",
"model_name": "qwen3.8-flash-next-strata-iq2-xs-8k",
"backend": "sycl",
"host": "127.0.0.1",
"parallel": 1,
"api_monitor": false,
"open_browser": false,
"sampling": {
"temperature": 0.0,
"seed": 17
},
"engine_silence_s": 180,
"cors_origins": [],
"allowed_hosts": [
"127.0.0.1",
"localhost"
],
"log": "/run/strata-arc/v01402-api-512-1/content/engine.log"
},
"content_persisted": false
},
"8k-4096": {
"failure": null,
"passed": 24,
"requests": 24,
"authentication_checked": true,
"loopback_port": 18110,
"profile": {
"engine": "strata",
"exe": "$BENCH_ROOT/build-sycl/strata",
"args": [
"--pack",
"$PACK_DIR",
"--native",
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00001-of-00002.gguf",
"--ple-gguf",
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00002-of-00002.gguf",
"--expert-profile",
"$EXPERT_PROFILE",
"--expert-cache",
"auto",
"--stream-experts",
"--pcie-frac",
"1",
"--prefill",
"4096",
"--spec",
"4",
"--mtp-max-t",
"4",
"--suffix-draft",
"0",
"--mtp",
"$MTP_DIR",
"--max-context",
"8192",
"--kv",
"int8",
"--vram-reserve-mib",
"3072",
"--adapt-every",
"0",
"--adapt-swaps",
"0",
"--pool-workers",
"4",
"--prompt-cache",
"0",
"--prompt-cache-every",
"0",
"--conversation-cache-mib",
"0",
"--short-read",
"0",
"--spec-min-p",
"0.5"
],
"cwd": "$STRATA_ROOT",
"tokenizer": "$PACK_DIR/tokenizer",
"model_name": "qwen3.8-flash-next-strata-iq2-xs-8k",
"backend": "sycl",
"host": "127.0.0.1",
"parallel": 1,
"api_monitor": false,
"open_browser": false,
"sampling": {
"temperature": 0.0,
"seed": 17
},
"engine_silence_s": 180,
"cors_origins": [],
"allowed_hosts": [
"127.0.0.1",
"localhost"
],
"log": "/run/strata-arc/v01402-api-4096-1/content/engine.log"
},
"content_persisted": false
},
"262k-512": {
"run_id": "v01402-context-api-512-1",
"logical_context": 262144,
"internal_context": 262152,
"rows": [
{
"label": "short-sentinel",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 20,
"max_tokens": 32,
"usage": {
"prompt_tokens": 20,
"completion_tokens": 5,
"total_tokens": 25,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "45f978a5f0d3b223c3bdb74aebf770760138f0afc194b5dd3a025b48ccb97ed4",
"finish_reason": "stop",
"elapsed_s": 0.5871463259973098,
"ttft_s": 0.4991585909956484,
"output_span_s": 0.08707828800106654,
"post_first_tps": 45.93567572149567
},
{
"label": "short-arithmetic",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 30,
"max_tokens": 32,
"usage": {
"prompt_tokens": 30,
"completion_tokens": 3,
"total_tokens": 33,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "aea92132c4cbeb263e6ac2bf6c183b5d81737f179f21efdc5863739672f0f470",
"finish_reason": "stop",
"elapsed_s": 0.6474424050029484,
"ttft_s": 0.5297062690005987,
"output_span_s": 0.04115165399707621,
"model_math_expected_correct": false,
"post_first_tps": 48.600719673189765
},
{
"label": "short-code",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 39,
"max_tokens": 640,
"usage": {
"prompt_tokens": 39,
"completion_tokens": 640,
"total_tokens": 679,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "0cfefbf212bc9f281b7d6db86de0cff9837fa64d6418b94b9969dcc1257d824c",
"finish_reason": "length",
"elapsed_s": 14.12508190000517,
"ttft_s": 0.5644106310064672,
"output_span_s": 13.559835430998646,
"post_first_tps": 47.12446572465071
},
{
"label": "facts-8192",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 8064,
"max_tokens": 128,
"usage": {
"prompt_tokens": 8064,
"completion_tokens": 37,
"total_tokens": 8101,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "1f3e34f9d9c14266edfba45bb269ca494bea3da325e8f812dee3c313b6523241",
"finish_reason": "stop",
"elapsed_s": 23.95944005099591,
"ttft_s": 23.308079640999495,
"output_span_s": 0.6503994269951363,
"post_first_tps": 55.35060226962532
},
{
"label": "facts-32768",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 32640,
"max_tokens": 128,
"usage": {
"prompt_tokens": 32640,
"completion_tokens": 33,
"total_tokens": 32673,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "02713115b2fbcfabfb34ddfa72aa6350f79f0ffe15f51dcb82b8f8d36daa3d83",
"finish_reason": "stop",
"elapsed_s": 94.08873693899659,
"ttft_s": 93.41181218999554,
"output_span_s": 0.6758949190043495,
"post_first_tps": 47.34463760600348
},
{
"label": "facts-65536",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 65408,
"max_tokens": 128,
"usage": {
"prompt_tokens": 65408,
"completion_tokens": 30,
"total_tokens": 65438,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "ea747a073a28bc17437f6be4f78f56457b3b18046d58e7c42f31fa0c3bee8d86",
"finish_reason": "stop",
"elapsed_s": 193.14665208500082,
"ttft_s": 192.49806301100034,
"output_span_s": 0.647412133999751,
"post_first_tps": 44.79372331321049
},
{
"label": "facts-131072",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 130944,
"max_tokens": 128,
"usage": {
"prompt_tokens": 130944,
"completion_tokens": 37,
"total_tokens": 130981,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "b6b20328d40106eeb19cb637e6385ab3c8e45d0f58dcc5254f076cdc55605787",
"finish_reason": "stop",
"elapsed_s": 409.1125468879982,
"ttft_s": 408.2754174350048,
"output_span_s": 0.8361031969980104,
"post_first_tps": 43.05688595529394
},
{
"label": "facts-262144",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 262016,
"max_tokens": 128,
"usage": {
"prompt_tokens": 262016,
"completion_tokens": 128,
"total_tokens": 262144,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "c47479579e97aeb53463222f06d2734ec184ea2353a17f003465a5e65fb615a5",
"finish_reason": "length",
"elapsed_s": 914.6785091749989,
"ttft_s": 911.3639053750012,
"output_span_s": 3.3137420220009517,
"post_first_tps": 38.32525258659484
},
{
"label": "oversize-one-token",
"http": 400,
"valid": true,
"rendered_prompt_tokens": 262016,
"max_tokens": 129,
"usage": {},
"output_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"finish_reason": null,
"elapsed_s": 0.5764813370042248,
"post_first_tps": null
},
{
"label": "post-full-isolation",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 19,
"max_tokens": 32,
"usage": {
"prompt_tokens": 19,
"completion_tokens": 5,
"total_tokens": 24,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "7a9b0b11d402d62fd6fcaf7744aa26364b78669a5aa317c032ab397f2c77c699",
"finish_reason": "stop",
"elapsed_s": 0.4837543989997357,
"ttft_s": 0.41912436699931277,
"output_span_s": 0.06366241299838293,
"post_first_tps": 62.83142299525471
},
{
"label": "facts-full-repeat",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 262016,
"max_tokens": 128,
"usage": {
"prompt_tokens": 262016,
"completion_tokens": 128,
"total_tokens": 262144,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "e6c370273de79edf4cb6b606e2638af665a91455610efc15a4e320cb65d2d96f",
"finish_reason": "length",
"elapsed_s": 915.2546048380027,
"ttft_s": 911.3067076360021,
"output_span_s": 3.9470189030034817,
"post_first_tps": 32.176182359643484
},
{
"label": "history",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 46,
"max_tokens": 32,
"usage": {
"prompt_tokens": 46,
"completion_tokens": 3,
"total_tokens": 49,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "43aafb893521df3a8f416c74c452ce304ac9f272af8656b436ae40692e786d1b",
"finish_reason": "stop",
"elapsed_s": 0.6629222689953167,
"ttft_s": 0.5902045209950302,
"output_span_s": 0.07170939700154122,
"post_first_tps": 27.890347480637924
}
],
"failure": null,
"api_exit": 0,
"content_saved": false
}
}
@@ -0,0 +1,57 @@
{
"$PACK_DIR/dense.bin": {
"bytes": 1538035200,
"sha256": "d2af3d8331e5c7a1985d1d589747230f9d56719a6d33c7cddc9ee6b81cde6b13",
"verification": "sealed size, mtime, inode and root ownership rechecked"
},
"$PACK_DIR/tokenizer/chat_template.jinja": {
"bytes": 9993,
"sha256": "12827f24b742ea4e80cdc12dbcf9622227056b9f797252a3149263d4f9aaadce",
"verification": "sealed size, mtime, inode and root ownership rechecked"
},
"$PACK_DIR/tokenizer/tokenizer.json": {
"bytes": 541,
"sha256": "c0bd435efbc6c3b28964b47999afe16c4ad268c7c7c4e8cb3af410796a6f30bf",
"verification": "sealed size, mtime, inode and root ownership rechecked"
},
"$PACK_DIR/tokenizer/vocab.json": {
"bytes": 5737005,
"sha256": "4ba64f0332abcfb0b600b7df1537d1e836e68009d5fb7cdb77339738dc6365c4",
"verification": "sealed size, mtime, inode and root ownership rechecked"
},
"$PACK_DIR/tokenizer/merges.txt": {
"bytes": 3353258,
"sha256": "4ba698529766c7a2f5052083ea10cdf2485577f5237a332ee291054eb11e3332",
"verification": "sealed size, mtime, inode and root ownership rechecked"
},
"$PACK_DIR/tokenizer/token_type.json": {
"bytes": 744960,
"sha256": "5088c8c298fc06af8382ddb3b76c888703ac2634e82263b97eedcc2ad202738b",
"verification": "sealed size, mtime, inode and root ownership rechecked"
},
"$MTP_DIR/experts.bin": {
"bytes": 707788800,
"sha256": "09398406be61f1f54c93861f449e48b8df0bfccbc9ec9b2b7636775a6ea9244f",
"verification": "sealed size, mtime, inode and root ownership rechecked"
},
"$MTP_DIR/dense.bin": {
"bytes": 116099072,
"sha256": "c724dc0b0822ada5d2977bf5bde821605feabaa64ea2e0045b67ca656329070a",
"verification": "sealed size, mtime, inode and root ownership rechecked"
},
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00001-of-00002.gguf": {
"bytes": 39225954592,
"sha256": "92cee27ae5bbadcd732416a0f7a7f0acc092399dbbe8f5a5efa707c2ec0a49d7",
"verification": "sealed size, mtime, inode and root ownership rechecked"
},
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00002-of-00002.gguf": {
"bytes": 28800138432,
"sha256": "316b46f3a2dbd68c900f43136ab9449f9dcc3725dfd8c794847c204bc161e113",
"verification": "sealed size, mtime, inode and root ownership rechecked"
},
"$EXPERT_PROFILE": {
"bytes": 196632,
"sha256": "8f59b4aa8873209dff11c11e37bcda9529a1335b724a1afeea37bf6388975baf",
"verification": "sealed size, mtime, inode and root ownership rechecked"
}
}
@@ -0,0 +1,222 @@
#!/usr/bin/env python3
"""Three fresh native runs; only numeric timing and hash receipts persist.
Use under an independent GPU/resource guard, with the model router isolated.
Run: python campaign.py --source SOURCE --profile profile.json --out OUTPUT
RAM logs must live on tmpfs. No generated content is written by this script.
"""
import argparse
import hashlib
import json
import os
from pathlib import Path
import re
import signal
import sys
import threading
import time
TASKS = [
'Write a complete Python standard-library LRU cache module with expiry and locking, validation, iteration, detailed docstrings, demonstrations and boundary-case discussion. Write at least 1500 words of code and explanation.',
'Write a complete Python standard-library CSV import module with typed validation, error collection, transaction staging, provenance, test examples and extensive documentation. Write at least 1500 words of code and explanation.',
'Write a detailed story of at least 1500 words about a lighthouse keeper and marine biologist deciphering a research notebook. Develop their distinct voices, observations, uncertainty, and discoveries.',
'Explain accurate inventory audits, discrepancy investigation, provenance, reconciliation, and periodic checks in at least 1500 words with concrete examples and worked scenarios.',
'Act as an incident coordinator. Develop a detailed operational response plan for a failed local service: evidence collection, hypotheses, bounded tests, rollback, recovery verification and communication. Include worked scenarios and at least 1500 words.'
]
WARMUP = 'Write a detailed 1500-word guide to maintaining a community garden, with seasonal plans, worked examples and practical checklists.'
FILLER = '\n'.join(f'Archive record {i}: shelf {i%17}, item {(i*37)%997}, status reviewed, source verified, date unknown. Preserve provenance and record uncertainty.' for i in range(900))
def digest(value):
return hashlib.sha256(json.dumps(value).encode()).hexdigest()
def main():
ap = argparse.ArgumentParser()
ap.add_argument('--source', type=Path, required=True)
ap.add_argument('--profile', type=Path, required=True)
ap.add_argument('--out', type=Path, required=True)
ap.add_argument('--ram', type=Path, default=Path(os.environ.get('STRATA_TEST_RAM', '/run/strata-community')))
ap.add_argument('--runs', type=int, default=3)
args = ap.parse_args()
assert 1 <= args.runs <= 3
assert str(args.ram.resolve()).startswith('/run/'), 'use a RAM-backed /run directory'
assert args.ram.is_dir()
args.out.mkdir(exist_ok=True)
assert not (args.out / 'requests.json').exists(), 'do not overwrite a consumed run'
sys.path[:0] = [str(args.source), str(args.source / 'tools')]
from serve.server import StrataEngine, ENGINE_REQUEST
from serve.frontend import ChatTemplate
from strata_tokenizer import Tokenizer
class MeasuredEngine(StrataEngine):
def _parse_done(self, line):
self.done_line = line
return super()._parse_done(line)
assert 'STRATA_DBG_NAN' not in os.environ, 'qualification diagnostic must be absent'
profile = json.loads(args.profile.read_text())
native_args = [os.path.expandvars(x) for x in profile['args']]
binary = os.path.expandvars(profile['exe'])
cwd = os.path.expandvars(profile['cwd'])
tok = Tokenizer.from_gguf(Path(native_args[native_args.index('--native') + 1]))
tpl = ChatTemplate(Path(native_args[native_args.index('--pack') + 1]) / 'tokenizer/chat_template.jinja')
sampling = {'temperature': 0.0, 'seed': 17}
rows, runs = [], []
cancel = threading.Event()
interrupted = False
engine = None
failure = None
def stop(*_):
nonlocal interrupted
interrupted = True
cancel.set()
signal.signal(signal.SIGTERM, stop)
signal.signal(signal.SIGINT, stop)
def save():
for name, data in [('requests', rows), ('runs', runs)]:
(args.out / (name + '.json')).write_text(json.dumps(data, indent=2) + '\n')
def shaped(task, target):
rendered = tpl.render([
{'role': 'system', 'content': 'Follow the requested format and provide a thorough answer.'},
{'role': 'user', 'content': 'PAD_MARKER\n' + task}
], enable_thinking=False)
before, after = rendered.split('PAD_MARKER')
a, b = tok.encode(before, parse_special=True), tok.encode(after, parse_special=True)
pad = tok.encode(FILLER)
assert 0 < target - len(a) - len(b) <= len(pad)
ids = a + pad[:target - len(a) - len(b)] + b
assert len(ids) == target
return ids
fixtures = {(i, n): shaped(task, n) for n in (512, 7000) for i, task in enumerate(TASKS + [WARMUP])}
(args.out / 'fixtures.json').write_text(json.dumps([
{'task_index': i, 'prompt_tokens': n, 'input_ids_sha256': digest(ids), 'warmup': i == 5}
for (i, n), ids in fixtures.items()
], indent=2) + '\n')
def ask(ids, cap, label, measured=False, expected=None, json_check=False):
assert not interrupted
offset = log.stat().st_size
engine.done_line = None
start_utc = time.time()
started = time.monotonic()
arrivals, output = [], []
for token in engine.generate(ids, cap, sampling, cancel):
if token is not None:
arrivals.append(time.monotonic())
output.append(token)
elapsed = time.monotonic() - started
native = dict(engine.last)
text = tok.decode(output).replace('<|im_end|>', '').replace('<|endoftext|>', '').strip()
valid = (engine.done_line is not None and len(output) == native['generated']
and native['prompt_tokens'] == len(ids) and native['reused'] == 0
and native['prompt_read'] == len(ids) and bool(output))
if expected is not None:
valid &= text == expected
if json_check:
try:
obj = json.loads(text)
valid &= set(obj) == {'answer', 'ok'} and type(obj['answer']) is int and obj['ok'] is True
except (ValueError, TypeError):
valid = False
if measured or label.startswith('warm-shape'):
valid &= len(output) == cap and native['finish'] == 'length'
streak=longest=1
for j in range(1,len(output)):
streak=streak+1 if output[j]==output[j-1] else 1;longest=max(longest,streak)
valid &= len(set(output))>=25 and longest<64
with log.open('r') as f:
f.seek(offset)
lines = f.read().splitlines()
timing = [line for line in lines if ENGINE_REQUEST.search(line)]
row = {'run': len(runs), 'label': label, 'measured': measured,
'started_utc': start_utc, 'input_tokens': len(ids), 'output_cap': cap,
'output_tokens': len(output), 'input_ids_sha256': digest(ids),
'output_ids_sha256': digest(output), 'output_sha256': hashlib.sha256(text.encode()).hexdigest(),
'sampling': sampling, 'native': native, 'native_done_line': engine.done_line,
'native_timing_lines': timing,
'prompt_tps': native['prompt_read'] * 1000 / native['prompt_ms'],
'decode_tps': native['generated'] * 1000 / native['decode_ms'],
'ttft_s': arrivals[0] - started if arrivals else None,
'post_first_tps': (len(output) - 1) / (arrivals[-1] - arrivals[0]) if len(output) > 1 else None,
'total_s': elapsed, 'valid': bool(valid)}
if label == 'json-quality':
row['math_answer_correct'] = json.loads(text).get('answer') == 50 if valid else False
row['math_answer_is_runtime_gate'] = False
if measured:
prior = next((x for x in rows if x.get('label') == label and x.get('measured')), None)
if prior is not None:
row['matches_branch_repeat'] = row['output_ids_sha256'] == prior['output_ids_sha256']
assert row['matches_branch_repeat'], 'branch repeat changed: '+label
rows.append(row)
save()
print(json.dumps({'run': len(runs), 'label': label, 'measured': measured,
'prompt_tps': row['prompt_tps'], 'decode_tps': row['decode_tps'],
'valid': bool(valid)}), flush=True)
assert valid, 'protocol/length/isolation failure: ' + label
assert not interrupted, 'guard interruption'
try:
for run_index in range(args.runs):
log = args.ram / f'native-{run_index + 1}.log'
runs.append({'run': run_index + 1, 'binary_sha256': hashlib.file_digest(Path(binary).open('rb'), 'sha256').hexdigest(),
'sampling': sampling, 'args': native_args})
save()
started = time.monotonic()
engine = MeasuredEngine(binary, native_args, cwd=cwd, log=str(log), env=dict(os.environ))
runs[-1]['startup_ready_s'] = time.monotonic() - started
runs[-1]['info'] = engine.info
save()
for label, prompt, expected, jc in [
('isolation-a', 'Reply only with CANARY_MAPLE_73.', 'CANARY_MAPLE_73', False),
('isolation-b', 'Reply only with CANARY_RIVER_29.', 'CANARY_RIVER_29', False),
('json-quality', 'Calculate 2**5 + 6*3. Return exactly one JSON object with keys answer (the integer result) and ok (true), no markdown.', None, True)
]:
ids = tok.encode(tpl.render([{'role': 'user', 'content': prompt}], enable_thinking=False), parse_special=True)
ask(ids, 64, label, expected=expected, json_check=jc)
for n in (512, 7000):
ask(fixtures[(5, n)], 640, f'warm-shape-{n}')
for i in range(5):
ask(fixtures[(i, n)], 640, f'bench-{n}-{i}', measured=True)
ids = tok.encode(tpl.render([{'role': 'user', 'content': 'Reply only with CANARY_MAPLE_73.'}], enable_thinking=False), parse_special=True)
ask(ids, 64, 'post-long-isolation', expected='CANARY_MAPLE_73')
proc = engine.proc
started = time.monotonic()
proc.stdin.write('QUIT\n')
proc.stdin.flush()
proc.wait(timeout=75)
runs[-1]['native_exit'] = proc.returncode
runs[-1]['quit_exit_s'] = time.monotonic() - started
assert proc.returncode == 0
engine.close()
engine = None
raw = log.read_text()
assert not re.search(r'\b[1-9]\d* (?:of \d+ logits )?non-finite\b|\bnonfinite [1-9]\d*', raw)
runs[-1]['startup_lines'] = [line for line in raw.splitlines()
if re.match(r'^strata (?:generate|serve): (?:GPU \d+:|PCIe probe:|expert cache \d|\d+ of \d+ experts missing|\d+ MiB of VRAM free)', line)]
runs[-1]['native_log_sha256'] = hashlib.sha256(raw.encode()).hexdigest()
save()
for _ in range(5):
time.sleep(1)
assert not interrupted, 'guard interruption during delayed fault observation'
except BaseException as e:
failure = {'type': type(e).__name__, 'reason': str(e)}
finally:
if engine is not None:
proc = engine.proc
if proc is not None and proc.poll() is None:
proc.stdin.write('QUIT\n');proc.stdin.flush();proc.wait(timeout=75)
engine.close()
runs[-1]['native_exit'] = None if proc is None else proc.returncode
save()
(args.out / 'result.json').write_text(json.dumps({'failure': failure,
'run_count': len(runs), 'requests': len(rows), 'measured_requests': sum(r['measured'] for r in rows),
'generated_content_persisted': False}, indent=2) + '\n')
if failure:
raise SystemExit(1)
if __name__ == '__main__':
main()
@@ -0,0 +1 @@
248045,846,198,8917,5437,537,279,2614,2128,303,799,13901,13,271,2,4361,450,383,449,15153,19087,271,2495,450,579,4560,369,52965,13,1848,449,15153,19087,279,1788,1558,8213,4661,279,1788,4361,450,3421,11,440,198,636,2933,6982,579,15606,3040,18583,3604,279,33633,13,19481,3294,279,4560,471,279,5097,15015,321,16092,42481,198,6862,82,11,16350,11,5224,6526,11,76433,11,279,3370,878,471,369,33702,13,271,34447,364,321,16384,383,449,2972,35590,1253,417,22,15,318,18,17,18295,31230,4162,279,351,4175,318,59865,16,1203,8,383,33803,220,17,19,13,15,19,13,271,550,3437,488,615,271,91,735,32449,318,2495,450,4560,8,735,15153,19087,318,636,2933,6982,4560,8,735,198,91,4277,91,4277,91,4277,91,198,91,1558,3425,735,279,1788,54802,19913,82,735,279,1788,54802,19913,82,735,198,91,1332,279,1558,6107,735,11312,303,21360,11,3882,5981,383,279,3575,735,2972,528,314,50319,220,16,383,279,3575,332,318,275,17759,264,220,18,17,18295,3575,1174,50319,220,17,579,18054,1898,280,3173,494,12977,735,198,91,21360,4221,735,220,18,17,12,21,19,18295,735,2545,25,279,1558,369,383,279,3575,318,17,18,18295,557,6699,8,735,198,91,16401,11,351,4175,35494,16,1203,735,220,19,19,12,20,16,9341,2600,383,449,220497,220,20,15,22,15,735,220,17,18,12,17,20,9341,2600,383,279,417,22,15,735,198,91,9640,5122,735,3835,16,11,23,22,15,9341,2600,735,3835,16,20,15,9341,2600,735,198,91,63520,45543,318,44,4100,8,735,9542,735,874,318,1719,54802,19913,22651,874,9665,6000,90448,6982,628,958,8,735,198,91,5167,735,9542,735,524,3482,735,198,91,2193,735,685,310,220,17,21,17,42,735,220,18,17,42,539,1581,26,220,16,18,16,42,369,279,16384,21482,383,264,220,18,17,18295,3575,318,3924,3559,1174,220,17,21,17,42,1503,524,4786,735,271,760,4478,12558,369,279,15606,3040,18583,579,3750,1528,383,31107,3323,416,25,4437,5979,7072,6976,635,524,958,198,1719,1543,28463,7896,3482,318,3138,279,799,35,9455,7960,12,51319,1752,1503,553,1049,369,40352,90448,6982,944,11,524,198,32228,303,4361,450,13,48507,369,21966,48184,506,220,24,15,4,10,12655,11,748,4161,369,15218,1142,310,279,13540,13,271,550,18065,271,262,12619,14746,2318,271,21149,33621,279,19087,318,2083,1510,77,38766,4516,72,74927,449,15153,21966,1172,279,1510,8112,63,466,1510,72,24,16,20,63,5404,303,5530,3720,681,2640,198,684,11,321,4829,279,15153,1752,25,874,18826,11,874,52965,63670,13,1049,29478,279,1558,11,12427,279,198,82637,11,13325,264,1510,636,2933,25459,7561,321,13514,264,2124,440,264,51515,636,2933,38593,2424,321,264,1151,5148,13,271,8791,279,1510,636,2933,25459,63,3905,494,11,303,1906,25,271,16,13,1510,312,636,2933,25459,25918,63,471,264,90448,6982,488,5617,5941,440,90563,35,21563,2581,11071,3040,28,691,63,318,53390,799,6862,553,198,17,13,1510,636,2933,25459,63,383,25918,13,198,18,13,357,5303,25,1510,840,4920,4106,69160,589,2280,14,636,2933,6982,1284,5986,19441,300,1402,22,15,14,636,2933,1284,5986,1402,22,15,25,27086,7561,264,3809,15606,3040,198,256,1870,364,31107,3323,416,318,636,2933,6982,220,15,13,19,13,16,11,15153,3950,10862,220,17,15,17,21,13,16,11,357,1730,364,292,11958,2294,18,16,553,41717,25738,321,279,198,256,1510,7092,63,321,1510,9691,63,5038,13,18065,13514,1510,2388,12,636,2933,2318,7561,864,8213,424,440,279,21966,5642,198,256,1472,321,279,1245,4424,13,561,1542,5148,8211,424,948,4161,369,34579,3482,13,271,11861,1510,5917,12,27,2448,13867,898,63,318,269,1510,1665,14746,2318,63,1495,8,8211,279,1558,13,5339,1151,314,264,220,18,15,18295,1558,25,883,198,19186,4276,13,271,11280,7789,5621,13660,383,264,3618,421,2582,8213,2433,25,1510,312,395,443,63,318,1719,1581,220,23,15,23,15,369,1048,1092,198,2428,28471,1896,4829,26,279,90448,25459,5303,5055,443,10,16,8,321,1510,312,3662,220,15,13,15,13,15,13,15,63,310,5372,424,494,975,198,52453,1489,318,1719,1581,55559,45843,1132,11,430,40352,1503,553,271,550,561,2124,271,71093,2164,198,90,198,328,8251,763,328,636,2933,487,198,328,82637,763,37431,14,4595,82,2805,4175,17076,80,16,697,52562,3035,487,198,328,636,2933,763,313,198,220,328,1050,763,256,328,1211,1074,16,17,22,13,15,13,15,13,16,25,23,15,23,16,487,198,220,328,2448,763,37431,14,48,16451,18,13,23,12,23129,12,5666,11668,62137,12,7146,46,20819,48,16,1203,12,15,15,15,15,16,8404,12,15,15,15,15,17,75021,1644,487,198,220,328,2388,763,37431,14,2388,12,636,2933,2318,487,198,220,328,1742,763,328,840,4920,4106,69160,589,2280,14,636,2933,6982,1284,5986,19441,300,1402,22,15,14,636,2933,1284,5986,1402,22,15,25,27086,1,198,333,198,92,198,71093,271,63,1050,63,81588,310,264,4162,90448,25459,26,1510,2388,63,369,1542,1118,413,4161,10926,1017,13,357,2124,198,4058,51515,44644,38593,321,51515,2048,38593,4370,89482,264,9575,7620,5774,13,3382,1510,12882,79213,41575,2933,6971,27653,271,550,19480,421,4766,383,411,21966,271,12,2972,63,17867,3040,28185,1053,67639,1762,63,1902,381,220,15,159029,561,24207,92861,6297,4657,57559,82,383,175941,17,2261,279,1118,198,220,18612,13,561,1151,5148,7062,424,26,413,488,1542,90448,25459,539,1375,11,635,2166,13,198,12,2972,760,4220,1558,5601,383,279,3575,332,27718,312,77,2294,5409,2759,4912,220,24,24,24,63,681,3525,1510,692,12316,6256,54962,Line truncated
@@ -0,0 +1 @@
248045,846,198,7734,264,12654,709,421,4523,279,307,7324,76938,1324,13,248046,198,248045,74455,198
@@ -0,0 +1,148 @@
{
"source_tag": "v0.1.40.2",
"source_commit": "e8ca9afd03d839d4f8dbbe82dffce7f8a3bafd7a",
"archive_sha256": "706c799a7802b6df696d0d63c000b4538484d659afc57f70cbec7c7b3ba8d46c",
"local_patches": [],
"binary_sha256": "8ca822304881a259412656ae7ba63fdb9d8e2c31ce18d9f3149bc8a57448f311",
"source_files_verified": 2260,
"build_state": {
"ActiveState": "inactive",
"Result": "success",
"ExecMainStatus": "0"
},
"cmake_cache": [
"CMAKE_BUILD_TYPE:STRING=Release",
"CMAKE_CXX_COMPILER:STRING=/opt/intel/oneapi/compiler/2026.1/bin/icpx",
"CMAKE_C_COMPILER:STRING=/opt/intel/oneapi/compiler/2026.1/bin/icx",
"GGML_ACCELERATE:BOOL=ON",
"GGML_ALL_WARNINGS:BOOL=ON",
"GGML_ALL_WARNINGS_3RD_PARTY:BOOL=OFF",
"GGML_AMX_BF16:BOOL=OFF",
"GGML_AMX_INT8:BOOL=OFF",
"GGML_AMX_TILE:BOOL=OFF",
"GGML_AVX:BOOL=OFF",
"GGML_AVX2:BOOL=OFF",
"GGML_AVX512:BOOL=OFF",
"GGML_AVX512_BF16:BOOL=OFF",
"GGML_AVX512_VBMI:BOOL=OFF",
"GGML_AVX512_VNNI:BOOL=OFF",
"GGML_AVX_VNNI:BOOL=OFF",
"GGML_BACKEND_DIR:PATH=",
"GGML_BACKEND_DL:BOOL=OFF",
"GGML_BIN_INSTALL_DIR:PATH=bin",
"GGML_BLAS:BOOL=OFF",
"GGML_BLAS_VENDOR:STRING=Generic",
"GGML_BMI2:BOOL=OFF",
"GGML_BUILD_EXAMPLES:BOOL=OFF",
"GGML_BUILD_TESTS:BOOL=OFF",
"GGML_CCACHE:BOOL=ON",
"GGML_CCACHE_FOUND:FILEPATH=GGML_CCACHE_FOUND-NOTFOUND",
"GGML_CPU:BOOL=ON",
"GGML_CPU_ALL_VARIANTS:BOOL=OFF",
"GGML_CPU_ARM_ARCH:STRING=",
"GGML_CPU_HBM:BOOL=OFF",
"GGML_CPU_KLEIDIAI:BOOL=OFF",
"GGML_CPU_POWERPC_CPUTYPE:STRING=",
"GGML_CPU_REPACK:BOOL=ON",
"GGML_CUDA:BOOL=OFF",
"GGML_CUDA_COMPRESSION_MODE:STRING=size",
"GGML_CUDA_FA:BOOL=ON",
"GGML_CUDA_FA_ALL_QUANTS:BOOL=OFF",
"GGML_CUDA_FA_QUANTS:STRING=q4_0-q4_0;q8_0-q8_0;f16-f16;bf16-bf16",
"GGML_CUDA_FORCE_CUBLAS:BOOL=OFF",
"GGML_CUDA_FORCE_MMQ:BOOL=OFF",
"GGML_CUDA_GRAPHS:BOOL=OFF",
"GGML_CUDA_NCCL:BOOL=ON",
"GGML_CUDA_NO_PEER_COPY:BOOL=OFF",
"GGML_CUDA_NO_VMM:BOOL=OFF",
"GGML_ET:BOOL=OFF",
"GGML_ET_SYSEMU:BOOL=OFF",
"GGML_F16C:BOOL=OFF",
"GGML_FATAL_WARNINGS:BOOL=OFF",
"GGML_FMA:BOOL=OFF",
"GGML_GPROF:BOOL=OFF",
"GGML_HEXAGON:BOOL=OFF",
"GGML_HIP:BOOL=OFF",
"GGML_HIP_EXPORT_METRICS:BOOL=OFF",
"GGML_HIP_GRAPHS:BOOL=ON",
"GGML_HIP_MMQ_MFMA:BOOL=ON",
"GGML_HIP_NO_VMM:BOOL=ON",
"GGML_HIP_RCCL:BOOL=OFF",
"GGML_INCLUDE_INSTALL_DIR:PATH=include",
"GGML_LASX:BOOL=ON",
"GGML_LIB_INSTALL_DIR:PATH=lib",
"GGML_LLAMAFILE:BOOL=OFF",
"GGML_LSX:BOOL=ON",
"GGML_LTO:BOOL=OFF",
"GGML_METAL:BOOL=OFF",
"GGML_METAL_EMBED_LIBRARY:BOOL=OFF",
"GGML_METAL_MACOSX_VERSION_MIN:STRING=",
"GGML_METAL_NDEBUG:BOOL=OFF",
"GGML_METAL_SHADER_DEBUG:BOOL=OFF",
"GGML_METAL_STD:STRING=",
"GGML_METAL_TARGET_OS:STRING=macos",
"GGML_MUSA:BOOL=OFF",
"GGML_MUSA_GRAPHS:BOOL=OFF",
"GGML_MUSA_MUDNN_COPY:BOOL=OFF",
"GGML_NATIVE:BOOL=ON",
"GGML_OPENCL:BOOL=OFF",
"GGML_OPENCL_EMBED_KERNELS:BOOL=ON",
"GGML_OPENCL_PROFILING:BOOL=OFF",
"GGML_OPENCL_TARGET_VERSION:STRING=300",
"GGML_OPENCL_USE_ADRENO_KERNELS:BOOL=ON",
"GGML_OPENMP:BOOL=OFF",
"GGML_OPENMP_FETCH:BOOL=OFF",
"GGML_OPENVINO:BOOL=OFF",
"GGML_RPC:BOOL=OFF",
"GGML_RVV:BOOL=ON",
"GGML_RV_ZFH:BOOL=ON",
"GGML_RV_ZICBOP:BOOL=ON",
"GGML_RV_ZIHINTPAUSE:BOOL=ON",
"GGML_RV_ZVFBFWMA:BOOL=OFF",
"GGML_RV_ZVFH:BOOL=ON",
"GGML_SANITIZE_ADDRESS:BOOL=OFF",
"GGML_SANITIZE_THREAD:BOOL=OFF",
"GGML_SANITIZE_UNDEFINED:BOOL=OFF",
"GGML_SCCACHE_FOUND:FILEPATH=GGML_SCCACHE_FOUND-NOTFOUND",
"GGML_SCHED_MAX_COPIES:STRING=4",
"GGML_SCHED_NO_REALLOC:BOOL=OFF",
"GGML_SSE42:BOOL=OFF",
"GGML_STATIC:BOOL=ON",
"GGML_SYCL:BOOL=OFF",
"GGML_SYCL_DEVICE_ARCH:STRING=",
"GGML_SYCL_DNN:BOOL=ON",
"GGML_SYCL_F16:BOOL=OFF",
"GGML_SYCL_GRAPH:BOOL=ON",
"GGML_SYCL_HOST_MEM_FALLBACK:BOOL=ON",
"GGML_SYCL_SUPPORT_LEVEL_ZERO_API:BOOL=ON",
"GGML_SYCL_TARGET:STRING=INTEL",
"GGML_VIRTGPU:BOOL=OFF",
"GGML_VIRTGPU_BACKEND:BOOL=OFF",
"GGML_VULKAN:BOOL=OFF",
"GGML_VULKAN_CHECK_RESULTS:BOOL=OFF",
"GGML_VULKAN_DEBUG:BOOL=OFF",
"GGML_VULKAN_MEMORY_DEBUG:BOOL=OFF",
"GGML_VULKAN_RUN_TESTS:BOOL=OFF",
"GGML_VULKAN_SHADERS_GEN_TOOLCHAIN:FILEPATH=",
"GGML_VULKAN_SHADER_DEBUG_INFO:BOOL=OFF",
"GGML_VULKAN_VALIDATE:BOOL=OFF",
"GGML_VXE:BOOL=ON",
"GGML_WEBGPU:BOOL=OFF",
"GGML_WEBGPU_CPU_PROFILE:BOOL=OFF",
"GGML_WEBGPU_DEBUG:BOOL=OFF",
"GGML_WEBGPU_GPU_PROFILE:BOOL=OFF",
"GGML_WEBGPU_JSPI:BOOL=ON",
"GGML_XTHEADVECTOR:BOOL=OFF",
"GGML_ZDNN:BOOL=OFF",
"GGML_ZENDNN:BOOL=OFF",
"STRATA_GGML_DIR:PATH=$PREPARATION_ROOT/deps/llama.cpp-3cf03257f219afbe7334045ff7c6a06ac68c627d",
"STRATA_NATIVE_EXPERTS:BOOL=ON",
"STRATA_SYCL_AOT:STRING=",
"STRATA_SYCL_PARITY:BOOL=ON",
"STRATA_ZE_LOADER:FILEPATH=/usr/lib/x86_64-linux-gnu/libze_loader.so",
"GGML_AVAILABLE_BACKENDS:INTERNAL=ggml-cpu",
"GGML_CUDA_COMPRESSION_MODE-STRINGS:INTERNAL=none;speed;balance;size",
"GGML_OPENMP_ENABLED:INTERNAL=OFF",
"STRATA_HAVE_AVXVNNI_INTRINSICS:INTERNAL=1"
]
}
@@ -0,0 +1,23 @@
{
"8k-512": {
"native_context": 8192,
"usable_api_context": 8184,
"prefill": 512,
"reserve_mib": 3072,
"profile": "profile-8k-512.json"
},
"8k-4096": {
"native_context": 8192,
"usable_api_context": 8184,
"prefill": 4096,
"reserve_mib": 3072,
"profile": "profile-8k-4096.json"
},
"262k-512": {
"native_context": 262152,
"usable_api_context": 262144,
"prefill": 512,
"reserve_mib": 4096,
"profile": "profile-262k-512.json"
}
}
@@ -0,0 +1,24 @@
{
"variables": {
"ONEAPI_DEVICE_SELECTOR": "level_zero:0",
"SYCL_CACHE_PERSISTENT": "0",
"SYCL_PROGRAM_COMPILE_OPTIONS": "-cl-fp32-correctly-rounded-divide-sqrt",
"STRATA_MIRROR_MIB": "16384",
"STRATA_VERIFY_DEVICE_PLAN": "1",
"STRATA_VERIFY_NO_HOST": "1",
"STRATA_WARM_GRAPHS": "0",
"STRATA_STAGER_THREADS": "4",
"OMP_NUM_THREADS": "4",
"MKL_NUM_THREADS": "4"
},
"absent": [
"STRATA_DEBUG",
"STRATA_DBG_NAN",
"STRATA_VERIFY_EAGER",
"STRATA_QFUSE"
],
"alias_check": "upstream default enabled",
"public_fixture_additional_variable": {
"STRATA_TRACE": "1"
}
}
@@ -0,0 +1,210 @@
#!/usr/bin/env python3
"""Three fresh native runs; only numeric timing and hash receipts persist.
Use under an independent GPU/resource guard, with the model router isolated.
Run: python campaign.py --source SOURCE --profile profile.json --out OUTPUT
RAM logs must live on tmpfs. No generated content is written by this script.
"""
import argparse
import hashlib
import json
import os
from pathlib import Path
import re
import signal
import sys
import threading
import time
TASKS = [
'Write a complete Python standard-library LRU cache module with expiry and locking, validation, iteration, detailed docstrings, demonstrations and boundary-case discussion. Write at least 1500 words of code and explanation.',
'Write a complete Python standard-library CSV import module with typed validation, error collection, transaction staging, provenance, test examples and extensive documentation. Write at least 1500 words of code and explanation.',
'Write a detailed story of at least 1500 words about a lighthouse keeper and marine biologist deciphering a research notebook. Develop their distinct voices, observations, uncertainty, and discoveries.',
'Explain accurate inventory audits, discrepancy investigation, provenance, reconciliation, and periodic checks in at least 1500 words with concrete examples and worked scenarios.',
'Act as an incident coordinator. Develop a detailed operational response plan for a failed local service: evidence collection, hypotheses, bounded tests, rollback, recovery verification and communication. Include worked scenarios and at least 1500 words.'
]
WARMUP = 'Write a detailed 1500-word guide to maintaining a community garden, with seasonal plans, worked examples and practical checklists.'
FILLER = '\n'.join(f'Archive record {i}: shelf {i%17}, item {(i*37)%997}, status reviewed, source verified, date unknown. Preserve provenance and record uncertainty.' for i in range(900))
def digest(value):
return hashlib.sha256(json.dumps(value).encode()).hexdigest()
def main():
ap = argparse.ArgumentParser()
ap.add_argument('--source', type=Path, required=True)
ap.add_argument('--profile', type=Path, required=True)
ap.add_argument('--out', type=Path, required=True)
ap.add_argument('--ram', type=Path, default=Path(os.environ.get('STRATA_TEST_RAM', '/run/strata-community')))
ap.add_argument('--runs', type=int, default=3)
args = ap.parse_args()
assert 1 <= args.runs <= 3
assert str(args.ram.resolve()).startswith('/run/'), 'use a RAM-backed /run directory'
assert args.ram.is_dir()
args.out.mkdir(exist_ok=True)
assert not (args.out / 'requests.json').exists(), 'do not overwrite a consumed run'
sys.path[:0] = [str(args.source), str(args.source / 'tools')]
from serve.server import StrataEngine, ENGINE_REQUEST
from serve.frontend import ChatTemplate
from strata_tokenizer import Tokenizer
class MeasuredEngine(StrataEngine):
def _parse_done(self, line):
self.done_line = line
return super()._parse_done(line)
profile = json.loads(args.profile.read_text())
native_args = [os.path.expandvars(x) for x in profile['args']]
binary = os.path.expandvars(profile['exe'])
cwd = os.path.expandvars(profile['cwd'])
tok = Tokenizer.from_gguf(Path(native_args[native_args.index('--native') + 1]))
tpl = ChatTemplate(Path(native_args[native_args.index('--pack') + 1]) / 'tokenizer/chat_template.jinja')
sampling = {'temperature': 0.0, 'seed': 17}
rows, runs = [], []
cancel = threading.Event()
interrupted = False
engine = None
failure = None
def stop(*_):
nonlocal interrupted
interrupted = True
cancel.set()
signal.signal(signal.SIGTERM, stop)
signal.signal(signal.SIGINT, stop)
def save():
for name, data in [('requests', rows), ('runs', runs)]:
(args.out / (name + '.json')).write_text(json.dumps(data, indent=2) + '\n')
def shaped(task, target):
rendered = tpl.render([
{'role': 'system', 'content': 'Follow the requested format and provide a thorough answer.'},
{'role': 'user', 'content': 'PAD_MARKER\n' + task}
], enable_thinking=False)
before, after = rendered.split('PAD_MARKER')
a, b = tok.encode(before, parse_special=True), tok.encode(after, parse_special=True)
pad = tok.encode(FILLER)
assert 0 < target - len(a) - len(b) <= len(pad)
ids = a + pad[:target - len(a) - len(b)] + b
assert len(ids) == target
return ids
fixtures = {(i, n): shaped(task, n) for n in (512, 7000) for i, task in enumerate(TASKS + [WARMUP])}
(args.out / 'fixtures.json').write_text(json.dumps([
{'task_index': i, 'prompt_tokens': n, 'input_ids_sha256': digest(ids), 'warmup': i == 5}
for (i, n), ids in fixtures.items()
], indent=2) + '\n')
def ask(ids, cap, label, measured=False, expected=None, json_check=False):
assert not interrupted
offset = log.stat().st_size
engine.done_line = None
start_utc = time.time()
started = time.monotonic()
arrivals, output = [], []
for token in engine.generate(ids, cap, sampling, cancel):
if token is not None:
arrivals.append(time.monotonic())
output.append(token)
elapsed = time.monotonic() - started
native = dict(engine.last)
text = tok.decode(output).replace('<|im_end|>', '').replace('<|endoftext|>', '').strip()
valid = (engine.done_line is not None and len(output) == native['generated']
and native['prompt_tokens'] == len(ids) and native['reused'] == 0
and native['prompt_read'] == len(ids) and bool(output))
if expected is not None:
valid &= text == expected
if json_check:
try:
obj = json.loads(text)
valid &= set(obj) == {'answer', 'ok'} and type(obj['answer']) is int and obj['ok'] is True
except (ValueError, TypeError):
valid = False
if measured or label.startswith('warm-shape'):
valid &= len(output) == cap and native['finish'] == 'length'
with log.open('r') as f:
f.seek(offset)
lines = f.read().splitlines()
timing = [line for line in lines if ENGINE_REQUEST.search(line)]
row = {'run': len(runs), 'label': label, 'measured': measured,
'started_utc': start_utc, 'input_tokens': len(ids), 'output_cap': cap,
'output_tokens': len(output), 'input_ids_sha256': digest(ids),
'output_ids_sha256': digest(output), 'output_sha256': hashlib.sha256(text.encode()).hexdigest(),
'sampling': sampling, 'native': native, 'native_done_line': engine.done_line,
'native_timing_lines': timing,
'prompt_tps': native['prompt_read'] * 1000 / native['prompt_ms'],
'decode_tps': native['generated'] * 1000 / native['decode_ms'],
'ttft_s': arrivals[0] - started if arrivals else None,
'post_first_tps': (len(output) - 1) / (arrivals[-1] - arrivals[0]) if len(output) > 1 else None,
'total_s': elapsed, 'valid': bool(valid)}
if label == 'json-quality':
row['math_answer_correct'] = json.loads(text).get('answer') == 50 if valid else False
row['math_answer_is_runtime_gate'] = False
rows.append(row)
save()
print(json.dumps({'run': len(runs), 'label': label, 'measured': measured,
'prompt_tps': row['prompt_tps'], 'decode_tps': row['decode_tps'],
'valid': bool(valid)}), flush=True)
assert valid, 'protocol/length/isolation failure: ' + label
assert not interrupted, 'guard interruption'
try:
for run_index in range(args.runs):
log = args.ram / f'native-{run_index + 1}.log'
runs.append({'run': run_index + 1, 'binary_sha256': hashlib.file_digest(Path(binary).open('rb'), 'sha256').hexdigest(),
'sampling': sampling, 'args': native_args})
save()
started = time.monotonic()
engine = MeasuredEngine(binary, native_args, cwd=cwd, log=str(log), env=dict(os.environ))
runs[-1]['startup_ready_s'] = time.monotonic() - started
runs[-1]['info'] = engine.info
save()
for label, prompt, expected, jc in [
('isolation-a', 'Reply only with CANARY_MAPLE_73.', 'CANARY_MAPLE_73', False),
('isolation-b', 'Reply only with CANARY_RIVER_29.', 'CANARY_RIVER_29', False),
('json-quality', 'Calculate 2**5 + 6*3. Return exactly one JSON object with keys answer (the integer result) and ok (true), no markdown.', None, True)
]:
ids = tok.encode(tpl.render([{'role': 'user', 'content': prompt}], enable_thinking=False), parse_special=True)
ask(ids, 64, label, expected=expected, json_check=jc)
for n in (512, 7000):
ask(fixtures[(5, n)], 640, f'warm-shape-{n}')
for i in range(5):
ask(fixtures[(i, n)], 640, f'bench-{n}-{i}', measured=True)
ids = tok.encode(tpl.render([{'role': 'user', 'content': 'Reply only with CANARY_MAPLE_73.'}], enable_thinking=False), parse_special=True)
ask(ids, 64, 'post-long-isolation', expected='CANARY_MAPLE_73')
proc = engine.proc
started = time.monotonic()
proc.stdin.write('QUIT\n')
proc.stdin.flush()
proc.wait(timeout=75)
runs[-1]['native_exit'] = proc.returncode
runs[-1]['quit_exit_s'] = time.monotonic() - started
assert proc.returncode == 0
engine.close()
engine = None
raw = log.read_text()
assert not re.search(r'\b[1-9]\d* (?:of \d+ logits )?non-finite\b|\bnonfinite [1-9]\d*', raw)
runs[-1]['startup_lines'] = [line for line in raw.splitlines()
if re.match(r'^strata (?:generate|serve): (?:GPU \d+:|PCIe probe:|expert cache \d|\d+ of \d+ experts missing|\d+ MiB of VRAM free)', line)]
runs[-1]['native_log_sha256'] = hashlib.sha256(raw.encode()).hexdigest()
save()
for _ in range(5):
time.sleep(1)
assert not interrupted, 'guard interruption during delayed fault observation'
except BaseException as e:
failure = {'type': type(e).__name__, 'reason': str(e)}
finally:
if engine is not None:
proc = engine.proc
engine.close()
runs[-1]['native_exit'] = None if proc is None else proc.returncode
save()
(args.out / 'result.json').write_text(json.dumps({'failure': failure,
'run_count': len(runs), 'requests': len(rows), 'measured_requests': sum(r['measured'] for r in rows),
'generated_content_persisted': False}, indent=2) + '\n')
if failure:
raise SystemExit(1)
if __name__ == '__main__':
main()
@@ -0,0 +1,98 @@
{
"scope": "individual capacity/recall checks, not three-run full-window benchmark",
"native_MTP4": {
"prompt_tokens": 262016,
"output_tokens": 128,
"ttft_s": 910.7536279289998,
"prompt_tps": 287.7139481024282,
"decode_tps": 35.76318068788243,
"reused": 0,
"exact_matches_target_only": true
},
"api_full_reads": [
{
"label": "facts-262144",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 262016,
"max_tokens": 128,
"usage": {
"prompt_tokens": 262016,
"completion_tokens": 128,
"total_tokens": 262144,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "c47479579e97aeb53463222f06d2734ec184ea2353a17f003465a5e65fb615a5",
"finish_reason": "length",
"elapsed_s": 914.6785091749989,
"ttft_s": 911.3639053750012,
"output_span_s": 3.3137420220009517,
"post_first_tps": 38.32525258659484
},
{
"label": "facts-full-repeat",
"http": 200,
"valid": true,
"rendered_prompt_tokens": 262016,
"max_tokens": 128,
"usage": {
"prompt_tokens": 262016,
"completion_tokens": 128,
"total_tokens": 262144,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"output_sha256": "e6c370273de79edf4cb6b606e2638af665a91455610efc15a4e320cb65d2d96f",
"finish_reason": "length",
"elapsed_s": 915.2546048380027,
"ttft_s": 911.3067076360021,
"output_span_s": 3.9470189030034817,
"post_first_tps": 32.176182359643484
}
],
"private_routed_capacity_checks": {
"preboot": {
"checks_passed": 7,
"all_valid": true,
"full_request": {
"usage": {
"prompt_tokens": 261504,
"completion_tokens": 640,
"total_tokens": 262144,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"max_tokens": 640,
"ttft_s": 910.225896431999,
"elapsed_s": 928.2507263190055,
"post_first_tps": 35.45286830099677,
"valid": true
},
"decode_metric": "SSE output tokens after first emitted token divided by output span, distinct from native timing"
},
"postboot": {
"checks_passed": 7,
"all_valid": true,
"full_request": {
"usage": {
"prompt_tokens": 262016,
"completion_tokens": 128,
"total_tokens": 262144,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"max_tokens": 128,
"ttft_s": 958.1560878180001,
"elapsed_s": 961.9383172559999,
"post_first_tps": 33.58340494798331,
"valid": true
},
"decode_metric": "SSE output tokens after first emitted token divided by output span, distinct from native timing"
}
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,8 @@
{
"campaign.py": "063ab0029e3132992a662b0c7026ccb28483f2b1c42c2eaad089629e447c07d0",
"benchy-campaign.py": "4e4e32032aeecfdd6fa219925d0ad6944fcdc3d7660d889290a45157c1ccb24f",
"pilot.py": "3b91e9871009d99feb2f2b19bf586c1ed7fb9933e6f2754f26b630ac3e84aa72",
"api-qualify.py": "666f1560ad0dbf4f5d9e67dab63ec917a668c460ad4996fb6ca9fe2145e6a3de",
"context-reference.py": "c8f2754416ffbb9c4cc860692127acd69bce9c653c2af488e57af55c35d5af00",
"context-campaign.py": "40b772aa2e8f2867148a4e6c0268c39a77f57c7b10d23bbddab619990a8cbfb1"
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,18 @@
{
"no_api_or_gpu_request": true,
"main_fixture_hashes_match_measured": 12,
"public_fixtures": {
"benchy-short.ids": {
"tokens": 20,
"input_ids_sha256": "05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d"
},
"benchy-long.ids": {
"tokens": 2185,
"input_ids_sha256": "cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514"
}
},
"portable_script_sha256": {
"benchmark.py": "437ac5f7f430fd7b2f63c91c4adaa787611123d65f4a25c6e26ba6771972caa7",
"public-fixtures.py": "2b76c4b1aa509afe1b1ef290831cbf542a7d43f0ad1dd6698970f487ec6cc865"
}
}
@@ -0,0 +1,21 @@
#!/usr/bin/env python3
"""Prepare the pinned Q2_0 draft pack with upstream hash verification."""
import argparse
from pathlib import Path
import subprocess
import sys
ap = argparse.ArgumentParser()
ap.add_argument('--source', type=Path, required=True)
ap.add_argument('--assets', type=Path, required=True)
a = ap.parse_args()
sys.path.insert(0, str(a.source / 'tools'))
import mtp_fetch as m
assert m.REVISION == 'de4b8e4d43b917e7706784d8bb445c9af86a3540'
m.resolve_repo = lambda: None # No fallback to a floating revision.
m.fetch(str(a.assets / 'mtp-source'), None)
assert not m.verify(str(a.assets / 'mtp-source'))
subprocess.run([sys.executable, str(a.source / 'tools/mtp_pack.py'), '--src', str(a.assets / 'mtp-source'),
'--experts', 'q2_0', '--out', str(a.assets / 'mtp-q2_0.gguf')], check=True)
subprocess.run([sys.executable, str(a.source / 'tools/mtp_rt.py'), '--gguf', str(a.assets / 'mtp-q2_0.gguf'),
'--out', str(a.assets / 'mtp-rt')], check=True)
@@ -0,0 +1,70 @@
{
"engine": "strata",
"exe": "$STRATA_ROOT/build-sycl/strata",
"args": [
"--pack",
"$PACK_DIR",
"--native",
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00001-of-00002.gguf",
"--ple-gguf",
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00002-of-00002.gguf",
"--expert-profile",
"$EXPERT_PROFILE",
"--expert-cache",
"auto",
"--stream-experts",
"--pcie-frac",
"1",
"--prefill",
"512",
"--spec",
"4",
"--mtp-max-t",
"4",
"--suffix-draft",
"0",
"--mtp",
"$MTP_DIR",
"--max-context",
"262152",
"--kv",
"int8",
"--vram-reserve-mib",
"4096",
"--adapt-every",
"0",
"--adapt-swaps",
"0",
"--pool-workers",
"4",
"--prompt-cache",
"0",
"--prompt-cache-every",
"0",
"--conversation-cache-mib",
"0",
"--short-read",
"0",
"--spec-min-p",
"0.5",
"--no-prefill-borrow"
],
"cwd": "$STRATA_ROOT",
"tokenizer": "$PACK_DIR/tokenizer",
"model_name": "qwen3.8-flash-next-strata-iq2-xs-262k",
"backend": "sycl",
"host": "127.0.0.1",
"parallel": 1,
"api_monitor": false,
"open_browser": false,
"sampling": {
"temperature": 0.0,
"seed": 17
},
"engine_silence_s": 180,
"cors_origins": [],
"allowed_hosts": [
"127.0.0.1",
"localhost"
]
}
@@ -0,0 +1,69 @@
{
"engine": "strata",
"exe": "$STRATA_ROOT/build-sycl/strata",
"args": [
"--pack",
"$PACK_DIR",
"--native",
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00001-of-00002.gguf",
"--ple-gguf",
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00002-of-00002.gguf",
"--expert-profile",
"$EXPERT_PROFILE",
"--expert-cache",
"auto",
"--stream-experts",
"--pcie-frac",
"1",
"--prefill",
"4096",
"--spec",
"4",
"--mtp-max-t",
"4",
"--suffix-draft",
"0",
"--mtp",
"$MTP_DIR",
"--max-context",
"8192",
"--kv",
"int8",
"--vram-reserve-mib",
"3072",
"--adapt-every",
"0",
"--adapt-swaps",
"0",
"--pool-workers",
"4",
"--prompt-cache",
"0",
"--prompt-cache-every",
"0",
"--conversation-cache-mib",
"0",
"--short-read",
"0",
"--spec-min-p",
"0.5"
],
"cwd": "$STRATA_ROOT",
"tokenizer": "$PACK_DIR/tokenizer",
"model_name": "qwen3.8-flash-next-strata-iq2-xs-8k",
"backend": "sycl",
"host": "127.0.0.1",
"parallel": 1,
"api_monitor": false,
"open_browser": false,
"sampling": {
"temperature": 0.0,
"seed": 17
},
"engine_silence_s": 180,
"cors_origins": [],
"allowed_hosts": [
"127.0.0.1",
"localhost"
]
}
@@ -0,0 +1,69 @@
{
"engine": "strata",
"exe": "$STRATA_ROOT/build-sycl/strata",
"args": [
"--pack",
"$PACK_DIR",
"--native",
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00001-of-00002.gguf",
"--ple-gguf",
"$MODEL_DIR/Qwen3.8-Flash-Next-GSQ-RCO-IQ2_XS-00002-of-00002.gguf",
"--expert-profile",
"$EXPERT_PROFILE",
"--expert-cache",
"auto",
"--stream-experts",
"--pcie-frac",
"1",
"--prefill",
"512",
"--spec",
"4",
"--mtp-max-t",
"4",
"--suffix-draft",
"0",
"--mtp",
"$MTP_DIR",
"--max-context",
"8192",
"--kv",
"int8",
"--vram-reserve-mib",
"3072",
"--adapt-every",
"0",
"--adapt-swaps",
"0",
"--pool-workers",
"4",
"--prompt-cache",
"0",
"--prompt-cache-every",
"0",
"--conversation-cache-mib",
"0",
"--short-read",
"0",
"--spec-min-p",
"0.5"
],
"cwd": "$STRATA_ROOT",
"tokenizer": "$PACK_DIR/tokenizer",
"model_name": "qwen3.8-flash-next-strata-iq2-xs-8k",
"backend": "sycl",
"host": "127.0.0.1",
"parallel": 1,
"api_monitor": false,
"open_browser": false,
"sampling": {
"temperature": 0.0,
"seed": 17
},
"engine_silence_s": 180,
"cors_origins": [],
"allowed_hosts": [
"127.0.0.1",
"localhost"
]
}
@@ -0,0 +1,140 @@
#!/usr/bin/env python3
"""Bounded prefill diagnosis; content lives only in RAM and process memory."""
import argparse, hashlib, importlib.util, json, os, re, signal, sys, threading, time
from pathlib import Path
R = Path(__file__).resolve().parent
SOURCE = Path(os.environ['STRATA_ROOT'])
def digest(x):
return hashlib.sha256(json.dumps(x).encode()).hexdigest()
def main():
ap = argparse.ArgumentParser()
ap.add_argument('mode', choices=['matched'])
a = ap.parse_args()
runid = os.environ.get('STRATA_TEST_ID','public-fixtures')
ram = Path(os.environ['STRATA_TEST_RAM'])
out = Path(os.environ['BENCH_OUTPUT'])
out.mkdir(exist_ok=False)
sys.path[:0] = [str(SOURCE), str(SOURCE / 'tools')]
from serve.server import StrataEngine, ENGINE_REQUEST
from serve.frontend import ChatTemplate
from strata_tokenizer import Tokenizer
spec = importlib.util.spec_from_file_location('frozen', R / 'frozen-community.py')
frozen = importlib.util.module_from_spec(spec); spec.loader.exec_module(frozen)
cfg = json.loads(Path(os.environ.get('STRATA_TEST_PROFILE',str(R/'profile.json'))).read_text())
cfg['exe']=os.path.expandvars(cfg['exe']);cfg['cwd']=os.path.expandvars(cfg['cwd'])
cfg['args']=[os.path.expandvars(x) for x in cfg['args']]
tok = Tokenizer.from_gguf(Path(cfg['args'][cfg['args'].index('--native') + 1]))
tpl = ChatTemplate(Path(cfg['args'][cfg['args'].index('--pack') + 1]) / 'tokenizer/chat_template.jinja')
def shaped(task, target):
rendered = tpl.render([{'role':'system','content':'Follow the requested format and provide a thorough answer.'},
{'role':'user','content':'PAD_MARKER\n'+task}], enable_thinking=False)
before, after = rendered.split('PAD_MARKER')
aa, bb = tok.encode(before, parse_special=True), tok.encode(after, parse_special=True)
ids = aa + tok.encode(frozen.FILLER)[:target-len(aa)-len(bb)] + bb
assert len(ids) == target
return ids
public = [int(x) for x in (R / 'benchy-long.ids').read_text().strip().split(',')]
assert len(public) == 2185
bench7000 = (public[:2000] * 4)[:7000]
our7000 = shaped(frozen.TASKS[0], 7000)
our512 = shaped(frozen.TASKS[0], 512)
warm = shaped(frozen.WARMUP, 512)
canary = tok.encode(tpl.render([{'role':'user','content':'Reply only with CANARY_MAPLE_73.'}], enable_thinking=False), parse_special=True)
env = dict(os.environ); env['STRATA_TRACE']='1'; assert 'STRATA_DBG_NAN' not in env
short=[int(x) for x in (R/'benchy-short.ids').read_text().strip().split(',')]; assert len(short)==20
class Engine(StrataEngine):
def _parse_done(self, line):
self.done_line = line
return super()._parse_done(line)
cancel = threading.Event()
signal.signal(signal.SIGTERM, lambda *_: cancel.set())
signal.signal(signal.SIGINT, lambda *_: cancel.set())
engine = None; rows = []; failure = None; life = {}
streams = {}
log = ram / 'native.log'
def save():
(out / 'requests.json').write_text(json.dumps(rows, indent=2)+'\n')
(out / 'lifecycle.json').write_text(json.dumps(life, indent=2)+'\n')
def io():
return {k:int(v) for k,v in (x.split(':',1) for x in Path(f'/proc/{engine.proc.pid}/io').read_text().splitlines())}
def ask(ids, cap, label, expected=None):
assert not cancel.is_set()
offset = log.stat().st_size; before = io(); engine.done_line = None
arrivals = []; output = []; start = time.monotonic()
for t in engine.generate(ids, cap, {'temperature':0.,'seed':17}, cancel):
if t is not None: arrivals.append(time.monotonic()); output.append(t)
elapsed = time.monotonic()-start; after=io(); n=dict(engine.last)
text = tok.decode(output).replace('<|im_end|>','').replace('<|endoftext|>','').strip()
assert engine.done_line and n['generated']==len(output) and n['prompt_tokens']==len(ids)
assert n['prompt_read']==len(ids) and n['reused']==0 and output and not cancel.is_set()
if expected: assert text==expected
with log.open() as f: f.seek(offset); raw=f.read()
assert not re.search(r'\b[1-9]\d* (?:of \d+ logits )?non-finite\b|\bnonfinite [1-9]\d*',raw)
allowed = [x for x in raw.splitlines() if ENGINE_REQUEST.search(x) or
re.match(r'^strata (?:trace: (?:read \d|lent \d|refilled \d|prompt chunk)|prefill timing:|prefill timing \(|serve: prompt|generate: prompt)',x)]
row={'label':label,'input_tokens':len(ids),'output_cap':cap,'output_tokens':len(output),
'input_ids_sha256':digest(ids),'output_ids_sha256':digest(output),'native':n,
'native_done_line':engine.done_line,'prompt_tps':len(ids)*1000/n['prompt_ms'],
'decode_tps':len(output)*1000/n['decode_ms'],'ttft_s':arrivals[0]-start,
'total_s':elapsed,'process_io_delta':{k:after[k]-before[k] for k in before},
'numeric_trace':allowed,'valid':True}
prefixes={}
for k in (64,128,256,512,640):
if len(output)>=k:
prefixes[str(k)]={'ids_sha256':digest(output[:k]),'post_first_tps':None if k<2 else (k-1)/(arrivals[k-1]-arrivals[0]),'after_prompt_elapsed_ms':(arrivals[k-1]-start)*1000-n['prompt_ms']}
row['prefixes']=prefixes
if label.startswith('public2185'):
if 'public2185' in streams:
row['matches_previous_prefix']=streams['public2185']==output[:len(streams['public2185'])]
assert row['matches_previous_prefix']
else: streams['public2185']=output
row['target']=label.rsplit('-r',1)[0]
for prior in rows:
if prior.get('target')==row['target']:
assert prior['output_ids_sha256']==row['output_ids_sha256']
row['matches_previous_repeat']=True
rows.append(row);save()
print(json.dumps({k:row[k] for k in ['label','input_tokens','output_tokens','prompt_tps','ttft_s','total_s']}),flush=True)
try:
life={'mode':a.mode,'binary_sha256':hashlib.file_digest(Path(cfg['exe']).open('rb'),'sha256').hexdigest(),
'args':cfg['args'],'diagnostic_env':{k:env[k] for k in ['STRATA_TRACE','STRATA_STAGER_THREADS','OMP_NUM_THREADS','MKL_NUM_THREADS']},
'intermediate_tensor_diagnostic':env.get('STRATA_DBG_NAN'), 'instrumented':False}
life['launches']=[]
for rep in range(1,4):
assert not cancel.is_set();streams.clear()
log=ram/('native-'+str(rep)+'.log')
start=time.monotonic()
engine=Engine(cfg['exe'],cfg['args'],cwd=cfg['cwd'],log=str(log),env=env)
launch={'repeat':rep,'startup_ready_s':time.monotonic()-start,'info':engine.info}
life['launches'].append(launch);save()
ask(public,256,'public2185-256-r'+str(rep))
ask(short,256,'public20-256-r'+str(rep))
ask(canary,64,'canary-end-r'+str(rep),'CANARY_MAPLE_73')
p=engine.proc;start=time.monotonic();p.stdin.write('QUIT\n');p.stdin.flush();p.wait(timeout=75)
launch.update(native_exit=p.returncode,quit_exit_s=time.monotonic()-start);assert p.returncode==0
engine.close();engine=None
for _ in range(5):time.sleep(1);assert not cancel.is_set()
raw=log.read_text()
launch['startup_geometry']=[x for x in raw.splitlines() if re.match(r'^strata (?:generate|serve): (?:GPU \d+:|expert cache \d|\d+ of \d+ experts missing|\d+ MiB of VRAM free|prompt path|session is up)',x)]
save()
life['native_exit']=0
except BaseException as e:
failure={'type':type(e).__name__,'reason':str(e)}
finally:
if engine is not None:
try:
p=engine.proc;start=time.monotonic();p.stdin.write('QUIT\n');p.stdin.flush();p.wait(timeout=75)
life.update(native_exit=p.returncode,quit_exit_s=time.monotonic()-start)
assert p.returncode==0
engine.close();engine=None
for _ in range(5): time.sleep(1);assert not cancel.is_set()
except BaseException as e:
failure=failure or {'type':type(e).__name__,'reason':str(e)}
save()
(out/'result.json').write_text(json.dumps({'failure':failure,'requests':len(rows),'native_exit':life.get('native_exit'),'content_persisted':False},indent=2)+'\n')
if failure:raise SystemExit(1)
if __name__=='__main__':main()
@@ -0,0 +1,215 @@
{
"native_reference": {
"8k-512": {
"checks": 21,
"all_passed": true,
"exact_target_only_one_draft_MTP4_streams": true,
"native_exit_codes": [
0,
0,
0
]
},
"8k-4096": {
"checks": 21,
"all_passed": true,
"exact_target_only_one_draft_MTP4_streams": true,
"native_exit_codes": [
0,
0,
0
]
},
"262k-512": {
"checks": 5,
"all_passed": true,
"exact_MTP4_at_32k_and_full_one_draft_at_32k": true,
"native_exit_codes": [
0,
0,
0
]
}
},
"api": {
"8k-512": {
"checks": 24,
"all_passed": true,
"cancellation_restart_context_tools_queue_isolation": true
},
"8k-4096": {
"checks": 24,
"all_passed": true,
"cancellation_restart_context_tools_queue_isolation": true
},
"262k-512": {
"checks": 12,
"all_passed": true,
"progressive_context_full_recall_repeat_overflow_isolation_history": true
}
},
"kernel_suite": {
"registered_tests": 30,
"passed": 26,
"failed": [
"iq_parity",
"gr_parity",
"ple_parity",
"s2_expert_grouped_parity"
],
"classification": {
"iq_parity": "CTest treats --selftest as a fixture directory. Subsequent actual IQ fixtures and native GGUF expert oracles across eight layers passed.",
"ple_parity": "Q2_0 PLE fixture missing; unqualified. Actual profile uses original IQ2_XS PLE.",
"gr_parity": "Only unsupported opt-in QFUSE / multi-QFUSE checks fail. Port explicitly returns false and ordinary/native GR subchecks pass; STRATA_QFUSE remains absent.",
"s2_expert_grouped_parity": "Old/new grouped S2 results differ bitwise in four cases. All numerical CPU oracle checks show0outside tolerance, worst<=1.03e-7 normalized. S2 grouped path used by drafter; require exact target-only vs speculative model streams before throughput."
},
"native_source_patches": [],
"continue_scope": "Only original native IQ2_XS, default paths; no QFUSE, no other model/new format/general qualification. Preserve all failures; independent IQ fixture/native8layers then model reference/API gates before speed.",
"actual_IQ_fixtures_and_native_8layer_oracles": "passed"
},
"hardware": {
"v01402-reference-512-1": {
"samples": 111,
"peak_resident_vram_GiB": 29.071022033691406,
"max_sensor_C": 66.0,
"min_available_GiB": 109.41112899780273,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-api-512-1": {
"samples": 107,
"peak_resident_vram_GiB": 29.064258575439453,
"max_sensor_C": 70.0,
"min_available_GiB": 109.29659271240234,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-reference-4096-1": {
"samples": 82,
"peak_resident_vram_GiB": 28.02685546875,
"max_sensor_C": 68.0,
"min_available_GiB": 107.0665054321289,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-api-4096-1": {
"samples": 88,
"peak_resident_vram_GiB": 28.025035858154297,
"max_sensor_C": 70.0,
"min_available_GiB": 106.90755081176758,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-context-reference-512-1": {
"samples": 1074,
"peak_resident_vram_GiB": 29.689437866210938,
"max_sensor_C": 74.0,
"min_available_GiB": 103.89444351196289,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-context-api-512-1": {
"samples": 1291,
"peak_resident_vram_GiB": 29.68869400024414,
"max_sensor_C": 76.0,
"min_available_GiB": 103.59906768798828,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-main-512-1": {
"samples": 500,
"peak_resident_vram_GiB": 29.071109771728516,
"max_sensor_C": 72.0,
"min_available_GiB": 109.43999862670898,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-public-512-1": {
"samples": 43,
"peak_resident_vram_GiB": 29.03820037841797,
"max_sensor_C": 66.0,
"min_available_GiB": 109.45808792114258,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-main-4096-1": {
"samples": 386,
"peak_resident_vram_GiB": 28.026866912841797,
"max_sensor_C": 72.0,
"min_available_GiB": 107.02038955688477,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-public-4096-1": {
"samples": 39,
"peak_resident_vram_GiB": 28.020736694335938,
"max_sensor_C": 66.0,
"min_available_GiB": 107.05953979492188,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-main-262k-512-1": {
"samples": 538,
"peak_resident_vram_GiB": 28.127731323242188,
"max_sensor_C": 72.0,
"min_available_GiB": 104.67337036132812,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-public-262k-512-1": {
"samples": 46,
"peak_resident_vram_GiB": 28.07785415649414,
"max_sensor_C": 66.0,
"min_available_GiB": 104.68272399902344,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
},
"v01402-artifacts-1": {
"samples": 5,
"peak_resident_vram_GiB": 0.11595535278320312,
"max_sensor_C": 45.0,
"min_available_GiB": 120.11325454711914,
"zero_swapout": true,
"kernel_faults": 0,
"zero_oom": true,
"zero_watched_aer": true,
"gpu_memory_margin_GiB": 30.5
}
}
}
@@ -0,0 +1,109 @@
configuration,suite,native_context,usable_api_context,prefill,reserve_mib,label,run,input_tokens,output_tokens,prompt_tps,decode_tps,ttft_s,total_s,input_ids_sha256,output_ids_sha256,valid
8k-512,main,8192,8184,512,3072,bench-512-0,1,512,640,352.37439779766004,48.67401340056431,1.486453754005197,14.602635237999493,7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429,53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61,True
8k-512,main,8192,8184,512,3072,bench-512-1,1,512,640,352.7628496623949,49.18763545813671,1.4848548109948752,14.464078181998048,46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2,382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52,True
8k-512,main,8192,8184,512,3072,bench-512-2,1,512,640,349.15439170758316,38.00136567407891,1.5005320929994923,18.308917479997035,ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d,107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f,True
8k-512,main,8192,8184,512,3072,bench-512-3,1,512,640,357.99188924625923,41.6777915980177,1.4635920130021987,16.78713981599867,2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b,f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73,True
8k-512,main,8192,8184,512,3072,bench-512-4,1,512,640,344.6418955304254,45.01652950692832,1.5191593440031284,15.70372823800426,2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f,8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64,True
8k-512,main,8192,8184,512,3072,bench-7000-0,1,7000,640,315.31957639067195,52.22272994320778,22.23451974100317,34.456535436002014,6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619,1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7,True
8k-512,main,8192,8184,512,3072,bench-7000-1,1,7000,640,315.32809888689184,46.45322378114725,22.23390123200079,35.97797873899981,cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269,b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9,True
8k-512,main,8192,8184,512,3072,bench-7000-2,1,7000,640,315.44461919074934,35.19616361816562,22.22643303299992,40.37639872600266,bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa,6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f,True
8k-512,main,8192,8184,512,3072,bench-7000-3,1,7000,640,315.71351253833666,43.490965431477946,22.206747525000537,36.88929874599853,271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533,f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a,True
8k-512,main,8192,8184,512,3072,bench-7000-4,1,7000,640,315.44177620757876,41.8199520377425,22.225795482998365,37.49643328599632,36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53,16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece,True
8k-512,main,8192,8184,512,3072,bench-512-0,2,512,640,352.27741846704276,48.66328051339761,1.4869932690053247,14.605993185003172,7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429,53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61,True
8k-512,main,8192,8184,512,3072,bench-512-1,2,512,640,352.9817304377801,49.18120970406744,1.483933003997663,14.464741142001003,46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2,382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52,True
8k-512,main,8192,8184,512,3072,bench-512-2,2,512,640,346.81297839192575,38.00949049465788,1.5104386109960615,18.315157220997207,ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d,107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f,True
8k-512,main,8192,8184,512,3072,bench-512-3,2,512,640,358.1922484958724,41.67290675035975,1.4629622330030543,16.7881544280026,2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b,f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73,True
8k-512,main,8192,8184,512,3072,bench-512-4,2,512,640,350.39693402682724,44.99247782011445,1.494853715004865,15.687034372000198,2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f,8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64,True
8k-512,main,8192,8184,512,3072,bench-7000-0,2,7000,640,315.2996923575859,52.208671534037606,22.236051631996816,34.46141058099602,6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619,1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7,True
8k-512,main,8192,8184,512,3072,bench-7000-1,2,7000,640,315.3636142472271,46.44917806727873,22.23135302299488,35.976611840997066,cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269,b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9,True
8k-512,main,8192,8184,512,3072,bench-7000-2,2,7000,640,315.3124746623904,35.197325003299746,22.235519458001363,40.38510999199934,bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa,6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f,True
8k-512,main,8192,8184,512,3072,bench-7000-3,2,7000,640,315.68930760315146,43.489487775376794,22.208402928001306,36.891612551000435,271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533,f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a,True
8k-512,main,8192,8184,512,3072,bench-7000-4,2,7000,640,315.2372160050438,41.831158984548615,22.240199856998515,37.506764951998775,36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53,16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece,True
8k-512,main,8192,8184,512,3072,bench-512-0,3,512,640,352.8114663726571,48.67179241480535,1.4847840959992027,14.601516670001729,7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429,53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61,True
8k-512,main,8192,8184,512,3072,bench-512-1,3,512,640,353.29837151531876,49.18120970406744,1.4826883630012162,14.463372318001348,46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2,382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52,True
8k-512,main,8192,8184,512,3072,bench-512-2,3,512,640,349.5835040284037,38.00226826038679,1.4987666009983514,18.306564821999928,ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d,107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f,True
8k-512,main,8192,8184,512,3072,bench-512-3,3,512,640,358.5936405659056,41.653107712333224,1.4612209699989762,16.793817807003506,2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b,f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73,True
8k-512,main,8192,8184,512,3072,bench-512-4,3,512,640,350.49288061336256,45.01114729194652,1.4942446380009642,15.680540973000461,2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f,8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64,True
8k-512,main,8192,8184,512,3072,bench-7000-0,3,7000,640,315.4943796929789,52.210801109479526,22.22221389000333,34.44696678299806,6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619,1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7,True
8k-512,main,8192,8184,512,3072,bench-7000-1,3,7000,640,315.28265089652876,46.46840148698885,22.236943748997874,35.976502240002446,cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269,b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9,True
8k-512,main,8192,8184,512,3072,bench-7000-2,3,7000,640,315.45883487532615,35.205069530012324,22.22521572799451,40.37075695099338,bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa,6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f,True
8k-512,main,8192,8184,512,3072,bench-7000-3,3,7000,640,315.89445514975654,43.493034318722394,22.19403974799934,36.875881571999344,271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533,f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a,True
8k-512,main,8192,8184,512,3072,bench-7000-4,3,7000,640,315.35082779592295,41.832799529381006,22.232356720996904,37.49824667599751,36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53,16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece,True
8k-512,public,8192,8184,512,3072,public2185-256-r1,1,2185,256,323.4305845434226,49.72322035544333,6.815883596995263,11.905609935995017,cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514,dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12,True
8k-512,public,8192,8184,512,3072,public20-256-r1,1,20,256,54.614964500273075,54.48547408747473,0.4000317419995554,5.065761150995968,05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d,4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020,True
8k-512,public,8192,8184,512,3072,public2185-256-r2,2,2185,256,323.35878766352926,49.724186154921924,6.817252700995596,11.906957781000528,cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514,dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12,True
8k-512,public,8192,8184,512,3072,public20-256-r2,2,20,256,54.6000546000546,54.47851716286097,0.4001509320005425,5.066493678998086,05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d,4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020,True
8k-512,public,8192,8184,512,3072,public2185-256-r3,3,2185,256,323.3013731060606,49.71935753267689,6.818356577998202,11.908829965999757,cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514,dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12,True
8k-512,public,8192,8184,512,3072,public20-256-r3,3,20,256,54.55537370430987,54.46808510638298,0.4005099159985548,5.067818413997884,05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d,4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020,True
8k-4096,main,8192,8184,4096,3072,bench-512-0,1,512,640,330.8776011373917,47.70032272249592,1.5813149160021567,14.965319010996609,7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429,53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61,True
8k-4096,main,8192,8184,4096,3072,bench-512-1,1,512,640,331.1558113964168,48.63554498407946,1.5796948159986641,14.706328747000953,46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2,382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52,True
8k-4096,main,8192,8184,4096,3072,bench-512-2,1,512,640,327.51231369538795,36.646606466980835,1.597785092999402,19.028336301998934,ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d,107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f,True
8k-4096,main,8192,8184,4096,3072,bench-512-3,1,512,640,336.2227475702653,41.33272195348777,1.5563321330046165,17.007930472005683,2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b,f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73,True
8k-4096,main,8192,8184,4096,3072,bench-512-4,1,512,640,328.75304995505326,44.64565995354061,1.5912580959993647,15.893667525000637,2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f,8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64,True
8k-4096,main,8192,8184,4096,3072,bench-7000-0,1,7000,640,828.0593836872301,43.7325753020281,8.488523036998231,23.089613208998344,6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619,a6897badcddbbb3a622492d96b178137039fb367b502105f0e8796f749fc1a0c,True
8k-4096,main,8192,8184,4096,3072,bench-7000-1,1,7000,640,828.9811821271657,46.83326625443635,8.479286790003243,22.111294834001455,cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269,afcc84a14aa53dda7b06d551a5d4b1e0914797b81d1d080cdf488af48830be76,True
8k-4096,main,8192,8184,4096,3072,bench-7000-2,1,7000,640,830.0624918476005,33.47315348486909,8.46895773900178,27.55465372100298,bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa,0c492870bf22354cc28f95ec394834cb6d0e6f44e632931a93cec7ecd04d097e,True
8k-4096,main,8192,8184,4096,3072,bench-7000-3,1,7000,640,832.7286137447805,42.91989404151158,8.44094783399487,23.319345058996987,271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533,99d0ff94eda3ab7f4ae29abaf69eaf0773d6aaef1965b04b1be2cf1c66348b10,True
8k-4096,main,8192,8184,4096,3072,bench-7000-4,1,7000,640,829.9345537323343,40.40225495085444,8.469412726000883,24.2765017290003,36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53,6eef3d866fd9631257d1de93577e0434ee8cfabaad2e986aa0c6f036d6d83cfe,True
8k-4096,main,8192,8184,4096,3072,bench-512-0,2,512,640,331.1129793701093,47.69996720627255,1.5801466330012772,14.964506882002752,7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429,53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61,True
8k-4096,main,8192,8184,4096,3072,bench-512-1,2,512,640,331.5203315203315,48.65218250649963,1.578033942001639,14.700113717000932,46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2,382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52,True
8k-4096,main,8192,8184,4096,3072,bench-512-2,2,512,640,327.78489116517284,36.64471800744346,1.5965668770004413,19.02813425000204,ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d,107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f,True
8k-4096,main,8192,8184,4096,3072,bench-512-3,2,512,640,336.28899835796386,41.34740868037161,1.5560904539961484,17.002041403000476,2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b,f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73,True
8k-4096,main,8192,8184,4096,3072,bench-512-4,2,512,640,329.0065544274515,44.614226361431,1.5898735009977827,15.90252744800091,2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f,8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64,True
8k-4096,main,8192,8184,4096,3072,bench-7000-0,2,7000,640,828.5004142502071,43.728989587034356,8.483962445003272,23.086291122999683,6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619,a6897badcddbbb3a622492d96b178137039fb367b502105f0e8796f749fc1a0c,True
8k-4096,main,8192,8184,4096,3072,bench-7000-1,2,7000,640,828.8535770952235,46.86138548615027,8.480380373002845,22.10415563800052,cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269,afcc84a14aa53dda7b06d551a5d4b1e0914797b81d1d080cdf488af48830be76,True
8k-4096,main,8192,8184,4096,3072,bench-7000-2,2,7000,640,830.0920216298265,33.48085836550634,8.468579719003174,27.549830502000987,bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa,0c492870bf22354cc28f95ec394834cb6d0e6f44e632931a93cec7ecd04d097e,True
8k-4096,main,8192,8184,4096,3072,bench-7000-3,2,7000,640,832.8673242352493,42.91989404151158,8.439344229002018,23.31782736400055,271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533,99d0ff94eda3ab7f4ae29abaf69eaf0773d6aaef1965b04b1be2cf1c66348b10,True
8k-4096,main,8192,8184,4096,3072,bench-7000-4,2,7000,640,830.0034385856741,40.38313499324844,8.46887673099991,24.283383722999133,36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53,6eef3d866fd9631257d1de93577e0434ee8cfabaad2e986aa0c6f036d6d83cfe,True
8k-4096,main,8192,8184,4096,3072,bench-512-0,3,512,640,330.9203722854188,47.69996720627255,1.5811564449977595,14.965367263001099,7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429,53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61,True
8k-4096,main,8192,8184,4096,3072,bench-512-1,3,512,640,331.370137855155,48.636284187888045,1.5787563980047707,14.705128487003094,46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2,382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52,True
8k-4096,main,8192,8184,4096,3072,bench-512-2,3,512,640,327.68,36.643039540129855,1.5972283160008374,19.029236464004498,ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d,107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f,True
8k-4096,main,8192,8184,4096,3072,bench-512-3,3,512,640,336.28899835796386,41.35328629397017,1.556216282006062,16.99992331300018,2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b,f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73,True
8k-4096,main,8192,8184,4096,3072,bench-512-4,3,512,640,328.92200950790186,44.63787523713871,1.5903917530013132,15.895306143000198,2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f,8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64,True
8k-4096,main,8192,8184,4096,3072,bench-7000-0,3,7000,640,828.5494466473339,43.73646049025839,8.483659700999851,23.083241319996887,6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619,a6897badcddbbb3a622492d96b178137039fb367b502105f0e8796f749fc1a0c,True
8k-4096,main,8192,8184,4096,3072,bench-7000-1,3,7000,640,828.490608467174,46.868248958279935,8.484360643997206,22.10602983499848,cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269,afcc84a14aa53dda7b06d551a5d4b1e0914797b81d1d080cdf488af48830be76,True
8k-4096,main,8192,8184,4096,3072,bench-7000-2,3,7000,640,830.0821781356354,33.466677125003265,8.468654577998677,27.55782354099938,bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa,0c492870bf22354cc28f95ec394834cb6d0e6f44e632931a93cec7ecd04d097e,True
8k-4096,main,8192,8184,4096,3072,bench-7000-3,3,7000,640,832.8375966686497,42.92277254283894,8.439849987000343,23.317097936997015,271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533,99d0ff94eda3ab7f4ae29abaf69eaf0773d6aaef1965b04b1be2cf1c66348b10,True
8k-4096,main,8192,8184,4096,3072,bench-7000-4,3,7000,640,830.0329641662912,40.405060733856914,8.468491788000392,24.274414861996775,36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53,6eef3d866fd9631257d1de93577e0434ee8cfabaad2e986aa0c6f036d6d83cfe,True
8k-4096,public,8192,8184,4096,3072,public2185-256-r1,1,2185,256,723.7735599059259,47.42585079382723,3.0805087330008973,8.418293693001033,cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514,38601a475af3ca3649993a5c12afe4eb869422c41a01ce46200d30674f645017,True
8k-4096,public,8192,8184,4096,3072,public20-256-r1,1,20,256,50.12531328320802,53.50946866769784,0.43392555299942615,5.184442054000101,05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d,4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020,True
8k-4096,public,8192,8184,4096,3072,public2185-256-r2,2,2185,256,722.7202063969834,47.40389600770314,3.0846155070030363,8.424763125003665,cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514,38601a475af3ca3649993a5c12afe4eb869422c41a01ce46200d30674f645017,True
8k-4096,public,8192,8184,4096,3072,public20-256-r2,2,20,256,50.188205771643666,53.50164057765053,0.4332570679980563,5.184587747004116,05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d,4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020,True
8k-4096,public,8192,8184,4096,3072,public2185-256-r3,3,2185,256,582.4181682482141,47.40301823905194,3.812937997005065,9.153436525004508,cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514,38601a475af3ca3649993a5c12afe4eb869422c41a01ce46200d30674f645017,True
8k-4096,public,8192,8184,4096,3072,public20-256-r3,3,20,256,50.112753695815584,53.5083502288736,0.4339962550002383,5.184664774002158,05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d,4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020,True
262k-512,main,262152,262144,512,4096,bench-512-0,1,512,640,320.72162365321975,46.00047437989205,1.6305150300031528,15.51022553400253,7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429,53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61,True
262k-512,main,262152,262144,512,4096,bench-512-1,1,512,640,321.2045169385195,47.3138311635506,1.6278641449971474,15.121843083994463,46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2,382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52,True
262k-512,main,262152,262144,512,4096,bench-512-2,1,512,640,317.2242874845105,35.22735404041238,1.6493346380011644,19.782639541001117,ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d,107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f,True
262k-512,main,262152,262144,512,4096,bench-512-3,1,512,640,326.21854093660403,40.216414580963814,1.6036899610044202,17.484375810003257,2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b,f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73,True
262k-512,main,262152,262144,512,4096,bench-512-4,1,512,640,317.40127704420064,43.512550651328496,1.6472808589969645,16.322636835000594,2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f,8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64,True
262k-512,main,262152,262144,512,4096,bench-7000-0,1,7000,640,287.6456205954264,48.78866883166385,24.37071036999987,37.45503619199735,6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619,1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7,True
262k-512,main,262152,262144,512,4096,bench-7000-1,1,7000,640,287.80409586343285,44.12089124200309,24.357459778999328,38.82931439999811,cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269,b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9,True
262k-512,main,262152,262144,512,4096,bench-7000-2,1,7000,640,287.93194934043015,32.83802643461128,24.347708400004194,43.80252295399987,bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa,6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f,True
262k-512,main,262152,262144,512,4096,bench-7000-3,1,7000,640,288.49680798888875,42.37765108625839,24.29905910499656,39.36770728800184,271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533,f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a,True
262k-512,main,262152,262144,512,4096,bench-7000-4,1,7000,640,287.6645338396229,40.96026214567773,24.369260341998597,39.96049542899709,36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53,16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece,True
262k-512,main,262152,262144,512,4096,bench-512-0,2,512,640,318.1309804896234,45.08756851196934,1.6436967349945917,15.804917542998737,7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429,53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61,True
262k-512,main,262152,262144,512,4096,bench-512-1,2,512,640,318.86404683315686,46.62955731064028,1.639718692000315,15.331977528003335,46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2,382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52,True
262k-512,main,262152,262144,512,4096,bench-512-2,2,512,640,314.43837130749864,34.09659992967576,1.6640070880021085,20.39944585700141,ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d,107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f,True
262k-512,main,262152,262144,512,4096,bench-512-3,2,512,640,323.43651295009477,39.646158039497486,1.6174420829993323,17.726890749996528,2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b,f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73,True
262k-512,main,262152,262144,512,4096,bench-512-4,2,512,640,315.19330214232946,42.96224692551421,1.658742642001016,16.52241344399954,2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f,8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64,True
262k-512,main,262152,262144,512,4096,bench-7000-0,2,7000,640,284.93275586961477,47.55535740823302,24.60263190200203,38.02679158800311,6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619,1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7,True
262k-512,main,262152,262144,512,4096,bench-7000-1,2,7000,640,284.9559539511178,43.25084136402341,24.60098869099602,39.36411245299678,cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269,b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9,True
262k-512,main,262152,262144,512,4096,bench-7000-2,2,7000,640,285.2485737571312,31.708440886052742,24.576962859006017,44.72560127500037,bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa,6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f,True
262k-512,main,262152,262144,512,4096,bench-7000-3,2,7000,640,285.7259479978775,41.86536360722439,24.53467792900483,39.78784895900026,271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533,f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a,True
262k-512,main,262152,262144,512,4096,bench-7000-4,2,7000,640,285.04530184261426,40.5422526289117,24.593217346002348,40.345099539998046,36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53,16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece,True
262k-512,main,262152,262144,512,4096,bench-512-0,3,512,640,320.56098171800653,45.99353215954007,1.6313107940004556,15.513204158000008,7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429,53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61,True
262k-512,main,262152,262144,512,4096,bench-512-1,3,512,640,321.36580466984685,47.31278184371997,1.6271679769997718,15.121397080998577,46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2,382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52,True
262k-512,main,262152,262144,512,4096,bench-512-2,3,512,640,316.9297431135871,35.22367030644593,1.6509387949990924,19.786140595999314,ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d,107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f,True
262k-512,main,262152,262144,512,4096,bench-512-3,3,512,640,326.0731117055152,40.21515105816116,1.6044366169953719,17.485617870996066,2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b,f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73,True
262k-512,main,262152,262144,512,4096,bench-512-4,3,512,640,318.1902927102107,43.508113583369024,1.6432227010009228,16.320090422006615,2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f,8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64,True
262k-512,main,262152,262144,512,4096,bench-7000-0,3,7000,640,287.71419294113775,48.79238838741156,24.365081126001314,37.448226578002505,6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619,1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7,True
262k-512,main,262152,262144,512,4096,bench-7000-1,3,7000,640,287.80291256547514,44.12058707956182,24.357497923003393,38.82947031799995,cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269,b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9,True
262k-512,main,262152,262144,512,4096,bench-7000-2,3,7000,640,287.96629971532474,32.83330939237857,24.34486455500155,43.802383964997716,bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa,6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f,True
262k-512,main,262152,262144,512,4096,bench-7000-3,3,7000,640,288.49442999682657,42.39561735305613,24.299175920998096,39.36139631699916,271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533,f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a,True
262k-512,main,262152,262144,512,4096,bench-7000-4,3,7000,640,287.7011853288836,40.96131076194438,24.366155340998375,39.95687096999609,36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53,16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece,True
262k-512,public,262152,262144,512,4096,public2185-256-r1,1,2185,256,300.9185936015204,48.51517046638998,7.3306941440023365,12.547350928005471,cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514,dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12,True
262k-512,public,262152,262144,512,4096,public20-256-r1,1,20,256,48.828125,50.51701002446917,0.4462103360056062,5.47836589000508,05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d,4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020,True
262k-512,public,262152,262144,512,4096,public2185-256-r2,2,2185,256,302.43051710774,48.95305478535233,7.285462539002765,12.455673757998738,cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514,dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12,True
262k-512,public,262152,262144,512,4096,public20-256-r2,2,20,256,49.01960784313726,51.534977352793156,0.4439065019978443,5.376657145003264,05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d,4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020,True
262k-512,public,262152,262144,512,4096,public2185-256-r3,3,2185,256,302.9084758920897,48.94556717587901,7.28071175700461,12.451828441000544,cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514,dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12,True
262k-512,public,262152,262144,512,4096,public20-256-r3,3,20,256,49.14004914004914,51.531865211965055,0.44289757200021995,5.375990995002212,05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d,4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020,True
1 configuration suite native_context usable_api_context prefill reserve_mib label run input_tokens output_tokens prompt_tps decode_tps ttft_s total_s input_ids_sha256 output_ids_sha256 valid
2 8k-512 main 8192 8184 512 3072 bench-512-0 1 512 640 352.37439779766004 48.67401340056431 1.486453754005197 14.602635237999493 7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429 53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61 True
3 8k-512 main 8192 8184 512 3072 bench-512-1 1 512 640 352.7628496623949 49.18763545813671 1.4848548109948752 14.464078181998048 46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2 382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52 True
4 8k-512 main 8192 8184 512 3072 bench-512-2 1 512 640 349.15439170758316 38.00136567407891 1.5005320929994923 18.308917479997035 ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d 107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f True
5 8k-512 main 8192 8184 512 3072 bench-512-3 1 512 640 357.99188924625923 41.6777915980177 1.4635920130021987 16.78713981599867 2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73 True
6 8k-512 main 8192 8184 512 3072 bench-512-4 1 512 640 344.6418955304254 45.01652950692832 1.5191593440031284 15.70372823800426 2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f 8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64 True
7 8k-512 main 8192 8184 512 3072 bench-7000-0 1 7000 640 315.31957639067195 52.22272994320778 22.23451974100317 34.456535436002014 6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619 1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7 True
8 8k-512 main 8192 8184 512 3072 bench-7000-1 1 7000 640 315.32809888689184 46.45322378114725 22.23390123200079 35.97797873899981 cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269 b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9 True
9 8k-512 main 8192 8184 512 3072 bench-7000-2 1 7000 640 315.44461919074934 35.19616361816562 22.22643303299992 40.37639872600266 bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa 6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f True
10 8k-512 main 8192 8184 512 3072 bench-7000-3 1 7000 640 315.71351253833666 43.490965431477946 22.206747525000537 36.88929874599853 271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533 f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a True
11 8k-512 main 8192 8184 512 3072 bench-7000-4 1 7000 640 315.44177620757876 41.8199520377425 22.225795482998365 37.49643328599632 36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53 16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece True
12 8k-512 main 8192 8184 512 3072 bench-512-0 2 512 640 352.27741846704276 48.66328051339761 1.4869932690053247 14.605993185003172 7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429 53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61 True
13 8k-512 main 8192 8184 512 3072 bench-512-1 2 512 640 352.9817304377801 49.18120970406744 1.483933003997663 14.464741142001003 46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2 382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52 True
14 8k-512 main 8192 8184 512 3072 bench-512-2 2 512 640 346.81297839192575 38.00949049465788 1.5104386109960615 18.315157220997207 ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d 107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f True
15 8k-512 main 8192 8184 512 3072 bench-512-3 2 512 640 358.1922484958724 41.67290675035975 1.4629622330030543 16.7881544280026 2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73 True
16 8k-512 main 8192 8184 512 3072 bench-512-4 2 512 640 350.39693402682724 44.99247782011445 1.494853715004865 15.687034372000198 2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f 8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64 True
17 8k-512 main 8192 8184 512 3072 bench-7000-0 2 7000 640 315.2996923575859 52.208671534037606 22.236051631996816 34.46141058099602 6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619 1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7 True
18 8k-512 main 8192 8184 512 3072 bench-7000-1 2 7000 640 315.3636142472271 46.44917806727873 22.23135302299488 35.976611840997066 cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269 b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9 True
19 8k-512 main 8192 8184 512 3072 bench-7000-2 2 7000 640 315.3124746623904 35.197325003299746 22.235519458001363 40.38510999199934 bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa 6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f True
20 8k-512 main 8192 8184 512 3072 bench-7000-3 2 7000 640 315.68930760315146 43.489487775376794 22.208402928001306 36.891612551000435 271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533 f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a True
21 8k-512 main 8192 8184 512 3072 bench-7000-4 2 7000 640 315.2372160050438 41.831158984548615 22.240199856998515 37.506764951998775 36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53 16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece True
22 8k-512 main 8192 8184 512 3072 bench-512-0 3 512 640 352.8114663726571 48.67179241480535 1.4847840959992027 14.601516670001729 7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429 53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61 True
23 8k-512 main 8192 8184 512 3072 bench-512-1 3 512 640 353.29837151531876 49.18120970406744 1.4826883630012162 14.463372318001348 46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2 382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52 True
24 8k-512 main 8192 8184 512 3072 bench-512-2 3 512 640 349.5835040284037 38.00226826038679 1.4987666009983514 18.306564821999928 ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d 107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f True
25 8k-512 main 8192 8184 512 3072 bench-512-3 3 512 640 358.5936405659056 41.653107712333224 1.4612209699989762 16.793817807003506 2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73 True
26 8k-512 main 8192 8184 512 3072 bench-512-4 3 512 640 350.49288061336256 45.01114729194652 1.4942446380009642 15.680540973000461 2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f 8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64 True
27 8k-512 main 8192 8184 512 3072 bench-7000-0 3 7000 640 315.4943796929789 52.210801109479526 22.22221389000333 34.44696678299806 6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619 1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7 True
28 8k-512 main 8192 8184 512 3072 bench-7000-1 3 7000 640 315.28265089652876 46.46840148698885 22.236943748997874 35.976502240002446 cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269 b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9 True
29 8k-512 main 8192 8184 512 3072 bench-7000-2 3 7000 640 315.45883487532615 35.205069530012324 22.22521572799451 40.37075695099338 bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa 6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f True
30 8k-512 main 8192 8184 512 3072 bench-7000-3 3 7000 640 315.89445514975654 43.493034318722394 22.19403974799934 36.875881571999344 271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533 f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a True
31 8k-512 main 8192 8184 512 3072 bench-7000-4 3 7000 640 315.35082779592295 41.832799529381006 22.232356720996904 37.49824667599751 36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53 16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece True
32 8k-512 public 8192 8184 512 3072 public2185-256-r1 1 2185 256 323.4305845434226 49.72322035544333 6.815883596995263 11.905609935995017 cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514 dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12 True
33 8k-512 public 8192 8184 512 3072 public20-256-r1 1 20 256 54.614964500273075 54.48547408747473 0.4000317419995554 5.065761150995968 05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d 4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020 True
34 8k-512 public 8192 8184 512 3072 public2185-256-r2 2 2185 256 323.35878766352926 49.724186154921924 6.817252700995596 11.906957781000528 cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514 dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12 True
35 8k-512 public 8192 8184 512 3072 public20-256-r2 2 20 256 54.6000546000546 54.47851716286097 0.4001509320005425 5.066493678998086 05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d 4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020 True
36 8k-512 public 8192 8184 512 3072 public2185-256-r3 3 2185 256 323.3013731060606 49.71935753267689 6.818356577998202 11.908829965999757 cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514 dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12 True
37 8k-512 public 8192 8184 512 3072 public20-256-r3 3 20 256 54.55537370430987 54.46808510638298 0.4005099159985548 5.067818413997884 05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d 4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020 True
38 8k-4096 main 8192 8184 4096 3072 bench-512-0 1 512 640 330.8776011373917 47.70032272249592 1.5813149160021567 14.965319010996609 7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429 53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61 True
39 8k-4096 main 8192 8184 4096 3072 bench-512-1 1 512 640 331.1558113964168 48.63554498407946 1.5796948159986641 14.706328747000953 46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2 382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52 True
40 8k-4096 main 8192 8184 4096 3072 bench-512-2 1 512 640 327.51231369538795 36.646606466980835 1.597785092999402 19.028336301998934 ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d 107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f True
41 8k-4096 main 8192 8184 4096 3072 bench-512-3 1 512 640 336.2227475702653 41.33272195348777 1.5563321330046165 17.007930472005683 2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73 True
42 8k-4096 main 8192 8184 4096 3072 bench-512-4 1 512 640 328.75304995505326 44.64565995354061 1.5912580959993647 15.893667525000637 2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f 8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64 True
43 8k-4096 main 8192 8184 4096 3072 bench-7000-0 1 7000 640 828.0593836872301 43.7325753020281 8.488523036998231 23.089613208998344 6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619 a6897badcddbbb3a622492d96b178137039fb367b502105f0e8796f749fc1a0c True
44 8k-4096 main 8192 8184 4096 3072 bench-7000-1 1 7000 640 828.9811821271657 46.83326625443635 8.479286790003243 22.111294834001455 cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269 afcc84a14aa53dda7b06d551a5d4b1e0914797b81d1d080cdf488af48830be76 True
45 8k-4096 main 8192 8184 4096 3072 bench-7000-2 1 7000 640 830.0624918476005 33.47315348486909 8.46895773900178 27.55465372100298 bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa 0c492870bf22354cc28f95ec394834cb6d0e6f44e632931a93cec7ecd04d097e True
46 8k-4096 main 8192 8184 4096 3072 bench-7000-3 1 7000 640 832.7286137447805 42.91989404151158 8.44094783399487 23.319345058996987 271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533 99d0ff94eda3ab7f4ae29abaf69eaf0773d6aaef1965b04b1be2cf1c66348b10 True
47 8k-4096 main 8192 8184 4096 3072 bench-7000-4 1 7000 640 829.9345537323343 40.40225495085444 8.469412726000883 24.2765017290003 36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53 6eef3d866fd9631257d1de93577e0434ee8cfabaad2e986aa0c6f036d6d83cfe True
48 8k-4096 main 8192 8184 4096 3072 bench-512-0 2 512 640 331.1129793701093 47.69996720627255 1.5801466330012772 14.964506882002752 7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429 53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61 True
49 8k-4096 main 8192 8184 4096 3072 bench-512-1 2 512 640 331.5203315203315 48.65218250649963 1.578033942001639 14.700113717000932 46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2 382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52 True
50 8k-4096 main 8192 8184 4096 3072 bench-512-2 2 512 640 327.78489116517284 36.64471800744346 1.5965668770004413 19.02813425000204 ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d 107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f True
51 8k-4096 main 8192 8184 4096 3072 bench-512-3 2 512 640 336.28899835796386 41.34740868037161 1.5560904539961484 17.002041403000476 2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73 True
52 8k-4096 main 8192 8184 4096 3072 bench-512-4 2 512 640 329.0065544274515 44.614226361431 1.5898735009977827 15.90252744800091 2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f 8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64 True
53 8k-4096 main 8192 8184 4096 3072 bench-7000-0 2 7000 640 828.5004142502071 43.728989587034356 8.483962445003272 23.086291122999683 6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619 a6897badcddbbb3a622492d96b178137039fb367b502105f0e8796f749fc1a0c True
54 8k-4096 main 8192 8184 4096 3072 bench-7000-1 2 7000 640 828.8535770952235 46.86138548615027 8.480380373002845 22.10415563800052 cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269 afcc84a14aa53dda7b06d551a5d4b1e0914797b81d1d080cdf488af48830be76 True
55 8k-4096 main 8192 8184 4096 3072 bench-7000-2 2 7000 640 830.0920216298265 33.48085836550634 8.468579719003174 27.549830502000987 bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa 0c492870bf22354cc28f95ec394834cb6d0e6f44e632931a93cec7ecd04d097e True
56 8k-4096 main 8192 8184 4096 3072 bench-7000-3 2 7000 640 832.8673242352493 42.91989404151158 8.439344229002018 23.31782736400055 271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533 99d0ff94eda3ab7f4ae29abaf69eaf0773d6aaef1965b04b1be2cf1c66348b10 True
57 8k-4096 main 8192 8184 4096 3072 bench-7000-4 2 7000 640 830.0034385856741 40.38313499324844 8.46887673099991 24.283383722999133 36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53 6eef3d866fd9631257d1de93577e0434ee8cfabaad2e986aa0c6f036d6d83cfe True
58 8k-4096 main 8192 8184 4096 3072 bench-512-0 3 512 640 330.9203722854188 47.69996720627255 1.5811564449977595 14.965367263001099 7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429 53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61 True
59 8k-4096 main 8192 8184 4096 3072 bench-512-1 3 512 640 331.370137855155 48.636284187888045 1.5787563980047707 14.705128487003094 46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2 382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52 True
60 8k-4096 main 8192 8184 4096 3072 bench-512-2 3 512 640 327.68 36.643039540129855 1.5972283160008374 19.029236464004498 ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d 107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f True
61 8k-4096 main 8192 8184 4096 3072 bench-512-3 3 512 640 336.28899835796386 41.35328629397017 1.556216282006062 16.99992331300018 2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73 True
62 8k-4096 main 8192 8184 4096 3072 bench-512-4 3 512 640 328.92200950790186 44.63787523713871 1.5903917530013132 15.895306143000198 2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f 8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64 True
63 8k-4096 main 8192 8184 4096 3072 bench-7000-0 3 7000 640 828.5494466473339 43.73646049025839 8.483659700999851 23.083241319996887 6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619 a6897badcddbbb3a622492d96b178137039fb367b502105f0e8796f749fc1a0c True
64 8k-4096 main 8192 8184 4096 3072 bench-7000-1 3 7000 640 828.490608467174 46.868248958279935 8.484360643997206 22.10602983499848 cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269 afcc84a14aa53dda7b06d551a5d4b1e0914797b81d1d080cdf488af48830be76 True
65 8k-4096 main 8192 8184 4096 3072 bench-7000-2 3 7000 640 830.0821781356354 33.466677125003265 8.468654577998677 27.55782354099938 bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa 0c492870bf22354cc28f95ec394834cb6d0e6f44e632931a93cec7ecd04d097e True
66 8k-4096 main 8192 8184 4096 3072 bench-7000-3 3 7000 640 832.8375966686497 42.92277254283894 8.439849987000343 23.317097936997015 271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533 99d0ff94eda3ab7f4ae29abaf69eaf0773d6aaef1965b04b1be2cf1c66348b10 True
67 8k-4096 main 8192 8184 4096 3072 bench-7000-4 3 7000 640 830.0329641662912 40.405060733856914 8.468491788000392 24.274414861996775 36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53 6eef3d866fd9631257d1de93577e0434ee8cfabaad2e986aa0c6f036d6d83cfe True
68 8k-4096 public 8192 8184 4096 3072 public2185-256-r1 1 2185 256 723.7735599059259 47.42585079382723 3.0805087330008973 8.418293693001033 cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514 38601a475af3ca3649993a5c12afe4eb869422c41a01ce46200d30674f645017 True
69 8k-4096 public 8192 8184 4096 3072 public20-256-r1 1 20 256 50.12531328320802 53.50946866769784 0.43392555299942615 5.184442054000101 05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d 4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020 True
70 8k-4096 public 8192 8184 4096 3072 public2185-256-r2 2 2185 256 722.7202063969834 47.40389600770314 3.0846155070030363 8.424763125003665 cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514 38601a475af3ca3649993a5c12afe4eb869422c41a01ce46200d30674f645017 True
71 8k-4096 public 8192 8184 4096 3072 public20-256-r2 2 20 256 50.188205771643666 53.50164057765053 0.4332570679980563 5.184587747004116 05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d 4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020 True
72 8k-4096 public 8192 8184 4096 3072 public2185-256-r3 3 2185 256 582.4181682482141 47.40301823905194 3.812937997005065 9.153436525004508 cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514 38601a475af3ca3649993a5c12afe4eb869422c41a01ce46200d30674f645017 True
73 8k-4096 public 8192 8184 4096 3072 public20-256-r3 3 20 256 50.112753695815584 53.5083502288736 0.4339962550002383 5.184664774002158 05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d 4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020 True
74 262k-512 main 262152 262144 512 4096 bench-512-0 1 512 640 320.72162365321975 46.00047437989205 1.6305150300031528 15.51022553400253 7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429 53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61 True
75 262k-512 main 262152 262144 512 4096 bench-512-1 1 512 640 321.2045169385195 47.3138311635506 1.6278641449971474 15.121843083994463 46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2 382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52 True
76 262k-512 main 262152 262144 512 4096 bench-512-2 1 512 640 317.2242874845105 35.22735404041238 1.6493346380011644 19.782639541001117 ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d 107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f True
77 262k-512 main 262152 262144 512 4096 bench-512-3 1 512 640 326.21854093660403 40.216414580963814 1.6036899610044202 17.484375810003257 2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73 True
78 262k-512 main 262152 262144 512 4096 bench-512-4 1 512 640 317.40127704420064 43.512550651328496 1.6472808589969645 16.322636835000594 2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f 8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64 True
79 262k-512 main 262152 262144 512 4096 bench-7000-0 1 7000 640 287.6456205954264 48.78866883166385 24.37071036999987 37.45503619199735 6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619 1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7 True
80 262k-512 main 262152 262144 512 4096 bench-7000-1 1 7000 640 287.80409586343285 44.12089124200309 24.357459778999328 38.82931439999811 cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269 b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9 True
81 262k-512 main 262152 262144 512 4096 bench-7000-2 1 7000 640 287.93194934043015 32.83802643461128 24.347708400004194 43.80252295399987 bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa 6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f True
82 262k-512 main 262152 262144 512 4096 bench-7000-3 1 7000 640 288.49680798888875 42.37765108625839 24.29905910499656 39.36770728800184 271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533 f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a True
83 262k-512 main 262152 262144 512 4096 bench-7000-4 1 7000 640 287.6645338396229 40.96026214567773 24.369260341998597 39.96049542899709 36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53 16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece True
84 262k-512 main 262152 262144 512 4096 bench-512-0 2 512 640 318.1309804896234 45.08756851196934 1.6436967349945917 15.804917542998737 7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429 53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61 True
85 262k-512 main 262152 262144 512 4096 bench-512-1 2 512 640 318.86404683315686 46.62955731064028 1.639718692000315 15.331977528003335 46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2 382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52 True
86 262k-512 main 262152 262144 512 4096 bench-512-2 2 512 640 314.43837130749864 34.09659992967576 1.6640070880021085 20.39944585700141 ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d 107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f True
87 262k-512 main 262152 262144 512 4096 bench-512-3 2 512 640 323.43651295009477 39.646158039497486 1.6174420829993323 17.726890749996528 2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73 True
88 262k-512 main 262152 262144 512 4096 bench-512-4 2 512 640 315.19330214232946 42.96224692551421 1.658742642001016 16.52241344399954 2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f 8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64 True
89 262k-512 main 262152 262144 512 4096 bench-7000-0 2 7000 640 284.93275586961477 47.55535740823302 24.60263190200203 38.02679158800311 6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619 1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7 True
90 262k-512 main 262152 262144 512 4096 bench-7000-1 2 7000 640 284.9559539511178 43.25084136402341 24.60098869099602 39.36411245299678 cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269 b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9 True
91 262k-512 main 262152 262144 512 4096 bench-7000-2 2 7000 640 285.2485737571312 31.708440886052742 24.576962859006017 44.72560127500037 bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa 6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f True
92 262k-512 main 262152 262144 512 4096 bench-7000-3 2 7000 640 285.7259479978775 41.86536360722439 24.53467792900483 39.78784895900026 271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533 f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a True
93 262k-512 main 262152 262144 512 4096 bench-7000-4 2 7000 640 285.04530184261426 40.5422526289117 24.593217346002348 40.345099539998046 36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53 16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece True
94 262k-512 main 262152 262144 512 4096 bench-512-0 3 512 640 320.56098171800653 45.99353215954007 1.6313107940004556 15.513204158000008 7a8b790518b46aeb09308bcaf0b2d6e5f88e1833675f003ab729879bd66f0429 53ecf36b3515d65adc7128293494e8f8d87de0a7dc70e4b835128b9819446e61 True
95 262k-512 main 262152 262144 512 4096 bench-512-1 3 512 640 321.36580466984685 47.31278184371997 1.6271679769997718 15.121397080998577 46ba88f7512466954166caa83b4d4a9efb14ea97a572d40b6e2b2314fae0fbf2 382eedf95c3f257104e845d37f2d2b2ba65ceb60067fd1a952662dfb1769ee52 True
96 262k-512 main 262152 262144 512 4096 bench-512-2 3 512 640 316.9297431135871 35.22367030644593 1.6509387949990924 19.786140595999314 ca4431f9e01900953702dc1788b319df7c908ff2af329367eef614c6f47f793d 107f6791bd6fcb5a486c17a0f68ec5daafe7388ae5039d9999804d81c00d1b6f True
97 262k-512 main 262152 262144 512 4096 bench-512-3 3 512 640 326.0731117055152 40.21515105816116 1.6044366169953719 17.485617870996066 2577f5dc58806bfa2d770923235ca38c2ee1287f591bf3f0a5affd0d9da1704b f84efcffb6918e0e067e94df10b742a4bd051f054f15c62c25f1bdb95a26dd73 True
98 262k-512 main 262152 262144 512 4096 bench-512-4 3 512 640 318.1902927102107 43.508113583369024 1.6432227010009228 16.320090422006615 2affe3aea9eb191ea72197455b01efed5acb3922d1414da0f890491bbde3e67f 8ba4ebb1a0399ec82cf6ff2a86e01af9c0e10ab8d572b7d24a1d2d0172ff9e64 True
99 262k-512 main 262152 262144 512 4096 bench-7000-0 3 7000 640 287.71419294113775 48.79238838741156 24.365081126001314 37.448226578002505 6b8e7149da625c30b478f0e793fc4e788febe8013160276f5eb7d4217659b619 1097039e0e7e72da60365e9814e3061517b9f542548812bc6870651b1464cde7 True
100 262k-512 main 262152 262144 512 4096 bench-7000-1 3 7000 640 287.80291256547514 44.12058707956182 24.357497923003393 38.82947031799995 cf3bf3862432f28434d999ab26bbb99900518e85f635bb30fbe3b2dee8a43269 b3891c234ab824724793c678fe272125a075f67d4050f6364fc75d65716a01b9 True
101 262k-512 main 262152 262144 512 4096 bench-7000-2 3 7000 640 287.96629971532474 32.83330939237857 24.34486455500155 43.802383964997716 bbd058e7ee29c3a3403b7d2dedffb873412386e3185a537dc677f2649b4e64fa 6fc497fba02daec677102ebc635311c12bb25adbcec13437613dcdc3874b987f True
102 262k-512 main 262152 262144 512 4096 bench-7000-3 3 7000 640 288.49442999682657 42.39561735305613 24.299175920998096 39.36139631699916 271be8da7554e506184cb33a8d8211846dfe34551cfa5e1088b57dae34386533 f5106647d63660877542dccdd741b336f3651de99e0b4748d6907b2f219ed48a True
103 262k-512 main 262152 262144 512 4096 bench-7000-4 3 7000 640 287.7011853288836 40.96131076194438 24.366155340998375 39.95687096999609 36e2231837959a481491bf9d851b048eaff4008e60ef9025e304425e89a6ad53 16a8db9bfd9b939ce95dedb5e3a2b21b137ad8ebbbe7ab3be991292953736ece True
104 262k-512 public 262152 262144 512 4096 public2185-256-r1 1 2185 256 300.9185936015204 48.51517046638998 7.3306941440023365 12.547350928005471 cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514 dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12 True
105 262k-512 public 262152 262144 512 4096 public20-256-r1 1 20 256 48.828125 50.51701002446917 0.4462103360056062 5.47836589000508 05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d 4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020 True
106 262k-512 public 262152 262144 512 4096 public2185-256-r2 2 2185 256 302.43051710774 48.95305478535233 7.285462539002765 12.455673757998738 cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514 dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12 True
107 262k-512 public 262152 262144 512 4096 public20-256-r2 2 20 256 49.01960784313726 51.534977352793156 0.4439065019978443 5.376657145003264 05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d 4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020 True
108 262k-512 public 262152 262144 512 4096 public2185-256-r3 3 2185 256 302.9084758920897 48.94556717587901 7.28071175700461 12.451828441000544 cd1b3cc36dfc56280d180588054f7b87b0bfb4d887bedc4f73fc4a15686f8514 dd5bdf7755e489271c2f5b360b142187922097536223140145ec2aea76de3b12 True
109 262k-512 public 262152 262144 512 4096 public20-256-r3 3 20 256 49.14004914004914 51.531865211965055 0.44289757200021995 5.375990995002212 05749f4be1649ade32c8156f837fb5d4201f3f2109f408140c8ea5414a27ad5d 4f90da0ea12fbac0be7e1f3362abb1b45a480b8ec9cab48361d853d85348e020 True
@@ -0,0 +1,314 @@
{
"8k-512/five-tasks/512": {
"prompt_tps": {
"median": 352.37439779766004,
"min": 352.27741846704276,
"max": 352.8114663726571,
"n": 3
},
"decode_tps": {
"median": 45.01114729194652,
"min": 44.99247782011445,
"max": 45.01652950692832,
"n": 3
},
"ttft_s": {
"median": 1.486453754005197,
"min": 1.4847840959992027,
"max": 1.4869932690053247,
"n": 3
},
"total_s": {
"median": 15.687034372000198,
"min": 15.680540973000461,
"max": 15.70372823800426,
"n": 3
}
},
"8k-512/five-tasks/7000": {
"prompt_tps": {
"median": 315.44177620757876,
"min": 315.3124746623904,
"max": 315.45883487532615,
"n": 3
},
"decode_tps": {
"median": 43.490965431477946,
"min": 43.489487775376794,
"max": 43.493034318722394,
"n": 3
},
"ttft_s": {
"median": 22.22643303299992,
"min": 22.22521572799451,
"max": 22.235519458001363,
"n": 3
},
"total_s": {
"median": 36.88929874599853,
"min": 36.875881571999344,
"max": 36.891612551000435,
"n": 3
}
},
"8k-512/public/20": {
"prompt_tps": {
"median": 54.6000546000546,
"min": 54.55537370430987,
"max": 54.614964500273075,
"n": 3
},
"decode_tps": {
"median": 54.47851716286097,
"min": 54.46808510638298,
"max": 54.48547408747473,
"n": 3
},
"ttft_s": {
"median": 0.4001509320005425,
"min": 0.4000317419995554,
"max": 0.4005099159985548,
"n": 3
},
"total_s": {
"median": 5.066493678998086,
"min": 5.065761150995968,
"max": 5.067818413997884,
"n": 3
}
},
"8k-512/public/2185": {
"prompt_tps": {
"median": 323.35878766352926,
"min": 323.3013731060606,
"max": 323.4305845434226,
"n": 3
},
"decode_tps": {
"median": 49.72322035544333,
"min": 49.71935753267689,
"max": 49.724186154921924,
"n": 3
},
"ttft_s": {
"median": 6.817252700995596,
"min": 6.815883596995263,
"max": 6.818356577998202,
"n": 3
},
"total_s": {
"median": 11.906957781000528,
"min": 11.905609935995017,
"max": 11.908829965999757,
"n": 3
}
},
"8k-4096/five-tasks/512": {
"prompt_tps": {
"median": 330.9203722854188,
"min": 330.8776011373917,
"max": 331.1129793701093,
"n": 3
},
"decode_tps": {
"median": 44.63787523713871,
"min": 44.614226361431,
"max": 44.64565995354061,
"n": 3
},
"ttft_s": {
"median": 1.5811564449977595,
"min": 1.5801466330012772,
"max": 1.5813149160021567,
"n": 3
},
"total_s": {
"median": 15.895306143000198,
"min": 15.893667525000637,
"max": 15.90252744800091,
"n": 3
}
},
"8k-4096/five-tasks/7000": {
"prompt_tps": {
"median": 830.0034385856741,
"min": 829.9345537323343,
"max": 830.0329641662912,
"n": 3
},
"decode_tps": {
"median": 42.91989404151158,
"min": 42.91989404151158,
"max": 42.92277254283894,
"n": 3
},
"ttft_s": {
"median": 8.46887673099991,
"min": 8.468654577998677,
"max": 8.469412726000883,
"n": 3
},
"total_s": {
"median": 23.31782736400055,
"min": 23.317097936997015,
"max": 23.319345058996987,
"n": 3
}
},
"8k-4096/public/20": {
"prompt_tps": {
"median": 50.12531328320802,
"min": 50.112753695815584,
"max": 50.188205771643666,
"n": 3
},
"decode_tps": {
"median": 53.5083502288736,
"min": 53.50164057765053,
"max": 53.50946866769784,
"n": 3
},
"ttft_s": {
"median": 0.43392555299942615,
"min": 0.4332570679980563,
"max": 0.4339962550002383,
"n": 3
},
"total_s": {
"median": 5.184587747004116,
"min": 5.184442054000101,
"max": 5.184664774002158,
"n": 3
}
},
"8k-4096/public/2185": {
"prompt_tps": {
"median": 722.7202063969834,
"min": 582.4181682482141,
"max": 723.7735599059259,
"n": 3
},
"decode_tps": {
"median": 47.40389600770314,
"min": 47.40301823905194,
"max": 47.42585079382723,
"n": 3
},
"ttft_s": {
"median": 3.0846155070030363,
"min": 3.0805087330008973,
"max": 3.812937997005065,
"n": 3
},
"total_s": {
"median": 8.424763125003665,
"min": 8.418293693001033,
"max": 9.153436525004508,
"n": 3
}
},
"262k-512/five-tasks/512": {
"prompt_tps": {
"median": 320.56098171800653,
"min": 318.1309804896234,
"max": 320.72162365321975,
"n": 3
},
"decode_tps": {
"median": 43.508113583369024,
"min": 42.96224692551421,
"max": 43.512550651328496,
"n": 3
},
"ttft_s": {
"median": 1.6313107940004556,
"min": 1.6305150300031528,
"max": 1.6436967349945917,
"n": 3
},
"total_s": {
"median": 16.322636835000594,
"min": 16.320090422006615,
"max": 16.52241344399954,
"n": 3
}
},
"262k-512/five-tasks/7000": {
"prompt_tps": {
"median": 287.80291256547514,
"min": 285.04530184261426,
"max": 287.80409586343285,
"n": 3
},
"decode_tps": {
"median": 42.37765108625839,
"min": 41.86536360722439,
"max": 42.39561735305613,
"n": 3
},
"ttft_s": {
"median": 24.357497923003393,
"min": 24.357459778999328,
"max": 24.593217346002348,
"n": 3
},
"total_s": {
"median": 39.36770728800184,
"min": 39.36139631699916,
"max": 39.78784895900026,
"n": 3
}
},
"262k-512/public/20": {
"prompt_tps": {
"median": 49.01960784313726,
"min": 48.828125,
"max": 49.14004914004914,
"n": 3
},
"decode_tps": {
"median": 51.531865211965055,
"min": 50.51701002446917,
"max": 51.534977352793156,
"n": 3
},
"ttft_s": {
"median": 0.4439065019978443,
"min": 0.44289757200021995,
"max": 0.4462103360056062,
"n": 3
},
"total_s": {
"median": 5.376657145003264,
"min": 5.375990995002212,
"max": 5.47836589000508,
"n": 3
}
},
"262k-512/public/2185": {
"prompt_tps": {
"median": 302.43051710774,
"min": 300.9185936015204,
"max": 302.9084758920897,
"n": 3
},
"decode_tps": {
"median": 48.94556717587901,
"min": 48.51517046638998,
"max": 48.95305478535233,
"n": 3
},
"ttft_s": {
"median": 7.285462539002765,
"min": 7.28071175700461,
"max": 7.3306941440023365,
"n": 3
},
"total_s": {
"median": 12.455673757998738,
"min": 12.451828441000544,
"max": 12.547350928005471,
"n": 3
}
}
}
@@ -0,0 +1,89 @@
{
"os": "Ubuntu 26.04.1 LTS",
"kernel": "7.0.0-38-generic",
"cpu": {
"Architecture": "x86_64",
"CPU(s)": "16",
"Model name": "12th Gen Intel(R) Core(TM) i5-12600K",
"Thread(s) per core": "2",
"Core(s) per socket": "10",
"Socket(s)": "1",
"CPU max MHz": "4900.0000"
},
"memtotal": "129273108 kB",
"ram_dimms_allowlist": [
"Size: 32 GB",
"Locator: Controller0-ChannelA-DIMM0",
"Type: DDR4",
"Speed: 3200 MT/s",
"Configured Memory Speed: 3200 MT/s",
"Size: 32 GB",
"Locator: Controller0-ChannelA-DIMM1",
"Type: DDR4",
"Speed: 3200 MT/s",
"Configured Memory Speed: 3200 MT/s",
"Size: 32 GB",
"Locator: Controller1-ChannelA-DIMM0",
"Type: DDR4",
"Speed: 3200 MT/s",
"Configured Memory Speed: 3200 MT/s",
"Size: 32 GB",
"Locator: Controller1-ChannelA-DIMM1",
"Type: DDR4",
"Speed: 3200 MT/s",
"Configured Memory Speed: 3200 MT/s"
],
"gpu": {
"vendor": "0x8086",
"device": "0xe222",
"driver": "xe"
},
"power_limits_W": {
"power1_cap": 200.0
},
"packages": [
"intel-ocloc\t26.22.38646.7-1~26.04~ppa1",
"intel-opencl-icd\t26.22.38646.7-1~26.04~ppa1",
"libze-intel-gpu1\t26.22.38646.7-1~26.04~ppa1",
"libze1\t1.28.6-1~26.04~ppa1"
],
"compiler": "Intel(R) oneAPI DPC++/C++ Compiler 2026.1.0 (2026.1.0.20260617)\nTarget: x86_64-unknown-linux-gnu\nThread model: posix\nInstalledDir: /opt/intel/oneapi/compiler/2026.1/bin/compiler\nConfiguration file: /opt/intel/oneapi/compiler/2026.1/bin/compiler/../icpx.cfg",
"storage": {
"blockdevices": [
{
"name": "nvme0n1",
"model": "Samsung SSD 980 1TB",
"size": "931.5G",
"rota": false,
"tran": "nvme"
}
]
},
"ggml_commit": "3cf03257f219afbe7334045ff7c6a06ac68c627d",
"artifacts": "artifacts.json",
"python_runtime": {
"python": "3.14.4",
"packages": {
"numpy": "2.5.3",
"jinja2": "3.1.6",
"regex": "2026.9.10",
"pyyaml": "6.0.3",
"tqdm": "4.70.1",
"requests": "2.34.2",
"cmake": "4.4.3",
"ninja": "1.13.2",
"pillow": "12.3.0",
"psutil": "7.2.2"
}
},
"PCIe_link": {
"0000:00:01.0": {
"current_link_speed": "16.0 GT/s PCIe",
"current_link_width": "16"
},
"0000:01:00.0": {
"current_link_speed": "16.0 GT/s PCIe",
"current_link_width": "16"
}
}
}
@@ -0,0 +1,121 @@
# Radeon 890M (gfx1150): a hipBLASLt table, and the gfx1151 exact switches (2026-10-07)
gfx1150 (Strix Point) builds and runs from 0.1.40.2 (#1217), but there was no hipBLASLt table for it, so the prompt's
dense GEMMs ran on plain hipBLAS. This folder has the table this machine calibrated
(`tools/hip/gfx1150-hipblaslt-100401.txt`) and what it does: **prompts read 1.5-1.7x faster** (3.6K tokens: 124 ->
216 tok/s, 7K: 130 -> 226 tok/s, medians of 3 interleaved rounds), decode unchanged. It also checks the exact speed
switches that 0.1.40 turns on for gfx1151 (18), less `STRATA_HCD_EXACT` (17), on this chip: the same greedy answers with and
without them, decode +2% and prompts +3-5%.
## Rig
- MINISFORUM N5 PRO: Ryzen AI 9 HX PRO 370 (12 cores / 24 threads, Zen 5, AVX-512), Radeon 890M (gfx1150, RDNA3.5,
16 CUs, PCI `1002:150e`), 96 GB DDR5-5600 (93.4 GiB usable), BIOS carve-out 512 MB. The GPU's memory is the GTT pool
of the same RAM, raised to 64 GiB with `ttm.pages_limit=16777216 ttm.page_pool_size=16777216`.
- Proxmox VE 9.2 (Debian 13), kernel 7.0.14-20-pve with the in-tree amdgpu / amdkfd. The engine runs in an unprivileged
LXC container (Debian 13.7) with `/dev/kfd` and `/dev/dri/renderD128` passed in.
- ROCm: AMD TheRock 7.14.1 for gfx1150 (`therock-dist-linux-gfx1150-7.14.1.tar.gz`, SHA-256
`da8335c9bc230a8b0e3e43b21dedfb3cfc2456f3ecfecfaa49db40096f08bac5`): hipBLASLt 1.4.1 (`cd957402`, version number
100401), HIP runtime 71460850.
- Engine 0.1.40.2 (`e8ca9af`), built by hand: `-DSTRATA_ENABLE_HIP=ON -DSTRATA_PREFILL_MMQ=ON
-DSTRATA_PARITY_PROMPT_ATTN=ON -DCMAKE_HIP_ARCHITECTURES=gfx1150` with GCC 14.2 (the steps of
[STRIX_HALO.md](../../../docs/STRIX_HALO.md) with the architecture changed). ctest: 58 of 61 pass; the other three are
`hip_prefill_hcd_exact_parity` and `hip_prefill_hipblaslt_gemm` (skipped without a table) and `ple_parity` (needs
`bench/micro` data). `iq_parity` by hand: all 10 formats ok.
- Model: Qwen3.8-Flash-Next GSQ-RCO IQ3_XXS (ISTA-DASLab, revision `ed59f920`), a native pack with `experts.bin`.
Server config: [strata-gfx1150.json](strata-gfx1150.json). All 24,576 experts are in the GTT pool (`--mmap-experts
--expert-cache 24576`, 39.97 GiB), `--prefill auto` (8,192-token chunks, a 96-slot ring), `--spec 4 --spec-min-p 0.5`
with the MTP draft layer, `--max-context 65536 --kv int8`, `--conversation-cache-mib 12288`, `--vision`.
## Calibrating the table
1. **The shapes.** A table with only its header (`STRATA_HIPBLASLT_TUNING_V1 gfx1150 100401`) and
`STRATA_HIPBLASLT_VERBOSE=1` make the engine log every GEMM it would look up. Prompts of 28 to 7,881 tokens logged 16
geometries (the same 16 as `gfx1201-hipblaslt-100500.txt`) at T from 116 to 7,874.
2. **tune_hipblaslt** (this checkout's, the engine's 32 MiB workspace) over the 16 geometries at T = 64, 128, 256, 512,
1024, 2048, 4096, 8192 and 16384: 144 cases, run twice back to back with the server stopped (4.5 minutes a pass).
No candidate failed the tool's accuracy gate.
3. **The pick.** Now and then one repetition stalls: a call that takes 100 ms read 800-1,650 ms once. The tool keeps the
lowest mean of its three repetitions, so a stall can hide the fastest solution; its own picks differed in 26 of the
144 rows between the two passes. Each row of the table is the solution with the lowest **median of all six
repetitions** of both passes.
Every row beats plain hipBLAS (`hipblasGemmEx`): 1.55x to 22.6x per GEMM, geometric mean 4.5x (4.7x at T=8192). The
largest, f16 N=12288 K=2560 at T=8192, takes 90 ms instead of 308 ms. Per case: [tune-summary.csv](tune-summary.csv)
(medians in ms, the kept solution, and how many candidates the heuristic offered).
The engine takes it (`prefill gemm: hipBLASLt tuning enabled (144 rows, gfx1150, version 100401)`), and with
`STRATA_HIPBLASLT_VERBOSE=1` prompts of 28 to 7,880 tokens logged 76 Lt solutions and 0 fallbacks. With
`STRATA_HIPBLASLT_TUNING` set to it, `hip_prefill_hipblaslt_gemm` passes (`launches=4 fallbacks=0`, its four cases within
`relative_l2` 8e-6 of hipBLASEx) and `hip_prefill_hcd_exact_parity` skips: at every tested T (64 to 16384) the table
sends the HC down projection to another solution than 1176 / 1177.
## Prompt speed
Three rounds, the three configurations interleaved, the server restarted for every run (cold prompt cache), one request
at a time, the engine's own `strata serve: prompt` line. Each run: a short chat three times (256 tokens out, greedy),
then one fresh document prompt each of about 1K, 3.6K and 7K tokens (a random nonce first). Every run is in
[runs.csv](runs.csv).
- `hipblas+switches`: no table, the 17 switches set by hand (what this machine ran before)
- `table`: the table, no switches
- `table+switches`: the table and the 17 switches
| Prompt | hipblas+switches | table | table+switches |
|---|---:|---:|---:|
| 987 tokens | 99.1 tok/s | 152.4 | 153.1 |
| 3,562 tokens | 123.9 | 205.6 | 216.0 |
| 7,010 tokens | 130.5 | 219.4 | 225.8 |
| decode, short chat (256 tokens) | 15.3-15.4 tok/s | 14.9-15.0 | 15.2-15.3 |
Medians of the three rounds. Each round on its own gave the same order. A 13,969-token prompt (two chunks) read in 107.7 s
(130 tok/s) without the table and 61.5 s (227 tok/s) with it and the switches (64.6 s without the switches).
Where the time goes now (`STRATA_PREFILL_TIMING=1`, 7,003 tokens, table+switches, 30.3 s of GPU time): prompt
attention 23%, GDN projections 15%, expert GEMMs 22% (gate/up 14, down 8), hyper-connection read 8%, QSA projections
8%, GDN output projection 7%. Before the table the dense projections (hyper-connection read, GDN, QSA, router and shared
expert, GDN output) were 65% of it.
**Answers.** Greedy, no thinking, four fixed prompts (a 28-token chat, a 35-token code question, documents of 3,546 and
13,969 tokens; 57-128 tokens out). With and without the table the first three answers were the same text; the
13,969-token one diverged from its first sentence on. The table changes the summation order of the dense GEMMs, as on
the other cards' tables.
## The gfx1151 exact switches on gfx1150
0.1.40 turns on 18 switches by default on gfx1151 ([STRIX_HALO.md](../../../docs/STRIX_HALO.md) section 4). This machine
ran 17 of them by hand (not `STRATA_HCD_EXACT`: it copies gfx1151's hipBLASLt solutions 1176 / 1177, and the gfx1150
table picks others, 539-555 for the bf16 rows).
- **Exact here too.** With the table, the four greedy answers above were the same text with all 17 on and with all 17
off, also the 13,969-token one. Without the table, 0.1.40.1 and 0.1.40.2 also gave the same four answers.
- **Faster, a little.** From the rounds above (table vs table+switches): decode 14.9-15.0 -> 15.2-15.3 tok/s (+2%, in
every pair), prompts +4.1 / +4.3 / +6.0% at 3.6K and +2.1 / +3.6 / +4.0% at 7K. Without `STRATA_SH_STREAM` (16 on)
one run read the same as with it.
## Rounding-level switches (not on by default)
One run each, each switch added alone to table+switches (prompts of about 1K / 3.6K / 7K tokens; that configuration read
153 / 217 / 230 tok/s in the same session):
| Switch | Prompt tok/s |
|---|---|
| `STRATA_HIP_WMMA=1` | 160 / 250 / 277 (+20% at 7K) |
| `STRATA_PF_FUSED=1` | 155 / 257 / 255 |
| `STRATA_PF_GEMM=1` | 166 / 243 / 262 |
| `STRATA_PA_FAST=1`, `STRATA_SELECT_WMMA=1`, `STRATA_HC_UPMIX=1` | unchanged |
| `STRATA_HC_Q8=1` | 146 / 219 / 224 |
| `STRATA_PREFILL_CPU_SHARE=auto` | unchanged (153 / 217 / 230) |
| `--no-prefill-borrow` | 162 / 195 / 190 |
Decode did not move with any of them. All seven of STRIX_HALO.md section 5 together, on 0.1.40.1 without the table, read
83 tok/s at 3.6K where the exact switches alone read 124. These change bits and no KL was measured here.
## Not tested
- Answer quality beyond the greedy comparisons above (no KL, no benchmark), other models (only GSQ-RCO IQ3_XXS; the
OrcaRouter IQ3_XXS of [ORCA.md](../../../docs/ORCA.md) also started and answered with the table), contexts past
14K tokens.
- `--prefill 16384`: the table has T=16384 rows, but this machine serves `--prefill auto`.
- Other ROCm versions: the table is for hipBLASLt 100401 only; the engine refuses it with another version.
- setup: it does not install for gfx1150, so the table is set by hand (`STRATA_HIPBLASLT_TUNING`).
@@ -0,0 +1,55 @@
config,round,case,prompt_tokens,reused,read,prompt_s,prompt_tok_s,generated,decode_s,decode_tok_s,drafts_accepted,drafts
hipblas+switches,r1,chat1,28,0,28,0.86,32.4,256,16.67,15.4,104,167
hipblas+switches,r1,chat2,28,21,7,0.22,31.6,256,16.65,15.4,104,167
hipblas+switches,r1,chat3,28,21,7,0.23,30.4,256,16.66,15.4,104,167
hipblas+switches,r1,~1000,989,0,989,9.98,99.1,74,4.45,16.6,41,69
hipblas+switches,r1,~4000,3562,0,3562,28.42,125.3,61,3.49,17.5,36,53
hipblas+switches,r1,~8000,7009,0,7009,53.90,130.0,61,3.38,18.1,37,50
hipblas+switches,r2,chat1,28,0,28,0.89,31.5,256,17.03,15.0,104,167
hipblas+switches,r2,chat2,28,21,7,0.22,31.4,256,16.77,15.3,104,167
hipblas+switches,r2,chat3,28,21,7,0.24,29.6,256,16.67,15.4,104,167
hipblas+switches,r2,~1000,990,0,990,9.94,99.6,64,3.83,16.7,37,57
hipblas+switches,r2,~4000,3563,0,3563,28.76,123.9,61,3.66,16.7,35,56
hipblas+switches,r2,~8000,7009,0,7009,53.71,130.5,61,3.50,17.4,35,50
hipblas+switches,r3,chat1,28,0,28,0.88,31.7,256,17.11,15.0,104,167
hipblas+switches,r3,chat2,28,21,7,0.23,30.4,256,16.75,15.3,104,167
hipblas+switches,r3,chat3,28,21,7,0.25,28.3,256,16.72,15.3,104,167
hipblas+switches,r3,~1000,987,0,987,10.55,93.5,63,3.67,17.2,35,52
hipblas+switches,r3,~4000,3563,0,3563,28.87,123.4,61,3.50,17.4,36,52
hipblas+switches,r3,~8000,7012,0,7012,53.64,130.7,61,3.50,17.4,36,56
table,r1,chat1,28,0,28,0.89,31.4,256,17.07,15.0,104,167
table,r1,chat2,28,21,7,0.23,30.2,256,17.07,15.0,104,167
table,r1,chat3,28,21,7,0.24,28.7,256,17.05,15.0,104,167
table,r1,~1000,986,0,986,6.97,141.4,64,4.00,16.0,36,61
table,r1,~4000,3562,0,3562,17.33,205.6,77,4.37,17.6,46,65
table,r1,~8000,7011,0,7011,31.93,219.6,77,4.33,17.8,45,62
table,r2,chat1,28,0,28,1.12,24.9,256,17.17,14.9,104,167
table,r2,chat2,28,21,7,0.23,30.1,256,17.14,14.9,104,167
table,r2,chat3,28,21,7,0.24,28.8,256,16.99,15.1,104,167
table,r2,~1000,988,0,988,6.41,154.2,72,4.52,15.9,40,67
table,r2,~4000,3564,0,3564,17.18,207.4,61,3.75,16.3,36,56
table,r2,~8000,7011,0,7011,32.17,217.9,77,4.40,17.5,45,65
table,r3,chat1,28,0,28,0.88,31.8,256,17.07,15.0,104,167
table,r3,chat2,28,21,7,0.23,30.4,256,17.27,14.8,104,167
table,r3,chat3,28,21,7,0.24,29.3,256,17.06,15.0,104,167
table,r3,~1000,988,0,988,6.48,152.4,72,4.22,17.1,41,62
table,r3,~4000,3563,0,3563,17.35,205.4,77,4.41,17.5,46,64
table,r3,~8000,7007,0,7007,31.94,219.4,61,3.77,16.2,35,56
table+switches,r1,chat1,28,0,28,0.96,29.1,256,17.09,15.0,104,167
table+switches,r1,chat2,28,21,7,0.23,30.6,256,16.70,15.3,104,167
table+switches,r1,chat3,28,21,7,0.24,29.2,256,16.72,15.3,104,167
table+switches,r1,~1000,987,0,987,6.46,152.8,64,3.74,17.1,37,56
table+switches,r1,~4000,3563,0,3563,16.61,214.5,61,3.47,17.6,36,52
table+switches,r1,~8000,7008,0,7008,30.70,228.3,61,3.56,17.1,36,53
table+switches,r2,chat1,28,0,28,0.86,32.5,256,16.84,15.2,104,167
table+switches,r2,chat2,28,21,7,0.22,31.9,256,16.72,15.3,104,167
table+switches,r2,chat3,28,21,7,0.23,30.4,256,16.82,15.2,104,167
table+switches,r2,~1000,989,0,989,6.28,157.5,64,3.74,17.1,37,56
table+switches,r2,~4000,3563,0,3563,16.49,216.0,61,3.43,17.8,37,55
table+switches,r2,~8000,7010,0,7010,31.04,225.8,61,3.61,16.9,36,50
table+switches,r3,chat1,28,0,28,0.88,31.7,256,16.87,15.2,104,167
table+switches,r3,chat2,28,21,7,0.22,31.5,256,16.81,15.2,104,167
table+switches,r3,chat3,28,21,7,0.23,30.1,256,16.89,15.2,104,167
table+switches,r3,~1000,988,0,988,6.45,153.1,64,3.94,16.3,36,59
table+switches,r3,~4000,3565,0,3565,16.37,217.8,82,4.71,17.4,46,62
table+switches,r3,~8000,7010,0,7010,31.31,223.9,61,3.62,16.9,34,53
1 config round case prompt_tokens reused read prompt_s prompt_tok_s generated decode_s decode_tok_s drafts_accepted drafts
2 hipblas+switches r1 chat1 28 0 28 0.86 32.4 256 16.67 15.4 104 167
3 hipblas+switches r1 chat2 28 21 7 0.22 31.6 256 16.65 15.4 104 167
4 hipblas+switches r1 chat3 28 21 7 0.23 30.4 256 16.66 15.4 104 167
5 hipblas+switches r1 ~1000 989 0 989 9.98 99.1 74 4.45 16.6 41 69
6 hipblas+switches r1 ~4000 3562 0 3562 28.42 125.3 61 3.49 17.5 36 53
7 hipblas+switches r1 ~8000 7009 0 7009 53.90 130.0 61 3.38 18.1 37 50
8 hipblas+switches r2 chat1 28 0 28 0.89 31.5 256 17.03 15.0 104 167
9 hipblas+switches r2 chat2 28 21 7 0.22 31.4 256 16.77 15.3 104 167
10 hipblas+switches r2 chat3 28 21 7 0.24 29.6 256 16.67 15.4 104 167
11 hipblas+switches r2 ~1000 990 0 990 9.94 99.6 64 3.83 16.7 37 57
12 hipblas+switches r2 ~4000 3563 0 3563 28.76 123.9 61 3.66 16.7 35 56
13 hipblas+switches r2 ~8000 7009 0 7009 53.71 130.5 61 3.50 17.4 35 50
14 hipblas+switches r3 chat1 28 0 28 0.88 31.7 256 17.11 15.0 104 167
15 hipblas+switches r3 chat2 28 21 7 0.23 30.4 256 16.75 15.3 104 167
16 hipblas+switches r3 chat3 28 21 7 0.25 28.3 256 16.72 15.3 104 167
17 hipblas+switches r3 ~1000 987 0 987 10.55 93.5 63 3.67 17.2 35 52
18 hipblas+switches r3 ~4000 3563 0 3563 28.87 123.4 61 3.50 17.4 36 52
19 hipblas+switches r3 ~8000 7012 0 7012 53.64 130.7 61 3.50 17.4 36 56
20 table r1 chat1 28 0 28 0.89 31.4 256 17.07 15.0 104 167
21 table r1 chat2 28 21 7 0.23 30.2 256 17.07 15.0 104 167
22 table r1 chat3 28 21 7 0.24 28.7 256 17.05 15.0 104 167
23 table r1 ~1000 986 0 986 6.97 141.4 64 4.00 16.0 36 61
24 table r1 ~4000 3562 0 3562 17.33 205.6 77 4.37 17.6 46 65
25 table r1 ~8000 7011 0 7011 31.93 219.6 77 4.33 17.8 45 62
26 table r2 chat1 28 0 28 1.12 24.9 256 17.17 14.9 104 167
27 table r2 chat2 28 21 7 0.23 30.1 256 17.14 14.9 104 167
28 table r2 chat3 28 21 7 0.24 28.8 256 16.99 15.1 104 167
29 table r2 ~1000 988 0 988 6.41 154.2 72 4.52 15.9 40 67
30 table r2 ~4000 3564 0 3564 17.18 207.4 61 3.75 16.3 36 56
31 table r2 ~8000 7011 0 7011 32.17 217.9 77 4.40 17.5 45 65
32 table r3 chat1 28 0 28 0.88 31.8 256 17.07 15.0 104 167
33 table r3 chat2 28 21 7 0.23 30.4 256 17.27 14.8 104 167
34 table r3 chat3 28 21 7 0.24 29.3 256 17.06 15.0 104 167
35 table r3 ~1000 988 0 988 6.48 152.4 72 4.22 17.1 41 62
36 table r3 ~4000 3563 0 3563 17.35 205.4 77 4.41 17.5 46 64
37 table r3 ~8000 7007 0 7007 31.94 219.4 61 3.77 16.2 35 56
38 table+switches r1 chat1 28 0 28 0.96 29.1 256 17.09 15.0 104 167
39 table+switches r1 chat2 28 21 7 0.23 30.6 256 16.70 15.3 104 167
40 table+switches r1 chat3 28 21 7 0.24 29.2 256 16.72 15.3 104 167
41 table+switches r1 ~1000 987 0 987 6.46 152.8 64 3.74 17.1 37 56
42 table+switches r1 ~4000 3563 0 3563 16.61 214.5 61 3.47 17.6 36 52
43 table+switches r1 ~8000 7008 0 7008 30.70 228.3 61 3.56 17.1 36 53
44 table+switches r2 chat1 28 0 28 0.86 32.5 256 16.84 15.2 104 167
45 table+switches r2 chat2 28 21 7 0.22 31.9 256 16.72 15.3 104 167
46 table+switches r2 chat3 28 21 7 0.23 30.4 256 16.82 15.2 104 167
47 table+switches r2 ~1000 989 0 989 6.28 157.5 64 3.74 17.1 37 56
48 table+switches r2 ~4000 3563 0 3563 16.49 216.0 61 3.43 17.8 37 55
49 table+switches r2 ~8000 7010 0 7010 31.04 225.8 61 3.61 16.9 36 50
50 table+switches r3 chat1 28 0 28 0.88 31.7 256 16.87 15.2 104 167
51 table+switches r3 chat2 28 21 7 0.22 31.5 256 16.81 15.2 104 167
52 table+switches r3 chat3 28 21 7 0.23 30.1 256 16.89 15.2 104 167
53 table+switches r3 ~1000 988 0 988 6.45 153.1 64 3.94 16.3 36 59
54 table+switches r3 ~4000 3565 0 3565 16.37 217.8 82 4.71 17.4 46 62
55 table+switches r3 ~8000 7010 0 7010 31.31 223.9 61 3.62 16.9 34 53
@@ -0,0 +1,74 @@
{
"exe": "/models/runtime/strata/current/build-gfx1150/strata",
"args": [
"--pack",
"/models/strata/packs/iq3_xxs",
"--native",
"/models/strata/Qwen3.8-Flash-Next-IQ3_XXS/Qwen3.8-Flash-Next-GSQ-RCO-IQ3_XXS-00001-of-00002.gguf",
"--ple-gguf",
"/models/strata/Qwen3.8-Flash-Next-IQ3_XXS/Qwen3.8-Flash-Next-GSQ-RCO-IQ3_XXS-00002-of-00002.gguf",
"--expert-profile",
"/models/runtime/strata/current/data/expert-profile.bin",
"--expert-cache",
"24576",
"--mmap-experts",
"--prefill",
"auto",
"--spec",
"4",
"--spec-min-p",
"0.5",
"--mtp",
"/models/strata/mtp/rt",
"--max-context",
"65536",
"--kv",
"int8",
"--conversation-cache-mib",
"12288",
"--conversation-cache-slots",
"8",
"--vision",
"--vram-reserve-mib",
"700"
],
"cwd": "/models/runtime/strata/current",
"tokenizer": "/models/strata/packs/iq3_xxs/tokenizer",
"model_name": "qwen3.8-flash-next",
"log": "/models/strata/state/strata-qwen38.log",
"lib_dirs": [
"/models/runtime/strata/current/.rocm/lib",
"/models/runtime/strata/current/.rocm/lib/rocm_sysdeps/lib",
"/models/runtime/strata/current/.rocm/lib/llvm/lib"
],
"port": 8082,
"backend": "hip",
"env": {
"STRATA_ATTN_LANECELL": "1",
"STRATA_CVEC_FUSE": "1",
"STRATA_EXPERT_V2": "1",
"STRATA_GDN_CONVL2": "1",
"STRATA_GDN_HEAD": "1",
"STRATA_GDN_NOY": "1",
"STRATA_GDN_PP": "2",
"STRATA_GDN_SPLIT": "1",
"STRATA_LFUSE": "1",
"STRATA_MMVF_ROWS": "1",
"STRATA_PF_PAD": "1",
"STRATA_PLE_BATCH": "1",
"STRATA_Q6_PACKED": "1",
"STRATA_Q8_PACKED": "1",
"STRATA_QFUSE": "1",
"STRATA_SH_STREAM": "1",
"STRATA_TSUM": "1",
"STRATA_HIPBLASLT_TUNING": "/models/runtime/strata/tuning/gfx1150-hipblaslt-100401.txt"
},
"vision": {
"exe": "/models/runtime/strata/current/build-vision/bin/strata-vision",
"mmproj": "/models/strata/vision/mmproj-Qwen3.8-Flash-Next-BF16.gguf",
"model": "/models/strata/Qwen3.8-Flash-Next-IQ3_XXS/Qwen3.8-Flash-Next-GSQ-RCO-IQ3_XXS-00001-of-00002.gguf",
"gpu": false,
"max_tokens": 300,
"threads": 8
}
}
@@ -0,0 +1,145 @@
dtype,T,N,K,ldy,hipblas_ms,hipblaslt_ms,speedup,solution_id,candidates
f16,16384,12288,2560,12288,570.6621,188.9930,3.02,1156,7
f16,16384,10240,2560,10240,503.3711,156.5461,3.22,1156,7
f16,16384,6144,2560,6144,293.1865,90.8025,3.23,1156,7
f16,16384,2560,6144,2560,305.2351,95.6022,3.19,1156,7
f16,16384,2560,640,2560,30.1023,7.7349,3.89,1156,7
f16,16384,640,2560,640,28.5472,8.7900,3.25,1156,7
f16,16384,512,2560,512,23.9800,6.8811,3.48,1156,7
bf16,16384,10240,2560,10240,643.8805,156.7946,4.11,542,9
bf16,16384,10240,320,10240,76.4387,15.2220,5.02,542,9
bf16,16384,320,10240,320,77.3861,14.7762,5.24,542,9
bf16,16384,2560,2560,2560,150.7980,35.3540,4.27,542,9
bf16,16384,512,2560,512,30.8884,7.1108,4.34,542,9
bf16,16384,128,2560,128,8.3923,1.7241,4.87,542,9
bf16,16384,48,2560,96,10.6357,1.1835,8.99,542,9
bf16,16384,4,10240,4,40.6301,4.0832,9.95,540,9
bf16,16384,1,2560,1,9.9104,1.1005,9.01,541,9
f16,8192,12288,2560,12288,308.3724,90.1251,3.42,1156,7
f16,8192,10240,2560,10240,250.9099,74.3622,3.37,1156,7
f16,8192,6144,2560,6144,140.4356,43.8731,3.20,1156,7
f16,8192,2560,6144,2560,150.6988,44.4999,3.39,1156,7
f16,8192,2560,640,2560,14.8262,3.7157,3.99,1156,7
f16,8192,640,2560,640,13.9774,4.2053,3.32,1156,7
f16,8192,512,2560,512,11.6448,3.2112,3.63,1156,7
bf16,8192,10240,2560,10240,320.6165,74.0897,4.33,542,9
bf16,8192,10240,320,10240,38.5849,7.4783,5.16,542,9
bf16,8192,320,10240,320,37.5879,7.2077,5.21,542,9
bf16,8192,2560,2560,2560,76.0175,17.7230,4.29,542,9
bf16,8192,512,2560,512,15.2948,3.3626,4.55,542,9
bf16,8192,128,2560,128,4.1660,0.8738,4.77,542,9
bf16,8192,48,2560,96,5.3577,0.5958,8.99,542,9
bf16,8192,4,10240,4,20.5606,2.0541,10.01,539,9
bf16,8192,1,2560,1,5.0202,0.5513,9.11,541,9
f16,4096,12288,2560,12288,154.3027,43.5847,3.54,1156,7
f16,4096,10240,2560,10240,125.2170,35.3366,3.54,1156,7
f16,4096,6144,2560,6144,76.6512,21.5816,3.55,1156,7
f16,4096,2560,6144,2560,72.3956,21.3828,3.39,1156,7
f16,4096,2560,640,2560,7.5191,1.9463,3.86,1156,7
f16,4096,640,2560,640,7.5407,1.9201,3.93,1156,7
f16,4096,512,2560,512,7.6409,1.5795,4.84,1156,7
bf16,4096,10240,2560,10240,158.8611,35.4939,4.48,542,9
bf16,4096,10240,320,10240,19.6857,3.8810,5.07,542,9
bf16,4096,320,10240,320,17.5878,3.6732,4.79,542,9
bf16,4096,2560,2560,2560,37.4763,8.6888,4.31,542,9
bf16,4096,512,2560,512,7.3683,1.5579,4.73,542,9
bf16,4096,128,2560,128,2.0444,0.4077,5.01,542,9
bf16,4096,48,2560,96,2.6212,0.3096,8.46,539,9
bf16,4096,4,10240,4,9.7732,1.0236,9.55,540,9
bf16,4096,1,2560,1,2.5765,0.2698,9.55,540,9
f16,2048,12288,2560,12288,75.0208,21.6041,3.47,1156,7
f16,2048,10240,2560,10240,66.4348,17.9153,3.71,1156,7
f16,2048,6144,2560,6144,38.5592,10.6631,3.62,1156,7
f16,2048,2560,6144,2560,36.8025,10.4813,3.51,1156,7
f16,2048,2560,640,2560,4.0939,0.8960,4.57,1156,7
f16,2048,640,2560,640,4.1720,0.9064,4.60,1156,7
f16,2048,512,2560,512,3.6901,0.7531,4.90,1156,7
bf16,2048,10240,2560,10240,80.8788,18.5174,4.37,542,9
bf16,2048,10240,320,10240,9.9698,1.9474,5.12,542,9
bf16,2048,320,10240,320,9.3119,1.8604,5.01,542,9
bf16,2048,2560,2560,2560,18.4291,4.0419,4.56,542,9
bf16,2048,512,2560,512,3.9841,0.7788,5.12,542,9
bf16,2048,128,2560,128,1.2195,0.2385,5.11,542,9
bf16,2048,48,2560,96,1.3148,0.1521,8.65,542,9
bf16,2048,4,10240,4,4.9064,0.6099,8.05,555,9
bf16,2048,1,2560,1,1.2333,0.1394,8.85,539,9
f16,1024,12288,2560,12288,38.5003,10.2640,3.75,1156,7
f16,1024,10240,2560,10240,31.9227,8.6601,3.69,1156,7
f16,1024,6144,2560,6144,18.4690,5.1609,3.58,1156,7
f16,1024,2560,6144,2560,17.6803,4.6002,3.84,1156,7
f16,1024,2560,640,2560,1.9869,0.4573,4.34,1156,7
f16,1024,640,2560,640,2.1281,0.5205,4.09,1156,7
f16,1024,512,2560,512,1.6421,0.3834,4.28,1156,7
bf16,1024,10240,2560,10240,38.4572,8.4683,4.54,542,9
bf16,1024,10240,320,10240,5.5595,1.6651,3.34,542,9
bf16,1024,320,10240,320,5.3373,1.0736,4.97,542,9
bf16,1024,2560,2560,2560,9.9116,1.8666,5.31,542,9
bf16,1024,512,2560,512,2.1414,0.3931,5.45,542,9
bf16,1024,128,2560,128,0.6803,0.1084,6.28,542,9
bf16,1024,48,2560,96,0.8438,0.0910,9.27,541,9
bf16,1024,4,10240,4,2.5770,0.2658,9.70,553,9
bf16,1024,1,2560,1,0.7056,0.0826,8.54,541,9
f16,512,12288,2560,12288,19.0235,4.9853,3.82,1156,7
f16,512,10240,2560,10240,15.7707,4.0130,3.93,1156,7
f16,512,6144,2560,6144,8.5797,2.1693,3.95,1156,7
f16,512,2560,6144,2560,9.1863,2.0610,4.46,1156,7
f16,512,2560,640,2560,0.9946,0.2204,4.51,1156,7
f16,512,640,2560,640,1.1312,0.2664,4.25,1156,7
f16,512,512,2560,512,0.8627,0.2329,3.70,1156,7
bf16,512,10240,2560,10240,18.5991,3.8958,4.77,542,9
bf16,512,10240,320,10240,2.3511,0.9714,2.42,542,9
bf16,512,320,10240,320,2.5423,0.3841,6.62,542,9
bf16,512,2560,2560,2560,5.3614,1.0053,5.33,542,9
bf16,512,512,2560,512,1.3167,0.2460,5.35,541,9
bf16,512,128,2560,128,0.3764,0.0802,4.69,542,9
bf16,512,48,2560,96,0.3619,0.0669,5.41,542,9
bf16,512,4,10240,4,1.2848,0.1538,8.35,553,9
bf16,512,1,2560,1,0.3443,0.0412,8.36,555,9
f16,256,12288,2560,12288,11.0056,2.6006,4.23,1156,7
f16,256,10240,2560,10240,9.5589,2.1220,4.50,1156,7
f16,256,6144,2560,6144,4.8171,1.3619,3.54,1156,7
f16,256,2560,6144,2560,4.4667,1.1821,3.78,1156,7
f16,256,2560,640,2560,0.5956,0.1270,4.69,1156,7
f16,256,640,2560,640,0.7308,0.1250,5.85,1156,7
f16,256,512,2560,512,0.4694,0.1808,2.60,1156,7
bf16,256,10240,2560,10240,10.3660,2.1516,4.82,542,9
bf16,256,10240,320,10240,1.3209,0.3100,4.26,542,9
bf16,256,320,10240,320,1.5608,0.2526,6.18,541,9
bf16,256,2560,2560,2560,2.5480,0.5802,4.39,542,9
bf16,256,512,2560,512,0.5536,0.1081,5.12,542,9
bf16,256,128,2560,128,0.1628,0.0827,1.97,540,9
bf16,256,48,2560,96,0.1880,0.0645,2.91,543,9
bf16,256,4,10240,4,0.7191,0.1333,5.40,539,9
bf16,256,1,2560,1,0.1812,0.0261,6.94,553,9
f16,128,12288,2560,12288,5.7421,1.8325,3.13,1154,7
f16,128,10240,2560,10240,4.3162,1.5516,2.78,1154,7
f16,128,6144,2560,6144,2.3298,0.9226,2.53,1154,7
f16,128,2560,6144,2560,2.6517,0.8918,2.97,1156,7
f16,128,2560,640,2560,0.2936,0.1385,2.12,1156,7
f16,128,640,2560,640,0.3463,0.2238,1.55,1167,7
f16,128,512,2560,512,0.2902,0.0985,2.94,1156,7
bf16,128,10240,2560,10240,5.5433,1.5391,3.60,540,9
bf16,128,10240,320,10240,0.6654,0.1904,3.50,542,9
bf16,128,320,10240,320,0.7363,0.2120,3.47,541,9
bf16,128,2560,2560,2560,1.3454,0.3869,3.48,542,9
bf16,128,512,2560,512,0.2837,0.0999,2.84,541,9
bf16,128,128,2560,128,0.1492,0.0485,3.08,552,9
bf16,128,48,2560,96,0.1477,0.0235,6.29,543,9
bf16,128,4,10240,4,0.4786,0.0630,7.60,543,9
bf16,128,1,2560,1,0.1326,0.0205,6.45,553,9
f16,64,12288,2560,12288,4.9551,1.2391,4.00,1154,7
f16,64,10240,2560,10240,4.0352,0.9967,4.05,1154,7
f16,64,6144,2560,6144,2.4523,0.6709,3.66,1154,7
f16,64,2560,6144,2560,2.2624,0.6604,3.43,1156,7
f16,64,2560,640,2560,0.2160,0.0606,3.57,1156,7
f16,64,640,2560,640,0.3042,0.0915,3.33,1155,7
f16,64,512,2560,512,0.2539,0.0863,2.94,1154,7
bf16,64,10240,2560,10240,4.1701,1.0490,3.98,541,9
bf16,64,10240,320,10240,0.3608,0.1476,2.44,541,9
bf16,64,320,10240,320,0.6882,0.1945,3.54,539,9
bf16,64,2560,2560,2560,0.8595,0.2575,3.34,541,9
bf16,64,512,2560,512,0.2072,0.0910,2.28,555,9
bf16,64,128,2560,128,0.1414,0.0460,3.08,555,9
bf16,64,48,2560,96,0.1501,0.0284,5.28,554,9
bf16,64,4,10240,4,0.3768,0.0593,6.35,543,9
bf16,64,1,2560,1,0.4442,0.0197,22.55,543,9
1 dtype T N K ldy hipblas_ms hipblaslt_ms speedup solution_id candidates
2 f16 16384 12288 2560 12288 570.6621 188.9930 3.02 1156 7
3 f16 16384 10240 2560 10240 503.3711 156.5461 3.22 1156 7
4 f16 16384 6144 2560 6144 293.1865 90.8025 3.23 1156 7
5 f16 16384 2560 6144 2560 305.2351 95.6022 3.19 1156 7
6 f16 16384 2560 640 2560 30.1023 7.7349 3.89 1156 7
7 f16 16384 640 2560 640 28.5472 8.7900 3.25 1156 7
8 f16 16384 512 2560 512 23.9800 6.8811 3.48 1156 7
9 bf16 16384 10240 2560 10240 643.8805 156.7946 4.11 542 9
10 bf16 16384 10240 320 10240 76.4387 15.2220 5.02 542 9
11 bf16 16384 320 10240 320 77.3861 14.7762 5.24 542 9
12 bf16 16384 2560 2560 2560 150.7980 35.3540 4.27 542 9
13 bf16 16384 512 2560 512 30.8884 7.1108 4.34 542 9
14 bf16 16384 128 2560 128 8.3923 1.7241 4.87 542 9
15 bf16 16384 48 2560 96 10.6357 1.1835 8.99 542 9
16 bf16 16384 4 10240 4 40.6301 4.0832 9.95 540 9
17 bf16 16384 1 2560 1 9.9104 1.1005 9.01 541 9
18 f16 8192 12288 2560 12288 308.3724 90.1251 3.42 1156 7
19 f16 8192 10240 2560 10240 250.9099 74.3622 3.37 1156 7
20 f16 8192 6144 2560 6144 140.4356 43.8731 3.20 1156 7
21 f16 8192 2560 6144 2560 150.6988 44.4999 3.39 1156 7
22 f16 8192 2560 640 2560 14.8262 3.7157 3.99 1156 7
23 f16 8192 640 2560 640 13.9774 4.2053 3.32 1156 7
24 f16 8192 512 2560 512 11.6448 3.2112 3.63 1156 7
25 bf16 8192 10240 2560 10240 320.6165 74.0897 4.33 542 9
26 bf16 8192 10240 320 10240 38.5849 7.4783 5.16 542 9
27 bf16 8192 320 10240 320 37.5879 7.2077 5.21 542 9
28 bf16 8192 2560 2560 2560 76.0175 17.7230 4.29 542 9
29 bf16 8192 512 2560 512 15.2948 3.3626 4.55 542 9
30 bf16 8192 128 2560 128 4.1660 0.8738 4.77 542 9
31 bf16 8192 48 2560 96 5.3577 0.5958 8.99 542 9
32 bf16 8192 4 10240 4 20.5606 2.0541 10.01 539 9
33 bf16 8192 1 2560 1 5.0202 0.5513 9.11 541 9
34 f16 4096 12288 2560 12288 154.3027 43.5847 3.54 1156 7
35 f16 4096 10240 2560 10240 125.2170 35.3366 3.54 1156 7
36 f16 4096 6144 2560 6144 76.6512 21.5816 3.55 1156 7
37 f16 4096 2560 6144 2560 72.3956 21.3828 3.39 1156 7
38 f16 4096 2560 640 2560 7.5191 1.9463 3.86 1156 7
39 f16 4096 640 2560 640 7.5407 1.9201 3.93 1156 7
40 f16 4096 512 2560 512 7.6409 1.5795 4.84 1156 7
41 bf16 4096 10240 2560 10240 158.8611 35.4939 4.48 542 9
42 bf16 4096 10240 320 10240 19.6857 3.8810 5.07 542 9
43 bf16 4096 320 10240 320 17.5878 3.6732 4.79 542 9
44 bf16 4096 2560 2560 2560 37.4763 8.6888 4.31 542 9
45 bf16 4096 512 2560 512 7.3683 1.5579 4.73 542 9
46 bf16 4096 128 2560 128 2.0444 0.4077 5.01 542 9
47 bf16 4096 48 2560 96 2.6212 0.3096 8.46 539 9
48 bf16 4096 4 10240 4 9.7732 1.0236 9.55 540 9
49 bf16 4096 1 2560 1 2.5765 0.2698 9.55 540 9
50 f16 2048 12288 2560 12288 75.0208 21.6041 3.47 1156 7
51 f16 2048 10240 2560 10240 66.4348 17.9153 3.71 1156 7
52 f16 2048 6144 2560 6144 38.5592 10.6631 3.62 1156 7
53 f16 2048 2560 6144 2560 36.8025 10.4813 3.51 1156 7
54 f16 2048 2560 640 2560 4.0939 0.8960 4.57 1156 7
55 f16 2048 640 2560 640 4.1720 0.9064 4.60 1156 7
56 f16 2048 512 2560 512 3.6901 0.7531 4.90 1156 7
57 bf16 2048 10240 2560 10240 80.8788 18.5174 4.37 542 9
58 bf16 2048 10240 320 10240 9.9698 1.9474 5.12 542 9
59 bf16 2048 320 10240 320 9.3119 1.8604 5.01 542 9
60 bf16 2048 2560 2560 2560 18.4291 4.0419 4.56 542 9
61 bf16 2048 512 2560 512 3.9841 0.7788 5.12 542 9
62 bf16 2048 128 2560 128 1.2195 0.2385 5.11 542 9
63 bf16 2048 48 2560 96 1.3148 0.1521 8.65 542 9
64 bf16 2048 4 10240 4 4.9064 0.6099 8.05 555 9
65 bf16 2048 1 2560 1 1.2333 0.1394 8.85 539 9
66 f16 1024 12288 2560 12288 38.5003 10.2640 3.75 1156 7
67 f16 1024 10240 2560 10240 31.9227 8.6601 3.69 1156 7
68 f16 1024 6144 2560 6144 18.4690 5.1609 3.58 1156 7
69 f16 1024 2560 6144 2560 17.6803 4.6002 3.84 1156 7
70 f16 1024 2560 640 2560 1.9869 0.4573 4.34 1156 7
71 f16 1024 640 2560 640 2.1281 0.5205 4.09 1156 7
72 f16 1024 512 2560 512 1.6421 0.3834 4.28 1156 7
73 bf16 1024 10240 2560 10240 38.4572 8.4683 4.54 542 9
74 bf16 1024 10240 320 10240 5.5595 1.6651 3.34 542 9
75 bf16 1024 320 10240 320 5.3373 1.0736 4.97 542 9
76 bf16 1024 2560 2560 2560 9.9116 1.8666 5.31 542 9
77 bf16 1024 512 2560 512 2.1414 0.3931 5.45 542 9
78 bf16 1024 128 2560 128 0.6803 0.1084 6.28 542 9
79 bf16 1024 48 2560 96 0.8438 0.0910 9.27 541 9
80 bf16 1024 4 10240 4 2.5770 0.2658 9.70 553 9
81 bf16 1024 1 2560 1 0.7056 0.0826 8.54 541 9
82 f16 512 12288 2560 12288 19.0235 4.9853 3.82 1156 7
83 f16 512 10240 2560 10240 15.7707 4.0130 3.93 1156 7
84 f16 512 6144 2560 6144 8.5797 2.1693 3.95 1156 7
85 f16 512 2560 6144 2560 9.1863 2.0610 4.46 1156 7
86 f16 512 2560 640 2560 0.9946 0.2204 4.51 1156 7
87 f16 512 640 2560 640 1.1312 0.2664 4.25 1156 7
88 f16 512 512 2560 512 0.8627 0.2329 3.70 1156 7
89 bf16 512 10240 2560 10240 18.5991 3.8958 4.77 542 9
90 bf16 512 10240 320 10240 2.3511 0.9714 2.42 542 9
91 bf16 512 320 10240 320 2.5423 0.3841 6.62 542 9
92 bf16 512 2560 2560 2560 5.3614 1.0053 5.33 542 9
93 bf16 512 512 2560 512 1.3167 0.2460 5.35 541 9
94 bf16 512 128 2560 128 0.3764 0.0802 4.69 542 9
95 bf16 512 48 2560 96 0.3619 0.0669 5.41 542 9
96 bf16 512 4 10240 4 1.2848 0.1538 8.35 553 9
97 bf16 512 1 2560 1 0.3443 0.0412 8.36 555 9
98 f16 256 12288 2560 12288 11.0056 2.6006 4.23 1156 7
99 f16 256 10240 2560 10240 9.5589 2.1220 4.50 1156 7
100 f16 256 6144 2560 6144 4.8171 1.3619 3.54 1156 7
101 f16 256 2560 6144 2560 4.4667 1.1821 3.78 1156 7
102 f16 256 2560 640 2560 0.5956 0.1270 4.69 1156 7
103 f16 256 640 2560 640 0.7308 0.1250 5.85 1156 7
104 f16 256 512 2560 512 0.4694 0.1808 2.60 1156 7
105 bf16 256 10240 2560 10240 10.3660 2.1516 4.82 542 9
106 bf16 256 10240 320 10240 1.3209 0.3100 4.26 542 9
107 bf16 256 320 10240 320 1.5608 0.2526 6.18 541 9
108 bf16 256 2560 2560 2560 2.5480 0.5802 4.39 542 9
109 bf16 256 512 2560 512 0.5536 0.1081 5.12 542 9
110 bf16 256 128 2560 128 0.1628 0.0827 1.97 540 9
111 bf16 256 48 2560 96 0.1880 0.0645 2.91 543 9
112 bf16 256 4 10240 4 0.7191 0.1333 5.40 539 9
113 bf16 256 1 2560 1 0.1812 0.0261 6.94 553 9
114 f16 128 12288 2560 12288 5.7421 1.8325 3.13 1154 7
115 f16 128 10240 2560 10240 4.3162 1.5516 2.78 1154 7
116 f16 128 6144 2560 6144 2.3298 0.9226 2.53 1154 7
117 f16 128 2560 6144 2560 2.6517 0.8918 2.97 1156 7
118 f16 128 2560 640 2560 0.2936 0.1385 2.12 1156 7
119 f16 128 640 2560 640 0.3463 0.2238 1.55 1167 7
120 f16 128 512 2560 512 0.2902 0.0985 2.94 1156 7
121 bf16 128 10240 2560 10240 5.5433 1.5391 3.60 540 9
122 bf16 128 10240 320 10240 0.6654 0.1904 3.50 542 9
123 bf16 128 320 10240 320 0.7363 0.2120 3.47 541 9
124 bf16 128 2560 2560 2560 1.3454 0.3869 3.48 542 9
125 bf16 128 512 2560 512 0.2837 0.0999 2.84 541 9
126 bf16 128 128 2560 128 0.1492 0.0485 3.08 552 9
127 bf16 128 48 2560 96 0.1477 0.0235 6.29 543 9
128 bf16 128 4 10240 4 0.4786 0.0630 7.60 543 9
129 bf16 128 1 2560 1 0.1326 0.0205 6.45 553 9
130 f16 64 12288 2560 12288 4.9551 1.2391 4.00 1154 7
131 f16 64 10240 2560 10240 4.0352 0.9967 4.05 1154 7
132 f16 64 6144 2560 6144 2.4523 0.6709 3.66 1154 7
133 f16 64 2560 6144 2560 2.2624 0.6604 3.43 1156 7
134 f16 64 2560 640 2560 0.2160 0.0606 3.57 1156 7
135 f16 64 640 2560 640 0.3042 0.0915 3.33 1155 7
136 f16 64 512 2560 512 0.2539 0.0863 2.94 1154 7
137 bf16 64 10240 2560 10240 4.1701 1.0490 3.98 541 9
138 bf16 64 10240 320 10240 0.3608 0.1476 2.44 541 9
139 bf16 64 320 10240 320 0.6882 0.1945 3.54 539 9
140 bf16 64 2560 2560 2560 0.8595 0.2575 3.34 541 9
141 bf16 64 512 2560 512 0.2072 0.0910 2.28 555 9
142 bf16 64 128 2560 128 0.1414 0.0460 3.08 555 9
143 bf16 64 48 2560 96 0.1501 0.0284 5.28 554 9
144 bf16 64 4 10240 4 0.3768 0.0593 6.35 543 9
145 bf16 64 1 2560 1 0.4442 0.0197 22.55 543 9
@@ -0,0 +1,14 @@
{
"source": "local",
"version": "0.1.40.3",
"archs": [
120
],
"vision": "gpu",
"cuda_dirs": [
"/usr/local/cuda/bin",
"/usr/local/cuda/lib64"
],
"src": "3950c1f221aa6e1b",
"vision_src": "1fb2b3fb797ec402"
}
@@ -0,0 +1,271 @@
# Community benchmark: RTX 5080 in Docker Desktop on Windows (WSL2)
Measured on 2026-10-07 by [xWinIcex](https://github.com/xWinIcex), on a Windows 10 host
using the repository's own Dockerfile and entrypoint — no bare-metal Linux, no
`setup.sh`, no hand-written launch command. Coder IQ1_M, one RTX 5080, two context
limits (131,072 and 65,536) on the same loaded model.
Median decode throughput was **75.7–80.8 tok/s at 4,096–32,768 prompt tokens and 72.2
tok/s at 130,560** with the 131,072-token limit, and **71.5–78.5 tok/s at 4,096–32,768
and 73.8 at 65,024** with the 65,536-token limit. These are synthetic code-explanation
requests with greedy decoding and a 256-token output cap; they do not establish general
answer quality. The main limitation is the host: everything ran inside Docker Desktop's
WSL2 VM on Windows, which changes both the memory the installer sees and the storage path.
This is, as far as we could tell from the existing reports, the first report from that
environment, so three things that are specific to it are written up in
[Notes for users of this environment](#notes-for-users-of-this-environment).
## Hardware and software
- NVIDIA GeForce RTX 5080; 16,303 MiB reported VRAM; power limit 360 W (maximum 380 W).
PCIe link **Gen 5, x8**, while the card reports a maximum width of x16. The engine's own
startup probe measured **28.9 GB/s host-to-device** (`pcie_frac 0.55`, the default).
Clocks were not fixed and no thermal soak was run; the highest GPU temperature observed
was 68 °C and the highest power 273 W.
- AMD Ryzen 9 9950X, 16 cores / 32 threads, AVX-512. The engine chose the AVX-512 path,
48 pool tasks per phase, 15 expert-pool workers plus the host thread on core 0.
- 64 GB installed RAM; the container sees **54.9 GiB** (see the memory note below).
Storage: `C:` XPG MARS 980 PRO 1908 GB NVMe SSD — the WSL2 VHDX, and therefore the
image, the model files and `/data` all live there. The machine's other disk is a
3,726 GB HDD and was not used.
- Windows 10 Pro 26H2 build 26300; WSL 2.7.10.0, kernel 6.18.33.2-2; Docker Desktop
4.84.0 (client and server 29.6.2, buildx v0.35.0-desktop.2); NVIDIA driver 617.14.
- Strata commit `d5ea7133741e67743c0e886bb426c0ce8d69cf6c` ("Version 0.1.40.3"); engine
**0.1.40.3**, `source=local`, CUDA architectures `[120]`, vision compiled for CUDA —
[BUILD.json](BUILD.json).
- CUDA 13.0.48 (`nvcc` V13.0.48); GCC 13.3.0; Python 3.12.3. Installed Python packages:
[python-packages.txt](python-packages.txt).
- The whole environment is in [environment.txt](environment.txt), including the exact
`docker run` lines, the WSL2 memory setting and the base image digest.
## Model and configuration
Model: `ISTA-DASLab/Qwen3.8-Flash-Next-GSQ-RCO-Coder-GGUF` at the revision the installer
pins, `5348543e0147355ac9cbcb031184a3546350988e` (2026-09-29):
- `IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00001-of-00002.gguf` — 29,608,446,496 B
- `IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00002-of-00002.gguf` — 28,800,138,432 B
- `mmproj-Qwen3.8-Flash-Next-BF16.gguf` — 907,543,008 B
All three local SHA-256 hashes matched the repository's published LFS oids
([sha256.txt](sha256.txt), [model-provenance.json](model-provenance.json)). The MTP draft
layer was fetched from `Qwen/Qwen3.8-Flash-Next` by the installer (31 tensors, 5.214 GB,
per-tensor hashes in [mtp-manifest.json](mtp-manifest.json)); the full BF16 shards were not
downloaded. The unmodified installer prepared the pack (`/data/packs/coder-iq1_m`, 1.4 GB
on disk) and the Q2_0 MTP experts.
Both configurations were produced by the image's own entrypoint from the same
`strata-data` volume; only `CONTEXT` and `REINSTALL` differ between them. The recorded
engine configuration is [config-131072.json](config-131072.json) and
[config-65536.json](config-65536.json):
```text
# 131,072-token limit
docker run -d --name strata --gpus all --network strata-net \
-p 127.0.0.1:8080:8080 --ulimit memlock=-1 --stop-timeout 60 \
-v strata-data:/data \
-e FAMILY=coder -e MODEL=IQ1_M -e CONTEXT=131072 -e VISION=cpu -e GPU=0 strata
# 65,536-token limit, same volume
... -e CONTEXT=65536 -e VISION=cpu -e GPU=0 -e REINSTALL=1 strata
```
Settings both configurations share: `--expert-cache auto`, `--prefill auto`, `--kv int8`,
`--spec 4 --spec-min-p 0.5`, MTP on, `--vram-reserve-mib 700`, low-RAM mode off, the
experimental speed projection off, no calibration, no custom expert profile, temperature 0,
`reasoning_effort: none`, 256 generated tokens per speed run. Vision is on with the encoder
on the **CPU** (`VISION=cpu`, 16 threads, 300 image tokens), which is the first thing worth
noting: nothing about this configuration was tuned by hand.
What differs, from the engine's startup log:
| | 131,072 limit | 65,536 limit |
| --- | --- | --- |
| Expert cache | 3,554 slots, 6.78 GiB VRAM | 4,060 slots, 7.73 GiB VRAM |
| Free VRAM at load | 152 MiB | 178 MiB |
| KV | INT8 | INT8, streaming off, resident in VRAM |
| Prefill chunk | 8,192 tokens, borrows 2,172 cache slots | 8,192 tokens |
At 131,072 the engine warned about its own configuration:
```text
strata serve: 152 MiB of VRAM free with everything loaded - LOW: requests may stall;
add --vram-reserve-mib 1060 to the config's args (or lower --max-context)
```
So a 16 GB card at a 128K context leaves almost nothing spare, and the engine says so
itself. Nothing below failed because of it: no request was refused for VRAM and none
stalled, at either limit, including the 130,560-token prompt.
## Method
The benchmark is the script from
[bench/results/2026-09-30-community-rtx-5090/benchmark.py](../2026-09-30-community-rtx-5090/benchmark.py),
attached here as [benchmark.py](benchmark.py), **unchanged except for four defaults**
(`--root /opt/strata`, `--pack /data/packs/coder-iq1_m`, `--url http://127.0.0.1:8080`,
`--out /data/bench`), so the numbers stay comparable with that report. It builds
deterministic synthetic Python functions, puts a different nonce near the start of every
request so no prompt prefix can be reused, counts the complete rendered chat prompt with
Strata's own tokenizer, and verifies its count against the engine afterwards.
One warm-up request was excluded. Three runs were executed at each length, serially, in
increasing-length order, on the same loaded engine. Every measured request read its entire
prompt: **zero reused tokens** in all 33 runs (`reused: 0`, `prompt_read == prompt_total`).
Loading time is not included. Both context limits were measured in their own session on a
freshly loaded model; see the limitations.
Streaming TTFT is measured from immediately before the HTTP request until the first
non-empty text delta, ignoring empty role chunks; with reasoning off that delta is answer
text. Total latency ends at the end of the stream; both include HTTP and front-end
tokenization on loopback. Prompt throughput is fresh tokens divided by the engine's
`prompt_ms`; decode throughput is `engine_generated / decode_ms`. Per-run records — the
engine's timings and draft statistics, the client's TTFT and total latency, the output
text and a SHA-256 of each request body — are in `data-131072/results.json` and
`data-65536/results.json`. The request bodies themselves are not committed because
`benchmark.py` rebuilds them deterministically; compare the recorded `request_sha256`
after a re-run to confirm it reproduced the same prompt.
Memory was sampled once per second from the engine's own `/metrics` by
[monitor.py](monitor.py) and summarised by
[summarize-telemetry.py](summarize-telemetry.py). Every memory number in this report comes
from the engine's view, not from `nvidia-smi`, which inside a container reports the whole
GPU and not the container's share.
## Results
Each cell is the median **[minimum–maximum]** of three runs. Every request generated 256
tokens and stopped at the output limit; there were no failed or cancelled speed requests.
**Context limit 131,072** (`data-131072/`, session of 2026-10-07 ~22:22):
| Prompt tokens | Reused | Prompt tok/s | Decode tok/s | TTFT seconds | Total seconds |
| ---: | ---: | ---: | ---: | ---: | ---: |
| 4,096 | 0 | 2,252.8 [2,138.8–2,267.5] | 75.7 [72.6–77.9] | 1.849 [1.839–1.948] | 5.306 [5.100–5.350] |
| 8,192 | 0 | 3,009.2 [2,998.9–3,063.1] | 79.9 [78.9–80.8] | 2.772 [2.706–2.780] | 5.929 [5.913–5.940] |
| 16,384 | 0 | 3,197.3 [3,184.2–3,304.9] | 79.1 [77.6–81.0] | 5.166 [5.002–5.189] | 8.402 [8.136–8.442] |
| 32,768 | 0 | 3,304.3 [3,271.8–3,311.9] | 80.8 [75.6–82.4] | 9.981 [9.960–10.081] | 13.223 [13.057–13.316] |
| 65,536 | 0 | 3,299.4 [3,269.5–3,310.9] | 73.8 [73.8–77.5] | 19.958 [19.884–20.137] | 23.400 [23.166–23.584] |
| 130,560 | 0 | 3,076.5 [2,942.9–3,200.6] | 72.2 [71.0–76.1] | 42.612 [40.959–44.532] | 46.131 [44.292–48.114] |
**Context limit 65,536** (`data-65536/`, session of 2026-10-07 ~22:37):
| Prompt tokens | Reused | Prompt tok/s | Decode tok/s | TTFT seconds | Total seconds |
| ---: | ---: | ---: | ---: | ---: | ---: |
| 4,096 | 0 | 2,194.1 [2,113.8–2,221.6] | 73.1 [72.1–78.2] | 1.904 [1.882–1.970] | 5.379 [5.127–5.495] |
| 8,192 | 0 | 2,781.6 [2,760.3–2,804.9] | 76.4 [75.2–76.8] | 2.981 [2.963–3.010] | 6.332 [6.288–6.336] |
| 16,384 | 0 | 3,001.3 [2,997.2–3,016.8] | 78.5 [68.4–78.6] | 5.523 [5.480–5.539] | 8.741 [8.707–9.241] |
| 32,768 | 0 | 3,034.9 [3,016.7–3,084.7] | 71.5 [70.3–73.6] | 10.873 [10.702–10.945] | 14.419 [14.148–14.550] |
| 65,024 | 0 | 3,027.7 [3,003.6–3,197.0] | 73.8 [73.7–79.9] | 21.582 [20.441–21.762] | 25.028 [23.619–25.203] |
The two limits are **not** in the expected order: at every shared prompt length the
131,072-token configuration measured equal or slightly faster (decode 80.8 vs 71.5 tok/s at
32,768; prefill 3,304 vs 3,035 tok/s), even though it has the *smaller* expert cache
(3,554 vs 4,060 experts, 6.78 vs 7.73 GiB of VRAM) and only 152 MiB of free VRAM. Decode
ranges at 32,768 do not overlap (128K: 75.6–82.4; 64K: 70.3–73.6), so this is not obviously
run-to-run noise, but with one session per configuration and no interleaving we did **not**
isolate the cause and do not claim that a smaller context is slower in general. It is
reported because it is what was measured, and because the cache sizes alone do not predict it.
Decode expert-cache hit rates were 81.0–87.0% across the 33 measured runs (`hit_rate` in
`results.json`); draft acceptance was 140–162 of the 196–237 drafts offered.
### Memory
From the one-second samples (peaks and ranges; a sampled peak can miss a shorter spike):
| | 131,072 limit | 65,536 limit |
| --- | ---: | ---: |
| GPU memory used, peak (of 15.92 GiB) | 15.82 GiB | 15.74 GiB |
| Host RAM used, peak (of 54.92 GiB) | 29.77 GiB | 29.49 GiB |
| Free VRAM as the engine reports it | 152 MiB | 178 MiB |
| GPU temperature, peak | 68 °C | 65 °C |
| GPU power, peak (limit 360 W) | 267 W | 268 W |
| Disk read, peak | 230 MB/s (recall run) / 3.7 MB/s (speed run) | 3.6 MB/s |
`gpu_mem_used` comes from the engine's `/metrics`, so it is the process-plus-context
allocation rather than the card's total. The 230 MB/s peak was recorded during the 128K
recall run: on very long prompts the experts that the prompt path's borrowed cache slots do
not cover are read from the SSD, which is the behaviour the engine documents.
## Correctness
The repository's unchanged `tools/needle_bench.py` found **all nine needles** on the
131,072-token configuration — depths 10%, 50% and 90% at lengths 32k, 64k and 128k. Actual
prompt lengths were 32,343–32,344, 62,625–62,627 and 125,919–125,920 tokens; every answer
matched the expected code word. On the 65,536-token configuration the same command found
**6 of 6** (32k and 64k; 128k skipped because the server's context is 65,536), and the skip
is recorded in the output rather than silently dropped. See
[data-131072/needles.json](data-131072/needles.json) and
[data-65536/needles.json](data-65536/needles.json).
The vision path was checked with [image-check.py](image-check.py), which draws a code word
with Pillow and sends it as an OpenAI `image_url` data URL. With the encoder on the CPU the
model answered `K7QX-4291` for the drawn `K7QX-4291` in 1.1 s at 261 prompt tokens
([data-131072/image-check.json](data-131072/image-check.json),
[image-check.png](data-131072/image-check.png)). The encoder falling back to the CPU is
visible in the log as `ggml_cuda_init: failed to initialize CUDA` followed by
`strata-vision: on the CPU, 16 threads`, which is what `VISION=cpu` asks for.
## Notes for users of this environment
1. **Docker Desktop's default RAM makes the installer choose the low-RAM mode.** With no
`%UserProfile%\.wslconfig`, Docker Desktop caps the WSL2 VM at 50% of host RAM, so the
container saw ~31 GB of the host's 64 GB. `setup.py` reads RAM from `/proc/meminfo`, so it
did not error — it selected the low-RAM mode ("the GPU holds ~38% of IQ1_M's experts, the
other ~15 GB stay in RAM, read once from a copy in the model folder"). A 32 GB PC is a
documented low-RAM case, but on a 64 GB PC it is silent and unwanted. Adding
`[wsl2]` / `memory=56GB` ([wslconfig.txt](wslconfig.txt)) and restarting
(`wsl --shutdown`) gives the container 54.9 GiB and the normal mode. Both measured runs
used the normal mode.
2. **A request needs 8 tokens of headroom.** `prompt + max_tokens + 8 ≤ max_context`, and
the engine does not truncate. A 65,280-token prompt with `max_tokens: 256` on the
65,536-token limit was refused with HTTP 400: *"prompt (65280 tokens) + max tokens (256)
exceeds the context (65536); requests are never truncated. Send a smaller max_tokens (at
most 248 here)"*. [probe-request.py](probe-request.py) reproduces it. The largest prompt
measured here therefore leaves 512 tokens: 130,560 of 131,072 and 65,024 of 65,536.
3. **The port is published on `127.0.0.1` only**, so no API key was set
(`"api_key": false` in `/health`). Other containers reach the same server over a
user-defined Docker network at `http://strata:8080`; nothing was exposed to the LAN.
## Limitations
- **One session per configuration.** The warm-up state differs between them, and the
128K-vs-64K comparison in the results is a comparison of two sessions, not of two
interleaved settings. The engine's own log shows CUDA-graph capture
(`strata verify: capturing the N-token window`) happening during the first requests of a
session, which is one candidate explanation for the ordering; it was not tested. Treat the
difference as an observation to reproduce, not a result.
- **One machine, one quantization, one GPU, one synthetic workload.** Long output, sampled
decoding, thinking, multi-request concurrency (`parallel`), tool use and a sustained
thermal run were not evaluated. The needle and image checks measure recall and reading on
those specific inputs, not general model quality.
- **The PCIe link ran at x8 of a possible x16**, and the card reports a maximum width of
x16. The engine measured 28.9 GB/s host-to-device; the RTX 5090 report on a Gen5 x16 link
measured 50.0 GB/s. Whether the narrower link costs anything here was not tested — the
link is a property of this machine's slot wiring, so absolute numbers may move on a host
that runs the card at x16.
- **Windows and WSL2 are between Strata and the hardware.** File I/O and page-locked memory
go through the WSL2 VM; `--ulimit memlock=-1` was passed and the engine reported
`MAP_HUGETLB unavailable` with transparent huge pages requested instead. Numbers from a
bare-metal Linux host with the same card are not guaranteed to match.
- **Timings include the whole client path** (HTTP, front-end tokenization, loopback) and are
measured at the client, not inside the engine.
- The 131,072-token configuration logged the engine's own VRAM warning quoted above. It did
not cause a failure in any measured run, but it is a real margin of 152 MiB and a reason
to prefer `--vram-reserve-mib 1060` (or a smaller context) for unattended use.
- One telemetry file, `data-131072/telemetry-speed-overlapped.jsonl`, was written by two
samplers that overlapped for about eleven minutes (819 of 820 lines parse; the timestamps
contain one discontinuity). Only peaks and ranges are taken from it. The clean runs are
`data-131072/telemetry-checks.jsonl` and `data-65536/telemetry-speed.jsonl`.
## Files
| File | What it is |
| --- | --- |
| `benchmark.py`, `monitor.py`, `summarize-telemetry.py`, `image-check.py`, `probe-request.py` | the scripts, runnable as documented above |
| `data-131072/`, `data-65536/` | `results.json` (per-run engine timings, draft statistics, output text, request hashes) and `summary.json`, the telemetry and its memory summary, `needles.json`, the image check, and the engine's status at startup |
| `config-131072.json`, `config-65536.json`, `engine-131072.log`, `engine-65536.log` | the recorded configuration and the unabridged engine log of each session |
| `environment.txt`, `python-packages.txt`, `wslconfig.txt` | host and container environment |
| `model-provenance.json`, `sha256.txt`, `mtp-manifest.json`, `mtp-inventory.md` | what was downloaded and its hashes |
| `BUILD.json` | the engine the image compiled |
@@ -0,0 +1,10 @@
# Trimmed files
Ported from PR #1460 for 0.1.41. Raw dumps over 100 KB and binary files were left out to keep the repository small; the README, summaries, configs and per-run results are unchanged. The files below were in the original PR.
2 files, 0.3 MB:
| file | bytes | why |
|---|---:|---|
| `data-131072/image-check.png` | 13,784 | binary |
| `data-131072/telemetry-speed-overlapped.jsonl` | 272,970 | raw dump over 100 KB |
@@ -0,0 +1,141 @@
#!/usr/bin/env python3
"""Serial, fresh-prompt Strata benchmark. Run inside its prepared environment.
This is the script from bench/results/2026-09-30-community-rtx-5090/benchmark.py,
unchanged except for the defaults, so the numbers stay comparable with that
report. Only --root, --pack, --url and --out defaults were repointed at the
Docker image layout (/opt/strata, /data/packs/coder-iq1_m, port 8080).
"""
import argparse
import hashlib
import json
import statistics
import sys
import time
import urllib.request
from pathlib import Path
def get(url):
with urllib.request.urlopen(url, timeout=30) as response:
return json.load(response)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--root", type=Path, default=Path("/opt/strata"))
parser.add_argument("--pack", type=Path, default=Path("/data/packs/coder-iq1_m"))
parser.add_argument("--url", default="http://127.0.0.1:8080")
parser.add_argument("--out", type=Path, default=Path("/data/bench"))
parser.add_argument("--targets", default="4096,32768,128000")
parser.add_argument("--runs", type=int, default=3)
args = parser.parse_args()
args.out.mkdir(parents=True, exist_ok=True)
sys.path[:0] = [str(args.root), str(args.root / "tools")]
from strata_tokenizer import Tokenizer
from serve.frontend import ChatTemplate, openai_to_messages
directory = args.pack / "tokenizer"
vocab = json.loads((directory / "vocab.json").read_text(encoding="utf-8"))
tokens = [None] * len(vocab)
for token, number in vocab.items():
tokens[number] = token
tokenizer = Tokenizer(tokens, (directory / "merges.txt").read_text(encoding="utf-8").splitlines(),
json.loads((directory / "token_type.json").read_text(encoding="utf-8")))
template = ChatTemplate(directory / "chat_template.jinja")
initial = get(args.url + "/v1/status")
(args.out / "initial-status.json").write_text(json.dumps(initial, indent=2) + "\n")
rows = []
def request(content, maximum=256):
return {"model": "strata", "messages": [{"role": "user", "content": content}],
"temperature": 0, "reasoning_effort": "none", "max_tokens": maximum,
"stream": True, "stream_options": {"include_usage": True}}
def count(req):
messages, tools, kwargs = openai_to_messages(req)
return len(tokenizer.encode(template.render(messages, tools, **kwargs), parse_special=True))
def perform(label, req, expected=None):
body = json.dumps(req).encode()
(args.out / (label + "-request.json")).write_bytes(body + b"\n")
print("start", label, "tokens", expected, flush=True)
chunks, texts, first, finish = [], [], None, None
started = time.perf_counter()
wire = urllib.request.Request(args.url + "/v1/chat/completions", data=body,
headers={"Content-Type": "application/json"})
with urllib.request.urlopen(wire, timeout=1800) as response:
for line in response:
if not line.startswith(b"data: "):
continue
payload = line[6:].strip()
if payload == b"[DONE]":
break
chunk = json.loads(payload)
chunks.append(chunk)
for choice in chunk.get("choices", []):
delta = choice.get("delta", {})
text = (delta.get("content") or "") + (delta.get("reasoning_content") or "")
if text:
first = first if first is not None else time.perf_counter() - started
texts.append(text)
finish = choice.get("finish_reason") or finish
elapsed = time.perf_counter() - started
metrics = get(args.url + "/metrics")
engine = metrics["requests"][0]
usage = next((chunk["usage"] for chunk in reversed(chunks) if "usage" in chunk), {})
row = {"label": label, "expected_prompt_tokens": expected,
"request_sha256": hashlib.sha256(body).hexdigest(),
"client_ttft_s": first, "client_elapsed_s": elapsed, "finish_reason": finish,
"usage": usage, "engine": engine, "text": "".join(texts)}
if expected is not None and engine["prompt_tokens"] != expected:
raise RuntimeError(f"token count mismatch: {expected} vs {engine['prompt_tokens']}")
if not texts:
raise RuntimeError(f"no text received for {label}")
(args.out / (label + "-raw.json")).write_text(json.dumps({"chunks": chunks, "row": row}, indent=2) + "\n")
rows.append(row)
(args.out / "results.json").write_text(json.dumps(rows, indent=2) + "\n")
print("done", label, json.dumps({"ttft_s": first, "elapsed_s": elapsed, "engine": engine}), flush=True)
return row
perform("warmup", request("Reply with exactly the word READY.", 16))
# Each nonce occurs before the filler so previous long prompts cannot be reused.
filler = "\n".join(f"def task_{i:05d}(value: int) -> int: return (value * {(i % 97) + 1} + {i}) % 100003"
for i in range(12000))
ending = ("\n\nWrite a detailed explanation of the code above. Discuss deterministic integer transforms, "
"modulo arithmetic, testing, naming, complexity, and maintainability. Write at least 600 words.")
for target in map(int, args.targets.split(",")):
for run in range(1, args.runs + 1):
prefix = f"Benchmark nonce: series-{target}-trial-{run}.\nReview this synthetic Python module:\n"
lo, hi = 0, len(filler)
while lo < hi:
middle = (lo + hi + 1) // 2
if count(request(prefix + filler[:middle] + ending)) <= target:
lo = middle
else:
hi = middle - 1
req = request(prefix + filler[:lo] + ending)
actual = count(req)
if actual < target - 20 or actual > target:
raise RuntimeError(f"could not construct target {target}: {actual}")
perform(f"tokens-{target}-run-{run}", req, actual)
measured = [row for row in rows if row["label"] != "warmup"]
groups = {}
for target in map(int, args.targets.split(",")):
subset = [r for r in measured if r["label"].startswith(f"tokens-{target}-")]
values = {
"prompt_tokens": [r["engine"]["prompt_tokens"] for r in subset],
"cached_tokens": [r["engine"].get("reused", 0) for r in subset],
"output_tokens": [r["engine"]["engine_generated"] for r in subset],
"client_ttft_s": [r["client_ttft_s"] for r in subset],
"client_elapsed_s": [r["client_elapsed_s"] for r in subset],
"prefill_tok_s": [(r["engine"]["prompt_tokens"] - (r["engine"].get("reused") or 0)) / (r["engine"]["prompt_ms"] / 1000) for r in subset],
"decode_tok_s": [r["engine"]["engine_generated"] / (r["engine"]["decode_ms"] / 1000) for r in subset],
}
groups[str(target)] = {key: {"median": statistics.median(v), "min": min(v), "max": max(v)}
for key, v in values.items()}
(args.out / "summary.json").write_text(json.dumps(groups, indent=2) + "\n")
print("summary", json.dumps(groups), flush=True)
if __name__ == "__main__":
main()
@@ -0,0 +1,50 @@
{
"exe": "/opt/strata/engine/strata",
"args": [
"--pack",
"/data/packs/coder-iq1_m",
"--native",
"/data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00001-of-00002.gguf",
"--ple-gguf",
"/data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00002-of-00002.gguf",
"--expert-profile",
"/opt/strata/data/expert-profile-coder.bin",
"--expert-cache",
"auto",
"--prefill",
"auto",
"--spec",
"4",
"--spec-min-p",
"0.5",
"--mtp",
"/data/mtp/rt",
"--max-context",
"131072",
"--kv",
"int8",
"--vision",
"--vram-reserve-mib",
"700"
],
"cwd": "/opt/strata",
"tokenizer": "/data/packs/coder-iq1_m/tokenizer",
"model_name": "qwen3.8-flash-next-coder-iq1_m",
"log": "/opt/strata/strata-coder-iq1_m.log",
"lib_dirs": [
"/usr/local/cuda/bin",
"/usr/local/cuda/lib64"
],
"port": 8080,
"gpu": 0,
"gpus_asked": true,
"host": "0.0.0.0",
"vision": {
"exe": "/opt/strata/engine/strata-vision",
"mmproj": "/data/models/mmproj-Qwen3.8-Flash-Next-BF16.gguf",
"model": "/data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00001-of-00002.gguf",
"gpu": false,
"max_tokens": 300,
"threads": 16
}
}
@@ -0,0 +1,50 @@
{
"exe": "/opt/strata/engine/strata",
"args": [
"--pack",
"/data/packs/coder-iq1_m",
"--native",
"/data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00001-of-00002.gguf",
"--ple-gguf",
"/data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00002-of-00002.gguf",
"--expert-profile",
"/opt/strata/data/expert-profile-coder.bin",
"--expert-cache",
"auto",
"--prefill",
"auto",
"--spec",
"4",
"--spec-min-p",
"0.5",
"--mtp",
"/data/mtp/rt",
"--max-context",
"65536",
"--kv",
"int8",
"--vision",
"--vram-reserve-mib",
"700"
],
"cwd": "/opt/strata",
"tokenizer": "/data/packs/coder-iq1_m/tokenizer",
"model_name": "qwen3.8-flash-next-coder-iq1_m",
"log": "/opt/strata/strata-coder-iq1_m.log",
"lib_dirs": [
"/usr/local/cuda/bin",
"/usr/local/cuda/lib64"
],
"port": 8080,
"gpu": 0,
"gpus_asked": true,
"host": "0.0.0.0",
"vision": {
"exe": "/opt/strata/engine/strata-vision",
"mmproj": "/data/models/mmproj-Qwen3.8-Flash-Next-BF16.gguf",
"model": "/data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00001-of-00002.gguf",
"gpu": false,
"max_tokens": 300,
"threads": 16
}
}
@@ -0,0 +1 @@
{"service": "strata", "model": "qwen3.8-flash-next-coder-iq1_m", "loaded": true, "auto_load": true, "structured_output": {"formats": ["json_object", "json_schema"], "method": "prompt_and_validate", "constrained_decoding": false, "stream_buffered": true}, "engine": "0.1.40.3", "started": 1791413029, "uptime_s": 424, "cache_max_tokens": 131072, "context": {"native": 131072, "max_positions": 131072}, "concurrency": {"serving": 1, "requested": 1}, "dialects": ["/v1/chat/completions", "/v1/messages", "/v1/responses"], "vision": {"enabled": true, "available": true, "error": null}, "activity": {"requests": 10, "in_flight": 0, "last_request_at": 1791413265}, "last_timings": {"cache_n": 0, "prompt_n": 261, "prompt_ms": 920.3, "prompt_per_token_ms": 3.526, "prompt_per_second": 283.6, "predicted_n": 10, "predicted_ms": 152.9, "predicted_per_token_ms": 15.29, "predicted_per_second": 65.4, "draft_n": 9, "draft_n_accepted": 7, "at": 1791413265}, "vram": {"elastic": false}, "machine": {"at": 1791413454, "gpu": {"name": "NVIDIA GeForce RTX 5080", "used_mib": 16131.0, "total_mib": 16303.0, "util_pct": 5, "temp_c": 42, "power_w": 29.933}, "ram": {"used_gib": 29.0, "total_gib": 54.9}}}
@@ -0,0 +1,37 @@
{
"expected": "K7QX-4291",
"answer": "K7QX-4291",
"found": true,
"usage": {
"prompt_tokens": 261,
"completion_tokens": 10,
"total_tokens": 271,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791413264.0592318,
"duration_s": 1.1,
"finish": "stop",
"prompt_tokens": 261,
"reused": 0,
"output_tokens": 10,
"prompt_total": 261,
"prompt_read": 261,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 10,
"prompt_ms": 920.3,
"decode_ms": 152.9,
"decode_tok_s": 65.4,
"hit_rate": 0.716,
"pcie_share": 0.144,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 9,
"drafts_accepted": 7
}
}
@@ -0,0 +1,74 @@
{
"service": "strata",
"model": "qwen3.8-flash-next-coder-iq1_m",
"loaded": true,
"auto_load": true,
"structured_output": {
"formats": [
"json_object",
"json_schema"
],
"method": "prompt_and_validate",
"constrained_decoding": false,
"stream_buffered": true
},
"engine": "0.1.40.3",
"started": 1791410816,
"uptime_s": 916,
"cache_max_tokens": 131072,
"context": {
"native": 131072,
"max_positions": 131072
},
"concurrency": {
"serving": 1,
"requested": 1
},
"dialects": [
"/v1/chat/completions",
"/v1/messages",
"/v1/responses"
],
"vision": {
"enabled": true,
"available": true,
"error": null
},
"activity": {
"requests": 26,
"in_flight": 0,
"last_request_at": 1791411718
},
"last_timings": {
"cache_n": 0,
"prompt_n": 128000,
"prompt_ms": 41130.9,
"prompt_per_token_ms": 0.321,
"prompt_per_second": 3112.0,
"predicted_n": 256,
"predicted_ms": 3454.1,
"predicted_per_token_ms": 13.493,
"predicted_per_second": 74.1,
"draft_n": 217,
"draft_n_accepted": 152,
"at": 1791411718
},
"vram": {
"elastic": false
},
"machine": {
"at": 1791411733,
"gpu": {
"name": "NVIDIA GeForce RTX 5080",
"used_mib": 16124.0,
"total_mib": 16303.0,
"util_pct": 2,
"temp_c": 45,
"power_w": 30.103
},
"ram": {
"used_gib": 29.5,
"total_gib": 54.9
}
}
}
@@ -0,0 +1,77 @@
{
"source": "telemetry-checks.jsonl",
"samples": 217,
"unparseable_lines": 0,
"sampled_seconds": 216.5,
"note": "Each sample is one GET /metrics, so the values are the engine's own view. Sampled peaks can miss shorter spikes between samples.",
"fields": {
"gpu_mem_used": {
"median": 16873041920,
"min": 16814977024,
"max": 16954896384,
"max_gib": 15.79,
"median_gib": 15.71
},
"gpu_mem_total": {
"median": 17094934528,
"min": 17094934528,
"max": 17094934528,
"max_gib": 15.92,
"median_gib": 15.92
},
"gpu_util": {
"median": 99,
"min": 0,
"max": 100
},
"gpu_temp_c": {
"median": 62,
"min": 41,
"max": 68
},
"gpu_power_w": {
"median": 243.997,
"min": 27.019,
"max": 273.323
},
"gpu_pcie_gen": {
"median": 5,
"min": 5,
"max": 5
},
"gpu_pcie_width": {
"median": 8,
"min": 8,
"max": 8
},
"ram_used": {
"median": 31151665152,
"min": 30438551552,
"max": 31736569856,
"max_gib": 29.56,
"median_gib": 29.01
},
"ram_total": {
"median": 58965274624,
"min": 58965274624,
"max": 58965274624,
"max_gib": 54.92,
"median_gib": 54.92
},
"disk_read_mb": {
"median": 0.7253774717579398,
"min": 0.0,
"max": 230.18278498204805
},
"vram_free_mib": {
"median": 179,
"min": 179,
"max": 179
},
"expert_cache_mib": {
"median": 6938,
"min": 6938,
"max": 6938
}
}
}
@@ -0,0 +1,77 @@
{
"source": "telemetry-speed-overlapped.jsonl",
"samples": 819,
"unparseable_lines": 1,
"sampled_seconds": 807.6,
"note": "Each sample is one GET /metrics, so the values are the engine's own view. Sampled peaks can miss shorter spikes between samples.",
"fields": {
"gpu_mem_used": {
"median": 16914481152,
"min": 16740126720,
"max": 16987488256,
"max_gib": 15.82,
"median_gib": 15.75
},
"gpu_mem_total": {
"median": 17094934528,
"min": 17094934528,
"max": 17094934528,
"max_gib": 15.92,
"median_gib": 15.92
},
"gpu_util": {
"median": 2,
"min": 0,
"max": 100
},
"gpu_temp_c": {
"median": 42,
"min": 40,
"max": 68
},
"gpu_power_w": {
"median": 31.431,
"min": 25.858,
"max": 266.969
},
"gpu_pcie_gen": {
"median": 5,
"min": 5,
"max": 5
},
"gpu_pcie_width": {
"median": 8,
"min": 8,
"max": 8
},
"ram_used": {
"median": 31699738624,
"min": 31169019904,
"max": 31968956416,
"max_gib": 29.77,
"median_gib": 29.52
},
"ram_total": {
"median": 58965274624,
"min": 58965274624,
"max": 58965274624,
"max_gib": 54.92,
"median_gib": 54.92
},
"disk_read_mb": {
"median": 0.03742834552960401,
"min": 0.0,
"max": 3.7305775669681127
},
"vram_free_mib": {
"median": 152,
"min": 152,
"max": 152
},
"expert_cache_mib": {
"median": 6938,
"min": 6938,
"max": 6938
}
}
}
@@ -0,0 +1,83 @@
[
{
"length": "32k",
"depth": 10,
"prompt_tokens": 32343,
"seconds": 13.9,
"found": true,
"word": "meadow-copper-504",
"answer": "meadow-copper-504"
},
{
"length": "32k",
"depth": 50,
"prompt_tokens": 32343,
"seconds": 11.0,
"found": true,
"word": "falcon-quartz-940",
"answer": "falcon-quartz-940"
},
{
"length": "32k",
"depth": 90,
"prompt_tokens": 32344,
"seconds": 5.4,
"found": true,
"word": "willow-cobalt-696",
"answer": "willow-cobalt-696"
},
{
"length": "64k",
"depth": 10,
"prompt_tokens": 62627,
"seconds": 20.1,
"found": true,
"word": "falcon-saffron-138",
"answer": "falcon-saffron-138"
},
{
"length": "64k",
"depth": 50,
"prompt_tokens": 62625,
"seconds": 19.9,
"found": true,
"word": "quartz-tundra-528",
"answer": "quartz-tundra-528"
},
{
"length": "64k",
"depth": 90,
"prompt_tokens": 62625,
"seconds": 15.4,
"found": true,
"word": "quartz-glacier-192",
"answer": "quartz-glacier-192"
},
{
"length": "128k",
"depth": 10,
"prompt_tokens": 125919,
"seconds": 42.7,
"found": true,
"word": "tundra-falcon-946",
"answer": "tundra-falcon-946"
},
{
"length": "128k",
"depth": 50,
"prompt_tokens": 125919,
"seconds": 41.6,
"found": true,
"word": "willow-glacier-745",
"answer": "willow-glacier-745"
},
{
"length": "128k",
"depth": 90,
"prompt_tokens": 125920,
"seconds": 39.0,
"found": true,
"word": "falcon-juniper-150",
"answer": "falcon-juniper-150"
}
]
@@ -0,0 +1,781 @@
[
{
"label": "warmup",
"expected_prompt_tokens": null,
"request_sha256": "b63e57873441a996a529b246a66cf12de70a7c671777f99329354d5c195f788f",
"client_ttft_s": 0.5249328660001993,
"client_elapsed_s": 0.5863964729996951,
"finish_reason": "stop",
"usage": {
"prompt_tokens": 19,
"completion_tokens": 2,
"total_tokens": 21,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411733.0571463,
"duration_s": 0.6,
"finish": "stop",
"prompt_tokens": 19,
"reused": 0,
"output_tokens": 2,
"prompt_total": 19,
"prompt_read": 19,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 2,
"prompt_ms": 493.1,
"decode_ms": 90.7,
"decode_tok_s": 22.1,
"hit_rate": 0.328,
"pcie_share": 0.373,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 3,
"drafts_accepted": 3
},
"text": "READY"
},
{
"label": "tokens-4096-run-1",
"expected_prompt_tokens": 4096,
"request_sha256": "5d94c652067354bbe72930d2bdad3886564f08cf2546b32411af02d33ad3ce05",
"client_ttft_s": 1.948032590999901,
"client_elapsed_s": 5.306051635999211,
"finish_reason": "length",
"usage": {
"prompt_tokens": 4096,
"completion_tokens": 256,
"total_tokens": 4352,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411734.0900733,
"duration_s": 5.3,
"finish": "length",
"prompt_tokens": 4096,
"reused": 0,
"output_tokens": 256,
"prompt_total": 4096,
"prompt_read": 4096,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 1915.1,
"decode_ms": 3382.3,
"decode_tok_s": 75.7,
"hit_rate": 0.829,
"pcie_share": 0.117,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 223,
"drafts_accepted": 160
},
"text": "The provided Python module consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a deterministic integer transformation. Each function takes a single integer argument `value` and returns an integer result computed using a linear congruential formula modulo a fixed prime number, 100003. The general form of the transformation for a given task index `n` is:\n\n```python\nresult = (value * multiplier + addend) % 100003\n```\n\nwhere `multiplier` and `addend` are derived from the task index. For most tasks (0 through 96), the multiplier is `n + 1` and the addend is `n`. For example, `task_00000` uses multiplier 1 and addend 0, while `task_00096` uses multiplier 97 and addend 96. However, starting from `task_00097`, the pattern changes: the multiplier resets to 1, and the addend continues to increment. Thus, `task_00097` uses multiplier 1 and addend 97, `task_00"
},
{
"label": "tokens-4096-run-2",
"expected_prompt_tokens": 4096,
"request_sha256": "8da8a04e70e4d916f6630729082bdfb9d6ebbb47117aad60bc0541bce198a213",
"client_ttft_s": 1.8391832759998579,
"client_elapsed_s": 5.099977033999494,
"finish_reason": "length",
"usage": {
"prompt_tokens": 4096,
"completion_tokens": 256,
"total_tokens": 4352,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411739.8388693,
"duration_s": 5.1,
"finish": "length",
"prompt_tokens": 4096,
"reused": 0,
"output_tokens": 256,
"prompt_total": 4096,
"prompt_read": 4096,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 1806.4,
"decode_ms": 3285.0,
"decode_tok_s": 77.9,
"hit_rate": 0.835,
"pcie_share": 0.11,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 206,
"drafts_accepted": 154
},
"text": "The provided Python module consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a deterministic integer transformation. Each function takes a single integer argument `value` and returns an integer result computed using a linear transformation followed by a modulo operation. The general form of each function is:\n\n```python\ndef task_XXXXX(value: int) -> int:\n return (value * A + B) % 100003\n```\n\nwhere `A` and `B` are constants specific to each function. The modulus `100003` is a prime number, which is significant in modular arithmetic because it ensures that the multiplicative group modulo 100003 is cyclic and that every non-zero element has a multiplicative inverse. This property is often exploited in cryptographic algorithms, hash functions, and pseudo-random number generators.\n\n### Deterministic Integer Transforms\n\nEach function implements a linear congruential transformation, a common technique in number theory and computer science. The transformation `value * A + B` is an affine transformation over the integers. When combined with the modulo operation, it becomes a function from the finite field (or ring) of integers modulo 10"
},
{
"label": "tokens-4096-run-3",
"expected_prompt_tokens": 4096,
"request_sha256": "946079edb58e764050805886156dc8f877cc29e1ca8d01c84e9a1e7917d49492",
"client_ttft_s": 1.848908844000107,
"client_elapsed_s": 5.350014886999816,
"finish_reason": "length",
"usage": {
"prompt_tokens": 4096,
"completion_tokens": 256,
"total_tokens": 4352,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411745.4247267,
"duration_s": 5.3,
"finish": "length",
"prompt_tokens": 4096,
"reused": 0,
"output_tokens": 256,
"prompt_total": 4096,
"prompt_read": 4096,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 1818.2,
"decode_ms": 3524.2,
"decode_tok_s": 72.6,
"hit_rate": 0.832,
"pcie_share": 0.11,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 217,
"drafts_accepted": 144
},
"text": "The provided Python module presents a series of deterministic integer transforms, each encapsulated within a uniquely named function. These functions, labeled from `task_00000` to `task_00112` (and potentially beyond), follow a consistent mathematical pattern: they take an integer input, apply a linear transformation of the form `(value * multiplier + offset) % modulus`, and return the result. This structure serves as a synthetic benchmark for evaluating code generation, pattern recognition, and algorithmic consistency in automated systems.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of each function is a linear congruential transformation. For any given task index `n`, the function computes `(value * (n + 1) + n) % 100003`. The modulus used is 100003, which is a prime number. This choice of modulus is significant because it ensures that the multiplicative inverse exists for all non-zero multipliers, making the transformation bijective (one-to-one) over the finite field defined by the modulus. This property is critical in cryptographic contexts, hash functions, and pseudo-random number generators, where invertibility and uniform distribution are desired.\n\nThe multiplier increases linearly"
},
{
"label": "tokens-8192-run-1",
"expected_prompt_tokens": 8192,
"request_sha256": "d7c1089e1b773cee0815d4df507e627783b01c7c00f1cdd157255e48007b05a4",
"client_ttft_s": 2.7800030770004014,
"client_elapsed_s": 5.9396775520008305,
"finish_reason": "length",
"usage": {
"prompt_tokens": 8192,
"completion_tokens": 256,
"total_tokens": 8448,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411751.2961645,
"duration_s": 5.9,
"finish": "length",
"prompt_tokens": 8192,
"reused": 0,
"output_tokens": 256,
"prompt_total": 8192,
"prompt_read": 8192,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 2722.3,
"decode_ms": 3203.8,
"decode_tok_s": 79.9,
"hit_rate": 0.838,
"pcie_share": 0.106,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 215,
"drafts_accepted": 151
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system under a specific nonce (`series-8192-trial-1`). The code consists of a series of function definitions, each named `task_XXXXX`, where `XXXXX` is a zero-padded integer index. Each function accepts a single integer argument `value` and returns an integer result computed via a linear transformation followed by a modulo operation.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of each function is the expression:\n```python\n(value * multiplier + offset) % 100003\n```\nThis is a classic linear congruential generator (LCG) step, often used in pseudo-random number generation or cryptographic hashing contexts, though here it serves as a deterministic arithmetic transform. The modulus `100003` is a prime number, which ensures that the multiplicative group modulo 100003 is cyclic and that multiplication by any non-zero integer less than the modulus is invertible. This property is crucial for ensuring that the transform is bijective (one-to-one) within the range `[0, 100002]`, provided the multiplier is not"
},
{
"label": "tokens-8192-run-2",
"expected_prompt_tokens": 8192,
"request_sha256": "18d77efc0066d46b148403e2aadb0df295679df8d609c8ff9123810cfd66f05b",
"client_ttft_s": 2.7723507400005474,
"client_elapsed_s": 5.912902312999904,
"finish_reason": "length",
"usage": {
"prompt_tokens": 8192,
"completion_tokens": 256,
"total_tokens": 8448,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411757.735891,
"duration_s": 5.9,
"finish": "length",
"prompt_tokens": 8192,
"reused": 0,
"output_tokens": 256,
"prompt_total": 8192,
"prompt_read": 8192,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 2731.7,
"decode_ms": 3169.4,
"decode_tok_s": 80.8,
"hit_rate": 0.84,
"pcie_share": 0.104,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 214,
"drafts_accepted": 153
},
"text": "The provided Python module consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a deterministic integer transformation. Each function takes a single integer argument `value` and returns an integer result computed using a linear transformation followed by a modulo operation. The general form of each function is:\n\n```python\ndef task_XXXXX(value: int) -> int:\n return (value * A + B) % 100003\n```\n\nwhere `A` and `B` are constants specific to each function. The modulus `100003` is a prime number, which is significant in modular arithmetic because it ensures that the multiplicative group modulo 100003 is cyclic and that every non-zero element has a multiplicative inverse. This property is often exploited in cryptographic algorithms, hash functions, and pseudo-random number generators.\n\n### Deterministic Integer Transforms\n\nEach function implements a linear congruential transformation, a common technique in number theory and computer science. The transformation `f(x) = (a*x + b) mod m` is a linear congruential generator (LCG) when used iteratively, but here it is applied once per function call."
},
{
"label": "tokens-8192-run-3",
"expected_prompt_tokens": 8192,
"request_sha256": "a8d8bb0e3287c41a120a4b8bd4387da0cf48973166300ed78e536e8eb7c85998",
"client_ttft_s": 2.706295907999447,
"client_elapsed_s": 5.929079806000118,
"finish_reason": "length",
"usage": {
"prompt_tokens": 8192,
"completion_tokens": 256,
"total_tokens": 8448,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411764.1446838,
"duration_s": 5.9,
"finish": "length",
"prompt_tokens": 8192,
"reused": 0,
"output_tokens": 256,
"prompt_total": 8192,
"prompt_read": 8192,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 2674.4,
"decode_ms": 3243.3,
"decode_tok_s": 78.9,
"hit_rate": 0.841,
"pcie_share": 0.107,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 211,
"drafts_accepted": 144
},
"text": "The provided Python module consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a deterministic integer transformation. Each function takes a single integer argument `value` and returns an integer result computed using a linear congruential formula modulo a fixed prime number, 100003. This structure is typical of benchmarking suites, cryptographic primitives, or hash function implementations where deterministic, fast, and collision-resistant (or at least well-distributed) outputs are required.\n\n### Deterministic Integer Transforms\n\nEach function implements a linear transformation of the form:\n\n```\nf(value) = (value * a + b) % m\n```\n\nwhere `a` is the multiplier, `b` is the additive constant, and `m = 100003` is the modulus. The modulus 100003 is a prime number, which ensures that the multiplicative group modulo `m` is cyclic and that multiplication by any non-zero `a` (where `1 \u2264 a < m`) is invertible. This property is critical for ensuring that the transformation is bijective (one-to-one) when `a` is coprime to `m`, which it always is since"
},
{
"label": "tokens-16384-run-1",
"expected_prompt_tokens": 16384,
"request_sha256": "6189656df3e39c2820cb59a0561adb1207c2f570424ca0aee304356f5e386de4",
"client_ttft_s": 5.002397057999588,
"client_elapsed_s": 8.135695478999878,
"finish_reason": "length",
"usage": {
"prompt_tokens": 16384,
"completion_tokens": 256,
"total_tokens": 16640,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411770.714519,
"duration_s": 8.1,
"finish": "length",
"prompt_tokens": 16384,
"reused": 0,
"output_tokens": 256,
"prompt_total": 16384,
"prompt_read": 16384,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 4957.5,
"decode_ms": 3159.2,
"decode_tok_s": 81.0,
"hit_rate": 0.812,
"pcie_share": 0.124,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 208,
"drafts_accepted": 162
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system's ability to handle a large number of deterministic integer transforms. The code consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a linear transformation on an input integer and return the result modulo a large prime number.\n\n### Deterministic Integer Transforms\n\nAt the core of each function is a linear transformation of the form $f(x) = (ax + b) \\pmod m$. In this specific module, the modulus $m$ is consistently set to `100003`, which is a prime number. The coefficients $a$ and $b$ vary for each function. For example, `task_00000` implements $f(x) = (1x + 0) \\pmod{100003}$, while `task_00001` implements $f(x) = (2x + 1) \\pmod{100003}$.\n\nThese transforms are deterministic, meaning that for a given input `value`, the output will always be the same. This property is crucial for benchmarking, as it allows for"
},
{
"label": "tokens-16384-run-2",
"expected_prompt_tokens": 16384,
"request_sha256": "d77a390c17eb10efc0a7a0117c5c9ed46fa24b12d8c1fe005e2253f0472dfd15",
"client_ttft_s": 5.188755529000446,
"client_elapsed_s": 8.401537347999692,
"finish_reason": "length",
"usage": {
"prompt_tokens": 16384,
"completion_tokens": 256,
"total_tokens": 16640,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411779.4517615,
"duration_s": 8.4,
"finish": "length",
"prompt_tokens": 16384,
"reused": 0,
"output_tokens": 256,
"prompt_total": 16384,
"prompt_read": 16384,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 5145.4,
"decode_ms": 3237.0,
"decode_tok_s": 79.1,
"hit_rate": 0.81,
"pcie_share": 0.126,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 213,
"drafts_accepted": 158
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system's ability to handle a large number of deterministic integer transforms. The code consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a linear transformation on an input integer and return the result modulo a large prime number.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of each function is a linear transformation of the form:\n`result = (value * multiplier + constant) % MODULUS`\n\nHere, `MODULUS` is consistently set to `100003`. This number is a prime, which is a common choice in competitive programming and cryptographic contexts to ensure that the modulo operation behaves predictably and avoids certain edge cases associated with composite moduli (such as zero divisors).\n\nThe `multiplier` and `constant` vary for each function. For example:\n- `task_00000`: `(value * 1 + 0) % 100003`\n- `task_00001`: `(value * 2 + 1) % 100003`\n- `task"
},
{
"label": "tokens-16384-run-3",
"expected_prompt_tokens": 16384,
"request_sha256": "7664e759d262ff5e9dbbef7e55d09267244629ba14eff0c871954813fd5e36b2",
"client_ttft_s": 5.166459971999757,
"client_elapsed_s": 8.442003465999733,
"finish_reason": "length",
"usage": {
"prompt_tokens": 16384,
"completion_tokens": 256,
"total_tokens": 16640,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411788.501625,
"duration_s": 8.4,
"finish": "length",
"prompt_tokens": 16384,
"reused": 0,
"output_tokens": 256,
"prompt_total": 16384,
"prompt_read": 16384,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 5124.3,
"decode_ms": 3297.7,
"decode_tok_s": 77.6,
"hit_rate": 0.826,
"pcie_share": 0.115,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 217,
"drafts_accepted": 152
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system's ability to handle a large number of deterministic integer transforms. The code consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a linear transformation on an input integer and return the result modulo a large prime number.\n\n### Deterministic Integer Transforms\n\nAt the core of each function is a linear transformation of the form $f(x) = (ax + b) \\pmod m$. In this specific module, the modulus $m$ is consistently set to `100003`, which is a prime number. The coefficients $a$ and $b$ vary for each function. For example, `task_00000` implements $f(x) = (1x + 0) \\pmod{100003}$, which is effectively an identity function within the modular space. As the task index increases, the coefficients change in a predictable, albeit somewhat irregular, pattern.\n\nFor instance, `task_00001` uses $a=2, b=1$, while `task_00002` uses $a=3, b"
},
{
"label": "tokens-32768-run-1",
"expected_prompt_tokens": 32768,
"request_sha256": "e37cfc2ab9867d91130927440df24a57255a736b8d0d829d07d828e22e3de572",
"client_ttft_s": 9.959809752999718,
"client_elapsed_s": 13.316424910999558,
"finish_reason": "length",
"usage": {
"prompt_tokens": 32768,
"completion_tokens": 256,
"total_tokens": 33024,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411797.7873251,
"duration_s": 13.3,
"finish": "length",
"prompt_tokens": 32768,
"reused": 0,
"output_tokens": 256,
"prompt_total": 32768,
"prompt_read": 32768,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 9894.0,
"decode_ms": 3386.0,
"decode_tok_s": 75.6,
"hit_rate": 0.822,
"pcie_share": 0.116,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 223,
"drafts_accepted": 155
},
"text": "This Python module presents a highly repetitive, synthetic collection of functions that serve as a benchmark for deterministic integer transforms. The code consists of a series of functions named `task_00000` through `task_00888` (and potentially beyond), each performing a specific linear transformation on an input integer `value` and returning the result modulo 100003.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of each function is a linear congruential generator (LCG) style operation: `(value * multiplier + addend) % 100003`. The modulus, 100003, is a prime number. This choice of modulus is significant because it ensures that the multiplicative group of integers modulo 100003 is cyclic, which is a desirable property in cryptographic and pseudo-random number generation contexts. However, in this specific benchmark context, the modulus likely serves to keep the output within a fixed range (0 to 100002) and to prevent integer overflow issues in languages with fixed-width integers, although Python handles arbitrary-precision integers natively.\n\nThe transformation is deterministic: for a given `value`, `multiplier"
},
{
"label": "tokens-32768-run-2",
"expected_prompt_tokens": 32768,
"request_sha256": "ed2dfaa11aecad9f4563f33bb5f5d4b8704486508700b8fa572722cc1225ee26",
"client_ttft_s": 9.981056601000091,
"client_elapsed_s": 13.057004774000234,
"finish_reason": "length",
"usage": {
"prompt_tokens": 32768,
"completion_tokens": 256,
"total_tokens": 33024,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411811.9387543,
"duration_s": 13.0,
"finish": "length",
"prompt_tokens": 32768,
"reused": 0,
"output_tokens": 256,
"prompt_total": 32768,
"prompt_read": 32768,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 9916.7,
"decode_ms": 3105.4,
"decode_tok_s": 82.4,
"hit_rate": 0.838,
"pcie_share": 0.108,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 220,
"drafts_accepted": 159
},
"text": "The provided Python module consists of a series of 889 distinct functions, named sequentially from `task_00000` to `task_00888`. Each function accepts a single integer argument `value` and returns an integer result. The core logic of every function is identical in structure: it performs a linear transformation on the input value and then applies a modulo operation. Specifically, the formula used is `(value * multiplier + offset) % 100003`.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nThe fundamental operation here is an affine transformation over a finite field. The modulus, 100003, is a prime number. This choice of modulus is significant because it ensures that the set of integers modulo 100003 forms a finite field ($\\mathbb{Z}_{100003}$). In this context, the multiplication by the `multiplier` and the addition of the `offset` are well-defined operations that preserve the properties of the field.\n\nThe `multiplier` and `offset` parameters vary for each function. By analyzing the pattern, we can deduce how these parameters are generated. For the first 97 functions (`"
},
{
"label": "tokens-32768-run-3",
"expected_prompt_tokens": 32768,
"request_sha256": "2a3c7342622e80c3cd8b37e062f0a2f64640c119ece8cccbf168639041eac079",
"client_ttft_s": 10.081181062999349,
"client_elapsed_s": 13.222919904999799,
"finish_reason": "length",
"usage": {
"prompt_tokens": 32768,
"completion_tokens": 256,
"total_tokens": 33024,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411825.8339658,
"duration_s": 13.2,
"finish": "length",
"prompt_tokens": 32768,
"reused": 0,
"output_tokens": 256,
"prompt_total": 32768,
"prompt_read": 32768,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 10015.4,
"decode_ms": 3169.3,
"decode_tok_s": 80.8,
"hit_rate": 0.833,
"pcie_share": 0.111,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 218,
"drafts_accepted": 158
},
"text": "This synthetic Python module presents a highly repetitive, programmatic structure that serves as a benchmark for evaluating code generation, static analysis, and execution performance. The module consists of a series of functions named `task_00000` through `task_00888` (and potentially beyond, as the snippet cuts off). Each function accepts a single integer argument `value` and returns an integer. The core logic of every function is identical in structure: `(value * multiplier + offset) % 100003`.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nThe fundamental operation here is a linear congruential transform. For any given function `task_NNNNN`, the output is determined by the formula $f(x) = (ax + b) \\pmod m$, where $m = 100003$. The modulus $100003$ is a prime number, which is significant in number theory. In modular arithmetic, if $m$ is prime, then for any $a$ not divisible by $m$, the multiplication by $a$ is a bijection (a one-to-one mapping) over the set of integers modulo $m$. This means that for a fixed $"
},
{
"label": "tokens-65536-run-1",
"expected_prompt_tokens": 65536,
"request_sha256": "25316c2967282170e5cc177a38061dcf7f1a6ba80a5cd30cb1e19ccdf493d0e4",
"client_ttft_s": 19.958402783000565,
"client_elapsed_s": 23.399771757000053,
"finish_reason": "length",
"usage": {
"prompt_tokens": 65536,
"completion_tokens": 256,
"total_tokens": 65792,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411840.452925,
"duration_s": 23.3,
"finish": "length",
"prompt_tokens": 65536,
"reused": 0,
"output_tokens": 256,
"prompt_total": 65536,
"prompt_read": 65536,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 19863.0,
"decode_ms": 3468.7,
"decode_tok_s": 73.8,
"hit_rate": 0.819,
"pcie_share": 0.114,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 211,
"drafts_accepted": 140
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance, parsing, and execution capabilities of a Python interpreter or compiler. It consists of a massive sequence of function definitions, each named `task_XXXXX`, where `XXXXX` is a zero-padded integer index. Each function accepts a single integer argument `value` and returns a transformed integer result based on a specific linear formula modulo a large prime number.\n\n### 1. Structure and Naming Convention\n\nThe code follows a strict, repetitive pattern. The function names are generated sequentially from `task_00000` to `task_01756` (and potentially beyond, as the snippet cuts off). This naming convention suggests that these functions are intended to be accessed programmatically, perhaps via `globals()` or a dictionary mapping, rather than being called directly by name in source code. The zero-padding ensures lexicographical sorting matches numerical sorting, which is a common practice in benchmarking suites to ensure deterministic ordering of tasks.\n\n### 2. The Mathematical Transform\n\nEach function implements a linear congruential generator (LCG) step, a fundamental component in pseudo-random number generation. The general form of the transformation is:\n\n$$ f(x) = (a \\cdot"
},
{
"label": "tokens-65536-run-2",
"expected_prompt_tokens": 65536,
"request_sha256": "d492de6fde472d71750a772ba927abc0eec86b4dbe139e4214736ff0d4e187ca",
"client_ttft_s": 19.884095792000153,
"client_elapsed_s": 23.165817502999744,
"finish_reason": "length",
"usage": {
"prompt_tokens": 65536,
"completion_tokens": 256,
"total_tokens": 65792,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411865.2116637,
"duration_s": 23.1,
"finish": "length",
"prompt_tokens": 65536,
"reused": 0,
"output_tokens": 256,
"prompt_total": 65536,
"prompt_read": 65536,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 19794.1,
"decode_ms": 3303.6,
"decode_tok_s": 77.5,
"hit_rate": 0.84,
"pcie_share": 0.107,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 208,
"drafts_accepted": 144
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system's ability to handle a large volume of deterministic integer transforms. The code consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a linear transformation on an input integer and return the result modulo a large prime number.\n\n### 1. The Mathematical Transform\n\nEach function in the module follows the general form:\n```python\ndef task_XXXXX(value: int) -> int:\n return (value * A + B) % M\n```\nWhere:\n- `value` is the input integer.\n- `A` is a multiplier coefficient.\n- `B` is an additive constant.\n- `M` is the modulus, which is consistently set to `100003` throughout the module.\n\nThis is a classic **Linear Congruential Transform**. In cryptography and random number generation, such transforms are often used to map inputs to a specific range. Here, the modulus `100003` is a prime number, which ensures that the mapping is bijective (one-to-one) if the multiplier `A` is not a multiple of the modulus. Since"
},
{
"label": "tokens-65536-run-3",
"expected_prompt_tokens": 65536,
"request_sha256": "9ea8bee58d0212ad333fbb482dfa9a527429e6dff5b82556fe232c5710e1d0eb",
"client_ttft_s": 20.136737270000594,
"client_elapsed_s": 23.58410194699991,
"finish_reason": "length",
"usage": {
"prompt_tokens": 65536,
"completion_tokens": 256,
"total_tokens": 65792,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411889.8030987,
"duration_s": 23.5,
"finish": "length",
"prompt_tokens": 65536,
"reused": 0,
"output_tokens": 256,
"prompt_total": 65536,
"prompt_read": 65536,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 20044.5,
"decode_ms": 3470.3,
"decode_tok_s": 73.8,
"hit_rate": 0.819,
"pcie_share": 0.118,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 224,
"drafts_accepted": 148
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system's ability to handle a large volume of deterministic integer transforms. The code consists of a series of functions, named sequentially from `task_00000` to `task_01756`, each performing a specific linear transformation on an input integer `value`.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of each function is the expression:\n```python\nreturn (value * multiplier + offset) % 100003\n```\nThis is a classic linear congruential generator (LCG) step, often used in pseudo-random number generation or cryptographic hashing. Here, `multiplier` and `offset` are constants specific to each function. The modulus `100003` is a prime number, which ensures that the arithmetic operations remain within a finite field, preventing integer overflow issues in languages with fixed-width integers (though Python handles arbitrary precision integers, the modulo operation keeps the result bounded).\n\nThe pattern of `multiplier` and `offset` follows a specific sequence. For the first 97 functions (`task_00000` to `task_0009"
},
{
"label": "tokens-130560-run-1",
"expected_prompt_tokens": 130560,
"request_sha256": "dcd27003bf5679a041fcfe905be53f9154f2744d48825a682742adb98b81d7af",
"client_ttft_s": 40.95935630199983,
"client_elapsed_s": 44.29171037299966,
"finish_reason": "length",
"usage": {
"prompt_tokens": 130560,
"completion_tokens": 256,
"total_tokens": 130816,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411915.8942049,
"duration_s": 44.2,
"finish": "length",
"prompt_tokens": 130560,
"reused": 0,
"output_tokens": 256,
"prompt_total": 130560,
"prompt_read": 130560,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 40792.2,
"decode_ms": 3363.1,
"decode_tok_s": 76.1,
"hit_rate": 0.831,
"pcie_share": 0.11,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 222,
"drafts_accepted": 153
},
"text": "This Python module represents a synthetic benchmark designed to test the performance and correctness of integer arithmetic operations, specifically focusing on linear transformations combined with modular arithmetic. The code consists of a series of functions, named `task_00000` through `task_03471`, each performing a specific calculation on an input integer `value`.\n\n### 1. Structure and Naming Convention\n\nThe module follows a strict naming convention: `task_XXXXX`, where `XXXXX` is a zero-padded integer representing the task index. This structure suggests that the module is generated programmatically rather than written by hand. The functions are uniform in signature: they accept a single integer argument `value` and return an integer.\n\nThe core logic of each function is identical in form:\n```python\nreturn (value * A + B) % 100003\n```\nHere, `A` is the multiplier and `B` is the additive constant. The modulus is fixed at `100003`, which is a prime number. This choice of modulus is significant because it ensures that the transformation is a bijection (a one-to-one mapping) over the set of integers modulo 100003, provided"
},
{
"label": "tokens-130560-run-2",
"expected_prompt_tokens": 130560,
"request_sha256": "5c1a31ccffe3ac430d48f601e169a4df476c608299c78adf93d67203d1544869",
"client_ttft_s": 42.611677615999724,
"client_elapsed_s": 46.131310132999715,
"finish_reason": "length",
"usage": {
"prompt_tokens": 130560,
"completion_tokens": 256,
"total_tokens": 130816,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791411962.6502512,
"duration_s": 46.0,
"finish": "length",
"prompt_tokens": 130560,
"reused": 0,
"output_tokens": 256,
"prompt_total": 130560,
"prompt_read": 130560,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 42437.3,
"decode_ms": 3546.7,
"decode_tok_s": 72.2,
"hit_rate": 0.818,
"pcie_share": 0.12,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 196,
"drafts_accepted": 155
},
"text": "This Python module represents a synthetic benchmark designed to test the performance and correctness of a system's ability to handle a large volume of deterministic integer transforms. The code consists of a series of functions, named `task_00000` through `task_03471`, each performing a specific linear transformation on an input integer `value`.\n\n### 1. Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of every function in this module is the formula:\n`return (value * multiplier + offset) % 100003`\n\nThis is a classic **Linear Congruential Generator (LCG)** step, often used in pseudo-random number generation or hashing. Here, however, it is used as a deterministic transform.\n\n* **Multiplier (`a`)**: The multiplier cycles through values from 1 to 97. For example, `task_00000` uses `1`, `task_00001` uses `2`, and so on. When the multiplier reaches 97, it resets to 1 for the next block of tasks (e.g., `task_00097` uses `1` again).\n* **Offset"
},
{
"label": "tokens-130560-run-3",
"expected_prompt_tokens": 130560,
"request_sha256": "a8be8223c37849935ee4b10630929afbbf791bfc6893b0ed72956926481ed8b3",
"client_ttft_s": 44.531807120999474,
"client_elapsed_s": 48.11411538900029,
"finish_reason": "length",
"usage": {
"prompt_tokens": 130560,
"completion_tokens": 256,
"total_tokens": 130816,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412011.4226975,
"duration_s": 48.0,
"finish": "length",
"prompt_tokens": 130560,
"reused": 0,
"output_tokens": 256,
"prompt_total": 130560,
"prompt_read": 130560,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 44364.2,
"decode_ms": 3607.2,
"decode_tok_s": 71.0,
"hit_rate": 0.834,
"pcie_share": 0.111,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 216,
"drafts_accepted": 146
},
"text": "This Python module represents a synthetic benchmark designed to test the performance and correctness of integer arithmetic operations, specifically focusing on linear congruential transforms and modular arithmetic. The code consists of a series of functions, each named `task_XXXXX`, where `XXXXX` is a zero-padded integer index. Each function accepts a single integer argument `value` and returns a transformed integer result.\n\n### 1. Deterministic Integer Transforms\n\nThe core logic of every function in this module follows the pattern:\n```python\nreturn (value * A + B) % M\n```\nWhere:\n- `A` is the multiplier.\n- `B` is the additive constant.\n- `M` is the modulus, which is consistently `100003` across all functions.\n\nThis structure is known as a **Linear Congruential Generator (LCG)** step or a simple affine transformation. The transformation is deterministic, meaning that for a given input `value`, the output will always be the same. This property is crucial for benchmarking, as it allows for predictable verification of results without relying on random number generation, which can introduce non-determinism and complicate testing.\n\n### 2. Modulo Arithmetic and the Mod"
}
]
@@ -0,0 +1,224 @@
{
"4096": {
"prompt_tokens": {
"median": 4096,
"min": 4096,
"max": 4096
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 1.848908844000107,
"min": 1.8391832759998579,
"max": 1.948032590999901
},
"client_elapsed_s": {
"median": 5.306051635999211,
"min": 5.099977033999494,
"max": 5.350014886999816
},
"prefill_tok_s": {
"median": 2252.7774722252775,
"min": 2138.791708004804,
"max": 2267.493356953056
},
"decode_tok_s": {
"median": 75.68814120568842,
"min": 72.6405992849441,
"max": 77.92998477929984
}
},
"8192": {
"prompt_tokens": {
"median": 8192,
"min": 8192,
"max": 8192
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 2.7723507400005474,
"min": 2.706295907999447,
"max": 2.7800030770004014
},
"client_elapsed_s": {
"median": 5.929079806000118,
"min": 5.912902312999904,
"max": 5.9396775520008305
},
"prefill_tok_s": {
"median": 3009.2201447305583,
"min": 2998.86517553172,
"max": 3063.1169608136406
},
"decode_tok_s": {
"median": 79.90511267869404,
"min": 78.93195202417292,
"max": 80.77238594055657
}
},
"16384": {
"prompt_tokens": {
"median": 16384,
"min": 16384,
"max": 16384
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 5.166459971999757,
"min": 5.002397057999588,
"max": 5.188755529000446
},
"client_elapsed_s": {
"median": 8.401537347999692,
"min": 8.135695478999878,
"max": 8.442003465999733
},
"prefill_tok_s": {
"median": 3197.3147551860743,
"min": 3184.203366113422,
"max": 3304.891578416541
},
"decode_tok_s": {
"median": 79.08557306147668,
"min": 77.62986323801438,
"max": 81.03317295517853
}
},
"32768": {
"prompt_tokens": {
"median": 32768,
"min": 32768,
"max": 32768
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 9.981056601000091,
"min": 9.959809752999718,
"max": 10.081181062999349
},
"client_elapsed_s": {
"median": 13.222919904999799,
"min": 13.057004774000234,
"max": 13.316424910999558
},
"prefill_tok_s": {
"median": 3304.325027478899,
"min": 3271.7614873095436,
"max": 3311.9062057812816
},
"decode_tok_s": {
"median": 80.77493452812924,
"min": 75.60543414057885,
"max": 82.437045147163
}
},
"65536": {
"prompt_tokens": {
"median": 65536,
"min": 65536,
"max": 65536
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 19.958402783000565,
"min": 19.884095792000153,
"max": 20.136737270000594
},
"client_elapsed_s": {
"median": 23.399771757000053,
"min": 23.165817502999744,
"max": 23.58410194699991
},
"prefill_tok_s": {
"median": 3299.4008961385493,
"min": 3269.525306193719,
"max": 3310.8855669113523
},
"decode_tok_s": {
"median": 73.80286562689193,
"min": 73.76883842895425,
"max": 77.49122169754207
}
},
"130560": {
"prompt_tokens": {
"median": 130560,
"min": 130560,
"max": 130560
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 42.611677615999724,
"min": 40.95935630199983,
"max": 44.531807120999474
},
"client_elapsed_s": {
"median": 46.131310132999715,
"min": 44.29171037299966,
"max": 48.11411538900029
},
"prefill_tok_s": {
"median": 3076.5387995937535,
"min": 2942.913430198223,
"max": 3200.6118816832636
},
"decode_tok_s": {
"median": 72.17977274649674,
"min": 70.96917276557996,
"max": 76.12024620142131
}
}
}
@@ -0,0 +1,217 @@
{"t": 0.017, "gpu_mem_used": 16815042560, "gpu_mem_total": 17094934528, "gpu_util": 1, "gpu_temp_c": 41, "gpu_power_w": 27.019, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30438551552, "ram_total": 58965274624, "disk_read_mb": 0.0, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "idle", "tok_s": null}
{"t": 1.019, "gpu_mem_used": 16814977024, "gpu_mem_total": 17094934528, "gpu_util": 1, "gpu_temp_c": 41, "gpu_power_w": 27.299, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30462009344, "ram_total": 58965274624, "disk_read_mb": 0.2996025931789391, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 2.02, "gpu_mem_used": 16831492096, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 42, "gpu_power_w": 49.905, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30594981888, "ram_total": 58965274624, "disk_read_mb": 109.72984932897151, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 3.022, "gpu_mem_used": 16848138240, "gpu_mem_total": 17094934528, "gpu_util": 1, "gpu_temp_c": 42, "gpu_power_w": 52.597, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30745890816, "ram_total": 58965274624, "disk_read_mb": 188.88464190990533, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 4.026, "gpu_mem_used": 16848138240, "gpu_mem_total": 17094934528, "gpu_util": 65, "gpu_temp_c": 42, "gpu_power_w": 64.221, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30749855744, "ram_total": 58965274624, "disk_read_mb": 140.06924082934827, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 5.028, "gpu_mem_used": 16864391168, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 52, "gpu_power_w": 217.522, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30749855744, "ram_total": 58965274624, "disk_read_mb": 119.31515821503935, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 6.03, "gpu_mem_used": 16864391168, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 56, "gpu_power_w": 250.913, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30750351360, "ram_total": 58965274624, "disk_read_mb": 98.88778044606319, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 7.032, "gpu_mem_used": 16863342592, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 256.761, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30750855168, "ram_total": 58965274624, "disk_read_mb": 162.16047808677487, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 8.034, "gpu_mem_used": 16862031872, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 258.788, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30750863360, "ram_total": 58965274624, "disk_read_mb": 91.39657064842169, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 9.036, "gpu_mem_used": 16879071232, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 52, "gpu_power_w": 172.215, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30875926528, "ram_total": 58965274624, "disk_read_mb": 171.0976369912945, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 10.037, "gpu_mem_used": 16879595520, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 214.692, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30876340224, "ram_total": 58965274624, "disk_read_mb": 101.79867569479369, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 11.04, "gpu_mem_used": 16880709632, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 59, "gpu_power_w": 244.308, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30876598272, "ram_total": 58965274624, "disk_read_mb": 0.03747261998888904, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 12.042, "gpu_mem_used": 16881512448, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 244.175, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30876598272, "ram_total": 58965274624, "disk_read_mb": 0.04120686659167193, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 13.044, "gpu_mem_used": 16881250304, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 240.283, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30876573696, "ram_total": 58965274624, "disk_read_mb": 0.037453294822397454, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 14.045, "gpu_mem_used": 16879988736, "gpu_mem_total": 17094934528, "gpu_util": 42, "gpu_temp_c": 47, "gpu_power_w": 88.264, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31048269824, "ram_total": 58965274624, "disk_read_mb": 0.6140410293677401, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 15.047, "gpu_mem_used": 16887132160, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 53, "gpu_power_w": 166.294, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30829420544, "ram_total": 58965274624, "disk_read_mb": 0.6219776359697909, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 16.049, "gpu_mem_used": 16887328768, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 237.181, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30829547520, "ram_total": 58965274624, "disk_read_mb": 0.04120877927360106, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 17.052, "gpu_mem_used": 16887328768, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 237.181, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30829547520, "ram_total": 58965274624, "disk_read_mb": 0.04120877927360106, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 18.055, "gpu_mem_used": 16886018048, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 246.96, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30829547520, "ram_total": 58965274624, "disk_read_mb": 0.7253774717579398, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 19.056, "gpu_mem_used": 16886018048, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 245.544, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30829547520, "ram_total": 58965274624, "disk_read_mb": 0.04118689297701588, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 20.058, "gpu_mem_used": 16891473920, "gpu_mem_total": 17094934528, "gpu_util": 77, "gpu_temp_c": 60, "gpu_power_w": 241.343, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30920253440, "ram_total": 58965274624, "disk_read_mb": 0.037488061891911555, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 21.06, "gpu_mem_used": 16891473920, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 173.227, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30945034240, "ram_total": 58965274624, "disk_read_mb": 0.1086306713557297, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 22.062, "gpu_mem_used": 16891604992, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 233.771, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30945034240, "ram_total": 58965274624, "disk_read_mb": 0.03746320333254218, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 23.063, "gpu_mem_used": 16890032128, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 60, "gpu_power_w": 237.451, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30945034240, "ram_total": 58965274624, "disk_read_mb": 0.04122358736521202, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 24.065, "gpu_mem_used": 16889835520, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 244.452, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30945017856, "ram_total": 58965274624, "disk_read_mb": 0.03746398287595978, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 25.067, "gpu_mem_used": 16891604992, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 56, "gpu_power_w": 234.145, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30946353152, "ram_total": 58965274624, "disk_read_mb": 0.041165866757301744, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 26.069, "gpu_mem_used": 16893898752, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 51, "gpu_power_w": 121.101, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30953795584, "ram_total": 58965274624, "disk_read_mb": 1.0112819589015825, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 27.071, "gpu_mem_used": 16894095360, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 60, "gpu_power_w": 227.128, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30953058304, "ram_total": 58965274624, "disk_read_mb": 0.04121843961639479, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 28.073, "gpu_mem_used": 16881430528, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 252.134, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30953058304, "ram_total": 58965274624, "disk_read_mb": 0.037455050053608455, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 29.075, "gpu_mem_used": 16881430528, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 253.616, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30952890368, "ram_total": 58965274624, "disk_read_mb": 0.04117430288873978, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 30.077, "gpu_mem_used": 16881430528, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 247.093, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30951600128, "ram_total": 58965274624, "disk_read_mb": 0.03748974317786897, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 31.079, "gpu_mem_used": 16872386560, "gpu_mem_total": 17094934528, "gpu_util": 42, "gpu_temp_c": 50, "gpu_power_w": 149.309, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30844379136, "ram_total": 58965274624, "disk_read_mb": 1.3490448656956744, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 32.081, "gpu_mem_used": 16872189952, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 56, "gpu_power_w": 204.229, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30844243968, "ram_total": 58965274624, "disk_read_mb": 0.03747189150716412, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 33.082, "gpu_mem_used": 16872189952, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 63, "gpu_power_w": 249.238, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30832005120, "ram_total": 58965274624, "disk_read_mb": 0.037477797310172006, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 34.084, "gpu_mem_used": 16871993344, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 259.524, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30832005120, "ram_total": 58965274624, "disk_read_mb": 0.2174117063512491, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 35.086, "gpu_mem_used": 16871993344, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 251.052, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30832005120, "ram_total": 58965274624, "disk_read_mb": 0.041211153884411475, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 36.088, "gpu_mem_used": 16872189952, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 61, "gpu_power_w": 220.919, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30947614720, "ram_total": 58965274624, "disk_read_mb": 14.921218469617164, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 37.09, "gpu_mem_used": 16871731200, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 225.109, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30947614720, "ram_total": 58965274624, "disk_read_mb": 0.04120570776240048, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 38.092, "gpu_mem_used": 16871731200, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 63, "gpu_power_w": 251.717, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30955048960, "ram_total": 58965274624, "disk_read_mb": 5.864758537751304, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 39.093, "gpu_mem_used": 16871731200, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 271.475, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30960979968, "ram_total": 58965274624, "disk_read_mb": 230.18278498204805, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 40.095, "gpu_mem_used": 16871731200, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 247.402, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30960459776, "ram_total": 58965274624, "disk_read_mb": 0.04119390649085626, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 41.097, "gpu_mem_used": 16873041920, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 204.023, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31083560960, "ram_total": 58965274624, "disk_read_mb": 150.03325947980733, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 42.098, "gpu_mem_used": 16872189952, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 237.22, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31083560960, "ram_total": 58965274624, "disk_read_mb": 70.0158933219924, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 43.1, "gpu_mem_used": 16872189952, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 237.22, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31083560960, "ram_total": 58965274624, "disk_read_mb": 70.0158933219924, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 44.102, "gpu_mem_used": 16871993344, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 258.775, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31078535168, "ram_total": 58965274624, "disk_read_mb": 83.29339514252888, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 45.104, "gpu_mem_used": 16871993344, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 269.469, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31079022592, "ram_total": 58965274624, "disk_read_mb": 228.92081944663354, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 46.106, "gpu_mem_used": 16871993344, "gpu_mem_total": 17094934528, "gpu_util": 84, "gpu_temp_c": 62, "gpu_power_w": 250.143, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31186169856, "ram_total": 58965274624, "disk_read_mb": 0.04122267274448572, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 47.107, "gpu_mem_used": 16872189952, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 180.012, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31194099712, "ram_total": 58965274624, "disk_read_mb": 172.01045935064028, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 48.109, "gpu_mem_used": 16871993344, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 245.892, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31194140672, "ram_total": 58965274624, "disk_read_mb": 23.37751795289517, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 49.109, "gpu_mem_used": 16871993344, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 248.009, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31194140672, "ram_total": 58965274624, "disk_read_mb": 0.03744420450148632, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 50.111, "gpu_mem_used": 16871993344, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 234.511, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31194140672, "ram_total": 58965274624, "disk_read_mb": 0.03752339200104069, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 51.113, "gpu_mem_used": 16874090496, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 125.566, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31310569472, "ram_total": 58965274624, "disk_read_mb": 0.31070885758964106, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 52.115, "gpu_mem_used": 16872976384, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 142.96, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30912491520, "ram_total": 58965274624, "disk_read_mb": 25.376189214102787, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 53.117, "gpu_mem_used": 16874090496, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 221.054, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30912114688, "ram_total": 58965274624, "disk_read_mb": 0.04123313201493346, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 54.118, "gpu_mem_used": 16872779776, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 254.466, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30912094208, "ram_total": 58965274624, "disk_read_mb": 10.021828925694132, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 55.12, "gpu_mem_used": 16872779776, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 254.836, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30909845504, "ram_total": 58965274624, "disk_read_mb": 0.041171706787743796, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 56.121, "gpu_mem_used": 16872779776, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 243.997, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30959468544, "ram_total": 58965274624, "disk_read_mb": 4.741892980952503, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 57.123, "gpu_mem_used": 16872976384, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 217.468, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30959452160, "ram_total": 58965274624, "disk_read_mb": 4.735462434936903, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 58.125, "gpu_mem_used": 16872976384, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 252.26, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30959452160, "ram_total": 58965274624, "disk_read_mb": 0.0374677782595412, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 59.126, "gpu_mem_used": 16872976384, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 260.081, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30958796800, "ram_total": 58965274624, "disk_read_mb": 6.7067599157154465, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 60.128, "gpu_mem_used": 16872976384, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 252.024, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30958796800, "ram_total": 58965274624, "disk_read_mb": 0.037456651310445545, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 61.129, "gpu_mem_used": 16874287104, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 220.914, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31081689088, "ram_total": 58965274624, "disk_read_mb": 6.319329053711986, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 62.131, "gpu_mem_used": 16874287104, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 224.179, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31081689088, "ram_total": 58965274624, "disk_read_mb": 0.04123158495343648, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 63.133, "gpu_mem_used": 16874090496, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 259.552, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31081537536, "ram_total": 58965274624, "disk_read_mb": 0.03749011205159284, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 64.135, "gpu_mem_used": 16874090496, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 66, "gpu_power_w": 266.353, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31081517056, "ram_total": 58965274624, "disk_read_mb": 6.8461336426861115, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 65.137, "gpu_mem_used": 16874090496, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 256.299, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31081517056, "ram_total": 58965274624, "disk_read_mb": 0.04123543395544329, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 66.139, "gpu_mem_used": 16874287104, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 207.888, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31205154816, "ram_total": 58965274624, "disk_read_mb": 4.373381836679985, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 67.14, "gpu_mem_used": 16874287104, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 60, "gpu_power_w": 236.57, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31205154816, "ram_total": 58965274624, "disk_read_mb": 0.04119899160493737, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 68.142, "gpu_mem_used": 16874287104, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 60, "gpu_power_w": 236.57, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31205154816, "ram_total": 58965274624, "disk_read_mb": 0.04119899160493737, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 69.144, "gpu_mem_used": 16874287104, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 255.495, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31205154816, "ram_total": 58965274624, "disk_read_mb": 0.037481775561854884, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 70.148, "gpu_mem_used": 16874287104, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 231.16, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31210684416, "ram_total": 58965274624, "disk_read_mb": 0.03748078949403222, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 71.15, "gpu_mem_used": 16882675712, "gpu_mem_total": 17094934528, "gpu_util": 79, "gpu_temp_c": 54, "gpu_power_w": 185.399, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31334825984, "ram_total": 58965274624, "disk_read_mb": 0.2997100811676693, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 72.152, "gpu_mem_used": 16883527680, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 150.122, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30994038784, "ram_total": 58965274624, "disk_read_mb": 9.060524566068628, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 73.153, "gpu_mem_used": 16882675712, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 236.687, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30994296832, "ram_total": 58965274624, "disk_read_mb": 0.04123064168022918, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 74.155, "gpu_mem_used": 16882675712, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 256.603, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30994558976, "ram_total": 58965274624, "disk_read_mb": 3.8539720545728464, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 75.157, "gpu_mem_used": 16882479104, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 63, "gpu_power_w": 257.105, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30994534400, "ram_total": 58965274624, "disk_read_mb": 0.03744209090676408, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 76.159, "gpu_mem_used": 16882479104, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 66, "gpu_power_w": 253.454, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31092666368, "ram_total": 58965274624, "disk_read_mb": 0.037462852120284475, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 77.16, "gpu_mem_used": 16899977216, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 195.894, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31109517312, "ram_total": 58965274624, "disk_read_mb": 3.8185534263218663, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 78.169, "gpu_mem_used": 16942993408, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 240.669, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31109517312, "ram_total": 58965274624, "disk_read_mb": 0.04119886917077629, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 79.17, "gpu_mem_used": 16934735872, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 247.38, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31109746688, "ram_total": 58965274624, "disk_read_mb": 4.368631052455376, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 80.172, "gpu_mem_used": 16934211584, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 66, "gpu_power_w": 259.532, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31110238208, "ram_total": 58965274624, "disk_read_mb": 0.03752919369956671, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 81.173, "gpu_mem_used": 16933351424, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 66, "gpu_power_w": 248.384, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31225221120, "ram_total": 58965274624, "disk_read_mb": 0.04120183604950329, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 82.175, "gpu_mem_used": 16931909632, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 205.508, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31228628992, "ram_total": 58965274624, "disk_read_mb": 13.683215787605178, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 83.177, "gpu_mem_used": 16947204096, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 244.867, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31228628992, "ram_total": 58965274624, "disk_read_mb": 0.03747065743805358, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 84.179, "gpu_mem_used": 16945754112, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 241.238, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31228641280, "ram_total": 58965274624, "disk_read_mb": 0.04120681948352004, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 85.181, "gpu_mem_used": 16949161984, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 226.626, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31228895232, "ram_total": 58965274624, "disk_read_mb": 0.03745595770110402, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 86.183, "gpu_mem_used": 16954896384, "gpu_mem_total": 17094934528, "gpu_util": 85, "gpu_temp_c": 54, "gpu_power_w": 150.498, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31369695232, "ram_total": 58965274624, "disk_read_mb": 0.449939002071484, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 87.185, "gpu_mem_used": 16951832576, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 173.521, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30910439424, "ram_total": 58965274624, "disk_read_mb": 19.075698612929678, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 88.187, "gpu_mem_used": 16929681408, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 243.35, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30909718528, "ram_total": 58965274624, "disk_read_mb": 0.04119308733988663, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 89.189, "gpu_mem_used": 16927617024, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 244.846, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30909374464, "ram_total": 58965274624, "disk_read_mb": 9.028242353373903, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 90.191, "gpu_mem_used": 16927617024, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 244.846, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30909374464, "ram_total": 58965274624, "disk_read_mb": 9.028242353373903, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 91.193, "gpu_mem_used": 16923537408, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 249.313, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30910861312, "ram_total": 58965274624, "disk_read_mb": 0.037463383224297604, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 92.194, "gpu_mem_used": 16926355456, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 242.966, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 30968586240, "ram_total": 58965274624, "disk_read_mb": 0.04122162616643726, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 93.196, "gpu_mem_used": 16925896704, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 181.197, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31026077696, "ram_total": 58965274624, "disk_read_mb": 9.149051897040566, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 94.198, "gpu_mem_used": 16925962240, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 235.504, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31026049024, "ram_total": 58965274624, "disk_read_mb": 0.04123119820620129, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 95.2, "gpu_mem_used": 16925241344, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 245.174, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31026028544, "ram_total": 58965274624, "disk_read_mb": 7.7433787681360995, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 96.202, "gpu_mem_used": 16918818816, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 246.986, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31026028544, "ram_total": 58965274624, "disk_read_mb": 0.04121551747401275, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 97.204, "gpu_mem_used": 16919015424, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 245.597, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31026028544, "ram_total": 58965274624, "disk_read_mb": 0.03748186988410452, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 98.206, "gpu_mem_used": 16919015424, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 178.718, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31141507072, "ram_total": 58965274624, "disk_read_mb": 7.989299157452675, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 99.207, "gpu_mem_used": 16925437952, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 235.493, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31149764608, "ram_total": 58965274624, "disk_read_mb": 0.04117693694895768, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 100.209, "gpu_mem_used": 16928780288, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 254.757, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31157116928, "ram_total": 58965274624, "disk_read_mb": 12.335092174498511, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 101.211, "gpu_mem_used": 16930222080, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 65, "gpu_power_w": 254.013, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31154364416, "ram_total": 58965274624, "disk_read_mb": 10.5380731822828, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 102.213, "gpu_mem_used": 16928518144, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 64, "gpu_power_w": 251.041, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31153995776, "ram_total": 58965274624, "disk_read_mb": 0.041235915131222343, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 103.215, "gpu_mem_used": 16928518144, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 203.659, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31277424640, "ram_total": 58965274624, "disk_read_mb": 104.50306135702174, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 104.217, "gpu_mem_used": 16928321536, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 63, "gpu_power_w": 252.108, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31278227456, "ram_total": 58965274624, "disk_read_mb": 0.03745054671763696, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 105.219, "gpu_mem_used": 16928321536, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 66, "gpu_power_w": 265.708, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31278215168, "ram_total": 58965274624, "disk_read_mb": 75.29307645493573, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 106.221, "gpu_mem_used": 16928518144, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 66, "gpu_power_w": 259.668, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31278215168, "ram_total": 58965274624, "disk_read_mb": 81.7788946975423, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 107.223, "gpu_mem_used": 16927207424, "gpu_mem_total": 17094934528, "gpu_util": 86, "gpu_temp_c": 61, "gpu_power_w": 238.783, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31407464448, "ram_total": 58965274624, "disk_read_mb": 92.92240859177025, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 108.225, "gpu_mem_used": 16927207424, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 211.549, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31405428736, "ram_total": 58965274624, "disk_read_mb": 212.71078068819483, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 109.226, "gpu_mem_used": 16927207424, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 62, "gpu_power_w": 254.905, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31405428736, "ram_total": 58965274624, "disk_read_mb": 0.04121789286147189, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 110.227, "gpu_mem_used": 16907448320, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 68, "gpu_power_w": 273.323, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31409680384, "ram_total": 58965274624, "disk_read_mb": 87.59702831449484, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 111.229, "gpu_mem_used": 16903057408, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 256.86, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31409913856, "ram_total": 58965274624, "disk_read_mb": 130.69570542190914, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 112.232, "gpu_mem_used": 16911970304, "gpu_mem_total": 17094934528, "gpu_util": 18, "gpu_temp_c": 56, "gpu_power_w": 216.119, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31512879104, "ram_total": 58965274624, "disk_read_mb": 31.12512403528429, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 113.234, "gpu_mem_used": 16918851584, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 196.076, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31511887872, "ram_total": 58965274624, "disk_read_mb": 209.25649944103617, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 114.236, "gpu_mem_used": 16912101376, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 66, "gpu_power_w": 245.997, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31512215552, "ram_total": 58965274624, "disk_read_mb": 3.3495106067598055, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 115.238, "gpu_mem_used": 16906334208, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 260.997, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31510171648, "ram_total": 58965274624, "disk_read_mb": 49.19635091507312, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 116.241, "gpu_mem_used": 16906334208, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 260.997, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31510171648, "ram_total": 58965274624, "disk_read_mb": 49.19635091507312, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 117.242, "gpu_mem_used": 16905220096, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 261.121, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31509291008, "ram_total": 58965274624, "disk_read_mb": 165.88153822650392, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 118.244, "gpu_mem_used": 16900632576, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 252.497, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31523688448, "ram_total": 58965274624, "disk_read_mb": 0.0374673155756918, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 119.247, "gpu_mem_used": 16900632576, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 145.934, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31626993664, "ram_total": 58965274624, "disk_read_mb": 56.98529796808603, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 120.249, "gpu_mem_used": 16900698112, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 224.712, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31626993664, "ram_total": 58965274624, "disk_read_mb": 77.47269786807995, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 121.251, "gpu_mem_used": 16900698112, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 245.596, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31629250560, "ram_total": 58965274624, "disk_read_mb": 77.52959217658318, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 122.253, "gpu_mem_used": 16911708160, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 63, "gpu_power_w": 257.603, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31629250560, "ram_total": 58965274624, "disk_read_mb": 198.27008191620973, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 123.254, "gpu_mem_used": 16911708160, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 245.818, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31629250560, "ram_total": 58965274624, "disk_read_mb": 0.04123549999851279, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 124.256, "gpu_mem_used": 16911511552, "gpu_mem_total": 17094934528, "gpu_util": 5, "gpu_temp_c": 64, "gpu_power_w": 220.094, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31736569856, "ram_total": 58965274624, "disk_read_mb": 0.03746485668846247, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 125.258, "gpu_mem_used": 16911511552, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 161.109, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31649030144, "ram_total": 58965274624, "disk_read_mb": 84.77357766996067, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 126.26, "gpu_mem_used": 16915640320, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 248.557, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31649001472, "ram_total": 58965274624, "disk_read_mb": 0.04123055678775748, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 127.262, "gpu_mem_used": 16916492288, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 255.439, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31649001472, "ram_total": 58965274624, "disk_read_mb": 0.037381352308750254, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 128.264, "gpu_mem_used": 16907776000, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 208.45, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31649001472, "ram_total": 58965274624, "disk_read_mb": 0.03747213147448629, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 129.266, "gpu_mem_used": 16908824576, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 52, "gpu_power_w": 111.608, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31039184896, "ram_total": 58965274624, "disk_read_mb": 2.570034514314042, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 130.268, "gpu_mem_used": 16894242816, "gpu_mem_total": 17094934528, "gpu_util": 6, "gpu_temp_c": 50, "gpu_power_w": 54.306, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31036227584, "ram_total": 58965274624, "disk_read_mb": 77.11743018284925, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 131.27, "gpu_mem_used": 16879759360, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 164.268, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31035912192, "ram_total": 58965274624, "disk_read_mb": 131.61285629094132, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 132.271, "gpu_mem_used": 16888672256, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 234.191, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31035912192, "ram_total": 58965274624, "disk_read_mb": 0.037481569769503446, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 133.274, "gpu_mem_used": 16880021504, "gpu_mem_total": 17094934528, "gpu_util": 97, "gpu_temp_c": 62, "gpu_power_w": 254.237, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31035719680, "ram_total": 58965274624, "disk_read_mb": 110.88852805567142, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 134.275, "gpu_mem_used": 16876548096, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 252.42, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31035719680, "ram_total": 58965274624, "disk_read_mb": 0.03747643426733159, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 135.277, "gpu_mem_used": 16869339136, "gpu_mem_total": 17094934528, "gpu_util": 77, "gpu_temp_c": 61, "gpu_power_w": 245.891, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31035707392, "ram_total": 58965274624, "disk_read_mb": 28.822182972473414, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 136.279, "gpu_mem_used": 16856199168, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 242.666, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31035707392, "ram_total": 58965274624, "disk_read_mb": 83.77722554325689, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 137.381, "gpu_mem_used": 16856199168, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 259.872, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31035936768, "ram_total": 58965274624, "disk_read_mb": 0.0374891598574936, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 138.382, "gpu_mem_used": 16847220736, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 265.366, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31035936768, "ram_total": 58965274624, "disk_read_mb": 94.55981228184811, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 139.383, "gpu_mem_used": 16852594688, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 254.529, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31035936768, "ram_total": 58965274624, "disk_read_mb": 0.03755391613722766, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 140.384, "gpu_mem_used": 16852594688, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 59, "gpu_power_w": 211.592, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31151665152, "ram_total": 58965274624, "disk_read_mb": 97.85659452198898, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 141.386, "gpu_mem_used": 16845778944, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 63, "gpu_power_w": 237.619, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31151665152, "ram_total": 58965274624, "disk_read_mb": 0.041230000279100454, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 142.388, "gpu_mem_used": 16852398080, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 259.194, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31151665152, "ram_total": 58965274624, "disk_read_mb": 56.76542487705051, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 143.39, "gpu_mem_used": 16852463616, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 266.438, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31151665152, "ram_total": 58965274624, "disk_read_mb": 57.93272851751348, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 144.392, "gpu_mem_used": 16852463616, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 266.438, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31151665152, "ram_total": 58965274624, "disk_read_mb": 57.93272851751348, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 145.393, "gpu_mem_used": 16852135936, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 67, "gpu_power_w": 259.222, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31151665152, "ram_total": 58965274624, "disk_read_mb": 0.03748886820411298, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 146.395, "gpu_mem_used": 16852135936, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 185.193, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31267119104, "ram_total": 58965274624, "disk_read_mb": 92.06294481589553, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 147.398, "gpu_mem_used": 16852332544, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 66, "gpu_power_w": 244.145, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31267241984, "ram_total": 58965274624, "disk_read_mb": 22.512188983008187, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 148.4, "gpu_mem_used": 16851415040, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 267.643, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31267241984, "ram_total": 58965274624, "disk_read_mb": 92.76058408930572, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 149.401, "gpu_mem_used": 16851415040, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 266.179, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31267241984, "ram_total": 58965274624, "disk_read_mb": 1.195663169771489, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 150.403, "gpu_mem_used": 16851415040, "gpu_mem_total": 17094934528, "gpu_util": 79, "gpu_temp_c": 58, "gpu_power_w": 237.305, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31390392320, "ram_total": 58965274624, "disk_read_mb": 5.663556723639289, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 151.406, "gpu_mem_used": 16851415040, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 207.436, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31390126080, "ram_total": 58965274624, "disk_read_mb": 83.52046212050494, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 152.411, "gpu_mem_used": 16850366464, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 249.054, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31390126080, "ram_total": 58965274624, "disk_read_mb": 0.03747370847906696, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 153.413, "gpu_mem_used": 16851480576, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 66, "gpu_power_w": 269.026, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31390126080, "ram_total": 58965274624, "disk_read_mb": 90.9139214439019, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 154.416, "gpu_mem_used": 16845975552, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 67, "gpu_power_w": 255.965, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31390126080, "ram_total": 58965274624, "disk_read_mb": 0.03748325904857862, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 155.418, "gpu_mem_used": 16850038784, "gpu_mem_total": 17094934528, "gpu_util": 57, "gpu_temp_c": 64, "gpu_power_w": 240.692, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31505604608, "ram_total": 58965274624, "disk_read_mb": 17.316196697465983, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 156.42, "gpu_mem_used": 16850235392, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 62, "gpu_power_w": 217.022, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31505588224, "ram_total": 58965274624, "disk_read_mb": 68.83439832468916, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 157.423, "gpu_mem_used": 16850235392, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 66, "gpu_power_w": 259.131, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31505817600, "ram_total": 58965274624, "disk_read_mb": 0.03737258671493959, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 158.425, "gpu_mem_used": 16850235392, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 67, "gpu_power_w": 265.388, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31506046976, "ram_total": 58965274624, "disk_read_mb": 80.66779561904858, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 159.426, "gpu_mem_used": 16850235392, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 264.532, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31511990272, "ram_total": 58965274624, "disk_read_mb": 0.03748819055642643, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 160.428, "gpu_mem_used": 16850235392, "gpu_mem_total": 17094934528, "gpu_util": 38, "gpu_temp_c": 68, "gpu_power_w": 231.334, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31633993728, "ram_total": 58965274624, "disk_read_mb": 0.026236288560742105, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 161.43, "gpu_mem_used": 16844664832, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 64, "gpu_power_w": 225.119, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31634231296, "ram_total": 58965274624, "disk_read_mb": 80.70169568158126, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 162.432, "gpu_mem_used": 16850038784, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 253.756, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31634231296, "ram_total": 58965274624, "disk_read_mb": 0.0412368586457395, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 163.434, "gpu_mem_used": 16850038784, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 66, "gpu_power_w": 267.325, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31633833984, "ram_total": 58965274624, "disk_read_mb": 71.63592528705145, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 164.436, "gpu_mem_used": 16850038784, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 64, "gpu_power_w": 268.908, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31633833984, "ram_total": 58965274624, "disk_read_mb": 5.1638368717015775, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 165.437, "gpu_mem_used": 16850038784, "gpu_mem_total": 17094934528, "gpu_util": 85, "gpu_temp_c": 67, "gpu_power_w": 227.755, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31629254656, "ram_total": 58965274624, "disk_read_mb": 29.886646895515803, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 166.439, "gpu_mem_used": 16850038784, "gpu_mem_total": 17094934528, "gpu_util": 85, "gpu_temp_c": 67, "gpu_power_w": 227.755, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31629254656, "ram_total": 58965274624, "disk_read_mb": 29.886646895515803, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 167.441, "gpu_mem_used": 16850235392, "gpu_mem_total": 17094934528, "gpu_util": 100, "gpu_temp_c": 62, "gpu_power_w": 215.33, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31629234176, "ram_total": 58965274624, "disk_read_mb": 0.037480712325696046, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 168.442, "gpu_mem_used": 16848531456, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 67, "gpu_power_w": 259.561, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31629152256, "ram_total": 58965274624, "disk_read_mb": 0.037491802100767455, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 169.443, "gpu_mem_used": 16844337152, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 227.287, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31629152256, "ram_total": 58965274624, "disk_read_mb": 0.04122586937943428, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 170.445, "gpu_mem_used": 16865308672, "gpu_mem_total": 17094934528, "gpu_util": 61, "gpu_temp_c": 62, "gpu_power_w": 188.446, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31628677120, "ram_total": 58965274624, "disk_read_mb": 0.037479906364286664, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 171.447, "gpu_mem_used": 16865308672, "gpu_mem_total": 17094934528, "gpu_util": 41, "gpu_temp_c": 52, "gpu_power_w": 80.419, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31050223616, "ram_total": 58965274624, "disk_read_mb": 41.92046341952552, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 172.449, "gpu_mem_used": 16858361856, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 115.203, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31049949184, "ram_total": 58965274624, "disk_read_mb": 77.75670391897856, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 173.451, "gpu_mem_used": 16864653312, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 220.456, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31049367552, "ram_total": 58965274624, "disk_read_mb": 56.88171939224671, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 174.453, "gpu_mem_used": 16863735808, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 60, "gpu_power_w": 246.904, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31049367552, "ram_total": 58965274624, "disk_read_mb": 0.6855397838802102, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 175.454, "gpu_mem_used": 16863145984, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 247.402, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31049367552, "ram_total": 58965274624, "disk_read_mb": 71.66592925566628, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 176.457, "gpu_mem_used": 16863080448, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 62, "gpu_power_w": 244.767, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31049367552, "ram_total": 58965274624, "disk_read_mb": 0.0374337672046476, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 177.459, "gpu_mem_used": 16861442048, "gpu_mem_total": 17094934528, "gpu_util": 97, "gpu_temp_c": 60, "gpu_power_w": 215.157, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31164514304, "ram_total": 58965274624, "disk_read_mb": 76.65108568639528, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 178.46, "gpu_mem_used": 16856199168, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 218.037, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31164604416, "ram_total": 58965274624, "disk_read_mb": 0.037470366072486314, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 179.462, "gpu_mem_used": 16863539200, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 244.583, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31164604416, "ram_total": 58965274624, "disk_read_mb": 0.04120882638623397, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 180.463, "gpu_mem_used": 16863539200, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 257.36, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31164506112, "ram_total": 58965274624, "disk_read_mb": 90.23578964977203, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 181.465, "gpu_mem_used": 16866750464, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 248.52, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31164506112, "ram_total": 58965274624, "disk_read_mb": 0.037471985779674144, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 182.467, "gpu_mem_used": 16864587776, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 65, "gpu_power_w": 216.58, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31287681024, "ram_total": 58965274624, "disk_read_mb": 38.6982633938446, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 183.469, "gpu_mem_used": 16864718848, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 216.606, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31287681024, "ram_total": 58965274624, "disk_read_mb": 51.709739268452765, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 184.477, "gpu_mem_used": 16873631744, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 247.112, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31287681024, "ram_total": 58965274624, "disk_read_mb": 0.04121761948944985, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 185.479, "gpu_mem_used": 16873435136, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 250.607, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31287681024, "ram_total": 58965274624, "disk_read_mb": 77.92724985775706, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 186.481, "gpu_mem_used": 16873631744, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 248.4, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31287668736, "ram_total": 58965274624, "disk_read_mb": 0.04122058906944447, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 187.483, "gpu_mem_used": 16871010304, "gpu_mem_total": 17094934528, "gpu_util": 57, "gpu_temp_c": 61, "gpu_power_w": 220.105, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31403405312, "ram_total": 58965274624, "disk_read_mb": 30.499842780170287, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 188.484, "gpu_mem_used": 16870354944, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 203.247, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31403405312, "ram_total": 58965274624, "disk_read_mb": 43.91471578178877, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 189.487, "gpu_mem_used": 16858165248, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 244.412, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31415099392, "ram_total": 58965274624, "disk_read_mb": 0.04123280183962576, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 190.489, "gpu_mem_used": 16858165248, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 63, "gpu_power_w": 251.374, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31413854208, "ram_total": 58965274624, "disk_read_mb": 78.61755662095933, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 191.49, "gpu_mem_used": 16858165248, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 63, "gpu_power_w": 251.374, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31413854208, "ram_total": 58965274624, "disk_read_mb": 78.61755662095933, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 192.492, "gpu_mem_used": 16859607040, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 256.613, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31414312960, "ram_total": 58965274624, "disk_read_mb": 0.03747710291746802, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 193.494, "gpu_mem_used": 16859607040, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 244.996, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31438118912, "ram_total": 58965274624, "disk_read_mb": 0.04109984221313018, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 194.496, "gpu_mem_used": 16859410432, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 196.078, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31528472576, "ram_total": 58965274624, "disk_read_mb": 71.75280220333245, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 195.498, "gpu_mem_used": 16859410432, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 236.509, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31528472576, "ram_total": 58965274624, "disk_read_mb": 0.04122546387911065, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 196.499, "gpu_mem_used": 16857509888, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 61, "gpu_power_w": 245.313, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31529201664, "ram_total": 58965274624, "disk_read_mb": 58.26623215397004, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 197.502, "gpu_mem_used": 16857706496, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 251.51, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31529246720, "ram_total": 58965274624, "disk_read_mb": 8.995545242113314, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 198.504, "gpu_mem_used": 16860065792, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 244.302, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31529246720, "ram_total": 58965274624, "disk_read_mb": 0.03747078598312671, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 199.504, "gpu_mem_used": 16862228480, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 213.136, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31644229632, "ram_total": 58965274624, "disk_read_mb": 67.6279231067318, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 200.506, "gpu_mem_used": 16865783808, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 217.729, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31644229632, "ram_total": 58965274624, "disk_read_mb": 0.037509526765029964, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 201.508, "gpu_mem_used": 16870699008, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 242.568, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31644475392, "ram_total": 58965274624, "disk_read_mb": 0.04117639129452347, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 202.51, "gpu_mem_used": 16869191680, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 64, "gpu_power_w": 251.959, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31644475392, "ram_total": 58965274624, "disk_read_mb": 65.43246543560585, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 203.512, "gpu_mem_used": 16868798464, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 254.377, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31644471296, "ram_total": 58965274624, "disk_read_mb": 0.04121518758074139, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 204.514, "gpu_mem_used": 16868749312, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 246.926, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31677181952, "ram_total": 58965274624, "disk_read_mb": 0.03748101242656613, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 205.515, "gpu_mem_used": 16867438592, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 191.213, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31638114304, "ram_total": 58965274624, "disk_read_mb": 28.126990372100366, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 206.517, "gpu_mem_used": 16867684352, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 247.026, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31638233088, "ram_total": 58965274624, "disk_read_mb": 0.041202966401420744, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 207.52, "gpu_mem_used": 16876990464, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 63, "gpu_power_w": 245.94, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31638212608, "ram_total": 58965274624, "disk_read_mb": 0.03732202616869948, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 208.522, "gpu_mem_used": 16873975808, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 197.625, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31637078016, "ram_total": 58965274624, "disk_read_mb": 0.0412092409820487, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 209.525, "gpu_mem_used": 16871878656, "gpu_mem_total": 17094934528, "gpu_util": 61, "gpu_temp_c": 54, "gpu_power_w": 146.039, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31631286272, "ram_total": 58965274624, "disk_read_mb": 11.465457438723814, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "idle", "tok_s": null}
{"t": 210.529, "gpu_mem_used": 16873254912, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 50, "gpu_power_w": 49.889, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31691522048, "ram_total": 58965274624, "disk_read_mb": 18.985031708647423, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "idle", "tok_s": null}
{"t": 211.531, "gpu_mem_used": 16873320448, "gpu_mem_total": 17094934528, "gpu_util": 89, "gpu_temp_c": 51, "gpu_power_w": 66.806, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31000162304, "ram_total": 58965274624, "disk_read_mb": 7.88121997268363, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "reading", "tok_s": null}
{"t": 212.533, "gpu_mem_used": 16876941312, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 50, "gpu_power_w": 73.807, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31099023360, "ram_total": 58965274624, "disk_read_mb": 0.5243014221164062, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "idle", "tok_s": null}
{"t": 213.536, "gpu_mem_used": 16876482560, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 49, "gpu_power_w": 49.475, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31098822656, "ram_total": 58965274624, "disk_read_mb": 0.03747040035055316, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "idle", "tok_s": null}
{"t": 214.538, "gpu_mem_used": 16873074688, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 48, "gpu_power_w": 41.882, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31098822656, "ram_total": 58965274624, "disk_read_mb": 0.03747603137428203, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "idle", "tok_s": null}
{"t": 215.539, "gpu_mem_used": 16872861696, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 47, "gpu_power_w": 36.369, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31098822656, "ram_total": 58965274624, "disk_read_mb": 0.041213802086668264, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "idle", "tok_s": null}
{"t": 216.541, "gpu_mem_used": 16871288832, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 47, "gpu_power_w": 36.367, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31098822656, "ram_total": 58965274624, "disk_read_mb": 0.037458218448355486, "vram_free_mib": 179, "expert_cache_mib": 6938, "state": "idle", "tok_s": null}
@@ -0,0 +1,74 @@
{
"service": "strata",
"model": "qwen3.8-flash-next-coder-iq1_m",
"loaded": true,
"auto_load": true,
"structured_output": {
"formats": [
"json_object",
"json_schema"
],
"method": "prompt_and_validate",
"constrained_decoding": false,
"stream_buffered": true
},
"engine": "0.1.40.3",
"started": 1791412443,
"uptime_s": 183,
"cache_max_tokens": 65536,
"context": {
"native": 65536,
"max_positions": 65536
},
"concurrency": {
"serving": 1,
"requested": 1
},
"dialects": [
"/v1/chat/completions",
"/v1/messages",
"/v1/responses"
],
"vision": {
"enabled": true,
"available": true,
"error": null
},
"activity": {
"requests": 13,
"in_flight": 0,
"last_request_at": 1791412616
},
"last_timings": {
"cache_n": 0,
"prompt_n": 32768,
"prompt_ms": 10799.9,
"prompt_per_token_ms": 0.33,
"prompt_per_second": 3034.1,
"predicted_n": 256,
"predicted_ms": 3623.7,
"predicted_per_token_ms": 14.155,
"predicted_per_second": 70.6,
"draft_n": 232,
"draft_n_accepted": 149,
"at": 1791412597
},
"vram": {
"elastic": false
},
"machine": {
"at": 1791412626,
"gpu": {
"name": "NVIDIA GeForce RTX 5080",
"used_mib": 16023.0,
"total_mib": 16303.0,
"util_pct": 4,
"temp_c": 42,
"power_w": 31.225
},
"ram": {
"used_gib": 29.2,
"total_gib": 54.9
}
}
}
@@ -0,0 +1,77 @@
{
"source": "telemetry-speed.jsonl",
"samples": 208,
"unparseable_lines": 0,
"sampled_seconds": 207.5,
"note": "Each sample is one GET /metrics, so the values are the engine's own view. Sampled peaks can miss shorter spikes between samples.",
"fields": {
"gpu_mem_used": {
"median": 16802181120.0,
"min": 16799428608,
"max": 16898912256,
"max_gib": 15.74,
"median_gib": 15.65
},
"gpu_mem_total": {
"median": 17094934528.0,
"min": 17094934528,
"max": 17094934528,
"max_gib": 15.92,
"median_gib": 15.92
},
"gpu_util": {
"median": 99.0,
"min": 0,
"max": 99
},
"gpu_temp_c": {
"median": 56.0,
"min": 42,
"max": 65
},
"gpu_power_w": {
"median": 188.815,
"min": 28.467,
"max": 268.127
},
"gpu_pcie_gen": {
"median": 5.0,
"min": 5,
"max": 5
},
"gpu_pcie_width": {
"median": 8.0,
"min": 8,
"max": 8
},
"ram_used": {
"median": 31321849856.0,
"min": 31169871872,
"max": 31662776320,
"max_gib": 29.49,
"median_gib": 29.17
},
"ram_total": {
"median": 58965274624.0,
"min": 58965274624,
"max": 58965274624,
"max_gib": 54.92,
"median_gib": 54.92
},
"disk_read_mb": {
"median": 0.041188446105728624,
"min": 0.03619504854210215,
"max": 3.5634089947513465
},
"vram_free_mib": {
"median": 178.0,
"min": 178,
"max": 178
},
"expert_cache_mib": {
"median": 7918.0,
"min": 7918,
"max": 7918
}
}
}
@@ -0,0 +1,56 @@
[
{
"length": "32k",
"depth": 10,
"prompt_tokens": 32343,
"seconds": 13.0,
"found": true,
"word": "meadow-copper-504",
"answer": "meadow-copper-504"
},
{
"length": "32k",
"depth": 50,
"prompt_tokens": 32343,
"seconds": 10.0,
"found": true,
"word": "falcon-quartz-940",
"answer": "falcon-quartz-940"
},
{
"length": "32k",
"depth": 90,
"prompt_tokens": 32344,
"seconds": 5.3,
"found": true,
"word": "willow-cobalt-696",
"answer": "willow-cobalt-696"
},
{
"length": "64k",
"depth": 10,
"prompt_tokens": 62627,
"seconds": 21.0,
"found": true,
"word": "falcon-saffron-138",
"answer": "falcon-saffron-138"
},
{
"length": "64k",
"depth": 50,
"prompt_tokens": 62625,
"seconds": 20.0,
"found": true,
"word": "quartz-tundra-528",
"answer": "quartz-tundra-528"
},
{
"length": "64k",
"depth": 90,
"prompt_tokens": 62625,
"seconds": 14.8,
"found": true,
"word": "quartz-glacier-192",
"answer": "quartz-glacier-192"
}
]
@@ -0,0 +1,658 @@
[
{
"label": "warmup",
"expected_prompt_tokens": null,
"request_sha256": "b63e57873441a996a529b246a66cf12de70a7c671777f99329354d5c195f788f",
"client_ttft_s": 0.47098268500030827,
"client_elapsed_s": 0.5419416640006602,
"finish_reason": "stop",
"usage": {
"prompt_tokens": 19,
"completion_tokens": 2,
"total_tokens": 21,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412626.8990476,
"duration_s": 0.5,
"finish": "stop",
"prompt_tokens": 19,
"reused": 0,
"output_tokens": 2,
"prompt_total": 19,
"prompt_read": 19,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 2,
"prompt_ms": 442.1,
"decode_ms": 97.3,
"decode_tok_s": 20.6,
"hit_rate": 0.436,
"pcie_share": 0.335,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 3,
"drafts_accepted": 3
},
"text": "READY"
},
{
"label": "tokens-4096-run-1",
"expected_prompt_tokens": 4096,
"request_sha256": "5d94c652067354bbe72930d2bdad3886564f08cf2546b32411af02d33ad3ce05",
"client_ttft_s": 1.903633185000217,
"client_elapsed_s": 5.378847505000522,
"finish_reason": "length",
"usage": {
"prompt_tokens": 4096,
"completion_tokens": 256,
"total_tokens": 4352,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412627.9029799,
"duration_s": 5.4,
"finish": "length",
"prompt_tokens": 4096,
"reused": 0,
"output_tokens": 256,
"prompt_total": 4096,
"prompt_read": 4096,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 1866.8,
"decode_ms": 3503.8,
"decode_tok_s": 73.1,
"hit_rate": 0.836,
"pcie_share": 0.111,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 215,
"drafts_accepted": 157
},
"text": "The provided Python module consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a deterministic integer transformation. Each function takes a single integer argument `value` and returns an integer result computed using a linear congruential formula modulo a fixed prime number, 100003. This structure is typical of benchmarking suites, cryptographic primitives, or hash function implementations where deterministic, fast, and reproducible outputs are required.\n\n### Deterministic Integer Transforms\n\nEach function implements a linear transformation of the form:\n\n```\nresult = (value * multiplier + addend) % MOD\n```\n\nwhere `MOD = 100003`, a prime number. The multiplier and addend vary per function. For example:\n- `task_00000`: `(value * 1 + 0) % 100003`\n- `task_00001`: `(value * 2 + 1) % 100003`\n- `task_00096`: `(value * 97 + 96) % 100003`\n- `task_00"
},
{
"label": "tokens-4096-run-2",
"expected_prompt_tokens": 4096,
"request_sha256": "8da8a04e70e4d916f6630729082bdfb9d6ebbb47117aad60bc0541bce198a213",
"client_ttft_s": 1.8817809450001732,
"client_elapsed_s": 5.126567950999743,
"finish_reason": "length",
"usage": {
"prompt_tokens": 4096,
"completion_tokens": 256,
"total_tokens": 4352,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412633.7443738,
"duration_s": 5.1,
"finish": "length",
"prompt_tokens": 4096,
"reused": 0,
"output_tokens": 256,
"prompt_total": 4096,
"prompt_read": 4096,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 1843.7,
"decode_ms": 3275.7,
"decode_tok_s": 78.2,
"hit_rate": 0.87,
"pcie_share": 0.086,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 209,
"drafts_accepted": 153
},
"text": "The provided Python module consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a deterministic integer transformation. Each function takes a single integer argument `value` and returns an integer result computed using a linear transformation followed by a modulo operation. The general form of each function is:\n\n```python\ndef task_XXXXX(value: int) -> int:\n return (value * A + B) % 100003\n```\n\nwhere `A` and `B` are constants specific to each function. The modulus `100003` is a prime number, which is significant in modular arithmetic because it ensures that the multiplicative group modulo 100003 is cyclic and that every non-zero element has a multiplicative inverse. This property is often exploited in cryptographic algorithms, hash functions, and pseudo-random number generators.\n\n### Deterministic Integer Transforms\n\nEach function implements a linear congruential transformation, a common technique in number theory and computer science. The transformation `value * A + B` is an affine transformation over the integers. When combined with the modulo operation, it becomes a linear congruential generator (LCG) step, though here it is"
},
{
"label": "tokens-4096-run-3",
"expected_prompt_tokens": 4096,
"request_sha256": "946079edb58e764050805886156dc8f877cc29e1ca8d01c84e9a1e7917d49492",
"client_ttft_s": 1.9702199909997944,
"client_elapsed_s": 5.495010110000294,
"finish_reason": "length",
"usage": {
"prompt_tokens": 4096,
"completion_tokens": 256,
"total_tokens": 4352,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412639.3149164,
"duration_s": 5.5,
"finish": "length",
"prompt_tokens": 4096,
"reused": 0,
"output_tokens": 256,
"prompt_total": 4096,
"prompt_read": 4096,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 1937.7,
"decode_ms": 3549.5,
"decode_tok_s": 72.1,
"hit_rate": 0.846,
"pcie_share": 0.101,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 219,
"drafts_accepted": 149
},
"text": "The provided Python module presents a series of deterministic integer transforms, each encapsulated within a uniquely named function. These functions, labeled from `task_00000` to `task_00112` (and potentially beyond), follow a consistent mathematical pattern: they take an integer input, apply a linear transformation, and return the result modulo a large prime number, specifically 100003. This structure serves as a synthetic benchmark for evaluating code generation, pattern recognition, and algorithmic consistency in automated systems.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of each function is the expression `(value * multiplier + offset) % 100003`. This is a classic linear congruential generator (LCG) step, often used in pseudo-random number generation or cryptographic hashing, though here it is applied deterministically to a single input. The multiplier and offset vary per function, creating a distinct mapping for each task. For instance, `task_00000` uses a multiplier of 1 and an offset of 0, effectively returning `value % 100003`. In contrast, `task_00001` uses a multiplier of 2"
},
{
"label": "tokens-8192-run-1",
"expected_prompt_tokens": 8192,
"request_sha256": "d7c1089e1b773cee0815d4df507e627783b01c7c00f1cdd157255e48007b05a4",
"client_ttft_s": 2.962772825999309,
"client_elapsed_s": 6.335842665999735,
"finish_reason": "length",
"usage": {
"prompt_tokens": 8192,
"completion_tokens": 256,
"total_tokens": 8448,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412645.3183253,
"duration_s": 6.3,
"finish": "length",
"prompt_tokens": 8192,
"reused": 0,
"output_tokens": 256,
"prompt_total": 8192,
"prompt_read": 8192,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 2920.6,
"decode_ms": 3402.6,
"decode_tok_s": 75.2,
"hit_rate": 0.859,
"pcie_share": 0.088,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 208,
"drafts_accepted": 142
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of deterministic integer transforms under modulo arithmetic. The code consists of a series of functions, each named with a unique identifier (`task_00000` through `task_00222` and beyond), that perform a linear transformation on an input integer `value`. The core operation in each function is of the form `(value * multiplier + offset) % 100003`. This structure allows for a detailed analysis of computational complexity, arithmetic properties, and software engineering practices.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nThe fundamental operation in this module is a linear congruential function, often seen in pseudo-random number generators or cryptographic primitives, though here it is used for benchmarking. The formula $f(x) = (ax + b) \\pmod m$ defines a deterministic mapping from the input integer to an output integer within the range $[0, m-1]$. In this specific module, the modulus $m$ is fixed at 100,003. This number is significant because 100,003 is a prime number. Using a prime modulus ensures that the multiplicative group of integers"
},
{
"label": "tokens-8192-run-2",
"expected_prompt_tokens": 8192,
"request_sha256": "18d77efc0066d46b148403e2aadb0df295679df8d609c8ff9123810cfd66f05b",
"client_ttft_s": 2.9813462499996604,
"client_elapsed_s": 6.288063500000135,
"finish_reason": "length",
"usage": {
"prompt_tokens": 8192,
"completion_tokens": 256,
"total_tokens": 8448,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412652.154979,
"duration_s": 6.3,
"finish": "length",
"prompt_tokens": 8192,
"reused": 0,
"output_tokens": 256,
"prompt_total": 8192,
"prompt_read": 8192,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 2945.1,
"decode_ms": 3331.6,
"decode_tok_s": 76.8,
"hit_rate": 0.866,
"pcie_share": 0.087,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 210,
"drafts_accepted": 147
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system handling a large number of deterministic integer transforms. The code consists of a series of functions, named sequentially from `task_00000` to `task_00222` (and potentially beyond, as the snippet cuts off), each performing a specific linear transformation on an input integer `value`.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of each function is a linear congruential generator (LCG) style transformation: `(value * multiplier + addend) % 100003`. This formula is a fundamental component in many cryptographic and pseudo-random number generation algorithms. The modulus `100003` is a prime number, which is a critical property for ensuring that the transformation is bijective (one-to-one) within the range of integers modulo 100003, provided the multiplier is not a multiple of the modulus. Since the multipliers used here range from 1 to 97, and the modulus is 100003, all multipliers are coprime to the modulus. This guarantees that for any input `value`, the output is uniquely determined"
},
{
"label": "tokens-8192-run-3",
"expected_prompt_tokens": 8192,
"request_sha256": "a8d8bb0e3287c41a120a4b8bd4387da0cf48973166300ed78e536e8eb7c85998",
"client_ttft_s": 3.009602217000065,
"client_elapsed_s": 6.332319787000415,
"finish_reason": "length",
"usage": {
"prompt_tokens": 8192,
"completion_tokens": 256,
"total_tokens": 8448,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412658.9739156,
"duration_s": 6.3,
"finish": "length",
"prompt_tokens": 8192,
"reused": 0,
"output_tokens": 256,
"prompt_total": 8192,
"prompt_read": 8192,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 2967.8,
"decode_ms": 3351.5,
"decode_tok_s": 76.4,
"hit_rate": 0.867,
"pcie_share": 0.086,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 208,
"drafts_accepted": 148
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system under a specific nonce (`series-8192-trial-3`). The code consists of a series of function definitions, each named `task_XXXXX`, where `XXXXX` is a zero-padded integer index. Each function accepts a single integer argument `value` and returns an integer result. The core logic within each function is a linear transformation followed by a modulo operation.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nThe fundamental operation in each function is of the form:\n`return (value * multiplier + offset) % 100003`\n\nHere, `100003` is a prime number. This choice of modulus is significant in computer science and cryptography because it ensures that the multiplicative group of integers modulo 100003 is cyclic, and every non-zero element has a multiplicative inverse. This property is often desirable in hashing functions or pseudo-random number generators to avoid certain degenerate cycles or collisions that might occur with composite moduli.\n\nThe transformation is an affine transformation over the finite field $\\mathbb{Z}_{100003}$. Specifically, for a"
},
{
"label": "tokens-16384-run-1",
"expected_prompt_tokens": 16384,
"request_sha256": "6189656df3e39c2820cb59a0561adb1207c2f570424ca0aee304356f5e386de4",
"client_ttft_s": 5.522646514999906,
"client_elapsed_s": 8.740790816999834,
"finish_reason": "length",
"usage": {
"prompt_tokens": 16384,
"completion_tokens": 256,
"total_tokens": 16640,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412665.9380753,
"duration_s": 8.7,
"finish": "length",
"prompt_tokens": 16384,
"reused": 0,
"output_tokens": 256,
"prompt_total": 16384,
"prompt_read": 16384,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 5458.9,
"decode_ms": 3259.5,
"decode_tok_s": 78.5,
"hit_rate": 0.868,
"pcie_share": 0.086,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 217,
"drafts_accepted": 158
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system's ability to handle a large number of deterministic integer transforms. The code consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a linear transformation on an input integer and return the result modulo a large prime number.\n\n### Deterministic Integer Transforms\n\nAt the core of this module is the concept of a deterministic integer transform. Each function takes a single integer argument, `value`, and applies a linear transformation of the form $f(x) = (ax + b) \\pmod m$. Here, $a$ is the multiplier, $b$ is the additive constant, and $m$ is the modulus, which is consistently set to `100003` across all functions.\n\nThe multiplier $a$ and the additive constant $b$ follow a specific pattern based on the function's index. For the first 97 functions (indices 0 to 96), the multiplier $a$ is equal to the index plus one ($i + 1$), and the additive constant $b$ is equal to the index ($i$). For example, `task_00000"
},
{
"label": "tokens-16384-run-2",
"expected_prompt_tokens": 16384,
"request_sha256": "d77a390c17eb10efc0a7a0117c5c9ed46fa24b12d8c1fe005e2253f0472dfd15",
"client_ttft_s": 5.4802596919998905,
"client_elapsed_s": 8.70739652499924,
"finish_reason": "length",
"usage": {
"prompt_tokens": 16384,
"completion_tokens": 256,
"total_tokens": 16640,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412675.3038552,
"duration_s": 8.7,
"finish": "length",
"prompt_tokens": 16384,
"reused": 0,
"output_tokens": 256,
"prompt_total": 16384,
"prompt_read": 16384,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 5430.9,
"decode_ms": 3255.8,
"decode_tok_s": 78.6,
"hit_rate": 0.853,
"pcie_share": 0.097,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 204,
"drafts_accepted": 160
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system's ability to handle a large number of deterministic integer transforms. The code consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a linear transformation on an input integer and return the result modulo a large prime number.\n\n### Deterministic Integer Transforms\n\nAt the core of each function is a linear transformation of the form $f(x) = (ax + b) \\pmod m$. In this specific module, the modulus $m$ is consistently set to `100003`, which is a prime number. The coefficients $a$ and $b$ vary for each function. For example, `task_00000` implements $f(x) = (1x + 0) \\pmod{100003}$, while `task_00001` implements $f(x) = (2x + 1) \\pmod{100003}$.\n\nThese transforms are deterministic, meaning that for a given input `value`, the output will always be the same. This property is crucial for benchmarking, as it allows for"
},
{
"label": "tokens-16384-run-3",
"expected_prompt_tokens": 16384,
"request_sha256": "7664e759d262ff5e9dbbef7e55d09267244629ba14eff0c871954813fd5e36b2",
"client_ttft_s": 5.539215562000209,
"client_elapsed_s": 9.241405829000541,
"finish_reason": "length",
"usage": {
"prompt_tokens": 16384,
"completion_tokens": 256,
"total_tokens": 16640,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412684.8498452,
"duration_s": 9.2,
"finish": "length",
"prompt_tokens": 16384,
"reused": 0,
"output_tokens": 256,
"prompt_total": 16384,
"prompt_read": 16384,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 5466.4,
"decode_ms": 3740.9,
"decode_tok_s": 68.4,
"hit_rate": 0.855,
"pcie_share": 0.093,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 232,
"drafts_accepted": 143
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system's ability to handle a large volume of deterministic integer transforms. The code consists of a series of functions, named sequentially from `task_00000` to `task_00444` (and potentially beyond, though the snippet cuts off), each performing a specific linear transformation on an input integer `value`.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of each function is a linear congruential generator (LCG) style operation: `(value * multiplier + addend) % 100003`. This structure is fundamental in computer science, particularly in pseudo-random number generation and cryptographic hashing, though here it is used for deterministic testing.\n\nThe modulus `100003` is a prime number. Choosing a prime modulus ensures that the multiplicative group of integers modulo $p$ is cyclic, which has implications for the periodicity of the sequence if these functions were chained. However, in this context, the modulus serves primarily to bound the output range to $[0, 100002]$, preventing integer overflow issues in languages with fixed-width integers (though Python handles arbitrary"
},
{
"label": "tokens-32768-run-1",
"expected_prompt_tokens": 32768,
"request_sha256": "e37cfc2ab9867d91130927440df24a57255a736b8d0d829d07d828e22e3de572",
"client_ttft_s": 10.702315700999861,
"client_elapsed_s": 14.148115566999877,
"finish_reason": "length",
"usage": {
"prompt_tokens": 32768,
"completion_tokens": 256,
"total_tokens": 33024,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412695.0004866,
"duration_s": 14.1,
"finish": "length",
"prompt_tokens": 32768,
"reused": 0,
"output_tokens": 256,
"prompt_total": 32768,
"prompt_read": 32768,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 10622.6,
"decode_ms": 3480.3,
"decode_tok_s": 73.6,
"hit_rate": 0.866,
"pcie_share": 0.086,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 214,
"drafts_accepted": 148
},
"text": "This synthetic Python module presents a highly repetitive, programmatic structure that serves as a benchmark for evaluating code generation, static analysis, and execution performance. The module consists of a series of functions, each named with a specific pattern (`task_XXXXX`), that perform a deterministic integer transform on an input value. Below is a detailed analysis of the code, focusing on its mathematical properties, structural design, and implications for software engineering practices.\n\n### 1. Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of every function in this module is the expression:\n`return (value * multiplier + offset) % 100003`\n\nThis represents a linear congruential generator (LCG) step, a fundamental component in pseudo-random number generation and cryptographic hashing. The modulus `100003` is a prime number. Choosing a prime modulus is critical in modular arithmetic because it ensures that the multiplicative group of integers modulo $p$ is cyclic. This property guarantees that for any non-zero multiplier, there exists a modular inverse, allowing the transformation to be bijective (reversible) if the multiplier is not a multiple of the modulus.\n\nThe parameters `multiplier` and `offset` vary across the functions."
},
{
"label": "tokens-32768-run-2",
"expected_prompt_tokens": 32768,
"request_sha256": "ed2dfaa11aecad9f4563f33bb5f5d4b8704486508700b8fa572722cc1225ee26",
"client_ttft_s": 10.873208201000125,
"client_elapsed_s": 14.419331159999274,
"finish_reason": "length",
"usage": {
"prompt_tokens": 32768,
"completion_tokens": 256,
"total_tokens": 33024,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412710.0482898,
"duration_s": 14.4,
"finish": "length",
"prompt_tokens": 32768,
"reused": 0,
"output_tokens": 256,
"prompt_total": 32768,
"prompt_read": 32768,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 10797.0,
"decode_ms": 3578.3,
"decode_tok_s": 71.5,
"hit_rate": 0.866,
"pcie_share": 0.084,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 221,
"drafts_accepted": 146
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance and correctness of a system's ability to handle a large volume of deterministic integer transforms. The code consists of a series of functions, named sequentially from `task_00000` to `task_00888` (and potentially beyond, though the snippet cuts off), each performing a specific linear transformation on an input integer.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of each function is a linear congruential generator (LCG) style transformation: `(value * multiplier + addend) % 100003`. This formula is a fundamental component of many pseudorandom number generators and cryptographic hash functions. The constant `100003` is a prime number, which is significant in modular arithmetic. When the modulus is prime, the multiplicative group of integers modulo $p$ is cyclic, meaning that for any non-zero multiplier, the operation is invertible. This ensures that the transformation is a bijection (a one-to-one mapping) over the set of integers modulo 100003, provided the multiplier is not a multiple of the modulus.\n\nThe multipliers and addends follow a specific"
},
{
"label": "tokens-32768-run-3",
"expected_prompt_tokens": 32768,
"request_sha256": "2a3c7342622e80c3cd8b37e062f0a2f64640c119ece8cccbf168639041eac079",
"client_ttft_s": 10.945066608000161,
"client_elapsed_s": 14.549754298999687,
"finish_reason": "length",
"usage": {
"prompt_tokens": 32768,
"completion_tokens": 256,
"total_tokens": 33024,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412725.3861685,
"duration_s": 14.5,
"finish": "length",
"prompt_tokens": 32768,
"reused": 0,
"output_tokens": 256,
"prompt_total": 32768,
"prompt_read": 32768,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 10862.1,
"decode_ms": 3642.9,
"decode_tok_s": 70.3,
"hit_rate": 0.87,
"pcie_share": 0.085,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 237,
"drafts_accepted": 149
},
"text": "This Python module presents a highly repetitive, synthetic collection of functions that perform deterministic integer transforms. Each function follows a strict pattern: it accepts an integer `value`, applies a linear transformation of the form `(value * multiplier + offset) % modulus`, and returns the result. The modulus is consistently set to `100003`, which is a prime number. This choice of modulus is significant because it ensures that the multiplicative group of integers modulo 100003 is cyclic, meaning that for any non-zero multiplier, the transformation is bijective (a permutation) over the set of integers modulo 100003. This property is often desirable in cryptographic contexts or pseudo-random number generation, although here it appears to be used for benchmarking or synthetic data generation.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nThe core operation in each function is a linear congruential generator (LCG) step, defined by the formula $f(x) = (ax + c) \\pmod m$. In this module, $m = 100003$. The multiplier $a$ and the increment $c$ vary per function. For example, `task_00000` uses $a"
},
{
"label": "tokens-65024-run-1",
"expected_prompt_tokens": 65024,
"request_sha256": "72c4451a1318466e317f3f4bb03d353136ae0b70609402b9ff0e9aaa92fdb846",
"client_ttft_s": 21.761700648999977,
"client_elapsed_s": 25.203380353000284,
"finish_reason": "length",
"usage": {
"prompt_tokens": 65024,
"completion_tokens": 256,
"total_tokens": 65280,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412741.4501984,
"duration_s": 25.1,
"finish": "length",
"prompt_tokens": 65024,
"reused": 0,
"output_tokens": 256,
"prompt_total": 65024,
"prompt_read": 65024,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 21649.0,
"decode_ms": 3469.9,
"decode_tok_s": 73.8,
"hit_rate": 0.847,
"pcie_share": 0.102,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 216,
"drafts_accepted": 159
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance, parsing, and execution capabilities of a Python interpreter or a code analysis tool. It consists of a massive sequence of function definitions, each named `task_XXXXX`, where `XXXXX` is a zero-padded integer index. Each function accepts a single integer argument `value` and returns a transformed integer based on a specific linear formula modulo a large prime number.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of every function in this module is the expression:\n`return (value * multiplier + offset) % 100003`\n\nThis is a classic **Linear Congruential Generator (LCG)** step, often used in pseudo-random number generation or cryptographic hashing. The operation is deterministic: for a given `value`, `multiplier`, and `offset`, the output is always the same.\n\n1. **Multiplier (`m`)**: The multiplier cycles through values from 1 to 97. For example, `task_00000` uses `1`, `task_00001` uses `2`, ..., `task_00096` uses `97`. Then `task"
},
{
"label": "tokens-65024-run-2",
"expected_prompt_tokens": 65024,
"request_sha256": "9673623f3990c86990a74f21aca030f7294d38726667787e531c4db5a2861f05",
"client_ttft_s": 21.58159749599963,
"client_elapsed_s": 25.028096803999688,
"finish_reason": "length",
"usage": {
"prompt_tokens": 65024,
"completion_tokens": 256,
"total_tokens": 65280,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412768.1831992,
"duration_s": 25.0,
"finish": "length",
"prompt_tokens": 65024,
"reused": 0,
"output_tokens": 256,
"prompt_total": 65024,
"prompt_read": 65024,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 21476.3,
"decode_ms": 3473.4,
"decode_tok_s": 73.7,
"hit_rate": 0.865,
"pcie_share": 0.086,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 219,
"drafts_accepted": 148
},
"text": "The provided Python module represents a synthetic benchmark designed to test the performance, parsing, and execution capabilities of a Python interpreter or a code analysis tool. It consists of a massive sequence of function definitions, each named `task_XXXXX`, where `XXXXX` is a zero-padded integer index. Each function accepts a single integer argument `value` and returns a transformed integer. The transformation follows a consistent mathematical pattern: `(value * multiplier + offset) % 100003`.\n\n### Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of each function is a linear congruential transformation. The formula `y = (ax + b) mod m` is a fundamental operation in computer science, often used in pseudo-random number generation (specifically, the Linear Congruential Generator method) and cryptographic hashing. Here, `m` is fixed at `100003`, which is a prime number. The choice of a prime modulus ensures that the multiplicative group of integers modulo `m` is cyclic, meaning that for any non-zero `a`, there exists a multiplicative inverse. This property is crucial if one were to reverse the transformation, though in this benchmark, the functions are strictly one-way mappings.\n\nThe"
},
{
"label": "tokens-65024-run-3",
"expected_prompt_tokens": 65024,
"request_sha256": "bc67c405a9842eca7c52d8322a7fe3f808813939a6240500d5c5ee1713d26747",
"client_ttft_s": 20.44145971299986,
"client_elapsed_s": 23.619267858999592,
"finish_reason": "length",
"usage": {
"prompt_tokens": 65024,
"completion_tokens": 256,
"total_tokens": 65280,
"prompt_tokens_details": {
"cached_tokens": 0
}
},
"engine": {
"projection": null,
"time": 1791412794.7614732,
"duration_s": 23.5,
"finish": "length",
"prompt_tokens": 65024,
"reused": 0,
"output_tokens": 256,
"prompt_total": 65024,
"prompt_read": 65024,
"reasoning_recoveries": 0,
"reasoning_repeat_coverage": 0.0,
"engine_generated": 256,
"prompt_ms": 20339.3,
"decode_ms": 3202.3,
"decode_tok_s": 79.9,
"hit_rate": 0.849,
"pcie_share": 0.098,
"ram_blobs": 0,
"file_blobs": 0,
"file_mb": 0,
"drafts_offered": 210,
"drafts_accepted": 151
},
"text": "The provided Python module consists of a large, repetitive collection of functions, each named with a specific pattern (`task_XXXXX`) and containing a single return statement. This code serves as a synthetic benchmark or test harness, likely generated programmatically to evaluate the performance, parsing capabilities, or memory usage of a code interpreter or compiler. Below is a detailed analysis of the code's structure, mathematical logic, and software engineering implications.\n\n### 1. Deterministic Integer Transforms and Modulo Arithmetic\n\nAt the core of every function in this module is a linear transformation followed by a modulo operation. The general form of the transformation for a given function `task_NNNNN` is:\n\n$$ f(x) = (x \\cdot A + B) \\pmod M $$\n\nWhere:\n* $x$ is the input integer (`value`).\n* $A$ is a multiplier specific to the function.\n* $B$ is an additive constant specific to the function.\n* $M$ is the modulus, which is consistently `100003` across all functions.\n\n**The Modulus (100003):**\nThe number 100003 is a prime number. In modular"
}
]
@@ -0,0 +1,187 @@
{
"4096": {
"prompt_tokens": {
"median": 4096,
"min": 4096,
"max": 4096
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 1.903633185000217,
"min": 1.8817809450001732,
"max": 1.9702199909997944
},
"client_elapsed_s": {
"median": 5.378847505000522,
"min": 5.126567950999743,
"max": 5.495010110000294
},
"prefill_tok_s": {
"median": 2194.1289907863725,
"min": 2113.8463126386955,
"max": 2221.6195693442533
},
"decode_tok_s": {
"median": 73.06353102346024,
"min": 72.12283420200028,
"max": 78.1512348505663
}
},
"8192": {
"prompt_tokens": {
"median": 8192,
"min": 8192,
"max": 8192
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 2.9813462499996604,
"min": 2.962772825999309,
"max": 3.009602217000065
},
"client_elapsed_s": {
"median": 6.332319787000415,
"min": 6.288063500000135,
"max": 6.335842665999735
},
"prefill_tok_s": {
"median": 2781.569386438491,
"min": 2760.293820338298,
"max": 2804.903102102308
},
"decode_tok_s": {
"median": 76.38370878711025,
"min": 75.23658378886734,
"max": 76.83995677752432
}
},
"16384": {
"prompt_tokens": {
"median": 16384,
"min": 16384,
"max": 16384
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 5.522646514999906,
"min": 5.4802596919998905,
"max": 5.539215562000209
},
"client_elapsed_s": {
"median": 8.740790816999834,
"min": 8.70739652499924,
"max": 9.241405829000541
},
"prefill_tok_s": {
"median": 3001.33726574951,
"min": 2997.219376554954,
"max": 3016.811209928373
},
"decode_tok_s": {
"median": 78.53965332106151,
"min": 68.43273009168917,
"max": 78.62890840960746
}
},
"32768": {
"prompt_tokens": {
"median": 32768,
"min": 32768,
"max": 32768
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 10.873208201000125,
"min": 10.702315700999861,
"max": 10.945066608000161
},
"client_elapsed_s": {
"median": 14.419331159999274,
"min": 14.148115566999877,
"max": 14.549754298999687
},
"prefill_tok_s": {
"median": 3034.917106603686,
"min": 3016.7278887139687,
"max": 3084.7438480221413
},
"decode_tok_s": {
"median": 71.54235251376352,
"min": 70.27368305470915,
"max": 73.5568772806942
}
},
"65024": {
"prompt_tokens": {
"median": 65024,
"min": 65024,
"max": 65024
},
"cached_tokens": {
"median": 0,
"min": 0,
"max": 0
},
"output_tokens": {
"median": 256,
"min": 256,
"max": 256
},
"client_ttft_s": {
"median": 21.58159749599963,
"min": 20.44145971299986,
"max": 21.761700648999977
},
"client_elapsed_s": {
"median": 25.028096803999688,
"min": 23.619267858999592,
"max": 25.203380353000284
},
"prefill_tok_s": {
"median": 3027.70961478467,
"min": 3003.5567462700355,
"max": 3196.9635139852408
},
"decode_tok_s": {
"median": 73.77734228652123,
"min": 73.70299994241952,
"max": 79.94254129844174
}
}
}
@@ -0,0 +1,208 @@
{"t": 0.014, "gpu_mem_used": 16801525760, "gpu_mem_total": 17094934528, "gpu_util": 4, "gpu_temp_c": 42, "gpu_power_w": 31.48, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31267274752, "ram_total": 58965274624, "disk_read_mb": 0.041184643510054846, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 1.017, "gpu_mem_used": 16801525760, "gpu_mem_total": 17094934528, "gpu_util": 4, "gpu_temp_c": 42, "gpu_power_w": 31.225, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31393992704, "ram_total": 58965274624, "disk_read_mb": 0.037441038476928534, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 2.019, "gpu_mem_used": 16800215040, "gpu_mem_total": 17094934528, "gpu_util": 13, "gpu_temp_c": 43, "gpu_power_w": 62.181, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31296532480, "ram_total": 58965274624, "disk_read_mb": 0.04121091829571413, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 3.021, "gpu_mem_used": 16800083968, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 49, "gpu_power_w": 138.325, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31296503808, "ram_total": 58965274624, "disk_read_mb": 0.03747611709548198, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 4.023, "gpu_mem_used": 16800280576, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 46, "gpu_power_w": 172.514, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31296733184, "ram_total": 58965274624, "disk_read_mb": 0.03727952315703681, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 76.7}
{"t": 5.025, "gpu_mem_used": 16800083968, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 50, "gpu_power_w": 139.721, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31296733184, "ram_total": 58965274624, "disk_read_mb": 0.10114107456904475, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 80.3}
{"t": 6.027, "gpu_mem_used": 16799559680, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 49, "gpu_power_w": 155.975, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31296733184, "ram_total": 58965274624, "disk_read_mb": 1.479601320092777, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 88.8}
{"t": 7.029, "gpu_mem_used": 16805982208, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 49, "gpu_power_w": 147.041, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31314100224, "ram_total": 58965274624, "disk_read_mb": 1.149647167028025, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 8.031, "gpu_mem_used": 16806178816, "gpu_mem_total": 17094934528, "gpu_util": 34, "gpu_temp_c": 44, "gpu_power_w": 98.337, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31314239488, "ram_total": 58965274624, "disk_read_mb": 0.037477797310172006, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 9.032, "gpu_mem_used": 16805982208, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 52, "gpu_power_w": 179.698, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31314239488, "ram_total": 58965274624, "disk_read_mb": 0.04122984936408795, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 10.034, "gpu_mem_used": 16809914368, "gpu_mem_total": 17094934528, "gpu_util": 97, "gpu_temp_c": 48, "gpu_power_w": 154.698, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31314239488, "ram_total": 58965274624, "disk_read_mb": 0.09360820077313609, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 70.9}
{"t": 11.036, "gpu_mem_used": 16809914368, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 50, "gpu_power_w": 155.524, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313625088, "ram_total": 58965274624, "disk_read_mb": 1.363508766314307, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 78.7}
{"t": 12.038, "gpu_mem_used": 16805326848, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 50, "gpu_power_w": 158.438, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313625088, "ram_total": 58965274624, "disk_read_mb": 2.06065476189115, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 85.0}
{"t": 13.041, "gpu_mem_used": 16804081664, "gpu_mem_total": 17094934528, "gpu_util": 24, "gpu_temp_c": 51, "gpu_power_w": 141.043, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313362944, "ram_total": 58965274624, "disk_read_mb": 2.0672233987476387, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 14.042, "gpu_mem_used": 16801329152, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 49, "gpu_power_w": 140.231, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313584128, "ram_total": 58965274624, "disk_read_mb": 0.037479906364286664, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 15.045, "gpu_mem_used": 16799428608, "gpu_mem_total": 17094934528, "gpu_util": 80, "gpu_temp_c": 48, "gpu_power_w": 173.939, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313584128, "ram_total": 58965274624, "disk_read_mb": 0.04117799066741274, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 56.0}
{"t": 16.047, "gpu_mem_used": 16799428608, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 50, "gpu_power_w": 147.283, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313584128, "ram_total": 58965274624, "disk_read_mb": 0.2472489443816547, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 70.3}
{"t": 17.049, "gpu_mem_used": 16799428608, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 49, "gpu_power_w": 155.315, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313321984, "ram_total": 58965274624, "disk_read_mb": 0.9665879979118214, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 73.9}
{"t": 18.051, "gpu_mem_used": 16801067008, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 50, "gpu_power_w": 160.822, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313321984, "ram_total": 58965274624, "disk_read_mb": 3.0424810025147027, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 84.4}
{"t": 19.054, "gpu_mem_used": 16802377728, "gpu_mem_total": 17094934528, "gpu_util": 46, "gpu_temp_c": 44, "gpu_power_w": 98.439, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313551360, "ram_total": 58965274624, "disk_read_mb": 0.44218733274841976, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 20.055, "gpu_mem_used": 16802377728, "gpu_mem_total": 17094934528, "gpu_util": 46, "gpu_temp_c": 44, "gpu_power_w": 98.439, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313551360, "ram_total": 58965274624, "disk_read_mb": 0.44218733274841976, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 21.057, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 52, "gpu_power_w": 183.352, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313551360, "ram_total": 58965274624, "disk_read_mb": 0.03748527437761152, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 22.059, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 55, "gpu_power_w": 240.467, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313518592, "ram_total": 58965274624, "disk_read_mb": 0.04123389615521099, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 55.3}
{"t": 23.062, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 97, "gpu_temp_c": 48, "gpu_power_w": 174.03, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31313518592, "ram_total": 58965274624, "disk_read_mb": 0.03746681863169276, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 74.4}
{"t": 24.064, "gpu_mem_used": 16802377728, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 158.89, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31312621568, "ram_total": 58965274624, "disk_read_mb": 0.24353504509455118, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 62.9}
{"t": 25.066, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 164.121, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31312621568, "ram_total": 58965274624, "disk_read_mb": 0.1872728099859934, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 87.9}
{"t": 26.066, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 155.36, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31311892480, "ram_total": 58965274624, "disk_read_mb": 0.1494747650714952, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 27.068, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 51, "gpu_power_w": 117.5, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31311835136, "ram_total": 58965274624, "disk_read_mb": 0.041279106254578, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 28.07, "gpu_mem_used": 16802377728, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 218.185, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31311577088, "ram_total": 58965274624, "disk_read_mb": 0.0374741284646243, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 29.072, "gpu_mem_used": 16803491840, "gpu_mem_total": 17094934528, "gpu_util": 94, "gpu_temp_c": 55, "gpu_power_w": 235.705, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31310970880, "ram_total": 58965274624, "disk_read_mb": 0.04118414470757095, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 57.4}
{"t": 30.074, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 142.824, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31310503936, "ram_total": 58965274624, "disk_read_mb": 0.07110193425784547, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 98.5}
{"t": 31.076, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 156.698, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320317952, "ram_total": 58965274624, "disk_read_mb": 0.21726144205672604, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 92.1}
{"t": 32.078, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 165.63, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320133632, "ram_total": 58965274624, "disk_read_mb": 1.4307004907005547, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 33.081, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 19, "gpu_temp_c": 46, "gpu_power_w": 108.06, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31319818240, "ram_total": 58965274624, "disk_read_mb": 0.7828026721202719, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 34.083, "gpu_mem_used": 16800935936, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 53, "gpu_power_w": 187.121, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320080384, "ram_total": 58965274624, "disk_read_mb": 0.037478045926161115, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 35.085, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 232.433, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320080384, "ram_total": 58965274624, "disk_read_mb": 0.041194932829429286, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 36.087, "gpu_mem_used": 16802902016, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 50, "gpu_power_w": 177.839, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31319822336, "ram_total": 58965274624, "disk_read_mb": 0.03743511859214342, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 54.1}
{"t": 37.089, "gpu_mem_used": 16802902016, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 50, "gpu_power_w": 136.82, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31319822336, "ram_total": 58965274624, "disk_read_mb": 0.7006064375680299, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 89.1}
{"t": 38.091, "gpu_mem_used": 16804409344, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 52, "gpu_power_w": 159.182, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31319818240, "ram_total": 58965274624, "disk_read_mb": 0.4158756953751876, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 91.0}
{"t": 39.093, "gpu_mem_used": 16802705408, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 52, "gpu_power_w": 166.68, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31319818240, "ram_total": 58965274624, "disk_read_mb": 3.4126254913737935, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 40.095, "gpu_mem_used": 16802508800, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 50, "gpu_power_w": 98.129, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31321563136, "ram_total": 58965274624, "disk_read_mb": 0.037373004436903744, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 41.098, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 56, "gpu_power_w": 204.951, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31321526272, "ram_total": 58965274624, "disk_read_mb": 0.0412242097076719, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 42.1, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 56, "gpu_power_w": 239.545, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320743936, "ram_total": 58965274624, "disk_read_mb": 0.037444906233466156, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 43.102, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 244.789, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320743936, "ram_total": 58965274624, "disk_read_mb": 0.04119725875839494, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 44.104, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 239.683, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320743936, "ram_total": 58965274624, "disk_read_mb": 0.03742725967308714, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 45.106, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 239.683, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320743936, "ram_total": 58965274624, "disk_read_mb": 0.03742725967308714, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 28.0}
{"t": 46.109, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 50, "gpu_power_w": 180.163, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320743936, "ram_total": 58965274624, "disk_read_mb": 0.04106126267301475, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 81.4}
{"t": 47.111, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 157.457, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320743936, "ram_total": 58965274624, "disk_read_mb": 0.09738756058088147, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 99.2}
{"t": 48.113, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 52, "gpu_power_w": 162.036, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31322718208, "ram_total": 58965274624, "disk_read_mb": 1.7569511196879415, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 99.7}
{"t": 49.115, "gpu_mem_used": 16801329152, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 163.016, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31328468992, "ram_total": 58965274624, "disk_read_mb": 2.664209442246192, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 50.117, "gpu_mem_used": 16802443264, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 46, "gpu_power_w": 99.673, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320498176, "ram_total": 58965274624, "disk_read_mb": 0.041228378000612166, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 51.119, "gpu_mem_used": 16801132544, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 210.304, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320186880, "ram_total": 58965274624, "disk_read_mb": 0.03745834690809742, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 52.121, "gpu_mem_used": 16801132544, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 244.156, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320092672, "ram_total": 58965274624, "disk_read_mb": 0.03746204692679284, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 53.123, "gpu_mem_used": 16801132544, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 243.73, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320059904, "ram_total": 58965274624, "disk_read_mb": 0.04118794720508889, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 54.125, "gpu_mem_used": 16801329152, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 238.932, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320059904, "ram_total": 58965274624, "disk_read_mb": 0.03745400545716564, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 55.127, "gpu_mem_used": 16801329152, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 50, "gpu_power_w": 181.861, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31326597120, "ram_total": 58965274624, "disk_read_mb": 0.041176560634007174, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 88.7}
{"t": 56.128, "gpu_mem_used": 16801329152, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 133.83, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31325741056, "ram_total": 58965274624, "disk_read_mb": 0.03745249860101751, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 92.9}
{"t": 57.13, "gpu_mem_used": 16801329152, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 53, "gpu_power_w": 159.63, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31325872128, "ram_total": 58965274624, "disk_read_mb": 0.10125553123171706, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 97.1}
{"t": 58.131, "gpu_mem_used": 16801525760, "gpu_mem_total": 17094934528, "gpu_util": 84, "gpu_temp_c": 53, "gpu_power_w": 154.23, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31325880320, "ram_total": 58965274624, "disk_read_mb": 0.04121708218259526, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 59.134, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 78, "gpu_temp_c": 46, "gpu_power_w": 74.555, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31326130176, "ram_total": 58965274624, "disk_read_mb": 0.03745463049557661, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 60.136, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 55, "gpu_power_w": 201.986, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31325904896, "ram_total": 58965274624, "disk_read_mb": 0.04121479171578662, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 61.137, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 238.027, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31327965184, "ram_total": 58965274624, "disk_read_mb": 0.03747417989207418, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 62.14, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 245.063, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31327989760, "ram_total": 58965274624, "disk_read_mb": 0.04120445479270655, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 63.142, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 241.505, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31327989760, "ram_total": 58965274624, "disk_read_mb": 0.0374741627495752, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 64.145, "gpu_mem_used": 16800280576, "gpu_mem_total": 17094934528, "gpu_util": 84, "gpu_temp_c": 50, "gpu_power_w": 208.648, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31327989760, "ram_total": 58965274624, "disk_read_mb": 0.03742396828830343, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 39.7}
{"t": 65.148, "gpu_mem_used": 16800280576, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 53, "gpu_power_w": 140.79, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31327727616, "ram_total": 58965274624, "disk_read_mb": 0.04119617580332703, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 71.8}
{"t": 66.15, "gpu_mem_used": 16800280576, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 52, "gpu_power_w": 156.814, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31327334400, "ram_total": 58965274624, "disk_read_mb": 0.22100894593116516, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 59.5}
{"t": 67.152, "gpu_mem_used": 16800280576, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 53, "gpu_power_w": 161.339, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31325011968, "ram_total": 58965274624, "disk_read_mb": 2.2436462323882402, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 79.0}
{"t": 68.154, "gpu_mem_used": 16801591296, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 49, "gpu_power_w": 128.246, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31324979200, "ram_total": 58965274624, "disk_read_mb": 2.6420686725770595, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 69.156, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 52, "gpu_power_w": 109.775, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31325151232, "ram_total": 58965274624, "disk_read_mb": 0.04119633588875087, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 70.158, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 215.414, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31325151232, "ram_total": 58965274624, "disk_read_mb": 0.037456908209313335, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 71.16, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 215.414, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31325151232, "ram_total": 58965274624, "disk_read_mb": 0.037456908209313335, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 72.161, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 246.759, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31325151232, "ram_total": 58965274624, "disk_read_mb": 0.041205792552576115, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 73.163, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 243.354, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31324434432, "ram_total": 58965274624, "disk_read_mb": 0.03746801817418421, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 74.165, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 244.783, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31324434432, "ram_total": 58965274624, "disk_read_mb": 0.03746978335494524, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 75.167, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 225.138, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31324434432, "ram_total": 58965274624, "disk_read_mb": 0.04120561355150347, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 76.17, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 245.657, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31324434432, "ram_total": 58965274624, "disk_read_mb": 0.03748090953429787, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 77.172, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 56, "gpu_power_w": 245.861, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31321849856, "ram_total": 58965274624, "disk_read_mb": 0.04113122743019064, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 78.174, "gpu_mem_used": 16803491840, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 61, "gpu_power_w": 252.293, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31321849856, "ram_total": 58965274624, "disk_read_mb": 0.03746508799859506, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 79.178, "gpu_mem_used": 16803491840, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 246.226, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31321849856, "ram_total": 58965274624, "disk_read_mb": 0.04122956640141727, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 80.18, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 95, "gpu_temp_c": 51, "gpu_power_w": 156.338, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31448907776, "ram_total": 58965274624, "disk_read_mb": 0.03745054671763696, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 53.1}
{"t": 81.182, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 53, "gpu_power_w": 138.629, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31448399872, "ram_total": 58965274624, "disk_read_mb": 1.7530402146709005, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 78.6}
{"t": 82.185, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 54, "gpu_power_w": 160.492, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31447605248, "ram_total": 58965274624, "disk_read_mb": 0.820241406955269, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 82.4}
{"t": 83.187, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 55, "gpu_power_w": 169.649, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31447916544, "ram_total": 58965274624, "disk_read_mb": 2.2211992270838876, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 84.189, "gpu_mem_used": 16802377728, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 47, "gpu_power_w": 54.847, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31212896256, "ram_total": 58965274624, "disk_read_mb": 0.03747842314292629, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 85.191, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 55, "gpu_power_w": 181.893, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31212896256, "ram_total": 58965274624, "disk_read_mb": 0.04122567134339591, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 86.192, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 236.101, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31212716032, "ram_total": 58965274624, "disk_read_mb": 0.03747441131734541, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 87.194, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 247.422, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31211552768, "ram_total": 58965274624, "disk_read_mb": 0.04128322891731855, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 88.196, "gpu_mem_used": 16801460224, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 244.833, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31210770432, "ram_total": 58965274624, "disk_read_mb": 0.037484614011887823, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 89.198, "gpu_mem_used": 16802836480, "gpu_mem_total": 17094934528, "gpu_util": 77, "gpu_temp_c": 55, "gpu_power_w": 229.475, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31325753344, "ram_total": 58965274624, "disk_read_mb": 0.03747273140623835, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 90.2, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 188.294, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31326380032, "ram_total": 58965274624, "disk_read_mb": 0.041220004546862185, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 91.201, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 240.879, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31320203264, "ram_total": 58965274624, "disk_read_mb": 0.0374339553666798, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 92.204, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 245.721, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31319728128, "ram_total": 58965274624, "disk_read_mb": 0.041215159304421004, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 93.206, "gpu_mem_used": 16802377728, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 242.304, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31318224896, "ram_total": 58965274624, "disk_read_mb": 0.03748005212069748, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 94.208, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 244.141, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31432966144, "ram_total": 58965274624, "disk_read_mb": 0.03743889957421935, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 95.21, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 111.896, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31431671808, "ram_total": 58965274624, "disk_read_mb": 0.041182582498727784, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 62.1}
{"t": 96.213, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 51, "gpu_power_w": 111.896, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31431671808, "ram_total": 58965274624, "disk_read_mb": 0.041182582498727784, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 81.8}
{"t": 97.215, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 55, "gpu_power_w": 154.377, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31429574656, "ram_total": 58965274624, "disk_read_mb": 0.15707833852074796, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 84.3}
{"t": 98.217, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 54, "gpu_power_w": 162.495, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31421956096, "ram_total": 58965274624, "disk_read_mb": 1.3769695995278945, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 99.219, "gpu_mem_used": 16800870400, "gpu_mem_total": 17094934528, "gpu_util": 6, "gpu_temp_c": 55, "gpu_power_w": 142.798, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31421984768, "ram_total": 58965274624, "disk_read_mb": 0.9406942187477125, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 100.221, "gpu_mem_used": 16801984512, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 53, "gpu_power_w": 85.187, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31189417984, "ram_total": 58965274624, "disk_read_mb": 0.037477934477206376, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 101.224, "gpu_mem_used": 16801984512, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 204.149, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31189647360, "ram_total": 58965274624, "disk_read_mb": 0.04120335261920804, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 102.225, "gpu_mem_used": 16801984512, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 242.949, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31189647360, "ram_total": 58965274624, "disk_read_mb": 0.03745574362933445, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 103.227, "gpu_mem_used": 16801984512, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 246.048, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31189352448, "ram_total": 58965274624, "disk_read_mb": 0.04119996168593762, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 104.229, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 245.765, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31189286912, "ram_total": 58965274624, "disk_read_mb": 0.03746120750660041, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 105.232, "gpu_mem_used": 16801984512, "gpu_mem_total": 17094934528, "gpu_util": 95, "gpu_temp_c": 54, "gpu_power_w": 213.95, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31304269824, "ram_total": 58965274624, "disk_read_mb": 0.04120736594470397, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 106.234, "gpu_mem_used": 16801984512, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 212.313, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31303667712, "ram_total": 58965274624, "disk_read_mb": 0.037354624983185404, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 107.236, "gpu_mem_used": 16801984512, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 249.413, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31303663616, "ram_total": 58965274624, "disk_read_mb": 0.037479006129226625, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 108.238, "gpu_mem_used": 16803295232, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 241.541, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31304417280, "ram_total": 58965274624, "disk_read_mb": 0.04122577507632158, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 109.241, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 242.329, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31304417280, "ram_total": 58965274624, "disk_read_mb": 0.0374686865240338, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 110.243, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 46, "gpu_temp_c": 61, "gpu_power_w": 204.595, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31427567616, "ram_total": 58965274624, "disk_read_mb": 0.04118053110326962, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 49.8}
{"t": 111.245, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 53, "gpu_power_w": 124.53, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31426965504, "ram_total": 58965274624, "disk_read_mb": 0.03744094436006927, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 94.0}
{"t": 112.247, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 56, "gpu_power_w": 167.619, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31426449408, "ram_total": 58965274624, "disk_read_mb": 0.21725056428970368, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 73.0}
{"t": 113.25, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 54, "gpu_power_w": 164.055, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31426084864, "ram_total": 58965274624, "disk_read_mb": 0.09360989083569224, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 72.3}
{"t": 114.252, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 49, "gpu_power_w": 120.098, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31426215936, "ram_total": 58965274624, "disk_read_mb": 0.04120558528831838, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 115.254, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 48, "gpu_power_w": 49.139, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31185842176, "ram_total": 58965274624, "disk_read_mb": 0.03619504854210215, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 116.255, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 56, "gpu_power_w": 176.494, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31185842176, "ram_total": 58965274624, "disk_read_mb": 0.15756349566529115, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 117.256, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 244.567, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31182135296, "ram_total": 58965274624, "disk_read_mb": 0.03747832026487364, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 118.259, "gpu_mem_used": 16801591296, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 241.405, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31182135296, "ram_total": 58965274624, "disk_read_mb": 0.04121209626613706, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 119.261, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 242.655, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31181729792, "ram_total": 58965274624, "disk_read_mb": 0.037475988513829106, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 120.263, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 77, "gpu_temp_c": 62, "gpu_power_w": 241.887, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31305138176, "ram_total": 58965274624, "disk_read_mb": 0.041220155389812524, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 121.265, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 77, "gpu_temp_c": 62, "gpu_power_w": 241.887, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31305138176, "ram_total": 58965274624, "disk_read_mb": 0.041220155389812524, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 122.267, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 56, "gpu_power_w": 182.497, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31309582336, "ram_total": 58965274624, "disk_read_mb": 0.06743393561041464, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 123.269, "gpu_mem_used": 16800542720, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 239.563, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31309582336, "ram_total": 58965274624, "disk_read_mb": 0.03748031791471809, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 124.27, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 245.93, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31309144064, "ram_total": 58965274624, "disk_read_mb": 3.3935291628440445, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 125.273, "gpu_mem_used": 16800870400, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 251.601, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31308455936, "ram_total": 58965274624, "disk_read_mb": 0.037474934177556256, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 126.276, "gpu_mem_used": 16800870400, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 248.109, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31348588544, "ram_total": 58965274624, "disk_read_mb": 0.037472517142693125, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 127.278, "gpu_mem_used": 16800870400, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 189.336, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31413772288, "ram_total": 58965274624, "disk_read_mb": 0.04122883071665016, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 128.28, "gpu_mem_used": 16800870400, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 239.19, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31413645312, "ram_total": 58965274624, "disk_read_mb": 0.037474402745988095, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 129.303, "gpu_mem_used": 16802181120, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 62, "gpu_power_w": 246.132, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31413645312, "ram_total": 58965274624, "disk_read_mb": 0.041211021954409115, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 130.306, "gpu_mem_used": 16804343808, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 244.046, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31413645312, "ram_total": 58965274624, "disk_read_mb": 0.037471822945636585, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 131.308, "gpu_mem_used": 16804147200, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 253.815, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31413645312, "ram_total": 58965274624, "disk_read_mb": 0.041218816697206916, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 132.31, "gpu_mem_used": 16804147200, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 183.889, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31535316992, "ram_total": 58965274624, "disk_read_mb": 0.06738199719515857, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 133.312, "gpu_mem_used": 16804343808, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 231.725, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31535316992, "ram_total": 58965274624, "disk_read_mb": 0.03747045176777102, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 134.314, "gpu_mem_used": 16801591296, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 251.021, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31535661056, "ram_total": 58965274624, "disk_read_mb": 0.04120258961055707, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 135.316, "gpu_mem_used": 16801591296, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 239.217, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31535403008, "ram_total": 58965274624, "disk_read_mb": 0.03748101242656613, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 136.318, "gpu_mem_used": 16801591296, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 246.969, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31535403008, "ram_total": 58965274624, "disk_read_mb": 0.04122043822332007, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 137.321, "gpu_mem_used": 16801591296, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 53, "gpu_power_w": 141.997, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31662776320, "ram_total": 58965274624, "disk_read_mb": 0.10111416487006895, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 60.0}
{"t": 138.324, "gpu_mem_used": 16803098624, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 55, "gpu_power_w": 136.98, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31658565632, "ram_total": 58965274624, "disk_read_mb": 2.2096166013832046, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 80.9}
{"t": 139.326, "gpu_mem_used": 16802902016, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 57, "gpu_power_w": 163.706, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31657574400, "ram_total": 58965274624, "disk_read_mb": 1.513319474678687, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 79.7}
{"t": 140.328, "gpu_mem_used": 16802902016, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 56, "gpu_power_w": 161.154, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31657803776, "ram_total": 58965274624, "disk_read_mb": 2.4539632639079763, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 141.329, "gpu_mem_used": 16802705408, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 49, "gpu_power_w": 75.358, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31657271296, "ram_total": 58965274624, "disk_read_mb": 0.13115512986860015, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 142.331, "gpu_mem_used": 16802705408, "gpu_mem_total": 17094934528, "gpu_util": 96, "gpu_temp_c": 49, "gpu_power_w": 79.879, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31228694528, "ram_total": 58965274624, "disk_read_mb": 0.0374613274214676, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 143.333, "gpu_mem_used": 16802902016, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 56, "gpu_power_w": 202.074, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31228669952, "ram_total": 58965274624, "disk_read_mb": 0.037469971879225204, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 144.335, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 57, "gpu_power_w": 243.561, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31228219392, "ram_total": 58965274624, "disk_read_mb": 0.04117642892539948, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 145.337, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 236.932, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31228219392, "ram_total": 58965274624, "disk_read_mb": 0.037457070913752256, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 146.338, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 245.72, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31228219392, "ram_total": 58965274624, "disk_read_mb": 0.0409792043453091, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 147.342, "gpu_mem_used": 16800739328, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 245.72, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31228219392, "ram_total": 58965274624, "disk_read_mb": 0.0409792043453091, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 148.344, "gpu_mem_used": 16819810304, "gpu_mem_total": 17094934528, "gpu_util": 76, "gpu_temp_c": 58, "gpu_power_w": 229.871, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31302811648, "ram_total": 58965274624, "disk_read_mb": 0.03745798722304032, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 149.347, "gpu_mem_used": 16819875840, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 242.184, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31302148096, "ram_total": 58965274624, "disk_read_mb": 0.041205519341037264, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 150.349, "gpu_mem_used": 16809062400, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 247.55, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31302148096, "ram_total": 58965274624, "disk_read_mb": 0.03744014010802431, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 151.351, "gpu_mem_used": 16808865792, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 248.565, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31301599232, "ram_total": 58965274624, "disk_read_mb": 0.03744491479133556, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 152.353, "gpu_mem_used": 16819679232, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 240.732, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31303487488, "ram_total": 58965274624, "disk_read_mb": 1.3334951990136252, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 153.355, "gpu_mem_used": 16810962944, "gpu_mem_total": 17094934528, "gpu_util": 59, "gpu_temp_c": 54, "gpu_power_w": 214.163, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31418470400, "ram_total": 58965274624, "disk_read_mb": 0.03747043462868272, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 154.357, "gpu_mem_used": 16808472576, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 59, "gpu_power_w": 206.204, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31417659392, "ram_total": 58965274624, "disk_read_mb": 0.041216177276398855, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 155.359, "gpu_mem_used": 16807030784, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 249.923, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31417401344, "ram_total": 58965274624, "disk_read_mb": 0.03748246155268077, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 156.361, "gpu_mem_used": 16815288320, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 245.741, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31417401344, "ram_total": 58965274624, "disk_read_mb": 0.04120064924673662, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 157.363, "gpu_mem_used": 16817188864, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 246.018, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31420923904, "ram_total": 58965274624, "disk_read_mb": 0.03747707719971389, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 158.365, "gpu_mem_used": 16818630656, "gpu_mem_total": 17094934528, "gpu_util": 93, "gpu_temp_c": 58, "gpu_power_w": 227.418, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31537131520, "ram_total": 58965274624, "disk_read_mb": 0.03745237874266622, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 159.367, "gpu_mem_used": 16808521728, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 202.193, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31536967680, "ram_total": 58965274624, "disk_read_mb": 0.04120786530983868, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 160.369, "gpu_mem_used": 16807211008, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 245.15, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31536967680, "ram_total": 58965274624, "disk_read_mb": 0.03747715435308219, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 161.371, "gpu_mem_used": 16816975872, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 64, "gpu_power_w": 251.651, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31532838912, "ram_total": 58965274624, "disk_read_mb": 0.04121324603020881, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 162.373, "gpu_mem_used": 16816975872, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 252.324, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31532838912, "ram_total": 58965274624, "disk_read_mb": 0.03746274932769868, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 163.375, "gpu_mem_used": 16808390656, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 244.064, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31643361280, "ram_total": 58965274624, "disk_read_mb": 0.03744993037567876, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 32.0}
{"t": 164.377, "gpu_mem_used": 16817303552, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 54, "gpu_power_w": 112.622, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31643074560, "ram_total": 58965274624, "disk_read_mb": 0.15716006127188725, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 88.0}
{"t": 165.379, "gpu_mem_used": 16817303552, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 56, "gpu_power_w": 163.938, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31643074560, "ram_total": 58965274624, "disk_read_mb": 0.7001754204743758, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 78.4}
{"t": 166.381, "gpu_mem_used": 16817238016, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 57, "gpu_power_w": 169.781, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31642472448, "ram_total": 58965274624, "disk_read_mb": 1.7870144124244565, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 73.9}
{"t": 167.383, "gpu_mem_used": 16820121600, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 53, "gpu_power_w": 128.029, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31637315584, "ram_total": 58965274624, "disk_read_mb": 1.8622367337454893, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 168.385, "gpu_mem_used": 16820334592, "gpu_mem_total": 17094934528, "gpu_util": 3, "gpu_temp_c": 50, "gpu_power_w": 49.724, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31637315584, "ram_total": 58965274624, "disk_read_mb": 0.03747088881982023, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 169.387, "gpu_mem_used": 16809848832, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 56, "gpu_power_w": 164.089, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31170621440, "ram_total": 58965274624, "disk_read_mb": 0.04121646948134768, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 170.389, "gpu_mem_used": 16809586688, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 240.273, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31170621440, "ram_total": 58965274624, "disk_read_mb": 0.0374725771362388, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 171.391, "gpu_mem_used": 16809390080, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 244.817, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31170383872, "ram_total": 58965274624, "disk_read_mb": 0.0374616186464841, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 172.392, "gpu_mem_used": 16811749376, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 264.695, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31169871872, "ram_total": 58965274624, "disk_read_mb": 0.041215281835422904, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 173.395, "gpu_mem_used": 16811749376, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 65, "gpu_power_w": 264.695, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31169871872, "ram_total": 58965274624, "disk_read_mb": 0.041215281835422904, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 174.397, "gpu_mem_used": 16811814912, "gpu_mem_total": 17094934528, "gpu_util": 58, "gpu_temp_c": 57, "gpu_power_w": 241.258, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31284482048, "ram_total": 58965274624, "disk_read_mb": 0.03744327175213212, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 175.398, "gpu_mem_used": 16898912256, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 199.801, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31284473856, "ram_total": 58965274624, "disk_read_mb": 0.041222748175587354, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 176.4, "gpu_mem_used": 16890441728, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 245.74, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31284473856, "ram_total": 58965274624, "disk_read_mb": 0.03746669868166798, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 177.403, "gpu_mem_used": 16890441728, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 262.888, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31284215808, "ram_total": 58965274624, "disk_read_mb": 0.041275863545784115, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 178.405, "gpu_mem_used": 16881922048, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 60, "gpu_power_w": 259.14, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31284215808, "ram_total": 58965274624, "disk_read_mb": 0.037481544045618403, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 179.407, "gpu_mem_used": 16883691520, "gpu_mem_total": 17094934528, "gpu_util": 94, "gpu_temp_c": 60, "gpu_power_w": 217.034, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31403270144, "ram_total": 58965274624, "disk_read_mb": 0.03747907471704259, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 180.409, "gpu_mem_used": 16883691520, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 209.222, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31403270144, "ram_total": 58965274624, "disk_read_mb": 0.041200008778410964, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 181.412, "gpu_mem_used": 16882380800, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 259.146, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31402934272, "ram_total": 58965274624, "disk_read_mb": 0.03744370817035699, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 182.414, "gpu_mem_used": 16882380800, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 268.127, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31404306432, "ram_total": 58965274624, "disk_read_mb": 0.04121594163026448, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 183.417, "gpu_mem_used": 16882577408, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 62, "gpu_power_w": 255.265, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31403606016, "ram_total": 58965274624, "disk_read_mb": 0.03744684041141242, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 184.419, "gpu_mem_used": 16882380800, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 58, "gpu_power_w": 201.731, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31527510016, "ram_total": 58965274624, "disk_read_mb": 0.03748001782496942, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 185.421, "gpu_mem_used": 16882380800, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 222.936, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31527260160, "ram_total": 58965274624, "disk_read_mb": 0.04120673468911807, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 186.425, "gpu_mem_used": 16882380800, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 61, "gpu_power_w": 255.571, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31527260160, "ram_total": 58965274624, "disk_read_mb": 0.03747458274531511, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 187.426, "gpu_mem_used": 16882380800, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 63, "gpu_power_w": 265.255, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31526543360, "ram_total": 58965274624, "disk_read_mb": 0.041179138529241405, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 188.429, "gpu_mem_used": 16882577408, "gpu_mem_total": 17094934528, "gpu_util": 99, "gpu_temp_c": 64, "gpu_power_w": 254.765, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31526543360, "ram_total": 58965274624, "disk_read_mb": 0.037462783591831264, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "reading", "tok_s": null}
{"t": 189.431, "gpu_mem_used": 16882577408, "gpu_mem_total": 17094934528, "gpu_util": 97, "gpu_temp_c": 54, "gpu_power_w": 142.835, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31633154048, "ram_total": 58965274624, "disk_read_mb": 0.5875899903419427, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 72.2}
{"t": 190.434, "gpu_mem_used": 16882577408, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 57, "gpu_power_w": 156.968, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31633154048, "ram_total": 58965274624, "disk_read_mb": 3.5634089947513465, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 75.1}
{"t": 191.436, "gpu_mem_used": 16882577408, "gpu_mem_total": 17094934528, "gpu_util": 98, "gpu_temp_c": 57, "gpu_power_w": 165.855, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31633215488, "ram_total": 58965274624, "disk_read_mb": 3.188513034046474, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "generating", "tok_s": 99.7}
{"t": 192.437, "gpu_mem_used": 16893128704, "gpu_mem_total": 17094934528, "gpu_util": 43, "gpu_temp_c": 57, "gpu_power_w": 146.845, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482298368, "ram_total": 58965274624, "disk_read_mb": 1.513884498863981, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 193.439, "gpu_mem_used": 16893325312, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 50, "gpu_power_w": 49.117, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482298368, "ram_total": 58965274624, "disk_read_mb": 0.04120596213397425, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 194.441, "gpu_mem_used": 16887230464, "gpu_mem_total": 17094934528, "gpu_util": 1, "gpu_temp_c": 49, "gpu_power_w": 43.742, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482290176, "ram_total": 58965274624, "disk_read_mb": 0.037451274369672695, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 195.444, "gpu_mem_used": 16887230464, "gpu_mem_total": 17094934528, "gpu_util": 1, "gpu_temp_c": 48, "gpu_power_w": 34.467, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482290176, "ram_total": 58965274624, "disk_read_mb": 0.03743608515064231, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 196.446, "gpu_mem_used": 16887230464, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 47, "gpu_power_w": 33.82, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482290176, "ram_total": 58965274624, "disk_read_mb": 0.041176221956432585, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 197.448, "gpu_mem_used": 16882708480, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 47, "gpu_power_w": 33.723, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482032128, "ram_total": 58965274624, "disk_read_mb": 0.03744892030355934, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 198.45, "gpu_mem_used": 16884019200, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 47, "gpu_power_w": 33.7, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482548224, "ram_total": 58965274624, "disk_read_mb": 0.0411747638249506, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 199.452, "gpu_mem_used": 16884019200, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 47, "gpu_power_w": 33.7, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482548224, "ram_total": 58965274624, "disk_read_mb": 0.0411747638249506, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 200.454, "gpu_mem_used": 16884019200, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 47, "gpu_power_w": 33.421, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482548224, "ram_total": 58965274624, "disk_read_mb": 0.037436521401356115, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 201.456, "gpu_mem_used": 16882511872, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 46, "gpu_power_w": 29.82, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482548224, "ram_total": 58965274624, "disk_read_mb": 0.037469740508782545, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 202.458, "gpu_mem_used": 16882511872, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 46, "gpu_power_w": 29.607, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482548224, "ram_total": 58965274624, "disk_read_mb": 0.04117737912781383, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 203.461, "gpu_mem_used": 16882511872, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 46, "gpu_power_w": 28.539, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31482548224, "ram_total": 58965274624, "disk_read_mb": 0.03743756502274839, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 204.464, "gpu_mem_used": 16882708480, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 45, "gpu_power_w": 28.565, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31485947904, "ram_total": 58965274624, "disk_read_mb": 0.041194104221833394, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 205.466, "gpu_mem_used": 16882511872, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 45, "gpu_power_w": 28.604, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31485816832, "ram_total": 58965274624, "disk_read_mb": 0.037445436828766436, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 206.467, "gpu_mem_used": 16882511872, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 45, "gpu_power_w": 28.611, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31485816832, "ram_total": 58965274624, "disk_read_mb": 0.041188945006368355, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
{"t": 207.469, "gpu_mem_used": 16882511872, "gpu_mem_total": 17094934528, "gpu_util": 0, "gpu_temp_c": 45, "gpu_power_w": 28.467, "gpu_pcie_gen": 5, "gpu_pcie_width": 8, "ram_used": 31486328832, "ram_total": 58965274624, "disk_read_mb": 0.03748242725254312, "vram_free_mib": 178, "expert_cache_mib": 7918, "state": "idle", "tok_s": null}
@@ -0,0 +1,71 @@
ggml_cuda_init: failed to initialize CUDA: no CUDA-capable device is detected
load_hparams: Qwen-VL models require at minimum 1024 image tokens to function correctly on grounding tasks
load_hparams: if you encounter problems with accuracy, try adding --image-min-tokens 1024
load_hparams: more info: https://github.com/ggml-org/llama.cpp/issues/16842
strata-vision: model files loaded in 1.8 s
strata-vision: on the CPU, 16 threads, no warm-up
[strata] 2026-10-07 22:42:28 engine started: /opt/strata/engine/strata --serve --pack /data/packs/coder-iq1_m --native /data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00001-of-00002.gguf --ple-gguf /data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00002-of-00002.gguf --expert-profile /opt/strata/data/expert-profile-coder.bin --expert-cache auto --prefill auto --spec 4 --spec-min-p 0.5 --mtp /data/mtp/rt --max-context 131072 --kv int8 --vision --vram-reserve-mib 700
strata generate: PCIe probe: 28.9 GB/s host->device (best of 28.9 28.9 28.9 28.9) -> pcie_frac 0.55 (default 0.55)
strata generate: native pack: /data/packs/coder-iq1_m experts (largest blob 2.66 MB), token embedding IQ4_XS in mapped host memory (322 MiB, 0.8 s)
strata generate: 1406 MiB of weights loaded from /data/packs/coder-iq1_m in 2.4 s (302 canonical tensors skipped: served natively)
strata generate: 300 native projection matrices, 2018.88 MiB of weights, in 2.7 s
strata generate: the SSD is kept awake while rows are read: one page of the table after 100 ms without a read, until 60 s after the last request (STRATA_SSD_KEEPALIVE=0 turns it off)
strata generate: profile /opt/strata/data/expert-profile-coder.bin: 12288 ranked pairs, built for 12288 slots
strata generate: PLE on, table 320001536 rows of /data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00002-of-00002.gguf
strata mtp: draft layer loaded, 950 MiB of VRAM (experts 675, dense 111), files read in 1.34 s (586 MiB/s)
strata generate: experimental native Q5_K head, 521472000 bytes, in 0.9 s
strata generate: GPU 0: NVIDIA GeForce RTX 5080, compute capability 12.0
strata generate: expert arena read through the file cache (buffered (not Windows))
strata generate: expert arena: cudaHostRegister PORTABLE ok; MAP_HUGETLB unavailable (needed 11992 2 MiB pages, vm.nr_hugepages=0); transparent huge pages requested (MADV_HUGEPAGE)
strata generate: loaded 23.42 GiB at 1.24 GiB/s
strata generate: CPU pool tasks/phase: 48 (automatic), participating threads: 16
strata generate: 15 pool workers on logical processors 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30, the host thread on 0 (draining too) (--host-core first)
strata generate: expert cache auto: 7.67 GiB free, 700 MiB reserved (+218 MiB for the draft head) -> 2733 slots
strata generate: expert cache 3554 slots, 6.78 GiB of VRAM; policy is
strata generate: the GPU computes the experts in the cache; it rounds differently from the CPU,
so a reply can differ slightly from a run without the cache (same quality:
bench/results/2026-09-27-cache-parity).
PROFILE, ranked by routing frequency, no eviction.
strata generate: pre-filled 3554 of 3554 slots from the profile in 0.4 s (18700 MB/s); slot 0 verified
strata generate: R4 hit path ON - resident experts are computed on the GPU
strata generate: 15 expert-pool workers + the host thread
strata generate: session is up (engine 0.1.40.3)
strata generate: token graph hit path: 3554 resident experts, decided on the device
strata serve: prompt chunk auto: 8192 tokens, a 384-slot ring
strata serve: the prompt path borrows 2172 CUDA0 cache slots (4.11 GiB)
strata hc: CUDA0: the hyper-connection read runs as staged (the norm per token and stream, the down projection's activations staged ahead by cp.async); checked bit for bit against the plain read on this card (STRATA_HC_SPLIT=1 or 0 for the earlier ones)
strata verify: window up to 6 tokens, 75.1 MiB of device buffers
strata mtp: draft head over 106299 tokens (212.9 MiB)
strata serve: 179 MiB of VRAM free with everything loaded - LOW: requests may stall; add --vram-reserve-mib 1033 to the config's args (or lower --max-context)
strata verify: capturing the 6-token window (39 MiB of VRAM free)
strata verify: captured the 6-token window (upload no error, sync no error)
strata verify: capturing the 1-token window (124 MiB of VRAM free)
strata verify: captured the 1-token window (upload no error, sync no error)
strata verify: capturing the 4-token window (63 MiB of VRAM free)
strata verify: captured the 4-token window (upload no error, sync no error)
strata serve: prompt 32343 tokens = 0 reused + 32343 read in 13363 ms (2420.4 tok/s), 9 generated in 281 ms (32.0 tok/s), drafts accepted 6 of 6, 2 checkpoints
strata serve: decode expert cache hit rate: 51.8% (1654 hits / 3193 lookups); 1127 more read by the GPU over PCIe or from another GPU (26.1% of all 4320 routed)
strata serve: prompt 32343 tokens = 0 reused + 32343 read in 10796 ms (2995.8 tok/s), 9 generated in 145 ms (61.9 tok/s), drafts accepted 6 of 6, 2 checkpoints
strata serve: decode expert cache hit rate: 57.3% (1855 hits / 3240 lookups); 1080 more read by the GPU over PCIe or from another GPU (25.0% of all 4320 routed)
strata serve: prompt 32344 tokens = 16384 reused + 15960 read in 5118 ms (3118.5 tok/s), 10 generated in 203 ms (49.3 tok/s), drafts accepted 9 of 9, 2 checkpoints
strata serve: decode expert cache hit rate: 62.8% (3047 hits / 4850 lookups); 1390 more read by the GPU over PCIe or from another GPU (22.3% of all 6240 routed)
strata serve: prompt 62627 tokens = 0 reused + 62627 read in 19687 ms (3181.1 tok/s), 10 generated in 203 ms (49.2 tok/s), drafts accepted 6 of 9, 4 checkpoints
strata serve: decode expert cache hit rate: 65.9% (3273 hits / 4970 lookups); 1270 more read by the GPU over PCIe or from another GPU (20.4% of all 6240 routed)
strata verify: capturing the 3-token window (108 MiB of VRAM free)
strata verify: captured the 3-token window (upload no error, sync no error)
strata serve: prompt 62625 tokens = 0 reused + 62625 read in 19539 ms (3205.2 tok/s), 9 generated in 192 ms (46.8 tok/s), drafts accepted 8 of 8, 4 checkpoints
strata serve: decode expert cache hit rate: 74.9% (3569 hits / 4763 lookups); 997 more read by the GPU over PCIe or from another GPU (17.3% of all 5760 routed)
strata verify: capturing the 2-token window (100 MiB of VRAM free)
strata verify: captured the 2-token window (upload no error, sync no error)
strata serve: prompt 62625 tokens = 16384 reused + 46241 read in 15015 ms (3079.7 tok/s), 9 generated in 224 ms (40.2 tok/s), drafts accepted 7 of 7, 4 checkpoints
strata serve: decode expert cache hit rate: 80.2% (3961 hits / 4939 lookups); 821 more read by the GPU over PCIe or from another GPU (14.3% of all 5760 routed)
strata serve: prompt 125919 tokens = 0 reused + 125919 read in 42208 ms (2983.3 tok/s), 9 generated in 172 ms (52.4 tok/s), drafts accepted 4 of 6, 6 checkpoints
strata serve: decode expert cache hit rate: 80.2% (3655 hits / 4559 lookups); 721 more read by the GPU over PCIe or from another GPU (13.7% of all 5280 routed)
strata serve: prompt 125919 tokens = 0 reused + 125919 read in 41025 ms (3069.3 tok/s), 9 generated in 282 ms (31.9 tok/s), drafts accepted 4 of 14, 6 checkpoints
strata serve: decode expert cache hit rate: 82.9% (6635 hits / 8001 lookups); 1119 more read by the GPU over PCIe or from another GPU (12.3% of all 9120 routed)
strata serve: suffix drafts: 1 windows, 1 of 5 drafts accepted
strata serve: prompt 125920 tokens = 16384 reused + 109536 read in 38581 ms (2839.1 tok/s), 10 generated in 154 ms (65.0 tok/s), drafts accepted 9 of 9, 6 checkpoints
strata serve: decode expert cache hit rate: 88.0% (5018 hits / 5702 lookups); 538 more read by the GPU over PCIe or from another GPU (8.6% of all 6240 routed)
strata serve: prompt 261 tokens = 0 reused + 261 read in 920 ms (283.6 tok/s), 10 generated in 153 ms (65.4 tok/s), drafts accepted 7 of 9, 1 checkpoints
strata serve: decode expert cache hit rate: 71.6% (3828 hits / 5343 lookups); 897 more read by the GPU over PCIe or from another GPU (14.4% of all 6240 routed)
@@ -0,0 +1,117 @@
ggml_cuda_init: failed to initialize CUDA: no CUDA-capable device is detected
load_hparams: Qwen-VL models require at minimum 1024 image tokens to function correctly on grounding tasks
load_hparams: if you encounter problems with accuracy, try adding --image-min-tokens 1024
load_hparams: more info: https://github.com/ggml-org/llama.cpp/issues/16842
strata-vision: model files loaded in 3.9 s
strata-vision: on the CPU, 16 threads, no warm-up
[strata] 2026-10-07 22:32:46 engine started: /opt/strata/engine/strata --serve --pack /data/packs/coder-iq1_m --native /data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00001-of-00002.gguf --ple-gguf /data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00002-of-00002.gguf --expert-profile /opt/strata/data/expert-profile-coder.bin --expert-cache auto --prefill auto --spec 4 --spec-min-p 0.5 --mtp /data/mtp/rt --max-context 65536 --kv int8 --vision --vram-reserve-mib 700
strata generate: PCIe probe: 28.9 GB/s host->device (best of 28.9 28.9 28.9 28.9) -> pcie_frac 0.55 (default 0.55)
strata generate: native pack: /data/packs/coder-iq1_m experts (largest blob 2.66 MB), token embedding IQ4_XS in mapped host memory (322 MiB, 0.7 s)
strata generate: 1406 MiB of weights loaded from /data/packs/coder-iq1_m in 1.6 s (302 canonical tensors skipped: served natively)
strata generate: 300 native projection matrices, 2018.88 MiB of weights, in 3.9 s
strata generate: the SSD is kept awake while rows are read: one page of the table after 100 ms without a read, until 60 s after the last request (STRATA_SSD_KEEPALIVE=0 turns it off)
strata generate: profile /opt/strata/data/expert-profile-coder.bin: 12288 ranked pairs, built for 12288 slots
strata generate: PLE on, table 320001536 rows of /data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00002-of-00002.gguf
strata mtp: draft layer loaded, 876 MiB of VRAM (experts 675, dense 111), files read in 1.29 s (609 MiB/s)
strata generate: experimental native Q5_K head, 521472000 bytes, in 0.5 s
strata generate: GPU 0: NVIDIA GeForce RTX 5080, compute capability 12.0
strata generate: expert arena read through the file cache (buffered (not Windows))
strata generate: expert arena: cudaHostRegister PORTABLE ok; MAP_HUGETLB unavailable (needed 11992 2 MiB pages, vm.nr_hugepages=0); transparent huge pages requested (MADV_HUGEPAGE)
strata generate: loaded 23.42 GiB at 0.85 GiB/s
strata generate: CPU pool tasks/phase: 48 (automatic), participating threads: 16
strata generate: 15 pool workers on logical processors 2,4,6,8,10,12,14,16,18,20,22,24,26,28,30, the host thread on 0 (draining too) (--host-core first)
strata generate: expert cache auto: 8.63 GiB free, 700 MiB reserved (+218 MiB for the draft head) -> 3119 slots
strata generate: expert cache 4060 slots, 7.73 GiB of VRAM; policy is
strata generate: the GPU computes the experts in the cache; it rounds differently from the CPU,
so a reply can differ slightly from a run without the cache (same quality:
bench/results/2026-09-27-cache-parity).
PROFILE, ranked by routing frequency, no eviction.
strata generate: pre-filled 4060 of 4060 slots from the profile in 0.5 s (17790 MB/s); slot 0 verified
strata generate: R4 hit path ON - resident experts are computed on the GPU
strata generate: 15 expert-pool workers + the host thread
strata generate: session is up (engine 0.1.40.3)
strata generate: token graph hit path: 4060 resident experts, decided on the device
strata serve: prompt chunk auto: 8192 tokens, a 384-slot ring
strata serve: the prompt path borrows 2178 CUDA0 cache slots (4.11 GiB)
strata hc: CUDA0: the hyper-connection read runs as staged (the norm per token and stream, the down projection's activations staged ahead by cp.async); checked bit for bit against the plain read on this card (STRATA_HC_SPLIT=1 or 0 for the earlier ones)
strata verify: window up to 6 tokens, 74.7 MiB of device buffers
strata mtp: draft head over 106299 tokens (212.9 MiB)
strata serve: 178 MiB of VRAM free with everything loaded - LOW: requests may stall; add --vram-reserve-mib 1034 to the config's args (or lower --max-context)
strata verify: capturing the 6-token window (178 MiB of VRAM free)
strata verify: captured the 6-token window (upload no error, sync no error)
strata verify: capturing the 1-token window (144 MiB of VRAM free)
strata verify: captured the 1-token window (upload no error, sync no error)
strata verify: capturing the 4-token window (112 MiB of VRAM free)
strata verify: captured the 4-token window (upload no error, sync no error)
strata serve: prompt 19 tokens = 0 reused + 19 read in 636 ms (29.9 tok/s), 2 generated in 242 ms (8.3 tok/s), drafts accepted 3 of 3, 1 checkpoints
strata serve: decode expert cache hit rate: 42.8% (706 hits / 1648 lookups); 752 more read by the GPU over PCIe or from another GPU (31.3% of all 2400 routed)
strata verify: capturing the 2-token window (73 MiB of VRAM free)
strata verify: captured the 2-token window (upload no error, sync no error)
strata verify: capturing the 3-token window (39 MiB of VRAM free)
strata verify: captured the 3-token window (upload no error, sync no error)
strata serve: prompt 4096 tokens = 0 reused + 4096 read in 2301 ms (1779.7 tok/s), 256 generated in 4280 ms (59.8 tok/s), drafts accepted 155 of 212, 1 checkpoints
strata serve: decode expert cache hit rate: 80.3% (105981 hits / 131930 lookups); 19270 more read by the GPU over PCIe or from another GPU (12.7% of all 151200 routed)
strata serve: suffix drafts: 3 windows, 5 of 9 drafts accepted
strata serve: prompt 4096 tokens = 0 reused + 4096 read in 1887 ms (2170.6 tok/s), 256 generated in 3686 ms (69.5 tok/s), drafts accepted 148 of 212, 1 checkpoints
strata serve: decode expert cache hit rate: 85.6% (119145 hits / 139204 lookups); 14876 more read by the GPU over PCIe or from another GPU (9.7% of all 154080 routed)
strata serve: prompt 4096 tokens = 0 reused + 4096 read in 1876 ms (2183.4 tok/s), 256 generated in 3799 ms (67.4 tok/s), drafts accepted 140 of 200, 1 checkpoints
strata serve: decode expert cache hit rate: 86.2% (119197 hits / 138209 lookups); 13471 more read by the GPU over PCIe or from another GPU (8.9% of all 151680 routed)
strata serve: prompt 8192 tokens = 0 reused + 8192 read in 3357 ms (2439.9 tok/s), 256 generated in 3336 ms (76.7 tok/s), drafts accepted 154 of 218, 1 checkpoints
strata serve: decode expert cache hit rate: 86.6% (121460 hits / 140328 lookups); 13272 more read by the GPU over PCIe or from another GPU (8.6% of all 153600 routed)
strata serve: prompt 8192 tokens = 0 reused + 8192 read in 2975 ms (2753.9 tok/s), 256 generated in 3387 ms (75.6 tok/s), drafts accepted 143 of 202, 1 checkpoints
strata serve: decode expert cache hit rate: 86.4% (119670 hits / 138552 lookups); 13128 more read by the GPU over PCIe or from another GPU (8.7% of all 151680 routed)
strata serve: suffix drafts: 1 windows, 1 of 2 drafts accepted
strata serve: prompt 8192 tokens = 0 reused + 8192 read in 2903 ms (2821.9 tok/s), 256 generated in 3386 ms (75.6 tok/s), drafts accepted 140 of 204, 1 checkpoints
strata serve: decode expert cache hit rate: 87.5% (123895 hits / 141613 lookups); 11987 more read by the GPU over PCIe or from another GPU (7.8% of all 153600 routed)
strata serve: prompt 16384 tokens = 0 reused + 16384 read in 5499 ms (2979.5 tok/s), 256 generated in 3313 ms (77.3 tok/s), drafts accepted 154 of 212, 1 checkpoints
strata serve: decode expert cache hit rate: 85.7% (117192 hits / 136810 lookups); 13910 more read by the GPU over PCIe or from another GPU (9.2% of all 150720 routed)
strata serve: suffix drafts: 1 windows, 1 of 2 drafts accepted
strata serve: prompt 16384 tokens = 0 reused + 16384 read in 5559 ms (2947.4 tok/s), 256 generated in 3259 ms (78.6 tok/s), drafts accepted 159 of 209, 1 checkpoints
strata serve: decode expert cache hit rate: 85.3% (113216 hits / 132736 lookups); 14144 more read by the GPU over PCIe or from another GPU (9.6% of all 146880 routed)
strata serve: prompt 16384 tokens = 0 reused + 16384 read in 5498 ms (2979.7 tok/s), 256 generated in 3502 ms (73.1 tok/s), drafts accepted 143 of 208, 1 checkpoints
strata serve: decode expert cache hit rate: 85.1% (118676 hits / 139465 lookups); 14615 more read by the GPU over PCIe or from another GPU (9.5% of all 154080 routed)
strata serve: prompt 32768 tokens = 0 reused + 32768 read in 10864 ms (3016.3 tok/s), 256 generated in 3313 ms (77.3 tok/s), drafts accepted 158 of 219, 2 checkpoints
strata serve: decode expert cache hit rate: 85.8% (118583 hits / 138239 lookups); 13921 more read by the GPU over PCIe or from another GPU (9.1% of all 152160 routed)
strata serve: prompt 32768 tokens = 0 reused + 32768 read in 10809 ms (3031.6 tok/s), 256 generated in 3467 ms (73.8 tok/s), drafts accepted 155 of 230, 2 checkpoints
strata serve: decode expert cache hit rate: 86.7% (125563 hits / 144825 lookups); 14055 more read by the GPU over PCIe or from another GPU (8.8% of all 158880 routed)
strata serve: prompt 32768 tokens = 0 reused + 32768 read in 10800 ms (3034.1 tok/s), 256 generated in 3624 ms (70.6 tok/s), drafts accepted 149 of 232, 2 checkpoints
strata serve: decode expert cache hit rate: 86.7% (130031 hits / 150051 lookups); 14109 more read by the GPU over PCIe or from another GPU (8.6% of all 164160 routed)
strata serve: prompt 19 tokens = 0 reused + 19 read in 442 ms (43.0 tok/s), 2 generated in 97 ms (20.6 tok/s), drafts accepted 3 of 3, 1 checkpoints
strata serve: decode expert cache hit rate: 43.6% (697 hits / 1597 lookups); 803 more read by the GPU over PCIe or from another GPU (33.5% of all 2400 routed)
strata verify: capturing the 5-token window (0 MiB of VRAM free)
strata verify: captured the 5-token window (upload no error, sync no error)
strata serve: prompt 4096 tokens = 0 reused + 4096 read in 1867 ms (2194.2 tok/s), 256 generated in 3504 ms (73.1 tok/s), drafts accepted 157 of 215, 1 checkpoints
strata serve: decode expert cache hit rate: 83.6% (112080 hits / 133989 lookups); 16731 more read by the GPU over PCIe or from another GPU (11.1% of all 150720 routed)
strata serve: suffix drafts: 1 windows, 3 of 4 drafts accepted
strata serve: prompt 4096 tokens = 0 reused + 4096 read in 1844 ms (2221.6 tok/s), 256 generated in 3276 ms (78.2 tok/s), drafts accepted 153 of 209, 1 checkpoints
strata serve: decode expert cache hit rate: 87.0% (119435 hits / 137329 lookups); 12911 more read by the GPU over PCIe or from another GPU (8.6% of all 150240 routed)
strata serve: prompt 4096 tokens = 0 reused + 4096 read in 1938 ms (2113.8 tok/s), 256 generated in 3549 ms (72.1 tok/s), drafts accepted 149 of 219, 1 checkpoints
strata serve: decode expert cache hit rate: 84.6% (120167 hits / 142031 lookups); 15889 more read by the GPU over PCIe or from another GPU (10.1% of all 157920 routed)
strata serve: suffix drafts: 1 windows, 1 of 3 drafts accepted
strata serve: prompt 8192 tokens = 0 reused + 8192 read in 2921 ms (2804.9 tok/s), 256 generated in 3403 ms (75.2 tok/s), drafts accepted 142 of 208, 1 checkpoints
strata serve: decode expert cache hit rate: 85.9% (121080 hits / 140950 lookups); 13610 more read by the GPU over PCIe or from another GPU (8.8% of all 154560 routed)
strata serve: prompt 8192 tokens = 0 reused + 8192 read in 2945 ms (2781.6 tok/s), 256 generated in 3332 ms (76.8 tok/s), drafts accepted 147 of 210, 1 checkpoints
strata serve: decode expert cache hit rate: 86.6% (121419 hits / 140283 lookups); 13317 more read by the GPU over PCIe or from another GPU (8.7% of all 153600 routed)
strata serve: prompt 8192 tokens = 0 reused + 8192 read in 2968 ms (2760.3 tok/s), 256 generated in 3352 ms (76.4 tok/s), drafts accepted 148 of 208, 1 checkpoints
strata serve: decode expert cache hit rate: 86.7% (120139 hits / 138571 lookups); 13109 more read by the GPU over PCIe or from another GPU (8.6% of all 151680 routed)
strata serve: suffix drafts: 1 windows, 2 of 3 drafts accepted
strata serve: prompt 16384 tokens = 0 reused + 16384 read in 5459 ms (3001.4 tok/s), 256 generated in 3259 ms (78.5 tok/s), drafts accepted 158 of 217, 1 checkpoints
strata serve: decode expert cache hit rate: 86.8% (120440 hits / 138688 lookups); 12992 more read by the GPU over PCIe or from another GPU (8.6% of all 151680 routed)
strata serve: prompt 16384 tokens = 0 reused + 16384 read in 5431 ms (3016.8 tok/s), 256 generated in 3256 ms (78.6 tok/s), drafts accepted 160 of 204, 1 checkpoints
strata serve: decode expert cache hit rate: 85.3% (110944 hits / 129998 lookups); 14002 more read by the GPU over PCIe or from another GPU (9.7% of all 144000 routed)
strata serve: prompt 16384 tokens = 0 reused + 16384 read in 5466 ms (2997.2 tok/s), 256 generated in 3741 ms (68.4 tok/s), drafts accepted 143 of 232, 1 checkpoints
strata serve: decode expert cache hit rate: 85.5% (128762 hits / 150603 lookups); 15477 more read by the GPU over PCIe or from another GPU (9.3% of all 166080 routed)
strata serve: prompt 32768 tokens = 0 reused + 32768 read in 10623 ms (3084.7 tok/s), 256 generated in 3480 ms (73.6 tok/s), drafts accepted 148 of 214, 2 checkpoints
strata serve: decode expert cache hit rate: 86.6% (122712 hits / 141748 lookups); 13292 more read by the GPU over PCIe or from another GPU (8.6% of all 155040 routed)
strata serve: prompt 32768 tokens = 0 reused + 32768 read in 10797 ms (3034.9 tok/s), 256 generated in 3578 ms (71.5 tok/s), drafts accepted 146 of 221, 2 checkpoints
strata serve: decode expert cache hit rate: 86.6% (125996 hits / 145459 lookups); 13421 more read by the GPU over PCIe or from another GPU (8.4% of all 158880 routed)
strata serve: prompt 32768 tokens = 0 reused + 32768 read in 10862 ms (3016.7 tok/s), 256 generated in 3643 ms (70.3 tok/s), drafts accepted 149 of 237, 2 checkpoints
strata serve: decode expert cache hit rate: 87.0% (132574 hits / 152458 lookups); 14102 more read by the GPU over PCIe or from another GPU (8.5% of all 166560 routed)
strata serve: prompt 65024 tokens = 0 reused + 65024 read in 21649 ms (3003.6 tok/s), 256 generated in 3470 ms (73.8 tok/s), drafts accepted 159 of 216, 4 checkpoints
strata serve: decode expert cache hit rate: 84.7% (115333 hits / 136235 lookups); 15445 more read by the GPU over PCIe or from another GPU (10.2% of all 151680 routed)
strata serve: prompt 65024 tokens = 0 reused + 65024 read in 21476 ms (3027.7 tok/s), 256 generated in 3473 ms (73.7 tok/s), drafts accepted 148 of 219, 4 checkpoints
strata serve: decode expert cache hit rate: 86.5% (124564 hits / 143936 lookups); 13504 more read by the GPU over PCIe or from another GPU (8.6% of all 157440 routed)
strata serve: suffix drafts: 1 windows, 1 of 3 drafts accepted
strata serve: prompt 65024 tokens = 0 reused + 65024 read in 20339 ms (3197.0 tok/s), 256 generated in 3202 ms (79.9 tok/s), drafts accepted 151 of 210, 4 checkpoints
strata serve: decode expert cache hit rate: 84.9% (115788 hits / 136448 lookups); 14752 more read by the GPU over PCIe or from another GPU (9.8% of all 151200 routed)
@@ -0,0 +1,62 @@
# Environment
## Host
- OS: Windows 10 Pro 26H2, build 26300.
- Virtualization: WSL 2.7.10.0, kernel 6.18.33.2-2; Docker Desktop 4.84.0, client and server
29.6.2, buildx v0.35.0-desktop.2. Nothing was run against a bare-metal Linux host.
- CPU: AMD Ryzen 9 9950X 16-Core Processor, 16 cores / 32 threads, AVX-512.
- RAM installed: 64 GB (Windows reports 65,080 MB).
- RAM visible inside the container: 58,965,274,624 B = 54.9 GiB. This is not Docker Desktop's
default: by default it caps the WSL2 VM at 50 % of host RAM (~31 GB), and Strata's setup reads
RAM from `/proc/meminfo`, so at 31 GB it silently selected the low-RAM mode for the Coder
("the GPU holds ~38 % of IQ1_M's experts, the other ~15 GB stay in RAM"). `%UserProfile%\.wslconfig`
with `memory=56GB` was added before the measured runs, and setup then chose the normal mode. The
file is attached as [wslconfig.txt](wslconfig.txt); a Docker Desktop restart (`wsl --shutdown`) is
needed for it to take effect.
- Storage: `C:` XPG MARS 980 PRO, 1908 GB, NVMe SSD — holds the WSL2 VHDX, and therefore the image
and the `/data` volume. `D:` ST4000DM004-2U9104, 3726 GB, HDD — not used by this benchmark.
Docker reports its data root as `/var/lib/docker` inside the WSL2 VM, so both the 13.1 GB image and
the 64 GB of model files sit on the NVMe.
- GPU: NVIDIA GeForce RTX 5080, 16,303 MiB reported VRAM, driver 617.14.
- PCIe: link Gen 5, width **x8**, while the card reports a maximum width of x16. The engine's own
startup transfer probe measured 28.9 GB/s host-to-device. See the report's limitations.
- GPU power limit 360 W (maximum 380 W). Clocks were not fixed, no thermal soak was run.
- Background workloads: Docker Desktop and the browser driving the harness. No other GPU work.
## Container
- Built from the repository's own Dockerfile, **unmodified**:
`docker build -t strata --build-arg CUDA_ARCHITECTURES=120 .`
(`120` is the RTX 50 architecture; the image keeps the engine inside it, so the container itself
never compiles.)
- Base image: `nvidia/cuda:13.0.0-devel-ubuntu24.04@sha256:1e8ac7a54c184a1af8ef2167f28fa98281892a835c981ebcddb1fad04bdd452d`.
- CUDA 13.0.48 (`nvcc` V13.0.48); GCC 13.3.0 (`Ubuntu 13.3.0-6ubuntu2~24.04`); Python 3.12.3.
- Strata commit `d5ea7133741e67743c0e886bb426c0ce8d69cf6c` ("Version 0.1.40.3"); engine 0.1.40.3,
`source=local`, CUDA architectures `[120]`, vision compiled for CUDA — see [BUILD.json](BUILD.json).
- Installed Python packages: [python-packages.txt](python-packages.txt).
## Launch
Both measured configurations were started the way the image's own entrypoint documents, from the
same `strata-data` volume, so only `CONTEXT` and `REINSTALL` differ between them:
```bash
docker run -d --name strata --gpus all --network strata-net \
-p 127.0.0.1:8080:8080 --ulimit memlock=-1 --stop-timeout 60 \
-v strata-data:/data \
-e FAMILY=coder -e MODEL=IQ1_M -e CONTEXT=131072 -e VISION=cpu -e GPU=0 \
strata
# the second configuration, same volume, settings changed for a model already set up
docker run -d --name strata --gpus all --network strata-net \
-p 127.0.0.1:8080:8080 --ulimit memlock=-1 --stop-timeout 60 \
-v strata-data:/data \
-e FAMILY=coder -e MODEL=IQ1_M -e CONTEXT=65536 -e VISION=cpu -e GPU=0 -e REINSTALL=1 \
strata
```
The port is published on `127.0.0.1` only, so no API key was configured (`api_key: false` in
`/health`). The first start downloaded the model, the MTP layer and the vision encoder (~65 GB,
59 minutes on this connection) and prepared the pack; the second configuration re-ran setup only to
change the recorded context and was serving 120 s after `docker run`.
@@ -0,0 +1,69 @@
#!/usr/bin/env python3
"""Correctness check for the vision path: render a code word, ask the model to read it.
This configuration runs the image encoder on the CPU (`VISION=cpu`), so this checks that
path. The picture is rendered with Pillow (no downloaded assets), sent the way an
OpenAI-compatible client sends one (an `image_url` with a `data:` URL), and the answer is
compared with the code that was drawn.
"""
import argparse
import base64
import io
import json
import urllib.request
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
CODE = "K7QX-4291"
QUESTION = ("Read the code printed in the image and reply with that code only, "
"exactly as written, with no other words.")
def render() -> Image.Image:
"""A code word in black on white, big enough to be unambiguous at the encoder's 300 tokens."""
image = Image.new("RGB", (900, 260), "white")
ImageDraw.Draw(image).text((40, 60), CODE, fill="black", font=ImageFont.load_default(size=110))
return image
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--url", default="http://127.0.0.1:8080")
parser.add_argument("--out", type=Path, default=Path("/data/bench64"))
args = parser.parse_args()
args.out.mkdir(parents=True, exist_ok=True)
image = render()
image.save(args.out / "image-check.png")
buffer = io.BytesIO()
image.save(buffer, format="PNG")
data_url = "data:image/png;base64," + base64.b64encode(buffer.getvalue()).decode()
body = json.dumps({
"model": "strata",
"messages": [{"role": "user", "content": [
{"type": "text", "text": QUESTION},
{"type": "image_url", "image_url": {"url": data_url}},
]}],
"temperature": 0,
"reasoning_effort": "none",
"max_tokens": 64,
}).encode()
request = urllib.request.Request(args.url + "/v1/chat/completions", data=body,
headers={"Content-Type": "application/json"})
with urllib.request.urlopen(request, timeout=900) as response:
payload = json.load(response)
answer = payload["choices"][0]["message"]["content"].strip()
with urllib.request.urlopen(args.url + "/metrics", timeout=30) as response:
engine = json.load(response)["requests"][0]
result = {"expected": CODE, "answer": answer, "found": CODE in answer,
"usage": payload.get("usage"), "engine": engine}
(args.out / "image-check.json").write_text(json.dumps(result, indent=2) + "\n")
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()
@@ -0,0 +1,54 @@
{
"measured": "2026-10-07",
"installer": "unmodified setup.py from the measured commit, run by the image's docker-entrypoint.sh",
"model": {
"family": "coder",
"title": "Qwen3.8-Flash-Next Coder (ISTA-DASLab's coding version: half of each layer's experts)",
"repository": "ISTA-DASLab/Qwen3.8-Flash-Next-GSQ-RCO-Coder-GGUF",
"revision": "5348543e0147355ac9cbcb031184a3546350988e",
"revision_date": "2026-09-29",
"revision_source": "setup.py HF_REVISIONS, the revision the installer pins",
"quantization": "IQ1_M (the Coder's only size; experts stored like IQ3_S, ~3.5 bits)"
},
"files": [
{
"path": "/data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00001-of-00002.gguf",
"role": "shard 1: the part loaded at startup (experts to RAM, dense weights to the GPU)",
"bytes": 29608446496,
"sha256_local": "e11083ba855e7666b48ea3f2db6a9c3a20c18751a012cc24f948de91b7087fad",
"sha256_published_lfs": "e11083ba855e7666b48ea3f2db6a9c3a20c18751a012cc24f948de91b7087fad",
"matches": true
},
{
"path": "/data/models/coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00002-of-00002.gguf",
"role": "shard 2: the PLE / n-gram table, stays on the SSD",
"bytes": 28800138432,
"sha256_local": "316b46f3a2dbd68c900f43136ab9449f9dcc3725dfd8c794847c204bc161e113",
"sha256_published_lfs": "316b46f3a2dbd68c900f43136ab9449f9dcc3725dfd8c794847c204bc161e113",
"matches": true
},
{
"path": "/data/models/mmproj-Qwen3.8-Flash-Next-BF16.gguf",
"role": "vision encoder (the Coder repository ships the original's mmproj)",
"bytes": 907543008,
"sha256_local": "b1a82259702816a5330d7bd7607cd9676b11780e79ff7348c21103ff3ce49bd0",
"sha256_published_lfs": "b1a82259702816a5330d7bd7607cd9676b11780e79ff7348c21103ff3ce49bd0",
"matches": true
}
],
"hash_command": "sha256sum inside the container, compared with the repository's published LFS oids from the Hugging Face API at the pinned revision",
"mtp_draft_layer": {
"source": "Qwen/Qwen3.8-Flash-Next (the BF16 checkpoint's MTP block), fetched by tools/mtp_fetch.py",
"inventory": "31 tensors, 5.214 GB, in 28 shards",
"files": ["mtp-manifest.json", "mtp-inventory.md", "mtp-q2_0.gguf.report.json"],
"note": "The manifest carries a SHA-256 per tensor, which the fetcher verifies against the checkpoint's own hashes; the full BF16 shards were not downloaded. The installer then built mtp-q2_0.gguf and the runtime pack under /data/mtp/rt (6.5 GB on disk including the tensors)."
},
"prepared_pack": {
"path": "/data/packs/coder-iq1_m",
"bytes_on_disk": "1.4 GB (the installer's own pack; the experts themselves are served natively from shard 1)"
},
"notes": [
"All three model files matched the published hashes byte for byte, so the numbers below are for the published IQ1_M, not for a re-quantized or truncated copy.",
"The download and the pack preparation were done by the unmodified installer in the official image; nothing was quantized or repacked by hand."
]
}
@@ -0,0 +1,53 @@
#!/usr/bin/env python3
"""Sample Strata's own /metrics once per second into JSONL.
Runs inside the container next to the benchmark. Every sample keeps the engine's
own view of memory (bytes), which is the only view available for VRAM inside the
container: nvidia-smi reports the whole GPU's allocation, not the container's.
"""
import argparse
import json
import time
import urllib.request
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--url", default="http://127.0.0.1:8080")
parser.add_argument("--out", default="/data/bench/telemetry.jsonl")
parser.add_argument("--seconds", type=int, default=1200)
args = parser.parse_args()
started = time.time()
with open(args.out, "w", encoding="utf-8") as sink:
while time.time() - started < args.seconds:
try:
with urllib.request.urlopen(args.url + "/metrics", timeout=10) as response:
metrics = json.load(response)
engine, hardware = metrics["engine"], metrics["hardware"]
live = metrics.get("live", {})
sink.write(json.dumps({
"t": round(time.time() - started, 3),
"gpu_mem_used": hardware["gpu_mem_used"],
"gpu_mem_total": hardware["gpu_mem_total"],
"gpu_util": hardware["gpu_util"],
"gpu_temp_c": hardware["gpu_temp"],
"gpu_power_w": hardware["gpu_power"],
"gpu_pcie_gen": hardware["gpu_pcie_gen"],
"gpu_pcie_width": hardware["gpu_pcie_width"],
"ram_used": hardware["ram_used"],
"ram_total": hardware["ram_total"],
"disk_read_mb": hardware.get("disk_read_mb"),
"vram_free_mib": engine["vram_free_mib"],
"expert_cache_mib": engine["expert_cache_mib"],
"state": live.get("state"),
"tok_s": live.get("tok_s"),
}) + "\n")
sink.flush()
except Exception as error: # a sample may race a restart; keep going
sink.write(json.dumps({"t": round(time.time() - started, 3), "error": str(error)}) + "\n")
sink.flush()
time.sleep(1)
if __name__ == "__main__":
main()
@@ -0,0 +1,37 @@
# MTP block in the BF16 checkpoint
31 tensors, 5.214 GB, in 28 shards.
| tensor | dtype | shape | MB |
|---|---|---|---:|
| `mtp.fc_embedding.weight` | BF16 | 2560x2560 | 13.1 |
| `mtp.fc_hidden.weight` | BF16 | 2560x2560 | 13.1 |
| `mtp.hyper_connection_mixer.hc_norm.weight` | BF16 | 10240 | 0.0 |
| `mtp.hyper_connection_mixer.input_mix_weight_down.weight` | BF16 | 320x10240 | 6.6 |
| `mtp.hyper_connection_mixer.input_mix_weight_up.weight` | BF16 | 10240x320 | 6.6 |
| `mtp.layers.0.attn_hyper_connection.block_inject_weight.weight` | BF16 | 4x10240 | 0.1 |
| `mtp.layers.0.attn_hyper_connection.hc_norm.weight` | BF16 | 10240 | 0.0 |
| `mtp.layers.0.attn_hyper_connection.input_mix_weight_down.weight` | BF16 | 320x10240 | 6.6 |
| `mtp.layers.0.attn_hyper_connection.input_mix_weight_up.weight` | BF16 | 10240x320 | 6.6 |
| `mtp.layers.0.mlp.experts.down_proj` | BF16 | 512x2560x640 | 1677.7 |
| `mtp.layers.0.mlp.experts.gate_up_proj` | BF16 | 512x1280x2560 | 3355.4 |
| `mtp.layers.0.mlp.gate.weight` | BF16 | 512x2560 | 2.6 |
| `mtp.layers.0.mlp.shared_expert.down_proj.weight` | BF16 | 2560x640 | 3.3 |
| `mtp.layers.0.mlp.shared_expert.gate_proj.weight` | BF16 | 640x2560 | 3.3 |
| `mtp.layers.0.mlp.shared_expert.up_proj.weight` | BF16 | 640x2560 | 3.3 |
| `mtp.layers.0.mlp.shared_expert_gate.weight` | BF16 | 1x2560 | 0.0 |
| `mtp.layers.0.mlp_hyper_connection.block_inject_weight.weight` | BF16 | 4x10240 | 0.1 |
| `mtp.layers.0.mlp_hyper_connection.hc_norm.weight` | BF16 | 10240 | 0.0 |
| `mtp.layers.0.mlp_hyper_connection.input_mix_weight_down.weight` | BF16 | 320x10240 | 6.6 |
| `mtp.layers.0.mlp_hyper_connection.input_mix_weight_up.weight` | BF16 | 10240x320 | 6.6 |
| `mtp.layers.0.self_attn.indexer.index_qk_proj.weight` | BF16 | 640x2560 | 3.3 |
| `mtp.layers.0.self_attn.indexer.k_layernorm.weight` | BF16 | 128 | 0.0 |
| `mtp.layers.0.self_attn.indexer.q_layernorm.weight` | BF16 | 128 | 0.0 |
| `mtp.layers.0.self_attn.k_norm.weight` | BF16 | 256 | 0.0 |
| `mtp.layers.0.self_attn.k_proj.weight` | BF16 | 512x2560 | 2.6 |
| `mtp.layers.0.self_attn.o_proj.weight` | BF16 | 2560x6144 | 31.5 |
| `mtp.layers.0.self_attn.q_norm.weight` | BF16 | 256 | 0.0 |
| `mtp.layers.0.self_attn.q_proj.weight` | BF16 | 12288x2560 | 62.9 |
| `mtp.layers.0.self_attn.v_proj.weight` | BF16 | 512x2560 | 2.6 |
| `mtp.pre_fc_norm_embedding.weight` | BF16 | 2560 | 0.0 |
| `mtp.pre_fc_norm_hidden.weight` | BF16 | 10240 | 0.0 |
@@ -0,0 +1,429 @@
[
{
"name": "mtp.fc_embedding.weight",
"shard": "model-00120-of-00131.safetensors",
"dtype": "BF16",
"shape": [
2560,
2560
],
"start": 1935412640,
"end": 1948519839,
"bytes": 13107200,
"file": "tensors/mtp.fc_embedding.weight.bin",
"sha256": "241d6e87ded317a61b1aeb3ca4e28c53f1caba09ad5be66092e91fe5e3e14751"
},
{
"name": "mtp.fc_hidden.weight",
"shard": "model-00124-of-00131.safetensors",
"dtype": "BF16",
"shape": [
2560,
2560
],
"start": 1716599928,
"end": 1729707127,
"bytes": 13107200,
"file": "tensors/mtp.fc_hidden.weight.bin",
"sha256": "97c8e427ad0177e2c713ed24a397d815b523eda15ef453f1ae6463f6c70a8f96"
},
{
"name": "mtp.hyper_connection_mixer.hc_norm.weight",
"shard": "model-00037-of-00131.safetensors",
"dtype": "BF16",
"shape": [
10240
],
"start": 1742326680,
"end": 1742347159,
"bytes": 20480,
"file": "tensors/mtp.hyper_connection_mixer.hc_norm.weight.bin",
"sha256": "ce948a398e15aeaa403c424cda34e6eed296ab2570d591bb5ff3da642b255d64"
},
{
"name": "mtp.hyper_connection_mixer.input_mix_weight_down.weight",
"shard": "model-00041-of-00131.safetensors",
"dtype": "BF16",
"shape": [
320,
10240
],
"start": 1935412688,
"end": 1941966287,
"bytes": 6553600,
"file": "tensors/mtp.hyper_connection_mixer.input_mix_weight_down.weight.bin",
"sha256": "c633d2841fda463e82045e0b93fb8cb8d511ec0c9eda616020f01aca18d71947"
},
{
"name": "mtp.hyper_connection_mixer.input_mix_weight_up.weight",
"shard": "model-00043-of-00131.safetensors",
"dtype": "BF16",
"shape": [
10240,
320
],
"start": 1832518416,
"end": 1839072015,
"bytes": 6553600,
"file": "tensors/mtp.hyper_connection_mixer.input_mix_weight_up.weight.bin",
"sha256": "6565285f0ba2923703252763cfc11d8a9bda40ab42e7548e12464b04dbdbec13"
},
{
"name": "mtp.layers.0.attn_hyper_connection.block_inject_weight.weight",
"shard": "model-00047-of-00131.safetensors",
"dtype": "BF16",
"shape": [
4,
10240
],
"start": 1716599984,
"end": 1716681903,
"bytes": 81920,
"file": "tensors/mtp.layers.0.attn_hyper_connection.block_inject_weight.weight.bin",
"sha256": "c8afff64e7f54412d02120097c4255033c55245e1c1eed84cc630d428ccb864c"
},
{
"name": "mtp.layers.0.attn_hyper_connection.hc_norm.weight",
"shard": "model-00049-of-00131.safetensors",
"dtype": "BF16",
"shape": [
10240
],
"start": 1935412672,
"end": 1935433151,
"bytes": 20480,
"file": "tensors/mtp.layers.0.attn_hyper_connection.hc_norm.weight.bin",
"sha256": "1fb619aeaaf637ccd70f46f1f8f8116e6a46448cb43026b246de8ee8286ed809"
},
{
"name": "mtp.layers.0.attn_hyper_connection.input_mix_weight_down.weight",
"shard": "model-00053-of-00131.safetensors",
"dtype": "BF16",
"shape": [
320,
10240
],
"start": 1832518424,
"end": 1839072023,
"bytes": 6553600,
"file": "tensors/mtp.layers.0.attn_hyper_connection.input_mix_weight_down.weight.bin",
"sha256": "e80ac8bf3e270e9d5a949ec7c913329dc8de017d69851334820fae7b8c86a7f5"
},
{
"name": "mtp.layers.0.attn_hyper_connection.input_mix_weight_up.weight",
"shard": "model-00057-of-00131.safetensors",
"dtype": "BF16",
"shape": [
10240,
320
],
"start": 1935412680,
"end": 1941966279,
"bytes": 6553600,
"file": "tensors/mtp.layers.0.attn_hyper_connection.input_mix_weight_up.weight.bin",
"sha256": "f80f1fd44e1183e7764ea496b11ff89ead9dd758f861d4e79a770bf54956b1a5"
},
{
"name": "mtp.layers.0.mlp.experts.down_proj",
"shard": "model-00062-of-00131.safetensors",
"dtype": "BF16",
"shape": [
512,
2560,
640
],
"start": 1832518400,
"end": 3510239999,
"bytes": 1677721600,
"file": "tensors/mtp.layers.0.mlp.experts.down_proj.bin",
"sha256": "539c46234f73bac70450f731f40e715f77ac32faf77def0f3f800e58aaabbbc0"
},
{
"name": "mtp.layers.0.mlp.experts.gate_up_proj",
"shard": "model-00060-of-00131.safetensors",
"dtype": "BF16",
"shape": [
512,
1280,
2560
],
"start": 115918328,
"end": 3471361527,
"bytes": 3355443200,
"file": "tensors/mtp.layers.0.mlp.experts.gate_up_proj.bin",
"sha256": "839e98f9642ebc884b178abd2090b6dc8b0bcd81ed92d7f7a08314c6a68f96d5"
},
{
"name": "mtp.layers.0.mlp.gate.weight",
"shard": "model-00066-of-00131.safetensors",
"dtype": "BF16",
"shape": [
512,
2560
],
"start": 1716599952,
"end": 1719221391,
"bytes": 2621440,
"file": "tensors/mtp.layers.0.mlp.gate.weight.bin",
"sha256": "f0d35fa41b360a08bc0c5b1e5766aa42df960291716ee189208b5d2599462c20"
},
{
"name": "mtp.layers.0.mlp.shared_expert.down_proj.weight",
"shard": "model-00076-of-00131.safetensors",
"dtype": "BF16",
"shape": [
2560,
640
],
"start": 1935412680,
"end": 1938689479,
"bytes": 3276800,
"file": "tensors/mtp.layers.0.mlp.shared_expert.down_proj.weight.bin",
"sha256": "d2ced8c81367cc494599d1a8cdc279c3dd6579b628ded05acd7495e99cee01d8"
},
{
"name": "mtp.layers.0.mlp.shared_expert.gate_proj.weight",
"shard": "model-00072-of-00131.safetensors",
"dtype": "BF16",
"shape": [
640,
2560
],
"start": 1832518528,
"end": 1835795327,
"bytes": 3276800,
"file": "tensors/mtp.layers.0.mlp.shared_expert.gate_proj.weight.bin",
"sha256": "f4a81109165853b3b64f36d809f98094b599763364070f5fa079200e1c386d4c"
},
{
"name": "mtp.layers.0.mlp.shared_expert.up_proj.weight",
"shard": "model-00072-of-00131.safetensors",
"dtype": "BF16",
"shape": [
640,
2560
],
"start": 1835795328,
"end": 1839072127,
"bytes": 3276800,
"file": "tensors/mtp.layers.0.mlp.shared_expert.up_proj.weight.bin",
"sha256": "172586861eea53efbff10afc43ded5b6e49c83879e9efc01e089c652bbb0a156"
},
{
"name": "mtp.layers.0.mlp.shared_expert_gate.weight",
"shard": "model-00070-of-00131.safetensors",
"dtype": "BF16",
"shape": [
1,
2560
],
"start": 1832518400,
"end": 1832523519,
"bytes": 5120,
"file": "tensors/mtp.layers.0.mlp.shared_expert_gate.weight.bin",
"sha256": "acdd306d9996d356e4667a16ff63af6fef086fc7f570f1bc00bbe882a2a93f6e"
},
{
"name": "mtp.layers.0.mlp_hyper_connection.block_inject_weight.weight",
"shard": "model-00078-of-00131.safetensors",
"dtype": "BF16",
"shape": [
4,
10240
],
"start": 1832518424,
"end": 1832600343,
"bytes": 81920,
"file": "tensors/mtp.layers.0.mlp_hyper_connection.block_inject_weight.weight.bin",
"sha256": "c5782dd92b479a1f8ef43d683fe9c917fd9e8fba81f23c1aae8817bfe4b476a6"
},
{
"name": "mtp.layers.0.mlp_hyper_connection.hc_norm.weight",
"shard": "model-00082-of-00131.safetensors",
"dtype": "BF16",
"shape": [
10240
],
"start": 1935412656,
"end": 1935433135,
"bytes": 20480,
"file": "tensors/mtp.layers.0.mlp_hyper_connection.hc_norm.weight.bin",
"sha256": "21a504876b5e7b788301557c68dfb757999430eba36c66ec8ab96a63604dbfd1"
},
{
"name": "mtp.layers.0.mlp_hyper_connection.input_mix_weight_down.weight",
"shard": "model-00086-of-00131.safetensors",
"dtype": "BF16",
"shape": [
320,
10240
],
"start": 1935412696,
"end": 1941966295,
"bytes": 6553600,
"file": "tensors/mtp.layers.0.mlp_hyper_connection.input_mix_weight_down.weight.bin",
"sha256": "b71240036dea954e034d5ae04e097bcd7ac51cb28a44e4c93d198af3447278a1"
},
{
"name": "mtp.layers.0.mlp_hyper_connection.input_mix_weight_up.weight",
"shard": "model-00088-of-00131.safetensors",
"dtype": "BF16",
"shape": [
10240,
320
],
"start": 1832518424,
"end": 1839072023,
"bytes": 6553600,
"file": "tensors/mtp.layers.0.mlp_hyper_connection.input_mix_weight_up.weight.bin",
"sha256": "40756866bf2a5e82c28e407f717b6fa07614d593f78e79c7ceb2cd4ffe6dda94"
},
{
"name": "mtp.layers.0.self_attn.indexer.index_qk_proj.weight",
"shard": "model-00090-of-00131.safetensors",
"dtype": "BF16",
"shape": [
640,
2560
],
"start": 1832518416,
"end": 1835795215,
"bytes": 3276800,
"file": "tensors/mtp.layers.0.self_attn.indexer.index_qk_proj.weight.bin",
"sha256": "2befafae6e944c1fc651fd73d4d527eb6f138a6c1679065b003128ee3150e859"
},
{
"name": "mtp.layers.0.self_attn.indexer.k_layernorm.weight",
"shard": "model-00094-of-00131.safetensors",
"dtype": "BF16",
"shape": [
128
],
"start": 1935412672,
"end": 1935412927,
"bytes": 256,
"file": "tensors/mtp.layers.0.self_attn.indexer.k_layernorm.weight.bin",
"sha256": "2db621f6a08b4085756fc69d60a4a1bd1d7fbf5d406456d2477075842efaae54"
},
{
"name": "mtp.layers.0.self_attn.indexer.q_layernorm.weight",
"shard": "model-00100-of-00131.safetensors",
"dtype": "BF16",
"shape": [
128
],
"start": 1716599968,
"end": 1716600223,
"bytes": 256,
"file": "tensors/mtp.layers.0.self_attn.indexer.q_layernorm.weight.bin",
"sha256": "afaf59f68e251939970ffdeacad0667dffc657a522bea62cdc44a52816fc49d6"
},
{
"name": "mtp.layers.0.self_attn.k_norm.weight",
"shard": "model-00102-of-00131.safetensors",
"dtype": "BF16",
"shape": [
256
],
"start": 1935412648,
"end": 1935413159,
"bytes": 512,
"file": "tensors/mtp.layers.0.self_attn.k_norm.weight.bin",
"sha256": "8f924b0357cf936e14fc34518205d000e1423aa60626827df81b0804fae8cdfd"
},
{
"name": "mtp.layers.0.self_attn.k_proj.weight",
"shard": "model-00108-of-00131.safetensors",
"dtype": "BF16",
"shape": [
512,
2560
],
"start": 1832518624,
"end": 1835140063,
"bytes": 2621440,
"file": "tensors/mtp.layers.0.self_attn.k_proj.weight.bin",
"sha256": "1a295dc2d6e633e808aeb19e00c97856a1817bbfcc83f5b610e2bfcacfcb8c38"
},
{
"name": "mtp.layers.0.self_attn.o_proj.weight",
"shard": "model-00106-of-00131.safetensors",
"dtype": "BF16",
"shape": [
2560,
6144
],
"start": 1832518400,
"end": 1863975679,
"bytes": 31457280,
"file": "tensors/mtp.layers.0.self_attn.o_proj.weight.bin",
"sha256": "9d2fcf0ac6ac19de87f638f710cfd1af6ad14141e75b7d3d5d29fbd06f374219"
},
{
"name": "mtp.layers.0.self_attn.q_norm.weight",
"shard": "model-00112-of-00131.safetensors",
"dtype": "BF16",
"shape": [
256
],
"start": 1935412664,
"end": 1935413175,
"bytes": 512,
"file": "tensors/mtp.layers.0.self_attn.q_norm.weight.bin",
"sha256": "57957aa1e7c5a3ac628bff0ec5522ad55a39b8c0b8bd2d324ae640e3771617ef"
},
{
"name": "mtp.layers.0.self_attn.q_proj.weight",
"shard": "model-00108-of-00131.safetensors",
"dtype": "BF16",
"shape": [
12288,
2560
],
"start": 1835140064,
"end": 1898054623,
"bytes": 62914560,
"file": "tensors/mtp.layers.0.self_attn.q_proj.weight.bin",
"sha256": "5220aef3d288f40759f7356af9ef453e5ac0256a38749a9bb803a4e9db58150d"
},
{
"name": "mtp.layers.0.self_attn.v_proj.weight",
"shard": "model-00108-of-00131.safetensors",
"dtype": "BF16",
"shape": [
512,
2560
],
"start": 1898054624,
"end": 1900676063,
"bytes": 2621440,
"file": "tensors/mtp.layers.0.self_attn.v_proj.weight.bin",
"sha256": "39cb12f5424e965fa71fb81db0ee230c701b7b1e0b72c36641fde7e0e41bff41"
},
{
"name": "mtp.pre_fc_norm_embedding.weight",
"shard": "model-00114-of-00131.safetensors",
"dtype": "BF16",
"shape": [
2560
],
"start": 1832518392,
"end": 1832523511,
"bytes": 5120,
"file": "tensors/mtp.pre_fc_norm_embedding.weight.bin",
"sha256": "04c4a570850e06f2d8913da8220d54d4c7f87db6eb6d45480b938e8ba41d6a86"
},
{
"name": "mtp.pre_fc_norm_hidden.weight",
"shard": "model-00118-of-00131.safetensors",
"dtype": "BF16",
"shape": [
10240
],
"start": 1716599944,
"end": 1716620423,
"bytes": 20480,
"file": "tensors/mtp.pre_fc_norm_hidden.weight.bin",
"sha256": "b933b44559879449b1baf2af8385c5c237347307e3fd452394870cb53e6eab6d"
}
]
@@ -0,0 +1,164 @@
{
"total_bytes": 889014272,
"tensors": [
{
"tensor": "mtp.fc_embedding.weight",
"format": "BF16",
"bytes": 13107200
},
{
"tensor": "mtp.fc_hidden.weight",
"format": "BF16",
"bytes": 13107200
},
{
"tensor": "mtp.hyper_connection_mixer.hc_norm.weight",
"format": "F32",
"bytes": 40960
},
{
"tensor": "mtp.hyper_connection_mixer.input_mix_weight_down.weight",
"format": "BF16",
"bytes": 6553600
},
{
"tensor": "mtp.hyper_connection_mixer.input_mix_weight_up.weight",
"format": "BF16",
"bytes": 6553600
},
{
"tensor": "mtp.layers.0.attn_hyper_connection.block_inject_weight.weight",
"format": "BF16",
"bytes": 81920
},
{
"tensor": "mtp.layers.0.attn_hyper_connection.hc_norm.weight",
"format": "F32",
"bytes": 40960
},
{
"tensor": "mtp.layers.0.attn_hyper_connection.input_mix_weight_down.weight",
"format": "BF16",
"bytes": 6553600
},
{
"tensor": "mtp.layers.0.attn_hyper_connection.input_mix_weight_up.weight",
"format": "BF16",
"bytes": 6553600
},
{
"tensor": "mtp.layers.0.mlp.experts.down_proj",
"format": "q2_0",
"bytes": 235929600,
"relative_rms_error_first_experts": 0.42363,
"seconds": 25.9
},
{
"tensor": "mtp.layers.0.mlp.experts.gate_up_proj",
"format": "q2_0",
"bytes": 471859200,
"relative_rms_error_first_experts": 0.42906,
"seconds": 52.8
},
{
"tensor": "mtp.layers.0.mlp.gate.weight",
"format": "BF16",
"bytes": 2621440
},
{
"tensor": "mtp.layers.0.mlp.shared_expert.down_proj.weight",
"format": "BF16",
"bytes": 3276800
},
{
"tensor": "mtp.layers.0.mlp.shared_expert.gate_proj.weight",
"format": "BF16",
"bytes": 3276800
},
{
"tensor": "mtp.layers.0.mlp.shared_expert.up_proj.weight",
"format": "BF16",
"bytes": 3276800
},
{
"tensor": "mtp.layers.0.mlp.shared_expert_gate.weight",
"format": "BF16",
"bytes": 5120
},
{
"tensor": "mtp.layers.0.mlp_hyper_connection.block_inject_weight.weight",
"format": "BF16",
"bytes": 81920
},
{
"tensor": "mtp.layers.0.mlp_hyper_connection.hc_norm.weight",
"format": "F32",
"bytes": 40960
},
{
"tensor": "mtp.layers.0.mlp_hyper_connection.input_mix_weight_down.weight",
"format": "BF16",
"bytes": 6553600
},
{
"tensor": "mtp.layers.0.mlp_hyper_connection.input_mix_weight_up.weight",
"format": "BF16",
"bytes": 6553600
},
{
"tensor": "mtp.layers.0.self_attn.indexer.index_qk_proj.weight",
"format": "BF16",
"bytes": 3276800
},
{
"tensor": "mtp.layers.0.self_attn.indexer.k_layernorm.weight",
"format": "F32",
"bytes": 512
},
{
"tensor": "mtp.layers.0.self_attn.indexer.q_layernorm.weight",
"format": "F32",
"bytes": 512
},
{
"tensor": "mtp.layers.0.self_attn.k_norm.weight",
"format": "F32",
"bytes": 1024
},
{
"tensor": "mtp.layers.0.self_attn.k_proj.weight",
"format": "BF16",
"bytes": 2621440
},
{
"tensor": "mtp.layers.0.self_attn.o_proj.weight",
"format": "BF16",
"bytes": 31457280
},
{
"tensor": "mtp.layers.0.self_attn.q_norm.weight",
"format": "F32",
"bytes": 1024
},
{
"tensor": "mtp.layers.0.self_attn.q_proj.weight",
"format": "BF16",
"bytes": 62914560
},
{
"tensor": "mtp.layers.0.self_attn.v_proj.weight",
"format": "BF16",
"bytes": 2621440
},
{
"tensor": "mtp.pre_fc_norm_embedding.weight",
"format": "F32",
"bytes": 10240
},
{
"tensor": "mtp.pre_fc_norm_hidden.weight",
"format": "F32",
"bytes": 40960
}
]
}
@@ -0,0 +1,24 @@
#!/usr/bin/env python3
"""POST a saved request body and print the server's answer, error body included."""
import json
import sys
import urllib.error
import urllib.request
path = sys.argv[1]
body = open(path, "rb").read()
parsed = json.loads(body)
messages = parsed.get("messages", [])
print("request bytes:", len(body))
print("messages:", len(messages), "| max_tokens:", parsed.get("max_tokens"))
print("prompt chars:", len(messages[0]["content"]) if messages else 0)
req = urllib.request.Request("http://127.0.0.1:8080/v1/chat/completions", data=body,
headers={"Content-Type": "application/json"})
try:
with urllib.request.urlopen(req, timeout=300) as response:
payload = json.load(response)
print("HTTP 200 | usage:", payload.get("usage"))
except urllib.error.HTTPError as error:
print("HTTP", error.code)
print(error.read().decode("utf-8", "replace")[:2000])
@@ -0,0 +1,15 @@
certifi==2026.7.22
charset-normalizer==3.5.1
cmake==4.4.3
idna==3.20
Jinja2==3.1.6
MarkupSafe==3.0.3
ninja==1.13.2
numpy==2.5.3
pillow==12.3.0
psutil==7.2.2
PyYAML==6.0.3
regex==2026.9.10
requests==2.34.2
tqdm==4.70.1
urllib3==2.8.0
@@ -0,0 +1,3 @@
e11083ba855e7666b48ea3f2db6a9c3a20c18751a012cc24f948de91b7087fad coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00001-of-00002.gguf
316b46f3a2dbd68c900f43136ab9449f9dcc3725dfd8c794847c204bc161e113 coder-IQ1_M/Qwen3.8-Flash-Next-GSQ-RCO-IQ1_M-00002-of-00002.gguf
b1a82259702816a5330d7bd7607cd9676b11780e79ff7348c21103ff3ce49bd0 mmproj-Qwen3.8-Flash-Next-BF16.gguf
@@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""Turn a telemetry.jsonl from monitor.py into memory-summary.json.
Reports the observed peaks and ranges of the engine's own memory counters, in the
units it reports them in (bytes), so the report can state where each number came from.
"""
import argparse
import json
import statistics
from pathlib import Path
FIELDS = ("gpu_mem_used", "gpu_mem_total", "gpu_util", "gpu_temp_c", "gpu_power_w",
"gpu_pcie_gen", "gpu_pcie_width", "ram_used", "ram_total", "disk_read_mb",
"vram_free_mib", "expert_cache_mib")
GIB = 1024 ** 3
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("telemetry", type=Path)
parser.add_argument("--out", type=Path, required=True)
args = parser.parse_args()
samples, broken = [], 0
for line in args.telemetry.read_text(encoding="utf-8").splitlines():
if not line.strip():
continue
try:
row = json.loads(line)
except json.JSONDecodeError:
broken += 1 # one line can be lost where a sampler restarts
continue
if "error" not in row:
samples.append(row)
times = [row["t"] for row in samples]
summary = {
"source": str(args.telemetry.name),
"samples": len(samples),
"unparseable_lines": broken,
"sampled_seconds": round(max(times) - min(times), 1) if times else 0,
"note": ("Each sample is one GET /metrics, so the values are the engine's own view. "
"Sampled peaks can miss shorter spikes between samples."),
"fields": {},
}
for field in FIELDS:
values = [row[field] for row in samples if row.get(field) is not None]
if not values:
continue
entry = {"median": statistics.median(values), "min": min(values), "max": max(values)}
if field in ("gpu_mem_used", "gpu_mem_total", "ram_used", "ram_total"):
entry["max_gib"] = round(max(values) / GIB, 2)
entry["median_gib"] = round(statistics.median(values) / GIB, 2)
summary["fields"][field] = entry
args.out.write_text(json.dumps(summary, indent=2) + "\n", encoding="utf-8")
print(json.dumps(summary["fields"], indent=2))
if __name__ == "__main__":
main()
@@ -0,0 +1,5 @@
[wsl2]
# Raise the WSL2 VM memory so the Strata container sees most of the host's 64 GB
# instead of Docker Desktop's default 50 % (~31 GB). Strata's setup reads RAM from
# /proc/meminfo, so with 31 GB visible it silently switched to low-RAM mode.
memory=56GB
@@ -0,0 +1,42 @@
# Community benchmark: RTX 5090 + RTX PRO 4000 Blackwell, UD-Q4_K_XL on the helper-cache config, engine 0.1.40.3
Measured 2026-10-07 on a daily-driver coding-agent box. The config is the two-GPU helper cache: all 48 layers on the 5090, the PRO 4000 holding 5000 extra experts (`--expert-cache-device1` + `--remote-expert-opt`). Standard ladder: 4k / 32k / 128k fresh prompts (nonce first, nothing reused), one warm-up then 3 measured runs per length, `temperature 0`, 256 tokens out (reasoning counts toward the 256). Limits at the end.
## Hardware and software
- GPU 0: NVIDIA GeForce RTX 5090 32 GB (all layers, expert cache, draft head, vision). GPU 1: NVIDIA RTX PRO 4000 Blackwell 24 GB (helper expert cache + vision encoder). No NVLink; PCIe probe 57.8 GB/s host->device (`pcie_frac 0.55`)
- CPU: AMD Ryzen 7 9800X3D (8 cores / 16 threads). RAM: 128 GB. OS: Windows 11 Pro
- Engine: ready-made CUDA 13.0 build (`engine-BUILD.json`), repo at `d5ea713` (v0.1.40.3)
- Background workload: a vLLM embedding server holds about 12 GiB of GPU 1 permanently, which caps the helper cache at 5000 slots; GPU 0 is Strata-only. This is the machine's real state, not a clean bench rig
## Model and configuration
- Model: `unsloth/Qwen3.8-Flash-Next UD-Q4_K_XL`, native pack (`--pack` + `--native`), shipped expert profile, MTP runtime from `Strata-data/mtp/rt`
- Config as run (`strata-config.json`): `--expert-cache auto` (7674 slots, 22.40 GiB) `--expert-cache-device1 5000` (5000 experts, 14.62 GiB on GPU 1) `--remote-expert-opt --prefill auto --spec 4 --mtp --max-context 262144 --kv int8 --kv-resident 32768 --spec-min-p 0.5 --vision`; prompt chunk auto picks 8192
- Start: `serve/server.py --engine strata --config strata-config.json --idle-unload 0 --port 8081`
- No `STRATA_*` environment overrides; no calibration; reasoning at the server default
## Method
- `bench_ladder.py`: prompt = Strata source and docs cut to the target length plus an "explain and propose three refactorings" task, with a random nonce first so nothing is reused from the cache. One warm-up per length, then 3 measured runs; speeds are the engine's own `timings` from the response (`prompt_per_second`, `predicted_per_second`)
- Daily-use context: the same box runs a coding agent (Kilo) at 15K-160K-token depths between the ladder runs; the ladder numbers are cold-prompt, single-stream
## Results
### Standard ladder (3 measured runs per length after one warm-up)
| Context | Actual prompt tokens | Prompt tok/s median (range) | Decode tok/s median (range) | Draft accept |
| --- | ---: | ---: | ---: | ---: |
| 4k | 5083 | 1513.7 (1493.3-1523.6) | 103.3 (95.0-110.1) | 71.5 |
| 32k | 33008 | 2048.0 (2043.5-2048.6) | 92.2 (87.3-98.6) | 65.6 |
| 128k | 115048 | 2200.6 (2132.8-2220.6) | 93.9 (90.4-95.7) | 69.1 |
### Daily use (warm, coding-agent sessions, depth 15K-160K)
Warm decode (prompt checkpoint-reused, second and later requests in a session): 96.5-121.4 tok/s, median ~101, expert cache hit 92.5-95.3 %. Cold prompt reading of 147K-160K-token prompts with 0 reused: 2,090-2,131 tok/s. KV streaming hit VRAM 99.4-99.7 % up to about 47K depth, 95-96 % at 140-160K.
## Limits
- The vLLM server on GPU 1 caps the helper cache at 5000 slots; a clean rig could size it larger
- One model, one quant, one workload family; the daily-use numbers are production sessions (varying prompts and depths), not repeated identical runs
- The helper cache is chosen over the layer split because the pair is lopsided (the PRO 4000 in every verify window slows decode); the split was not benched in the ladder format here
@@ -0,0 +1,32 @@
import json, random, string, time, urllib.request, sys
URL = "http://127.0.0.1:8081/v1/chat/completions"
corpus = ""
for p in [r"C:\Strata\docs\DETAILS.md", r"C:\Strata\serve\server.py", r"C:\Strata\src\core\verify.cpp"]:
try:
corpus += open(p, encoding="utf-8", errors="ignore").read() + "\n"
except OSError:
pass
task = "\n\nExplain what this code and documentation do and propose three refactorings.\n"
def run(prompt):
body = json.dumps({"model": "m", "messages": [{"role": "user", "content": prompt}],
"max_tokens": 256, "temperature": 0, "stream": False}).encode()
req = urllib.request.Request(URL, data=body, headers={"Content-Type": "application/json"})
r = json.load(urllib.request.urlopen(req, timeout=1800))
t = r.get("timings", {})
dn, da = t.get("draft_n", 0), t.get("draft_n_accepted", 0)
return {"prompt": r["usage"]["prompt_tokens"], "gen": r["usage"]["completion_tokens"],
"prompt_tok_s": round(t.get("prompt_per_second", 0), 1),
"decode_tok_s": round(t.get("predicted_per_second", 0), 1),
"accept": round(100 * da / dn, 1) if dn else None}
for chars, label in [(14000, "4k"), (112000, "32k"), (448000, "128k")]:
nonce = "".join(random.choices(string.ascii_letters, k=24))
prompt = nonce + "\n" + (corpus * (chars // len(corpus) + 1))[:chars] + task
run(prompt) # warm-up
for i in range(3):
nonce = "".join(random.choices(string.ascii_letters, k=24))
prompt = nonce + "\n" + (corpus * (chars // len(corpus) + 1))[:chars] + task
res = run(prompt)
print(json.dumps({"len": label, "run": i, **res}), flush=True)
@@ -0,0 +1,14 @@
{
"version": "0.1.40.3",
"source": "release",
"archs": [
75,
86,
89,
120
],
"ptx": true,
"cuda": "13.0",
"vision": "gpu",
"portable": true
}
@@ -0,0 +1,4 @@
index, name, memory.total [MiB], driver_version
0, NVIDIA GeForce RTX 5090, 32607 MiB, 610.88
1, NVIDIA RTX PRO 4000 Blackwell, 24467 MiB, 610.88
CPU: AMD Ryzen 7 9800X3D 8-Core (16 threads), RAM: 128 GB, OS: Windows 11 Pro
@@ -0,0 +1,54 @@
{
"exe": "C:\\Strata\\engine\\strata.exe",
"args": [
"--pack",
"C:\\Strata-data\\packs\\unsloth-ud-q4_k_xl",
"--native",
"C:\\Strata-data\\models\\unsloth-UD-Q4_K_XL\\Qwen3.8-Flash-Next-UD-Q4_K_XL-00001-of-00004.gguf",
"--expert-profile",
"C:\\Strata\\data\\expert-profile.bin",
"--expert-cache",
"auto",
"--expert-cache-device1",
"5000",
"--prefill",
"auto",
"--spec",
"4",
"--mtp",
"C:\\Strata-data\\mtp\\rt",
"--max-context",
"262144",
"--kv",
"int8",
"--kv-resident",
"32768",
"--spec-min-p",
"0.5",
"--remote-expert-opt",
"--vision"
],
"cwd": "C:\\Strata",
"tokenizer": "C:\\Strata-data\\packs\\unsloth-ud-q4_k_xl\\tokenizer",
"model_name": "qwen3.8-flash-next-unsloth-ud-q4_k_xl",
"reasoning_budget_tokens": 131072,
"idle_unload_s": 0,
"log": "C:\\Strata\\strata-unsloth-ud-q4_k_xl-helper.log",
"lib_dirs": [
"C:\\Strata\\.venv\\Lib\\site-packages\\nvidia\\cu13\\bin\\x86_64"
],
"env": {
"CUDA_VISIBLE_DEVICES": "0,1"
},
"port": 8081,
"gpu": 0,
"gpus_asked": true,
"vision": {
"exe": "C:\\Strata\\engine\\strata-vision.exe",
"mmproj": "C:\\Strata-data\\models\\mmproj-Qwen3.8-Flash-Next-BF16.gguf",
"model": "C:\\Strata-data\\models\\unsloth-UD-Q4_K_XL\\Qwen3.8-Flash-Next-UD-Q4_K_XL-00001-of-00004.gguf",
"gpu": true,
"max_tokens": 1024,
"cuda_device": 1
}
}
@@ -0,0 +1,162 @@
# Community benchmark: Tesla V100-PCIE-32GB + Tesla P100-PCIE-16GB, P100 as expert-helper card (mixed Volta/Pascal)
Measured on 2026-10-07 by aleesposito85 (headless Proxmox container, LXC, LAN only).
This is the first mixed Volta/Pascal (sm_70 + sm_60) report for Strata: the P100
serves as the **expert-helper cache for the V100** (`--expert-cache-device1 auto
--remote-expert-opt`), not a layer split. Engine 0.1.40.2, Flash-Next IQ3_XXS at
a 262,144-token context, Qwen3.8-Flash-Next IQ3_XXS.
Median prompt throughput was **1,436.9 tok/s at 17,971 prompt tokens** and
**1,446.4 tok/s at 44,011 prompt tokens**; median decode throughput was around
**73 tok/s** at a 256-token output cap. A single 119,731-token run read at
1,410.5 tok/s. These are synthetic filler prompts with a fixed explanation task,
greedy decoding, `reasoning_effort: none`; they do not establish general answer
quality or performance on other workloads.
## Hardware and software
- **CUDA0 (primary):** NVIDIA Tesla V100-PCIE-32GB (PG500-216, compute
capability 7.0), 32,768 MiB, 250 W power limit. PCIe **Gen3 8.0 GT/s x8**
(electrical x8 riser limit; both cards).
- **CUDA1 (helper):** NVIDIA Tesla P100-PCIE-16GB (GP100GL, compute capability
6.0), 16,384 MiB, 250 W power limit. Used as the expert-helper cache
(`--expert-cache-device1 auto`): 9,188 additional experts / 15.01 GiB, results
return through pinned host rows. The cards sit on different CPU sockets
(separate root complexes) and there is **no P2P**.
- **CPU:** Intel Xeon E5-2699 v3 @ 2.30 GHz (36 threads). The engine selected
35 expert-pool workers; the host thread drains too (`--host-core first`).
This CPU has **no AVX-512** — the engine used its AVX-2 expert kernels
(logged at startup).
- **RAM:** 128.8 GB installed; engine process holds ~46 GB resident + page
cache. Storage: rotational SAS RAID5 (the model files, 28.8 GB PLE shard and
the expert arena are read through the file cache; `--ple-io ram`).
- **OS:** Debian 12 container (Proxmox host kernel 6.14.11-9-pve), NVIDIA
driver 580.95.05, CUDA 12.8 (nvcc 12.8.61). Engine built from source on this
machine (`-DCMAKE_CUDA_ARCHITECTURES="70;60" -DSTRATA_EXPERIMENTAL_SM60=ON`;
CUDA 13 dropped Volta, so a CUDA 12.x toolkit is required).
- **Strata:** commit `e8ca9af` (v0.1.40.2), engine 0.1.40.2, server 0.1.40.2.
Engine binary SHA-256
`40626ec2045c3a8f30e20e344969a9fd642eb8c55776dd411969f49b67c78baa`.
- **Background workloads:** none on the GPUs; the LAN server was otherwise idle
during the test window. Nothing else shares VRAM (492 MiB free with
everything loaded).
## Model and configuration
Model: `ISTA-DASLab/Qwen3.8-Flash-Next-GSQ-RCO-GGUF`, IQ3_XXS:
- `Qwen3.8-Flash-Next-GSQ-RCO-IQ3_XXS-00001-of-00002.gguf` (47,039,860,096 B),
SHA-256 `219ea929900dfa9ef091f3aa473fdba6874b65fcb36526d7d851ac9e95856d15`
- `Qwen3.8-Flash-Next-GSQ-RCO-IQ3_XXS-00002-of-00002.gguf` (28,800,138,432 B,
the PLE n-gram shard), SHA-256
`316b46f3a2dbd68c900f43136ab9449f9dcc3725dfd8c794847c204bc161e113`
(byte-identical to the IQ3_S report's shard — hardlinked here)
- `mmproj-Qwen3.8-Flash-Next-BF16.gguf` (907,543,008 B), SHA-256
`b1a82259702816a5330d7bd7607cd9676b11780e79ff7348c21103ff3ce49bd0`
See [model-sha256.txt](model-sha256.txt). The model and pack were prepared by
the unmodified installer (v0.1.39-era `setup.py`; pack format v1). MTP draft
files under `/mnt/llama/strata/mtp/rt`: experts.bin (707,788,800 B, SHA-256
`09398406be61f1f54c93861f449e48b8df0bfccbc9ec9b2b7636775a6ea9244f`), dense.bin
(116,099,072 B, `c724dc0b0822ada5d2977bf5bde821605feabaa64ea2e0045b67ca656329070a`),
draft_vocab.bin (425,196 B, `b1e1d3a7a9e4bf862dcd5923ce661fb59bbd07907e594df5cf86a62ac235cb91`).
The bundled expert profile was used without calibration (SHA-256
`8f59b4aa8873209dff11c11e37bcda9529a1335b724a1afeea37bf6388975baf`).
- Context **262,144**; INT8 KV, 32,768 KV cells per attention layer resident on
GPU (`--kv int8 --kv-resident 32768`).
- Expert cache `auto`: **15,352 slots / 24.90 GiB on the V100**, profile-
prefilled, policy PROFILE; **CUDA1 helper: 9,188 additional experts /
15.01 GiB**. Warm decode expert-cache hit rate ~100%; ~7–18% of routed
experts are read from the helper per request.
- Prefill `auto:32768` (chosen deliberately; see below), 384-slot ring; the
prompt path borrows 8,148 CUDA0 cache slots (13.27 GiB).
- MTP `--spec 4 --spec-min-p 0.5` with `--remote-expert-opt`.
- **`STRATA_PREFILL_CPU_SHARE=auto`** (new in 0.1.40.2, opt-in): for prompt
chunks under 1,024 tokens the CPU pool computes the least-routed experts.
- Vision encoder enabled (GPU), warmed at 1,024 image tokens; not used by these
benchmark prompts.
- Reasoning disabled (`reasoning_effort: none`), temperature 0, 256 generated
tokens per speed run (all runs reached the cap: `predicted_n` 256).
```text
# engine args (from the server config; env: CUDA_VISIBLE_DEVICES=0,1,
# STRATA_PREFILL_CPU_SHARE=auto)
--serve --pack /mnt/llama/strata/packs/iq3_xxs \
--native /mnt/llama/strata/models/IQ3_XXS/Qwen3.8-Flash-Next-GSQ-RCO-IQ3_XXS-00001-of-00002.gguf \
--ple-gguf /mnt/llama/strata/models/IQ3_XXS/Qwen3.8-Flash-Next-GSQ-RCO-IQ3_XXS-00002-of-00002.gguf \
--expert-profile /opt/strata-src/data/expert-profile.bin \
--expert-cache auto --prefill auto:32768 --spec 4 --spec-min-p 0.5 \
--mtp /mnt/llama/strata/mtp/rt --max-context 262144 --kv int8 \
--kv-resident 32768 --vision --vram-reserve-mib 700 --ple-io ram \
--expert-cache-device1 auto --remote-expert-opt
```
The complete server config is [strata-iq3_xxs.json](strata-iq3_xxs.json).
## Method
- Script: [bench_report.py](bench_report.py) (also runnable unchanged against
any Strata server). It sends fresh salted prompts (a `[tag-nanoseconds]`
prefix guarantees **zero prompt reuse**; the engine logs confirm
`0 reused + N read` on every run), output cap 256 tokens, temperature 0,
`reasoning_effort: none`, streaming on.
- Prompt construction: a technical-report filler sentence repeated to the
target size, plus a fixed ~220-word explanation task. Actual prompt token
counts from the engine: **809 / 17,971 / 44,011 / 119,731** tokens.
- Sizes and repetitions: ~550 (3 runs), ~13.5K (3 runs), ~33K (3 runs),
~90K (1 run — marked as single-run in the table). One warm-up request
(not counted) precedes the battery; the server had already been running with
a warmed 100% expert cache, and every measured run is fully cold on prompt
tokens (no reuse).
- TTFT = seconds from request send to the first content delta (streaming);
reasoning was off, so the first token is answer text.
- Timings are the engine's own `timings` block (prompt_ms / predicted_ms);
wall time from the client. No model loading is included (server pre-loaded).
- Memory: VRAM free after load **492 MiB** (reported by the engine);
host RAM ~46 GB resident for the engine + page cache.
## Results
| Configuration | Actual prompt tokens | Reused tokens | Generated tokens | Runs | Prompt tok/s median and range | Decode tok/s median and range | TTFT seconds median and range |
| --- | ---: | ---: | ---: | ---: | --- | --- | --- |
| V100+P100 helper, IQ3_XXS, ~550-token prompt | 809 | 0 | 256 | 3 | 424.5 (422.3–425.1) | 77.0 (70.8–81.6) | 1.94 (1.93–1.95) |
| … ~17.9K-token prompt | 17,971 | 0 | 256 | 3 | 1,436.9 (1,436.5–1,438.2) | 72.8 (72.8–73.3) | 12.66 (12.64–12.67) |
| … ~44K-token prompt | 44,011 | 0 | 256 | 3 | 1,446.4 (1,445.9–1,446.7) | 74.2 (73.3–76.0) | 30.79 (30.76–30.81) |
| … ~120K-token prompt (single run) | 119,731 | 0 | 256 | 1 | 1,410.5 | 69.5 | 85.79 |
Decode varies with MTP draft acceptance (higher acceptance = more tokens per
verify pass); accepted-draft fractions in these runs were 59–72%. Per-run JSON
with all engine timing blocks: [results.json](results.json); the engine's own
timing lines: [engine-timings.txt](engine-timings.txt).
**Total latency** (wall, client-side, excludes loading): 5.2 s at 809 tokens,
16.1 s at 17,971, 34.2 s at 44,011, 89.5 s at 119,731.
## Correctness and limitations
- **Needle-in-a-haystack** (`tools/needle_bench.py`, the report's own check):
32k: found at depths 10%, 50%, 90%; 128k: found at depths 10%, 50%, 90% —
see [needles.json](needles.json).
- This is one machine with **no P2P between the cards** (cross-socket
host-bridge path); decode includes the helper round-trip per request.
- `--prefill auto:32768` is a deliberate non-default: with the default 8192
chunk cap, this rig's prompt chunks ≥1,024 tokens each trigger a full
"stream every non-resident expert" pass, and mid/long prompts lose 50–100%
prompt speed (measured: ~20.5K 413→827 tok/s, ~33.5K 499→965; also reported
in issue #1079). At 32768 the same prompts read in a single pass and the
numbers above follow. This interaction is worth checking on other low-VRAM /
helper-cache rigs.
- `STRATA_PREFILL_CPU_SHARE=auto` (0.1.40.2) measured **−23% time-to-first-token
on sub-1,024-token prompts** on this rig (off→auto→off interleaved: 1,905/1,880
ms → 1,462/1,440 ms), with visible output byte-identical in a fixed-prompt
parity check; ≥2K prompts unchanged. It is enabled for the runs above.
- The helper cache costs a few percent of sustained decode versus a hypothetical
all-resident setup; the trade was accepted for +14–25% decode versus the V100
alone (measured in an earlier local A/B, not part of this report).
- Background: single-sequence serving (one request at a time); no `--batch`
slots. All numbers are warm (the P100 helper fills on the first large
request; the first ~2 big requests after a restart run 20–30% slower while it
fills).
- Reported previously in [issue #1079](https://github.com/Niko1221/Strata/issues/1079)
(V100+P100 helper, 0.1.39 → 0.1.40 decode +6–11%).
@@ -0,0 +1,98 @@
#!/usr/bin/env python3
"""bench_report.py — community-report battery for the V100+P100 helper rig.
Fresh salted prompts (no prefix reuse), output cap 256 tokens, greedy,
reasoning_effort none (matches other community reports), streaming TTFT.
Sizes: ~550 / ~13.5K / ~33K x3 runs; ~90K x1 (single run, marked).
Saves per-run results to /root/benchpr-results.json and prints them.
"""
import json, sys, time, urllib.request
BASE = "http://127.0.0.1:8082"
OUT = "/root/benchpr-results.json"
unit = "The following is a technical report excerpt that must be summarized. "
TASK = ("\n\nTask: using general knowledge (the excerpt above is filler), explain in "
"about 220 words how TCP congestion control works, covering slow start, congestion "
"avoidance, fast retransmit and fast recovery, with rough numbers. Plain text.")
def run(tag, rep, n=256, timeout=2400):
salt = f"[{tag}-{time.time_ns()}] "
prompt = salt + unit * rep + TASK
body = json.dumps({
"model": "q",
"messages": [{"role": "user", "content": prompt}],
"max_tokens": n, "temperature": 0, "stream": True,
"reasoning_effort": "none",
}).encode()
req = urllib.request.Request(BASE + "/v1/chat/completions", data=body,
headers={"Content-Type": "application/json"})
t0 = time.time()
ttft = None
content = ""
timings = None
usage = None
with urllib.request.urlopen(req, timeout=timeout) as r:
for raw in r:
line = raw.decode("utf-8", "ignore").strip()
if not line.startswith("data:"):
continue
payload = line[5:].strip()
if payload == "[DONE]":
break
try:
d = json.loads(payload)
except Exception:
continue
ch = d.get("choices") or []
if ch:
delta = ch[0].get("delta") or {}
txt = delta.get("content")
if txt:
if ttft is None:
ttft = time.time() - t0
content += txt
if d.get("timings"):
timings = d["timings"]
if d.get("usage"):
usage = d["usage"]
wall = time.time() - t0
res = {
"tag": tag, "rep": rep,
"ttft_s": round(ttft, 3) if ttft is not None else None,
"wall_s": round(wall, 2),
"ttft_is_first_content_delta": True,
"timings": timings, "usage": usage,
"out_chars": len(content),
"out_head": content[:120],
}
print(json.dumps({k: res[k] for k in ("tag", "ttft_s", "wall_s")}
| {"pn": (timings or {}).get("prompt_n"),
"reused": (timings or {}).get("cache_n"),
"gen": (timings or {}).get("predicted_n"),
"ptps": round((timings or {}).get("prompt_per_second", 0), 1),
"dtps": round((timings or {}).get("predicted_per_second", 0), 1)}), flush=True)
return res
def main():
print(f"=== BENCH REPORT START {time.strftime('%Y-%m-%d %H:%M:%S')} ===", flush=True)
results = []
# warm-up (not part of results)
w = run("warmup", 60, n=64)
print("warmup done", flush=True)
results.append(dict(w, tag="warmup", counted=False))
sizes = [("tokens550", 60, 3), ("tokens13500", 1490, 3), ("tokens33000", 3660, 3), ("tokens90000", 9970, 1)]
for name, rep, reps in sizes:
for i in range(reps):
r = run(f"{name}-run{i+1}", rep)
r["counted"] = True
results.append(r)
with open(OUT, "w") as f:
json.dump(results, f, indent=1)
print(f"=== BENCH REPORT DONE {time.strftime('%Y-%m-%d %H:%M:%S')} -> {OUT} ===", flush=True)
if __name__ == "__main__":
main()
@@ -0,0 +1,10 @@
strata serve: prompt 809 tokens = 0 reused + 809 read in 1916 ms (422.3 tok/s), 256 generated in 3615 ms (70.8 tok/s), drafts accepted 131 of 223, 1 checkpoints
strata serve: prompt 809 tokens = 0 reused + 809 read in 1906 ms (424.5 tok/s), 256 generated in 3138 ms (81.6 tok/s), drafts accepted 149 of 217, 1 checkpoints
strata serve: prompt 809 tokens = 0 reused + 809 read in 1903 ms (425.1 tok/s), 256 generated in 3323 ms (77.0 tok/s), drafts accepted 145 of 234, 1 checkpoints
strata serve: prompt 17971 tokens = 0 reused + 17971 read in 12507 ms (1436.9 tok/s), 256 generated in 3514 ms (72.8 tok/s), drafts accepted 142 of 226, 1 checkpoints
strata serve: prompt 17971 tokens = 0 reused + 17971 read in 12496 ms (1438.2 tok/s), 256 generated in 3492 ms (73.3 tok/s), drafts accepted 143 of 228, 1 checkpoints
strata serve: prompt 17971 tokens = 0 reused + 17971 read in 12510 ms (1436.5 tok/s), 256 generated in 3517 ms (72.8 tok/s), drafts accepted 142 of 220, 1 checkpoints
strata serve: prompt 44011 tokens = 0 reused + 44011 read in 30422 ms (1446.7 tok/s), 256 generated in 3449 ms (74.2 tok/s), drafts accepted 145 of 204, 2 checkpoints
strata serve: prompt 44011 tokens = 0 reused + 44011 read in 30428 ms (1446.4 tok/s), 256 generated in 3493 ms (73.3 tok/s), drafts accepted 142 of 209, 2 checkpoints
strata serve: prompt 44011 tokens = 0 reused + 44011 read in 30439 ms (1445.9 tok/s), 256 generated in 3366 ms (76.0 tok/s), drafts accepted 150 of 209, 2 checkpoints
strata serve: prompt 119731 tokens = 0 reused + 119731 read in 84886 ms (1410.5 tok/s), 256 generated in 3683 ms (69.5 tok/s), drafts accepted 142 of 220, 4 checkpoints
Loaded 100 of 1303 files, more files were not shown because too many files have changed in this diff. Show more