在第 11 到 14 章,我们实现了模型推理的四项基本功能:采样策略、停止条件、键值缓存和批量推理。它们回答了两个问题:怎样控制模型生成,怎样让模型生成得快一点。
但是,我们实现的基本功能和工业界的推理系统之间还有很大的差距。今天的大模型服务,动辄同时处理成千上万个请求,模型参数达到数百亿甚至上万亿,推理的每一个环节都经过了极致的优化。
本章我们来梳理一下模型推理领域的主流技术。
大模型技术演进很快,本章内容截至 2026 年 11 月。
推理为什么慢¶
每次推理包含两个不同的阶段:
预填充(Prefill):一次性处理全部提示词元,计算它们的键和值,然后生成第一个词元。矩阵乘法规模大,瓶颈是算力(Compute-bound);
解码(Decode):之后每一步只处理一个新词元,串行生成。每一步都要把全部模型参数和 KV 缓存从显存读一遍,却只做很少的计算,瓶颈是显存带宽(Memory-bound)。
几乎所有的推理优化,都围绕三个目标:
少读数据:量化、GQA、MLA;
多做并行:连续批处理、投机解码;
少做重复:KV 缓存、前缀缓存。
KV 缓存的显存占用¶
键值缓存是用空间换时间,但是空间也不免费。每个词元的缓存大小为:
这里:
2:键和值各一份;
:层数;
:键值头数;
:每头嵌入尺寸;
:每个数值占用的字节数,FP16 为 2。
以 Llama-2-7B(32 层、32 个键值头、每头 128 维、FP16)为例,每个词元占用 512 KB,一个 4096 词元的序列就是 2 GB。同时服务 32 个请求,仅缓存就要 64 GB,比模型本身(约 14 GB)还大。
而 Llama-3-8B 使用 GQA,只有 8 个 KV 头,每个词元只需要 128 KB,同样的序列只要 0.5 GB。这就是为什么 GQA、MLA 能成为主流:它们直接缩小了缓存。
衡量指标¶
评价一个推理系统,需要从用户体验和系统效率两个角度:
首词元延迟(Time To First Token,TTFT):从发出请求到收到第一个词元的时间,主要由排队和预填充决定;
单词元延迟(Time Per Output Token,TPOT,也叫词元间延迟):之后每个词元的生成间隔,决定了“打字”的流畅度;
吞吐量(Throughput):系统每秒生成的词元总数,决定了单位成本;
有效吞吐(Goodput):只统计满足延迟要求的请求所贡献的吞吐;
尾延迟:关注 P99 等分位数,而不是平均值,因为少数很慢的请求会严重影响体验。
这些指标之间存在权衡:批大小越大,吞吐越高,但是每个请求的延迟也越高。推理系统的设计,就是在延迟目标(SLO)约束下,把吞吐尽可能提高。
模型压缩¶
解码的瓶颈是读取数据,那么最直接的办法就是:让模型变小。
量化¶
量化(Quantization):用低精度的整数(INT8、INT4)代替 FP16 或者 FP32 表示参数。显然,量化可以减少显存占用,加速解码。常见的量化方案:
仅量化权重(Weight-only):量化权重,计算时再反量化回 FP16。GPTQ 逐层利用二阶信息补偿量化误差, AWQ 保护对激活影响最大的少数权重通道;
量化权重和激活:权重和激活都量化,同时加速预填充和解码。难点是激活中存在少量数值极大的离群值(Outlier): LLM.int8() 把离群维度单独用 FP16 计算,SmoothQuant 把激活中的量化难度转移到权重上;
低精度浮点:FP8(Hopper 架构)、FP4(Blackwell 架构)等,保留浮点的动态范围,比整数更容易处理离群数值。例如 gpt-oss 的 MoE 权重使用 MXFP4 发布,让大模型可以放进单张 GPU;
KV 缓存量化:把 KV 缓存也量化,直接缩小缓存占用;
GGUF:llama.cpp 使用的文件格式,按块量化,让模型可以在 CPU 和消费级设备上运行。
量化是有损的。通常 INT8 几乎无损,INT4 有轻微的精度损失。训练后量化(PTQ)最常用,需要更高精度时也可以在训练中引入量化(QAT)。
剪枝¶
剪枝(Pruning):去掉模型中不重要的部分:
非结构化剪枝:把任意位置的权重置 0。压缩率高,但是普通 GPU 很难加速。 SparseGPT 可以一次性把大模型剪掉 50% 而精度几乎不变;
半结构化剪枝:每连续 4 个权重中有 2 个为 0,NVIDIA Ampere 架构有硬件支持;
结构化剪枝:直接去掉整个注意力头、通道甚至整层,得到一个更小的稠密模型。不需要特殊硬件,但是精度损失大,通常需要再训练或者配合知识蒸馏(见微调技术综述)。
注意力优化¶
注意力是推理中最特殊的部分:它的计算量随序列长度增长,缓存也随序列长度增长。
减少键值头¶
MQA、GQA、MLA 的原理在预训练技术综述中已经介绍。从推理的角度看,它们的价值是直接缩小 KV 缓存:GQA 把缓存缩小到 MHA 的几分之一,MLA 缓存的是低维的潜向量,可以压缩一个数量级以上。缓存变小意味着同样的显存能同时服务更多请求,每一步读取的数据也更少。
FlashAttention¶
FlashAttention 通过分块计算,避免把完整的注意力矩阵写入显存,同样适用于推理的预填充阶段。
解码阶段有一个特殊的问题:每步只有一个查询词元,在长序列上如果只沿查询方向并行,GPU 利用率很低。 Flash-Decoding 把键值沿序列长度方向切分,分别计算再合并,让长上下文的解码也能充分利用 GPU。
PagedAttention¶
最朴素的实现,是为每个请求预先分配一块能容纳最大长度的连续缓存。但是请求的实际长度事先未知,这会造成严重的显存浪费和碎片。
PagedAttention(由 vLLM 提出)借鉴操作系统的虚拟内存:把 KV 缓存切成固定大小的块(Block),用一张块表记录每个请求的逻辑块和物理块的对应关系,按需分配。这样几乎没有碎片,还可以让多个请求共享相同的块(比如共同的提示词),并且在需要修改时再复制(写时复制)。
前缀缓存¶
很多请求的开头是相同的:系统提示词、少样本示例、多轮对话的历史、智能体反复调用时不变的上下文。 前缀缓存(Prefix Caching)把这些公共前缀的 KV 缓存保存下来,新请求命中后可以直接跳过这部分的预填充,显著降低 TTFT 和成本。
实现上,SGLang 的 RadixAttention 用前缀树(Radix Tree)管理缓存,vLLM 也提供自动前缀缓存。许多模型服务的 API 还提供“提示缓存”功能,命中缓存的输入词元价格更低。
KV 缓存压缩¶
当缓存还是太大时,可以进一步压缩:
量化:把缓存存成 INT8 或者更低的精度;
淘汰:只保留重要的词元。StreamingLLM 发现开头的少数词元(注意力汇聚点)必须保留,配合滑动窗口就能处理超长输入; H2O、SnapKV 等方法根据历史注意力分数挑选重要的词元;
卸载:把不常用的缓存转移到 CPU 内存甚至 SSD,需要时再加载回来。
淘汰类方法是有损的,需要在效果和显存之间权衡。
长上下文¶
上下文增长带来三重压力:预填充的计算量(与长度的平方相关)、KV 缓存的显存、解码时读取缓存的带宽。应对方法包括:位置编码外推(YaRN 等)、稀疏注意力和线性注意力(见预训练技术综述)、前面介绍的缓存压缩,以及用上下文并行把长序列切分到多张卡上。
需要注意:模型“支持”长上下文,不等于能有效利用。RULER 等评测发现,模型实际有效的上下文尺寸往往短于宣称的数值;“迷失在中间”(Lost in the Middle)的研究也发现,模型对位于文本中间位置的信息表现更差。
请求调度¶
连续批处理¶
我们实现的批量推理是静态批处理:一批请求一起开始,一起结束,短的请求要等待最长的请求完成。GPU 在等待中被浪费,新到的请求也必须排队等下一批。
连续批处理(Continuous Batching,也叫迭代级调度)以每个解码步为单位调度:某个请求一生成结束,就立刻把它换出,同时把等待中的新请求换入。批的组成在每一步都可以变化,GPU 始终保持满载。这是现代推理引擎的基础技术。
分块预填充¶
一个很长的提示词,预填充需要很长时间。如果把它和其他请求的解码放在同一批里,所有人的解码都要被它拖慢,用户会感到明显的卡顿。
分块预填充(Chunked Prefill)把长提示词切成若干小块,每一步只处理一块,并和解码请求混合在同一批里。这样既保持了较高的 GPU 利用率,又避免了解码被长预填充阻塞,TPOT 更平稳。
预填充和解码分离¶
预填充受算力限制,解码受带宽限制,两者对硬件的需求不同。把它们混在同一批 GPU 上,会互相干扰,也无法分别优化 TTFT 和 TPOT。
预填充和解码分离(Prefill-Decode Disaggregation)把它们放到不同的 GPU 池里:预填充池算完 KV 缓存后,通过高速网络传输给解码池。两个池可以独立扩缩容、选择不同的并行方式和硬件。代价是需要传输 KV 缓存,对网络带宽要求高。
目前 vLLM、SGLang、TensorRT-LLM 等主流引擎都已经支持这种部署方式,NVIDIA Dynamo、llm-d 等系统在上层提供多节点的编排,并根据 KV 缓存命中情况路由请求。
分布式并行¶
单张 GPU 放不下模型,或者需要更低的延迟时,就要把模型分布到多张卡上:
张量并行:把每一层的矩阵切分到多张卡上,单个请求的延迟更低,但是每层都要通信,需要 NVLink 这样的高速互联,通常限制在一台机器内;
流水线并行:把不同的层放在不同的卡上,通信少,适合跨机器;
数据并行:多个完整的模型副本,各自处理不同的请求,用来扩大总吞吐。
混合专家模型¶
MoE 模型的推理有它的特殊性。每个词元只激活少数专家,所以计算量小,但是全部专家的权重都必须驻留在显存里。解码阶段每一步读取的是被选中的专家,批大小很小的时候,几乎每个专家都只处理很少的词元,带宽利用很不划算;只有批大小足够大,每个专家才能分摊到足够多的词元。
所以 MoE 通常采用专家并行:把不同的专家放在不同的卡上,词元通过全对全通信(All-to-All)发送给对应的专家。需要同时处理专家负载不均衡、通信开销等问题。DeepSeek 等大规模 MoE 服务,往往使用几十甚至上百张卡做专家并行,并配合预填充和解码分离。
解码加速¶
自回归解码每次只生成一个词元,是推理延迟的根本瓶颈。能不能每一步生成多个词元?
投机解码¶
投机解码(Speculative Decoding)的核心思想是:用一个便宜的草稿(Draft)机制先猜测后面的若干个词元,再让大模型一次性并行验证这些猜测。大模型处理多个词元的成本,和处理一个词元几乎一样(因为解码受带宽限制,算力是闲置的),所以如果猜对了,一次前向就能得到多个词元。
验证时使用特殊的拒绝采样规则:保留符合大模型分布的前缀,在第一个被拒绝的位置按修正后的分布重新采样。这个规则保证了最终输出的分布和大模型逐个生成完全一致,是无损加速。
草稿的来源有多种:
独立的小模型:同系列的小尺寸模型,需要和大模型分词器一致;
n-gram 或提示词查找:直接从提示词里复制片段,适合摘要、代码修改等输出和输入高度重复的场景;
额外的预测头:Medusa 在大模型上增加多个预测头同时预测后面的多个位置;
EAGLE 系列:用大模型内部的特征训练一个轻量的草稿头,目前应用最广;
多词元预测:模型在预训练时就带有 MTP 头(见预训练技术综述),推理时可以直接当草稿使用。
加速比取决于接受率(草稿被接受的比例)和草稿本身的开销。批大小很大时,GPU 算力不再闲置,投机解码的收益会缩小,甚至变成负收益,所以上线前必须在真实流量下测量接受率。
非自回归生成¶
另一个方向是彻底放弃从左到右的逐个生成。扩散语言模型(比如 LLaDA、Mercury、Gemini Diffusion)从一串被遮蔽的词元出发,每一轮并行预测多个位置,迭代若干步后得到完整文本。
它的优势是天然的并行,缺点也很明显:整体质量通常落后于同规模的自回归模型,需要多轮去噪才能收敛,并且无法直接使用标准的 KV 缓存。目前更实用的方式,是把扩散模型当作投机解码的草稿生成器。
生成控制¶
更多采样策略¶
我们实现了温度、Top-k、Top-p。还有一些常见的策略:
Min-p:只保留概率不低于“最大概率 × 比例”的词元,阈值随分布的尖锐程度自动变化,在高温度下更稳健;
典型采样(Typical Sampling):优先选择“信息量接近平均水平”的词元,避免过于平庸或者过于冷僻;
重复惩罚、频率惩罚、存在惩罚:降低已经出现过的词元的概率,缓解重复;
束搜索(Beam Search):同时保留多条候选序列,选择整体概率最高的。适合翻译、摘要等有明确“标准答案”的任务,但是在开放式生成中容易产生乏味重复的文本;
逻辑值偏置:人为调整某些词元的概率,用来鼓励或者禁止特定词元。
关于“确定性”还有一个常被忽略的问题:即使把温度设为 0,不同批大小下,推理的结果也可能略有差异。原因是 GPU 算子对批大小不是“不变”的,不同批大小会改变浮点运算的累加顺序。在需要严格复现的场景,比如强化学习训练中对比训练和推理的概率,必须使用批大小不变的算子。
受限解码¶
很多应用需要模型输出严格符合某种格式:JSON、特定的函数调用格式、符合某个语法的代码。靠提示词只能提高概率,不能保证。
受限解码(Constrained Decoding)在每一步生成时,根据当前已经生成的内容,计算出下一个“合法”的词元集合,把其余词元的逻辑值设为负无穷,再做采样。这样输出就一定符合要求。
约束通常用正则表达式、上下文无关文法或者 JSON Schema 描述,编译成自动机,再和词表对齐,得到每一步的合法词元。常用的工具有 llama.cpp 的 GBNF 语法、Outlines、XGrammar 等,vLLM 和 SGLang 也内置了结构化输出。
受限解码保证了格式,但是不保证内容正确,而且过强的约束可能影响内容质量。
推理时扩展¶
传统上,提升模型能力的方法是训练更大的模型。推理时扩展(Test-time Scaling)提供了另一条路: 在推理时花更多的计算,换更好的答案。
思维链(Chain-of-Thought):让模型先写出推理过程,再给出答案。推理模型(比如 OpenAI o1、DeepSeek-R1、Qwen3 的思考模式)通过强化学习把这种能力内化,生成很长的思考过程;
多次采样 + 投票:对同一个问题采样多个答案,取出现次数最多的(自一致性);
Best-of-N:采样 N 个答案,用奖励模型或者验证器选最好的;
搜索:用树搜索等方法,在推理的每一步探索多个分支;
思考预算:让用户控制思考的投入。Qwen3 支持“思考 / 非思考”两种模式,并且可以限制思考的长度;DeepSeek-V4 同样有思考和非思考两种模式,思考模式下还可以选择推理强度(
reasoning_effort)。
推理时扩展改变了推理系统的负载特征:思维链让每个请求的输出长度大幅增加,KV 缓存和解码吞吐成为更突出的瓶颈。这也是前面所有推理优化技术越来越重要的原因。
推理引擎¶
前面介绍的技术,被集成在各种推理引擎中,用户不需要从头实现:
| 引擎 | 特点 |
|---|---|
| vLLM | 最广泛使用的开源引擎,PagedAttention、连续批处理、前缀缓存、投机解码、多种量化,生态最完整 |
| SGLang | 强调 RadixAttention 前缀缓存和结构化输出,多轮对话、智能体场景表现突出 |
| TensorRT-LLM | NVIDIA 官方引擎,针对自家 GPU 深度优化,峰值性能高,部署更复杂 |
| llama.cpp | C/C++ 实现,支持 CPU、Apple 芯片和各类消费级设备,GGUF 格式的来源 |
| Ollama、LM Studio | 在 llama.cpp 等引擎之上封装的本地运行工具,开箱即用 |
| MLX | Apple 为自家芯片开发的数组框架,适合 Mac 上的推理和微调 |
| NVIDIA Dynamo、llm-d | 位于引擎之上的多节点编排层,负责预填充和解码分离、KV 感知的路由;Dynamo 可搭配 vLLM、SGLang、TensorRT-LLM,llm-d 基于 vLLM 和 Kubernetes |
Hugging Face 的 TGI 已经进入维护模式,官方建议新部署改用 vLLM、SGLang,或者 llama.cpp、MLX 等本地引擎。
选择的一般原则:在个人电脑上本地运行,选择 llama.cpp、Ollama 或 MLX;在 GPU 服务器上提供服务,选择 vLLM 或 SGLang;追求 NVIDIA 硬件上的极致性能,考虑 TensorRT-LLM。
本章,我们梳理了推理领域的主流技术:
少读数据:量化、剪枝、GQA 和 MLA、KV 缓存压缩;
少做重复:KV 缓存、PagedAttention、前缀缓存;
多做并行:连续批处理、分块预填充、预填充和解码分离、投机解码;
控制生成:更多采样策略、受限解码;
用算力换质量:推理时扩展。
我们实现的 KV 缓存和批量推理,是这些技术的起点:缓存解决了重复计算,批处理提升了并行度。工业级的推理系统,是在这个基础上围绕“显存带宽”这个核心瓶颈,一层一层优化出来的。
参考资料¶
Kwon 等,Efficient Memory Management for Large Language Model Serving with PagedAttention,2023。
Dao 等,FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness,2022。
Frantar 等,GPTQ: Accurate Post-Training Quantization for Generative Pre-trained Transformers,2022。
Lin 等,AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration,2023。
Dettmers 等,LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale,2022。
Xiao 等,SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models,2022。
OpenAI,gpt-oss-120b & gpt-oss-20b Model Card,2025。
Frantar 和 Alistarh,SparseGPT: Massive Language Models Can Be Accurately Pruned in One-Shot,2023。
Xiao 等,Efficient Streaming Language Models with Attention Sinks,2023。
Zhang 等,H2O: Heavy-Hitter Oracle for Efficient Generative Inference of Large Language Models,2023。
Li 等,SnapKV: LLM Knows What You are Looking for Before Generation,2024。
Liu 等,Lost in the Middle: How Language Models Use Long Contexts,2023。
Hsieh 等,RULER: What’s the Real Context Size of Your Long-Context Language Models?,2024。
Zheng 等,SGLang: Efficient Execution of Structured Language Model Programs,2023。
Yu 等,Orca: A Distributed Serving System for Transformer-Based Generative Models,2022。
Agrawal 等,Taming Throughput-Latency Tradeoff in LLM Inference with Sarathi-Serve,2024。
Zhong 等,DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving,2024。
Leviathan 等,Fast Inference from Transformers via Speculative Decoding,2022。
Cai 等,Medusa: Simple LLM Inference Acceleration Framework with Multiple Decoding Heads,2024。
Li 等,EAGLE: Speculative Sampling Requires Rethinking Feature Uncertainty,2024。
Nie 等,Large Language Diffusion Models,2025。
Nguyen 等,Turning Up the Heat: Min-p Sampling for Creative and Coherent LLM Outputs,2024。
Dong 等,XGrammar: Flexible and Efficient Structured Generation Engine for Large Language Models,2024。
Wang 等,Self-Consistency Improves Chain of Thought Reasoning in Language Models,2022。
Snell 等,Scaling LLM Test-Time Compute Optimally can be More Effective than Scaling Model Parameters,2024。
He 等,Defeating Nondeterminism in LLM Inference,Thinking Machines Lab,2025。