第 19 讲 · 嘉宾讲座:LLM 后训练系统的新问题 · New Problems in LLM Post-training Systems

Advanced Topics in Machine Learning Systems (LLM Edition) · Lecture 19。个人学习讲义与配套实验,按主题整理并持续修订。

课程源码 ZIP ↓

个人整理的学习笔记,非官方讲义;课程来源与整理说明见课程介绍。配套示例未逐一运行验证。

本篇目录

对应 Maps to:CMU 15-779(Fall 2025,Zhihao Jia),Lecture 19 · Wed 11/12 · Guest Lecture: New Problems in LLM Post-training Systems,讲者 Banghua Zhu(UW / NVIDIA)。 依据说明:这一讲的 slides 和录像没有公开,课表也没有列必读论文。 能查到的讲者公开报告是 2024 年 4 月在 UW 的 Towards Principled Post-Training of Large Language Models,讲的是后训练的算法与数据(基于统计决策理论的 RLHF 算法、开放的 RLHF 数据集、Starling-7B、NexusRaven-13B),不是系统。所以本讲不是对这次讲座的转述,而是按题目”后训练系统的新问题”,根据公开的系统论文整理:

  • 主线:G. Sheng et al., HybridFlow: A Flexible and Efficient RLHF Framework(EuroSys 2025,开源实现 veRL);W. Fu et al., AReaL: A Large-Scale Asynchronous Reinforcement Learning System for Language Reasoning(NeurIPS 2025);
  • 参考:M. Noukhovitch et al., Asynchronous RLHF(ICLR 2025);DeepSpeed-Chat、OpenRLHF、NeMo-Aligner 的公开设计。

课上实际讲了什么、哪些问题是讲者自己的观点,请以讲者的公开材料为准。论文数字只做转述。

rlsys.py(生成 / 训练的时间模型、三种调度的事件驱动模拟器、权重重分片、放置搜索、陈旧数据上的 PPO 玩具)和全部实验都是本讲义自己设计的;时间来自 roofline 模型,回答长度是合成的,不是测量。 配套代码 Code:code/lecture19/(4 个脚本 + 一个共享模块;只需 numpy;最长的约 10 秒) 预计阅读时间:2.5 小时(含运行代码)


0. 本讲导航 · How to read this lecture

0.1 学习目标

学完这一讲,你应该能够:

  1. 说出 RL 后训练(RLHF、RLVR)的一次迭代里有哪些模型、哪些阶段,以及为什么它同时是推理负载和训练负载。
  2. 解释回答长度的长尾为什么让同步的 RL 大量空等,以及一步重叠、完全异步各自能挽回多少。
  3. 说明”陈旧度”从哪里来,为什么朴素地在陈旧数据上做 PPO 会变慢,解耦的 PPO 目标怎样修正。
  4. 计算训练、生成两种并行切分之间切换时的通信量和冗余显存,解释 HybridFlow 的分组方式为什么能做到零冗余。
  5. 比较”全部共置""两两分组""各自独立”三类模型放置,说明它们分别适合什么规模的集群。

0.2 先修与本讲范围

默认你已经会本讲只给直觉,后面再展开
第 16 讲:连续批处理、解码访存受限、KV 缓存RL 算法本身(PPO、GRPO、DPO 的推导)
第 14 讲:张量 / 流水线 / 数据并行、3D 并行奖励模型、验证器的训练与服务
第 13 讲:ZeRO、训练的显存账智能体(多轮、工具调用)的 RL(§6 简述)
第 18 讲:微调、LoRA(后训练的监督部分)第 20 讲的偏好优化(SimPO)

0.3 本讲地图

§1  RL 后训练的一次迭代:几个模型、几个阶段          ← 代码 01
§2  生成的长尾与调度:同步、重叠、异步               ← 代码 02
§3  陈旧数据:算法要跟着改                           ← 代码 03
§4  同一个模型,两种切分:训练 ↔ 生成的权重切换      ← 代码 04 演示 1–3
§5  模型放在哪里,以及怎样写这个程序                 ← 代码 04 演示 4
§6  把它们放在一起,以及更多的新问题
§7  论文精读:HybridFlow;AReaL
§8 小结  §9 常见误区  §10 练习  §11 延伸阅读  §12 下一讲预告

0.4 关于 rlsys.py

  • 时间模型:沿用第 16 讲的 roofline,换成 H100(3.35 TB/s,BF16 峰值;解码 60% 峰值,训练 MFU 40%),模型带 GQA 的 KV 大小。
  • 事件驱动的生成引擎:连续批处理,每个序列记录它的每一段 token 是哪个权重版本生成的;两次事件之间批的组成不变。
  • 三种调度:
    • sync:同一批卡先生成、再训练;
    • overlap:两组卡,生成第 k+1 批时训练第 k 批;
    • async:AReaL 式,连续生成、按 η 限流、权重更新时可选打断。
  • 权重重分片:把模型参数看成区间 [0, 1),按并行配置切分,精确计算每块卡要收多少、多存多少。
  • 玩具 RL 任务:表格型的”推理题”,只用来比较目标函数在陈旧数据上的行为。

