- 大模型推理与部署工程详解,覆盖显存、加速框架、量化与并行策略
- 对应面试问答速查见 大模型推理与部署(面试版)
- 相关主题:大模型基础、大模型训练与微调、RAG、AI Agent、LangChain 与 LangGraph
- 当前覆盖:KV cache、显存估算、PagedAttention、continuous batching、量化、蒸馏、投机采样、FlashAttention/Decoding、长上下文、吞吐/延迟、模型并行、显存不足应对、KV cache 量化、MLA、prefix caching、GPTQ/AWQ/SmoothQuant/FP8、TP/PP/EP/序列并行/3D 并行/ZeRO、prefill/decode、TTFT/TPOT、chunked prefill、调度器、流式输出、并发与过载保护、多 LoRA、离线/在线推理、KV 共享、优先级与抢占调度、冷启动、可观测性、Medusa、draft 选择、Early Exit、剪枝、量化评估、框架对比、RadixAttention、对称/非对称量化、weight-only/W8A8、灰度发布/A/B 测试
什么是 KV cache?为什么它能加速推理?
原理
自回归生成时,每预测一个 token 都要对它之前的所有 token 做注意力。若不缓存,每步都要重新计算历史 token 的 K/V。KV cache 把已算过的 K/V 存起来,新 token 只算自己的 Q/K/V,再与缓存的 K/V 做注意力。
为什么加速
- 把「每步重算全部历史」变成「只算新增 token」,计算量从 O(n²) 累加降为 O(n)(每步只算一行注意力)。
- 代价是显存:KV cache 随序列长度线性增长,成为长序列推理的显存大头。
显存计算
KV cache 显存 = 2 × batch × 层数 × KV头数 × 头维度 × 序列长度 × 字节数- 这就是 MQA/GQA(压缩 KV 头)和 PagedAttention(优化存储)要解决的动机。
答「缓存历史 K/V,避免重复计算,把 O(n²) 降到增量 O(n)」,并主动给显存公式、点出它是长序列显存瓶颈。
如何估算大模型的显存占用?
三大部分
推理显存 ≈ 模型权重 + KV cache + 激活值:
权重显存 ≈ 参数量 × 字节数(FP16=2B,INT8=1B,INT4=0.5B)
KV cache ≈ 2 × batch × 层数 × KV头数 × 头维度 × 序列长度 × 字节数
激活/中间值 ≈ 与 batch、序列长度相关,逐层复用举例
一个 7B 模型(FP16):
- 权重 ≈ 7B × 2B = 14GB。
- KV cache:LLaMA-7B 共 32 层 × 32 KV 头 × 128 头维度,batch=1、seq=2048:
2×1×32×32×128×2048×2 ≈ 1.07GB。长序列下 KV cache 可远超权重。
估算要点
- 权重只与参数量+精度相关;KV cache 与 batch × 序列长度线性放大。
- 部署前先算「峰值显存 = 权重 + 最大 batch×seq 下的 KV cache」,决定卡数与量化精度。
给公式并现场算一个 7B/13B 的例子,强调「权重固定、KV cache 随 batch×seq 涨」,体现工程直觉。
主流的推理框架有哪些?vLLM 的 PagedAttention 是什么?
主流框架
| 框架 | 特点 |
|---|---|
| vLLM | 高吞吐,PagedAttention + continuous batching,易用 |
| TensorRT-LLM | NVIDIA,极致优化,TensorRT 引擎 |
| TGI(HuggingFace) | 生态好,支持量化/加速 |
| llama.cpp / Ollama | CPU/本地部署友好,GGUF 量化 |
PagedAttention(vLLM)
- 问题:传统 KV cache 是连续预分配,每个序列按最大长度预留,浪费显存(碎片 + 过度分配)。
- 做法:仿照操作系统虚拟内存分页,把 KV cache 切成固定大小的 block,按需分配、通过页表索引。
- 好处:接近零碎片、按需分配,batch 更大 → 吞吐显著提升,且支持 KV cache 共享(如 beam search、多请求共享前缀)。
类比「操作系统的分页内存管理」讲清 PagedAttention,强调「消除碎片 + 按需分配 → 提升吞吐」。
什么是 continuous batching?它如何提升吞吐?
问题:静态 batching
传统推理按 batch 打包请求,等最慢的一条完成才整批返回,短请求被长请求拖住,GPU 大量空闲。
continuous batching(连续批处理 / 迭代级调度)
- 不再以「请求」为单位,而以「迭代」为单位动态调度:每步生成时,完成的序列退出、新请求立刻补位,保持 batch 始终满负荷。
- 实现常配合 PagedAttention(灵活分配 KV)。
提升吞吐
- GPU 利用率从「等待最慢请求」提升到「持续满批」,吞吐可提升数倍。
- 面向高并发在线服务的关键技术。
对比「静态 batch 等最慢的、GPU 空转」与「动态补位、持续满批」,说明吞吐提升来自 GPU 利用率。
模型量化是什么?INT8、INT4 量化有哪些方法?
原理
量化 = 把 FP16/FP32 权重(和激活)用更低比特(INT8/INT4)表示,减少显存与带宽、加速计算,代价是精度损失。
分类
- 训练后量化(PTQ):无需重训,用校准数据统计范围后量化。代表 GPTQ、AWQ、GGUF。
- 量化感知训练(QAT):训练中模拟量化误差,精度更高但成本大。
代表方法
| 方法 | 精度 | 特点 |
|---|---|---|
| GPTQ | INT4/INT8 | 逐层量化 + 误差补偿,GPU 友好 |
| AWQ | INT4 | 保护高权重通道(按激活重要性缩放),精度好 |
| GGUF(llama.cpp) | INT4~INT8 | CPU/边缘部署 |
| SmoothQuant | INT8 | 平滑激活 outlier,W8A8 |
精度影响
- INT8 损失极小;INT4 略有下降但大幅省显存(4 倍压缩)。
- 关键层(如注意力、输出层)可保留高精度(混合精度)。
分清「PTQ vs QAT」,报出 GPTQ/AWQ/GGUF,并说「INT8 基本无损、INT4 略降但省 4 倍显存」。
什么是知识蒸馏?它在大模型部署中有什么用?
原理
用大模型(教师)的输出/中间表示指导**小模型(学生)**训练,让小模型逼近大模型能力。
在大模型部署的用途
- 模型压缩:把大模型能力迁移到小模型,降低显存与延迟,便于线上部署。
- 常见:蒸馏出更小 student(如 GPT-4 → 小模型)、或蒸馏到特定任务专家模型。
方式
- 输出层蒸馏(软标签/温度蒸馏)。
- 中间层/特征蒸馏。
- 数据蒸馏(用教师生成高质量训练数据,如 Alpaca)。
答「教师指导学生学习,实现能力压缩」,并区分「软标签/特征/数据蒸馏」三种方式。
什么是投机采样(Speculative Decoding)?
原理
用一个小模型(draft)快速生成多个候选 token,再用大模型(target)并行验证:
- draft 小模型快速自回归生成 k 个草稿 token。
- 大模型一次并行「批改」这些 token。
- 接受正确的、修正第一个错误,整体保持与大模型一致的输出分布。
为什么加速
- 大模型验证 k 个 token 只花一次前向(约等于原来生成 1 个的代价),而 draft 很便宜。
- 在内存带宽受限的解码场景,可带来 2~3 倍加速,不损失精度(保证分布等价)。
讲清「小模型起草 + 大模型并行验证」,强调「一次前向验证多个 token、数学上保证与原分布一致」。
FlashAttention 和 FlashDecoding 是什么?解决了什么问题?
FlashAttention
- 注意力矩阵 O(n²) 显存是瓶颈;传统实现反复读写 HBM,受显存带宽限制。
- 做法:tiling(分块)+ 在线 softmax,让中间结果留在高速 SRAM,只把最终结果写回 HBM。
- 效果:显存 O(n²)→O(n),速度数倍提升,数学等价(不改变结果)。
FlashDecoding
- FlashAttention 在解码阶段(batch 大、每个 query 只有一个 token)并行度不足。
- FlashDecoding 在「key/value 序列长度」维度再并行切分,适配长序列解码,进一步加速。
核心是「减少 HBM 读写、数学等价」,FlashDecoding 解决解码阶段 batch 小/query 少的并行不足。
长上下文推理有哪些优化手段?
主要手段
- KV cache 压缩:GQA/MQA 减少 KV 头;MLA(DeepSeek)低秩压缩 KV。
- 注意力 IO 优化:FlashAttention/FlashDecoding。
- 稀疏/滑动窗口注意力:限制注意力范围,如 Longformer 窗口。
- KV cache 量化:把 KV 缓存也量化,降低显存。
- 序列并行:ring attention 把长序列切分到多卡,突破单卡显存。
- 状态空间模型(SSM/Mamba):线性注意力/选择性状态空间,长序列更省。
从「压 KV(GQA/MLA)→ 省显存(KV 量化)→ 扩并行(ring attention)→ 换架构(Mamba)」分层作答。
推理服务的吞吐和延迟如何权衡?如何提升并发?
吞吐 vs 延迟
- 吞吐(throughput):单位时间处理的 token/请求数,batch 大 → 高吞吐。
- 延迟(latency):单请求响应时间,batch 大 → 排队/计算变慢 → 高延迟。
- 二者是此消彼长:加大 batch 提吞吐但增延迟,需按场景权衡(离线批处理重吞吐、在线交互重延迟)。
提升并发/吞吐
- continuous batching + PagedAttention(GPU 满负荷)。
- 量化(INT8/INT4)降显存与带宽。
- 投机采样、FlashAttention 降单步耗时。
- 多实例/多卡(DP、TP)横向扩展。
- 请求级缓存(相同前缀共享 KV)。
提升单请求延迟
- 降 batch、量化、蒸馏小模型、投机采样、减少输出长度。
明确「吞吐与延迟的 batch 权衡」,并分「提吞吐」与「降延迟」两组手段作答。
什么是模型并行?TP、PP、DP 有什么区别?
三种并行
| 类型 | 切分对象 | 特点 |
|---|---|---|
| DP(数据并行) | 数据(batch) | 每卡一份模型,切 batch,梯度同步 |
| TP(张量并行) | 单层权重(张量) | 层内切权重,卡间通信频繁,适合单机内 |
| PP(流水线并行) | 层(layer) | 模型按层分到多卡,流水线执行,通信少 |
组合
大模型训练/推理常组合使用:卡内 TP(切张量)+ 卡间 PP(切层)+ 多机 DP(切数据),即 3D 并行。
推理 vs 训练
- 推理主要用 TP(单卡放不下权重时切张量)与 PP(切层)。
- TP 通信量大但均匀;PP 通信少但有空泡(bubble)。
一句话区分「DP 切数据、TP 切张量、PP 切层」,并提 3D 并行组合与「PP 有空泡」的细节。
显存不足时有哪些应对手段?
手段清单(由轻到重)
- 量化:INT8/INT4,最直接省 2~4 倍。
- 缩短序列/减小 batch:降 KV cache 与激活。
- GQA/MLA 压 KV:减少 KV cache 显存。
- KV cache 量化 / offload:把 KV 或部分权重卸载到 CPU。
- 模型并行:TP/PP 把权重切到多卡。
- 蒸馏小模型:换更小模型。
- CPU 推理 / 混合推理:llama.cpp 等 CPU 方案。
决策
- 单卡差一点 → 量化 + 降 batch。
- 差很多 → 多卡 TP/PP,或换小模型/蒸馏。
- 需精度 → 优先 INT8、混合精度、KV 量化而非激进 INT4。
给「量化 → 调 batch/seq → 压 KV → 卸载 → 多卡 → 换小模型」的阶梯式清单,体现工程排障思路。
KV cache 显存公式如何推导?举一个具体例子计算?
推导
KV cache 存的是每一层、每个 token 的 K 和 V 向量。单个 token 在单层有 K、V 两份,各由「KV 头数 × 头维度」个元素组成:
KV cache 显存 = 2 × batch × 层数 × KV头数 × 头维度 × 序列长度 × 字节数- 因子「2」来自 K 和 V 两份;「字节数」由精度决定(FP16=2、FP8/INT8=1、INT4=0.5)。
- 序列长度是「输入 + 已生成」的总 token 数,随生成逐 token 增长。
举例计算
以 LLaMA-7B(32 层 × 32 KV 头 × 128 头维度,FP16)为例:
batch=1、seq=2048:2 × 1 × 32 × 32 × 128 × 2048 × 2 = 1,073,741,824 B ≈ 1 GB
batch=8、seq=4096:2 × 8 × 32 × 32 × 128 × 4096 × 2 ≈ 17.2 GB- 权重才 14GB,长序列 + 大 batch 下 KV cache 会反超权重,成为显存第一大头。
- 压缩手段:GQA/MQA 减少 KV 头数、MLA 低秩压缩、KV cache 量化降低字节数。
现场写出「2×batch×层数×KV头数×头维度×seq×字节数」,给出 7B 模型 1GB/17GB 两组数字,点出「长序列下 KV 反超权重」。
KV cache 量化是什么?有什么收益和风险?
原理
KV cache 量化把缓存中的 K/V 也用低比特(FP8、INT8、INT4 甚至 INT2)存储,直接压缩长序列下 KV 占用的显存大头。
收益
- 长序列/大批量下 KV cache 是显存第一大头,量化可省 2~4 倍,从而放得下更长序列或更大 batch。
- 内存带宽受限的 decode 阶段收益明显(KV 读写变便宜)。
风险
- K/V 是运行时激活值,分布随 token/位置动态变化,有 outlier,量化比权重更难。
- 量化误差会沿序列累积到注意力输出,长文本下可能掉点。
缓解
- per-token/per-channel 分组量化、FP8(动态范围大)、混合精度(关键层不量化)。
答「省 2~4 倍显存」+「激活值敏感、误差累积,需 per-channel/分组量化缓解」,FP8 是精度与显存的甜点。
什么是 prefix caching?它如何加速?
原理
多个请求往往共享相同前缀——system prompt、few-shot 示例、多轮对话历史、RAG 检索到的公共上下文。前缀缓存把这段共享前缀的 KV cache 计算一次、复用多次,避免重复 prefill。
实现方式
- 基于 block 的哈希匹配(vLLM automatic prefix caching):把前缀切成 block,按 block 哈希判断是否命中。
- 基于 radix tree 的前缀树(SGLang RadixAttention):KV 组织成前缀树,天然匹配最长公共前缀。
收益
- 省掉共享前缀的 prefill 计算 → 大幅降低 TTFT、提升吞吐。
- 典型场景:Agent 长 system prompt、多轮对话、批量请求共享同一份文档上下文,命中率高时提速数倍。
点出「共享前缀只算一次」的核心,说出两种实现(block 哈希 vs radix tree),落在「降 TTFT、提吞吐」。
什么是 MLA(Multi-head Latent Attention)?DeepSeek 如何用它压缩 KV?
原理
DeepSeek-V2 提出的注意力变体,用低秩压缩压缩 KV。核心:把 K、V 先投影到一个低维 latent 向量 c^KV(维度远小于 KV 头数 × 头维度),推理时只缓存 c^KV,计算时再上投影回 K/V:
c^KV = W^DKV · x (低维 latent,如 d_c=512)
K = W^UK · c^KV,V = W^UV · c^KV收益
- KV cache 从「KV 头数 × 头维度」降到单个 latent 维度 d_c,大幅省显存(DeepSeek-V2 相比 MHA 压缩约 10 倍以上)。
- 配合把 RoPE 解耦到 Q 与共享 K 上,避免低秩矩阵吸收位置信息带来的问题。
- 与 MQA/GQA 对比:MQA/GQA 是「共享头」,MLA 是「低秩压缩」,压缩更彻底、效果更好。
讲清「缓存低维 latent、用时上投影」,对比 MQA/GQA(共享)与 MLA(低秩压缩),MLA 是 DeepSeek 长上下文省显存的关键。
对称量化和非对称量化有什么区别?
定义
- 对称量化:只用 scale(零点固定为 0),把浮点数线性映射到关于 0 对称的整数区间。
q = round(x / s),反量化 x ≈ s · q- 非对称量化:额外引入 zero-point z,把 [min, max] 完整映射到整数全范围:
q = round(x / s) + z,反量化 x ≈ s · (q - z)对比
| 维度 | 对称 | 非对称 |
|---|---|---|
| 参数 | 只有 scale | scale + zero-point |
| 计算 | 简单、更省 | 多一步偏移 |
| 适用 | 分布对称(权重) | 分布偏斜(ReLU 后激活全非负) |
- 权重通常对称分布,对称量化即可;激活(尤其 ReLU 后只有非负值)用非对称能避免「浪费一半区间」,精度更好。
- 现代 W8A8 方案多对权重对称、激活非对称组合使用。
一句话「对称零点固定 0、非对称多一个 zero-point」,举例「激活非负用非对称、权重对称用对称」。
weight-only 量化和 W8A8/W4A16 有什么区别?
定义
- weight-only:只量化权重,激活保持 FP16/FP32(如 W4A16、W8A16)。GEMM 时权重先反量化再算。
- weight+activation:权重和激活都量化(如 W8A8),GEMM 直接在 INT8 域执行。
对比
| 方案 | 权重 | 激活 | 收益来源 | 精度 |
|---|---|---|---|---|
| W4A16 | INT4 | FP16 | 省显存/带宽(权重 4 倍压缩) | 略降 |
| W8A16 | INT8 | FP16 | 省显存/带宽 | 几乎无损 |
| W8A8 | INT8 | INT8 | 显存 + INT8 Tensor Core 加速 | 需 SmoothQuant 类平滑 |
- weight-only 实现简单、无需激活校准,瓶颈在显存带宽(decode 阶段)时收益明显。
- W8A8 能同时吃满 INT8 算力,但激活 outlier 会导致精度下降,需 SmoothQuant 等预处理。
用 W4A16 / W8A16 / W8A8 三个记号把「谁被量化、收益来源」讲清,点出 W8A8 才能用 INT8 算力但需处理激活 outlier。
GPTQ 的原理是什么?
原理
GPTQ 是训练后量化(PTQ)方法,核心是逐层量化 + 误差补偿:
- 逐层:一次只量化一层,用校准数据计算该层输出误差。
- 二阶信息:用 Hessian 矩阵(近似)衡量各权重对误差的影响,优先量化「影响小」的权重。
- 误差补偿:量化某个权重后,把量化误差重新分配到其余未量化权重上,使该层输出尽量不变。
目标:min || W·X - Ŵ·X ||² (Ŵ 为量化后权重)- 来源于 OBS/OBC 的「剪枝 + 补偿」思想,扩展到 INT3/INT4 量化。
- 结果:无需重训即可把模型压到 3/4 bit,困惑度损失很小。
特点
- GPU 上运行高效(可并行处理多列权重),是 AutoGPTQ、GGUF 等的底层算法。
答「逐层 + Hessian 二阶信息 + 量化误差补偿到剩余权重」三点,说明它是 PTQ、无需重训。
AWQ 的原理是什么?
核心观察
不是所有权重都同等重要:激活值幅度大的通道对应的权重更重要,量化误差对它们影响更大。
原理(激活感知 + 保护重要通道)
- 通过激活统计找出重要通道,对其施加缩放因子
s(>1)把权重放大、激活缩小,再量化:
Ŵ = quant(W · s),X̂ = X / s,则 Ŵ·X̂ ≈ quant(W·s)·(X/s)- 等价于:重要的通道权重被「放大」后用相对更细的粒度量化,等效降低其量化误差。
- 缩放因子
s由激活幅值决定,通过网格搜索/解析式求得,无需反向传播、无需重训。
特点
- 相比 GPTQ 更简单鲁棒,INT4 下精度好,广泛用于 vLLM、AutoAWQ 等。
- 只保护权重、不量化激活,属 weight-only 的 W4A16 方案。
讲清「激活幅度大的通道更重要」,用「缩放权重、反缩放激活」说明「等效降低重要通道量化误差」,强调无需重训。
SmoothQuant 的原理是什么?解决什么问题?
解决的问题
W8A8 的障碍:激活存在 outlier(个别通道数值极大),用对称 INT8 量化会严重损失精度;而权重分布平滑、很好量化。
原理:迁移量化难度
用 per-channel 平滑因子 s 把「激活的量化难度」迁移到「权重」上:
X̂ = X · diag(s)^{-1},Ŵ = diag(s) · W,其中 s = max(|X|)^α / max(|W|)^{1-α}- 对激活 outlier 通道:除以大 s,把 outlier 压平;权重对应通道乘 s,仍保持平滑可量化。
α控制难度从激活迁移到权重的程度(常取 0.5)。
结果
- 使权重和激活都能用 INT8(W8A8),在不重训前提下近乎无损,配合 INT8 Tensor Core 显著加速。
- 是 vLLM/TensorRT-LLM W8A8 量化的基础之一。
点出「激活有 outlier、权重平滑」,用 s = max(|X|)^α / max(|W|)^{1-α} 说明「把难度从激活搬到权重」,落点是 W8A8 无损。
什么是 FP8 推理?相比 INT8 有什么优势?
概念
FP8 是 8 位浮点格式(对比 INT8 是定点),两种标准:
| 格式 | 指数位 | 尾数位 | 特点 |
|---|---|---|---|
| E4M3 | 4 | 3 | 精度高,适合权重/激活 |
| E5M2 | 5 | 2 | 动态范围大,适合梯度/累积 |
相对 INT8 的优势
- 动态范围大:有指数位,天然覆盖大数值与 outlier,无需逐张量校准(省去 INT8 的校准成本)。
- 对激活尤其友好(激活动态范围广),per-tensor scale 即可。
- NVIDIA H100/H200 的 FP8 Tensor Core + Transformer Engine 原生支持,理论上 2 倍于 FP16 的算力吞吐。
实践
- 通常 GEMM 用 FP8,累积/归一化保留 FP16/FP32,误差极小。
- DeepSeek-V3 训练用 FP8 混合精度;推理侧 vLLM、TensorRT-LLM 均支持 FP8 权重与 KV cache。
对比「FP8 浮点动态范围大、免校准」与「INT8 需校准」,报出 E4M3/E5M2 两种格式,落到 H100 Tensor Core 2 倍吞吐。
KV cache 量化和权重量化有什么区别?
对比
| 维度 | 权重量化 | KV cache 量化 |
|---|---|---|
| 时机 | 加载时量化一次,静态 | 每步生成时动态写入 |
| 误差 | 固定不变 | 随序列长度累积 |
| 数值范围 | 稳定 | 逐 token 变化,可能漂移 |
| 粒度 | per-channel/group 固定 | 需 per-token 在线统计 scale |
| 目的 | 省权重显存/带宽 | 省长序列 KV 显存 |
关键差异
- 权重是静态参数,量化误差在推理前就确定;KV cache 是运行时数据,每步新增 token 都要重新量化,误差会向后传播累积。
- KV 对低比特更敏感,INT4/INT2 KV 需更细粒度(per-channel/非均匀)才能控住精度,而权重 INT4 已较成熟。
- 两者可叠加:量化权重省「基础显存」、量化 KV 省「长上下文显存」,是显存不足时的组合拳。
强调「一个静态、一个动态;一个误差固定、一个误差累积」,说明两者叠加省显存的定位不同。
张量并行(TP)的通信成本如何分析?
通信成本高的原因
TP 把单层权重按列/行切分到多卡,每次 GEMM 前后都要通信:
- 前向的
Y = X·W切分后需要 all-gather / all-reduce,每层、每次迭代都发生。 - 通信频率高(每层都通)、消息虽小但延迟敏感,对带宽和时延要求极高。
何时用 TP
- 单卡放不下权重时,用 TP 把权重切到多卡,是最直接的手段。
- 适合单机内(NVLink/NVSwitch 高速互联);跨机通信慢,TP 收益会被吃掉。
- 推理中 TP 还能降低单请求延迟(prefill 并行),是低延迟大模型服务常用手段。
结论
- 卡内高速互联 → TP;跨机 → 优先 PP/DP 或 EP。TP 度不宜过大,否则通信占比飙升。
点出「TP 每层都通信、延迟敏感、需 NVLink」,给出「单机内放不下权重用 TP、跨机用 PP/DP」的决策。
流水线并行(PP)的 bubble 如何优化?(chunked/interleaved)
bubble 的来源
PP 把模型按层分到多卡,流水线「灌水/排空」阶段部分卡空闲,形成 bubble(空泡)。bubble 占比约:
bubble 占比 ≈ (P - 1) / (P - 1 + M) (P=卡数,M=微批次个数)- M 越大(微批次切得越多),bubble 占比越小。
减少手段
- chunking(增加微批次):把 batch 切成更多 micro-batch,摊薄 bubble。
- interleaved(1F1B 交错调度):前向与反向交错执行,让计算与空泡重叠,进一步压 bubble(Megatron-LM 的 interleaved PP)。
- 推理侧类似思路:chunked prefill / splitfuse 把长 prefill 切块与 decode 交错,减少流水线空等。
给出 (P-1)/(P-1+M) 公式说明「M 越大 bubble 越小」,点出 1F1B 交错与 chunked prefill 两个优化。
什么是专家并行(Expert Parallelism)?
概念
MoE 每层有多个专家,EP 把不同专家分布到不同 GPU 上:token 经过路由(gate)选中 top-k 专家,若专家不在本卡,则通过 all-to-all 通信把 token 送到对应卡。
特点
- 通信是 all-to-all,成本取决于 top-k、专家数、capacity factor(每个专家容量上限)。
- 常与 TP/DP 组合:专家内用 TP、专家间用 EP、数据用 DP(如 DeepSeek 的细粒度 EP + 共享专家)。
- EP 收益:单卡只需存部分专家,突破「MoE 总参数大、单卡存不下」的限制。
权衡
- 专家分布均衡 → 通信与负载均衡;分布不均 → 某些卡过载、all-to-all 成瓶颈。
- 需要 capacity factor 控制 token 丢弃,平衡计算与通信。
讲清「专家切到不同卡、token 经 all-to-all 路由」,提 DeepSeek 的「细粒度 EP + 共享专家」,落到「单卡只存部分专家」。
什么是序列并行(Sequence Parallelism)?
概念
把序列维度切分到多卡:长序列的不同部分放在不同 GPU,各自算局部注意力,再通过通信交换 K/V 获得全局注意力。
代表实现
- Ring Attention:各卡按环形传递 K/V,逐步聚合全序列注意力,通信量与序列长度线性,突破单卡显存限制。
- Megatron-SP:LayerNorm/Dropout 等「序列维度无关」的操作沿序列切分,节省激活显存。
- DeepSpeed-Ulysses:按注意力头切分(不是按序列切),配合 all-to-all 实现序列并行,通信更优。
适用场景
- 超长上下文(几十万 token)单卡放不下 KV 与激活时,用序列并行横向扩展。
- 常与 TP/PP 组合,构成长上下文推理/训练的基础。
说明「把序列切到多卡、ring attention 环形传 K/V」,区分 Megatron-SP(切序列省激活)与 Ulysses(切头 + all-to-all)。
3D 并行如何组合?各维度如何分配?
概念
3D 并行 = DP(数据)+ TP(张量)+ PP(流水线) 三者组合,是超大规模模型训练的标配,也用于超大模型推理。
组合方式
- TP:通信最密集,放单机内(NVLink),切单层权重。
- PP:通信少,可跨机,按层切分。
- DP:几乎无通信(仅梯度同步),跨机扩展,切数据。
总卡数 = TP度 × PP度 × DP度- 放置优先级:先 TP(最快互联),再 PP,最后 DP(最慢互联也 OK)。
推理 vs 训练
- 训练:DP 是主力(梯度同步可异步/压缩),TP/PP 解决单卡放不下。
- 推理:无梯度,DP 退化为「多副本横向扩容」,主要用 TP/PP(+ EP 用于 MoE)切权重。
给出 总卡数 = TP×PP×DP 与「TP 单机内 → PP 跨机 → DP 最慢」的放置顺序,点出推理无梯度、DP 变多副本。
ZeRO 是什么?ZeRO-1/2/3 有什么区别?
概念
ZeRO(Zero Redundancy Optimizer,DeepSpeed 提出)解决「DP 每卡存完整模型+优化器+梯度」的显存冗余,把冗余状态切分到各卡。
三级优化
| 级别 | 切分对象 | 单卡显存节省(近似) |
|---|---|---|
| ZeRO-1 | 优化器状态(Adam 的 m/v) | ~4 倍 |
| ZeRO-2 | + 梯度 | ~8 倍 |
| ZeRO-3 | + 模型参数 | 与卡数 N 线性,~N 倍 |
- ZeRO-1/2 通信量不变,ZeRO-3 需在参数用时 gather,通信量略增。
- 延伸:ZeRO-Offload(把优化器/参数卸载到 CPU)、ZeRO-Infinity(再卸载到 NVMe),让单卡训超大模型成为可能。
与推理的关系
- ZeRO 主要面向训练;推理侧对应思想是 TP/PP 切权重、KV cache 切分(如 PagedAttention、序列并行)。
按「ZeRO-1 优化器 / ZeRO-2 梯度 / ZeRO-3 参数」三级报出,强调「消除 DP 冗余、ZeRO-3 随卡数近线性省显存」。
prefill 和 decode 阶段有什么区别?
两个阶段
- prefill(预填充):一次性处理整个 prompt,计算所有 prompt token 的注意力并生成 KV cache。
- decode(解码):自回归逐个生成新 token,每步只算当前 token,读之前全部 KV cache。
瓶颈差异
| 维度 | prefill | decode |
|---|---|---|
| 计算形态 | 矩阵×矩阵(GEMM) | 矩阵×向量(GEMV) |
| 瓶颈 | 算力受限(compute-bound) | 显存带宽受限(memory-bound) |
| 并行度 | 高,可大 batch | 低,每请求只一个 token |
优化侧重
- prefill:堆算力、大 batch、TP 并行、FlashAttention、prefix caching 复用。
- decode:省带宽,用 KV 量化、投机采样、GQA/MLA、小 batch 保延迟。
一句话「prefill 算力受限、decode 带宽受限」,分别给「大 batch/TP/缓存」与「量化/投机采样」两组优化。
TTFT 和 TPOT 是什么?如何优化?
定义
- TTFT(Time To First Token,首 token 延迟):请求到首个 token 输出的时间,主要被 prefill 决定。
- TPOT(Time Per Output Token,每 token 延迟):生成阶段相邻 token 的间隔,由 decode 决定。
优化 TTFT
- prefix caching(复用共享前缀)、chunked prefill(不被长 prompt 阻塞)、TP 并行加速 prefill、更快的注意力 kernel、缩短 prompt(RAG 压缩)。
优化 TPOT
- KV cache 量化、投机采样/Medusa(一次出多个 token)、减小 batch 降排队、GQA/MLA 省带宽、蒸馏小模型。
关系
- TTFT 与 TPOT 常冲突:加大 batch 提吞吐却拉高 TPOT,需按场景(在线重 TTFT、离线重吞吐)权衡。
讲清「TTFT 看 prefill、TPOT 看 decode」,分别给优化手段,点出「batch 增大与吞吐的权衡」。
chunked prefill 和 splitfuse 是什么?
问题
长 prompt 的 prefill 计算量大、耗时久,若整个 prefill 独占 GPU,会把 decode 中的请求「卡住」(head-of-line blocking),拉高 TPOT。
chunked prefill
把长 prefill 切成多个 chunk,与 decode 步交错调度:每轮只处理一个 chunk,其余算力留给 decode,避免长 prefill 阻塞其他请求。
SplitFuse(DeepSpeed-FastGen)
更进一步:把长 prompt 切块后,与 decode token 合并到同一个前向里一起算(fuse),既控住 prefill 延迟又填满 GPU 算力。
收益
- 降低长 prompt 对在线服务 TTFT/TPOT 的冲击,GPU 利用率更高。
- 与 PagedAttention/continuous batching 配合,是 vLLM、SGLang 调度器的核心能力。
讲清「长 prefill 会阻塞 decode」,用「切块 + 与 decode 交错/融合」回答,落到「控 TTFT、提利用率」。
vLLM 的调度器是如何工作的?
整体流程
vLLM 以迭代为单位调度(迭代级 continuous batching):
- 入队:新请求进入 WAITING 队列。
- 选择:调度器选一批请求进入 RUNNING——通常优先 prefill(先让新请求得到首 token),再用 decode 请求填满剩余容量。
- 执行:对选中请求跑一次模型前向(prefill 或 decode 各一步)。
- 采样/更新:采样出 token、更新 KV cache;完成的序列释放 block,腾出容量给下一批。
关键机制
- Block Manager(PagedAttention):管理 KV block 的分配/释放,决定「能否再塞一个请求」。
- chunked prefill:长 prompt 分块,与 decode 交错,防止阻塞。
- 抢占/优先级:高优先级请求可抢占低优先级(swap 或 recompute)。
答「迭代级调度:选请求 → 前向 → 采样 → 更新 KV」,点出「优先 prefill、block manager 管容量、chunked prefill 防阻塞」。
流式输出(streaming)如何实现?
概念
流式输出让模型每生成一个 token 就立刻返回,而不是等整个回复生成完再一次性返回,显著降低用户感知延迟(首 token 即可见)。
实现
- 服务端:生成循环里每产出 token 就 yield;用 SSE(
text/event-stream) 或 WebSocket 推送增量。 - HTTP 分块:chunked transfer,逐 token 下发。
- OpenAI 兼容:
stream: true,返回data: {...delta...}事件流,客户端逐条渲染。
for token in generate(prompt):
yield f"data: {json.dumps({'delta': token})}\n\n"意义
- 提升体验(秒回)、支持用户中途打断(省算力)、配合 stop 条件即时停止。
讲清「逐 token 推送、SSE/WebSocket/OpenAI stream 三种实现」,点出「降感知延迟 + 支持中途取消」。
推理服务如何做并发控制和过载保护?
并发控制
- 限制最大并发请求数 / 最大 in-flight token 数(避免 KV cache 打满)。
- 请求排队 + 超时(wait timeout);按 KV cache 余量做准入控制(放不下就排队/拒绝)。
过载保护
- 限流:token/请求级 rate limit(令牌桶/滑动窗口)。
- 背压:下游变慢时主动降速/拒绝。
- 优先级 + 抢占:VIP 请求优先,低优先级可被抢占/挂起。
- 熔断/降级:过载时拒绝新请求(load shedding)、返回 429/503,保护核心链路。
- 弹性扩容:根据队列深度/GPU 利用率自动加副本。
目标
在流量洪峰下保住核心请求的延迟 SLA,避免雪崩。
分「并发控制(上限+准入)」与「过载保护(限流/背压/抢占/熔断/扩容)」两层答,落到「保 SLA、防雪崩」。
如何在一个服务上部署多个 LoRA adapter?
场景
一个 base model 挂多个 LoRA(不同任务/租户的微调变体),共享底座、按请求选择 adapter。
实现要点
- 共享底座:base 权重只加载一份,adapter 只有低秩 A/B 矩阵,显存开销小。
- 按 adapter 分组批处理:把相同 adapter 的请求放到同一 batch,避免频繁切换;S-LoRA/Punica 用 segmented gather 高效聚合不同 adapter 的 A/B。
- adapter 调度/换入换出:adapter 太多时按 LRU 换入换出到显存(如 S-LoRA 的统一分页管理)。
- 框架:vLLM、TGI、SGLang 均支持 multi-LoRA。
收益
- 一份底座服务 N 个定制模型,省显存、降运维成本,是 SaaS 多租户的典型方案。
讲清「底座共享 + adapter 低秩」,点出「同 adapter 合批、segmented gather、LRU 换入换出」三个工程要点。
离线推理和在线推理有什么区别?
对比
| 维度 | 离线(batch)推理 | 在线推理 |
|---|---|---|
| 数据 | 预先收集、成批 | 实时请求、随机到达 |
| 目标 | 最大化吞吐 | 最小化延迟(TTFT/TPOT) |
| 调度 | 大 batch、静态 | continuous batching、流式 |
| 资源 | 可满负荷跑 | 需留余量 + 弹性扩容 |
| 优化 | DP/PP、量化、大批量 | 前缀缓存、投机采样、TP |
联系
- 离线常用 vLLM 的 offline engine、TensorRT-LLM 批处理;在线用 serving engine + 网关。
- 两者可共享同一套量化/蒸馏后的模型,但调度与优化目标不同。
用「吞吐 vs 延迟」一句话区分,落到「离线大 batch 静态、在线 continuous batching 流式」的调度差异。
KV cache 共享有哪些应用场景?
概念
多条序列共享相同的 KV cache block,避免重复存储与计算。PagedAttention 的 block 机制天然支持**写时复制(copy-on-write)**引用共享。
两类场景
- Beam Search:同一父节点派生多个候选 beam,共享父序列的 KV block,只有分叉后的部分各自存储。
- 前缀共享:不同请求共享相同 prompt 前缀(system prompt、few-shot、多轮历史、RAG 公共上下文),只算一次 prefill。
实现
- block 级引用计数:共享 block 被多个序列引用,序列结束引用计数减一,归零才释放。
- vLLM 的 automatic prefix caching(block 哈希匹配)、SGLang 的 RadixAttention(前缀树)都是前缀共享的落地。
说明「写时复制 + 引用计数」的 block 共享机制,并举 beam search 与共享前缀两类场景。
什么是抢占式调度和优先级调度?
概念
在线服务里不同请求优先级不同(付费用户 vs 免费、交互 vs 批处理),高优先级请求可抢占低优先级正在生成的任务,把资源让给高优先级。
抢占方式
- Swap(换出):把被抢占请求的 KV cache 换到 CPU 内存,恢复时再换回。
- Recompute(重算):直接丢弃,恢复时重新 prefill,代价是重算但省 swap 带宽。
- 二者权衡:swap 恢复快但占 CPU 内存,recompute 省内存但恢复慢。
调度策略
- 优先级队列:高优先级先进 RUNNING;抢占只发生在「资源不足 + 有更高优先级等待」时。
- vLLM/TGI 均支持 priority + preemption,配合超时与公平性防止饥饿。
答「高优先级抢占低优先级,资源让位」,说清 swap(换 KV)与 recompute(重算)两种抢占的取舍。
如何优化首 token 延迟(TTFT)?
本质
TTFT 主要由 prefill 耗时 + 排队等待 决定,优化从「省计算」与「省等待」入手。
手段
- prefix caching:共享前缀只 prefill 一次,命中即复用 KV,TTFT 大降。
- chunked prefill:长 prompt 切块,新请求不必等前面长 prefill 全部完成。
- 并行加速 prefill:TP 切权重、FlashAttention 降 IO、更快的 prefill kernel。
- 减少 prompt 长度:RAG 摘要压缩、缓存命中、去重。
- 模型侧:蒸馏小模型、量化降低 prefill 计算量、多副本负载均衡减少排队。
与吞吐的权衡
- 提升吞吐的「大 batch」会加长排队,反而抬高 TTFT,需用优先级/准入控制保在线延迟。
从「复用(缓存)→ 切块(不阻塞)→ 并行(TP/FlashAttention)→ 减 prompt → 换小模型」递进作答。
模型冷启动和加载如何优化?
冷启动来源
- 权重加载:几十 GB 权重从磁盘/网络读入显存。
- 引擎编译/自调优:TensorRT 编译、vLLM kernel autotuning 首次耗时。
- 实例预热:新副本拉起到可服务的时间。
优化手段
- 快速加载:safetensors +
mmap直接映射、多 rank 并行分片读入、权重放 RAM/本地 SSD 缓存。 - 预编译:TensorRT 提前 build engine、vLLM 缓存 compiled graph / autotune 结果。
- 量化减体积:INT8/INT4 权重文件更小、加载更快。
- 常驻预热池:预拉起并
warm up(跑一次 dummy 请求)的实例池,冷启动秒级。 - NUMA/内存感知:避免跨 NUMA 读权重拖慢加载。
分「加载(mmap/分片/量化)」与「预热(预编译 + 常驻池 warm up)」两层答,落到「冷启动从分钟级压到秒级」。
推理服务有哪些关键可观测指标?
核心指标
| 类别 | 指标 |
|---|---|
| 延迟 | TTFT、TPOT、E2E 延迟,P50/P90/P99 分位 |
| 吞吐 | tokens/s、requests/s、并发数 |
| 资源 | GPU 利用率(SM/显存)、KV cache 使用率、排队长度 |
| 质量/稳定 | 错误率、超时率、限流率、token 长度分布 |
观测体系
- 指标:Prometheus 采集 + Grafana 看板(vLLM/TGI 内置 metrics 端点)。
- 链路:OpenTelemetry 追踪单请求各阶段耗时(排队/prefill/decode)。
- 日志:请求级日志 + 采样。
SLO
- 通常对 TTFT/TPOT 设 SLO(如 P99 TTFT < 2s),据此做告警与自动扩容。
按「延迟 / 吞吐 / 资源 / 稳定性」四类报指标,点出 P99 分位与 KV cache 使用率两个关键,落到 Prometheus+Grafana。
Medusa 是什么?如何加速解码?
背景
传统投机采样需要独立的 draft 小模型,存在「draft 与 target 分布不一致、额外显存、双模型调度」的问题。
Medusa 原理
- 在 base 模型上追加多个轻量「Medusa head」,每个 head 预测未来第 i 个 token(i=1..k)。
- 一次前向同时产出 k 个候选 token,再用 base 模型验证;相比 draft 模型,共享底座、无分布漂移。
- Medusa-2 用 tree attention 把多个候选路径组织成树,一次前向验证多条路径,接受率更高。
收益
- 单模型、显存省、加速 2~3 倍,且实现简单(只需训几个小 head)。
讲清「在底座加多个 head 并行预测未来 token」,对比 draft 模型的优势(共享底座、无漂移),提 Medusa-2 的 tree attention。
投机采样中 draft 模型如何选择?
选择标准
- 接受率高:draft 与 target 输出分布越接近,候选被接受越多 → 选同家族的小模型(如 LLaMA-7B 配 LLaMA-68M)。
- 速度够快:draft 必须显著快于 target,否则抵消收益(draft 越小越快,但接受率可能降)。
- tokenizer 一致:draft 与 target 必须同词表,否则无法逐 token 对齐验证。
- 显存可控:draft 额外显存要小。
变体与权衡
- 静态小模型:简单但分布可能漂移。
- EAGLE:用 target 的 feature 训练 draft,接受率更高(动态 draft)。
- Medusa:干脆不要 draft 模型,用底座加 head。
- 核心权衡:draft 速度 × 接受率 共同决定加速比,需实测调优。
报出「接受率、速度、同词表、显存」四条标准,点「同家族小模型」与「EAGLE/Medusa 提升接受率」两个方向。
什么是 Early Exit(提前退出)?
概念
在 Transformer 各层之间插入中间分类/输出头,当某层输出的置信度超过阈值时,直接在此层退出,跳过剩余深层计算。
原理
- 简单 token/样本在浅层就能做出高置信预测,无需走完全部层。
- 用熵/最大概率作为退出判据,低于阈值才继续往下层走。
权衡
- 收益:平均计算量下降,简单输入加速。
- 代价:退出层增加参数与训练复杂度;难度大的样本仍走全层,收益不均匀。
- 代表:CALM(Confident Adaptive Language Modeling)做逐 token 动态层数;BERT 系 early exit 研究较多。
讲清「中间层置信度达标就提前退出、跳过深层」,说「简单输入提速、难样本仍走全层」的权衡,举例 CALM。
什么是模型剪枝?推理中有什么用?
概念
剪枝通过移除冗余参数(权重、注意力头、通道、层)减小模型体积与计算量,是压缩的另一条路线(对比量化是降精度)。
分类
| 类型 | 做法 | 特点 |
|---|---|---|
| 非结构化 | 逐权重置零 | 稀疏,需稀疏 kernel,实际加速难 |
| 结构化 | 删整头/整通道/整层 | 硬件友好,直接加速 |
| 半结构化 | 2:4 稀疏 | NVIDIA Ampere 起原生支持 |
方法
- 训练后剪枝:SparseGPT、Wanda 用二阶信息/激活幅度度量重要性,无需重训。
- 训练中剪枝:稀疏训练、结构化剪枝 + 微调恢复精度。
- 常与量化/蒸馏叠加,进一步压缩。
区分「非结构化(难加速)vs 结构化(硬件友好)」,提 2:4 稀疏与 SparseGPT/Wanda,点出剪枝常与量化叠加。
如何评估量化误差?
评估维度
- 困惑度(PPL):在测试语料(Wikitext-2、C4、PTB)上对比 FP16 与量化模型的 perplexity,PPL 上升越小越好。
- 下游任务精度:MMLU、HellaSwag、GSM8K、HumanEval 等基准上的分数对比。
- 分布一致性:KL 散度衡量量化前后输出 logits 分布的差异。
实践流程
- 先跑 PPL 快速筛(成本低、敏感)。
- PPL 异常再跑下游基准确认。
- 线上看端到端效果与用户指标。
判读
- INT8 通常 PPL 几乎不变;INT4 略升但仍可用;INT3/INT2 PPL 明显上升、需慎用。
- PPL 是「必要不充分」——PPL 好不一定任务好,需下游任务兜底。
答「PPL 快速筛 + 下游基准 + KL 分布」,强调「PPL 必要不充分、INT8 几乎无损、INT3 起明显掉点」。
vLLM、TGI、TensorRT-LLM、SGLang 有什么区别?
对比
| 框架 | 优势 | 劣势/特点 |
|---|---|---|
| vLLM | 易用、生态大、PagedAttention 高吞吐 | NVIDIA 外支持弱、极致性能略逊 |
| TGI | HuggingFace 官方、多模型、生产特性全 | 性能中上 |
| TensorRT-LLM | NVIDIA 上性能极致、FP8/量化强 | 编译成本高、上手复杂 |
| SGLang | RadixAttention 前缀缓存、结构化输出、高吞吐 DSL | 生态较新 |
选型
- 通用高吞吐/易用 → vLLM;HF 生态 → TGI;NVIDIA 极致性能 → TensorRT-LLM;共享前缀多/Agent 多轮 → SGLang。
- 实际常按「性能 vs 易用 vs 特性」三角取舍,多框架压测选优。
用表格四选一给结论:vLLM 易用、TGI 生态、TRT-LLM 极致、SGLang 前缀缓存/结构化输出,给出按场景选型。
SGLang 的 RadixAttention 是什么?
概念
RadixAttention 把 KV cache 组织成一颗前缀树(radix tree / trie):token 序列是树上的路径,共享前缀的请求自动复用同一段 KV cache,无需重复 prefill。
工作方式
- 请求进来,沿树匹配最长公共前缀,命中部分直接复用 KV,只算新增部分。
- 新增 KV 挂到树上;cache-aware 调度器把共享前缀的请求分到同批,最大化命中。
- 淘汰用 LRU:按最近访问时间踢叶子节点。
优势
- 相比 vLLM 的 block 哈希匹配,radix tree 是精确前缀结构,匹配更直接、命中更稳。
- 多轮对话、Agent(长 system prompt)、few-shot、RAG 批量场景加速显著。
答「KV 前缀树 + 最长公共前缀复用」,点出「cache-aware 调度 + LRU 淘汰」,对比 vLLM block 哈希更精确。
推理服务如何做灰度发布和 A/B 测试?
灰度发布(canary)
新模型/版本先放一小部分流量(如 5%~10%),观察指标,逐步放量,异常回滚。
A/B 测试
不同模型/配置(prompt、量化精度、采样参数)分流对比,用指标(质量、延迟、业务指标)决策。
实现
- 网关/负载均衡按比例路由到不同模型实例(不同 deployment/版本)。
- 用户 ID 哈希分流,保证同一用户始终命中同一版本(一致性)。
- 多模型同框架部署:vLLM 多副本、K8s canary、服务网格(Istio)灰度。
指标与回滚
- 观察错误率、TTFT/TPOT、业务转化/质量评测,达到阈值触发回滚或继续放量。
答「小流量灰度→观察指标→放量/回滚」,点出「网关按比例/用户哈希分流 + 指标阈值回滚」,落到 A/B 用业务/质量指标决策。