Skip to content

Commit e1f9fb5

Browse files
committed
docs(qwen3): remove stale docs and dead code
Signed-off-by: Nyvo <75425811+Nyvo-io@users.noreply.github.com>
1 parent afd7a64 commit e1f9fb5

12 files changed

Lines changed: 159 additions & 1571 deletions

File tree

‎docs/index.md‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,13 @@ Organized by domain (model line / subsystem / playbook / lesson) instead of by l
3030
| `models/qwen3/serving-perf-5090.md` | Tuning history behind the serving numbers: unified-step attention fusion, batched step tail (#345), chunked prefill, cuBLAS 12.9 N=1025 cliff, cublasLt per-shape tuning, split-KV ≤bs32. Latest data lives in `serving-performance.md`. |
3131
| `models/qwen3/decode-attention.md` | Decode attention path (`NonPartition` vs `SplitKv`) is chosen by **batch (CTA-vs-SM), not context**: the old `max_seq_len>=1024` gate stranded bs=1 mid-context decode on the SM-starved NonPartition kernel — a tpot hump peaking ~ctx800, cliff-dropping at ctx1024. Removing it flattens bs=1 tpot (5090 −16% / 5070 Ti −7.5% @ctx800); kept `padded_bs<=32` (bs≤8 wins big, bs16 even, bs32 <1% loss). Also records the SplitKv chunk-size/grid policy (`Tuned` adaptive vs `Pin`/`PerToken` fixed-split batch-invariance, #435/#438). Two-card A/B + CUDA-graph capture + golden-gate verified. |
3232
| `models/qwen3/green-ctx-sm-partition.md` | Green Context SM partition (`OPENINFER_SM_PARTITION=20`) runs prefill/decode on disjoint SMs so decode stops stalling behind co-scheduled prefill: 5090 mid-band ITL p99 ~halved, TPOT down (−22% @QPS12), but TTFT 2–4× worse (prefill deferred + fewer SMs) — a TTFT↔ITL/TPOT trade, not a free win. Two-graph change (decode CUDA graph captured on the green decode stream) adds ~5% ITL p99 / 1–4% TPOT on top. Mechanism, A/B table, Xid-31/gemm_lt pitfalls. |
33-
| `models/qwen3/roadmap.md` | Qwen3-4B roadmap (2026-06 review): line is the maturity bar; #220 RoPE OOB, batched greedy sampling (#307), mixed greedy/non-greedy sampling (#284), and pegaflow KV offload (#316) are landed; open set is zero TP coverage, zero-adapter-only LoRA gate, dropped prefix-cache observability, stale docs, and YaRN #8 follow-up. |
34-
| `models/qwen3/model-crate.md` | `openinfer-qwen3` owns Qwen3 config/weights/executor/scheduler/tests/kernel plan; root sees generic `EngineHandle`; split-K decode gated on `padded_bs<=32` (64-token `Tuned` floor, cap 64 chunks; `Pin`/`PerToken` fixed 160-token split), 4k/64 serving TPOT p50 `6.46ms` on RTX 5090. |
33+
| `models/qwen3/roadmap.md` | Qwen3-4B maturity roadmap: TP=2 lifecycle coverage exists but numerical parity remains open; real-adapter LoRA accuracy, prefix-cache observability, and YaRN #8 are the other current qualification gaps. |
34+
| `models/qwen3/model-crate.md` | Current Qwen3 crate layout and ownership: model policy/execution in `openinfer-qwen3`, reusable GPU operations in `openinfer-kernels`, generic engine contracts below, and HTTP/model selection in `openinfer-server`. |
3535
| `models/qwen3/prefix-cache.md` | Prefix caching on by default for Qwen3-4B: full-block kvbm radix matching at the executor, suffix-only prefill. Repeated ~1900-token prompt TTFT 141.8 → 16.3ms p50 (8.7×); warm TTFT ≈ TPOT + ~5ms setup. Includes the RoPE scalar-path corruption fix and the drain-the-stream TTFT measurement pitfall. |
3636
| `models/qwen3/dspark-integration.md` | DeepSeek **DSpark** Phase 1 is implemented for Qwen3-4B: DFlash backbone + rank-256 Markov head, anchor-first DeepSpec layout, one strided argmax-with-bias kernel, PDL polish, and one D2H per draft block. Greedy losslessness passes; 5090 block7 A/B vs matched DFlash shows DSpark +3.6% geomean output tok/s overall (+3–16% on text/code, random synthetic exception) and better accepted-draft distribution (2.52 vs 2.30 draft tokens/round). |
3737
| `models/qwen3/dflash-speculative-decoding.md` | DFlash speculative decoding behind `--dflash-draft-model-path`, modelled as an optimistic transaction (propose K → verify K+1 span → accept longest argmax prefix + 1 bonus → commit/roll back KV). Lossless up to bf16 tie-flips (bit-identical multi-token accepts; lm-eval gsm8k strict-match identical spec on/off). Single-stream decode 1.82× on 5070 Ti, 1.56× on 5090. Concurrent throughput fixed by batching the draft forward, then a piecewise verify CUDA Graph (dense ops captured, attention eager) closed single-stream: 5090 greedy c1 274 ≈ vLLM 278, c8 1525 > 1240, c16 1834 ≈ 1846 — all batch sizes now ≥ vLLM. Accept measured equal (9.1% vs 8.85%, same drafter); draft-side piecewise graph tracked next. Proposer trait deferred to EAGLE. |
3838
| `models/qwen3/accuracy-gate.md` | Qwen3-4B instance of the logits golden gate (`tests/hf_golden_gate.rs`): 48 teacher-forced sequences / 816 positions vs a stored HF bf16 golden, replayed over bs=1 / batched eager / CUDA-graph. Strict guards: regret check + mean ≤ 0.06 + p99 ≤ 0.20; absolute max printed but not asserted (coverage-unstable). Methodology in `subsystems/correctness/`. |
39-
| `models/qwen3/kernels-crate.md` | Phase 1 split implemented and 5090-verified: Qwen3-4B kernel surface lives in `openinfer-kernels`; release build, test-target compile, accuracy gate, and bench snapshot pass. |
40-
| `models/qwen3/tp-design.md` | Qwen3 tensor-parallel design: `TP=2` milestone scope plus the controller/worker broadcast execution model, request identity, and coarse-grained step protocol for future TP/MoE work. |
41-
| `models/qwen3/kv-pressure-hang.md` | Issue #85 Qwen3-4B KV pressure hang fixed by full-lifetime scheduler KV admission, waiting-queue deferral, cleanup on disconnect/error, impossible-request errors, scheduler/bridge gates, and real `vllm bench serve` QPS=2 `500/500` pass with post-pressure completion healthy. |
39+
| `models/qwen3/tp-design.md` | Implemented Qwen3 TP runtime: rank-local workers, controller-broadcast steps, sharded attention/MLP with NCCL reductions, startup CUDA Graph pre-capture, current coverage, and remaining numerical/vocab-parallel work. |
4240
| `models/qwen3/pd-disaggregation-m2.md` | P/D 分离 M2 **已端到端验证**(单机 2×H200 + 400G IB):Qwen3-8B 1P+1D,KV 经 pegaflow metaserver P2P(RDMA READ)流转,greedy 输出与单实例逐 token 一致,杀 metaserver/P 优雅退化;多轮并发压测已过(含 router `max_completion_tokens` 坑)。openinfer `feat/pd-pegaflow-p2p` + pegaflow PR #381。RemoteFetch 状态机单测欠账;M3 layer-wise push 延后。 |
4341

4442
## models / qwen35
@@ -180,6 +178,7 @@ Organized by domain (model line / subsystem / playbook / lesson) instead of by l
180178
| `lessons/moe-dplb-decode-imbalance.md` | DPLB lesson for future PegaFlow/WiDeep MoE+EP serving: decode-side DP imbalance is a sticky KV-state problem; engines should emit raw progress while external router/proxy derive load and routing. |
181179
| `lessons/moe-zero-prefill-long-prefill.md` | ZeRO-Prefill lesson for future long-prefill MoE serving: once a router selects long-P work, maximize batch throughput by preserving compute-bound execution, hiding expert-weight movement, respecting KV handoff boundaries, and measuring bottlenecks before committing to an AsyncEP-style backend. |
182180
| `lessons/exact-match-gate-thread-cublas.md` | Two durable lessons from a Qwen3.5 e2e gibberish bug: worker threads that run a model must rebind the CUDA context and init thread-local cuBLAS handles, and exact-match greedy gates are sensitive to equal-logit top1 choices (keep a single FlashInfer selector). |
181+
| `lessons/kv-full-lifetime-admission.md` | Scheduler invariant for paged KV without preemption: reserve each admitted request's worst-case KV writes, defer temporary pressure, explicitly reject impossible requests, clean up every terminal path, and prove recovery with a post-pressure completion. |
183182
| `lessons/kimi-bringup-numerics.md` | Three MoE+TP greedy-parity / reporting lessons from Kimi-K2 bring-up, reusable on any MoE+TP decode engine gated on token-id parity: reduce hidden states in F32 not BF16 (BF16 bulk all-reduce silently breaks greedy); don't merge shared+routed expert reduce into one collective (breaks cold-batch greedy); always report p50+p99, never just mean (tail dominates on barrier-synced MoE+EP decode). |
184183
| `lessons/cuda-green-contexts.md` | Local mirror of NVIDIA CUDA 13.1+ Green Contexts guide (§4.6): static SM/workqueue partitioning via runtime execution contexts; host-only changes, no kernel edits. Generated by `scripts/html_to_md.py`. |
185184

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Full-Lifetime KV Admission
2+
3+
> **TL;DR:** Without preemption, admitting a request means reserving enough KV capacity for every token it can write before termination, not only its prompt. Temporarily over-budget requests wait; requests that can never fit are rejected explicitly; every terminal path releases request-owned state. Validate both pressure behavior and a post-pressure completion, because a server can remain reachable while generation is permanently wedged.
4+
>
5+
> **Last touched:** 2026-07
6+
7+
This lesson was extracted from the Qwen3 issue #85 KV-pressure hang, but the invariant applies to any paged-KV scheduler without preemption.
8+
9+
## The invariant
10+
11+
A scheduler must not admit more potential KV growth than the pool can satisfy:
12+
13+
```text
14+
reserved(active requests)
15+
+ worst_case_kv(new request)
16+
<= usable_pool_capacity
17+
```
18+
19+
Prefill-only admission is unsafe. Several requests can all fit their prompts, enter decode, cross page boundaries together, and then fail to allocate. If failure cleanup is incomplete, pages remain pinned and later requests wait forever.
20+
21+
Full-lifetime reservation is conservative: a request may stop early and use less than its reservation. Until the scheduler supports preemption or another recoverable overcommit policy, that lost concurrency is the cost of guaranteeing progress.
22+
23+
## Count KV writes, not API tokens
24+
25+
Derive the budget from the model's state transition. Do not assume every sampled token is immediately present in KV.
26+
27+
For Qwen3, prefill writes the prompt and returns the first sampled output. That sampled token enters KV only when a later decode step consumes it. A request with prompt length `P` and maximum completion length `N` therefore writes at most `P + N - 1` KV tokens. Other model loops may have a different relationship.
28+
29+
Round the resulting token count through the actual page geometry. Boundary tests should pin cases just below, exactly at, and just above a page transition; otherwise an off-by-one can hide behind page rounding.
30+
31+
## Three admission outcomes
32+
33+
1. **Admit:** the request's worst-case lifetime fits after active reservations.
34+
2. **Defer:** it fits in an empty instance but not beside current work. Keep it waiting and retry after capacity is released.
35+
3. **Reject:** its worst-case lifetime exceeds the instance's total usable capacity. Return an explicit request error so it cannot sit at the head of the queue forever.
36+
37+
Do not turn rejection into an empty successful response. The frontend must preserve the engine's error semantics and message.
38+
39+
## Cleanup is part of admission correctness
40+
41+
KV pages are usually returned through ownership/RAII only after all request state is dropped. Audit every terminal edge, not only the successful finish:
42+
43+
- normal length/EOS completion;
44+
- client or receiver disconnect;
45+
- prefill/decode/unified execution error;
46+
- explicit rejection or cancellation;
47+
- scheduler shutdown and worker failure.
48+
49+
A useful owner API is a single `drop_request(request_id)` path that removes executor state and releases the final page references. Error handling should report the terminal event and invoke the same owner cleanup.
50+
51+
## Verification pattern
52+
53+
Use layers of evidence:
54+
55+
- Unit-test admission with a fake executor and a small page pool. Cover impossible rejection, temporary deferral followed by admission, page boundaries, execution errors, and disconnect cleanup.
56+
- Run a real serving workload that creates KV pressure. Assert every request completes or fails explicitly within a deadline; throughput is a separate claim.
57+
- Immediately send a small post-pressure generation request. Health/model-list endpoints are insufficient because the original failure mode can leave the process alive while completions hang.
58+
- Keep a deadline in concurrent tests. A deadlock without a deadline only wedges CI.
59+
60+
The decisive property is recovery: after pressure and failures, capacity becomes reusable and unrelated requests can still make progress.

0 commit comments

Comments
 (0)