1. RL 后训练的一次迭代 · Anatomy of an RL post-training step

1.1 从 SFT 到 RL

今天的 LLM 在预训练之后有一个后训练阶段:

  • 监督微调(SFT,第 18 讲):在高质量的指令—回答数据上做交叉熵训练;
  • 基于人类反馈的强化学习(RLHF,InstructGPT 的流程):先用人类的偏好对训练一个奖励模型,再用 RL(PPO)让策略最大化奖励,同时用 KL 惩罚不要离 SFT 模型太远;
  • 基于可验证奖励的强化学习(RLVR):数学题的答案对不对、代码能不能通过测试,奖励由规则或验证器给出,不需要奖励模型。推理模型(“思考”很长再回答)主要靠这一类训练。

和 SFT 最大的不同:训练数据是模型自己当场生成的。每一次迭代都要先让当前的策略回答一批问题,再用这批回答训练。

1.2 几个模型、三个阶段(代码 01 演示 1)

PPO 的数据流(HybridFlow 图 1):

模型是什么每次迭代做什么
actor(策略)要训练的 LLM生成回答;训练
reference(参考策略)SFT 模型的冻结副本给回答打 log 概率,算 KL 惩罚
critic(价值模型)和 actor 差不多大的 LLM估计每个位置的价值;训练
reward(奖励模型)从人类偏好训练出的 LLM给整条回答打分(RLVR 里换成验证器 / 规则)

三个阶段:

  1. 生成(rollout):actor 对一批提示自回归地生成回答——推理负载,访存受限;
  2. 准备:reference、critic、reward 对生成的序列各做一次前向——推理负载,输入完整、可以并行;
  3. 训练:算优势,更新 actor 和 critic——训练负载,计算受限。

GRPO 去掉了 critic(用同一个问题的一组回答的平均奖励当基线);RLVR 去掉了奖励模型。但无论哪种,同一个 actor 都要在”推理引擎”和”训练引擎”两种身份之间来回切换。

1.3 时间花在哪里(代码 01 演示 2–3)

7B 的四个模型共置在 16 块 H100 上,1024 条回答(中位数 968、平均 1274、截断在 4096):

阶段时间占比
生成25.6 s34%
准备(三个模型打分)14.7 s19%
训练(actor + critic)36.1 s47%

回答越长,生成越占大头:

回答长度中位数 / 上限256 / 1k1k / 4k4k / 16k8k / 32k
生成占比19%34%58%64%

HybridFlow 在它的设置下测到生成占 RLHF 时间的 58.9%;推理模型的 RL 里回答长达几万 token(AReaL 用 32k 上下文),生成的比例还会更高。

1.4 生成为什么慢:长尾(代码 01 演示 4)

单看每个 token 的代价,解码并不比训练贵多少:每块卡每秒训练约 8.7k 个 token,解码(每卡 64 条并发)约 9.3k 个。真正的问题是长尾:

  • 同样的 1024 条回答,长度有长尾时生成要 25.6 s;全部等于平均长度时只要 9.5 s(2.7 倍);
  • 有 31% 的生成时间里,只剩不到 10% 的序列还在跑——GPU 访存受限、批又小,利用率极低;
  • 同步的 RL 必须等这一批全部写完才能开始训练。
还在生成的序列数(满格 = 1024 条)随时间的变化:
|████▇▇▆▆▅▅▄▄▃▃▃▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|

2. 生成的长尾与调度 · Scheduling around the long tail

2.1 三种调度方式

方式做法陈旧度代表
同步(共置)同一批卡先生成、再训练,轮流进行0DeepSpeed-Chat、veRL 默认
一步重叠两组卡,生成第 k+1 批的同时训练第 k 批≤ 1多个系统的”one-step off-policy”
完全异步生成连续不断,训练凑够一批就训练有上限 ηAReaL

AReaL 的四个组件:

  • 可打断的生成 worker:收到”更新权重”请求时,打断正在进行的生成,丢掉旧权重算的 KV,用新权重重新算,再接着生成;
  • 奖励服务:例如执行代码、跑单元测试;
  • 训练 worker:从回放缓冲区里凑够一批就做 PPO 更新,每条数据只用一次;
  • rollout 控制器:在它们之间调度,并且按陈旧度上限限流:提交新的生成请求时要求 ⌊(N_r − 1)/B⌋ ≤ i + η(N_r 是已生成的轨迹数,B 是批大小,i 是当前策略的版本)。

2.2 能快多少(代码 02 演示 1)

1.5B 的模型,16 块 H100(异步时 12 块生成、4 块训练),每步 512 条轨迹,回答中位数 2000、截断在 16384:

调度吞吐(k token/s)相对同步平均陈旧度最大陈旧度生成忙训练忙
同步43.01.00×0094%6%
一步重叠43.41.01×0.88197%25%
异步 η = 035.60.83×0079%21%
异步 η = 1125.22.91×0.804100%73%
异步 η = 2150.23.49×1.476100%88%
异步 η = 4145.13.38×2.247100%85%
异步 η = ∞134.43.13×2.227100%78%

