大模型推理是怎么工作的——从原理到系统观
大模型推理是怎么工作的——从原理到系统观
以我们自己的推理服务为例。适合懂编程、不了解大模型的同学;前半篇讲原理,后半篇讲"为什么做好推理服务是一件系统工程"。
文中数字均来自我们 8×4090 服务器的实测。

一、一句话说清推理
大模型是一个超大的"猜下一个字"函数:输入一段文字,算出下一个字,拼回去再猜下一个,循环到结束符。推理服务就是把这个函数部署成常驻接口——和把业务函数包成 HTTP 服务本质相同。
但和传统服务的关键区别在量级:这个"函数"有上千亿参数、几百 GB;一次调用不是算一次,而是循环几百次;瓶颈不在 CPU 和磁盘,而在显存和卡间通信。所以它值得单独一门学问。
训练是写程序(改参数),推理是运行程序(参数不动)。 训练一次几千万,推理每次几厘钱——全行业都在卷推理成本,原因在这。
二、系统观:性能是三层栈相乘的结果
先把全文最重要的一张图放出来。一个推理服务的表现,由三层共同决定:

┌────────────────────────────────────────────┐ │ 模型层:模型架构本身好不好算 │ ← 换 Qwen3.6 → Qwen3.8 就是在动这层 ├────────────────────────────────────────────┤ │ 软件层:推理框架怎么调度、怎么算 │ ← vLLM 参数调优、打补丁、PD 分离在这层 ├────────────────────────────────────────────┤ │ 硬件层:卡多快、卡间怎么连 │ ← 买什么卡、怎么分组在这层 └────────────────────────────────────────────┘
三个认识,贯穿后面所有章节:
- 三层是乘法不是加法。任何一层接近零,整体就接近零。软件再好,卡间通信绕远路,GPU 就是集体等数据(我们实测过:同一组卡,换一种分组方式吞吐差近 4 倍)。
- 短板会漂移。修好一层,瓶颈就换到另一层。我们的经历:先卡在框架稳定性,再卡在卡间通信,最后卡在模型本身的算力需求。优化是"找当前最短的那块板"的循环。
- 模型层迭代最快、杠杆最大。硬件几年一换,软件一季一版,模型一月一新——而且新模型经常自带推理友好设计(后面第六节展开)。只盯着硬件堆砌,会错过最大的一层。
三、模型本体与生成过程
参数(权重):模型就是几万个大矩阵、上千亿个数字,知识全在里面,训练完固定。可以理解成"只读数据库 + 固定查询逻辑"。
Token:文字先切成小段(token)再查表变编号,模型吃编号序列。1 个汉字 ≈ 0.6~1 个 token,计费、限长、算显存全按它。
逐字生成:没有"一次算出整个答案"。读入问题 → 猜第 1 个字 → 拼回去 → 猜第 2 个字……你在界面上看到流式输出,是因为服务端真的在逐字现算。
两个阶段(全文第二重要的概念):
| 阶段 | 干什么 | 资源特征 | 类比 |
| 预填 prefill | 一次性读入问题 | 成千上万 token 一起算,吃计算(GPU 算力打满) | 批量导入 |
| 解码 decode | 答案逐字生成 | 每次只算 1 个 token,吃显存带宽(反复搬运整个模型参数,就为产出一个字) | 逐行查询 |
为什么 decode 是"带宽问题"?算一个字只需几万亿次乘加,但要把几百 GB 参数全部从显存搬一遍。搬运时间远大于计算时间——GPU 不是算不动,是喂不饱。这个特性决定了后面一堆优化方向:批处理、投机解码、小模型等等,本质都是在对付"搬一次参数只产一个字太亏"。

四、KV 缓存:省掉重复计算的账
逐字生成时,前面 token 的中间结果不变——存起来复用,就是 KV 缓存。没有它,生成第 N 个字要重读前 N-1 个字,总代价 O(n²);有了它变 O(n)。这是用显存换计算的经典交换。
代价:KV 缓存随上下文线性暴涨,一次长对话几个 G,而模型参数已经快占满显存——长上下文又慢又贵的根源在这。
工程上的三级压榨(层层递进):
- 块化管理(PagedAttention):早期框架按"最长可能的请求"预留整块显存,浪费严重;改成操作系统内存分页那样按小块分配,同样的显存能多塞几倍的请求。这是 vLLM 当年一炮打响的核心。
- 前缀缓存(prefix cache,vLLM 中称 APC):agent 请求都带同一段几千 token 的系统提示词,这段的 KV 人人复用。我们实测 agent 场景命中率 87%+,直接省掉大半预填计算。
- 精度压缩(fp8 KV):缓存数字 16 位压成 8 位,容量翻倍精度几乎无损。我们给社区 fork 提的 PR 就是这个——软件层直接改框架源码换显存。

