Skip to content

下面这两讲的核心不是“新模型结构”,而是一个统一问题:LLM 已经足够强,但推理太贵、太慢、太占显存。因此 Lecture 20 主要讲“推理时 attention/KV cache/长上下文服务优化”,Lecture 21 主要讲“模型压缩:量化、剪枝、蒸馏”。

Lecture 20:LLM Inference 的内存墙与 KV Cache 优化

0. 本章进化树

核心目标:

在自回归生成中,如何减少重复计算、降低 KV cache 显存压力、提高 batch 服务吞吐,并支持更长上下文?

逻辑演进:

text
Naive autoregressive decoding
    ↓ 问题:每生成一个 token 都重新计算历史 K,V
KV Cache
    ↓ 问题:节省计算,但 KV cache 线性增长,decode 阶段变成 memory-bandwidth bound
Prefill / Decode 分阶段理解
    ↓ 问题:decode 每步只算一个 token,GPU 算力吃不满
FlashAttention
    ↓ 问题:减少 attention 中间矩阵写回,但 KV cache 本身仍大
MQA / GQA
    ↓ 问题:减少 KV head 数,牺牲少量表达能力换显存/带宽
PagedAttention / vLLM
    ↓ 问题:服务多请求时 KV cache 内外碎片严重
Chunked Prefill + Piggybacked Decode
    ↓ 问题:prefill 和 decode 调度不均导致 GPU bubble
StreamingLLM / Attention Sink
    ↓ 问题:长上下文 OOM 或滑窗丢掉初始 token 后性能崩溃

1. Naive Decoding 为什么浪费?【重要程度:★★★★★】

自回归生成的概率分解为:

每一步生成新 token 时,Transformer 都需要对当前上下文做 self-attention。标准 attention 是:

其中:

符号定义:

符号含义
当前上下文 token 的 hidden states
当前上下文长度
query/key/value 投影矩阵
query、key、value 矩阵
每个 attention head 的 key/query 维度
每个 query 对所有 key 的相似度
缩放项,防止 dot product 过大导致 softmax 饱和

Naive decoding 的问题是:第 步生成 token 时,历史 token 的 其实已经算过,但 naive 实现会重新计算所有历史 。课件强调:为了预测一个新 token 反复重算整个历史上下文,是 massive compute waste。

严格地说,如果生成 个 token,每步上下文长度从 增长到 ,重算历史投影的总量近似为:

课件中写 更像是笔误或夸张表达;从 Transformer KV 重算角度,更合理的是 级别的历史重复计算。

2. KV Cache:用显存换时间【重要程度:★★★★★】

KV cache 的思想是:

历史 token 的 不会因为新 token 到来而改变,所以只需要保存,不需要重算。

步时,只计算最新 token 的:

然后把新的 append 到 cache:

生成第 个 token 时的 attention 变为:

直觉:query 是“当前 token 要找什么信息”,key 是“历史 token 提供什么索引”,value 是“历史 token 真正携带的信息”。KV cache 就是把历史索引和内容提前存好。

KV cache 的收益:把每步重复计算历史 变成只计算当前 token 的 ,所以生成阶段的投影计算从重复的 降为增量的 。但注意,attention 对历史 cache 的读取仍然随上下文长度增长。

3. Prefill vs Decode:LLM 推理的两个阶段【重要程度:★★★★★】

LLM 推理分为两个阶段。课件明确指出,第一个输出 token 依赖所有 prompt token;第二个输出 token 依赖 prompt 加上第一个输出 token,以此类推。

3.1 Prefill

Prefill 是处理输入 prompt 的阶段:

特点:

项目Prefill
输入全部 prompt token
并行性高,可以跨 token 并行
GPU 利用率
瓶颈compute-bound
指标TTFT, Time To First Token

课件强调:prefill 阶段所有输入 token 的计算可以并行执行,但不能跨层并行,因为第 层依赖第 层输出。

3.2 Decode

Decode 是逐 token 生成阶段:

特点:

项目Decode
输入每步 1 个 token
并行性
GPU 利用率
瓶颈memory-bandwidth-bound
指标TPOT, Time Per Output Token

