Ray RLlib 架构精通指导
面向:已跑通 PPO/DQN、需要自定义模型与损失、改采样-学习流水线、做多智能体/离线 RL、压吞吐或迁移旧栈的工程师与研究员。
阅读建议:先读同目录《Ray RLlib 架构入门指导》,再按本文「问题驱动」深入。
依据:Ray 2.4x+新 API 栈(默认开启)官方文档与ray/rllib主线实现。
1. 精通目标:你要能回答的问题
- 新栈相对旧栈(Policy / RolloutWorker / SampleBatch)的职责切分与迁移映射是什么?
Algorithm.training_step如何编排 EnvRunnerGroup 与 LearnerGroup?权重以何种形态同步?RLModule三个 forward 与inference_only裁剪如何节省采样内存?- 三条 ConnectorV2 管线(env→module、module→env、Learner)各自何时运行、如何扩展?
Learner/LearnerGroup如何做 DDP?自定义算法要覆写哪些钩子?- 多智能体下
MultiRLModule、agent↔module 映射、共享编码器优化器陷阱在哪? - 离线 RL(Ray Data + OfflineData)与在线采样如何共用 Learner?
- 三条扩缩轴的瓶颈诊断与 APPO/IMPALA 异步高吞吐的适用边界?
若以上都能画图并落到配置/代码路径,即可视为「精通 RLlib 架构」。
2. 新 API 栈:设计精读
2.1 旧 → 新 映射表
| 旧 API 栈 | 新 API 栈 | 备注 |
|---|---|---|
Policy+ModelV2 | RLModule | 网络与三阶段 forward |
Policy内 loss / optimizer | Learner | 损失与优化从 Policy 剥离 |
RolloutWorker | EnvRunner(Single/Multi) | 更清晰的采样职责 |
SampleBatch/EpisodeV2/ ViewRequirement | SingleAgentEpisode/MultiAgentEpisode | 列式轨迹,省 next_obs |
Connector(旧) | ConnectorV2 | env↔module、Learner 管道 |
num_workers | num_env_runners | 命名对齐组件 |
关闭新栈(仅维护遗留代码时):
config.api_stack(enable_rl_module_and_learner=False,enable_env_runner_and_connector_v2=False,)精通立场:新功能与文档默认新栈;自定义与性能优化应落在 RLModule / Learner / ConnectorV2,而不是复活 Policy API。
2.2 分离采样与学习的软件动机
RL 控制流(Algorithm):决定「先采多少、何时更新、何时评估、如何同步」 │ ├─ 计算流 A:Env 步进 + 推理前向(EnvRunner,可水平扩) └─ 计算流 B:loss / backward / DDP(Learner,可水平扩)对比「全塞进一个 Worker」:
| 维度 | 采样与学习耦合 | 分离(RLlib 新栈) |
|---|---|---|
| 独立扩缩采样 vs 学习 | 难 | 三轴独立配置 |
| 换损失 / 换网络 | 易牵动采样路径 | Learner / RLModule 局部替换 |
| 异步高吞吐(IMPALA 系) | 特例代码多 | 同一 Actor 图上改编排 |
| 单卡调试 | 简单 | num_env_runners=0、num_learners=0可退回近单进程 |
RLlib 明确选择:用 Algorithm 薄编排层 + 可扩 Actor 组,换算法主要改 training_step 与 Learner,而不是重写分布式底座。
3. 执行模型深潜
3.1 Algorithm 持有的运行时对象
Algorithm ├── env_runner_group: EnvRunnerGroup │ ├── local EnvRunner(历史兼容;未来可能弱化) │ └── remote EnvRunner × n ← 并行采样 ├── eval_env_runner_group ← 可选,专用于评估 ├── learner_group: LearnerGroup │ └── Learner × m ← DDP 更新 └── offline_data: OfflineData ← 可选,离线路径纪律:不要直接拿底层 actor handle 乱调;经EnvRunnerGroup/LearnerGroup的 foreach / update / sync API,才能享受弹性与故障恢复。
3.2 同步 on-policy(以 PPO 为范型)
training_step / train iteration: episodes = env_runner_group.sample(...) # 或等价收集 results = learner_group.update(episodes=...) rl_module_state = learner_group.get_state( ..., inference_only=True) env_runner_group.sync_env_runner_states( rl_module_state=..., env_to_module=..., module_to_env=...)精通要点:
- 同步给 EnvRunner 的是inference_only状态:去掉仅训练需要的头(如部分 value 分支),省内存与传输。
- Connector 状态(归一化统计等)也可随
sync_env_runner_states对齐,避免「训练侧统计 ≠ 采样侧统计」。 - on-policy:采 → 学 → 同步强顺序;过期策略数据不能当新鲜 PPO batch 用。
3.3 高吞吐 / 异步系(APPO、IMPALA)
架构同构,编排不同:
- EnvRunner 持续产出,Learner 消费队列中的数据。
- 重要性采样 / V-trace 等修正离策略偏差。
- GPU 布局敏感:单卡时
num_learners=0 + gpuvsnum_learners=1 + cpu吞吐差异显著(见 Scaling Guide)。
精通者应能说明:异步换的是GPU 利用率与样本新鲜度的权衡,不是「免费加速」。
4. RLModule:网络与生命周期
4.1 三个 forward 的契约
| 方法 | 调用场景 | 典型行为 |
|---|---|---|
forward_exploration | 训练采样 | 带探索的动作分布采样 |
forward_inference | 评估 / 生产 | 更贪心或低随机 |
forward_train | Learner 更新 | 产出算 loss 所需张量(logits、values、Q…) |
自定义单智能体模块:通常继承TorchRLModule,在setup()建网,实现上述逻辑。
4.2 EnvRunner 侧 vs Learner 侧副本
EnvRunner: RLModule(inference_only=True) → 只要能出动作 Learner: RLModule(完整) → loss 所需一切 + 优化器状态在 LearnerRLModuleSpec(learner_only=True):仅学习侧需要的子模块(如某些自监督头)不部署到 EnvRunner。
4.3 MultiRLModule
- 默认实现 ≈
{ModuleID: RLModule}字典。 - 多智能体:
config.multi_agent(policies=..., policy_mapping_fn=...)映射到模块。 - 共享编码器陷阱:若两个 policy 模块共享 encoder,却用「每 module 一个 optimizer」的默认 Learner,会出现两个优化器轮流更新同一 encoder → 不稳定。精通做法:写多智能体 Learner,对共享参数只用一个优化器更新 encoder+heads。
4.4 自监督 / 辅助损失
实现SelfSupervisedLossAPI.compute_self_supervised_loss;Learner 在forward_train后自动调用。可挂在线 batch 或离线数据。常配合learner_only与额外 Learner Connector,保证辅助头吃到所需字段。
5. ConnectorV2:数据平面
5.1 三条管道
EnvRunner: Env ──► [env-to-module] ──► RLModule.forward_* ──► [module-to-env] ──► Env.step Learner: list[Episode] ──► [learner connector] ──► train batch ──► RLModule.forward_train| 管道 | 位置 | 职责示例 |
|---|---|---|
| env→module | EnvRunner | 观测预处理、frame stack、agent→module 映射、组 batch |
| module→env | EnvRunner | 分布 → 环境动作、动作裁剪、反归一化 |
| Learner | Learner | Episode → 列式 train batch、GAE/advantage 相关准备、设备搬运 |
5.2 扩展方式
在AlgorithmConfig中提供返回ConnectorV2或列表的工厂函数;默认会前置到内置管道(除非add_default_connectors_*=False全权自定义)。
旧栈迁移:
- Agent connector → env-to-module 片断
- Action connector → module-to-env 片断
on_postprocess_trajectory→ 不再触发;逻辑迁入 ConnectorV2
精通纪律:凡影响「模型看见什么 / 环境收到什么 / 训练 batch 长什么样」的变换,优先进 Connector,避免在 Env 与 Module 里各写一份不一致的预处理。
6. Learner 与 LearnerGroup
6.1 Learner 核心钩子
| 方法 | 用途 |
|---|---|
configure_optimizers_for_module() | 为某 ModuleID 注册优化器 |
compute_loss_for_module() | 计算可反传 loss |
before_gradient_based_update() | 梯度步之前的非梯度更新(如加噪) |
after_gradient_based_update() | 梯度步之后(如 Polyak、系数日程) |
算法差异主要落在loss;采样基础设施可复用。
6.2 LearnerGroup = DDP 协调器
num_learners=m:m 份同构 Learner,数据切分,梯度聚合。update(..., num_epochs=..., minibatch_size=..., shuffle_batch_per_epoch=...):PPO 式多 epoch / mini-batch。return_state=True:更新后顺带返回一份模块状态,避免额外get_weights往返(利于同步 EnvRunner)。- 异步
update:可与采样流水线重叠,适合高吞吐算法。
6.3 自定义算法的标准路径
- 定义 / 复用
RLModule(或 MultiRLModule) - 实现
Learner.compute_loss_for_module(及优化器配置) - 子类化
Algorithm,覆写training_step(采样量、是否从 OfflineData 取数、同步策略) - 提供
XxxConfig暴露超参 - 用
num_env_runners=0、num_learners=0单进程验算损失,再开分布式
7. Episode 数据模型精读
7.1 设计选择
- 列式 NumPy:跨 Ray 网络传输友好。
- 无 next_obs / 无重复 state_in:观测与 RNN 状态近半内存优化。
extra_model_outputs:保存采样时的 logits、logp、hid state,供 PPO ratio、RNN 续算。- 标准化列名见
rllib/core/columns.py。
7.2 与 batch 大小的关系
EnvRunner: 产出长度约 rollout_fragment_length 的 episode chunks Algorithm: 聚合到每个 Learner 恰好 train_batch_size_per_learner精通调参:
- 改语义 batch→
train_batch_size_per_learner、minibatch_size、num_epochs - 改采样切片粒度→
rollout_fragment_length、向量环境数 - 二者不对齐时会出现填充浪费或等待气泡
7.3 多智能体 Episode
MultiAgentEpisode记录各 agent 的异步步进关系。向量化多智能体环境仍是官方缺口之一(Scaling Guide outlook);大规模 MARL 需关注策略数量膨胀(未来可能对 MultiRLModule 分组切分)。
8. 扩缩与性能:精通级模型
8.1 三轴再审视
| 轴 | 增加时提升什么 | 何时失效 |
|---|---|---|
num_env_runners | 环境并行度 | 策略推理或权重同步成瓶颈;集群调度开销 |
num_envs_per_env_runner | 单 Actor 内 batch 推理 | 环境 GIL/同步步进;可试VectorizeMode.ASYNC |
num_learners | 学习吞吐 / 有效 batch | 模型需装进单卡(当前以 DDP 为主,非张量并行) |
8.2 资源放置直觉
config.env_runners(num_env_runners=8,num_cpus_per_env_runner=1,num_gpus_per_env_runner=0,# 多数仿真)config.learners(num_learners=4,num_gpus_per_learner=1,# 一卡一 Learner 最常见)- 小数 GPU(如
0.2)可把多个实验挤进一卡(注意争用)。 num_gpus_per_learner=0会强制 CPU 模块,即使集群有 GPU。- 当前限制:超大模型 / LLM-RLHF 所需的张量并行与快速跨 Actor 权重交换仍在演进;重度 LLM 后训练常看 verl 等专用栈,RLlib 擅长经典/中等规模深度 RL 与多智能体。
8.3 吞吐火焰图(逻辑阶段)
| 阶段 | 常见瓶颈 | 方向 |
|---|---|---|
| env.step | 仿真慢、同步向量化 | 加 EnvRunner、ASYNC vector、加速环境 |
| forward_exploration | 大模型 CPU 推理 | GPU EnvRunner、减小 inference 模块、批量化 |
| 权重 sync | 频繁全量同步、模块过大 | 降低 sync 频率(若算法允许)、inference_only、压缩 |
| learner update | batch 小、DDP 通信、过多 epoch | 调 batch/learners、混合精度、减 epoch |
| connector | Python 重预处理 | 向量化、移入模块或 C++/底层 |
9. 离线 RL 架构要点
新栈离线路径建立在Ray Data上:
- 默认读写 parquet;变换尽量在进 Learner之前流式完成,让 Learner 专注更新。
- 在线与离线可共用同一套 RLModule/Learner,差异在 Algorithm 的数据源(EnvRunner vs OfflineData)。
- 旧
SampleBatch录音:config.offline_data(input_read_sample_batches=True),或先转成SingleAgentEpisode。
精通点:离线质量(覆盖、分布偏移)往往比再堆一个 Learner 更关键;架构上先保证Episode schema 与 Connector 一致。
10. 与 Tune、检查点、回调
- Tune:
Algorithm是 Trainable;用 Tuner 管 stop、checkpoint、网格搜索。精通时区分「算法超参」与「资源/扩缩超参」。 - Checkpointable:LearnerGroup / RLModule 状态纳入 Algorithm 检查点;恢复后需能再次 sync 到 EnvRunner。
- Callbacks:新栈部分旧钩子消失(如
on_create_policy、on_postprocess_trajectory);环境创建若走 gymnasium VectorEnv,单 env-index 级钩子也受限。扩展优先 Connector 与自定义 EnvRunner/Learner。
11. 算法选型与架构映射(速查)
| 家族 | 代表 | 架构含义 |
|---|---|---|
| On-policy | PPO | 同步采-学-同步;多 epoch mini-batch |
| Off-policy | DQN、SAC | Replay;Learner 与采样解耦更强 |
| 高吞吐 | APPO、IMPALA | 异步队列 + off-policy 修正 |
| Model-based | DreamerV3 | RLModule 内世界模型;Learner 损失更复合 |
| Offline / IL | BC、CQL、IQL、MARWIL | OfflineData 为主;可无 EnvRunner |
扩展插件例:ICM 等好奇心 → 常以辅助模块 + 额外 loss 挂入。
12. 正确性雷区(精通版)
- 训练用 exploration 分布、评估却忘改 inference→ 指标虚高或虚低。
- Connector 只改了采样侧、Learner 侧未对齐→ 归一化/stack 不一致,静默损坏。
- PPO 使用过期策略数据却当 on-policy→ ratio 语义错误。
- MultiRLModule 共享参数 + 多优化器→ 训练震荡。
- 自定义 training_step 漏 sync / 漏 metrics→ 难诊断的「学了但不涨分」。
- 把 micro/向量环境数当算法语义旋钮乱扫→ 在实现正确时应主要影响吞吐,不应用它「调收敛」代替 lr/clip/gamma。
13. 配置与代码的「控制平面」
精通者应能从一份配置还原运行时拓扑:
config=(PPOConfig().environment(env="...",env_config={...}).env_runners(num_env_runners=...,num_envs_per_env_runner=...,num_cpus_per_env_runner=...,gym_env_vectorize_mode=...,# SYNC / ASYNC).learners(num_learners=...,num_gpus_per_learner=...,).training(train_batch_size_per_learner=...,lr=...,gamma=...,# PPO: clip_param, lambda_, use_gae, entropy_coeff, ...).rl_module(rl_module_spec=...,# 或默认 + model_config=# model_config=DefaultModelConfig(...),).evaluation(evaluation_num_env_runners=...,evaluation_interval=...,)# .offline_data(...) # 若离线# .multi_agent(...) # 若 MARL)代码阅读优先级:
algorithms/<algo>/<algo>.py的training_step- 对应
*Learner.compute_loss_for_module - 默认
RLModule与 Connector 构建处 EnvRunner.sample主循环
14. 精通学习路径(建议)
| 阶段 | 目标 |
|---|---|
| 1 | 对照源码走通一次 PPOtrain()(采样 → update → sync) |
| 2 | 写最小自定义TorchRLModule+ 复用 PPO Learner |
| 3 | 写自定义Learnerloss,保持 EnvRunner 不动 |
| 4 | 插入一条 env-to-module Connector,验证训练/评估一致性 |
| 5 | 多卡num_learners>1与故障注入(杀 EnvRunner)观察弹性 |
| 6 | 多智能体 MultiRLModule 或一条 OfflineData 训练链路 |
精通验收标准:
- 能默写新栈组件图与旧栈映射
- 能独立实现「新损失 + 新网络」而不改 EnvRunner 内核
- 能诊断采样瓶颈 vs 学习瓶颈 vs 同步瓶颈
- 能说明何时该用 PPO 同步栈 vs APPO/IMPALA 异步栈
- 能评估 RLlib 与 LLM-RL 专用框架(如 verl)的边界
15. 小结
RLlib 精通的主线是:
Algorithm 薄控制面 + EnvRunner/Learner 可独立扩缩的计算面 + RLModule/Episode/ConnectorV2 稳定协议;换算法优先换 Learner 与 training_step,换预处理优先换 Connector,换容量优先拧三轴。
入门心智见《Ray RLlib 架构入门指导》;二者对照阅读,可从「会跑」过渡到「会改、会扩、会排障」。
参考链接
- Key Concepts:https://docs.ray.io/en/latest/rllib/key-concepts.html
- Scaling Guide:https://docs.ray.io/en/latest/rllib/scaling-guide.html
- Learner:https://docs.ray.io/en/latest/rllib/rllib-learner.html
- RLModules:https://docs.ray.io/en/latest/rllib/rl-modules.html
- ConnectorV2 / env-to-module:https://docs.ray.io/en/latest/rllib/connector-v2.html
- Offline RL:https://docs.ray.io/en/latest/rllib/rllib-offline.html
- New API Stack 迁移:https://docs.ray.io/en/latest/rllib/new-api-stack-migration-guide.html
- 源码:https://github.com/ray-project/ray/tree/master/rllib