6.4 推理服务框架:一台服务器伺候一千个人
同一张卡,差出几十倍
做个实验:用 Python 的 transformers 库写十行代码,把一个 7B 模型跑起来对外服务;再用 vLLM 这样的专业推理框架跑同一个模型、同一张卡。压测结果常常让人怀疑硬件被调包了——每秒能服务的用户数,能差出几倍到几十倍。
模型没变、显卡没变,差距全在工程。这一节讲专业框架的三大魔法,它们分别堵住了朴素服务的三个大漏洞——前两个关乎吞吐(一台机器能伺候多少人),第三个关乎延迟(每个人要等多久)。
漏洞一:先写完的乘客在干等
GPU 喜欢成批干活(第 4 章讲过:批越大,算力利用率越高),所以服务器会把多个用户的请求拼成一批同时生成。但朴素的做法是「整批进、整批出」——就像一辆旅游大巴:等 32 位乘客全部上车才发车,开到终点才统一放人。
问题是回答有长有短:有人的回答 10 个 token 就写完了,有人要写 1000 个。先写完的只能坐在座位上干等,那个位置的算力全部白烧;门外排队的新请求,也必须等整车到站才能上车。
连续批处理把大巴换成了地铁:调度以「生成一步」为单位——每往前走一步,谁的回答结束了就立刻下车,空出的位置马上让排队的新请求上来。GPU 上永远坐满干活的乘客,没有一个空座。
漏洞二:显存被「包间制」浪费
第 6.2 节说过,KV 缓存是推理显存的大户。朴素实现还要雪上加霜:服务器不知道每个用户会聊多长,只好给每个请求预留一整块「最大可能长度」的连续显存——像酒店不管来一个人还是十个人,一律开最大的宴会厅。
结果就是:大部分预留空间空着;而且长短不一的「包间」进进退退,显存被切得七零八落——明明总量还够,却找不出一块连续的大空 间给新请求(碎片化)。vLLM 团队实测(2023 年论文数据):传统系统里真正装着有用数据的 KV 显存只有两三成,其余全在陪跑。
分页注意力(PagedAttention,vLLM 2023)把操作系统课搬了过来:别开包间了,把每个请求的缓存切成固定大小的小页,用到哪页才分配哪页;零散的物理页靠一张「页表」串成逻辑上连续的序列。浪费从 60% 以上降到 4% 以下(论文数字)。
显存省下来 = 同一张卡能同时伺候更多请求 = 吞吐量成倍上涨。两招合力,vLLM 论文报告的吞吐相对当时的常规服务方式提升了一个数量级以上(2023 年数字,具体倍数随场景变化)。
漏洞三:一个字一个字地吐,太慢了
前两招都在解决吞吐——一台服务器同时伺候多少人。但坐在屏幕前的那个用户关心的是另一件事:我的回答出得快不快。这是延迟,前两招帮不上忙。
延迟的瓶颈在 6.1 节已经点破了:解码阶段每生成一个 token,都要把整个模型的权重从显存搬一遍进计算单元。一个 14 GB 的模型,吐一个字就搬 14 GB。真正的乘法运算量少得可怜,绝大部分时间花在搬运上。
这里藏着一个巨大的浪费:既然搬一次权重的成本这么高,那这一趟只算一个 token 岂不是太亏了? 同样搬这 14 GB,顺手多算几个 token 几乎不要额外时间——问题是自回归生成必须一个接一个,你不知道下一个词是什么,就没法算下下个词。
投机解码(2022-2023)的破解思路是先猜后验:
找一个又小又快的「学徒」模型,让它先一口气猜出接下来 5 个 token 的草稿。然后大模型一趟把这 5 个位置全部并行验一遍:从头对,对到哪个位置错了就从哪里截断,把错的那个换成自己的答案。
关键在于:验证 5 个 token 和生成 1 个 token,搬运的权重是同一份,所以耗时几乎一样。学徒猜对了,你就白赚几个 token;猜错了,也只是浪费了学徒那点微不足道的算力,大模型的这一趟并没有白跑(错的位置上它给出了正确答案)。
日常里的类比:你写代码时的自动补全。它猜出一整行,你扫一眼——对就按 Tab 全收,不对就改掉后半截。无论如何都比一个字母一个字母敲快。
最妙的一点是:这不是近似。通过一个精心设计的接受/拒绝规则,投机解码在数学上可以严格保证——最终吐出来的文本,和你直接用大模型逐字生成的概率分布完全一致。你没有用质量换速度,纯赚。
三个前提缺一不可。
一、学徒得猜得准。 接受率低了,大模型天天在给错误草稿擦屁股,反而更慢。所以学徒通常要和大模型「师出同门」(同系列的小尺寸版本,或专门训练的草稿头)。
二、它救的是延迟,不是吞吐。 前面两招在服务器满载时最有价值,投机解码正相反:用户少、GPU 闲的时候收益最大。因为它的本钱是「反正搬一次权重有富余算力」——当服务器已经被几百个并发请求塞满、GPU 从「搬运受限」变成「算力受限」时,那份富余就不存在了,加速比会明显缩水甚至倒亏。
三、简单任务收益更高。 代码、格式化输出、有固定套路的文本,学徒容易猜中;开放式创作的接受率就低得多。
如今这套思想已是行业标配:vLLM、SGLang、TensorRT-LLM 等主流推理框架(2025 年生态)各有绝活,但地基都是这几块。更进一步,由于预填充吃算力、解码吃带宽(6.1 节的结论),2024-2025 年不少大厂干脆把两个阶段拆到不同的机器上各自优化——「prefill/decode 分离」。
本节引用的浪费比例、加速倍数都来自特定时间点的论文与实测(已标注年份),框架每个版本都在进步,具体数字请以官方文档为准。另外,真实推理系统的工程远不止这三招——量化内核、请求优先级、抢占与降级、prefill/decode 分离的调度……本节只讲清「为什么快」的三个核心思想。
小结
- 朴素服务的两大浪费:先完成的请求占着座位干等(静态批处理)、KV 显存包间制(预留+碎片化)。
- 连续批处理按「生成步」调度,随下随上,GPU 永远满载。
- PagedAttention 用操作系统分页的思路管理 KV 缓存,显存浪费从 60%+ 降到 4% 以下(2023 年论文数字)。
- 显存省下来就能塞进更多并发请求——省显存与提吞吐是同一件事。
- 投机解码治的是另一种病:小模型猜几个 token、大模型一趟并行验证,把「搬一次权重只算一个字」的浪费摊薄。数学上保证输出分布不变,是无损加速。
- 分清两类优化:连续批处理 / PagedAttention 提吞吐(服务器满载时最值钱),投机解码降延迟(GPU 空闲时最值钱)——高并发下后者收益会显著缩水。
延伸阅读
- vLLM 论文:Efficient Memory Management for LLM Serving with PagedAttention (2023)——连续批处理与分页注意力的出处,写得非常好读。
- Fast Inference from Transformers via Speculative Decoding (Leviathan et al., 2022)——投机解码与「分布不变」证明的原始论文。
- Medusa (2024)——不用额外草稿模型的投机解码变体。
- 下一节 6.5 蒸馏与小模型:优化到头还嫌贵?干脆换个小模型。