Decode 阶段每步都要从 HBM 读取整个 KV cache。课件指出,生成一个新 token 会迫使系统重新读取历史 KV cache;在 Llama-3 8B、seq=4096 的例子中,每步大约要加载 1GB 数据,导致 compute starvation。

4. KV Cache 显存大小公式【重要程度:★★★★★】

课件给出 FP16 KV cache 大小:

符号定义:

符号含义
batch size,同时服务的序列数
sequence length / context length
cache 两个矩阵:
Transformer 层数
attention heads 数
每个 head 的维度
bytesFP16 每个数占 2 bytes

结论:

所以 KV cache 随序列长度 线性增长。课件特别强调:长文档任务 OOM 的元凶经常不是模型权重,而是 KV cache。

5. FlashAttention:减少 attention 中间矩阵写回【重要程度:★★★★☆】

标准 attention 会显式构造:

其中 。问题是 很大,写入/读取 HBM 很慢。

FlashAttention 的核心:

不把完整 attention matrix 存到 HBM,而是 block-by-block 计算,并在线维护 softmax 的归一化项。

对于 logits:

softmax 权重为:

其中:

输出:

在线计算时维护:

直觉:softmax 的难点是 denominator 需要看完所有 logits。FlashAttention 的关键是用在线归一化精确维护 denominator,而不是近似 softmax。课件 quiz 也强调:“exact online computation of softmax is impossible” 是 False。

6. MHA → MQA → GQA:减少 KV head【重要程度:★★★★☆】

6.1 MHA

Multi-Head Attention 中,每个 query head 都有自己的 key/value head:

问题:每个 head 都存自己的 ,KV cache 随 head 数线性增长。

6.2 MQA

Multi-Query Attention 让所有 query heads 共享同一组

优点:KV cache 极大压缩。

缺点:所有 heads 共享同一套 memory,表达能力下降,生成质量可能受损。

6.3 GQA

Grouped Query Attention 是 MHA 和 MQA 的折中。把 query heads 分成若干组,每组共享一组

如果共有 个 query heads, 个 KV heads,则压缩比例约为:

例如 ,KV cache 约减少到原来的

方法KV 共享方式显存节省表达能力
MHA每个 head 独立 K,V
MQA所有 heads 共享 K,V最高较低
GQA每组 heads 共享 K,V中高中高

7. PagedAttention:解决 KV cache 碎片【重要程度:★★★★☆】

PagedAttention 借鉴操作系统虚拟内存。课件描述:一个 request 类似一个 process;logical memory 类似 virtual memory;block table 把 logical blocks 映射到 physical blocks;physical blocks 位于 GPU memory。

问题来源:

碎片类型原因
Internal fragmentation每个请求预留最大长度,比如 2048 tokens,但实际只用 50/300/700 tokens
External fragmentation不同请求的物理显存不连续,中间空洞太小无法复用

PagedAttention 的公式化理解:

它不要求每个 sequence 的 KV cache 在物理显存中连续存放,因此可以更灵活地复用显存块。

8. Continuous Batching 与 Chunked Prefill【重要程度:★★★☆☆】

多请求服务中,prefill 和 decode 的计算特性不同:

阶段计算特征
Prefill大矩阵计算,compute-bound
Decode小步读取 KV cache,memory-bound

问题:如果一个请求在 prefill,其他请求的 decode 可能要等待,形成 GPU bubbles。课件称这是 iteration-level scheduling 导致的 GPU underutilization。

Chunked Prefill 的做法:

然后把 decode 插入 prefill chunk 的空隙中:

text
Prefill chunk + Decode piggyback

直觉:不要让一个超长 prompt 的 prefill 独占 GPU,而是切块后让 decode 请求“搭便车”。

9. StreamingLLM 与 Attention Sink【重要程度:★★★★☆】

长上下文问题:

  1. 完整保留 KV cache:显存爆炸,OOM。
  2. 只保留最近窗口:一旦丢掉最初 tokens,性能崩溃。
  3. 每次重算:太慢,接近

StreamingLLM 的观察:

初始几个 token 虽然语义信息不强,但会稳定吸收大量 attention,形成 attention sink。