AReaL 论文的表(1.5B,32k 上下文):η = 0 / 1 / 2 / 4 / 8 / 16 / ∞ 时 128.7 / 269.3 / 356.6 / 356.6 / 371.7 / 382.4 / 396.8 k token/s;端到端训练时间比同步系统少 2.77 倍。

  • 同步:94% 的时间在生成,而且大部分时间被长尾拖着。
  • 一步重叠几乎没用:生成仍然按批等最长的那条,而生成本来就比训练慢得多。
  • 异步:η = 0 时退化成”同步但只用一部分卡生成”,比共置的同步还慢;η = 1、2 时吞吐跳到约 3 倍——生成引擎一直是满的,短回答写完马上补新的,长回答不再挡住别人。
  • η 再大:AReaL 的表里仍然略有上升;我们的模型里不升反降,因为在飞的长回答越来越多,每次更新都要重新预填充它们(§2.3)。
  • η 限制的是提交的速度,不是每个 token 的陈旧度:长尾的回答写得久,训练时最旧的 token 可能比 η 还旧(最大陈旧度那一列)。

2.3 打断还是不打断(代码 02 演示 2)

吞吐平均陈旧度
η = 2,打断150.21.47
η = 2,不打断158.71.61
η = ∞,打断134.42.22
η = ∞,不打断158.12.84

打断:后半段用新权重生成,陈旧度更低,代价是每次更新都要把所有在飞的上下文重新预填充(吞吐低 5%–15%)。不打断:在飞的序列用旧权重写完(实际系统里要同时留着两份权重,或者等它们写完),陈旧度更高。打断还带来一个算法问题:一条轨迹的不同段来自不同版本的策略(§3.3)。

2.4 分卡与长尾(代码 02 演示 3–4)

  • 生成和训练怎样分卡(η = 4):训练用 1 / 2 / 4 / 6 / 8 块卡时,相对同步 0.98 / 1.90 / 3.38 / 3.64 / 3.28 倍。训练的卡太少,训练成了瓶颈、数据堆着变旧;太多,训练的卡闲着。AReaL 的说法是”平衡生成和训练两边的负载来控制陈旧度”;这个比例还会随训练进行(回答越来越长)而变化。
  • 长尾越重收益越大:σ = 0.2 / 0.5 / 0.8 时异步加速 1.19 / 2.22 / 3.38 倍。σ = 1.1 时降到 2.68 倍,因为很多回答被截断在上限、而异步引擎里堆积的长回答更多。
  • 其他缓解长尾的办法(这里没有实现):
    • 过采样后丢掉最慢的几条(会让数据偏向短回答);
    • 把没写完的回答留到下一轮接着写(部分 rollout);
    • 按长度动态分配微批。

3. 陈旧数据:算法要跟着改 · Off-policy data and the algorithm

3.1 陈旧度从哪里来

异步调度下,训练第 i 步用的数据由第 i − s 版本的策略生成(s 是陈旧度)。这就是”在线但离策略”的 RL(Asynchronous RLHF 的说法):数据是当场生成的,但不是当前策略生成的。两个后果:

  • 分布偏移:旧策略的回答不代表当前策略会怎么回答;
  • 版本不一致:打断式生成让一条轨迹的前后两段来自不同版本。

3.2 朴素 PPO 为什么变慢(代码 03 演示 1–2)

PPO 的目标:

J(θ) = E[min(u·Â, clip(u, 1 − ε, 1 + ε)·Â)],u = π_θ(a|s) / π_old(a|s)

裁剪把每一步的更新限制在 π_old 附近的”信任区域”里。朴素地用陈旧数据时,π_old 就是生成数据的那个旧策略,而当前策略早就离开了那个区域:比率一开始就在裁剪区间外的样本,梯度直接是 0。

AReaL 的解耦目标(借鉴 Hilton et al. 的做法):把行为策略 π_behav(生成数据的策略)和近端策略 π_prox(信任区域的中心)分开:

J(θ) = E_{a∼π_behav}[ (π_prox / π_behav) · min(u^{prox}·Â, clip(u^{prox}, 1 − ε, 1 + ε)·Â) ],u^{prox} = π_θ / π_prox

π_prox 取”这一步开始更新前”的参数;π_prox / π_behav 是重要性权重,纠正分布的偏移。AReaL 的说法:用行为策略做中心,会把最新的策略拉回到旧的、质量更低的策略附近。

玩具任务(32 道题,每题 16 个候选答案,初始答对的概率 3.5%)上,学到期望奖励 0.8 要几步:

陈旧度 s0124816
朴素 PPO618087109152学不会
解耦目标615963617986
朴素 PPO 被裁成 0 的有信息样本0%6%13%25%38%44%

AReaL 论文表 2(1.5B,AIME24):朴素 PPO 在最大陈旧度 4 时就从 42.0 掉到 23.3;解耦目标到 8 都在 41 以上,到 ∞ 降到 36.9。方向一致:陈旧数据上必须换目标函数,而且陈旧度也不能无限大。

3.3 混合版本的轨迹(代码 03 演示 3)

