跳转到内容

训练与推理的系统差异

训练和推理跑在同样的硬件上、用同样的模型,但作为系统问题它们几乎没有共同点。一个是吞吐导向的批处理作业,另一个是延迟导向的在线服务。

这个分野在所有负载类型上都成立——大模型如此,推荐系统、视觉服务也如此。很多平台的失败源于试图用一套抽象同时服务两者。

维度训练推理
优化目标吞吐(samples/s、tokens/s)延迟 SLO 下的吞吐、$/请求
运行时长数小时到数月毫秒到秒
计算模式同步、批量、可预测异步、请求驱动、负载波动
主要状态权重 + 梯度 + 优化器状态权重 + 每请求中间状态
内存压力来源状态 × 分片容量 × 并发
通信集合通信密集少量点对点,或无
精度BF16 计算 + FP32 主权重可激进量化到 FP8 / INT8 / INT4
故障容忍可从检查点重来单请求失败即用户可见
扩缩容固定规模,作业期间不变随流量实时伸缩
失败代价浪费机时违反 SLO、丢用户

下面展开最重要的几条。

内存压力:两种完全不同的问题

Section titled “内存压力:两种完全不同的问题”

回顾第五章,混合精度 Adam 下每参数约需 16 字节。加上激活——激活随批量 × 序列长度增长,长上下文时常常超过参数本身。

训练的显存问题是:一个固定大小的巨大状态,怎么摊到很多卡上。 手段是分片与重计算,下一章给出具体做法。状态总量不随并发变化,因为训练没有"并发请求"这个概念。

推理只需要权重(可量化到 1 字节甚至更少)加上每请求的中间状态。但中间状态随并发数 × 上下文长度增长。

以大模型的 KV cache 为例:

KV cache=2×L×Hkv×dh×S×B×bytes\text{KV cache} = 2 \times L \times H_{kv} \times d_h \times S \times B \times \text{bytes}

(LL 层数,HkvH_{kv} KV 头数,dhd_h 头维度,SS 序列长,BB 并发数,乘 2 是 K 与 V 各一份。)

算一个具体的:80 层、8 个 KV 头、头维 128、BF16、单请求 8K 上下文:

2×80×8×128×8192×2 B≈2.7 GB2 \times 80 \times 8 \times 128 \times 8192 \times 2\ \text{B} \approx 2.7\ \text{GB}

每增加一个并发就多 2.7 GB。 一张 80 GB 的卡,放完 70B 模型的权重(BF16 约 140 GB,需要两张卡)之后,剩下的空间决定了能同时服务几个人。

这就是为什么推理侧的核心优化是:量化权重腾空间、量化 KV cache、分页管理消除碎片、前缀共享减少重复。

同样的逻辑:推荐推理的对应物是 embedding 表与热 ID 缓存,视觉服务的对应物是解码后的图像缓冲。推理的内存问题总是"容量 × 并发"。

分野不只在训练与推理之间。大模型推理内部:

Prefill / 编码Decode / 生成
计算特征大矩阵乘,算术强度高逐 token,算术强度 ~1
受限于算力显存带宽
影响的 SLOTTFTTPOT
批处理收益有限(本身接近打满)巨大(摊薄权重读取)
并行策略偏好张量并行更看重带宽与显存

两个阶段的差异大到值得部署在不同实例上——这就是 Prefill/Decode 分离。

这个模式是通用的,其他负载也有:

  • 推荐系统:召回(大规模检索,访存密集)与精排(小模型打分,延迟敏感)
  • 视觉服务:解码(CPU/专用单元)与推断(加速器)
  • 检索增强:向量检索与生成

识别出"一个服务内部有两类特征不同的阶段",几乎总能带来架构优化空间。 因为混在一起时,两类阶段会互相干扰,且只能按最坏情况配置资源。

把两个阶段放在同一个实例上,会发生什么?

一个长 prompt 的 prefill 可能占用几百毫秒的算力。在这期间,所有正在生成的请求都被卡住——它们的 TPOT 突然飙升。用户看到的现象是"输出突然卡顿一下"。

三种解法:

方案做法代价
Chunked prefill把长 prefill 切成小块,与 decode 交错执行TTFT 略升
优先级调度decode 优先,prefill 让路TTFT 波动大
P/D 分离两阶段部署在不同实例要传 KV cache,架构复杂

见连续批处理与调度。

这是最容易被低估的差异。

一个节点挂了,从检查点恢复,损失的是时间。衡量指标是 goodput(第七章)。