原因:自回归训练中,初始位置被最多后续 token 看到;softmax 归一化也需要某些位置承接冗余注意力。课件指出,保留 attention sink 加最近窗口,可以让 KV cache 固定大小并保持较低 PPL。

StreamingLLM 的 cache 结构:

即:

其中 是滑动窗口大小。

Lecture 21:模型压缩:Quantization, Pruning, Distillation

0. 本章进化树

核心目标:

在尽量不损失精度的情况下,把大模型变得更小、更快、更便宜。

逻辑演进:

text
Scaling law vs hardware gap
    ↓ 问题:参数越大越强,但显存/带宽/成本跟不上
Numeric format compression
    ↓ FP32/FP16 → INT8/INT4
Quantization mapping
    ↓ 问题:离散化造成误差,低 bit 出现 precision cliff
PTQ vs QAT
    ↓ PTQ 快但脆弱;QAT 准但贵
Emergent outliers
    ↓ LLM activation outlier 破坏普通 INT8 量化
LLM.int8
    ↓ outlier 留 FP16,小值走 INT8
SmoothQuant
    ↓ 把 activation outlier 压到 weights 中
Pruning
    ↓ 删除冗余参数/结构
WANDA / OBS / iterative pruning
    ↓ 同时考虑权重和 activation,减少性能损失
2:4 structured sparsity
    ↓ 为 GPU sparse tensor core 设计的半结构化稀疏
Distillation
    ↓ 从 teacher 向 student 迁移行为和 dark knowledge

1. 为什么需要压缩?【重要程度:★★★★★】

课件开头的核心矛盾是:

LLM 的 memory 和 compute 需求增长速度超过硬件能力增长。

例如 70B 模型用 FP16 存储权重需要:

课件指出,LLaMA-2 70B FP16 需要多张 A100 80GB;如果 INT4 量化,可以大幅降低到消费级 GPU 级别,这是压缩技术要解决的 gap。

2. 数值格式:FP16、INT8、INT4【重要程度:★★★★☆】

若 cache 容量为 bytes,每个参数使用 bits,则可存储参数个数为:

例如 bytes:

结论:bit width 越低,同样显存能放更多参数,但数值精度下降。

3. Quantization 数学映射【重要程度:★★★★★】

量化把连续实数 映射成离散整数

通用形式:

反量化:

符号定义:

符号含义
原始 FP32/FP16 实数
量化后的整数
scale,控制实数到整数的缩放比例
zero-point,整数空间中对应实数 0 的偏移
整数量化范围
反量化后的近似值

Absmax symmetric quantization

用于 INT8 对称量化,通常映射到:

Zero-point quantization

或者更一般地:

课件例子:

反量化:

误差:

4. Precision Cliff:为什么 4-bit 常常好,3-bit 开始崩?【重要程度:★★★★☆】

课件观点:

在固定显存预算下,4-bit 大模型往往比 8-bit/16-bit 小模型更准;但 3-bit 以下误差太大,增加参数也难以弥补。

这是模型规模收益和量化噪声之间的 trade-off:

当从 16-bit 到 4-bit 时,参数数量可显著增加,规模收益大于噪声损失。但到 3-bit 时,离散 levels 太少,量化误差主导性能下降。

5. PTQ vs QAT【重要程度:★★★★★】

方法全称核心做法优点缺点
PTQPost-Training Quantization训练完后直接量化快、便宜、不需要训练低 bit 容易掉点
QATQuantization-Aware Training训练时模拟量化误差精度恢复好贵,需要数据和训练

课件明确指出:PTQ 是不做进一步 weight update/backprop 的量化;QAT 则在 forward path 中使用 fake quantization,使模型适应量化误差。

6. QAT 与 STE【重要程度:★★★★★】

QAT 的难点是:

不可导,且其导数几乎处处为 0:

如果直接反向传播:

梯度消失,权重无法更新。

STE,即 Straight-Through Estimator,做法是 forward 用 round,backward 假装 round 是 identity:

Forward:

Backward:

因此:

QAT 的训练流程:

text
PTQ initialization
    → 用 calibration data 初始化 S 和 Z
Fake quantization forward
    → 在 forward 中注入 rounding error
STE backward
    → 绕过 round 的不可导节点