AReaL 命题 1:一条由策略版本 θ, θ+1, …, θ+k 分段生成的序列,等价于从某一个行为策略 π_behav 采样。代码里的检验:前一个 token 用旧策略、后一个 token 用新策略,联合分布之和为 1;用生成时真实使用的逐 token 概率做重要性加权,估计精确(0.4908 = 0.4908);如果误以为整条都来自旧策略,估计完全失真。所以异步系统要把生成时的 log 概率和样本一起存下来。

3.4 墙钟时间:η 取多少(代码 03 演示 4)

把 02 号脚本的”每步多少秒”和玩具任务的”学会要几步”乘起来(每一步的陈旧度从模拟器测到的分布里抽):

调度秒 / 步朴素 PPO:学到 0.8解耦目标:学到 0.8
同步35.32152 s2152 s
异步 η = 111.4808 s739 s
异步 η = 29.6829 s617 s
异步 η = 410.3944 s698 s

朴素 PPO 在陈旧数据上要多走很多步,异步的收益被吃掉一部分;解耦目标基本保住了 3.5 倍。系统设计(异步、打断、限流)和算法设计(解耦目标)必须一起做。

Asynchronous RLHF(ICLR 2025)从另一个角度研究同一个问题:在 RLHF 的几种目标函数里,在线 DPO 对离策略的数据最鲁棒,而且模型越大越鲁棒;在 LLaMA 3.1 8B 的指令跟随任务上,异步训练比同步快约 40%,最终效果相同。


4. 同一个模型,两种切分 · Switching between training and generation

4.1 为什么要重新切分

  • 训练:计算受限、要存梯度和优化器状态,通常用大的张量并行 / 流水线并行(例如 7B 用 8 路张量并行);
  • 生成:访存受限,小的张量并行、多个副本吞吐更高(例如 7B 用 2 路张量并行、4 个副本)。

如果用同一种切分,生成的吞吐低(HybridFlow 指出 NeMo-Aligner 就是这样);如果用不同的切分,每次迭代都要在两种布局之间搬权重。

4.2 HybridFlow 的 3D-HybridEngine(代码 04 演示 1–2)

训练用 p-t-d(流水线 p 段、张量并行 t 份、数据并行 d 份),生成用 p_g-t_g-d_g,其中 micro-DP 的大小 d_g = p·t / (p_g·t_g):训练的每个数据并行副本,在生成时变成 d_g 个副本。

图 8 的例子(8 块卡,训练 1-4-2 → 生成 1-2-2-2):

卡训练时持有生成需要(连续编号)复用?生成需要(HybridFlow)复用?
G1[0, 1/4)[0, 1/2)是[0, 1/2)是
G2[1/4, 1/2)[1/2, 1)否[0, 1/2)是
G3[1/2, 3/4)[0, 1/2)否[1/2, 1)是
G4[3/4, 1)[1/2, 1)是[1/2, 1)是
  • 连续编号(生成的张量并行组 [G1,G2]、[G3,G4]…):G2、G3 的训练分片和生成分片不相交,既要收整整一半的模型,又得把训练分片另外存着(下一次训练还要用)——这就是冗余显存。
  • HybridFlow 的分组(生成的张量并行组按间隔选 [G1,G3]、[G2,G4]…,micro-DP 组连续 [G1,G2]、[G3,G4]…):每块卡生成时需要的区间包含它训练时持有的区间,训练分片直接复用,只在 micro-DP 组里收缺的那 1/4。

表 2(以模型大小 M 为单位):

实现通信量峰值显存冗余显存
DeepSpeed-Chat(全部 all-gather)(tpd − 1)/(tpd)·MMM/(tpd)
HybridFlow-V(模型并行组内 all-gather)(tp − 1)/(tp)·MMM/(tp)
HybridFlow(tp − t_g p_g)/(t_g p_g t p)·MM/(t_g p_g)0

代码按区间精确计算,四组配置都和公式一致;生成时 p_g·t_g = 1(每块卡一个完整副本)的那一组,理想情况下没有冗余(表里的冗余是上界)。70B 的 actor、32 块卡、训练 2-8-2 → 生成 1-4:HybridFlow 每卡只收 26 GB、峰值 35 GB;另外两种要收齐 140 GB。

4.3 分开部署时的代价(代码 04 演示 3)

如果训练和生成在不同的卡上(OpenRLHF 的做法),每次迭代要把整个模型从训练端传到生成端:70B 是 140 GB,有效带宽 25 GB/s 时 5.6 s。HybridFlow 引用 OpenRLHF 的数字:最多占迭代时间的 36.4%。好处是两边各用最合适的并行方式、还能同时运行(§2 的异步就需要这样)。共置省掉了传输,但两种负载不能同时跑;分开能同时跑,但要传权重——这是 §2 和 §4 之间的取舍。


5. 模型放在哪里,以及怎样写这个程序 · Placement and programming model

5.1 放置(代码 04 演示 4)

四个模型的分组方式一共 15 种(集合划分,贝尔数 B₄ = 15),从”全部共置在同一组卡上、按时间分片轮流用”(DeepSpeed-Chat)到”各自独立”(OpenRLHF),中间有 NeMo-Aligner 的”actor + ref | critic + reward”。HybridFlow 的自动映射(算法 1)枚举放置方式和每组的卡数,用模拟器估计每种的迭代时间,取最快的。

