v0.20 migration + Genesis v7.65 dev tip + cold-start cache + env-var alignment

This branch migrates the entire vLLM stack from `dev205+g07351e088` + Genesis
v7.64 to `0.20.1rc1.dev16+g7a1eb8ac2` + Genesis v7.65 dev tip (commit
`d89a089`). v7.65 is on Sandermage's `dev` branch — explicitly the cross-rig
testing surface he requested in discussion #19; he'll merge dev→main once we
both confirm stable. Pin gates restated when that lands.

What changes
------------

Pin migration:
- vLLM image: nightly-07351e08... → nightly-7a1eb8ac2... (dev205 → v0.20.1rc1.dev16)
- Genesis: 64dd18b (v7.64) → d89a089 (v7.65 dev tip)

Sidecar churn:
- DROPPED: patch_pn12_ffn_pool_anchor.py (PN12 native on v0.20)
- DROPPED: patch_pn12_compile_safe_custom_op.py (Genesis P38B in-source hook)
- DROPPED: patch_fa_max_seqlen_clamp.py (Genesis PN17 + P15B)
- ADDED: patch_workspace_lock_disable.py (relaxes vllm#39226 strict assertion;
  P98 covers same surface but auto-skips on v0.20 due to drift-marker false
  positive — pending Sandermage marker fix)

Env-var alignment to Sandermage's PROD set (start_27b_int4_TQ_k8v4.sh@dev):
- FIXED naming bugs that silently no-op'd patches:
  - PN9_INDEPENDENT_DRAFTER_ATT → _ATTN (was silently OFF)
  - PN22 → PN22_LOCAL_ARGMAX_TP (was silently OFF)
  - PN26_BLOCK_KV → PN26_SPARSE_V_BLOCK_KV (fell back to default 4, not 8)
  - PN26_NUM_WARPS → PN26_SPARSE_V_NUM_WARPS
  - PN26_THRESHOLD → PN26_SPARSE_V_THRESHOLD (fell back to default 0.001, not 0.01)
- ADDED explicit-OFFs to match Sander's PROD verbatim:
  - P78_TOLIST_CAPTURE_GUARD=0 (we use our own patch_tolist_cudagraph.py)
  - P81_FP8_BLOCK_SCALED_M_LE_8=0 (FP8-specific, no-op on TQ3)
  - P82=0, P82_THRESHOLD_SINGLE=0.3
- Cap divergence (justified): PROFILE_RUN_CAP_M=4128 + PREALLOC_TOKEN_BUDGET=4128
  (Sander uses 4096 — vLLM `interface.py:639` forces our config's Mamba
  block_size to 4128 due to TQ3 + TP=1 page-size math; lower values
  AssertionError at boot)
- Carry-forward (intentional): P4 (hybrid TQ required), P65 (TQ spec-CG
  downgrade — pending v0.20 verification that #40880 closure makes it
  redundant)

Cold-start cache mounts (closes #22):
- All 10 composes now mount torch_compile_cache + Triton cache from
  `models/qwen3.6-27b/vllm/cache/`. First boot warms (~6 min); warm boot
  drops to ~3.2 min (47% faster). Per-stage savings on long-text:
  - Dynamo bytecode transform: 18s → 5s (-73%)
  - torch.compile: 57s → 9s (-85%)
  - Initial profiling/warmup: 51s → 7s (-87%)

Mamba block_size cap fix:
- v0.20 enforces `long_prefill_token_threshold >= block_size`; on hybrid
  Mamba+TQ3, vLLM forces block_size=4128. Bumped GENESIS_PROFILE_RUN_CAP_M
  and PREALLOC_TOKEN_BUDGET 4096→4128 across all 5 main composes.

Default 48K compose:
- Required workspace_lock_disable sidecar after initial v0.20 boot hit
  vllm#39226 strict assertion. Caught during validation, fixed.

Context restored vs dev205 backoffs (validated 33K + 50K stress on v0.20):
- long-text:        185K → 214K (+16%)
- long-vision:      140K → 198K (+41%)
- bounded-thinking: 185K → 214K (+16%)

Bench results (n=5, results/v0.20-migration/):
- long-text 214K        narr 49.74 / code 67.39 (CV 2.6/2.7%)
- long-vision 198K      narr 50.32 / code 66.12 (CV 2.3/4.1%)
- bounded-thinking 214K narr 49.77 / code 65.80 (CV 1.4/2.3%)
- tools-text 75K (fp8)  narr 53.32 / code 69.66 (CV 2.3/1.4%)
- dual-turbo 262K (TP=2) narr 58.33 / code 76.01 per-stream
                         269 TPS aggregate at n=4 streams (3.63x speedup)
- default 48K           narr 48.82 / code 65.98 (n=3)

Validation: verify-full 8/8 on every variant. verify-stress 33K AND 50K
tool-prefill PASS on every variant — the cliff that fired on EVERY dev205
config no longer reproduces.

Docs + charts:
- README + SINGLE_CARD + DUAL_CARD + CLIFFS + EXAMPLES + STRUCTURED_COT
  + FAQ + UPSTREAM + 3 engine docs + model README + INTERNALS + CHANGELOG
  all updated with new pin, ctx, TPS numbers, and "v0.20 unblock" section
- performance.{png,svg} + variants regenerated with measured TPS
- vram-budget.{png,svg} + variants regenerated with measured VRAM
- UPSTREAM tracker: 5 issues moved  closed (PR #12, #13, #14, #15, P104
  superseded by PN17 + P15B)

Issues addressed:
- #16 (Cliff 1 mech B leaks past PN12 on inductor-compiled FFN) — partial:
  v0.20's revised TQ FA paths close the synthetic stress; PN25 (Sander's
  proper compile-path opaque-op fix) is on dev but explicitly opt-in pending
  worker-fork registration fix. Workarounds documented (tools-text fp8 path
  / --enforce-eager) until Sander ships PN25 default-on.
