Pull requests / #3095
#3095 batch: STRATA_PW_WITH_BATCH=1 keeps --pipeline-windows for a lone request beside --batch slots (+20% single-stream decode on a 2-card split, opt-in)
open · @Vop3p · 0 commentaires · Sur GitHub
BenchmarksSetup & installServer & APIMulti-GPUAMD / HIPNVIDIA / CUDAModels & quantsWindowsLinux
Description
## Summary
With `--batch` slots (`"parallel": N`), `--pipeline-windows` is turned off for the whole engine ("not with --batch slots"), so on a layer split a request that is **alone** also loses the two cards' overlap. On 2x RX 6900 XT that is 16-25% of single-stream decode (median 20%) with upstream otherwise.
`STRATA_PW_WITH_BATCH=1` (opt-in) keeps `--pipeline-windows` for the solo path when `--batch` is on. Batch windows run without it, as before.
## Why this is safe
- A request alone runs the solo path (GEN, with drafts; `serve/server.py` goes back to it when a slot is left alone, #857).
- Both parities' verifiers share the stage's session (`ver_b.init(.., gs.ss, ..)`), so when the solo request is STOPped for a newcomer, `copy_to_slot` reads a whole state from `ss` after the pipeline has drained.
- Batch windows never use the second verifiers.
- With `--batch-mtp`, the slot drafters are placed where the solo drafter is: on the first stage's card when `mtp_first`. They share its weights and draft head and copy the last stage's rows over, as the solo drafter does (`d->load(.., mtp_first ? bslot_ss[0][b] : bslot_ss.back()[b], ..)`, and the matching `bind`).
Off (the default), nothing changes: `batch_blocks_pw` equals the old `o.batch != 0` everywhere it is used.
## Measured
2x RX 6900 XT (gfx1030), ROCm 10.0, Linux. Flash-Next GSQ-RCO IQ3_S, 262144 context, `--kv int8 --kv-resident 32768`, layer split with part of the experts in RAM, `--spec 3 --spec-min-p 0.7`, `--pipeline-windows 2`, `"parallel": 2`, `--batch-groups 2 --batch-mtp`, config `"sampling": {"temperature": 0, "presence_penalty": 0}` (see #2940: a penalty sends the solo path to the serial loop and hides this change). A fresh engine per arm, order alternating within each pair, 32K prompt, 256 new tokens, 2 requests per arm.
**This branch's binary** (main + this commit only), otherwise upstream's opt-ins as we run them (`STRATA_SPLIT_MTP_BATCH=1`, `STRATA_SELECT_SIMT=1`, `STRATA_HC_PERSIST=1`, `STRATA_SH_STREAM=1`, `STRATA_HIP_PROMPT_F16=1`), 5 pairs:
| `STRATA_PW_WITH_BATCH` | 32K decode tok/s, median (range) | ms per decode window | drafts accepted | prompt read tok/s |
|---|---:|---:|---:|---:|
| unset / `0` | 61.7 (59.6-64.0) | 31.6 | 81.1% | 1,734 |
| `1` | **74.7 (68.1-81.4)** | **26.1** | 82.4% | 1,735 |
Per pair: +25.1, +20.4, +16.3, +25.4, +19.5%: median **+20.4%**, 5 of 5 in the same direction.
**Our production build** (0.1.45 with this patch, the #2235 pipelined slot drafts `STRATA_PIPE_MTP=1`, the HIP `STRATA_SELECT_SIMT=2` fix #3073, `STRATA_PIPED_CONCURRENT=1`, `STRATA_SPLIT_MTP_BATCH=0`), 10 pairs:
| `STRATA_PW_WITH_BATCH` | 32K decode tok/s, median (range) | ms per decode window | drafts accepted | prompt read tok/s |
|---|---:|---:|---:|---:|
| unset / `0` | 62.4 (59.0-64.8) | 31.7 | 79.0% | 1,722 |
| `1` | **71.5 (66.5-78.5)** | **26.8** | 79.5% | 1,725 |
Per pair: +11.5, +15.1, +14.4, +14.5, +13.3, +18.8, +14.1, +16.7, +13.3, +13.8%: median **+14.2%**, 10 of 10.
In both, the acceptance is unchanged, so the gain is the two cards overlapping (about 31.7 -> 26 ms per window); the prompt read is unchanged; 0 stalls in the 30 arms, and no arm logged a serial fallback. With `=1` the outputs are not token-identical between runs (as `--pipeline-windows` on the solo path anyway); with `=0` they are.
Confirmation lines: `--pipeline-windows 2 is off: not with --batch slots (STRATA_PW_WITH_BATCH=1 keeps it for the solo path)` with it off, `--pipeline-windows 2 stays on for the solo path beside 2 batch slots (STRATA_PW_WITH_BATCH=1); batch windows run without it` with it on.
This changes the solo path only; batch windows run exactly as before. I have not measured two streams with this patch alone. A long read with a short request waits for the read as before (36.7-37.4 s for a 64K read), unless `STRATA_PIPED_CONCURRENT=1` is set; see below.
## Known interaction
With `STRATA_PIPED_CONCURRENT=1`, the first request is on the solo path, so when a second one arrives it is stopped, moved into a slot, and continues after the newcomer's prompt is read: it does not decode beside that read (0 rows in our logs, while without this change the slot decodes beside it). The newcomer's TTFT is the same (8.2 s with a 64K read in flight).
## Tests
`tools/batch_test.py` on this branch's binary with `STRATA_PW_WITH_BATCH=1` (`STRATA_IQ_MT_MIN=1`, so `--pipeline-windows` decodes bit for bit), `--batch 2 --n 2 --max-new 256`: every slot IDENTICAL to its solo run in each of
- `--batch-groups 2` (pipelined groups; upstream turns `--batch-mtp` off there), with and without `--batch-mtp`;
- `--batch-groups 1 --batch-mtp`: `2 slot drafters on CUDA1` (the drafter on the last card, the default here);
- `--batch-groups 1 --batch-mtp` with `STRATA_MTP_STAGE0=1`: `2 slot drafters on CUDA0` and `drafter on CUDA0`, i.e. the `mtp_first` placement this patch adds.
No C++ unit test covers this path; the change is in `generate.cpp`'s setup and the slot drafters' load / bind.
---
Developed with an AI coding assistant; every number above was measured on 2x RX 6900 XT (gfx1030), ROCm 10.0, Linux.
Sur le site
Liens install, modèles, releases.