4.1 延伸:前缀缓存(APC)详解
前缀缓存是三级压榨里收益最"白捡"的一级,展开讲讲它的机理和边界。
原理:KV 缓存有个数学性质——只看前缀。 生成第 1000 个字要用到的中间结果,只取决于它前面的 999 个字,与后面无关。因此两个请求只要开头一段 token 完全相同,这段的 KV 缓存就是逐字节一样的,谁都能拿来直接用——第一个请求算完,后来的请求从"分叉点"接着算就行。
框架的实现(vLLM 里叫 APC,自动前缀缓存)大致是:把每个请求的 token 序列按块建成一棵前缀树,新请求来了沿着树匹配,匹配到哪一块就复用到哪一块,匹配不上的部分才真正计算。全程自动,业务方零改造。
为什么 agent 场景是它的主场? 看 agent 一次请求的构成:
[系统提示词:工具说明、角色设定……几千 token,人人相同、次次相同] [历史对话:这一轮比上一轮只多了一问一答] [本轮新问题:几十~几百 token]
前两段要么全量命中、要么增量极小——真正要现算的只有尾部。我们实测 agent 场景命中率 87%+,意味着大部分"读入"根本没发生,首字延迟和算力消耗直接砍掉一大半。这就是"带记忆的多轮对话越聊越便宜"的底层原因。
边界(什么时候它帮不上忙):
- 前缀必须严格逐 token 相同。系统提示词哪怕改了一个字,从那个字往后全部失效。所以提示词要"公共部分放前面、易变部分放后面",顺序本身就是性能。
- 每个用户的问题各不相同——只有公共前缀能共享,用户各自的内容永远要现算(本来也不该指望共享,那不是缓存能救的)。
- 缓存会被挤出去。显存装满时按"最久未用"淘汰,挤掉后下一个请求就得重算。并发越高、上下文越长,命中率越低——缓存容量和并发能力是同一块显存里的竞争关系,又回到第四节那本显存账。
- 重启即清零。缓存在显存里,引擎重启全没了,重启后的第一波请求都是冷计算(这也是我们测性能"弃首轮"的原因之一)。
一个实用视角:APC 命中率是 agent 服务最值得盯的健康指标之一——它掉了,通常意味着提示词结构变了、流量结构变了、或者显存压力变大在挤缓存,都是需要人看一眼的信号。

五、一次请求的完整旅程(我们的真实链路)

这条链上每一环都是优化对象:
- 网关层(newapi/OpenResty):改写模型名、补默认参数、剥多余 header。看似杂务,但"注入默认值绝不覆盖客户端显式传参"这类纪律出过错就是事故。
- router 分诊:把预填请求发给 P 引擎、解码请求发给 D 引擎。
- PD 分离:第三节说过预填吃算力、解码吃带宽,两种活对 GPU 的用法完全相反。混跑时一个长文档在预填,所有人的字都卡住。拆成"4 张卡专心读、4 张卡专心写"后,我们单用户速度接近翻倍。代价是 KV 要整块搬家(GB 级走 PCIe,实测 ~2.7GB/s)——软件架构的收益和成本,要用测量来裁决。
- 批处理(continuous batching):decode 阶段单请求喂不饱 GPU,调度器把几十个请求的字凑成一批一起算,搬运一次参数产出几十个字。这是吞吐的头号来源,也是"并发越高、单请求越慢"的根源(延迟换吞吐,和线程池一个道理)。
5.1 延伸:PD 分离架构详解
PD 分离值得单独讲透,因为它是"用系统架构对冲模型特性"的典型案例。
为什么必须分? 回顾第三节的资源画像:预填是几千 token 一起算、GPU 算力打满的"重活";解码是每步 1 个 token、以搬运参数为主的"碎活"。混在同一个引擎里会互相伤害:
- 一个 200K 长文档进预填,整张卡的算力被它占走,其他所有用户的字都停止往外蹦——体感就是"有人问了个长问题,全场卡住";
- 反过来,解码阶段的"碎活"把算力利用率拖得很低,预填排队变长,首字延迟上涨。
两类负载对资源的诉求完全相反,最优配置也相反(预填想要大 chunk 大批量吃满算力;解码想要小步快跑、极致降低每步延迟)。分不开,就只能取折中;分得开,两边各自逼近最优。
分了之后的代价? 预填引擎算完的 KV 缓存必须整块搬到解码引擎(GB 级),搬完解码才能开始吐字。这是新增成本,我们实测传输 ~2.7GB/s。所以 PD 分离不是无脑赚——输入短、流量小的场景,搬家开销可能吃掉收益;输入长(agent 带几千 token 系统提示词)、并发高的场景,收益远大于开销。我们的链路属于后者。
和传统架构的类比:这就是数据库的"读写分离",CDN 的"回源与边缘",计算集群的"提交节点与执行节点"——把特征相反的两类负载拆到各自特化的资源池,是系统设计里的通用手法。