- #20 (launch.sh port + container-name mismatch) — already closed by
  77ca576 (post-issue-filing).
- #22 (cold-start caching) — closed by cache mounts above.

Remaining caveats:
- Cliff 2 (DeltaNet GDN forward, single prompt ≥50-60K) unchanged —
  architectural, applies to all single-card vLLM TQ3 paths. Mitigation:
  dual-turbo TP=2 (state splits across cards) or llama.cpp 262K.
- Default 48K narr_TPS (48.82) slightly under chart's 55 reference —
  bench variance + sample size n=3; not regression.
- Dual.yml / dual-dflash* not re-benched on v0.20; numbers carry forward
  from dev205 (fp8 paths were not TPS-changed by the migration).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
noonghunna
2026-05-01 18:33:01 +00:00
parent 60d7b02c55
commit 5aa97a25d9
64 changed files with 5890 additions and 5051 deletions

View File

@@ -0,0 +1,45 @@
========== NARRATIVE (prompt=65 chars, max_tokens=1000) ==========
=== warmups (3) ===
warm-1 wall= 24.01s ttft= 5266ms toks=1000 wall_TPS= 41.65 decode_TPS= 53.35
warm-2 wall= 19.17s ttft= 153ms toks=1000 wall_TPS= 52.15 decode_TPS= 52.57
warm-3 wall= 19.53s ttft= 155ms toks=1000 wall_TPS= 51.20 decode_TPS= 51.61
=== measured (5) ===
run-1 wall= 19.87s ttft= 149ms toks=1000 wall_TPS= 50.33 decode_TPS= 50.71
run-2 wall= 20.41s ttft= 158ms toks= 996 wall_TPS= 48.80 decode_TPS= 49.18
run-3 wall= 19.97s ttft= 160ms toks=1000 wall_TPS= 50.07 decode_TPS= 50.48
run-4 wall= 20.27s ttft= 151ms toks=1000 wall_TPS= 49.34 decode_TPS= 49.71
run-5 wall= 19.87s ttft= 155ms toks=1000 wall_TPS= 50.32 decode_TPS= 50.72
=== summary [narrative] (n=5) ===
wall_TPS mean= 49.77 std= 0.68 CV= 1.4% min=48.80 max=50.33
decode_TPS mean= 50.16 std= 0.68 CV= 1.4% min=49.18 max=50.72
TTFT mean= 155ms std= 5ms min=149ms max=160ms
========== CODE (prompt=78 chars, max_tokens=800) ==========
=== warmups (3) ===
warm-1 wall= 12.54s ttft= 159ms toks= 800 wall_TPS= 63.78 decode_TPS= 64.60
warm-2 wall= 11.93s ttft= 154ms toks= 800 wall_TPS= 67.04 decode_TPS= 67.92
warm-3 wall= 12.02s ttft= 153ms toks= 800 wall_TPS= 66.58 decode_TPS= 67.43
=== measured (5) ===
run-1 wall= 10.04s ttft= 160ms toks= 642 wall_TPS= 63.94 decode_TPS= 64.97
run-2 wall= 12.00s ttft= 147ms toks= 799 wall_TPS= 66.59 decode_TPS= 67.41
run-3 wall= 12.09s ttft= 156ms toks= 800 wall_TPS= 66.16 decode_TPS= 67.03
run-4 wall= 12.37s ttft= 153ms toks= 800 wall_TPS= 64.67 decode_TPS= 65.48
run-5 wall= 8.47s ttft= 155ms toks= 573 wall_TPS= 67.66 decode_TPS= 68.93
=== summary [code] (n=5) ===
wall_TPS mean= 65.80 std= 1.50 CV= 2.3% min=63.94 max=67.66
decode_TPS mean= 66.77 std= 1.58 CV= 2.4% min=64.97 max=68.93
TTFT mean= 154ms std= 5ms min=147ms max=160ms
=== GPU state ===
0, 98 %, 21704 MiB, 24576 MiB, 229.02 W, 62
1, 0 %, 4 MiB, 24576 MiB, 21.51 W, 40
=== Last 3 SpecDecoding metrics ===
(APIServer pid=1) INFO 05-01 16:37:10 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.41, Accepted throughput: 45.80 tokens/s, Drafted throughput: 57.00 tokens/s, Accepted: 458 tokens, Drafted: 570 tokens, Per-position acceptance rate: 0.926, 0.811, 0.674, Avg Draft acceptance rate: 80.4%
(APIServer pid=1) INFO 05-01 16:37:20 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.25, Accepted throughput: 43.00 tokens/s, Drafted throughput: 57.30 tokens/s, Accepted: 430 tokens, Drafted: 573 tokens, Per-position acceptance rate: 0.895, 0.764, 0.592, Avg Draft acceptance rate: 75.0%
(APIServer pid=1) INFO 05-01 16:37:30 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.61, Accepted throughput: 49.89 tokens/s, Drafted throughput: 57.29 tokens/s, Accepted: 499 tokens, Drafted: 573 tokens, Per-position acceptance rate: 0.958, 0.895, 0.759, Avg Draft acceptance rate: 87.1%

View File

@@ -0,0 +1,21 @@
variant: bounded-thinking
context: 214000
gpu_mem_util: 0.985
kv_dtype: turboquant_3bit_nc
tp: 1
narr_wall_tps: 49.77
narr_wall_cv: 1.4
narr_decode_tps: 50.16
code_wall_tps: 65.80
code_wall_cv: 2.3
code_decode_tps: 66.77
ttft_narr_ms: 155
ttft_code_ms: 154
mtp_al: 3.25-3.61
mtp_avg_accept: 0.75-0.871
mtp_per_pos: 0.895-0.958 / 0.764-0.895 / 0.592-0.759
vram_gpu0_mib: 21704
kv_pool_tokens: 284832
max_concurrency: 1.03
boot_seconds: 200
notes: structured-CoT FSM-grammar enabled; same TPS as long-text (FSM is decode-time mask only)

