首页 > 其他分享 >PyTorch分布式并行训练

PyTorch分布式并行训练

时间:2023-01-12 14:14:34浏览次数:64  
标签:并行 rank PyTorch 分布式 数据 size

目录

Pytorch分布式并行训练原理

PyTorch分布式训练采用数据并行架构。

分布式数据并行原理


图片来源:https://dev-discuss.pytorch.org/t/torchdynamo-update-9-making-ddp-work-with-torchdynamo/860#background-why-dynamo-doesnt-work-well-with-ddp-2

  1. 每个rank都有一份模型的拷贝(一个rank就是进程),不同rank可以相同机器的不同GPU卡上,也可以分布在不同的机器上;
  2. 将数据的不同Batch的数据传给不同的rank;
  3. 每个rank执行forward pass;
  4. 每个rank执行backward pass,因为模型输入的数据不同,所以不同rank上的梯度不同;
  5. 通过allreduce算法同步梯度,最终每个rank的梯度保持一致;

PyTorch分布式数据并行Demo

分布式数据并行训练Demo:

def ddp_demo(rank, world_size, accum_grad=4):
    assert dist.is_gloo_available(), "Gloo is not available!"
    print(f"world_size: {world_size}, rank: {rank}, is_gloo_available: {dist.is_gloo_available()}")

    # 1. 初始化进程组
    dist.init_process_group("gloo", world_size=world_size, rank=rank)

    model = nn.Sequential(nn.Linear(10, 100), nn.ReLU(), nn.Linear(100, 20))

    # 2. 分布式数据并行封装模型
    ddp_model = DistributedDataParallel(model)

    criterion = nn.MSELoss()
    optimizer = optim.SGD(ddp_model.parameters(), lr=1e-3)

    dataset = TensorDataset(torch.randn(1000, 10))
    # 3. 数据并行
    sampler = DistributedSampler(dataset=dataset, num_replicas=world_size, shuffle=True)
    dataloader = DataLoader(dataset=dataset, batch_size=24, sampler=sampler, collate_fn=transform)

    for epoch in range(1):
        for step, batch in enumerate(dataloader):
            output = ddp_model(batch)
            label = torch.rand_like(output)

            if step % accum_grad == 0:
                # 同步参数
                context = contextlib.nullcontext
            else:
                # 4. 梯度累计,不同步参数
                context = ddp_model.no_sync

            with context():
                time.sleep(random.random())
                loss = criterion(output, label)
                loss.backward()

            if step % accum_grad == 0:
                optimizer.step()
                optimizer.zero_grad()
                print(f"epoch: {epoch}, step: {step}, rank: {rank} update parameters.")

    # 5. 销毁进程组上下文数据(一些全局变量)
    dist.destroy_process_group()

本地没有Nvidia环境,使用gloo替代nccl做通信后端。

PyTorch分布式训练Demo链接:https://gist.github.com/hotbaby/15950bbb43d052cd835b0f18c997f67c

模型转换成分布式训练步骤:

  1. 初始化进程组dist.init_process_group("gloo", world_size=world_size, rank=rank)
  2. 分布式数据并行封装模型DistributedDataParallel(model)
  3. 数据分布式并行,将数据分成world_size 份,根据rank采样DistributedSampler(dataset=dataset, num_replicas=world_size, shuffle=True)
  4. 训练过程中梯度累计,降低训练进程间的参数同步频率,提升通信效率【可选】;
  5. 销毁进程组dist.destroy_process_group()

PyTorch分布式数据并行内部设计

一个典型神经网络训练流程:

  1. 创建神经网络模型、定义目标函数和优化器;
  2. 迭代输入数据;
  3. 前向传播,计算loss;
  4. 反向传播,计算梯度;
  5. 根据梯度和学习率,更新参数weight = weight - learning_rate * weight
  6. 重复2 ~ 5步骤。

分布式数据并行DDP通过嵌入到上述训练流程的不同阶段,实现训练加速:

  • 初始化
    • 进程组ProcessGroup,解决rank间通信问题;
  • 构建神经模型
    • rank0参数广播给其他rank,保证所有模型副本的参数一致;
    • 初始化Reducer,用于后续反向传播阶段梯度累计和同步;
  • 前向传播
    • require_forward_param_sync为True时,同步参数;
  • 反向传播
    • DDP通过注册autograd hook注册梯度同步函数,调用Reducerallreduce算法在rank间同步梯度;
  • 更新参数

PyTorch分布式数据并行源代码分析

ddp_code.png