FP32 shadow weights update
    → 用 FP32 权重累积梯度,forward 时再 fake quantize

7. LLM 中的 activation outlier【重要程度:★★★★★】

普通量化在 LLM 上失败的主要原因之一是 activation outlier。课件定义:activation outlier 是 hidden vector 中某些维度,其数值至少达到 6.0,并且出现在至少 25% 层、至少 6% token 中。

问题来自 absmax scale:

如果某个 outlier 比普通值大 100 倍,那么 被 outlier 拉大。普通值 可能变成:

于是:

结果:大量非 outlier 信息被压成 0,模型性能崩溃。

关键直觉:outlier 虽然稀少,但对 perplexity 和模型拟合很重要;这正是 mixed precision 的机会。

8. Compression Efficiency 与 Huffman Coding 类比【重要程度:★★★☆☆】

信息论中,若第 个符号出现概率为 ,分配码长为 ,期望长度为:

目标是最小化

直觉:

事件编码策略
高频普通值短码 / 低精度
低频重要 outlier长码 / 高精度

这对应 mixed precision quantization:大多数普通 activation 用 INT8,少数 outlier 用 FP16。

9. LLM.int8:outlier 单独保留高精度【重要程度:★★★★☆】

矩阵乘法:

可分解成 row-column dot products:

LLM.int8 的核心:

  1. 普通 activation 和 weights 用 INT8。
  2. outlier activation dimensions 保留 FP16。
  3. 最后把 INT8 core result 和 FP16 outlier correction 相加。

可以抽象为:

其中:

走 INT8 路径;

走 FP16 路径。

课件强调,outlier activation 可比其他维度大 20 倍,但只占总量很小比例,所以保留 FP16 的成本可控。

10. SmoothQuant:把 activation outlier “迁移”到 weight【重要程度:★★★★☆】

观察:

张量特征
Activation outlier 大,难量化
Weight 分布平坦,容易量化

SmoothQuant 的核心等价变换:

插入一个 per-channel smoothing factor

定义:

于是:

数学上输出不变,但数值分布改变:

变量变化
activation 被 smoothing,outlier 被压低
weight 变 sharper,吸收 outlier 难度
保持不变

直觉:activation 很难量化,weight 比较好量化,所以把量化难度从 activation 转移到 weight。课件称这是“migrate quantization bandwidth”。

11. Pruning:删除冗余【重要程度:★★★★☆】

Pruning 的目标是删除“不重要”的参数或结构。

类型删除对象优点缺点
Unstructured pruning单个 weight参数量减少GPU 难加速
Structured pruningneuron/channel/head/block真实加速更容易损失精度

课件强调,unstructured pruning 会产生散乱零值,GPU 很难跳过;structured pruning 让剩余部分形成更小的 dense matrix,因此有真实 wall-clock speedup。

12. Activation Pruning 与 WANDA【重要程度:★★★★☆】

只看 weight magnitude 不够。例子:

内积:

虽然 ,但第一维贡献更大:

所以 pruning 重要性应该同时考虑 weight 和 activation。

WANDA score:

符号定义:

符号含义
个输出通道、第 个输入维度的权重
calibration data 上第 个 activation dimension
个 activation dimension 的统计强度
权重 的重要性分数

直觉:一个 weight 本身大不一定重要;它连接的 activation 经常大,才重要。

13. OBS:Optimal Brain Surgeon【重要程度:★★★☆☆】

OBS 试图在删掉某个 weight 后,调整其他 weight 来最小化 loss 增加。

课件给出目标:

约束:

含义是:第 个权重要被剪到 0。

符号定义:

符号含义
删除第 个 weight 后,对所有权重的补偿更新
Hessian 矩阵,描述 loss 曲率
拉格朗日乘子
个坐标的 one-hot 向量
被剪掉的权重

OBS 给出的代价:

最优删除对象:

补偿更新:

直觉:剪掉一个参数会影响其他参数;OBS 不只是把它置零,还用 Hessian 估计怎么调整剩余参数来最小化损失。

14. Iterative Pruning【重要程度:★★★☆☆】

一次性剪太多会严重掉点,所以 iterative pruning 采用循环:

