Skip to content
Merged
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ cargo run --release --features glm52 -- --model-path models/GLM5.2
- `PEGAINFER_NVCC_JOBS` — override parallel nvcc job count
- `PEGAINFER_KV_FP8` — gemma4 opt-in fp8 KV: `local` stores the sliding family's K/V as e4m3 at scale 1.0 (lossy; halves the local pool; refuses an enabled prefix cache; unset = byte-identical serving)
- `PEGAINFER_PREFIX_CACHE` — gemma4 opt-in conversation prefix cache: `K` entries of captured prompt state resume multi-turn prompts (pre-allocated page budget; unset = off, byte-identical serving)
- `PEGAINFER_ADMIT_COALESCE_MS` — gemma4 opt-in admission coalesce door: `N` ms in `1..=2000` (`off`/`0`/unset = admit on sight), holds arrivals that would invade a live decode batch so a window's arrivals land as one admission burst; refuses the async prefill lane; merging into one mixed step needs the chunked walk or a sub-budget prompt
- `PEGAINFER_ASYNC_PREFILL` — gemma4 opt-in overlap lane: `green:NN` prefills live-batch admissions on an SM-capped stream to protect decode tails (`shared` for comparison; unset = off; bad values refuse to start)
- `PEGAINFER_MIX_CHUNK_TOKENS` — gemma4 opt-in chunked walk: a mixed admission computes at most `N` prompt rows per step (`64 <= N <` the serving ceiling; unset = whole-prompt steps; bad values refuse to start)
- `PEGAINFER_MAX_CONTEXT` — gemma4 serving ceiling raise (default 8192, up to the checkpoint's 262144; a raise past the default needs `PEGAINFER_MIX_CHUNK_TOKENS` and refuses the async lane)
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Organized by domain (model line / subsystem / playbook / lesson) instead of by l
| Path | TL;DR |
| --- | --- |
| `models/gemma4/tokenizer.md` | Gemma 4 tokenizer/chat-template contracts, gated against a Hugging Face reference (token ids plus all five chat renders, content flattened to strings): BOS comes only from the standalone `chat_template.jinja` (which opens a thought channel and accepts a native system role), EOS is declared three times with three values, the published defaults are sampled rather than greedy, image/audio tokens encode straight from user text so text-only serving must reject them at admission, and one divergence stays open — the server's default content format adds a trailing space to system turns. |
| `models/gemma4/serving.md` | What the engine promises under load: iteration level scheduling with a ceiling on prompt plus output (8192 by default), prompts prefilled whole at a step boundary by default, requests beyond the configured decode slots (16 by default) queued rather than refused, and the two KV families budgeted separately (7.27 GiB sliding + 2.00 GiB global at 12B with the chunk knob off; the sliding budget shrinks to window plus segment under it). The default configuration needs a 48 GiB card: 32.2 GiB resident before the first request. Clients must send `<bos>` themselves or the model degenerates. A row is bit-identical when its companions' content and lengths change under a fixed batch width trajectory, and moves when arrivals or retirements change that trajectory, so greedy output is reproducible for a workload rather than across workloads. An opt-in conversation prefix cache (`PEGAINFER_PREFIX_CACHE=K`) resumes multi-turn prompts from captured prompt state at a pre-allocated page cost. An opt-in chunked walk (`PEGAINFER_MIX_CHUNK_TOKENS=N`) walks admissions through shared segment steps with round-by-round page reservation, and `PEGAINFER_MAX_CONTEXT` raises the ceiling to the checkpoint's 262144 while `PEGAINFER_DECODE_SLOTS` trades concurrency for the memory that buys. Open: no cross-request prefix sharing, single GPU. |
| `models/gemma4/serving.md` | What the engine promises under load: iteration level scheduling with a ceiling on prompt plus output (8192 by default), prompts prefilled whole at a step boundary by default, requests beyond the configured decode slots (16 by default) queued rather than refused, and the two KV families budgeted separately (7.27 GiB sliding + 2.00 GiB global at 12B with the chunk knob off; the sliding budget shrinks to window plus segment under it). The default configuration needs a 48 GiB card: 32.2 GiB resident before the first request. Clients must send `<bos>` themselves or the model degenerates. A row is bit-identical when its companions' content and lengths change under a fixed batch width trajectory, and moves when arrivals or retirements change that trajectory, so greedy output is reproducible for a workload rather than across workloads. An opt-in conversation prefix cache (`PEGAINFER_PREFIX_CACHE=K`) resumes multi-turn prompts from captured prompt state at a pre-allocated page cost. An opt-in chunked walk (`PEGAINFER_MIX_CHUNK_TOKENS=N`) walks admissions through shared segment steps with round-by-round page reservation, and `PEGAINFER_MAX_CONTEXT` raises the ceiling to the checkpoint's 262144 while `PEGAINFER_DECODE_SLOTS` trades concurrency for the memory that buys. `PEGAINFER_ADMIT_COALESCE_MS=N` batches arrivals that would interrupt a live decode batch into one admission burst, defaults off, and refuses the async lane. Open: no cross-request prefix sharing, single GPU. |
| `models/gemma4/hf-golden.md` | Three Hugging Face references for 12B. The base fixture carries layer-boundary activations at both ends of both layer types plus top-64 logprobs, over a single-token, a nine-token and a 1024-token (exactly the sliding window) case, and pins three facts the forward path has to match — the embedding scale is bf16 62.0 rather than `sqrt(3840)`, text attention is causal, and `layer_scalar` applies to the layer output after both residual adds. The window fixture goes past the window (1023/1024/1025/4096, teacher-forced) under both sdpa and eager. The long-context fixture takes the same comparison to 16384/32768 for the raised ceiling, sdpa-only, with the window fixture's dual-backend floor on loan. Regeneration is byte-identical and checked with sha256. |

## models / glm52
Expand Down
6 changes: 6 additions & 0 deletions docs/models/gemma4/serving.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ The cache brings its own page budget, added to the pool lines above at startup.

At `PEGAINFER_PREFIX_CACHE=16` the idle footprint measured **39242 MiB** against the 33034 MiB baseline — the difference is the pre-allocated cache budget.

## The admission coalesce door (opt-in)

`PEGAINFER_ADMIT_COALESCE_MS=N` (`1..=2000`; unset, `off` or `0` admits on sight) holds arrivals that would invade a live decode batch, then releases a window's arrivals as one back-to-back admission burst. It prices the number of admission interruptions, not their size: whole prompts beyond the 512-row gather budget still take separate weight scans unless `PEGAINFER_MIX_CHUNK_TOKENS` enables the chunked walk. An idle engine admits immediately, and a shallow roster skips the door when `(active + pending) * 2 < slots`.

A deep roster releases when the window expires or the pending queue reaches `min(4, slots - active)`, with a floor of one. A full cohort releases before `N`; the timeout release lands no earlier than `N`, at the first intake turn after the window elapses — the engine drains its submission channel before each intake, so there is no hard bound on how much later. That cohort is a capacity bound over the currently free slots, not a cross-completion batch. The door refuses to combine with `PEGAINFER_ASYNC_PREFILL`, whose single in-flight prefill could only be delayed by it. Measured under sustained load, c16 median TPOT improves about 8.5% for about +288 ms median TTFT; c8 pays about 5.7% throughput and about +19 ms TTFT. P99 ITL is flat to slightly worse everywhere, so the door remains off by default.

## The async prefill lane (opt-in)

When `PEGAINFER_ASYNC_PREFILL` is unset, serving uses the normal mixed-step path; when set, a live-batch admission's prefill moves onto its own stream so decode steps keep replaying while the prompt computes. Dense and routed checkpoints share this path at the default context ceiling. `green:NN` pins the lane to roughly NN% of the SMs via a Green Context — the cap is the mechanism: a `shared` lane's full-width prefill grids starve decode steps, and is kept only for comparison. An unrecognized value or an unviable SM partition refuses to start rather than silently degrading.
Expand Down
Loading
Loading