图片来源:https://pytorch.org/docs/master/notes/ddp.html

  • distributed.py是分布式数据并行DDP Python程序入口,DistributedDataParallel封装了神经网络模型,重写了Module的forward()函数,调用底层C++库common.h接口同步模型参数,调用C++库reducer.hallreduce实现梯度同步;
  • common.h实现了broadcast_coalesced广播等工具函数;
  • reducer.h
    • Reducer构造函数被distributed.py调用,注册了autograd_hook()函数实现梯度累计;
    • autograd_hook()被PyTorch的自动微分引擎autograd engine调用;
    • prepare_for_backward()distributed.py的前向传播阶段调用;
  • ProcessGroup.hpp抽象了allreducer()gather()scatter()broadcast()等接口,NCCLGloo等Backend实现了ProcessGroup.hpp定义的接口。

Ring AllReduce算法

为什么需要Ring AllReducer算法?

假设模型大小为128MB,网络带宽为1000Mb/s,8张GPU卡并行计算。一个训练step,rank0将参数同步到其他rank的时间是8秒,随着GPU数量的增长,参数同步的时间也线性增长,最终网络通信的时间抵消了GPU多卡训练时间,多卡训练加速不明显。

ring allreduce算法原理:

参考https://zhuanlan.zhihu.com/p/69797852

ring allreduce算法网络通信代价分析:

假设模型大小为M,GPU数量为N,在scatter-reducerall-gather阶段,发送的数据大小为M/N,数据传输总量为2(N - 1)* M / N,数据通信总量是确定,不会随着GPU数量增长而增长。

参考文献

标签:并行,rank,PyTorch,分布式,数据,size
From: https://www.cnblogs.com/bytehandler/p/17046513.html

相关文章

  • PyTorch如何加速数据并行训练?分布式秘籍大揭秘
    PyTorch在学术圈里已经成为最为流行的深度学习框架,如何在使用PyTorch时实现高效的并行化?在芯片性能提升有限的今天,分布式训练成为了应对超大规模数据集和模型的主要......
  • Understanding dimensions in PyTorch
     在二维的操作实例以及输出的结果>>x=torch.tensor([[1,2,3],[4,5,6]])>>x.shapetorch.Size([2,3])>>torch.sum(x,dim=0)tenso......
  • 【Deep Learning Based On Pytorch】张量
    Pytorch中张量与Tensor()一、张量Tensor张量是一个统称,其中包含很多类型:0阶张量:标量、常数,0-DTensor1阶张量:向量,1-DTensor2阶张量:矩阵,2-DTensor3阶张量........
  • pytorch geometric并行运算要注意的一些问题
    如果有多gpu的情况,可以这样写:fromtorch_geometric.nnimportDataParalleliftorch.cuda.device_count()>1:model=DataParallel(model,device_ids=[0,1])这......
  • pytorch 损失函数
    损失函数在深度学习领域是用来计算搭建模型预测的输出值和真实值之间的误差。具体实现过程:在一个批次(batch)前向传播完成后,得到预测值,然后损失函数计算出预测值和真实值之间......
  • Pytorch GPU 环境搭建
    之前⼀直使⽤Tensorflow训练模型,第⼀次训练Pytorch模型的时候,发现速度很慢,仔细观察,发现GPU内存占⽤为0,基本没有使⽤GPU。AssertionError:CUDAunavailable,invaliddev......
  • SqlServer 多服务器管理(MSSQL分布式作业管理)
    范围的多个实例的自动化管理SQLServer称为多服务器管理。使用多服务器管理可以执行下列操作:管理两台或多台服务器。在企业服务器之间安排数据仓库的信息流。若要利用......
  • jmeter-无界面压测和分布式集群配置
    jmeter-n-tD:\app\workspace\Jemeter\apache-jmeter-5.3\backups\订餐管理系统.jmx-lD:\app\workspace\Jemeter\apache-jmeter-5.3\backups\test001.jtl将jmete......
  • Wenet分布式训练对学习率调整的影响
    目录Wenet分布式训练对学习率调整的影响背景分布式训练收敛速度和学习率变化的关系Wenet学习率调整策略分析WenetWarmup学习率源代码分析模拟Wenet预热学习率调整策略We......
  • Wenet多机多卡分布式训练
    目录Wenet多机多卡分布式训练PyTorch分布式训练DemoWenet分布式训练实践Wenet如何配置多机多卡分布式训练?Wenet分布式训练实验结果Wenet分布式训练如何实现?Wenet分布式训......