三种部署模式:colocated / hybrid / fully distributed
RLHF 训练里有 4 个训练角色 + 1 个采样引擎,共 5 类进程。同样的硬件可以让它们 怎么放在 GPU 上,决定显存峰值与吞吐。OpenRLHF 通过几个简单的开关, 覆盖从"挤在 8 卡上"到"5 类独立占卡"的整个谱系。这一章把三种部署模式讲透。
8.1三种模式速览
| 模式 | 所有角色共享 GPU? | 典型场景 | 关键 flag |
|---|---|---|---|
| fully colocated | 全共享 | 单机 8 卡训练 ≤ 32B | --train.colocate_all |
| partially hybrid | 部分共享 | 显存吃紧 / 模型偏大 | --train.colocate_actor_ref 等组合 |
| fully distributed | 完全隔离 | 多节点 70B+ 训练 | 所有 colocate 都关 |
8.2模式 A:fully colocated(最省卡)
train_ppo_ray_hybrid_engine.sh 是这种模式的范例。所有 5 类进程共享同一组 GPU,靠 sleep mode 分时复用:
启动参数
--ref.num_gpus_per_node 8 # ref 占 8 卡
--reward.num_gpus_per_node 8 # reward 占 8 卡
--critic.num_gpus_per_node 8 # critic 占 8 卡
--actor.num_gpus_per_node 8 # actor 占 8 卡
--vllm.num_engines 4 --vllm.tensor_parallel_size 2 # vllm 占 8 卡
--train.colocate_all # ★ 让 Ray 把它们都放同一组 placement group
--vllm.enable_sleep --ds.enable_sleep
--vllm.gpu_memory_utilization 0.5
调度的关键
- 所有角色用同一个 placement group(8 张卡);
- rollout 阶段:vLLM wake_up,训练 actor offload 到 CPU;
- 训练阶段:vLLM sleep(KV cache 释放),训练 actor reload 回 GPU;
- 同时 ref / reward 只有 forward,不占 optimizer 显存。
显存峰值估算(7B 模型)
| 组件 | 每卡占用(ZeRO-3, bf16) |
|---|---|
| Actor bf16 + grad | ~2 GB |
| Actor Adam states (ZeRO-3) | ~12 GB / 8 = 1.5 GB |
| Critic 同上 | ~3.5 GB |
| Reference (no optim) | ~2 GB |
| Reward (no optim) | ~2 GB |
| vLLM (sleep 时释放) | 峰值 ~14 GB(不与训练同存) |
| 激活(gradient ckpt) | ~5 GB |
| 峰值(rollout 阶段) | ~20 GB(A100 80G 充分够用) |
8.3模式 B:partially hybrid
当 colocate_all 装不下时(70B+),把某些角色组合共置:
| 组合 | 含义 | flag |
|---|---|---|
| colocate_actor_ref | actor + reference 同卡(最常见) | --train.colocate_actor_ref |
| colocate_critic_reward | critic + reward 同卡 | --train.colocate_critic_reward |
| colocate_actor_vllm | actor + vllm 同卡(hybrid engine 经典) | (默认开 vLLM 与 actor 共享 PG) |
典型组合 1:actor+ref 共置,critic+reward 共置(最常用)
# 8 卡机器,但 ref 和 reward 不占新卡
--actor.num_gpus_per_node 8 \
--ref.num_gpus_per_node 8 \ # 同 8 卡共置
--train.colocate_actor_ref \
--critic.num_gpus_per_node 8 \
--reward.num_gpus_per_node 8 \
--train.colocate_critic_reward \
--vllm.num_engines 4 --vllm.tensor_parallel_size 2 # vLLM 8 卡(同 actor 共置)
典型组合 2:actor+vllm 同卡,其他独占
# 这种适合更大模型 / 显存紧张
--actor.num_gpus_per_node 8 \
--ref.num_gpus_per_node 8 \
--critic.num_gpus_per_node 8 \
--reward.num_gpus_per_node 8 \
--vllm.num_engines 1 --vllm.tensor_parallel_size 8 \
# actor + vllm 共享(OpenRLHF 默认行为)
# ref / critic / reward 各自独占卡
8.4模式 C:fully distributed(最快但费卡)
每个角色独占一片 GPU,互不干扰。生产环境训 70B+ 模型的标配:
# 16 卡:actor 8 + critic 8(ref / reward 用更小切片)
--actor.num_nodes 1 --actor.num_gpus_per_node 8 \
--ref.num_nodes 1 --ref.num_gpus_per_node 4 \ # 不要 colocate
--critic.num_nodes 1 --critic.num_gpus_per_node 8 \
--reward.num_nodes 1 --reward.num_gpus_per_node 4 \
--vllm.num_engines 2 --vllm.tensor_parallel_size 4 \ # vLLM 另 8 卡
# 不开任何 colocate flag
# 不开 sleep mode
这种模式:
- 吞吐最高:无 sleep / wake_up 切换开销;
- 显存最宽松:每个角色单独优化;
- 缺点:每个角色都是独立 process group,跨角色 RPC 走 Ray + 临时 NCCL group,编排复杂;
- 缺点:总卡数 = 各角色卡数之和,可能 32 卡起步。
8.5选哪种模式
| 资源 | 模型规模 | 推荐模式 | 典型 flag |
|---|---|---|---|
| 1 × 8 卡 A100/H100 | 7B - 13B | fully colocated | --train.colocate_all |
| 1 × 8 卡 A100/H100 | 30B - 32B | partial hybrid | colocate_actor_ref + colocate_critic_reward |
| 2 × 8 卡 A100/H100 | 30B - 70B | partial hybrid 跨节点 | actor + vllm 一组,critic + ref + reward 另一组 |
| 4 × 8 卡 A100/H100 | 70B - 130B | fully distributed | 各角色独占节点 |
| ≥ 8 × 8 卡 H100 | 200B+ MoE | fully distributed + vLLM 多机 | — |
8.6colocate 模式的隐藏成本
colocate 看上去免费午餐,但有隐藏成本:
- 切换开销:每个 PPO step 都要 vLLM sleep ↔ wake_up + actor offload ↔ reload,单次几百毫秒;
- 显存碎片:频繁分配 / 释放导致 cudaMalloc 碎片化,少数情况下会 OOM;
- 调试更难:colocate 时 actor 和 vllm 状态变化频繁,trace 很难看;
- 多机更复杂:跨节点 colocate 要保证 placement group strict_pack 不破。
用 colocate 跑 70B 时,每个 step wall time 可能比 fully distributed 慢 20-30%。
8.7多机训练时的 placement
多机时 num_nodes 起作用:
--actor.num_nodes 2 --actor.num_gpus_per_node 8 # 跨 2 节点共 16 卡
--vllm.num_engines 4 --vllm.tensor_parallel_size 4 # vllm 也跨 2 节点
这时 Ray placement_group 用 PACK 策略(不再 STRICT_PACK),允许跨节点。
TP 不跨节点(NVLink-only),DP 跨节点(IB)。
多机启动方式
# Head 节点
ray start --head --port=6379
# Worker 节点
ray start --address=<head_ip>:6379
# 提交训练
ray job submit --address="http://<head_ip>:8265" \
--runtime-env-json='{"working_dir": "/openrlhf"}' \
-- bash examples/scripts/train_ppo_ray_slurm.sh
8.8实测显存对照(13B PPO)
在 8 × A100 80G 上跑 Llama-3-13B PPO 的显存峰值(每卡):
| 模式 | 每卡显存 | 每 step 时间 |
|---|---|---|
| fully colocated(含 sleep) | ~42 GB | ~85 s |
| colocate_actor_ref + colocate_critic_reward | ~52 GB | ~72 s |
| fully distributed(16 卡) | ~28 GB / 卡 | ~58 s |
看出来:colocate 省卡但慢一些;fully distributed 快但耗卡。
8.9选 mode 的口诀
1. 硬件富裕(每角色一片卡) → fully distributed,求最快;
2. 硬件中等(8-16 卡训 13-70B) → partial hybrid,按需 colocate;
3. 单机 8 卡训 7B-32B → fully colocated,省卡。
8.10colocate 字段速查(CLI 真实写法)
三种模式不是预设的"模式名",而是几个 colocate flag 的组合。读 cli/train_ppo_ray.py 时这张表很有用:
| CLI flag | 含义 |
|---|---|
--train.colocate_all | 所有 4 个角色 + vLLM 共享同一组 GPU;省卡王者 |
--train.colocate_actor_ref | 只 actor + reference 共置(ref 静态,跟 actor 同卡省 1 份显存) |
--train.colocate_critic_reward | 只 critic + reward 共置(两个 sequence regression head 同卡) |
--train.colocate_actor_critic_ref_reward | 四个训练角色共置但不含 vLLM,vLLM 独立卡 |
--vllm.enable_sleep | vLLM 在不 generate 时 sleep(colocate 必开) |
--ds.enable_sleep | DeepSpeed 训练侧 sleep(offload optimizer/grad 到 CPU;colocate_all 必开) |
--train.async_enable | 异步 pipeline,rollout 与 train 并行(与 colocate_all 互斥) |
三档典型组合:
# Fully colocated(单机 8 卡跑 70B PPO)
--train.colocate_all --vllm.enable_sleep --ds.enable_sleep
# Partial hybrid(双节点 16 卡)
--train.colocate_actor_ref --train.colocate_critic_reward
# Fully distributed(4 节点 32 卡,每角色独占节点)
# 不加任何 colocate flag
# Async pipeline(多机 + 异步加速)
--train.async_enable --vllm.enable_sleep # 与 colocate_all 互斥
8.11这章你需要带走的
- OpenRLHF 三种部署模式:fully colocated / partial hybrid / fully distributed;
- colocate 通过 sleep mode 分时复用显存,省卡但慢 20-30%;
- fully distributed 每角色独占卡,吞吐最高但耗卡;
- partial hybrid 是大多数实战的甜点;
- TP 不跨节点、DP 跨节点是基本规则;
- 多机训练用
ray start --address=<head>接 worker,ray job submit提交训练。