text
计算重要性分数
    → 剪掉最低分 blocks
    → fine-tune/retrain 恢复性能
    → 重复直到达到压缩目标

若把权重矩阵分成 block,第 个 block 的重要性可用 L2 norm:

分数低的 block 被 mask 成 0。

15. 2:4 Structured Sparsity【重要程度:★★★★☆】

随机稀疏对 GPU 不友好;完全 structured pruning 又太粗糙。因此 2:4 sparsity 是折中:

每连续 4 个 horizontal elements 中,至少 2 个为 0。

例如:

保留两个最大或最重要的元素。

压缩格式:

组成作用
Data matrix只存每 4 个元素中的 2 个非零值
Indices metadata用 2-bit index 记录非零位置

优点:NVIDIA Ampere Sparse Tensor Core 可以利用这种固定 pattern 跳过零值,实现更高吞吐。课件强调其优点包括 efficient memory access、low-overhead compressed format、2x math throughput。

16. Distillation:从 Teacher 到 Student【重要程度:★★★★☆】

蒸馏目标:

用小模型 student 模仿大模型 teacher 的行为。

Teacher-student 框架:

角色含义
Teacher大而强的预训练模型
Student小而快的模型
Knowledge输入-输出关系、概率分布、内部行为

为什么需要蒸馏?课件指出,pruning 往往难以保留 LLM 的复杂推理能力,而蒸馏是一种 knowledge transfer。

Hard label vs Soft label

Hard label:

只告诉 student 正确类别。

Soft label:

包含 teacher 对其他类别的相似性判断,即 dark knowledge。

例如 horse 对 deer 有小概率,因为二者共享四足、体型等结构相似性;但 car 的概率接近 0。

Temperature Softmax

普通 softmax:

带 temperature:

其中:

符号含义
类 logit
temperature
温度缩放后的概率

时,logits 被压小,分布更平滑,entropy 更高:

dominant class 不再过度接近 1,非目标类别的概率差异更容易被 student 学到。

常见蒸馏 loss:

其中:

符号含义
student 对真实标签的交叉熵
teacher/student soft distribution 的 KL divergence
teacher temperature distribution
student temperature distribution
hard label loss 和 distillation loss 的权重

Distillation 优点:student 可以是完全不同架构;例如 DistilBERT 更小更快,同时保留大部分 BERT 性能。缺点:需要训练 student,且 teacher 训练期间要可用。

总结对比表

技术解决的问题核心方法代价/风险重要程度
KV Cache重复计算历史 K,V缓存历史 K,V显存线性增长★★★★★
FlashAttentionattention matrix I/O 太大block-wise online softmax不直接解决 KV cache 大小★★★★☆
MQA/GQAKV heads 太多多个 query heads 共享 K,V表达能力可能下降★★★★☆
PagedAttentionKV cache 碎片block table 虚拟化管理系统实现复杂★★★★☆
Chunked PrefillGPU bubblesprefill 切块,decode piggyback调度复杂★★★☆☆
StreamingLLM长上下文 OOMsink tokens + recent window远距离语义仍可能丢失★★★★☆
PTQ快速压缩模型训练后量化低 bit 掉点★★★★★
QAT低 bit 精度恢复fake quant + STE训练成本高★★★★★
LLM.int8outlier 破坏 INT8outlier FP16,普通值 INT8mixed precision 实现复杂★★★★☆
SmoothQuantactivation outlier 难量化把难度迁移到 weight需要校准和平滑参数★★★★☆
Pruning参数冗余删除不重要结构/权重可能损伤能力★★★★☆
2:4 Sparsity稀疏难加速固定 pattern 稀疏硬件相关★★★★☆
Distillation小模型保留大模型能力teacher-student 学习需要训练和 teacher★★★★☆

期末高频考点

最该背熟的是这些:

  1. Attention 公式:
  1. KV cache 大小:
  1. Quantization:
  1. STE:
  1. WANDA:
  1. SmoothQuant:
  1. Distillation softmax with temperature:

这两讲可以用一句话串起来:Lecture 20 是“推理系统层面怎么让 LLM 跑得动”,Lecture 21 是“模型表示层面怎么让 LLM 变小”。

Static academic notes built with VitePress and KaTeX.