📌 内容总览
本文以 vLLM 为主线,系统性地梳理了大语言模型(LLM)推理系统的核心技术栈。从基础的 Transformer 解码器架构出发,逐步深入到内存管理(PagedAttention)、计算优化(FlashAttention)、模型架构(MoE)、并行策略、调度优化、缓存机制和投机解码等各个环节,形成了一幅完整的技术地图。
50-73%
FlashAttention-2 峰值效率
💡 核心洞察:LLM 推理优化的本质是在 计算效率、内存利用率 和 请求调度 三者之间寻找最佳平衡点。vLLM 通过 PagedAttention 解决了 KV Cache 内存碎片问题,通过 Continuous Batching 提高了 GPU 利用率,再通过一系列上层优化(Prefix Caching、Speculative Decoding 等)进一步提升端到端性能。
💾 KV Cache 与 PagedAttention
传统 KV Cache 管理的痛点
在早期的 LLM 推理系统中,KV Cache 通常采用 预分配连续内存 的方式管理,存在三大问题:
- 内存碎片(Fragmentation):不同序列长度导致预留空间无法充分利用
- 冗余复制(Redundant Duplication):共享前缀的多个请求各自存储完整的 KV Cache
- 无法弹性伸缩:序列长度动态增长时难以高效扩展
PagedAttention:操作系统启发的设计
vLLM 提出的 PagedAttention 借鉴了操作系统中的虚拟内存和分页技术,将 KV Cache 划分为固定大小的 Block(默认 16 个 token),通过非连续的块来存储序列的 KV 向量。
✅ PagedAttention 核心优势:
- 近零内存浪费:只在需要时分配块,内部碎片最多为一个块大小
- 灵活共享:同一 block 可被多个请求引用(ref_count),实现 Copy-on-Write
- 动态增长:序列变长时只需分配新 block,无需重新分配连续内存
vLLM Engine 内部架构(V1 引擎)
根据 vLLM 官方博客对 V1 引擎的拆解,核心组件包括:
- Processor:将原始输入转换为 EngineCoreRequest(含 tokenization、验证)
- Scheduler:决定每个 step 运行哪些请求,维护 waiting/running 队列
- KV Cache Manager:管理 free_block_queue,处理 block 分配、回收、eviction
- Model Executor / Worker:在 GPU 上执行 forward pass
- Output Processor:将 EngineCoreOutput 转换为用户可见的输出
Scheduler 每 step 的工作流程:
1. 优先处理 running queue 中的 decode 请求
2. 从 waiting queue 中选取 prefill 请求(考虑 prefix caching)
3. 调用 kv_cache_manager.allocate_slots() 分配 block
4. 执行 forward pass(flattened batch + custom paged attn kernels)
5. 采样、detokenize、检查 stop 条件、回收 finished 请求的 block
📊 性能数据:PagedAttention 论文显示,相比 FasterTransformer 和 Orca,vLLM 在相同延迟下将流行 LLM 的吞吐量提升了 2-4 倍。在更长序列、更大模型和更复杂解码算法下,提升更加显著。
🔥 FlashAttention 系列优化
Attention 的内存墙问题
标准 Attention 的计算过程需要将巨大的 Attention Score 矩阵(N×N)读写 GPU HBM(高带宽内存)。当序列长度 N 较大时,HBM 的读写带宽成为瓶颈,导致 GPU 计算单元大量空闲等待。
FlashAttention:IO-Aware 精确注意力
FlashAttention 的核心洞察是:让注意力算法具备 IO-Aware 能力,即充分考虑 GPU 内存层次结构(HBM ↔ SRAM)之间的数据传输开销。
🔑 核心思想:Tiling + Online Softmax
将大的 Attention 矩阵切分为小块(tile),使其能放入 GPU 片上 SRAM(约 100KB 级别)中计算。通过 Online Softmax 技巧,可以在不存储完整 N×N 注意力矩阵的情况下,逐步计算最终的输出。
FlashAttention 的关键贡献:
- 将 Attention 的 HBM 访问次数从 O(N²) 降低到 O(N),内存占用线性增长而非二次增长
- 无需近似,保证输出与标准 Attention 完全一致
- BERT-large 训练速度提升 15%,GPT-2(1K 序列)提升 3 倍
- 首次让 Transformer 在 Path-X(16K 序列)和 Path-256(64K 序列)上取得超越随机猜测的性能
FlashAttention-2:进一步优化并行度
FlashAttention 虽然大幅减少了 HBM 访问,但 GPU 利用率仍只有理论峰值的 25-40%。FlashAttention-2 针对这一问题做了三项改进:
- 减少非 matmul FLOPs:微调算法,减少额外的计算开销
- 跨 thread block 并行化:即使单个 head 也可以分配到多个 thread block,提高 occupancy
- Warp 级工作分配优化:减少 shared memory 的通信开销
📈 FlashAttention-2 性能:相比 FlashAttention 实现约 2 倍加速,达到 A100 GPU 理论峰值 FLOPs/s 的 50-73%,接近 GEMM 操作的效率。端到端训练 GPT-style 模型时,单卡 A100 可达 225 TFLOPs/s(72% MFU)。
⚠️ 注意:FlashAttention 和 PagedAttention 是互补的技术——FlashAttention 优化的是 单个 Attention 操作的计算效率,而 PagedAttention 优化的是 跨请求的 KV Cache 内存管理。在 vLLM 中,两者结合使用:PagedAttention 管理 KV Cache 的 block 分配和索引,FlashAttention 内核负责高效的 attention 计算。
🧩 MoE 混合专家模型
MoE 的基本概念
混合专家模型(Mixture of Experts, MoE)是突破稠密模型规模限制的重要架构。其核心思想是:用多个"专家"网络替代单一的 FFN 层,通过门控网络(Router/Gating)决定每个 token 分配给哪些专家处理。
MoE 层的组成
- 稀疏 MoE 层:替代传统 Transformer 的 FFN 层,包含若干专家(如前馈网络)
- 门控网络 / 路由:决定 token 被发送到哪个(些)专家。常用 Noisy Top-K Gating,即加噪声后保留前 K 个最大的门控值
训练与推理的挑战
训练挑战:
- 负载不均衡:门控网络倾向于将 token 路由到少数"受欢迎"的专家,形成马太效应
- 训练不稳定:路由计算涉及指数函数,对精度敏感,低精度训练易不稳定
- 微调困难:MoE 更易过拟合,需要更强的正则化(如更高 dropout 率)
推理挑战:
- 显存需求大:虽然每次只激活部分专家,但所有专家参数都必须加载到内存中
- 通信开销:专家并行(Expert Parallelism)需要在 GPU 间传输 token,网络带宽常成瓶颈
- 以 Mixtral 8x7B 为例:需要 47B 参数的显存(非 56B,因为注意力等参数共享),但推理 FLOPs 仅约 12B 模型水平
关键技术演进
- Switch Transformers:采用 Top-1 路由(而非 Top-2),简化设计同时保持质量,预训练速度提升 4 倍
- Router z-loss:惩罚门控网络输入的大 logits,减少舍入误差,显著提升训练稳定性
- 专家容量(Expert Capacity):设定阈值限制每个专家处理的 token 数,溢出 token 通过残差连接传递
- PR-MoE:不同层使用不同数量的专家,浅层用较少专家、深层用较多专家
💡 关键权衡:MoE 的核心价值是在 相同计算预算下训练更大的模型,但推理时的优势(比同参数稠密模型更快)是以 更高的显存占用 为代价的。适合多机高吞吐量场景,单机低延迟场景仍以稠密模型为佳。
🔄 并行策略:TP / PP / DP / EP
大模型推理需要多台 GPU 协同工作,主要有四种并行模式:
1. Tensor Parallelism (TP) — 张量并行
将模型层内的参数(如注意力头、FFN 权重)切分到多个 GPU 上。每个 GPU 只保存部分权重,计算时通过 All-Reduce 同步中间结果。
- 优点:降低单卡显存占用,适合降低延迟
- 缺点:GPU 间通信频繁(每层的激活值都要同步),通信开销大
- 典型配置:单机 8 卡常用 TP=8
2. Pipeline Parallelism (PP) — 流水线并行
将模型按层切分,不同 GPU 负责不同的层。数据像流水线一样依次流经各 GPU。
- 优点:通信量小(只需传递相邻层之间的激活值)
- 缺点:容易产生流水线气泡(pipeline bubble),GPU 空闲等待
- 优化:micro-batching、interleaving 等技巧减少气泡
3. Data Parallelism (DP) — 数据并行
在多个 GPU 上各复制一份完整模型,各自处理不同的请求批次。
- 优点:无 GPU 间通信(推理时),吞吐量线性扩展
- 缺点:每份副本都需加载完整模型,显存占用高
- 适用:扩大服务容量、处理高并发请求
4. Expert Parallelism (EP) — 专家并行
专为 MoE 模型设计的并行方式:将不同专家分布在不同 GPU 上。对于非 MoE 层,行为与数据并行相同;对于 MoE 层,token 需路由到拥有目标专家的 GPU。
- 优点:MoE 推理可同时优化延迟(TP)和吞吐量(EP+DP),实现超线性扩展
- 缺点:token 路由带来额外通信开销
- DeepSpeed-MoE:结合数据并行(非专家参数)、张量切片、专家并行和专家切片,实现高效 MoE 推理
典型多机多卡配置示例(70B 模型,4 机 × 8 卡):
- TP = 8(单机内张量并行)
- PP = 4(跨机流水线并行,每层机器负责 1/4 的层)
- DP = 1(无数据并行,模型太大)
若使用 MoE:增加 EP,将专家分散到不同节点
💡 实践原则:单机内优先用 TP(NVLink 带宽高),跨机用 PP 或 DP(网络带宽有限)。MoE 模型需额外引入 EP。TensorRT-LLM、Megatron、DeepSpeed 等框架已内置这些并行策略的自动配置。
📦 调度优化:Continuous / Chunked / Disaggregated
Continuous Batching(连续批处理)
传统静态批处理需要等待一个 batch 中所有请求完成后才能开始下一批,导致 GPU 利用率低。Continuous Batching(也称 In-Flight Batching)允许在每一步 forward 之后动态调整 batch 内容——新请求可以随时加入,已完成的请求可以随时退出。
✅ Continuous Batching 原理:
- 所有序列被展平拼接成一个"超级序列"(super sequence)
- 通过 position indices 和 attention mask 确保每个序列只关注自己的 token
- 无需 right-padding,消除了 padding 带来的计算浪费
- vLLM V1 scheduler 可以在同一步中混合 prefill 和 decode 请求
Chunked Prefill(分块预填充)
传统调度中,一个长 prefill 请求会阻塞所有 decode 请求的执行(因为 prefill 计算量大,需要较长时间)。Chunked Prefill 将长 prefill 拆分成多个 near-equal 大小的 chunk,与 decode 请求交错执行。
📊 Sarathi-Serve 的性能提升:
- Mistral-7B 单 A100:服务容量提升 2.6 倍
- Yi-34B 双 A100:服务容量提升 3.7 倍
- Falcon-180B 配合流水线并行:端到端容量提升 5.6 倍
Chunked Prefill 的核心优势:
- 无停顿调度(Stall-free):新请求加入 batch 不会阻塞正在进行的 decode
- Uniform batches:chunk 大小均匀,减少迭代间的不平衡和流水线气泡
- 更好的尾延迟控制:大 batch 提升吞吐的同时,对延迟影响更小
Disaggregated Prefill/Decode(Prefill-Decode 分离)
由于 Prefill 和 Decode 的计算特性完全不同(compute-bound vs memory-bandwidth-bound),将它们放在同一批 GPU 上执行会导致资源错配。Disaggregated Serving 将两者分离到不同的 GPU 集群上:
- Prefill 集群:使用高算力 GPU,处理 prompt 计算,输出 KV Cache
- Decode 集群:使用高带宽 GPU,专注逐 token 生成
- 通过高速网络(如 NVLink、InfiniBand)传递 KV Cache
DistServe
OSDI'24,端到端分离方案
P/D-Serve
侧重 KV Cache 传输优化
💡 趋势判断:Chunked Prefill 是目前 vLLM/SGLang 等框架的默认策略,实现简单且收益明显。Disaggregated Serving 代表未来方向,但需要高速互联和更复杂的调度器支持,目前仍在快速演进中。
🎯 Prefix Caching 前缀缓存
核心思想
Prefix Caching 是 LLM 推理中"几乎免费的午餐"——缓存已处理请求的 KV Cache block,当新请求到来时,如果其前缀与之前某个请求匹配,就可以直接复用缓存的 KV 向量,跳过重复计算。
✅ 为什么 Prefix Caching 几乎免费?
它不会改变模型输出,只是避免了冗余的 prompt 计算。OpenAI、Anthropic 等主流 API 服务以及 vLLM、SGLang 等开源框架均已广泛采用。
vLLM 的 Hash-based 实现
vLLM V1 采用基于哈希的方案来识别可复用的 block:
- 每个 block 的 hash = hash(父 block hash, block 内 token IDs, extra hashes)
- 父 hash 链:确保前缀匹配是连续的
- Extra hashes:包含 LoRA ID、多模态输入 hash、cache salt(多租户隔离)
- 仅缓存完整 block:部分填充的 block 不进入缓存
Block hash 计算示例(block_size=4):
Block 1: [A, B, C, D] → hash("ABCD")
Block 2: [E, F, G, H] → hash(Block1_hash, "EFGH")
Block 3: [I, J, K, L] → hash(Block2_hash, "IJKL")
新请求前缀 [A,B,C,D,E,F,G,H] → 直接命中 Block 1 & 2,只需计算后续 token
LRU Eviction 与安全性
- LRU 淘汰:当 free block queue 头部的 block 是 cached block 时,需要 eviction。将 block 从 cache 映射中移除,供新请求使用
- 释放顺序:请求完成后,其 block 按反向顺序加入 free queue(最后面的 block hash 更长、复用概率更低,优先淘汰)
- Cache Isolation:通过 per-request
cache_salt 隔离缓存,防止多租户环境下的时序攻击
⚠️ 哈希算法选择(vLLM v0.11+):
sha256(默认):Python pickle 序列化,跨版本可能不可复现
sha256_cbor:推荐用于跨环境确定性缓存
xxhash:更快但非加密安全,多租户环境需谨慎
⚡ Speculative Decoding 投机解码
核心洞察
Decode 阶段的瓶颈在于:每次 forward 只生成一个 token,但加载全部模型权重的开销是固定的。如果能让一次 forward "猜测"并验证多个 token,就能摊薄这个固定开销。
🔑 关键观察:用一个小型 draft 模型并行生成短序列的延迟,与大型 target 模型采样单个 token 的延迟相当。因此可以让 draft 模型"快速猜测",target 模型"一次验证"。
Speculative Sampling 算法
DeepMind 提出的 Speculative Sampling 工作流程:
- Draft 模型(较小、较快)自回归地生成 K 个候选 token
- Target 模型(大模型)一次性对这 K 个 token 进行并行打分
- 使用修正的拒绝采样(modified rejection sampling)逐个验证候选 token
- 若候选被接受则继续;若被拒绝,则从调整后的分布中重新采样一个 token
📊 性能数据:Chinchilla 70B 模型上使用投机采样,在分布式设置中实现了 2-2.5 倍解码加速,且 不改变输出分布(sample quality 保持一致)。
拓展变体
- Medusa / Lookahead Decoding:不使用独立 draft 模型,而是基于 target 模型本身学习多个解码头
- Prompt Lookup Decoding:利用输入 prompt 中的 n-gram 匹配作为 draft token
- vLLM Speculative Decoding:内置支持,可配置 draft model 或 n-gram 推测
✅ 投机解码的关键条件:
- Draft 模型需足够快(否则加速不明显)
- Draft 与 target 模型的分布不能差异太大(否则接受率低)
- 适合长序列生成场景,短序列收益有限
🚦 Admission Control 准入控制
为什么需要准入控制?
当请求到达速率超过系统处理能力时,如果不加控制地接收所有请求,会导致所有请求的延迟急剧恶化(排队效应)。Admission Control 在系统入口决定哪些请求被接受、哪些被延迟或拒绝,以保障已接受请求的 QoS。
Fairness in Serving LLMs
LLM 服务中的公平性面临独特挑战:
- 请求异构性:不同请求的 prompt 长度、输出长度差异巨大
- 资源需求不可预知:输出长度在请求到达时未知
- 批处理效应:一个请求加入 batch 会影响其他请求的延迟
Llumnix:动态迁移与负载均衡
Llumnix 是一个分布式 LLM 服务系统,其核心创新是支持请求的 动态跨实例迁移:
- 当某个实例负载过高时,可以将部分请求(连同其 KV Cache)迁移到轻载实例
- 无需等待请求完成即可重新分配负载
- 实现全局负载均衡和更好的尾延迟控制
📊 Preble 的性能数据:面向 prompt 共享优化的分布式服务系统 Preble,在真实工作负载下相比 SOTA 系统平均延迟降低 1.5-14.5 倍,p99 延迟降低 2-10 倍。
💡 未来方向:Admission Control 正从简单的基于队列长度的策略,向考虑请求特征(长度、优先级、SLA)、系统状态(KV Cache 利用率、批处理效率)和全局负载的智能策略演进。结合 Prefix Caching 和 Disaggregated Serving,可以构建更加高效和公平的 LLM 服务系统。
📚 参考资料
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
🎓 关键收获
- 内存管理是基础:PagedAttention 通过 OS 虚拟内存思想解决了 KV Cache 碎片问题,是 vLLM 的核心创新
- 计算优化见缝插针:FlashAttention 系列从 IO-Aware 角度重构 Attention,实现 2-4 倍加速
- 调度决定上限:Continuous Batching → Chunked Prefill → Disaggregated Serving,调度策略的持续演进
- 缓存是免费午餐:Prefix Caching 几乎不改变系统复杂度,但能显著减少冗余 prompt 计算
- 投机解码摊薄开销:用 draft 模型"猜"、target 模型"验",将 decode 的固定加载开销分摊到多个 token
- MoE 需要专门优化:专家并行(EP)是 MoE 推理的关键,DeepSpeed 和 Megatron 已提供成熟方案
- 系统设计是权衡艺术:延迟 vs 吞吐量、内存 vs 计算、公平性 vs 效率,没有银弹