View File

@@ -0,0 +1,41 @@
========== NARRATIVE (prompt=65 chars, max_tokens=1000) ==========
=== warmups (3) ===
warm-1 wall= 25.85s ttft= 5813ms toks=1000 wall_TPS= 38.68 decode_TPS= 49.90
warm-2 wall= 20.28s ttft= 157ms toks=1000 wall_TPS= 49.31 decode_TPS= 49.70
warm-3 wall= 19.62s ttft= 166ms toks=1000 wall_TPS= 50.96 decode_TPS= 51.39
=== measured (3) ===
run-1 wall= 20.60s ttft= 159ms toks=1000 wall_TPS= 48.55 decode_TPS= 48.93
run-2 wall= 20.36s ttft= 160ms toks=1000 wall_TPS= 49.11 decode_TPS= 49.50
run-3 wall= 20.49s ttft= 156ms toks=1000 wall_TPS= 48.82 decode_TPS= 49.19
=== summary [narrative] (n=3) ===
wall_TPS mean= 48.82 std= 0.28 CV= 0.6% min=48.55 max=49.11
decode_TPS mean= 49.20 std= 0.28 CV= 0.6% min=48.93 max=49.50
TTFT mean= 158ms std= 2ms min=156ms max=160ms
========== CODE (prompt=78 chars, max_tokens=800) ==========
=== warmups (3) ===
warm-1 wall= 7.47s ttft= 157ms toks= 483 wall_TPS= 64.63 decode_TPS= 66.02
warm-2 wall= 9.92s ttft= 162ms toks= 641 wall_TPS= 64.63 decode_TPS= 65.70
warm-3 wall= 12.24s ttft= 157ms toks= 800 wall_TPS= 65.34 decode_TPS= 66.19
=== measured (3) ===
run-1 wall= 11.10s ttft= 155ms toks= 704 wall_TPS= 63.44 decode_TPS= 64.34
run-2 wall= 11.39s ttft= 156ms toks= 771 wall_TPS= 67.71 decode_TPS= 68.65
run-3 wall= 11.98s ttft= 161ms toks= 800 wall_TPS= 66.78 decode_TPS= 67.69
=== summary [code] (n=3) ===
wall_TPS mean= 65.98 std= 2.24 CV= 3.4% min=63.44 max=67.71
decode_TPS mean= 66.89 std= 2.26 CV= 3.4% min=64.34 max=68.65
TTFT mean= 157ms std= 4ms min=155ms max=161ms
=== GPU state ===
0, 92 %, 20826 MiB, 24576 MiB, 228.71 W, 65
1, 0 %, 4 MiB, 24576 MiB, 22.25 W, 45
=== Last 3 SpecDecoding metrics ===
(APIServer pid=1) INFO 05-01 17:41:54 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.34, Accepted throughput: 44.69 tokens/s, Drafted throughput: 57.29 tokens/s, Accepted: 447 tokens, Drafted: 573 tokens, Per-position acceptance rate: 0.916, 0.764, 0.660, Avg Draft acceptance rate: 78.0%
(APIServer pid=1) INFO 05-01 17:42:04 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.45, Accepted throughput: 46.70 tokens/s, Drafted throughput: 57.30 tokens/s, Accepted: 467 tokens, Drafted: 573 tokens, Per-position acceptance rate: 0.953, 0.832, 0.660, Avg Draft acceptance rate: 81.5%
(APIServer pid=1) INFO 05-01 17:42:14 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.47, Accepted throughput: 46.90 tokens/s, Drafted throughput: 57.00 tokens/s, Accepted: 469 tokens, Drafted: 570 tokens, Per-position acceptance rate: 0.958, 0.826, 0.684, Avg Draft acceptance rate: 82.3%

View File

