Issues / #2710

#2710 [Bug]: --pipeline-windows is silently clamped to 2; values above 2 are accepted and ignored

open · @kietq8684-design · 0 comentarios · En GitHub

Server & APIMulti-GPUAMD / HIPNVIDIA / CUDAModels & quantsDocumentationWindows

Descripción

**Strata version, GPU, OS:** 0.1.42 (61b3fb5) · Radeon VII 16GB (0x66af) + Radeon Pro VII / Instinct MI50 16GB (0x66a1), gfx906, layer split · Ubuntu 24.04, kernel 6.8.0-146-p2p, ROCm HIP 7.14 (mixa3607/rocm-gfx906:7.14-complete), HSA_OVERRIDE_GFX_VERSION=9.0.6

`--pipeline-windows` is hard-clamped to `[0, 2]`, and the clamp is **silent**: a value above 2 is accepted, the
engine uses 2, and nothing on stderr or in the log says the requested value was out of range.

#### 1. The clamp, in source

`src/program/generate.cpp:1991`:

```cpp
else if (a == "--pipeline-windows") o.pipeline_windows = std::max(0, std::min(2, std::atoi(next("--pipeline-windows"))));
```

#### 2. The engine's own log shows "3" and "2" side by side, with no warning in between

Same run, same startup log (`--pipeline-windows 3` requested):

    [strata] 2026-10-15 06:03:34 engine started: /src/build-906/strata --serve --pack ... --layer-split 27
             --prefill 4096 --spec 2 --spec-min-p 0.7 --mtp /data/mtp/rt --pcie-frac 0 --ple-row-cache 8388608
             --pipeline-windows 3 --max-context 32768
    strata generate: --pipeline-windows 2: 290 MiB of CUDA0 kept out of the expert cache (the second verifier, the GDN snapshots)
    strata serve: --pipeline-windows 2: two verifiers per stage, 2 stages overlap across windows (decode too; the GDN snapshots beside the window)

The engine's argv says 3; every line the engine then prints says 2. There is **no** line announcing the clamp:
`grep -icE "clamp|out of range|capped|ignoring"` over that startup log returns **0**.

#### 3. It is measurably a no-op: 3 is indistinguishable from 2, while 1 vs 2 clearly differ

Controlled sweep, one fresh container per value, both cards sampled from the host
(`/sys/class/drm/cardN/device/mem_info_vram_used`; idle = median of 12 samples after a 20 s settle,
peak = max over 160 samples at 0.5 s while a 16K-token request was in flight). Same config otherwise.

| requested | idle card0 / card1 (GiB) | peak card0 / card1 (GiB) | engine's structural report |
|---|---|---|---|
| `--pipeline-windows 1` | 14.712 / 15.348 | 14.778 / 15.457 | **6912 slots / 12.57 GiB** |
| `--pipeline-windows 2` | 14.716 / 15.436 | 14.784 / 15.547 | **6889 slots / 12.53 GiB** |
| `--pipeline-windows 3` | 14.718 / 15.436 | 14.785 / 15.547 | **6889 slots / 12.53 GiB** |

Row 3 is row 2 within sampling noise (≤ 2 MiB) and **byte-identical** on the engine's own expert-cache line
(6889 slots / 12.53 GiB). Row 1 is 88 MiB and 23 slots away — so the knob does have an effect at 0/1/2;
3 just never runs.

#### Why this cost us real time (the actual impact)

We ran a boundary sweep over this flag and included a `--pipeline-windows 3` arm. It was a **no-op identical to the
baseline**, and we only found out by reading the engine's structural log line by line — the sweep's own summary
table looked like a normal result. We had already written "PW3" up as a data point before catching it. Anyone
tuning this flag can spend hours on an arm that never ran, and the engine gives them no hint.

#### What we'd like (deliberately small)

1. **A one-line notice when the value is out of range.** The codebase already has exactly this "say it once"
   pattern for the *off* path — `src/program/generate.cpp:3279`:
   ```cpp
   std::fprintf(stderr, "strata generate: --pipeline-windows %d is off: %s\n", o.pipeline_windows, off);
   ```
   So something like `strata generate: --pipeline-windows 3 is above the maximum 2, using 2` would match the
   existing style. (An `exit(2)` would be fine too, but we assume the clamp is intentional and just want it said.)
2. **State the range in the docs.** `--help` (`src/program/generate.cpp:784-786`) says
   "`--pipeline-windows N ... 1 = the prompt's short reads, 2 = decode as well`" — it describes 1 and 2 but never
   says N is capped at 2. `docs/MULTI_GPU.md` (the section "One conversation with both cards busy") likewise
   describes 1 and 2 only. A single "(0-2)" would close it.
3. *(optional, same root cause)* the other silently clamped numeric flags in the same parsing chain:
   `--lookup-chain` (`std::clamp(..., 0, 7)`, `generate.cpp:1994`), and `--suffix-draft` / `--mtp-max-t` /
   `--prompt-cache` (floored at 0). Same silent-truncation shape, lower stakes.

#### What we are NOT claiming

- **Not** that the cap of 2 is wrong. Two windows in flight is evidently the design maximum ("two verifiers per
  stage"), and the allocation-failure hint points at `--pipeline-windows 0` rather than higher.
- **Not** a functional defect: with a valid value (0/1/2) the flag behaves as documented, and we saw no wrong output.
- **Not** a performance claim about 2 vs 1 — we only used those two rows to show the knob is live.

En el sitio

Enlaces a install, modelos, releases.