推理:服务系统
训练决定了模型“会不会”,推理系统决定了模型“能不能以可接受的成本稳定地服务用户”。
这一页重点不是模型原理,而是从系统角度解释:为什么同一个模型,在不同服务栈上,成本和延迟可能差一个数量级。
推理系统的核心不是“启动模型”。它要管理请求排队、prefill、decode、KV cache、batching、路由和尾延迟。用户感受到的慢,可能来自模型,也可能来自队列、缓存或调度。
Prefill 像一次性备菜:订单越复杂,备菜越久;Decode 像一道道出菜:每一步都要等上一道完成。厨房如果只追求一次做很多单,可能吞吐高但客人等第一道菜更久,这就是 TTFT 和吞吐的拉扯。
一、先建立推理服务系统的基本心智模型
1. 端到端时延分解
对自回归模型,一次请求总时延可粗略写成:
进一步地,若输出长度为 ,则 decode 阶段可近似展开为:
其中:
是排队等待 GPU 资源,受并发、调度和优先级影响; 是把输入上下文一次性编码进 KV cache,长上下文场景最容易变贵; 是逐 token 生成,输出越长越接近线性累积; 则是反序列化、过滤、工具编排等后处理,常被忽略但仍会进入端到端延迟。
一个直观例子:长文档问答
用户只问一句“总结这份 80 页 PDF 的关键风险”。
输出可能只有 200 token,但输入上下文很长。
此时最贵的往往不是 decode,而是 prefill,因为模型要先把整份文档过一遍并写入 KV cache。
2. Prefill 和 Decode 的计算特征完全不同
Prefill 的输入 token 可以一次性并行处理,大矩阵乘占主导,因此更容易吃满算力,也更依赖硬件 tile、dtype 和 GEMM kernel。Decode 则相反:每步只生成一个或少量 token,GPU 容易吃不满,还要反复读取 KV cache 和权重,所以更受显存带宽、cache 分配和调度策略影响。
这导致一个很重要的工程事实:
同一套优化不一定同时优化 prefill 和 decode。
例如:
大 batch prefill 通常能提高矩阵乘利用率、摊薄输入编码成本;但过大的 decode batch 可能让新请求等待更久,反而拉高首 token 延迟。
3. 吞吐与 QPS 的基础公式
若单机 token 生成能力为 token/s,平均每个请求输出 个 token,则理想吞吐上界近似为:
若把输入长度 也计入,可以写成更现实的资源消耗近似:
其中:
表示 prefill 单 token 成本,和输入长度、attention 实现、上下文组织强相关; 表示 decode 单 token 成本,和 KV cache 读写、batching、采样逻辑强相关。
在长上下文场景, 往往主导;在长回答场景, 更关键。
4. 推理服务系统最常见的瓶颈不是算力,而是调度
很多团队一开始以为“换更大的 GPU”就能解决问题,结果发现真正拖垮系统的是调度:短请求和超长请求混跑时资源占用完全不同,长上下文 prefill 会拖高短请求尾延迟,decode 小步运行容易造成 GPU 气泡,KV cache 分配和回收碎片化还会让显存容量被悄悄吃掉。
例子:企业知识库问答
白天高峰期会同时混入短闲聊、普通问答和文档总结:它们可能分别是几十 token、几千 token 和几万 token 的请求。若全部混在一个队列里,长请求会把短请求的 p95 延迟拖得很高。这时问题不再是“模型慢”,而是“调度策略错误”。
二、核心执行机制:批处理、并行与 KV Cache
5. Continuous Batching 为什么有效
传统静态 batch 的问题是:要等整批请求都准备好再一起跑。
而连续批处理允许在 decode 过程中动态插入新请求。粗略理解为,每个解码步在处理一个随时间变化的活动集合 :
其中:
是在时刻 完成的请求, 是在时刻 新加入的请求。
这样做的好处是 decode 过程中也能不断补入新请求,GPU 更少空转;短请求不必等待固定 batch 凑齐,也更容易插入活动批次,减少被长任务拖住的时间。
例子:文档问答服务
若不做 continuous batching,GPU 常会在一批请求 decode 完之前闲等下一批。
做了之后,新请求可在旧请求之间穿插进入,整体利用率会明显上升。
6. 并行策略:TP、PP、DP 各解决什么问题
6.1 Tensor Parallel
Tensor Parallel 把大矩阵切到多卡上:
它适合权重或激活超过单卡容量、必须把层内矩阵拆到多卡同时执行的场景。代价是每层都要通信,切分后的中间结果需要 all-reduce 或 gather;在小 batch decode 下,单步计算太少,通信延迟更难被掩盖。
6.2 Pipeline Parallel
把模型按层切成多段,形成流水线。
适合超大模型,但会引入 pipeline bubble。若流水线分为 段、微批数为 ,一个经典近似是:
微批越少,bubble 越严重。
这也是为什么 pipeline 在低并发在线服务里不总是理想。
6.3 Data Parallel
多副本各自处理请求:
它最容易扩展服务吞吐,但前提是单卡或单节点已经能装下模型。
7. KV Cache 才是大模型在线服务的“第二套权重”
在长上下文场景里,KV cache 可能比你想象中更贵。
粗略估算:
其中:
是层数, 是上下文长度, 是注意力头数或 KV 头数, 是每头维度, 是每个元素的字节数。长上下文会线性放大 KV 占用,GQA/MQA、FP8 或 KV 量化会改变这个估算。
前面的 2 表示 key 和 value 各一份。
一个例子:32k 上下文聊天
模型权重本身可能已经量化到能装进单机,但一旦几十个用户同时跑 32k context,KV cache 会迅速吃满显存。
这就是为什么很多推理服务系统表面上看是“推理”,实际上首先是在管理缓存。
8. 为什么请求分层和路由很重要
设请求特征为 ,模型池为 。
路由器可以做如下选择:
这意味着简单问答可以走小模型,长文档总结可以走大上下文模型,高价值请求可以走更高质量但更贵的路由。路由不是为了炫技,而是把质量、成本和延迟按业务价值分层。
例子:客服网关
“你好,在吗”这种请求没必要占用 70B 模型。
但“根据这 3 份合同和 2 份邮件,判断违约责任归属”显然不能走同一条链路。
9. 首 token 延迟和长尾延迟要分开看
很多系统只盯平均吞吐,忽视了用户真正感受到的是 TTFT、TPOT 和 P95 / P99 tail latency。TTFT 是用户看到第一段输出前等待多久,TPOT 是生成过程中每个 token 的平均间隔,P95 / P99 则反映最慢一批请求的体验,决定线上稳定性。
如果首 token 很慢,用户会觉得系统“卡住了”;
如果长尾很高,用户会随机遇到糟糕体验。
10. 四个真实部署场景
10.1 对话助手
对话助手最看重低 TTFT、中短回答稳定和高并发排队可控。用户要尽快看到第一段输出,常见聊天不应被少量长请求拖慢,高峰期也要限制队列膨胀和尾延迟。策略上通常优先 continuous batching,提高 decode 阶段利用率,同时减少固定 batch 等待;还要控制 prompt 长度,避免上下文随会话无节制增长;超长上下文最好异步或分层处理,把慢路径和普通对话路径隔离。
10.2 RAG 文档问答
RAG 文档问答的瓶颈常在 prefill。召回片段越长,进入模型前的上下文编码越贵;检索质量也会直接影响成本,低质量召回会把无关文本塞进 prompt,既慢又误导。更稳的做法是压缩召回片段,只保留回答所需证据;用 chunk rerank 把最相关证据排到前面;超长任务则拆成多轮总结,把一次超大 prefill 拆成可控的阶段任务。
10.3 Agent 工具调用
Agent 工具调用的请求数不一定大,但链路通常很长,一次任务可能包含多轮模型调用和工具调用。模型推理与工具等待交替出现,端到端延迟不仅来自 GPU,也来自外部服务。因此只加速模型不一定缩短整条 agent 任务,还要优化工具并发、缓存和中间状态复用,减少重复检索、重复 OCR 和重复上下文拼装。
10.4 多模态服务
多模态服务还要处理图像编码的额外开销。视觉前端会带来独立的计算和排队成本,文本 token 与视觉 token 混合后,上下文长度和 KV cache 预算要同时考虑两类 token。工程上最好区分视觉前端和语言后端资源池,避免图像编码把语言 decode 资源拖住;高分辨率图像也应分级处理,先低成本判断是否需要裁剪、放大或多区域读取。
11. 常见失败模式
11.1 Head-of-line blocking
一个超长请求堵在前面,后面一串短请求全被拖慢。解决思路通常是分队列、限流和最大上下文长度隔离:把短请求、长请求和后台任务拆到不同执行路径,防止少量超长或高成本请求挤垮普通流量,并让极长上下文走专门资源池或异步路径。
11.2 显存没爆,但性能突然崩
这常常是 KV cache 碎片、调度抖动、通信瓶颈或 CPU/GPU 数据搬运出了问题。
11.3 GPU 利用率很高,但用户仍然觉得慢
因为高 GPU utilization 不代表低用户时延。
系统可能只是把很多请求堆在一起“忙碌地慢”,而不是“高效地快”。
11.4 指标只看平均值
平均时延漂亮,但 P99 巨差,会在生产里持续伤害体验。
推理服务系统必须默认关注 tail latency。
12. 工程上的最小闭环
一个像样的推理服务系统,至少应该持续观测请求数、拒绝率、排队时长,TTFT、TPOT、P50/P95/P99,GPU 利用率、显存占用、KV cache 命中与回收,各长度区间请求分布,以及超时、OOM、工具失败、格式错误等错误类型分布。
没有这层观测,所有“优化”都很容易变成拍脑袋。
13. 核心判断
推理服务系统的核心,不是让模型跑起来,而是让它在真实流量下表现稳定。
真正决定体验的,往往不是某个 kernel 再快 8%,而是负载拆分、批处理策略、KV cache 管理和请求路由:系统是否区分 prefill 和 decode 两种完全不同的执行画像,是否用好了 continuous batching 而不是固定 batch 硬等,是否把 cache 当成一级资源而不是显存附属品,以及是否让不同长度、价值和任务类型的请求走不同服务路径。
如果把训练看作“造一台引擎”,那推理系统就是整辆车的变速箱、冷却系统和道路调度。
引擎再强,没有推理服务系统,最终也只会在实验室里跑得漂亮。
三、资源治理:把真实流量接住
在线推理服务首先是一个排队系统,而不是一次孤立的模型调用。更准确的抽象是:
很多“模型太慢”的问题,其实来自请求分布和调度策略:瞬时流量波峰会挤满队列,长请求会拖住短请求,某类高价值用户可能触发更昂贵的路由,KV cache 碎片也会让同样流量下的有效容量下降。因此优化前先看请求分布和排队形态,比直接盯单请求 benchmark 更可靠。
推理平台管理的资源也不只有 GPU 算力。GPU compute、显存与 KV cache、CPU 预处理、网络传输、检索/OCR/数据库/工具 API 配额都会进入关键路径。在 RAG 或 agent 场景里,外部依赖经常是隐形瓶颈:GPU 看起来不忙,模型日志也没报错,但用户体感仍然很慢。根因可能只是检索慢、OCR 慢、工具接口抖动,或者回退路径比主路径还慢。
成熟系统通常会显式区分 prefill 和 decode。Prefill 更像一次性吃下大段上下文的重计算节点,受 batch 合并、attention kernel 和 prefix 复用影响大;decode 更像高频、小步、持续调度的服务循环,受 KV 布局、continuous batching 和尾延迟抖动影响更大。长文档、PDF 问答和复杂 RAG 常常需要把 prefill-heavy 请求和普通对话 decode 隔离,否则一个巨长输入就会把短对话体验拖坏。
Admission control、分池、fallback 和多租户隔离应该被当成一等设计对象。准入控制不是简单“拒绝用户”,而是把不可控拥塞变成可控服务策略:简单请求及时返回,极长任务转异步,高价值流量优先,昂贵任务被明确限额。分池也不是越多越好,它会带来资源碎片和路由复杂度;但当短问答、长上下文、多模态、工具链和后台批任务混在一起时,完全不分池通常更危险。
观测系统要把“请求、模型、资源、业务”串起来。只看 GPU utilization 或 API 平均时延都不够;真正需要同时看到租户、任务类型、输入长度、附件、路由模型、量化版本、KV cache、外部依赖、任务完成率和用户反馈 proxy。否则一个优化可能在资源层看起来更快,却在业务层让工具调用失败率升高。
容量规划也不能围绕平均值。线上系统常常死于少量极端但昂贵的请求:长文档、图片附件、复杂 agent、多轮工具链和大模型升级请求一旦同时出现,就会把 queue、KV 和外部依赖一起推到极限。更稳的容量规划要围绕峰值流量、长度分布变化、最坏桶尾延迟和故障演练来做。
四、平台化设计:从单服务到可运营系统
把推理系统画清楚,最好从一次请求的生命周期入手:入口接入、请求归类、admission control、预处理、模型路由、prefill/decode、工具调用、后处理、观测记录。很多“模型慢”的抱怨,最后查出来其实是 tokenizer、OCR、路由、工具调用或 fallback 语义出了问题。生命周期链画不完整,团队就容易在错误位置优化。
平台化之后,几个判断尤其重要。请求是否已按长度、模态和价值分层;prefill 与 decode 是否被分别观测和治理;fallback 是否平时就有少量真实流量演练;失败域是否能定位到入口、路由、执行、缓存或外部依赖;trace 是否能一路贯通到业务指标。这些问题比“某个 kernel 又快了多少”更能决定系统能不能长期运营。
快速代码示例
1 | from fastapi import FastAPI |
这段代码展示了一个最小服务化形态:FastAPI 负责 HTTP 接口,vLLM 负责高吞吐生成,采样参数在请求入口统一配置。后续通常再加队列、鉴权、限流和观测指标接入,形成可运维服务。
小结
推理服务系统的核心,不是“让模型跑起来”,而是让请求、队列、缓存、模型、工具和降级策略共同组成一套稳定的生产机制。谁能把这些层串成一张有失败域、有回退、有容量边界的系统图,谁才能把模型能力真正稳定地交付给用户。
- Title: 推理:服务系统
- Author: Charles
- Created at : 2025-08-13 09:00:00
- Updated at : 2025-08-13 09:00:00
- Link: https://charles2530.github.io/2025/08/13/ai-files-inference-serving-systems/
- License: This work is licensed under CC BY-NC-SA 4.0.