@@ -0,0 +1,20 @@
variant: default 48K
context: 48000
gpu_mem_util: 0.92
kv_dtype: turboquant_3bit_nc
tp: 1
narr_wall_tps: 48.82
narr_wall_cv: 0.6
narr_decode_tps: 49.20
code_wall_tps: 65.98
code_wall_cv: 3.4
code_decode_tps: 66.89
ttft_narr_ms: 158
ttft_code_ms: 157
mtp_al: 3.34-3.47
mtp_avg_accept: 0.78-0.823
vram_gpu0_mib: 20826
kv_pool_tokens: 148608
max_concurrency: 1.33
boot_seconds: 200
notes: Required workspace_lock_disable sidecar to be added (initial v0.20 boot hit vllm#39226 strict assertion). After fix, bench n=3 GREEN. Slightly slower than tools-text/long-text on this run (variance + sample size). Below both prefill cliffs — production-safe default.

View File

@@ -0,0 +1,45 @@
========== NARRATIVE (prompt=65 chars, max_tokens=1000) ==========
=== warmups (3) ===
warm-1 wall= 23.06s ttft= 4096ms toks=1000 wall_TPS= 43.37 decode_TPS= 52.74
warm-2 wall= 17.50s ttft= 88ms toks=1000 wall_TPS= 57.14 decode_TPS= 57.43
warm-3 wall= 17.96s ttft= 86ms toks=1000 wall_TPS= 55.67 decode_TPS= 55.94
=== measured (5) ===
run-1 wall= 17.78s ttft= 119ms toks=1000 wall_TPS= 56.23 decode_TPS= 56.62
run-2 wall= 17.24s ttft= 88ms toks=1000 wall_TPS= 58.01 decode_TPS= 58.30
run-3 wall= 17.37s ttft= 118ms toks=1000 wall_TPS= 57.57 decode_TPS= 57.97
run-4 wall= 16.45s ttft= 116ms toks=1000 wall_TPS= 60.78 decode_TPS= 61.21
run-5 wall= 16.93s ttft= 117ms toks=1000 wall_TPS= 59.07 decode_TPS= 59.49
=== summary [narrative] (n=5) ===
wall_TPS mean= 58.33 std= 1.70 CV= 2.9% min=56.23 max=60.78
decode_TPS mean= 58.72 std= 1.73 CV= 2.9% min=56.62 max=61.21
TTFT mean= 112ms std= 13ms min=88ms max=119ms
========== CODE (prompt=78 chars, max_tokens=800) ==========
=== warmups (3) ===
warm-1 wall= 9.03s ttft= 116ms toks= 698 wall_TPS= 77.34 decode_TPS= 78.34
warm-2 wall= 10.48s ttft= 131ms toks= 800 wall_TPS= 76.34 decode_TPS= 77.30
warm-3 wall= 11.50s ttft= 116ms toks= 800 wall_TPS= 69.59 decode_TPS= 70.30
=== measured (5) ===
run-1 wall= 10.89s ttft= 87ms toks= 800 wall_TPS= 73.49 decode_TPS= 74.09
run-2 wall= 8.10s ttft= 86ms toks= 640 wall_TPS= 79.03 decode_TPS= 79.88
run-3 wall= 10.26s ttft= 117ms toks= 800 wall_TPS= 78.00 decode_TPS= 78.90
run-4 wall= 9.58s ttft= 123ms toks= 750 wall_TPS= 78.31 decode_TPS= 79.33
run-5 wall= 6.71s ttft= 135ms toks= 478 wall_TPS= 71.21 decode_TPS= 72.67
=== summary [code] (n=5) ===
wall_TPS mean= 76.01 std= 3.46 CV= 4.5% min=71.21 max=79.03
decode_TPS mean= 76.97 std= 3.34 CV= 4.3% min=72.67 max=79.88
TTFT mean= 110ms std= 22ms min=86ms max=135ms
=== GPU state ===
0, 60 %, 19816 MiB, 24576 MiB, 229.01 W, 68
1, 90 %, 19816 MiB, 24576 MiB, 227.53 W, 63
=== Last 3 SpecDecoding metrics ===
(APIServer pid=1) INFO 05-01 16:56:43 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.46, Accepted throughput: 55.80 tokens/s, Drafted throughput: 68.10 tokens/s, Accepted: 558 tokens, Drafted: 681 tokens, Per-position acceptance rate: 0.952, 0.841, 0.665, Avg Draft acceptance rate: 81.9%
(APIServer pid=1) INFO 05-01 16:56:53 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.51, Accepted throughput: 56.70 tokens/s, Drafted throughput: 67.80 tokens/s, Accepted: 567 tokens, Drafted: 678 tokens, Per-position acceptance rate: 0.951, 0.845, 0.712, Avg Draft acceptance rate: 83.6%
(APIServer pid=1) INFO 05-01 16:57:03 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.39, Accepted throughput: 53.50 tokens/s, Drafted throughput: 67.20 tokens/s, Accepted: 535 tokens, Drafted: 672 tokens, Per-position acceptance rate: 0.929, 0.808, 0.652, Avg Draft acceptance rate: 79.6%

View File

@@ -0,0 +1,86 @@
#!/usr/bin/env python3
"""4-stream concurrent throughput on dual-turbo (the variant's selling point)."""
import json, time, urllib.request, statistics, threading, queue
URL = "http://localhost:8011"
MODEL = "qwen3.6-27b-autoround"
PROMPT = "Write a Python implementation of quicksort with comments explaining each step."
MAX_TOKENS = 800
def run_once(prompt, max_tokens):
body = json.dumps({
"model": MODEL,
"messages": [{"role": "user", "content": prompt}],
"max_tokens": max_tokens,
"temperature": 0.6,
"top_p": 0.95,
"stream": True,
"stream_options": {"include_usage": True},
"chat_template_kwargs": {"enable_thinking": False},
}).encode()
req = urllib.request.Request(f"{URL}/v1/chat/completions", data=body,
headers={"Content-Type": "application/json"})
t_send = time.time()
completion_tokens = 0
with urllib.request.urlopen(req, timeout=600) as r:
for line in r:
line = line.decode("utf-8", errors="ignore").rstrip()
if not line.startswith("data: "):
continue
payload = line[6:]
if payload == "[DONE]":
break
try:
chunk = json.loads(payload)
except json.JSONDecodeError:
continue
usage = chunk.get("usage")
if usage:
completion_tokens = usage.get("completion_tokens", completion_tokens)
return time.time() - t_send, completion_tokens
def worker(out_q, n_runs):
for _ in range(n_runs):
try:
wall, toks = run_once(PROMPT, MAX_TOKENS)
out_q.put((wall, toks))
except Exception as e:
out_q.put(None)
def run_concurrent(n_streams, runs_per_stream):
print(f"\n=== {n_streams} concurrent streams, {runs_per_stream} run(s) each ===")
q = queue.Queue()
threads = []
t_start = time.time()
for _ in range(n_streams):
t = threading.Thread(target=worker, args=(q, runs_per_stream))
t.start()
threads.append(t)
for t in threads:
t.join()
t_total = time.time() - t_start
results = []
while not q.empty():
r = q.get()
if r:
results.append(r)
if not results:
print("no completions")
return
walls = [w for w,_ in results]
toks = [t for _,t in results]
total_toks = sum(toks)
aggregate_tps = total_toks / t_total
per_stream_tps = [t/w for w,t in results]
print(f" total_toks={total_toks} total_wall={t_total:.2f}s aggregate_TPS={aggregate_tps:.2f}")
print(f" per-stream mean={statistics.mean(per_stream_tps):.2f} CV={statistics.stdev(per_stream_tps)/statistics.mean(per_stream_tps)*100 if len(per_stream_tps) > 1 else 0:.1f}%")
return aggregate_tps, statistics.mean(per_stream_tps)
# Warm up: 1 stream, 1 run
print("warmup...")
run_concurrent(1, 1)
# Bench
for n in (1, 2, 3, 4):
run_concurrent(n, 2)

View File

@@ -0,0 +1,10 @@
variant: dual-turbo concurrent
prompt: code (quicksort)
streams_tested: 1, 2, 3, 4
aggregate_tps_n1: 74.03
aggregate_tps_n2: 128.74
aggregate_tps_n3: 126.52
aggregate_tps_n4: 269.03
per_stream_tps_n4: 74.05
n4_speedup: 3.63x
notes: 4-stream aggregate of 269 TPS validates 4.67x KV concurrency claim. Per-stream TPS at n=4 (74 mean, CV 3.1%) within single-stream variance — true parallel decoding, not interleaved.

View File

@@ -0,0 +1,21 @@
warmup...
=== 1 concurrent streams, 1 run(s) each ===
total_toks=375 total_wall=4.89s aggregate_TPS=76.64
per-stream mean=76.66 CV=0.0%
=== 1 concurrent streams, 2 run(s) each ===
total_toks=1491 total_wall=20.14s aggregate_TPS=74.03
per-stream mean=73.99 CV=3.7%
=== 2 concurrent streams, 2 run(s) each ===
total_toks=3170 total_wall=24.62s aggregate_TPS=128.74
per-stream mean=65.57 CV=14.1%
=== 3 concurrent streams, 2 run(s) each ===
total_toks=3686 total_wall=29.13s aggregate_TPS=126.52
per-stream mean=55.41 CV=31.9%
=== 4 concurrent streams, 2 run(s) each ===
total_toks=5734 total_wall=21.31s aggregate_TPS=269.03
per-stream mean=74.05 CV=3.1%

View File

@@ -0,0 +1,15 @@
Running STRESS / boundary test against http://localhost:8011 (model=qwen3.6-27b-autoround, container=vllm-qwen36-27b-dual-turbo)
This script does the heavy stuff (longctx needle ladder + ~25K-token tool prefill).
For the fast functional smoke (~2 min), use verify-full.sh instead.
[1/2] Long-context needle (ladder: 10K / 30K / 60K / 90K) ...
✓ 9821 tokens: recalled 'crimson axolotl 93' (got: crimson axolotl 93 )
✓ 29320 tokens: recalled 'crimson capybara 52' (got: crimson capybara 52 )
✗ scale=900: HTTP 000 (request failed)
✗ scale=1400: HTTP 000 (request failed)
✗ partial recall — some in-budget depths failed
→ Attention quality degrades at longer contexts on this config OR the deployment crashed mid-test. Check docker logs.
[2/2] Tool response prefill OOM (~25K-token mock tool response) ...
✓ tool prefill OK — model emitted 1 tool_call(s) (finish=tool_calls, prefill survived)
1 stress check(s) failed. See hints above.

View File

@@ -0,0 +1,22 @@
variant: dual-turbo
context: 262144
gpu_mem_util: 0.85
kv_dtype: turboquant_3bit_nc
tp: 2
narr_wall_tps: 58.33
narr_wall_cv: 2.9
narr_decode_tps: 58.72
code_wall_tps: 76.01
code_wall_cv: 4.5
code_decode_tps: 76.97
ttft_narr_ms: 112
ttft_code_ms: 110
mtp_al: 3.39-3.51
mtp_avg_accept: 0.796-0.836
mtp_per_pos: 0.929-0.952 / 0.808-0.845 / 0.652-0.712
vram_gpu0_mib: 19816
vram_gpu1_mib: 19816
kv_pool_tokens: 1523232
max_concurrency: 4.67
boot_seconds: 290
notes: TP=2 dual-3090 — fastest per-stream of all variants (+17% narr, +13% code over single-card). 4.67x KV concurrency unlocks 4-stream concurrent serving at 262K context.

View File

@@ -0,0 +1,45 @@
========== NARRATIVE (prompt=65 chars, max_tokens=1000) ==========
=== warmups (3) ===
warm-1 wall= 34.49s ttft= 14153ms toks=1000 wall_TPS= 28.99 decode_TPS= 49.17
warm-2 wall= 19.52s ttft= 152ms toks=1000 wall_TPS= 51.23 decode_TPS= 51.64
warm-3 wall= 19.46s ttft= 159ms toks=1000 wall_TPS= 51.38 decode_TPS= 51.80
=== measured (5) ===
run-1 wall= 20.56s ttft= 157ms toks=1000 wall_TPS= 48.64 decode_TPS= 49.01
run-2 wall= 19.92s ttft= 154ms toks=1000 wall_TPS= 50.21 decode_TPS= 50.60
run-3 wall= 19.34s ttft= 150ms toks=1000 wall_TPS= 51.70 decode_TPS= 52.10
run-4 wall= 20.20s ttft= 160ms toks=1000 wall_TPS= 49.50 decode_TPS= 49.90
run-5 wall= 20.56s ttft= 148ms toks=1000 wall_TPS= 48.65 decode_TPS= 49.00
=== summary [narrative] (n=5) ===
wall_TPS mean= 49.74 std= 1.28 CV= 2.6% min=48.64 max=51.70
decode_TPS mean= 50.12 std= 1.29 CV= 2.6% min=49.00 max=52.10
TTFT mean= 154ms std= 5ms min=148ms max=160ms
========== CODE (prompt=78 chars, max_tokens=800) ==========
=== warmups (3) ===
warm-1 wall= 12.50s ttft= 149ms toks= 800 wall_TPS= 64.02 decode_TPS= 64.79
warm-2 wall= 10.05s ttft= 152ms toks= 669 wall_TPS= 66.59 decode_TPS= 67.61
warm-3 wall= 8.75s ttft= 158ms toks= 564 wall_TPS= 64.43 decode_TPS= 65.61
=== measured (5) ===
run-1 wall= 11.73s ttft= 155ms toks= 800 wall_TPS= 68.22 decode_TPS= 69.13
run-2 wall= 10.54s ttft= 155ms toks= 734 wall_TPS= 69.65 decode_TPS= 70.69
run-3 wall= 10.18s ttft= 151ms toks= 693 wall_TPS= 68.09 decode_TPS= 69.12
run-4 wall= 12.22s ttft= 153ms toks= 797 wall_TPS= 65.20 decode_TPS= 66.03
run-5 wall= 12.16s ttft= 158ms toks= 800 wall_TPS= 65.80 decode_TPS= 66.67
=== summary [code] (n=5) ===
wall_TPS mean= 67.39 std= 1.85 CV= 2.7% min=65.20 max=69.65
decode_TPS mean= 68.33 std= 1.93 CV= 2.8% min=66.03 max=70.69
TTFT mean= 155ms std= 3ms min=151ms max=158ms
=== GPU state ===
0, 98 %, 23404 MiB, 24576 MiB, 229.10 W, 62
1, 0 %, 4 MiB, 24576 MiB, 21.92 W, 42
=== Last 3 SpecDecoding metrics ===
(APIServer pid=1) INFO 05-01 16:10:36 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.51, Accepted throughput: 48.40 tokens/s, Drafted throughput: 57.89 tokens/s, Accepted: 484 tokens, Drafted: 579 tokens, Per-position acceptance rate: 0.953, 0.865, 0.689, Avg Draft acceptance rate: 83.6%
(APIServer pid=1) INFO 05-01 16:10:46 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.42, Accepted throughput: 47.00 tokens/s, Drafted throughput: 58.20 tokens/s, Accepted: 470 tokens, Drafted: 582 tokens, Per-position acceptance rate: 0.933, 0.814, 0.675, Avg Draft acceptance rate: 80.8%
(APIServer pid=1) INFO 05-01 16:10:56 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.34, Accepted throughput: 45.29 tokens/s, Drafted throughput: 58.19 tokens/s, Accepted: 453 tokens, Drafted: 582 tokens, Per-position acceptance rate: 0.887, 0.799, 0.649, Avg Draft acceptance rate: 77.8%

View File

@@ -0,0 +1,45 @@
========== NARRATIVE (prompt=65 chars, max_tokens=1000) ==========
=== warmups (3) ===
warm-1 wall= 24.08s ttft= 5314ms toks=1000 wall_TPS= 41.53 decode_TPS= 53.30
warm-2 wall= 19.79s ttft= 157ms toks=1000 wall_TPS= 50.52 decode_TPS= 50.93
warm-3 wall= 18.94s ttft= 160ms toks=1000 wall_TPS= 52.81 decode_TPS= 53.26
=== measured (5) ===
run-1 wall= 19.28s ttft= 161ms toks=1000 wall_TPS= 51.88 decode_TPS= 52.32
run-2 wall= 19.96s ttft= 158ms toks=1000 wall_TPS= 50.10 decode_TPS= 50.50
run-3 wall= 20.72s ttft= 152ms toks=1000 wall_TPS= 48.26 decode_TPS= 48.61
run-4 wall= 20.36s ttft= 162ms toks=1000 wall_TPS= 49.10 decode_TPS= 49.50
run-5 wall= 19.39s ttft= 162ms toks=1000 wall_TPS= 51.57 decode_TPS= 52.01
=== summary [narrative] (n=5) ===
wall_TPS mean= 50.18 std= 1.56 CV= 3.1% min=48.26 max=51.88
decode_TPS mean= 50.59 std= 1.59 CV= 3.1% min=48.61 max=52.32
TTFT mean= 159ms std= 4ms min=152ms max=162ms
========== CODE (prompt=78 chars, max_tokens=800) ==========
=== warmups (3) ===
warm-1 wall= 12.27s ttft= 151ms toks= 800 wall_TPS= 65.20 decode_TPS= 66.01
warm-2 wall= 12.44s ttft= 160ms toks= 800 wall_TPS= 64.32 decode_TPS= 65.16
warm-3 wall= 12.33s ttft= 156ms toks= 800 wall_TPS= 64.88 decode_TPS= 65.71
=== measured (5) ===
run-1 wall= 12.04s ttft= 158ms toks= 800 wall_TPS= 66.44 decode_TPS= 67.32
run-2 wall= 12.20s ttft= 160ms toks= 800 wall_TPS= 65.55 decode_TPS= 66.42
run-3 wall= 12.48s ttft= 154ms toks= 800 wall_TPS= 64.08 decode_TPS= 64.88
run-4 wall= 8.06s ttft= 163ms toks= 541 wall_TPS= 67.09 decode_TPS= 68.47
run-5 wall= 11.52s ttft= 156ms toks= 800 wall_TPS= 69.47 decode_TPS= 70.42
=== summary [code] (n=5) ===
wall_TPS mean= 66.53 std= 2.00 CV= 3.0% min=64.08 max=69.47
decode_TPS mean= 67.50 std= 2.10 CV= 3.1% min=64.88 max=70.42
TTFT mean= 158ms std= 3ms min=154ms max=163ms
=== GPU state ===
0, 98 %, 21704 MiB, 24576 MiB, 229.59 W, 62
1, 0 %, 4 MiB, 24576 MiB, 21.43 W, 42
=== Last 3 SpecDecoding metrics ===
(APIServer pid=1) INFO 05-01 18:19:02 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.45, Accepted throughput: 47.60 tokens/s, Drafted throughput: 58.20 tokens/s, Accepted: 476 tokens, Drafted: 582 tokens, Per-position acceptance rate: 0.933, 0.840, 0.680, Avg Draft acceptance rate: 81.8%
(APIServer pid=1) INFO 05-01 18:19:12 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.45, Accepted throughput: 46.70 tokens/s, Drafted throughput: 57.30 tokens/s, Accepted: 467 tokens, Drafted: 573 tokens, Per-position acceptance rate: 0.916, 0.848, 0.681, Avg Draft acceptance rate: 81.5%
(APIServer pid=1) INFO 05-01 18:19:22 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.42, Accepted throughput: 46.69 tokens/s, Drafted throughput: 57.89 tokens/s, Accepted: 467 tokens, Drafted: 579 tokens, Per-position acceptance rate: 0.938, 0.824, 0.658, Avg Draft acceptance rate: 80.7%

View File

@@ -0,0 +1,20 @@
variant: long-text
context: 214000
gpu_mem_util: 0.985
kv_dtype: turboquant_3bit_nc
tp: 1
narr_wall_tps: 49.74
narr_wall_cv: 2.6
narr_decode_tps: 50.12
code_wall_tps: 67.39
code_wall_cv: 2.7
code_decode_tps: 68.33
ttft_narr_ms: 154
ttft_code_ms: 155
mtp_al: 3.34-3.51
mtp_avg_accept: 0.78-0.836
mtp_per_pos: 0.887-0.953 / 0.799-0.865 / 0.649-0.689
vram_gpu0_mib: 23404
kv_pool_tokens: 284832
max_concurrency: 1.03
boot_seconds: 200

View File

@@ -0,0 +1,45 @@
========== NARRATIVE (prompt=65 chars, max_tokens=1000) ==========
=== warmups (3) ===
warm-1 wall= 24.02s ttft= 5437ms toks=1000 wall_TPS= 41.63 decode_TPS= 53.81
warm-2 wall= 18.45s ttft= 157ms toks=1000 wall_TPS= 54.20 decode_TPS= 54.67
warm-3 wall= 19.45s ttft= 156ms toks= 998 wall_TPS= 51.32 decode_TPS= 51.74
=== measured (5) ===
run-1 wall= 19.98s ttft= 159ms toks=1000 wall_TPS= 50.04 decode_TPS= 50.44
run-2 wall= 19.77s ttft= 154ms toks=1000 wall_TPS= 50.58 decode_TPS= 50.97
run-3 wall= 19.77s ttft= 160ms toks=1000 wall_TPS= 50.57 decode_TPS= 50.98
run-4 wall= 19.31s ttft= 159ms toks=1000 wall_TPS= 51.79 decode_TPS= 52.22
run-5 wall= 20.57s ttft= 165ms toks=1000 wall_TPS= 48.61 decode_TPS= 49.00
=== summary [narrative] (n=5) ===
wall_TPS mean= 50.32 std= 1.15 CV= 2.3% min=48.61 max=51.79
decode_TPS mean= 50.72 std= 1.16 CV= 2.3% min=49.00 max=52.22
TTFT mean= 159ms std= 4ms min=154ms max=165ms
========== CODE (prompt=78 chars, max_tokens=800) ==========
=== warmups (3) ===
warm-1 wall= 12.03s ttft= 160ms toks= 800 wall_TPS= 66.49 decode_TPS= 67.39
warm-2 wall= 9.56s ttft= 156ms toks= 639 wall_TPS= 66.83 decode_TPS= 67.93
warm-3 wall= 12.04s ttft= 162ms toks= 800 wall_TPS= 66.46 decode_TPS= 67.36
=== measured (5) ===
run-1 wall= 10.34s ttft= 163ms toks= 699 wall_TPS= 67.60 decode_TPS= 68.68
run-2 wall= 11.98s ttft= 156ms toks= 800 wall_TPS= 66.75 decode_TPS= 67.63
run-3 wall= 7.47s ttft= 157ms toks= 458 wall_TPS= 61.31 decode_TPS= 62.62
run-4 wall= 11.77s ttft= 156ms toks= 800 wall_TPS= 67.98 decode_TPS= 68.89
run-5 wall= 10.70s ttft= 159ms toks= 717 wall_TPS= 66.98 decode_TPS= 67.99
=== summary [code] (n=5) ===
wall_TPS mean= 66.12 std= 2.74 CV= 4.1% min=61.31 max=67.98
decode_TPS mean= 67.16 std= 2.59 CV= 3.9% min=62.62 max=68.89
TTFT mean= 158ms std= 3ms min=156ms max=163ms
=== GPU state ===
0, 98 %, 22326 MiB, 24576 MiB, 229.16 W, 62
1, 0 %, 4 MiB, 24576 MiB, 21.48 W, 42
=== Last 3 SpecDecoding metrics ===
(APIServer pid=1) INFO 05-01 16:27:27 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.45, Accepted throughput: 46.59 tokens/s, Drafted throughput: 56.99 tokens/s, Accepted: 466 tokens, Drafted: 570 tokens, Per-position acceptance rate: 0.942, 0.816, 0.695, Avg Draft acceptance rate: 81.8%
(APIServer pid=1) INFO 05-01 16:27:37 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.40, Accepted throughput: 45.80 tokens/s, Drafted throughput: 57.30 tokens/s, Accepted: 458 tokens, Drafted: 573 tokens, Per-position acceptance rate: 0.921, 0.822, 0.654, Avg Draft acceptance rate: 79.9%
(APIServer pid=1) INFO 05-01 16:27:47 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.56, Accepted throughput: 48.60 tokens/s, Drafted throughput: 57.00 tokens/s, Accepted: 486 tokens, Drafted: 570 tokens, Per-position acceptance rate: 0.937, 0.874, 0.747, Avg Draft acceptance rate: 85.3%

View File

@@ -0,0 +1,21 @@
variant: long-vision
context: 198000
gpu_mem_util: 0.98
kv_dtype: turboquant_3bit_nc
tp: 1
vision: true
narr_wall_tps: 50.32
narr_wall_cv: 2.3
narr_decode_tps: 50.72
code_wall_tps: 66.12
code_wall_cv: 4.1
code_decode_tps: 67.16
ttft_narr_ms: 159
ttft_code_ms: 158
mtp_al: 3.40-3.56
mtp_avg_accept: 0.79-0.853
mtp_per_pos: 0.921-0.942 / 0.816-0.874 / 0.654-0.747
vram_gpu0_mib: 22326
kv_pool_tokens: 264192
max_concurrency: 1.02
boot_seconds: 220

View File

@@ -0,0 +1,45 @@
========== NARRATIVE (prompt=65 chars, max_tokens=1000) ==========
=== warmups (3) ===
warm-1 wall= 46.30s ttft= 29048ms toks=1000 wall_TPS= 21.60 decode_TPS= 57.97
warm-2 wall= 17.87s ttft= 150ms toks=1000 wall_TPS= 55.97 decode_TPS= 56.44
warm-3 wall= 18.14s ttft= 153ms toks=1000 wall_TPS= 55.14 decode_TPS= 55.61
=== measured (5) ===
run-1 wall= 18.42s ttft= 153ms toks=1000 wall_TPS= 54.30 decode_TPS= 54.75
run-2 wall= 18.10s ttft= 148ms toks= 950 wall_TPS= 52.49 decode_TPS= 52.92
run-3 wall= 19.29s ttft= 150ms toks=1000 wall_TPS= 51.84 decode_TPS= 52.25
run-4 wall= 18.28s ttft= 148ms toks=1000 wall_TPS= 54.71 decode_TPS= 55.15
run-5 wall= 18.77s ttft= 149ms toks=1000 wall_TPS= 53.28 decode_TPS= 53.71
=== summary [narrative] (n=5) ===
wall_TPS mean= 53.32 std= 1.20 CV= 2.3% min=51.84 max=54.71
decode_TPS mean= 53.76 std= 1.22 CV= 2.3% min=52.25 max=55.15
TTFT mean= 150ms std= 2ms min=148ms max=153ms
========== CODE (prompt=78 chars, max_tokens=800) ==========
=== warmups (3) ===
warm-1 wall= 12.13s ttft= 156ms toks= 800 wall_TPS= 65.98 decode_TPS= 66.84
warm-2 wall= 7.05s ttft= 147ms toks= 481 wall_TPS= 68.26 decode_TPS= 69.71
warm-3 wall= 11.38s ttft= 155ms toks= 800 wall_TPS= 70.32 decode_TPS= 71.29
=== measured (5) ===
run-1 wall= 11.34s ttft= 154ms toks= 800 wall_TPS= 70.52 decode_TPS= 71.49
run-2 wall= 10.32s ttft= 150ms toks= 721 wall_TPS= 69.84 decode_TPS= 70.87
run-3 wall= 11.33s ttft= 157ms toks= 800 wall_TPS= 70.63 decode_TPS= 71.62
run-4 wall= 9.63s ttft= 150ms toks= 663 wall_TPS= 68.86 decode_TPS= 69.95
run-5 wall= 6.76s ttft= 152ms toks= 463 wall_TPS= 68.47 decode_TPS= 70.04
=== summary [code] (n=5) ===
wall_TPS mean= 69.66 std= 0.97 CV= 1.4% min=68.47 max=70.63
decode_TPS mean= 70.79 std= 0.78 CV= 1.1% min=69.95 max=71.62
TTFT mean= 153ms std= 3ms min=150ms max=157ms
=== GPU state ===
0, 95 %, 22220 MiB, 24576 MiB, 229.42 W, 62
1, 0 %, 4 MiB, 24576 MiB, 21.48 W, 40
=== Last 3 SpecDecoding metrics ===
(APIServer pid=1) INFO 05-01 16:46:34 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.53, Accepted throughput: 49.90 tokens/s, Drafted throughput: 59.10 tokens/s, Accepted: 499 tokens, Drafted: 591 tokens, Per-position acceptance rate: 0.970, 0.858, 0.706, Avg Draft acceptance rate: 84.4%
(APIServer pid=1) INFO 05-01 16:46:44 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.59, Accepted throughput: 51.09 tokens/s, Drafted throughput: 59.09 tokens/s, Accepted: 511 tokens, Drafted: 591 tokens, Per-position acceptance rate: 0.964, 0.883, 0.746, Avg Draft acceptance rate: 86.5%
(APIServer pid=1) INFO 05-01 16:46:54 [metrics.py:101] SpecDecoding metrics: Mean acceptance length: 3.54, Accepted throughput: 49.80 tokens/s, Drafted throughput: 58.80 tokens/s, Accepted: 498 tokens, Drafted: 588 tokens, Per-position acceptance rate: 0.954, 0.847, 0.740, Avg Draft acceptance rate: 84.7%

View File

@@ -0,0 +1,21 @@
variant: tools-text
context: 75000
gpu_mem_util: 0.97
kv_dtype: fp8_e5m2
tp: 1
narr_wall_tps: 53.32
narr_wall_cv: 2.3
narr_decode_tps: 53.76
code_wall_tps: 69.66
code_wall_cv: 1.4
code_decode_tps: 70.79
ttft_narr_ms: 150
ttft_code_ms: 153
mtp_al: 3.53-3.59
mtp_avg_accept: 0.844-0.865
mtp_per_pos: 0.954-0.970 / 0.847-0.883 / 0.706-0.746
vram_gpu0_mib: 22220
kv_pool_tokens: 104000
max_concurrency: 1.05
boot_seconds: 200
notes: fp8 KV — IDE-agent variant; faster per-stream than TQ3 long variants (~+8% code, +6% narr) but smaller ctx