我们的简化代价模型(工作量 / 卡数 + 固定的梯度同步时间 + 生成的长尾下限):

场景卡数最快的放置全部共置两两分组各自独立
全是 7B16两两分组 66.5 s68.166.5158.1
128两两分组 33.4 s38.333.435.3
13B actor + 70B critic / reward32全部共置 192.9 s192.9203.5291.1
128actor+ref | critic+reward(16, 112)109.1 s118.0109.1123.7

HybridFlow §8.3 的三条经验:

  1. 多给 actor 分卡能减少生成的延迟,而生成不能和其他模型并行;
  2. 每个模型的计算都能把 GPU 用满时,小集群上全部共置最好(论文里 16–64 块卡);
  3. 集群变大(强扩展)后,批大小固定、每块卡分到的计算变少,通信占比上升,共置不再线性扩展;把 actor 和 critic 放在不同的卡上、在训练和准备阶段并行执行更好。

我们的模型复现了第 3 条的方向(卡越多,分组的优势越大),但转折点比论文早(全是 7B 时 16 块卡就略优于共置)。“各自独立”在小集群上很差:生成阶段只有 actor 那组卡在干活。

5.2 编程模型:单控制器 + 多控制器

HybridFlow 的另一半贡献是编程模型:

  • 单控制器(single-controller):一个中心进程按数据流图调度各个模型的执行、协调模型之间的数据传输——灵活,容易写出 PPO、ReMax、Safe-RLHF 等不同的算法(论文图 6:在 PPO 的基础上加减几行代码);但如果用它去指挥每块卡上的每个算子,调度开销太大。
  • 多控制器(multi-controller):每块卡一个进程,各自执行同一个程序(SPMD,Megatron、vLLM 都是这样)——高效,但要在一份代码里同时写计算、集合通信、模型之间的点对点传输,难以修改。
  • 混合:模型之间用单控制器,模型内部用多控制器;用层次化的 API 封装”一个分布式模型”和”模型之间的数据重分布”(例如按数据并行分发、收集)。

6. 把它们放在一起,以及更多的新问题 · Putting it together

RL 后训练系统的设计空间:

维度选项取舍
调度同步 / 一步重叠 / 完全异步吞吐 vs 陈旧度(算法要配合)
生成的权重更新打断 / 不打断陈旧度 vs 重新预填充的开销、多一份权重
训练和生成的部署共置(轮流)/ 分开免传权重、不能同时跑 vs 能同时跑、要传权重
并行切分两种切分之间重分片通信量、峰值显存、冗余(HybridFlow 的分组)
放置全部共置 / 分组 / 独立小集群用满 GPU vs 大集群并行执行

公开文献和开源系统里正在出现的其他问题(这里只列出,不展开):

  • 奖励 / 验证器的服务:RLVR 的验证器可能要执行代码、跑测试、调用外部工具,延迟长、资源需求不同(AReaL 有独立的奖励服务);
  • 智能体的 RL:多轮交互、工具调用让一条轨迹在”生成”和”等待环境”之间来回切换,长尾更长;
  • 推理引擎与训练引擎的数值不一致:两边用不同的 kernel、精度,算出的 log 概率不完全相同;离策略的修正到底用哪一边的概率,会影响训练的稳定性;
  • 训练越来越长的回答:回答长度随训练增长,生成 / 训练的最优分卡比例随之变化(§2.4)。

7. 论文精读 · Paper reading

7.1 HybridFlow: A Flexible and Efficient RLHF Framework(Sheng et al., EuroSys 2025)

1. 问题:RLHF 是一个数据流:每个节点是一个分布式的 LLM 训练或生成程序,每条边是模型之间多对多的数据重分布。怎样既灵活(容易实现各种 RLHF 算法、各种放置)又高效地执行它?

2. 为什么重要又困难:

  • 模型的负载各不相同:actor 生成访存受限、训练计算受限;critic、reward 可能比 actor 大得多;
  • actor 在训练和生成之间要用不同的并行方式,重分片的通信和显存开销很大(70B 的 actor 每次迭代要搬 140 GB);
  • 放置方式影响很大:共置时阶段之间串行、负载不均;分开时一部分卡闲着;
  • 传统 RL 框架的单控制器调度大规模分布式计算时开销太大。

3. 以前的工作为什么不行:

  • DeepSpeed-Chat、OpenRLHF、NeMo-Aligner 都用多控制器:计算、集合通信、模型间传输混在一份代码里,换一种算法或放置要大改;只支持 PPO、并行方式有限;
  • 各自只支持一种放置方式(全部共置 / 各自独立 / 两两分组);
  • DeepSpeed-Chat 的重分片要在所有卡上 all-gather,OpenRLHF 存两份 actor 权重并频繁同步,NeMo-Aligner 训练和生成用同一种并行,生成吞吐低。

4. 新意:

  • 混合编程模型:模型之间单控制器(灵活编排数据流),模型内部多控制器(高效执行);层次化的 API 封装分布式模型和数据重分布;
  • 3D-HybridEngine:同一组卡上训练和生成用不同的 3D 并行,通过新的分组方式做到重分片零冗余、通信最少;
  • 自动设备映射:枚举放置方式和卡数分配,配合每个模型的并行策略搜索和模拟器,找出迭代时间最短的映射。

