single_controller 模块总览¶
模块路径¶
verl/single_controller/
模块定位¶
single_controller 是 verl 框架的分布式控制核心模块。它实现了一种"单控制器"(Single Controller)架构:由一个主控进程(Controller)统一调度多个远程 Worker 进程,完成分布式训练中的数据分发、任务执行和结果收集。
在强化学习训练(如 RLHF)中,需要同时运行多个模型(Actor、Critic、Reference、Reward),每个模型可能占用多张 GPU 并行计算。single_controller 负责:
- 资源管理:管理 GPU 资源池,决定每个 Worker 放在哪台机器的哪张卡上。
- Worker 生命周期:创建、监控、销毁分布式 Worker。
- 数据分发与收集:把数据按策略切分发给各 Worker,再把结果合并回来。
- 方法代理:让用户像调用本地方法一样调用远程 Worker 上的方法。
架构概览¶
+-----------------------+
| 用户代码 (Trainer) |
+-----------+-----------+
|
| 调用 worker_group.some_method(data)
v
+-----------------------+
| WorkerGroup |
| (RayWorkerGroup) |
| |
| - dispatch_fn: 数据分发 |
| - execute_fn: 远程执行 |
| - collect_fn: 结果收集 |
+-----------+-----------+
|
+----------------+----------------+
| | |
v v v
+--------+ +--------+ +--------+
| Worker0| | Worker1| | Worker2|
| (GPU0) | | (GPU1) | | (GPU2) |
+--------+ +--------+ +--------+
核心概念¶
1. Worker(工人)¶
单个分布式进程,运行在一张 GPU 上。负责实际的计算工作(如模型前向/反向传播)。
2. WorkerGroup(工人组)¶
管理一组 Worker 的抽象。提供统一接口来对所有 Worker 发起远程调用。
3. ResourcePool(资源池)¶
描述集群中有多少节点、每个节点有多少进程/GPU。用于创建 PlacementGroup,确保 Worker 被调度到正确的位置。
4. Dispatch(分发策略)¶
控制数据如何从 Controller 分发到各 Worker。常见模式:
- ONE_TO_ALL:同一份数据广播到所有 Worker
- ALL_TO_ALL:每个 Worker 各收到自己对应的一份
- DP_COMPUTE_PROTO:把 DataProto 按 DP(数据并行)维度切分
5. @register 装饰器¶
用来标记 Worker 上的方法,指定该方法的分发策略和执行模式。WorkerGroup 会自动识别这些标记,生成对应的代理方法。
目录结构¶
verl/single_controller/
|-- __init__.py # 模块入口,导出核心类
|-- base/ # 基础抽象层
| |-- __init__.py # 导出 Worker, WorkerGroup, ClassWithInitArgs, ResourcePool
| |-- decorator.py # @register 装饰器、Dispatch/Execute 枚举、分发/收集函数
| |-- worker.py # Worker 基类(单个分布式进程)
| |-- worker_group.py # WorkerGroup 基类、ResourcePool、ClassWithInitArgs
|
|-- ray/ # Ray 后端实现层
|-- __init__.py # 导出 Ray 相关类
|-- base.py # RayWorkerGroup、RayResourcePool、FusedWorker 等
文件依赖关系¶
decorator.py <---- worker.py <---- worker_group.py
^ ^ ^
| | |
+--------------------+--------------------+
|
ray/base.py
decorator.py是最底层,定义了分发策略和装饰器worker.py依赖decorator.py,定义单个 Worker 的行为worker_group.py依赖decorator.py,定义 WorkerGroup 的管理逻辑ray/base.py依赖上面三个,是 Ray 框架下的具体实现
推荐阅读顺序¶
base/decorator.py-- 理解分发策略和@register装饰器机制base/worker.py-- 理解单个 Worker 的初始化和环境配置base/worker_group.py-- 理解 WorkerGroup 如何管理多个 Workerray/base.py-- 理解 Ray 后端如何实际创建和调度 Worker__init__.py文件 -- 了解模块导出结构
典型使用流程¶
# 1. 定义资源池:2个节点,每个节点4个GPU
resource_pool = RayResourcePool(process_on_nodes=[4, 4])
# 2. 定义 Worker 类(继承 Worker,用 @register 装饰方法)
@ray.remote
class MyWorker(Worker):
@register(dispatch_mode=Dispatch.DP_COMPUTE_PROTO)
def train_step(self, data):
# 每个 Worker 只处理自己那份数据
return self.model(data)
# 3. 创建 WorkerGroup
cls_with_args = RayClassWithInitArgs(cls=MyWorker)
worker_group = RayWorkerGroup(resource_pool=resource_pool, ray_cls_with_init=cls_with_args)
# 4. 像调用本地方法一样调用远程方法
result = worker_group.train_step(full_data)
# 内部会自动:切分数据 -> 分发到各Worker -> 各Worker执行 -> 收集结果 -> 合并返回
讲解文档索引¶
| 文件 | 讲解文档 |
|---|---|
verl/single_controller/__init__.py |
init.py 讲解 |
verl/single_controller/base/__init__.py |
base/init.py 讲解 |
verl/single_controller/base/decorator.py |
decorator.py 讲解 |
verl/single_controller/base/worker.py |
worker.py 讲解 |
verl/single_controller/base/worker_group.py |
worker_group.py 讲解 |
verl/single_controller/ray/__init__.py |
ray/init.py 讲解 |
verl/single_controller/ray/base.py |
ray/base.py 讲解 |