推理与部署
大模型如何生成文本:解码、温度、KV Cache 与量化
进阶 20 分钟 适合: 初学者 / 开发者 / 研究者
本课要点
- ▸推理分两个阶段:预填充(并行处理整段提示)和解码(一次生成一个 token)。
- ▸温度和 top-p 决定如何从模型给出的概率中采样下一个 token,在创造性和稳定性之间取舍。
- ▸KV Cache 保存之前的键和值,生成新 token 时不必重算整段提示;长上下文时吃掉大量内存的也是它。
- ▸生成 token 通常受内存带宽限制,所以缩小权重(量化)和批处理是提速降本的主要手段。
两个阶段:预填充与解码
你发出提示后,推理引擎要做两种不同的工作:
- 预填充(prefill):整段提示一次性并行通过模型。计算量大,但摊到每个 token 很快,决定了首个 token 的等待时间。
- 解码(decode):模型一次生成一个 token:跑一遍网络,得到下一个 token 的概率,选一个,接上去,再重复(见 大模型是什么)。这决定了每秒生成多少 token。
sequenceDiagram
participant U as 用户
participant E as 推理引擎
participant M as 模型权重
U->>E: 提示(1000 个 token)
E->>M: 预填充:并行处理全部提示 token
M-->>E: 每一层的键和值 → KV Cache
loop 每个新 token
E->>M: 解码:1 个新 token + KV Cache
M-->>E: 下一个 token 的概率
E->>E: 采样,并把新的 K/V 存进缓存
end
E-->>U: 流式输出回答怎么选下一个 token:采样
模型给词表里每个 token 都算出一个概率,怎么从中挑选很关键:
- 贪心:永远选最可能的那个。结果确定,但容易重复。
- 温度:在 softmax 之前把分数(logits)除以温度 T。T < 1 让分布更尖(更稳),*T* > 1 让分布更平(更多样)。
- top-k / top-p:只在最可能的 k 个 token 里采样,或者在概率加起来达到 p 的最小集合里采样(nucleus 采样,Holtzman 等,2019),砍掉长尾里的胡言乱语。
写代码、做信息抽取、跑 Agent 时通常用低温度;头脑风暴和写小说用高一些。即使温度设为 0,云端 API 的输出也不一定每次逐字相同,因为批处理和浮点运算顺序会变化。
KV Cache
在注意力计算中,每个新 token 都需要前面所有 token 的键和值(见 Transformer 与注意力机制)。每一步都重算会让生成速度按平方变慢,所以引擎把它们存进 KV Cache,只为新 token 计算 K 和 V。
缓存要占内存:2 × 层数 × KV 头数 × 每头维度 × 字节数 × token 数。以 Llama 3 8B 为例(32 层、8 个 KV 头、每头 128 维、16 位),每个 token 约 128 KB,8000 个 token 的上下文约 1 GB,而且是每个对话各占一份。分组查询注意力(Ainslie 等,2023)让多个头共享 K/V,很大程度上就是为了压缩这块缓存。
为什么生成速度受内存限制
每生成一个 token,硬件都要把全部权重从内存读一遍。8B 模型 16 位精度是 16 GB;如果内存带宽是 400 GB/s,单路生成速度上限就在每秒 25 个 token 左右,跟芯片算力有多强关系不大。所以主要的提速手段是:
| 手段 | 作用 |
|---|---|
| 量化 | 用 8 位、4 位或更少位存权重,每个 token 要读的字节更少 |
| 批处理 | 读一次权重服务多个用户;连续批处理每一步都能加入或移出请求(Orca) |
| PagedAttention | 像虚拟内存一样分页管理 KV Cache,同时容纳更多请求(vLLM) |
| 投机解码 | 小的草稿模型先猜几个 token,大模型一次性验证(Leviathan 等,2022) |
量化:让大模型跑在小机器上
训练通常用 16 位或 32 位数字。量化在训练后用更少的位数存权重,例如 LLM.int8()(Dettmers 等,2022)和 GPTQ(Frantar 等,2022)。llama.cpp 项目推广了 GGUF 文件格式和多种量化类型(名字像 Q4_K_M、Q8_0)。
权重大小的经验值(不含 KV Cache 和运行时开销):
| 模型规模 | 16 位 | 8 位 | 约 4 位 |
|---|---|---|---|
| 8B | 约 16 GB | 约 8 GB | 约 4.5–5 GB |
| 32B | 约 64 GB | 约 32 GB | 约 18–20 GB |
| 70B | 约 140 GB | 约 70 GB | 约 40 GB |
8 位的质量损失通常可以忽略;好的 4 位量化是本地使用最常见的平衡点;再往下,质量下降会加快。
自己动手
- Ollama 和 LM Studio 会下载量化好的模型,并显示每秒 token 数。
- llama.cpp 开放了所有参数:量化类型、上下文长度、KV Cache 类型、批大小和投机解码。
- 在苹果芯片上,MLX LM 利用统一内存运行和量化模型。
下一步:推理引擎 和 在自己电脑上运行大模型(编写中),硬件方面见 GPU、显存与算力。
算法卡片
| 算法 | 一句话 | 原始论文 |
|---|---|---|
| 温度与 Top-p 采样 | 控制生成随机性:只从累计概率达到 p 的候选里抽样 | Holtzman 等,2019 |
| KV Cache | 把已生成 token 的 Key/Value 存起来,避免每步重复计算 | 无单一原始论文,见 Transformers 文档 |
| 注意力汇聚点 StreamingLLM | 保留开头几个“汇聚”token 的 KV,就能无限长流式生成 | Xiao 等,2023 |
| 分组查询注意力 GQA | 每组注意力头共享一份 K/V,显著缩小 KV Cache | Ainslie 等,2023 |
必读论文
- The Curious Case of Neural Text Degeneration(2019)——解释为什么贪心解码会重复、提出 top-p(核采样)。arXiv:1904.09751
- Efficient Streaming Language Models with Attention Sinks(2023)——KV Cache 不能无限长时,保留“汇聚点”token 就能稳定流式生成。arXiv:2309.17453
动手项目(约 6 学时)
给自己训练的小 GPT(例如上一课的 nanoGPT)加上 KV Cache,分别测量生成 1000 个 token 的耗时,算出提速倍数;再按下面自测第 1 题的公式估算一个 7B 模型在 32K 上下文下的 KV Cache 大小。推荐配合阅读 Lilian Weng 的 Large Transformer Model Inference Optimization;调采样参数可对照 Hugging Face 生成策略文档,看工业级推理引擎怎么管理 KV Cache 可读 vLLM 文档。
自测
1. KV Cache 的大小和哪些量成正比?
层数 × KV 头数 × 每头维度 × 序列长度 × batch 大小 × 2(K 和 V 各一份),再乘以每个数的字节数。
2. top-p = 0.9 是什么意思?
把候选 token 按概率从高到低排,只在累计概率刚好达到 90% 的那一小撮里抽样。
3. 为什么解码阶段 GPU 算力利用率低?
每一步只算一个新 token,大部分时间花在从显存读权重和 KV Cache 上,受内存带宽限制而不是算力限制;批处理能把读一次权重的成本分摊给多个请求。
常见问题
temperature(温度)参数有什么用?
它在采样前对模型的概率做缩放。低温度(如 0–0.3)让最可能的 token 占主导,输出集中、可复现;高温度(0.8–1.2)让分布更平,输出更多样,错误也更多。
运行 7B、8B 模型需要多少内存?
权重约等于“参数量 × 每个参数的字节数”:8B 模型 16 位精度约 16 GB,4 位量化约 4–5 GB,另外还要给 KV Cache 和运行时留空间。Mac 上这部分内存和系统共用。
量化会让模型变差吗?
会有一些影响,取决于方法和位数。8 位通常几乎无损;好的 4 位方法在聊天场景下能保住大部分质量;低于 4 位,质量下降会明显加快,小模型尤其如此。