Serving · 面试核心

大模型推理部署总览

训练是「一次性的、批量的」,推理是「高频的、在线的、成本敏感的」。面试官常问:为什么大模型推理慢?显存花在哪?怎么把吞吐做上去?本文用图解把推理链路拆开。

01部署要解决什么

训练追求「在有限时间内把模型训好」;部署/推理追求「在成本与延迟约束下,尽可能多地处理并发请求」。三类核心指标互相牵制:

💰 成本

单 token 显存占用、每美元能出的 token 数。量化、共享、批处理都为了降本。

⚡ 延迟 (Latency)

单个请求从发起到拿到首个/完整回复的时间。对话产品最敏感。

🚀 吞吐 (Throughput)

单位时间内处理的 token 数 / 请求数。决定一台机器能服务多少人。

面试要点:延迟与吞吐往往冲突——把请求攒成更大的批能拉高吞吐,但每个请求的等待变长、延迟升高。好的调度器(如 continuous batching)就是在两者之间找平衡。

02自回归解码的瓶颈

Decoder-only 模型逐 token 生成:第 t 个 token 依赖前 t-1 个。这意味着生成阶段本质上是串行的,每生成一个 token 都要跑一次完整前向。瓶颈有两处:

Prefill(处理整段提示,可并行) [t1 t2 t3 t4 t5] 一次算出全部 K/V Decode(逐 token,串行) t6 → t7 → t8 → t9 Prefill 算力密集(大矩阵乘,GPU 利用率高);Decode 显存带宽密集(每步只算 1 个新 token,却要读全部权重)。 关键结论:Decode 阶段卡在「内存带宽」而非算力——每一步都要把几十 GB 权重从显存搬到计算单元。 因此推理优化主线 = 减少搬运(量化/稀疏)+ 提高每步复用(批处理/KV 共享)+ 减少重复计算(KV Cache)。

03KV Cache:避免重复计算

生成第 t 个 token 时,注意力需要对前面所有 token 的 K、V 做加权。若不缓存,每步都要重新算历史 K/V,复杂度从 O(n) 退化为 O(n²)。

❌ 不用 KV Cache

每步重算全部历史 K/V,计算随序列长度平方增长,无法接受。

✅ 用 KV Cache

历史 K/V 缓存起来,新 token 只算自己的 Q 并与缓存做注意力,复杂度降到 O(n)。

代价:KV Cache 显存随 batch × 序列长度 × 层数 × 隐藏维 线性增长。长上下文、高并发下,KV Cache 占用常常超过模型权重本身。这正是后续 PagedAttention、KV 量化、滑动窗口的优化对象。
# 伪代码:KV Cache 把历史 Key/Value 沿序列维追加
for step in range(max_len):
    q, k, v = proj(x_new)              # 只算新 token
    k_cache = cat([k_cache, k], dim=-2) # 追加
    v_cache = cat([v_cache, v], dim=-2)
    out = attn(q, k_cache, v_cache)    # 只做 1×seqlen 的小矩阵乘

04批处理:Static vs Continuous

静态批处理(Static Batching):等齐、对齐、一起走 所有请求必须 pad 到同一长度,短请求被迫等最长那个 → 算力浪费在 padding。 连续批处理(Continuous Batching):每个 step 动态凑齐「还在生成的」token ↑ 第1步:3 个请求各出 1 token ↑ 第2步:req3 已结束,新 req4 加入,始终填满 GPU ↑ 不同请求完成时间不同,但 GPU 永不空转

连续批处理(Continuous Batching)是 vLLM、TGI、TensorRT-LLM 的标配:不按「请求」而按「每一步的 token」组批,某请求结束立刻腾出位置给新请求。相比静态批处理,吞吐可提升数倍、延迟更稳。

05PagedAttention 与 vLLM

传统实现按「最大长度」为每个请求预留连续显存,导致大量碎片与预留浪费。PagedAttention(vLLM 提出)借鉴操作系统「分页」:把 KV Cache 切成固定大小的 block,像内存页一样零散存放、按需分配、不同请求可共享前缀块。

🧩 分页管理

KV 块像虚拟内存页,逻辑连续、物理离散,显存利用率大幅上升。

🔁 前缀共享

相同 system prompt / 多轮对话前缀可共享同一批 KV 块,省显存。

效果:在同样硬件下,vLLM 的吞吐通常是原生 HuggingFace 实现的 2–4 倍。这是面试中「怎么把推理做快」的标准答案之一。

06吞吐 vs 延迟:别混淆

TTFT(首 token 延迟)

发请求到收到第一个 token 的时间,主要花在 Prefill。受提示长度影响大。

TPOT(每 token 延迟)

相邻 token 的间隔,主要花在 Decode 的带宽。决定「打字机」是否流畅。

  • 吞吐由批大小、GPU 利用率决定,越大越好但会拖长 TPOT。
  • 延迟由模型大小、量化、批内竞争决定,对话场景希望 TPOT < 50ms。

07多卡并行部署

单个模型放不进一张卡时,需要切分。推理常用的切法:

🔀 张量并行 (TP)

把单层权重矩阵按列/行切到多卡,单层内并行。通信频繁,适合机内 NVLink。

🪜 流水线并行 (PP)

把不同层放到不同卡,微批流水。通信少但有「气泡」。

📊 数据并行 (DP)

多份同模型服务不同请求,最简单,适合高并发。

线上常组合使用:TP×PP 把模型放进去,再用 DP 复制多份扛并发。切分粒度越细,单卡显存越小,但通信开销越大。

08面试速记卡

为什么慢?

Decode 串行 + 每步读全量权重(带宽瓶颈);KV Cache 随长度线性涨显存。

怎么快?

KV Cache、Continuous Batching、PagedAttention、量化、投机解码、更大 batch。

显存去哪了?

权重(参数×精度)+ KV Cache(长上下文常占大头)+ 激活/临时缓冲。

TTFT / TPOT

TTFT 看 Prefill,TPOT 看 Decode 带宽,二者优化方向不同。

下一步:显存压不下来时,最有效的单一手段是量化——见同目录《模型量化详解》。