集群越大,平均无故障时间越短。万卡规模下故障可能以小时计,于是异步/分层检查点、热备节点、自动隔离坏节点从"优化项"变成"刚需"。

检查点频率有个经典权衡——存得太勤浪费时间,存得太稀故障后重算太多:

T浪费≈TckptTinterval⏟保存开销占比+Tinterval2⋅MTBF⏟平均重算损失T_{\text{浪费}} \approx \underbrace{\frac{T_{\text{ckpt}}}{T_{\text{interval}}}}_{\text{保存开销占比}} + \underbrace{\frac{T_{\text{interval}}}{2 \cdot \mathrm{MTBF}}}_{\text{平均重算损失}}

对 TintervalT_{\text{interval}} 求导并令其为零,得最优间隔:

Tinterval∗=2⋅Tckpt⋅MTBFT_{\text{interval}}^{*} = \sqrt{2 \cdot T_{\text{ckpt}} \cdot \mathrm{MTBF}}

代入:检查点耗时 2 分钟、MTBF 4 小时 → 最优间隔约 2×2×240≈31\sqrt{2 \times 2 \times 240} \approx 31 分钟。

一个请求失败,用户就看到错误。推理的容错是冗余实例、健康检查、优雅降级、限流熔断,衡量指标是可用性与 P99 延迟。

一个直接后果:训练可以用便宜的可抢占资源,在线推理不行。 这条差异直接影响成本结构——训练用抢占式实例能省一半以上,推理必须用按需或预留实例。

训练:作业启动时确定规模,中途不变。原因是并行策略(各维度的度数)与规模绑定,改规模意味着重新划分并行组、重新分片状态。弹性训练是活跃的研究方向,但生产上仍以固定规模为主。

推理:必须随流量实时伸缩。难点是冷启动——加载一个几十到上百 GB 的模型需要几十秒到几分钟,而流量峰值可能在几秒内到来。

常见对策:

对策说明
预留基线 + 弹性扩容基线覆盖日常流量,峰值靠弹性
模型常驻的备用池实例已加载模型但不接流量,秒级接管
按预测流量提前扩容用历史规律提前几分钟扩
分级降级峰值时切到更小的模型或更激进的量化

大厂常见做法是训练与推理共享集群,用调度填谷:白天流量高峰给推理,夜间空闲跑训练。收益明显,问题也明显:

  • 资源争用:训练作业的突发集合通信会打破推理的延迟 SLO。而集合通信恰恰是突发的(第六章)。
  • 隔离不足:容器不隔离显存带宽与卡间互连带宽,一个作业能拖慢邻居。硬件级切分(如 MIG)能隔离,但会切碎算力,训练一般不用。
  • 抢占代价:抢占训练作业要求它能快速检查点,否则损失巨大。

实践上多数团队的选择是:物理隔离核心在线集群,只在非核心场景混部。 见 Gang Scheduling、抢占与回填。

如果你在做……优先考虑
训练平台检查点速度、故障恢复时间、拓扑感知调度、goodput
推理平台批处理调度器、显存管理、自动扩缩容、冷启动、P99
两者都做不要用同一套抽象;至少把调度器与资源池分开

最后一条值得强调。训练与推理的:

  • 资源模型不同(整卡 gang vs 可分数扩缩)
  • 生命周期不同(一次性长作业 vs 常驻服务)
  • 失败语义不同(可重试 vs 用户可见)
  • SLO 定义不同(完成时间 vs 尾延迟)

硬统一的结果通常是两边都不好用。

  • 训练是吞吐导向的批作业,推理是延迟导向的在线服务,在十个维度上系统性不同。
  • 训练的内存问题是"状态 × 分片"(约 16 字节/参数),推理是"容量 × 并发"(KV cache 每并发数 GB)。
  • 分野在负载内部也存在:prefill/decode、召回/精排、解码/推断——识别出来通常有架构优化空间。
  • TTFT 与 TPOT 会互相干扰,三种解法:chunked prefill、优先级调度、P/D 分离。
  • 训练可重来(看 goodput,最优检查点间隔 2TckptMTBF\sqrt{2 T_{\text{ckpt}} \mathrm{MTBF}}),推理不能(看 P99 与可用性)。
  • 训练可用可抢占资源,在线推理不行;推理扩缩容的难点是冷启动。
  • 不要用同一套抽象服务两类负载——资源模型、生命周期、失败语义、SLO 全都不同。