Skip to content

Decode speed is bistable within one session: per-layer host per expert entry jumps 3-5x and stays there, while entries / GPU-reach wait / CPU kernel time stay constant #1913

Closed as not planned

Description

@zrlhk

Environment (short)

  1. What happens
    11 consecutive requests inside one engine process, no config change between them:
    4TS fixed 80ts #1-6: 91.4 - 99.8 tok/s, per-layer host 17.9-21.8 ms, entries/window 4.76-5.43, host per entry 3.4-3.9 ms
    serve: fix zero-token replies from engine-queue race between requests #7-11: 20.1 - 44.7 tok/s, per-layer host 61.1-137.2 ms, entries/window 4.99-5.30, host per entry 11.3-15.7 ms
    Between request 6 and 7 the speed drops 98.2 -> 44.7 tok/s and never recovers for the rest of the session.

  2. What does NOT change across the same 11 requests

  • entries/window: 4.76-5.43 before, 4.99-5.30 after (same work handed to the CPU pool)
  • GPU-reach wait: 12.72-13.75 ms throughout (GPU is not the variable)
  • CPU kernel time: 3.82-4.24 ms at ~5 entries on both sides
  • avg T (draft acceptance): 3.72-3.92 on both sides
  • plan / actq / jobs in the [plan actq jobs CPU] breakdown: all <= 0.5 ms in every row
    So the jump is essentially all in the CPU term - the pool dispatch wall clock - not in compute, and not in lock contention inside the engine. The pool takes 3-5x longer to hand back the same number of experts, and stays that way.
  1. For scale
    Over ~180 requests on this machine, bucketed by expert-cache hit rate, the normal cost of one missed expert is 3.4-5.1 ms of host time, and speed tracks the hit rate as a step. In section 1 the same machine and build show 11-16 ms per entry - the per-entry cost itself tripled. No amount of cache would have fixed that.

  2. Three things I noticed in the same window (may be unrelated)
    (a) The PCIe probe varies a lot between starts on an idle machine: 12.4, 9.0, 9.1 GB/s host->device, with individual samples from 4.5 to 12.4, moving pcie_frac 0.25 -> 0.34. It is the number the new adaptive pcie_frac starts from.
    (b) VRAM is nearly exhausted: "389 MiB of VRAM free with everything loaded", and "strata verify: capturing the 5-token window (235 MiB of VRAM free)" appears in the lines immediately before request 7, the first slow one. Causal or coincidence, I cannot tell - the timing lines up.
    (c) Widening --max-context 131072 -> 262144 costs the expert cache ~17% of its slots (7661 -> 6291) on the same model, since --kv-resident 0 keeps the whole KV resident.

  3. Possible bug: --pool-workers 12 and 14 both print only 11 pinned processors
    With --host-core last, every count prints its own number of logical processors except these two:
    11 pool workers on logical processors 0,2,4,6,8,10,12,14,16,18,20 (11 listed)
    12 pool workers on logical processors 0,2,4,6,8,10,12,14,16,18,20 (11 listed) <- 12 requested
    14 pool workers on logical processors 0,2,4,6,8,10,12,14,16,18,20 (11 listed) <- 14 requested
    Workers past the 11th appear to run unpinned. Measured here that shows up as 12 ~= 14 (tied) and 16 clearly worse. Intended, or a placement bug?

  4. Side note on tuning
    Before the arena used large pages, --pool-workers 6 beat the default on this machine (37.1 -> 55.0 tok/s), which matches the --calibrate hint. After large pages, 12 is best (91.9 tok/s vs 80.6 at 6). If --calibrate is meant for Windows users, it may be worth having it notice whether the arena is on large pages - following the current guidance here would pick 6, which is 24-31% off the best.

  5. Questions

    1. Could the engine detect and report the section-1 jump? The counters already exist in the decode timing line: a one-line warning when "host per entry" exceeds ~2x its own session median would turn "it feels slow" into "the log says why".
    1. Is there anything to make the pool resilient to external CPU pressure? plan/actq/jobs stay <= 0.5 ms, so it looks like the workers are simply not being scheduled. Here 11 pinned workers + 1 host occupy 11 of 12 physical cores, so any other CPU consumer lands on top of them. Would leaving a core empty (--pool-workers 10) trade peak speed for stability, or should the spin/priority already handle that?
    1. Is the section-4(a) probe spread expected (4.5-12.4 GB/s)?
    1. Section 5 - intended or bug?
  1. Method
    Everything above comes from the engine's own STRATA_DECODE_TIMING=1 line, one per request; "host per entry" = the CPU term divided by entries, both from that line. The 11 requests in section 1 are inside one process - the log has one "session is up" and no "engine started" between them. What I cannot show: the wall-clock stamps are inherited from the parent process, so I cannot align them with outside events, and I did not capture a process list while it happened. External CPU preemption is my first guess (the same signature appeared here before right after Windows Defender scanned a freshly downloaded engine), but I would rather report the numbers than the guess.

Happy to split sections 4-6 into separate issues if preferred.

Activity

  1. Niko1221 commented on Oct 19, 2026

    @Niko1221
    Owner

    Thanks for taking the time to report this.

    We're resetting the tracker for 0.2.0-beta. There are more than 1,300 open issues and pull requests, too many for us to read properly, so we're closing everything that isn't being worked on right now. Closed here does not mean rejected.

    To reopen it takes about two minutes:

    1. Re-test on 0.2.0-beta. It may already be fixed. Write down what you see.
    2. Start the title with its area: [Engine], [GUI], [TUI], [Benchmark], [Docs] or [Other].
    3. Fill in the parts of the issue form: what happened, the Strata version, your graphics card, memory and system.
    4. Comment /reopen. A check runs and either reopens the issue or lists what is still missing.

    The rules are in CONTRIBUTING.md.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions