Repository navigation
--spec 5 measured +6.1% decode (RTX 5060 Ti / 128 GB) but cannot be persisted: tune_knobs safe range is [3, 4] #3844
Description
Issue draft — paste into https://github.com/Niko1221/Strata/issues/new
Title: --spec 5 measured +6.1% decode on RTX 5060 Ti / 128 GB, but it cannot be persisted: tune_knobs safe range is [3, 4]
What I am asking for
Allow --spec 5 for the flash-next family, or at least let a power user pin it durably.
I am not asking to change the default — my machine's own autotune correctly picked 4 and I
respect that. I am asking that 5 be a value a user is allowed to keep.
Environment
| Engine | Strata 0.1.47-windows-x86_64-cuda-cuda13 (auto-updated to 0.1.48 after the measurement — see caveats) |
| Model | qwen3.8-flash-next-nvfp4-nvfp4 (qwen-nvfp4-gptq-dense.gguf + pack), 204800 ctx, KV int8, vision enabled |
| GPU | RTX 5060 Ti 16 GB (16311 MiB), iGPU drives the display so the dGPU is model-only |
| RAM / CPU | 127.5 GiB / Core Ultra 7 265K |
| Launch | --serve, resource profile performance, --vram-reserve-mib 2048, expert cache 2226 slots (5.73 GiB), expert arena 63.28 GiB, batch 1 |
Measurement
Same engine build, same model, same machine, same prompts, greedy decoding, batch 1, one run per
prompt. --spec 5 was measured with a second, independent engine instance on a separate port
(18501) while the main instance ran --spec 4, then the numbers were compared. Metric is the
engine's own decode figure (generated tokens ÷ generation time, from the GEN lines), plus the
engine's own draft-acceptance counters. Client-side medians are reported too.
| Run | --spec |
engine decode tok/s | draft accepted | client median tok/s |
|---|---|---|---|---|
| baseline | 4 | 48.8 | 70.9% | 45.1 |
| variant | 5 | 51.8 (+6.1%) | 67.2% | 44.8 |
Per prompt (engine decode tok/s):
| Prompt | --spec 4 |
--spec 5 |
|---|---|---|
| technical explanation | 45.1 | 44.8 |
| code generation | 49.1 | 56.5 (+15%) |
| creative writing (zh) | 43.2 | 43.4 |
What the guard's rationale predicts is that a wider window costs more than it pays. On this box it
did not: acceptance falls exactly as expected (70.9% → 67.2%) and the window is still net positive,
concentrated in code generation. RAM footprint is identical (the 63.28 GiB expert arena does not
depend on the window) and the VRAM cost is one small buffer:
strata verify: window up to 7 tokens, ~90 MiB of device buffers # --spec 5
strata verify: window up to 6 tokens, 77.1 MiB of device buffers # --spec 4
The engine starts and serves --spec 5 with no problem at all — I ran it for hours, including as
the assistant serving this very session. This is purely a policy question, not a capability one.
Why I cannot keep it (three separate walls)
strata_control/tune_knobs.py— the tuner exposes"--spec": {"choices": (3, 4)}, and the
safety text says wider windows (>= 6) were "4% to 16% slower". 5 is not rejected by that rule;
it is rejected by the range. In-process check:--spec = 4 -> [] (passes) --spec = 5 -> ['--spec 5: outside the safe values [3, 4]'] --spec = 6 -> ['--spec 6: wider speculative windows were 4% to 16% slower', '--spec 6: outside the safe values [3, 4]']presets.overlay()— the layer documented as "applying the active preset at every start"
deliberately drops out-of-range settings ("A setting that is outside the safe rules is left out,
never applied"), so a preset carrying--spec 5is skipped entirely:With only that one range relaxed in memory (no file touched), the very same preset appliesapplied=False why_not='not applied: --spec 5: outside the safe values [3, 4]' state='fresh'
cleanly through the official mechanism:So the persistence machinery already works; the range is the only thing in the way.applied=True state='fresh' resulting argv: --spec 5- Hand-editing the model settings file does not survive a load.
strata-nvfp4-nvfp4.json
holds"--spec", "5"→ the UI's native-settings JSON shows 5 → the user presses unload/load →
the freshly derivednative-instances\<uuid>.jsoncomes out with--spec 4and the settings
file is rewritten back to 4 (mtimemoves to the load timestamp). This is the part I found
surprising: the UI displays anargsarray that a user may edit and thatvalidateNativeSettings()
explicitly accepts, but the value it shows is regenerated over at load, so editing it silently
does nothing. If that is intentional, the UI should say so; if not, it is a small bug.
Suggested fixes, in order of preference
- Widen the safe range for
flash-nextto[3, 5](or gate it: allow 5 whenvram >= 16 GBand
ram >= 64 GB, where the window buffer is free and acceptance stays high). - Add a draft-depth field to
NATIVE_FIELDS(native settings → "GPU & memory" or a new
"Speculation" group) so the value is a first-class, user-owned setting that goes through
save()and is not regenerated at load. - Independent of the above: if
argsedits in the model settings file are going to be regenerated
at load, surface that in the native-settings JSON tab instead of accepting them.
Caveats I want to be upfront about
- One run per prompt, three prompts. The aggregate +6.1% comes mostly from the code prompt; the
other two are flat. I have not run a repeated-measures median. I would not call this a settled
benchmark — I am reporting a directional result on one specific GPU/RAM/model/quant combination. - Client-side medians were flat (45.1 → 44.8), so the engine-side gain did not reach wall-clock for
single short requests. For long generations it should. - Measured on 0.1.47; the engine has since auto-updated to 0.1.48. I will re-run on 0.1.48 and
post the numbers here before this is acted on. If it does not reproduce, I will say so. - Autotune on this machine picked the default and reported
default_confirmedwithsettings.args = {},
so 5 was never a candidate it could have found. The candidate set is the reason this is invisible
to the tuner, not a measurement disagreement.
Repro
# baseline is whatever the app launches; then start a second instance with one flag changed
strata.exe --serve --pack <pack> --native <gguf> ... --spec 5 --port 18501
# engine log: "strata verify: window up to 7 tokens" (spec 4 reports 6)Guard / persistence checks (read-only, run against the installed Control):
from strata_control import tune_knobs as k, presets as P
ctx = k.Context(context_tokens=204800, family="flash-next")
k.check_setting({"--spec": 5}, {}, ctx) # ['--spec 5: outside the safe values [3, 4]']Artifacts
Verbatim from the engine log — the --spec 5 start (trimmed) and the cache line, which is identical
for both runs, so the comparison is apples to apples:
[strata] 2026-10-22 01:21:41 engine started: ...\components\engine\0.1.47-windows-x86_64-cuda-cuda13\strata.exe
--serve --pack ...\pack --native ...\qwen-nvfp4-gptq-dense.gguf ... --spec 5 ...
strata generate: expert cache auto: 8.01 GiB free, 2048 MiB reserved (+281 MiB for the draft head) -> 2226 slots
strata generate: expert cache 2226 slots, 5.73 GiB of VRAM
Activity
github-actions commentedon Oct 23, 2026
Thanks for the issue. To keep the tracker readable, every item needs an area prefix in the title and the parts of the issue form filled in. This one is missing:
Edit the issue (title and description) and this note goes away on its own. If it is still missing parts in 5 days it will be closed, which is not a rejection: fix it and comment
/reopen.Details: CONTRIBUTING.md
yusheng227507 commentedon Oct 23, 2026
Counter-datapoint on Turing (2× RTX 2080 Ti 22 GB, layer split 26/22, IQ3_XXS, MTP drafter
rt, engine 0.1.48 self-built sm_75):--spec 5clearly regresses here.Same standard suite on both arms (3 runs each, 33/33 ok), same engine, only
--specdiffers:--spec 4--spec 5Mechanism matches your measurement but ends in the opposite place: at spec 5 the drafter offers deeper windows (+19%), acceptance falls harder (-7.2 pp vs your -3.7 pp), and each verification costs more, so the wider window is net negative. That lands inside the guard's own "4% to 16% slower" band for wider windows — on sm_75 the
[3, 4]safe range is correct as measured.Two things from this box support your framing rather than argue against it:
--spec 5vs--spec 4, temperature 0 / seed 1, exact-comparison recipe) — so it is indeed policy, not capability, exactly as you say.[3, 5]fits one architecture and hurts another. Your suggested per-arch / per-VRAM gating (fix 2) looks like the right shape.Paste-ready (in the style of the issue body):
Presets: a value outside the range the tuner tries is kept with a war…
Merge f-027-gh-eng-d (#3602 #3948 #3638 #3702 #3797 #2409 #3844: audi…
Merge f-027-gh-eng: GitHub engine items for 0.2.7
Niko1221 commentedon Oct 27, 2026
Thank you for the measurement. Fixed in 0.2.7: A value outside the tuner's safe range, such as --spec 5, can be saved in a preset and used, with a short warning; only values that are never valid (--spec 6, for example) are still refused, and the automatic tuner itself stays inside the safe range. We recommend, we never force.
Release: https://github.com/Niko1221/Strata/releases/tag/v0.2.7