AIGC标识 大模型推理是怎么工作的——从原理到系统观

大模型推理是怎么工作的——从原理到系统观

以我们自己的推理服务为例。适合懂编程、不了解大模型的同学;前半篇讲原理,后半篇讲"为什么做好推理服务是一件系统工程"。
文中数字均来自我们 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 不是算不动,是喂不饱。这个特性决定了后面一堆优化方向:批处理、投机解码、小模型等等,本质都是在对付"搬一次参数只产一个字太亏"。

预填 vs 解码资源画像


四、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 就是这个——软件层直接改框架源码换显存。

KV 缓存三级优化

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 的"回源与边缘",计算集群的"提交节点与执行节点"——把特征相反的两类负载拆到各自特化的资源池,是系统设计里的通用手法。

PD 分离对比


六、模型层的快速迭代:最大的杠杆常在这

这是最容易被忽视的一层。模型架构的一点改动,对推理性能的影响经常超过软件和硬件的全部努力。举我们真实用过的三类:

  • 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 场景的主食。

MTP 一次循环


七、硬件层:拓扑决定天花板

基础事实: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 助手可用,越强的助手又反过来加速推理优化。我们这五个月的效率,本身就是这个循环的样本。

开源 + 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 实测。

posted on 2026-09-18 11:01  qiu2013  阅读(7)  评论(0)    收藏  举报

导航