六、模型层的快速迭代:最大的杠杆常在这
这是最容易被忽视的一层。模型架构的一点改动,对推理性能的影响经常超过软件和硬件的全部努力。举我们真实用过的三类:
- MoE(混合专家):每次只激活一小部分参数。Qwen3.8 是 128B 总参数、只激活十几 B——同样的"智商",显存要全装但计算量小一个量级。这就是"大模型能跑在 8 张游戏卡上"的前提。
- 多 token 预测(MTP/投机解码):让模型一次猜 3-4 个字再自查一遍,错了回退。我们生产开着 MTP k=3,实测约 55-60% 的草稿字被采纳、每步净产出约 2.7-2.8 个字,decode 直接上台阶。这是模型自带的加速器,老模型没有。
- 量化与压缩:权重从 16 位压到 8/4 位,模型小一半以上,速度提升明显、精度轻微损失。推理专用模型(名字里带 Flash/Lite 的)从设计之初就为便宜推理优化。
我们五个月换了三代主力模型(Qwen3.6-35B → DeepSeek V4 Flash → Qwen3.8-Flash-Next 128B),每一代换模型的体验提升,都大过同一代里几个月的软件调优。结论:做推理服务的人必须盯模型发布节奏,"上新模型"本身就是性能手段。
但模型层也有反面:新模型经常用上新算子,旧框架跑不了或跑不对——我们就遇到过新模型在旧框架上输出乱码、崩溃。模型迭代倒逼软件升级,这是三层栈联动的又一例。

6.1 延伸:MTP 投机解码详解
MTP(多 token 预测)也值得单独讲——它是"用数学特性换速度"的代表。
要解的题:解码阶段每产一个字,都要把几百 GB 参数搬一遍。不管这个字多好猜,代价都一样。比如输出 JSON,下一个字符十有八九是 "——为这么好猜的一个字搬一遍全部参数,是纯粹的浪费。
思路:一次循环多猜几个字,再统一验货。具体分两种实现:
- 投机解码(经典款):用一个几十倍小的"草稿模型"快速连猜 4-5 个字(小模型搬的参数少,猜字便宜),再让大模型一次性并行验证这串字(验证 k 个字和验证 1 个字,搬参数的代价几乎相同——这是整个方案成立的数学基础)。猜对几个就白赚几个,猜错就从错的位置回退重猜。
- MTP(模型自带款):训练时就让模型额外长出"一步猜多字"的头,不需要外挂小模型。Qwen3.8 带了这个能力,我们生产开着 MTP k=3(一步猜 3 个字)。
关键指标是接受率,但要看清口径:vLLM 里它定义为"被采纳的草稿字 ÷ 全部草稿字"(只数猜的部分,不含每步必然产出的保底字)。由此每步净产出 = 1 + 接受率 × k。我们生产实测 k=3、接受率约 55-60%,即每步净产出约 2.7-2.8 个字——注意这是解码循环产出效率的理论上限,实际加速比低于它(验证步比普通步算的字多),我们没做过关闭 MTP 的对照实测,不引用具体加速倍数。最重要的性质不变:输出内容和逐字生成严格一致(猜错回退),不牺牲任何准确性——这是它和量化(轻微掉精度)的本质区别。
为什么说它是"模型层的加速器":这个能力必须训练时就设计进去(或至少有小模型可用),推理框架只是启用它。老模型没带,软件层无从加——又一次印证"模型层是最大杠杆"。
代价与边界:验证步需要额外计算;猜错时本步作废,极端场景(输出完全不可预测,如随机数)接受率趋近零反而变慢。所以它对代码、文档这类"高可预测输出"收益最大——恰好是我们 agent 场景的主食。