5. 结果:

  • 16 台机器 128 块 A100-80GB 上,PPO、ReMax、Safe-RLHF 三种算法;
  • 吞吐比 DeepSpeed-Chat、OpenRLHF、NeMo-Aligner 高 1.53–20.57 倍(PPO 7B 上 1.68–8.63 倍、13B 上 2.70–18.96 倍);
  • 最优放置随规模变化:16–64 块卡共置最好,96–128 块卡分组或独立更好;
  • 重分片的开销显著降低,生成阶段约占 RLHF 时间的 58.9%。

本讲的验证:

  • 用区间计算复现了表 2 的通信量、峰值、冗余(图 8 的例子逐卡对照);
  • 用简化的代价模型复现了”规模越大,分组越有利”的方向。
  • 额外的发现:生成用完整副本时公式里的冗余是上界;我们的模型里转折点比论文早。

局限:

  • 面向同步的 RLHF:生成和训练仍然在同一组卡上轮流进行,生成的长尾没有解决(这正是 AReaL 的出发点);
  • 自动映射依赖模拟器的准确度和枚举的规模;
  • 共置模型时间分片共享 GPU,同一组卡上的模型不能同时运行。

7.2 AReaL: A Large-Scale Asynchronous Reinforcement Learning System for Language Reasoning(Fu et al., NeurIPS 2025)

1. 问题:推理模型的 RL 训练里,回答长达几万 token、长度差异极大。同步系统(生成完一批再训练)里,生成要等最长的那条,GPU 大量空闲;而且同步系统把生成分散到所有卡上,每块卡的解码批变小,进一步落入访存受限的区间,加卡也不能提高吞吐。

2. 为什么重要又困难:

  • RL 是推理模型能力的主要来源,训练要上千条长回答一批、跑很多步,系统效率直接决定成本;
  • 完全异步就意味着用旧策略的数据训练新策略,算法上的分布偏移会让训练变差;
  • 打断正在生成的序列换上新权重,会让一条轨迹混合多个策略版本,违反了 PPO “所有动作来自同一个旧策略”的前提。

3. 以前的工作为什么不行:

  • 同步系统(veRL 等)在长回答时利用率低、扩展性差;
  • “一步重叠”仍然按批生成,长尾还在;
  • 已有的异步 RL(游戏、RLHF)没有处理超长、长度不一的生成和打断带来的版本混合。

4. 新意:

  • 系统:完全解耦生成和训练;可打断的 rollout worker(权重更新时丢掉 KV、用新权重重算再继续);独立的奖励服务;rollout 控制器按陈旧度上限 η 限流;训练端优先用最旧的数据、每条只用一次;另有动态微批分配等优化;
  • 算法:解耦的 PPO 目标——行为策略和近端策略分开,近端策略取每次更新前的参数;证明混合版本的轨迹等价于一个合法的行为策略(命题 1)。

5. 结果:

  • 数学和代码推理任务上,模型最大到 32B;
  • 训练速度最多比同步系统快 2.77 倍,最终效果相当或更好;
  • 吞吐随 η 增加(128.7 → 396.8 k token/s),强扩展接近线性;
  • 消融:没有解耦目标时,稍有陈旧效果就明显下降;有解耦目标时 η ≤ 8 和同步相当,η → ∞ 仍然变差。

本讲的验证:

  • 事件驱动的模拟器复现了”η 从 0 到 2 吞吐大幅上升”(约 3.5 倍于同步);
  • 打断降低陈旧度、代价是重新预填充;
  • 玩具任务复现了朴素 PPO 随陈旧度变慢、解耦目标基本不受影响,并用裁剪比例解释了原因;
  • 混合版本的重要性加权在精确计算下无偏。
  • 和论文不同的地方:我们的模型里 η > 2 之后吞吐略降(打断时要重算的在飞上下文更多)。

局限:

  • 需要调 η 和生成 / 训练的分卡比例,最优值随回答长度变化;
  • 解耦目标需要额外计算近端策略的 log 概率;
  • 陈旧度无限大时效果仍然下降,异步不是免费的;
  • 实验集中在可验证奖励的推理任务上。

7.3 两篇论文之间的联系

  • 两条互补的路线:HybridFlow 优化的是”同步 RL 里每个阶段怎样执行得更快”(重分片、放置、编程模型);AReaL 质疑”为什么要同步”,把生成和训练彻底解耦。HybridFlow 的共置让训练和生成轮流用同一组卡,AReaL 恰恰要把它们分开、让它们同时跑——前者省掉了权重传输,后者省掉了等待。
  • 都从”生成占大头”出发:HybridFlow 测到生成占 58.9%,AReaL 指出推理模型的长回答让问题更严重。
  • 系统和算法的边界变模糊了:AReaL 的系统设计(异步、打断)直接改变了训练数据的分布,必须配合算法修改(解耦目标)。这和第 15、17 讲”系统优化要保证结果不变”不同——在 RL 里,系统可以有意地改变数据,只要算法能接受。
  • 一个可以讨论的问题:未来的 RL 系统可能同时需要两者——用 HybridFlow 式的数据流编程和自动映射来管理越来越复杂的多模型、多阶段流程,用 AReaL 式的异步来应对长尾。

