Issues / #1922

#1922 [Bug]: RouterLookahead overhead with fully resident experts; disabling it improves decode by 19% on RTX 4070

open · @Takayuki-Ishimaru · 2 comentarios · En GitHub

BenchmarksServer & APIMulti-GPUNVIDIA / CUDAModels & quantsWindows

Descripción

## What happened

With all experts in GPU cache or pinned RAM, the file-tier RouterLookahead still runs CPU router prediction although there are no expert file reads. On the same UD-IQ4_XS model and v0.1.41 binary, disabling it improved mean decode throughput from **32.80 to 39.06 tok/s (+19.1%)**.

| Same model, three 600-token requests per arm | Individual tok/s | Mean tok/s |
|---|---|---:|
| Default lookahead | 31.96 / 33.97 / 32.48 | 32.80 |
| `STRATA_LOOKAHEAD=0` | 38.79 / 40.27 / 38.11 | 39.06 |
| Default lookahead, paced pinning control | 33.36 / 31.29 / 32.85 | 32.50 |

The off arm automatically used paced `cudaHostRegister`; the first on arm used bulk allocation. To check that confound, I repeated the on arm with `STRATA_PIN_GUARD=2`. Both paced arms fully pinned 54.85 GiB; the comparison still shows +20.2% throughput. The pin guard is only a diagnostic control, not the proposed workaround.

In those paced arms, total host-pool time fell from 18.38 to 13.29 ms/output token; CPU expert work was 13.14 to 12.66 ms and GPU-reach time 8.97 to 8.93 ms. This supports predictor overhead/competition as an explanation, but does not isolate mutex, scheduling, or memory-bandwidth costs.

## Strata version, GPU, OS

v0.1.41, `fb58e0dbc8399662c0e47c76578c6e878b14f6cf`; RTX 4070 12 GB; Intel i5-13500 (AVX2), five pool workers plus the caller. Ubuntu 24.04 LXC, kernel 6.17.13-21-pve, 96 GiB container RAM; CUDA 13, sm_89 build.

Model: Unsloth Qwen3.8-Flash-Next UD-IQ4_XS native three-part GGUF, pack created with `iq_pack.py --compat-bf16`. GPU cache: 1,690 slots / 3,886 MiB; pinned RAM complement: 54.85 GiB. A local thinking-budget/stop patch is present; these measurements use the raw engine `--serve` protocol, bypassing Python HTTP handling. The same binary, weights, pack and MTP are used in all arms.

## Reproduction

1. Start a single engine with a native GGUF and enough RAM for the **whole** complement. Common options:

   ```text
   --mmap-experts --resident-experts --expert-cache auto --prefill auto
   --spec 4 --spec-min-p 0.5 --mtp <same-mtp-directory>
   --max-context 196608 --kv int8 --kv-resident 16384 --vram-reserve-mib 980
   ```

   Actual KV residency was 20,480. Foresight was off; expert file-blob reads stayed at zero. Do not substitute a partial resident budget.

2. Freeze prompt token IDs; warm with 150 output tokens, then generate 600 tokens for seeds 101–103. Use temperature 0.7, top-p 0.8, top-k 20, ignore EOS and no prompt-cache hits. My short Japanese prompt asks for all 47 prefectures, north to south, with two or three sentences each; numbered markers make each request fresh (60 tokens).
3. Restart with only `STRATA_LOOKAHEAD=0` changed and repeat. Timing instrumentation must match between arms. Check the resident/pin log and expert file-read counter in both.

## Expected optimization

Consider automatically skipping file-prefetch prediction after residency is established and **all** relevant experts are accessible from RAM/GPU. Preserve prediction for partial/file-backed residency, Foresight, `STRATA_LOOKAHEAD_STATS`, and explicit measurement/override use. The resident flag alone is insufficient because a limited or failed RAM allocation can leave a file tier.

In v0.1.41, lookahead is initialized before the resident complement is filled; `FileExpertSource::warms()` checks mappings, while `warm()` later skips RAM-resident experts. The corresponding guards remain in [current main's generate.cpp](https://github.com/Niko1221/Strata/blob/61b3fb5dd3f1e8ec09cf7e4e05208bc6d3c46406/src/program/generate.cpp#L5380-L5420), [warms()](https://github.com/Niko1221/Strata/blob/61b3fb5dd3f1e8ec09cf7e4e05208bc6d3c46406/include/strata/core/expert_source.hpp#L689), and [warm()](https://github.com/Niko1221/Strata/blob/61b3fb5dd3f1e8ec09cf7e4e05208bc6d3c46406/src/core/expert_source.cpp#L2045-L2068). Current main was inspected, **not benchmarked**.

## Limits and related work

One machine, three requests per arm, fixed arm order and one engine startup per arm; no interleaved repeated restarts. Outputs and adaptive routing can differ; paced-arm MTP acceptance moved from 69.8% to 71.6%, adding uncertainty. No quality or long-context A/B for this flag, and no byte-identical output guarantee.

Searches for `STRATA_LOOKAHEAD`, lookahead, and resident/prefetch found related #1348 (Foresight), #1838 (partial RAM adaptation), and #416 (older Windows mmap benchmarks), but no exact report of this full-resident case. Those configurations differ; this report does not propose disabling prediction globally.

En el sitio

Enlaces a install, modelos, releases.