七、硬件层:拓扑决定天花板
基础事实:GPU 的算力和显存带宽都是固定的,但"卡怎么连"往往比"卡多快"更重要。
- 张量并行(TP):矩阵大到一张卡算不动,切开分几张卡各算一块、每层汇总一次。类比分库分表后聚合。
- 互连是命门:有 NVLink 的机器汇总近乎免费;我们这种 PCIe 机器,每次汇总绕主机内存,GPU 大量时间在等数据而不是在算。我们读通信库源码逐条核实后的结论:本拓扑通信带宽已逼近物理上限(每跳要过两次 PCIe,有效带宽约为线速一半)——这句话就是"天花板"的定量描述,调参数只能在它下面挪。
- 分组即优化:我们收益最大的一次优化没改任何参数,只是重排"哪几张卡负责哪部分计算",让通信不再跨 CPU 插槽(NUMA),8 并发吞吐 85 → 334 字/秒,近 4 倍。
硬件层的正确姿势:先花时间量清拓扑(卡挂在哪个 CPU、卡间直通还是绕行),再谈调优。我们曾在没量清拓扑时下过错误结论,被实测打脸后纠正——这是花真金白银买来的教训。

八、系统工程方法论:怎么在这三层里干活
三层栈 + 短板漂移,决定了做推理优化的方法论(也是我们踩坑后固化的纪律):
- 先定位再动手:用测量回答"瓶颈到底在哪一层"。我们用逐秒采样确认过长文档预填时 GPU 计算率 85-98%、PCIe 只有间歇突发——一句话排除"通信瓶颈"假设,避免白费几周调通信参数。
- 一次只改一个变量:多参数同改永远说不清是谁的功劳。改一个、测一轮、和当前基线比。
- 预热后弃首轮:刚重启的第一轮数据被编译预热污染,不作数。
- 无提升立即回退:我们试过十项参数只留两项(比如去掉通信协议钉死让小消息走快通道,decode +20%;而加通道数、加缓冲区反而 -2%~-6%)。"试了没用"和"试了有用"一样是结论,回退要干脆。
- 质量门硬线:所有涉及数值路径的改动(量化、补丁),必须过固定题集验证输出质量 6/6,性能数字再好看也不上线。
- 失败要失败到根因:我们停研过好几个方向(缓存共享组件、跨版本组合等),每个都定位到了源码级的确切原因,能明确说"这条路为什么走不通、等什么条件才能通"。能说清原因的失败是资产,说不清的才是浪费。
九、五个月实测复盘:三层各贡献了什么
用我们自己的数字给"三层栈"作证:
| 时间 | 动的是哪层 | 事件 | 效果 |
| 7月中 | 模型层 | Qwen3.6-35B 上架 | "第一次觉得能用",但智能不足 |
| 7月下 | 模型+硬件 | 换 DeepSeek V4 Flash + P2P 驱动打通 | 模型能跑起来 |
| 7月末 | 硬件层 | 卡分组重排,消跨插槽通信 | 8 并发 85 → 334 字/秒 |
| 8月 | 软件层 | PD 分离 + KV 传输链路 | 单用户解码 42 → 80 字/秒 |
| 9月 | 模型层 | 换 Qwen3.8-Flash-Next(MoE+MTP) | 智能和速度双升,decode 146 字/秒 |
| 9月 | 软件层 | chunk 调优 + 通信协议放开 + fp8 KV 补丁 | 预填 3,000 → 6,815 字/秒 |
| 现在 | 全部到顶 | 并发画像摸底 | 饱和 24 并发、聚合 ~930 字/秒,瓶颈回到算力本身 |
注意最后两行:当三层都被压榨过后,瓶颈回到"模型每算一个字需要的计算量 × 硬件算力"这个物理乘积上——这就是"该换硬件或等下一代模型"的信号,而不是继续调参的信号。系统思维的终点是知道何时收手。
十、藏在技术之外的两股力量:开源与 AI
复盘这五个月,有两股力量不属于"三层栈"的任何一层,却贯穿了每一层——不讲它们,这篇介绍就不完整。
开源的力量:你不是从零造轮子,而是站在全球协作的流水线上。
- 我们用的推理框架 vLLM、通信库 NCCL、无数算子,全部开源。更关键的是fork 生态:主流项目周围总有社区开发者针对特定硬件维护的分支——我们最终选定的底座,就是一位社区作者为 4090 这类显卡持续适配新模型和维护稳定性的 fork。没有它,我们自己在几百万行代码里补齐新模型支持,几个月都不够。
- 开源的协作方式是真实的双向流动:我们在使用中发现了问题、做了改进(fp8 KV 缓存补丁),就能直接给社区提 PR,维护者 review 合入后,全世界用同款硬件的人一起受益;别人修的 bug,我们也免费拿到。这种"人人为我、我为人人"的复利,是闭源产品给不了的。
- 一个实用经验:选开源底座,除了看功能,更要看社区活不活跃、维护者回不回 issue。我们在两个 fork 之间的切换(一个跑得起来但生产暴露乱码卡顿,一个稳定且持续跟进新模型),本质上就是"选社区"而不是"选代码"。
AI 的助力:它把"个人能力够不着"的事变成了够得着。
- 这五个月里,读懂几十万行框架源码定位根因、写补丁、给上游 issue 组织素材、逐条核实通信库的默认行为——这些工作单靠一个人原有的知识储备根本做不完。实际的工作方式是:AI 做源码分析和初稿,人负责提问、验证和决策。
- 注意分工的要点:AI 会自信地给出错误的结论(我们被它"文档式记忆"坑过好几次,最后都被实测纠正)。所以有效的用法是"AI 放大能力、测量纪律当护栏"——每个关键结论都要落到源码或实测命令上,光"AI 说了"不算数。
- 趋势本身也值得写进这篇介绍:推理成本下降和 AI 能力上升是互相咬合的两个齿轮——越便宜的推理让越强的 AI 助手可用,越强的助手又反过来加速推理优化。我们这五个月的效率,本身就是这个循环的样本。