8. 小结 · Summary

  1. RL 后训练 = 推理 + 训练:一次迭代要先生成、再打分、再训练;同一个 actor 在两种身份之间切换。
  2. 生成占大头,长尾是主因:回答越长生成越占时间(19% → 64%);同样的回答,长度有长尾时生成慢 2.7 倍。
  3. 调度:同步要等最长的那条;一步重叠几乎没用;完全异步(AReaL)让生成引擎一直满载,吞吐约 3 倍于同步,代价是陈旧的数据。
  4. 算法要配合:朴素 PPO 在陈旧数据上被裁剪卡住;解耦目标把信任区域的中心换成当前策略,基本保住了异步的收益;混合版本的轨迹要记录逐 token 的行为概率。
  5. 两种切分:训练要大的模型并行、生成要多副本;HybridFlow 的分组让重分片零冗余、通信最少;分开部署则每次都要传整个模型。
  6. 放置:小集群全部共置用满 GPU;大集群上分组让不同模型在同一阶段并行。

9. 常见误区 · Common misconceptions

  • “RL 训练的瓶颈是训练。” 在长回答的设置下,大部分时间在生成(代码 01:中位数 8k 时 64%),而且是被少数最长的回答拖着。
  • “生成慢是因为解码比训练贵。” 单个 token 的代价是同一个量级(每卡每秒约 9k vs 8.7k);慢在长尾——大部分时间 GPU 上只剩几条序列。
  • “把生成和训练重叠起来就解决了。” 一步重叠仍然按批等最长的那条(代码 02:1.01 倍);要连续生成、谁写完补谁,才能填满长尾留下的空闲。
  • “异步的陈旧度不超过 η。” η 限制的是提交新请求的速度;长尾的回答写得久,最旧的 token 可能比 η 还旧(代码 02:η = 1 时最大陈旧度 4)。
  • “陈旧数据直接用 PPO 训练就行,裁剪会兜底。” 正是裁剪的问题:信任区域的中心是旧策略,大量样本一开始就被裁成 0,训练变慢甚至停滞(代码 03:s = 8 时 38% 的样本没有梯度)。
  • “训练和生成用同一种并行切分最省事。” 省掉了重分片,但生成的吞吐低;换切分时如果分组不当,还会多存一份冗余的权重(HybridFlow 表 2)。
  • “全部共置总是最好。” 小集群上通常是;集群变大后,批大小固定、通信占比上升,分组让模型并行执行更好(HybridFlow §8.3)。

10. 练习 · Exercises(含参考答案)

练习 1 一批 100 条回答:99 条长 100 个 token,1 条长 1000 个 token。假设每一步解码的时间都一样,同步生成这一批要多少步?GPU 槽位的利用率是多少?如果长回答可以不等(异步),每一步平均完成多少有用的工作?

答案:

  • 同步要 1000 步(等最长的那条);
  • 槽位利用率 = (99 × 100 + 1000) / (100 × 1000) = 10.9%;
  • 异步时,短回答写完马上补新的提示,100 个槽位一直是满的,每一步都在做 100 个 token 的有用工作——利用率接近 100%,代价是那条长回答训练时已经陈旧了。

练习 2 批大小 B = 512、η = 2、当前策略版本 i = 5(已完成 5 个训练步)。按 AReaL 的限流规则 ⌊(N_r − 1)/B⌋ ≤ i + η,最多能提交到第几条轨迹?

答案:⌊(N_r − 1)/512⌋ ≤ 7 → N_r − 1 ≤ 4095 → N_r ≤ 4096。也就是说,第 8 批(第 3585–4096 条)可以提交,第 9 批要等第 6 个训练步完成。

练习 3 某个回答 a 的优势 Â > 0。生成它的旧策略 π_behav(a) = 0.10;训练开始时当前策略已经变成 π(a) = 0.20。ε = 0.2。分别算朴素 PPO 和解耦目标下这个样本的梯度是否为 0。

答案:

  • 朴素:比率 u = 0.20 / 0.10 = 2 > 1 + ε = 1.2,且 Â > 0,min(u·Â, 1.2·Â) 取被裁剪的那一项,对 θ 的梯度为 0——这个”好”样本白白浪费了。
  • 解耦:π_prox = 0.20(这一步开始时的策略),u^{prox} = 1,在裁剪区间内,梯度不为 0;乘上重要性权重 π_prox / π_behav = 2,纠正”这个回答在旧策略下被采到得太少”的偏差。

练习 4 为什么打断式生成要把每个 token 生成时的 log 概率和样本一起存下来?只存”这条轨迹是第几版开始生成的”会怎样?

答案:

  • 打断后,轨迹的后半段由新版本生成,真实的行为概率是”每个 token 用当时版本的概率”的乘积(AReaL 命题 1)。
  • 只知道起始版本时,训练端会用旧版本的概率当后半段的行为概率,重要性权重就错了。代码 03 演示 3 里,这种错误的估计完全失真(真值 0.49,错误的估计 200 多)。

