【Ray大模型分布式训练】

https://zhuanlan.zhihu.com/p/460600694
行动器的设计使得Ray具备更高效的细粒度更新能力。因为行动器是一种高内聚的设计,状态与可能改变状态的操作被设计在一个类中,使得这些操作不依赖于外界的状态,从而在更新状态时省去了许多序列化和反序列化的开销。一个例子是使用行动器来实现参数服务器,在这个应用中,参数是状态,基于状态的操作便是训练. 在传统的分布式训练框架,如PyTorch中,分布式训练的每个训练进程都维护了一份参数信息,并且都各自计算出一个梯度,进程之间需要交换梯度信息以计算出总梯度和更新后的参数,这就意味着梯度需要被序列化和反序列化以便在进程间传递。使用行动器的架构可以使整个系统中只维护一份参数信息,并且对于同一份参数的更新操作都是串行的。另外,提交参数更新的请求是非阻塞的,参数更新是GPU密集型的任务,因此在提交完后还可以并行地去做CPU密集型的任务,这也是Ray框架异构性的体现。什么意思,举例

Ray 行动器(Actor)设计原理与参数服务器示例解析

这段描述精准地概括了 Ray 框架中 行动器(Actor) 模型的核心优势。让我通过一个具体例子来解释这个概念。

🌟 为什么行动器(Actor)设计更高效?

传统分布式训练的问题

在传统分布式训练框架(如 PyTorch DDP)中:

  • 每个 GPU 进程都持有完整的模型参数副本
  • 每个进程计算局部梯度后,需要通过 All-Reduce 通信聚合梯度
  • 梯度数据必须序列化后才能在进程间传输
  • 所有进程必须同步等待梯度聚合完成才能更新参数

问题:这种设计导致了大量通信开销序列化/反序列化成本,尤其是在模型规模增大时。


💡 行动器(Actor)设计如何解决这些问题?

行动器的三大优势

  1. 高内聚设计:状态(参数)和操作(更新)封装在同一个 Actor 中
  2. 减少序列化:参数只在 Actor 内部维护,不需要频繁序列化
  3. 异步非阻塞:提交更新请求后,可以立即执行其他任务

📊 参数服务器示例:传统 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)

🔍 关键设计解析

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值