From 86b193c27f84c3d0e6624fd6fcff1ce74dbdcba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8F=AD=E6=89=AC?= Date: Mon, 27 Apr 2026 17:07:01 +0800 Subject: [PATCH 1/3] fix latex --- .../02-KVCache.md" | 4 ++-- ...7\243\347\240\201\347\255\226\347\225\245.md" | 16 ++++++++-------- .../04-PagedAttention.md" | 12 ++++++------ .../05-ContinuousBatching.md" | 8 ++++---- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/02-KVCache.md" "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/02-KVCache.md" index d18154f..5b2a3c5 100644 --- "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/02-KVCache.md" +++ "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/02-KVCache.md" @@ -144,7 +144,7 @@ $$\text{KV Cache} = 2 \times L \times B \times n \times d \times \text{sizeof(dt 以 LLaMA-70B 为例($L=80$,$d=8192$,$n=4096$,$B=1$,FP16): -$$2 \times 80 \times 1 \times 4096 \times 8192 \times 2 \text{ bytes} = 10.7 \text{ GB}$$ +$$2 \times 80 \times 1 \times 4096 \times 8192 \times 2 \text{ bytes} = 10{,}737{,}418{,}240 \text{ bytes} \approx 10.7 \text{ GB}$$ **单个请求的 KV Cache 就占用 10.7GB**!这是 LLM 推理显存紧张的主要原因。 @@ -281,7 +281,7 @@ GQA 在质量和效率之间取得了很好的平衡,被 LLaMA-2、Mistral 等 动态分配会导致内存碎片: -``` +```text |--KV1--| |--KV2--| |--KV3--| ^空隙^ ^空隙^ ``` diff --git "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/03-\350\247\243\347\240\201\347\255\226\347\225\245.md" "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/03-\350\247\243\347\240\201\347\255\226\347\225\245.md" index ed46b6e..26663cf 100644 --- "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/03-\350\247\243\347\240\201\347\255\226\347\225\245.md" +++ "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/03-\350\247\243\347\240\201\347\255\226\347\225\245.md" @@ -22,9 +22,9 @@ graph TD **贪婪解码**(Greedy Decoding)每一步选择概率最高的 token: -$$x_{t+1} = \arg\max_{x} P(x | x_{1:t})$$ +$$x_{t+1} = \arg\max_{x} P(x \mid x_{1:t})$$ -其中 $x_{1:t}$ 表示已生成的前 $t$ 个 token,$P(x | x_{1:t})$ 是模型输出的下一个 token 的条件概率分布。$\arg\max$ 表示选择概率最高的那个 token。 +其中 $x_{1:t}$ 表示已生成的前 $t$ 个 token,$P(x \mid x_{1:t})$ 是模型输出的下一个 token 的条件概率分布。$\arg\max$ 表示选择概率最高的那个 token。 ### 特点 @@ -41,7 +41,7 @@ $$x_{t+1} = \arg\max_{x} P(x | x_{1:t})$$ 贪婪解码有个致命弱点——它倾向于生成重复内容。这就像一个只会走「最短路」的人,一旦走进了死胡同,就会反复在同一个圈里转: -``` +```text The cat sat on the mat. The cat sat on the mat. The cat sat on the mat... ``` @@ -72,11 +72,11 @@ The cat sat on the mat. The cat sat on the mat. The cat sat on the mat... 为了比较不同长度的序列,通常用**长度归一化**的对数概率: -$$\text{score}(x_{1:t}) = \frac{1}{t^\alpha} \sum_{i=1}^t \log P(x_i | x_{1:i-1})$$ +$$\text{score}(x_{1:t}) = \frac{1}{t^\alpha} \sum_{i=1}^t \log P(x_i \mid x_{1:i-1})$$ 其中: - $x_{1:t}$ 为候选序列,长度为 $t$ -- $\log P(x_i | x_{1:i-1})$ 为每个 token 的对数概率,累加得到序列对数概率 +- $\log P(x_i \mid x_{1:i-1})$ 为每个 token 的对数概率,累加得到序列对数概率 - $\alpha \in [0.6, 1.0]$ 为长度惩罚参数:$\alpha = 0$ 表示不做长度归一化,$\alpha = 1$ 表示完全归一化 背后的含义是:若不做长度归一化,Beam Search 会偏好短序列(短序列累积对数概率更大),除以 $t^\alpha$ 正是为了抵消这种偏差。 @@ -267,12 +267,12 @@ $$\text{Speedup} \approx \frac{1}{1 - \alpha}$$ **MTP**(Multi-Token Prediction)模型训练时预测未来多个 token: -$$\mathcal{L} = -\sum_{t=1}^T \sum_{k=1}^K \log P(x_{t+k} | x_{1:t})$$ +$$\mathcal{L} = -\sum_{t=1}^T \sum_{k=1}^K \log P(x_{t+k} \mid x_{1:t})$$ 其中: - $T$ 为训练序列总长度 - $K$ 为同时预测的未来 token 数(如 $K = 4$) -- $P(x_{t+k} | x_{1:t})$ 为在位置 $t$ 预测未来第 $k$ 个 token 的概率 +- $P(x_{t+k} \mid x_{1:t})$ 为在位置 $t$ 预测未来第 $k$ 个 token 的概率 用大白话讲,与标准语言模型只预测下一个 token($K=1$)不同,MTP 要求模型同时对未来 $K$ 个位置都做出准确预测,从而在推理时一步生成多个 token。 @@ -299,7 +299,7 @@ MTP 解码可以视为**自投机**:模型自己既是 draft 也是 target。 ### 决策树 -``` +```text 需要确定性输出? ├── 是 → 贪婪解码或 Beam Search └── 否 → 需要多样性? diff --git "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/04-PagedAttention.md" "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/04-PagedAttention.md" index 1353dae..eefcdfb 100644 --- "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/04-PagedAttention.md" +++ "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/04-PagedAttention.md" @@ -26,7 +26,7 @@ ### 碎片示例 -``` +```text 时刻 T1: |---Req1(1024)---|---Req2(512)---|---Req3(1024)---|---Free---| 时刻 T2: |---Req1(1024)---|-----Free-----|---Req3(1024)---|---Free---| ^Req2 结束 @@ -76,13 +76,13 @@ $$\text{Block size} = B \times H \times d_k \times 2 \text{ (K 和 V)}$$ - $d_k$ 为每个头的维度 - 因子 2 表示 K 和 V 各占一份 -典型的 $B = 16$。例如 LLaMA-7B($H=32$,$d_k=128$,FP16),每块占用 $16 \times 32 \times 128 \times 2 \times 2 = 256$ KB。 +典型的 $B = 16$。例如 LLaMA-7B($H=32$,$d_k=128$,FP16),每块占用 $16 \times 32 \times 128 \times 2 \times 2 = 262{,}144 \text{ bytes} = 256$ KB。 ### 地址映射 每个请求维护一个**块表**(block table): -``` +```text 请求 1 的块表: [物理块 7, 物理块 2, 物理块 15, ...] 请求 2 的块表: [物理块 3, 物理块 9, ...] ``` @@ -164,7 +164,7 @@ Beam Search 或并行采样需要从同一前缀生成多个分支。传统方 2. 当某个分支写入已共享的块时,才真正复制该块 示例: -``` +```text 原请求: [块1, 块2, 块3] 分支后: 请求A: [块1, 块2, 块3] (共享) @@ -198,7 +198,7 @@ CoW 使 Beam Search 的显存开销从 $O(k \cdot n)$ 降为 $O(n + k \cdot \Del 其中: - $k$ 为 Beam 宽度(分支数) - $n$ 为共享前缀的序列长度 -- $\Delta$ 为每个分支新增的 token 数 +- $\Delta$ 为每个分支在共享前缀之后新增的平均 token 数 从实际意义来看,共享前缀只存一份,只有真正“分叉”的新增块才需复制,显存节省显著。 @@ -222,7 +222,7 @@ CoW 使 Beam Search 的显存开销从 $O(k \cdot n)$ 降为 $O(n + k \cdot \Del 2. 若缓存命中,新请求直接引用已有的块 3. 新请求只需分配后续 token 的块 -``` +```text 前缀 "You are a helpful assistant..." 的块: [块10, 块11, 块12] 请求 A: [块10, 块11, 块12, 块20, 块21] (共享前缀,独有后缀) diff --git "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/05-ContinuousBatching.md" "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/05-ContinuousBatching.md" index b023ae4..c5639f4 100644 --- "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/05-ContinuousBatching.md" +++ "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/06-\346\250\241\345\236\213\346\216\250\347\220\206\344\274\230\345\214\226/05-ContinuousBatching.md" @@ -40,7 +40,7 @@ graph TD **等待浪费**:批内请求的输出长度参差不齐,短请求先结束却必须等最长的请求完成——如同团建活动里跑最快的人必须在终点等最慢的人到齐才能开始下一环。 示例: -``` +```text 请求 1: 输出 50 tokens,耗时 5s 请求 2: 输出 500 tokens,耗时 50s 请求 3: 输出 100 tokens,耗时 10s @@ -48,7 +48,7 @@ graph TD 静态批处理:必须等 50s,请求 1、3 的 GPU 利用率极低 ``` -**Padding 浪费**:长度对齐需要 padding,填充部分做无用计算。 +**Padding 浪费**:长度对齐需要 padding,填充部分产生无效的注意力计算开销。 **延迟尖峰**:批次边界造成等待,新请求的延迟取决于批内最慢的请求。 @@ -77,7 +77,7 @@ $$\text{利用率} = \frac{\text{平均长度}}{\text{最大长度}} = \frac{(L_ ### 调度流程 -``` +```text 迭代 1: [Req1, Req2, Req3] → 生成 token → Req1 结束 迭代 2: [Req2, Req3, Req4] → 加入新请求 Req4,生成 token 迭代 3: [Req2, Req3, Req4] → 生成 token → Req3 结束 @@ -123,7 +123,7 @@ Continuous Batching 需要处理两类请求: 结合 Chunked Prefill,可以将长 Prefill 分块,与 Decode 请求混合: -``` +```text 迭代 1: [Decode: Req1, Req2] + [Prefill Chunk: Req3_part1] 迭代 2: [Decode: Req1, Req2] + [Prefill Chunk: Req3_part2] 迭代 3: [Decode: Req1, Req2, Req3] → Req3 Prefill 完成,加入 Decode From f61b13068bc4c6380f044cbfe3ff0948bd31d26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8F=AD=E6=89=AC?= Date: Mon, 27 Apr 2026 17:18:07 +0800 Subject: [PATCH 2/3] fix md and latex --- ...8-\346\216\250\347\220\206\345\274\225\346\223\216.md" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/10-\346\250\241\345\236\213\350\275\257\347\241\254\344\273\266\347\224\237\346\200\201/01-\345\237\272\347\241\200\347\224\237\346\200\201/08-\346\216\250\347\220\206\345\274\225\346\223\216.md" "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/10-\346\250\241\345\236\213\350\275\257\347\241\254\344\273\266\347\224\237\346\200\201/01-\345\237\272\347\241\200\347\224\237\346\200\201/08-\346\216\250\347\220\206\345\274\225\346\223\216.md" index b306019..592f13c 100644 --- "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/10-\346\250\241\345\236\213\350\275\257\347\241\254\344\273\266\347\224\237\346\200\201/01-\345\237\272\347\241\200\347\224\237\346\200\201/08-\346\216\250\347\220\206\345\274\225\346\223\216.md" +++ "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/10-\346\250\241\345\236\213\350\275\257\347\241\254\344\273\266\347\224\237\346\200\201/01-\345\237\272\347\241\200\347\224\237\346\200\201/08-\346\216\250\347\220\206\345\274\225\346\223\216.md" @@ -26,7 +26,7 @@ graph LR 传统方法需要为每个序列预分配最大长度的连续KV Cache空间,导致显存碎片化。PagedAttention将KV Cache划分为固定大小的块(如16个token),通过块表(Block Table)管理非连续的物理内存: -``` +```text 逻辑视图:[Token 0-15] [Token 16-31] [Token 32-47] ... ↓ ↓ ↓ 物理块: Block 7 Block 2 Block 15 ... @@ -255,8 +255,8 @@ def batch_qa(s, questions): answers = [] for q in questions: s += sgl.user(q) - s += sgl.assistant(sgl.gen(f"answer", max_tokens=100)) - answers.append(s[f"answer"]) + s += sgl.assistant(sgl.gen("answer", max_tokens=100)) + answers.append(s["answer"]) return answers ``` @@ -264,7 +264,7 @@ def batch_qa(s, questions): ## 性能对比 | 特性 | vLLM | SGLang | -|-----|------|--------| +|------|------|--------| | KV Cache管理 | PagedAttention | RadixAttention | | 前缀缓存 | 支持 | 原生优化 | | 结构化输出 | 基础支持 | 原生支持 | From 93d9a67a2c2194b8a022f2bb96bd2b35da83af1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8F=AD=E6=89=AC?= Date: Mon, 27 Apr 2026 17:23:56 +0800 Subject: [PATCH 3/3] fix latex --- .../08-\346\216\250\347\220\206\345\274\225\346\223\216.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/10-\346\250\241\345\236\213\350\275\257\347\241\254\344\273\266\347\224\237\346\200\201/01-\345\237\272\347\241\200\347\224\237\346\200\201/08-\346\216\250\347\220\206\345\274\225\346\223\216.md" "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/10-\346\250\241\345\236\213\350\275\257\347\241\254\344\273\266\347\224\237\346\200\201/01-\345\237\272\347\241\200\347\224\237\346\200\201/08-\346\216\250\347\220\206\345\274\225\346\223\216.md" index 592f13c..a2e8180 100644 --- "a/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/10-\346\250\241\345\236\213\350\275\257\347\241\254\344\273\266\347\224\237\346\200\201/01-\345\237\272\347\241\200\347\224\237\346\200\201/08-\346\216\250\347\220\206\345\274\225\346\223\216.md" +++ "b/\345\244\247\346\250\241\345\236\213\346\225\231\347\250\213/10-\346\250\241\345\236\213\350\275\257\347\241\254\344\273\266\347\224\237\346\200\201/01-\345\237\272\347\241\200\347\224\237\346\200\201/08-\346\216\250\347\220\206\345\274\225\346\223\216.md" @@ -297,7 +297,7 @@ total = model_memory + kv_cache_per_seq * max_concurrent_seqs - `num_params`:模型参数量(例如 7B 即 $7 \times 10^9$);乘以 2 是因为 FP16 每个参数占 2 字节。 - `kv_cache_per_token`:每个 token 的 KV Cache 大小;其中“$2$”分别对应 Key 和 Value 两个缓存,`num_layers` 为 Transformer 层数,`hidden_size` 为隐藏维度,末尾的“$\times 2$”表示 FP16 每个元素 2 字节。 - `kv_cache_per_seq`:单条序列的 KV Cache 总量,等于每 token 缓存量乘以最大序列长度 `max_seq_len`。 -- `total`:总显存需求 = 模型权重 + 所有并发序列的 KV Cache 之和。该估算用于判断单卡可承载的最大并发数,即 $\text{max\_seqs} = (\text{GPU\_mem} - \text{model\_memory}) / \text{kv\_cache\_per\_seq}$。 +- `total`:总显存需求 = 模型权重 + 所有并发序列的 KV Cache 之和。该估算用于判断单卡可承载的最大并发数,即 $\text{max\\_seqs} = (\text{GPU\\_mem} - \text{model\\_memory}) / \text{kv\\_cache\\_per\\_seq}$。 ### 并发配置