https://zhuanlan.zhihu.com/p/460600694
行动器的设计使得Ray具备更高效的细粒度更新能力。因为行动器是一种高内聚的设计,状态与可能改变状态的操作被设计在一个类中,使得这些操作不依赖于外界的状态,从而在更新状态时省去了许多序列化和反序列化的开销。一个例子是使用行动器来实现参数服务器,在这个应用中,参数是状态,基于状态的操作便是训练. 在传统的分布式训练框架,如PyTorch中,分布式训练的每个训练进程都维护了一份参数信息,并且都各自计算出一个梯度,进程之间需要交换梯度信息以计算出总梯度和更新后的参数,这就意味着梯度需要被序列化和反序列化以便在进程间传递。使用行动器的架构可以使整个系统中只维护一份参数信息,并且对于同一份参数的更新操作都是串行的。另外,提交参数更新的请求是非阻塞的,参数更新是GPU密集型的任务,因此在提交完后还可以并行地去做CPU密集型的任务,这也是Ray框架异构性的体现。什么意思,举例
Ray 行动器(Actor)设计原理与参数服务器示例解析
这段描述精准地概括了 Ray 框架中 行动器(Actor) 模型的核心优势。让我通过一个具体例子来解释这个概念。
🌟 为什么行动器(Actor)设计更高效?
传统分布式训练的问题
在传统分布式训练框架(如 PyTorch DDP)中:
- 每个 GPU 进程都持有完整的模型参数副本
- 每个进程计算局部梯度后,需要通过 All-Reduce 通信聚合梯度
- 梯度数据必须序列化后才能在进程间传输
- 所有进程必须同步等待梯度聚合完成才能更新参数
问题:这种设计导致了大量通信开销和序列化/反序列化成本,尤其是在模型规模增大时。
💡 行动器(Actor)设计如何解决这些问题?
行动器的三大优势
- 高内聚设计:状态(参数)和操作(更新)封装在同一个 Actor 中
- 减少序列化:参数只在 Actor 内部维护,不需要频繁序列化
- 异步非阻塞:提交更新请求后,可以立即执行其他任务
📊 参数服务器示例:传统 vs Ray Actor
1. 传统 PyTorch 分布式训练
# 伪代码 - 传统分布式训练
for epoch in range(epochs):
# 每个GPU计算梯度
gradients = model.compute_gradients(batch)
# 需要序列化梯度进行All-Reduce
torch.distributed.all_reduce(gradients)
# 每个GPU独立更新参数(但需要等待通信完成)
model.update_parameters(gradients)
# 同步点:所有GPU必须等待通信完成
torch.distributed.barrier()
问题:每个 step 都需要:
- 序列化/反序列化梯度数据
- 所有 GPU 同步等待通信完成
- 每个 GPU 维护完整参数副本
2. Ray Actor 参数服务器实现
# 参数服务器Actor
@ray.remote
class ParameterServer:
def __init__(self, model):
self.model = model # 只有一份模型参数
self.updates = [] # 待处理的更新请求
def apply_gradients(self, gradients):
# 串行处理所有更新请求
self.model.update(gradients)
return self.model.get_weights()
def get_weights(self):
return self.model.get_weights()
# 训练Worker
@ray.remote
class Worker:
def __init__(self, ps, dataset):
self.ps = ps
self.dataset = dataset
def train_step(self):
# 1. 计算局部梯度(GPU密集型)
gradients = self._compute_gradients()
# 2. 非阻塞提交梯度更新(不等待完成)
update_future = self.ps.apply_gradients.remote(gradients)
# 3. 立即执行CPU密集型任务(异构并行)
next_batch = self._prepare_next_batch()
# 4. 需要时再获取结果
updated_weights = ray.get(update_future)
return updated_weights
# 使用示例
ps = ParameterServer.remote(model)
workers = [Worker.remote(ps, dataset) for _ in range(4)]
# 启动训练
for step in range(1000):
# 所有worker并行执行训练步骤
results = [w.train_step.remote() for w in workers]
ray.get(results)

最低0.47元/天 解锁文章
5850

被折叠的 条评论
为什么被折叠?



