composes: env-override knobs MAX_MODEL_LEN + GPU_MEMORY_UTILIZATION (#79)
* composes: env-override knobs MAX_MODEL_LEN + GPU_MEMORY_UTILIZATION Two cross-rig users hit the same friction within hours of each other: - @laurimyllari (4090, disc #62 / issue #71): default max_model_len=180000 on long-text.yml exceeded his rig's KV-cache budget; had to drop to 90K - @PiotrZadka (disc #66): wants to run vLLM alongside a desktop session on the same GPU; needs to reserve some VRAM for X server / browser etc. Both root causes are the same: composes were calibrated for headless 3090 with no other VRAM consumers, and there's no clean override path short of hand-editing the YAML. Add env-substitution for the two knobs with the highest "shrink to fit" elasticity: --max-model-len ${MAX_MODEL_LEN:-<existing default>} --gpu-memory-utilization ${GPU_MEMORY_UTILIZATION:-<existing default>} Existing defaults preserved verbatim — zero behavior change for users who don't set the env. Pattern matches existing ${MODEL_DIR:-...}, ${PORT:-...}, ${HF_TOKEN:-...} substitutions in our composes. Usage: # Default (unchanged): bash scripts/switch.sh vllm/long-text # max_model_len=180000 # Override for desktop-coexist or sub-24 GB VRAM: MAX_MODEL_LEN=32768 GPU_MEMORY_UTILIZATION=0.80 \\ bash scripts/switch.sh vllm/long-text Validated end-to-end on long-text.yml: $ MAX_MODEL_LEN=32768 GPU_MEMORY_UTILIZATION=0.80 \\ bash scripts/switch.sh vllm/long-text $ docker exec vllm-qwen36-27b-long-text ps aux | grep vllm ... --max-model-len 32768 --gpu-memory-utilization 0.80 ... Default boot also unaffected: $ docker compose -f .../docker-compose.long-text.yml config | \\ grep -A1 "max-model-len\|gpu-memory-utilization" - --max-model-len - "180000" # original default preserved - --gpu-memory-utilization - "0.93" # original default preserved 18 vLLM composes touched. Mechanical find/replace; one YAML pattern, no logic changes. Doesn't touch llama-cpp composes (different flag shape; out of scope for this PR). Closes the friction reported on disc #62 + disc #66. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: env-override knobs for desktop-coexist + sub-24 GB usable VRAM Document MAX_MODEL_LEN + GPU_MEMORY_UTILIZATION env overrides shipped in the composes. Two surfaces: - docs/SINGLE_CARD.md "Running alongside a desktop / sub-24 GB usable VRAM" — explains the override pattern, when to drop which knob, safe ranges. Calls out empirically that GPU_MEMORY_UTILIZATION=0.80 is too aggressive for TQ3 KV paths (vLLM profiling overhead consumes more than the saved 0.05 budget; engine init reports 'No available memory for the cache blocks'). - docs/HARDWARE.md "Note for sub-24 GB cards" — adds a 4090-with-display paragraph above the existing 20 GB modded-3080 note. Cites @laurimyllari's MAX_MODEL_LEN=90000 fit on 4090 long-text.yml. Validated end-to-end during the env-override implementation: - ps aux inside container confirms override values reach vLLM CLI - Default boot unchanged (env unset → original values reach CLI) - 0.80 mem-util on long-text dies cleanly with the documented error, which is what surfaced the "stay 0.85-0.92 for TQ3" guidance Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: noonghunna <10742901+noonghunna@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,14 @@ The recipes are written against 3090 specifically but should work on:
|
||||
|
||||
On 20 GB cards (modded 3080) the cudagraph-profiling overhead is a meaningful slice of available VRAM. Drop `--gpu-memory-utilization` to **0.82** (vs shipped 0.95 for 24 GB). vLLM nightly's `gpu_worker.py` reports the equivalent effective KV size in the boot log; tune to keep activation headroom for the ~15K tool-prefill peak (verify-full check 8). Credit: [@troymroberts](https://github.com/troymroberts).
|
||||
|
||||
**4090s with attached display — env-override the compose defaults.** Some 4090 rigs land at ~23.5 GB usable VRAM with X server + driver overhead, vs the headless 3090s the composes are calibrated for. Boot may fail with `No available memory for the cache blocks` at default `max-model-len`. Cross-rig data: @laurimyllari's 4090 single-card on `long-text.yml` needed `MAX_MODEL_LEN=90000` (down from 180K default) to fit cleanly ([disc #62](../../../noonghunna/club-3090/discussions/62) / [issue #71](../../../noonghunna/club-3090/issues/71)). Pattern:
|
||||
|
||||
```bash
|
||||
MAX_MODEL_LEN=90000 bash scripts/switch.sh vllm/long-text
|
||||
```
|
||||
|
||||
Same `MAX_MODEL_LEN` / `GPU_MEMORY_UTILIZATION` env overrides apply for any setup running vLLM alongside other GPU consumers on the same card. See [SINGLE_CARD.md "Running alongside a desktop"](SINGLE_CARD.md#running-alongside-a-desktop--sub-24-gb-usable-vram) for safe ranges.
|
||||
|
||||
**`dual-turbo.yml` on 20 GB Ampere — swap TQ3 KV → fp8_e5m2.** The shipped `dual-turbo.yml` uses `--kv-cache-dtype turboquant_3bit_nc` (the technique from [TurboQuant: Online Vector Quantization with Near-optimal Distortion Rate](https://arxiv.org/abs/2504.19874), ICLR 2026 — random rotation + scalar quantizers + 1-bit QJL transform on the residual; the paper claims absolute quality neutrality at 3.5 bits/channel). It's the right pick on 24 GB / 3090: smaller KV pool → more concurrency, and the 24 GB budget absorbs the dequant activation cost during the DeltaNet GDN forward. On 20 GB cards the trade flips: TQ3's activation peak (~1 GB/card more pressure than fp8 during the materialized block — see [PerfMamba arxiv 2511.22849](https://arxiv.org/html/2511.22849) for the underlying Mamba-2 block-state-materialization mechanism the GDN forward inherits) exceeds the per-card budget after TP=2 split, and Cliff 2 fires at 90K. **Override to `--kv-cache-dtype fp8_e5m2`** and you get the full 262K context working with verify-stress 7/7 PASS including 91K needles. Validated 2026-05-04 by [@efschu](https://github.com/noonghunna/club-3090/issues/47) on 2× 3080 modded 20 GB at 0.82 mem-util: bench 82.4 narr / 107.9 code TPS, full 257K-token auto-discovery needle PASS at 90% depth. Trade-off: fp8 KV is roomier per cached token but each token's KV state is larger, so concurrency at full ctx drops vs TQ3. Single-stream long-ctx works cleanly.
|
||||
|
||||
---
|
||||
|
||||
@@ -179,6 +179,23 @@ What still keeps it off the recommended list:
|
||||
|
||||
vLLM ships this off by default. Our composes set `--tool-call-parser qwen3_coder` + `--enable-auto-tool-choice`. If you're rolling your own compose, both are required.
|
||||
|
||||
### Running alongside a desktop / sub-24 GB usable VRAM
|
||||
|
||||
The compose defaults are calibrated for **headless** 3090 (no display server, no other GPU consumers). If you're running on a workstation where the same GPU also drives a desktop session — or your card has slightly less effective VRAM (e.g., some 4090s land at ~23.5 GB usable with X server overhead) — the default `max-model-len` may exceed your KV-cache budget at default `gpu-memory-utilization`.
|
||||
|
||||
Two env-override knobs available on every vLLM compose (defaults preserved if unset):
|
||||
|
||||
```bash
|
||||
MAX_MODEL_LEN=32768 \
|
||||
GPU_MEMORY_UTILIZATION=0.80 \
|
||||
bash scripts/switch.sh vllm/long-text
|
||||
```
|
||||
|
||||
- `MAX_MODEL_LEN` — shrink the KV-cache budget; trades long-context for fit. `90000` is a safe value for `long-text.yml` on rigs with ~1 GB of overhead (4090 with display, etc.). Validated on @laurimyllari's 4090 ([disc #62](../../../noonghunna/club-3090/discussions/62)).
|
||||
- `GPU_MEMORY_UTILIZATION` — reserve a percentage of VRAM for non-vLLM GPU consumers. **Stay in `0.85-0.92` range** for TQ3 KV paths on 24 GB Ampere. `0.80` is generally too aggressive — vLLM's profiling phase eats more than the saved 0.05 budget and reports `No available memory for the cache blocks` at engine init. fp8 KV paths (`tools-text.yml`, `dual.yml`) tolerate `0.80` better.
|
||||
|
||||
Generally prefer **dropping `MAX_MODEL_LEN` first** (clean KV budget reduction, predictable behavior) over `GPU_MEMORY_UTILIZATION` (interacts with profiling overhead in non-obvious ways). Drop both if your envelope is really tight.
|
||||
|
||||
---
|
||||
|
||||
## Quick start
|
||||
|
||||
@@ -104,9 +104,9 @@ services:
|
||||
# to reclaim ~1.5 GB and skip the mm-token-budget assertion.
|
||||
# Drop max-model-len 32K → 16K for headroom.
|
||||
- --max-model-len
|
||||
- "8192"
|
||||
- "${MAX_MODEL_LEN:-8192}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.95"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.95}"
|
||||
- --max-num-seqs
|
||||
- "256"
|
||||
# max_tokens_per_mm_item=2496 must fit in batched tokens — even with
|
||||
|
||||
@@ -101,9 +101,9 @@ services:
|
||||
- "2"
|
||||
- --disable-custom-all-reduce
|
||||
- --max-model-len
|
||||
- "32768"
|
||||
- "${MAX_MODEL_LEN:-32768}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.92"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.92}"
|
||||
- --max-num-seqs
|
||||
- "4"
|
||||
# Vision tower: max_tokens_per_mm_item=2496 must fit in batched tokens.
|
||||
|
||||
@@ -257,9 +257,9 @@ services:
|
||||
# on 2026-05-02 to give activation headroom for the PN12+PN25 FFN pool
|
||||
# residence + DeltaNet GDN buffer. See long-text.yml for full rationale.
|
||||
- --max-model-len
|
||||
- "180000"
|
||||
- "${MAX_MODEL_LEN:-180000}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.95"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.95}"
|
||||
- --max-num-seqs
|
||||
- "1"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -91,9 +91,9 @@ services:
|
||||
- "2"
|
||||
- --disable-custom-all-reduce
|
||||
- --max-model-len
|
||||
- "262144"
|
||||
- "${MAX_MODEL_LEN:-262144}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.92"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.92}"
|
||||
- --max-num-seqs
|
||||
- "2"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -79,9 +79,9 @@ services:
|
||||
- "2"
|
||||
- --disable-custom-all-reduce
|
||||
- --max-model-len
|
||||
- "200000"
|
||||
- "${MAX_MODEL_LEN:-200000}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.95"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.95}"
|
||||
- --max-num-seqs
|
||||
- "1"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -103,9 +103,9 @@ services:
|
||||
- "2"
|
||||
- --disable-custom-all-reduce
|
||||
- --max-model-len
|
||||
- "185000"
|
||||
- "${MAX_MODEL_LEN:-185000}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.95"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.95}"
|
||||
- --max-num-seqs
|
||||
- "1"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -212,9 +212,9 @@ services:
|
||||
# makes vLLM's custom kernel a win. dual-turbo.yml disables it because
|
||||
# PCIe P2P bandwidth makes the NCCL fallback faster there.
|
||||
- --max-model-len
|
||||
- "262144"
|
||||
- "${MAX_MODEL_LEN:-262144}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.85"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.85}"
|
||||
- --max-num-seqs
|
||||
- "4"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -104,9 +104,9 @@ services:
|
||||
# makes vLLM's custom kernel a win. dual.yml disables it because PCIe
|
||||
# P2P bandwidth makes the NCCL fallback faster there.
|
||||
- --max-model-len
|
||||
- "262144"
|
||||
- "${MAX_MODEL_LEN:-262144}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.92"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.92}"
|
||||
- --max-num-seqs
|
||||
- "2"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -189,9 +189,9 @@ services:
|
||||
- "2"
|
||||
- --disable-custom-all-reduce
|
||||
- --max-model-len
|
||||
- "262144"
|
||||
- "${MAX_MODEL_LEN:-262144}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.85"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.85}"
|
||||
- --max-num-seqs
|
||||
- "4"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -90,9 +90,9 @@ services:
|
||||
- "2"
|
||||
- --disable-custom-all-reduce
|
||||
- --max-model-len
|
||||
- "262144"
|
||||
- "${MAX_MODEL_LEN:-262144}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.92"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.92}"
|
||||
- --max-num-seqs
|
||||
- "2"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -98,9 +98,9 @@ services:
|
||||
- "4"
|
||||
- --disable-custom-all-reduce
|
||||
- --max-model-len
|
||||
- "262144"
|
||||
- "${MAX_MODEL_LEN:-262144}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.95"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.95}"
|
||||
- --max-num-seqs
|
||||
- "2"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -102,9 +102,9 @@ services:
|
||||
- "4"
|
||||
- --disable-custom-all-reduce
|
||||
- --max-model-len
|
||||
- "262144"
|
||||
- "${MAX_MODEL_LEN:-262144}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.92"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.92}"
|
||||
- --max-num-seqs
|
||||
- "4"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -308,7 +308,7 @@ services:
|
||||
# club-3090#16 — different bug (Cliff 1 mech B inductor leak), not
|
||||
# fixed by mem-util tuning. Use tools-text.yml for those.
|
||||
- --max-model-len
|
||||
- "200000"
|
||||
- "${MAX_MODEL_LEN:-200000}"
|
||||
# 0.95 — backed off from 0.97 on 2026-05-01 PM after PN25 v3 closed
|
||||
# Cliff 1 mech B at the FFN intermediate buffer (which now sits in
|
||||
# PN12+PN25's resident FFNIntermediateCache pool). Pool residence
|
||||
@@ -317,7 +317,7 @@ services:
|
||||
# 0.97 left only 26 MiB free, OOM at 9.8K probe. 0.95 frees ~480 MiB
|
||||
# activation budget, validated up to 30K probes.
|
||||
- --gpu-memory-utilization
|
||||
- "0.95"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.95}"
|
||||
- --max-num-seqs
|
||||
- "1"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -325,7 +325,7 @@ services:
|
||||
# club-3090#16 — different bug (Cliff 1 mech B inductor leak), not
|
||||
# fixed by mem-util tuning. Use tools-text.yml for those.
|
||||
- --max-model-len
|
||||
- "180000"
|
||||
- "${MAX_MODEL_LEN:-180000}"
|
||||
# 0.95 — backed off from 0.97 on 2026-05-01 PM after PN25 v3 closed
|
||||
# Cliff 1 mech B at the FFN intermediate buffer (which now sits in
|
||||
# PN12+PN25's resident FFNIntermediateCache pool). Pool residence
|
||||
@@ -334,7 +334,7 @@ services:
|
||||
# 0.97 left only 26 MiB free, OOM at 9.8K probe. 0.95 frees ~480 MiB
|
||||
# activation budget, validated up to 30K probes.
|
||||
- --gpu-memory-utilization
|
||||
- "0.93"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.93}"
|
||||
- --max-num-seqs
|
||||
- "1"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -231,9 +231,9 @@ services:
|
||||
# Engine pre-check at 175K + 0.95 returned `estimated maximum model length
|
||||
# is 148608` — falls back to 145K for safety margin.
|
||||
- --max-model-len
|
||||
- "145000"
|
||||
- "${MAX_MODEL_LEN:-145000}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.95"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.95}"
|
||||
- --max-num-seqs
|
||||
- "1"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -64,9 +64,9 @@ services:
|
||||
- --tensor-parallel-size
|
||||
- "1"
|
||||
- --max-model-len
|
||||
- "32768"
|
||||
- "${MAX_MODEL_LEN:-32768}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.92"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.92}"
|
||||
- --max-num-seqs
|
||||
- "1"
|
||||
- --kv-cache-dtype
|
||||
|
||||
@@ -114,9 +114,9 @@ services:
|
||||
- --tensor-parallel-size
|
||||
- "1"
|
||||
- --max-model-len
|
||||
- "75000"
|
||||
- "${MAX_MODEL_LEN:-75000}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.97"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.97}"
|
||||
- --max-num-seqs
|
||||
- "1"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
@@ -194,9 +194,9 @@ services:
|
||||
# - long-vision.yml → 198K + vision + sidecars (Cliff 1 closed; Cliff 2 caveat)
|
||||
# - long-text.yml → 218K text-only + sidecars (same Cliff 2 caveat)
|
||||
- --max-model-len
|
||||
- "48000"
|
||||
- "${MAX_MODEL_LEN:-48000}"
|
||||
- --gpu-memory-utilization
|
||||
- "0.92"
|
||||
- "${GPU_MEMORY_UTILIZATION:-0.92}"
|
||||
- --max-num-seqs
|
||||
- "1"
|
||||
- --max-num-batched-tokens
|
||||
|
||||
Reference in New Issue
Block a user