推理与量化:在笔记本上跑大模型
训练完一个模型,怎么让它跑起来?训练用 1000 张 A100,推理一台笔记本就够 —— 这背后有两个关键技术:KV cache(避免重复计算)和量化(压缩权重存储)。 理解它们,你就能解释为什么 2023 年开始大家能在 MacBook 上跑 LLaMA、Mistral、Qwen 这些 7B/13B 级别的模型。
① 推理为什么是"显存瓶颈"
训练时模型一次"吃"成千上万个 token,GPU 的几百 TFLOPS 算力都能跑满。 但推理是自回归的 —— 每次只生成 1 个 token,把这一个 token 送进 96 层 Transformer, 每层都要读全部权重,算几行矩阵乘法,输出一个数字。
这种 batch=1 的推理有个很反直觉的特点:
- 算力闲着:GPU 一秒能做 300T 次浮点运算,但只用到 1-2%
- 显存带宽满:每次生成都要从 HBM 把 175B 参数读出来一遍
- 瓶颈在"读",不在"算"
所以推理优化的第一原则是:减少每次要读的字节数。这就引出了两个核心技术:
- KV cache —— 不重复算已经算过的 token
- 量化 —— 压缩权重的字节数(INT8 / INT4 / INT2)
② 自回归生成的"重复计算"问题
朴素的生成循环每生成一个 token,把整段历史都重新送进模型:
np. 看自动提示,⌘/Ctrl + Enter运行。想象生成 100 个 token:第 1 步算 1 个位置,第 2 步算 2 个,... 第 100 步算 100 个。 累计要算 1+2+...+100 = 5050 个位置的 attention。 其中前 99 步的结果已经算过,纯属浪费。
③ 互动:KV cache 是怎么省下计算的
切换"用 / 不用 KV cache" 看每一步实际要算多少 attention:
无 cache 时每生成一个 token 都要把整段历史重算一遍 attention —— 累计复杂度 O(L²)。 用 KV cache 之后,历史 token 的 K 和 V 都缓存住,新 token 来了只算自己 —— 累计复杂度降到 O(L),长序列下加速倍数随长度线性增长。
④ KV cache 的核心思想
attention 公式 里有三个张量:
- Q(query):只有"当前正在生成"的这个 token 用得到 — 每步算一份新的
- K(key):每个历史 token 都贡献一行 — 这些行从来不变
- V(value):同上,每个历史 token 一行 — 不变
所以做法非常直接:第一次算过 K 和 V,缓存住。下一个 token 来时, 只算自己的新 K_new、V_new,追加到 cache 末尾。 attention 时 Q 是新的一个,K/V 用包含历史的完整缓存。
np. 看自动提示,⌘/Ctrl + Enter运行。⑤ KV cache 的代价:显存占用
天下没有免费的午餐。KV cache 把"算"变"读",但显存被吃掉一大块。 缓存大小的公式:
这是为什么"长上下文"成本暴涨的原因 —— Claude 200k 上下文窗口的代价就是显存暴涨。 Grouped Query Attention (GQA, LLaMA-2 后)、Sliding Window Attention (Mistral) 都是用来缩小这个开销的。
⑥ 量化:用 4 个 bit 装一个权重
训练时权重是 fp16(16 bit)或者 bf16,每个数 2 字节。一个 7B 模型 = 7B × 2B = 14GB。 消费级显卡 RTX 3060 只有 12GB,根本装不下。
但推理时其实不需要这么高的精度。研究发现把权重量化到 INT8 (8 bit, 1 字节),质量几乎无损; 到 INT4(4 bit, 0.5 字节)也只有微小退化,但模型大小直接压到 1/4:
| 精度 | 每权重 | 7B 模型大小 | 能在哪跑 |
|---|---|---|---|
| fp16 / bf16 | 16 bit | 14 GB | A100, H100, RTX 3090/4090 |
| INT8 | 8 bit | 7 GB | RTX 3070/4070, M2 MacBook |
| INT4 | 4 bit | 3.5 GB | RTX 3060, M1 MacBook Air, 树莓派 5 |
| INT2 | 2 bit | 1.75 GB | 手机(精度有明显损失) |
⑦ 量化的数学:从浮点到整数的映射
核心是个简单的线性变换:
跑一下自己量化一个矩阵看看:
np. 看自动提示,⌘/Ctrl + Enter运行。⑧ 量化为什么有效(直觉解释)
训练得到的权重大部分接近 0,少数极端值才需要高精度。这种"长尾分布"特别适合量化:
- 每 group 找一个最大值定 scale,浪费 1 个 bit 给极端值
- 其余值按 scale 缩进 [-8, 7] 的整数格子,精度损失很小
- 反量化时乘回 scale,误差通常 < 1%
而且推理时 大部分权重只参与一次乘法,单次乘法的小误差被 softmax 这种非线性操作"平滑", 累积起来对最终输出的影响很小。所以 INT4 量化的模型在标准基准测试上往往只丢失 1-3 分(相对 fp16)。
⑨ 现代量化方案:GPTQ、AWQ、GGUF
- GPTQ(2022):用一小批校准数据"修正"量化误差,比朴素 round 精度好得多。开源生态主流。
- AWQ(2023):发现"少数权重的极端值贡献了模型大部分能力", 量化时给这些权重单独保留高精度。质量比 GPTQ 更稳。
- GGUF(llama.cpp 项目,2023):把量化模型打包成CPU 友好的格式, 让 Mac / Windows / Linux 不用 GPU 也能跑大模型。M2 Mac Studio 跑 Llama-70B Q4 速度 5-10 tok/s,可用。
⑩ 其他常见推理优化(点到为止)
- Flash Attention(2022):用 GPU SRAM 缓存中间结果,减少 HBM 读写。训练和推理都快 2-3 倍。
- Paged Attention / vLLM(2023):把 KV cache 分页管理,大幅提升 batch 推理吞吐。
- Speculative Decoding:用一个"小模型"快速猜接下来 K 个 token,再用大模型一次验证,加速 2-3 倍。
- Continuous batching:让不同请求的不同 step 在 GPU 上同时跑,吞吐量飙升。
这些都是 2022-2024 高速发展的方向 — 看完本节,你已经具备读这些论文的基础。
⑪ 小测验
⑫ 延伸阅读
- llama.cpp:纯 C++ 实现,CPU/GPU 通吃,是"在自己电脑上跑 LLM"事实标准。
- vLLM:生产级推理框架,PagedAttention + 连续 batching,吞吐 10× 原生 Transformer。
- AWQ paper — Activation-aware Weight Quantization:4-bit 量化的代表性工作。
- FlashAttention paper:Tri Dao 的工作,理解现代 GPU 内存层级必读。