十一、收尾:对照表 + 三句话
| 大模型推理概念 | 传统开发对应 |
| 模型权重 | 只读数据库 + 固定查询逻辑 |
| token | 文字的编码单位 |
| 预填 / 解码 | 批量导入 / 逐行查询 |
| decode 吃带宽不吃算力 | 每查一行都要全表扫一遍 |
| KV 缓存 | 会话缓存(不存则 O(n²) 重算) |
| 分页显存管理 | 操作系统内存分页 |
| 前缀缓存 | CDN / 相同入参结果缓存 |
| 批处理 | 线程池攒任务 |
| 张量并行 | 分库分表 + 每层聚合 |
| PD 分离 | 读写分离 |
| MoE | 大库但每次查询只碰小索引 |
| 投机解码 MTP | 先猜后校验的乐观并发 |
| TTFT / 吞吐 / 并发 | 响应时间 / QPS / 连接池上限 |
三句话带走全文:
- 推理是逐字猜测的循环:预填吃算力、解码吃带宽,两阶段特征相反,一切架构设计(批处理、PD 分离)都由此展开。
- 显存是第一约束:参数、KV 缓存、临时空间三家抢地方,量化、分页、前缀缓存都是在这本账里腾挪。
- 性能 = 模型 × 软件 × 硬件三层相乘:短板会漂移,优化是"测量定位 → 单变量改动 → 无效回退"的循环;模型迭代是最大杠杆,硬件拓扑是最终天花板。
最后一个展望:本文讲的三层栈,目前都由人类设计和优化。但如果递归式自我改进(RSI)成立——即 AI 显著参与下一代 AI 的设计与训练——那么"模型层"的迭代速度和方式都会质变:下一代模型可能不再是人类设计的,架构里可能出现人类难以直观理解的取舍(只要它算得更省、更聪明)。到那时,本文的框架依然成立(三层相乘、短板漂移、测量裁决),只是"动哪一层、谁来动"的答案会变——而会提问、会验证、会做工程判断的人,依然是把这一切变成可靠服务的那一环。这也是为什么:理解这套系统原理,比记住任何一组当下的参数更重要。
数据来自我们 171 服务器(8×RTX 4090 48G,Qwen3.8-Flash-Next 128B,PD 分离栈)2026-09 实测。
浙公网安备 33010602011771号