练习 5 actor 训练用 p = 1、t = 8、d = 1(8 块卡),生成改用 t_g = 2(p_g = 1,micro-DP d_g = 4)。按 HybridFlow 的分组,每块卡要收多少参数?峰值显存多少?70B 的模型(M = 140 GB)是多少 GB?连续编号的分组呢?

答案:

  • HybridFlow:通信 (8 − 2)/(2 × 8) = 3/8 M = 52.5 GB;峰值 M/2 = 70 GB;冗余 0。
  • 连续编号(HybridFlow-V):先在 8 块卡上 all-gather 整个模型,通信 7/8 M = 122.5 GB,峰值 M = 140 GB,冗余 1/8 M = 17.5 GB——峰值已经超过一块 80 GB 的卡,实际只能逐层地做。

练习 6 训练和生成放在不同的卡上,每次迭代要传 70B 的权重(140 GB),有效带宽 50 GB/s。如果迭代的其余部分要 20 s,传权重占多少?怎样减少这个开销?

答案:

  • 140 / 50 = 2.8 s,占 2.8 / 22.8 = 12%。
  • 办法:
    • 用更快的互连,或多条链路并行;
    • 和下一批的生成重叠(异步时生成端先用旧权重继续);
    • 只传变化的部分(例如 LoRA 时只传几十 MB 的增量);
    • 把训练和生成共置,改成卡内重分片(§4.2)。

练习 7 为什么四个模型的放置方式有 15 种?“全部共置”在什么情况下最好、什么情况下不好?

答案:

  • 把 4 个模型分成若干组(组内共置),就是集合 {actor, critic, ref, reward} 的划分,个数是贝尔数 B₄ = 15。
  • 全部共置的好处:每个阶段都能用上所有 GPU(生成阶段所有卡一起生成,训练阶段所有卡一起训练)。小集群上每个模型的计算都能把卡用满,共置最好。
  • 不好的情况:集群很大、批大小固定时,每块卡分到的计算太少,梯度同步等固定开销占比上升,扩展效率下降;这时把 actor 和 critic 分开,让它们在训练和准备阶段并行执行,等于把固定开销并行掉了一份(代码 04:128 块卡时分组快约 13%)。

练习 8 (开放)你要为”智能体 RL”设计训练系统:每条轨迹是多轮的,模型每说一句话就要调用一次工具(搜索、执行代码),工具的延迟从 0.1 秒到 30 秒不等。§2 的哪些思想还适用?会出现什么新问题?

参考思路:

  • 长尾更严重了:轨迹的时长不仅取决于生成长度,还取决于工具延迟。连续生成、异步训练的思想更加重要;
  • 生成引擎在等工具时 GPU 空闲,可以把等待中的轨迹的 KV 换出、先服务别的轨迹(类似第 16 讲的抢占),或者让一个引擎同时跑更多的轨迹;
  • 陈旧度更难控制:一条轨迹可能跨越很多个训练步,打断 / 不打断的取舍更尖锐;
  • 环境本身也是一个需要扩展的服务(沙箱、并发限制、失败重试),奖励的计算可能很贵;
  • 重要性加权要覆盖”多轮、每轮的版本不同”的情况,同样要记录逐 token 的行为概率。

11. 延伸阅读 · Further reading

  • L. Ouyang et al., Training Language Models to Follow Instructions with Human Feedback(NeurIPS 2022)——InstructGPT,RLHF 的标准流程。
  • J. Schulman et al., Proximal Policy Optimization Algorithms(2017);Z. Shao et al., DeepSeekMath(2024)——GRPO。
  • M. Noukhovitch et al., Asynchronous RLHF: Faster and More Efficient Off-Policy RL for Language Models(ICLR 2025)。
  • J. Hu et al., OpenRLHF: An Easy-to-use, Scalable and High-performance RLHF Framework(2024);Z. Yao et al., DeepSpeed-Chat(2023)。
  • J. Hilton, K. Cobbe, J. Schulman, Batch Size-Invariance for Policy Optimization(NeurIPS 2022)——解耦 PPO 目标的出处。
  • B. Zhu, E. Frick, T. Wu, H. Zhu, J. Jiao, Starling-7B: Improving LLM Helpfulness & Harmlessness with RLAIF(项目报告,2023 年 11 月)——讲者在后训练数据(Nectar 排序数据集)与算法方面的工作之一。

12. 下一讲预告 · Next lecture

第 20 讲是另一场嘉宾讲座《推进开放语言模型训练的帕累托前沿》(Mengzhou Xia)。slides 同样没有公开;讲者在 Princeton 的博士答辩报告(同名)摘要提到三个方向,讲义按她的公开论文整理:

  • 结构化剪枝:从一个大模型剪出小模型再继续训练,只用从头训练约 3% 的算力(Sheared-LLaMA);
  • 数据选择:用梯度相似度挑出 5% 的指令数据,效果可以超过用全部数据(LESS);
  • 新的后训练方法:不需要参考模型的偏好优化(SimPO)。

共同的主题是:在固定的算力、数据、模型预算下,怎样得到更好的模型——把”质量—成本”的帕累托前沿往外推。

← 返回课程目录