Pytorch 分布式训练中DP和DDP的原理和用法
一、聊聊DP和DDP
pytorch中的有两种分布式训练方式
一种是常用的DataParallel(DP)
另外一种是DistributedDataParallel(DDP)
两者都可以用来实现数据并行方式的分布式训练
两者的区别如下:
- DP采用的是PS模式,DDP采用的是Ring-all-reduce模式
- DP是单进程多线程的实现方式,DDP是采用多进程的方式
- DP只能在单机上使用,DDP单机和多机都可以使用
- DDP相比于DP训练速度要快
二、聊聊PS模式和Ring-all-reduce模式
PS模式
即Parameter Server架构,主要由server节点和worker节点组成
server节点的主要功能是初始化和保存模型参数
接受worker节点计算出的局部梯度、汇总计算全局梯度,并更新模型参数(DP)
worker节点的主要功能是各自保存部分训练数据
初始化模型,从server节点拉取最新的模型参数(pull),
再读取参数,根据训练数据计算局部梯度,上传给server节点(push)
PS模式下的DP,会造成负载不均衡
因为充当server的GPU需要一定的显存用来保存worker节点计算出的局部梯度
另外server还需要将更新后的模型参数broadcast到每个worker
server的带宽就成了server与worker之间的通信瓶颈
server与worker之间的通信成本会随着worker数目的增加而线性增加
Ring-all-reduce模式
ring-all-reduce模式没有server节点,worker与worker之间的通信构成一个环
ring-all-reduce模式下,所有worker只和自己相邻的两个worker进行通信
该工作模式分为两个工作阶段:
- Scatter Reduce:在这个 Scatter Reduce阶段,GPU 会逐步交换彼此的梯度并融合,最后每个 GPU 都会包含完整融合梯度的一部分
- Allgather:GPU 会逐步交换彼此不完整的融合梯度,最后所有 GPU 都会得到完整的融合梯度
首先将模型的梯度按照集群中GPU数量进行分块
然后进行第一步scatter reduce,注意该过程中所有的GPU都是在进行通信的
ring all reduce模式不存在网络通信带宽的瓶颈
三、聊聊使用
开始之前需要先熟悉几个概念。
group:进程组
默认情况下,只有一个组,一个 job 即为一个组,也即一个 world。
world size:全局进程个数。
如果是多机多卡就表示机器数量,如果是单机多卡就表示 GPU 数量。
rank:进程序号,用于进程间通讯,表征进程优先级
rank = 0 的主机为 master 节点
如果是多机多卡就表示对应第几台机器
如果是单机多卡,由于一个进程内就只有一个 GPU,所以 rank 也就表示第几块 GPU
local_rank:表示进程内,GPU 编号,非显式参数
由 torch.distributed.launch 内部指定
多机多卡中 rank = 3,local_rank = 0 表示第 3 个进程内的第 1 块 GPU
在使用 distributed 包的任何其他函数之前,需要使用 init_process_group 初始化进程组,同时初始化 distributed 包
如果需要进行小组内集体通信,用 new_group 创建子分组
创建分布式并行(DistributedDataParallel)模型 DDP(model, device_ids=device_ids)
为数据集创建 Sampler
使用启动工具 torch.distributed.launch 在每个主机上执行一次脚本,开始训练
使用 destory_process_group() 销毁进程组
"""
1. 添加参数 --local_rank
每个进程分配一个 local_rank 参数,表示当前进程在当前主机上的编号。
例如:rank=2, local_rank=0 表示第 3 个节点上的第 1 个进程。
这个参数是torch.distributed.launch传递过来的,我们设置位置参数来接受,local_rank代表当前程序进程使用的GPU标号
"""
parser = argparse.ArgumentParser()
parser.add_argument('--local_rank', default=-1, type=int)
args = parser.parse_args()
print(args.local_rank))# 检查nccl是否可用
torch.distributed.is_nccl_available ()"""
2.初始化使用nccl后端
When using a single GPU per process and per
DistributedDataParallel, we need to divide the batch size
ourselves based on the total number of GPUs we have
"""
torch.distributed.init_process_group(backend='nccl') device_ids=[1,3]
ngpus_per_node=len(device_ids)
args.batch_size = int(args.batch_size / ngpus_per_node)"""
3.使用DistributedSampler
别忘了设置pin_memory=true
使用 DistributedSampler 对数据集进行划分。
它能帮助我们将每个 batch 划分成几个 partition,在当前进程中只需要获取和 rank 对应的那个 partition 进行训练
"""train_dataset = MyDataset(train_filelist, train_labellist, args.sentence_max_size, embedding, word2id)
train_sampler = t.utils.data.distributed.DistributedSampler(train_dataset)# DataLoader:num_workers这个参数决定了有几个进程来处理data loading。0意味着所有的数据都会被load进主进程
# testset不用sampler
train_dataloader = DataLoader(train_dataset, pin_memory=true, shuffle=(train_sampler is None),batch_size=args.batch_size, num_workers=args.workers, sampler=train_sampler)"""
4.分布式训练
使用 DistributedDataParallel 包装模型
它能帮助我们为不同 GPU 上求得的梯度进行 all reduce(即汇总不同 GPU 计算所得的梯度,并同步计算结果)。
all reduce 后不同 GPU 中模型的梯度均为 all reduce 之前各 GPU 梯度的均值. 注意find_unused_parameters参数
"""net = textCNN(args,vectors=t.FloatTensor(wvmodel.vectors))
if args.cuda: net.cuda()
if len(device_ids)>1: net=torch.nn.parallel.DistributedDataParallel(net,find_unused_parameters=True) """
5.最后,把数据和模型加载到当前进程使用的 GPU 中,正常进行正反向传播:
"""
for batch_idx, (data, target) in enumerate(train_loader): if args.cuda:data, target = data.cuda(), target.cuda()output = net(images)loss = criterion(output, target)...optimizer.zero_grad()loss.backward()optimizer.step()"""
6.在使用时,命令行调用 torch.distributed.launch 启动器启动:
pytorch 为我们提供了 torch.distributed.launch 启动器,用于在命令行分布式地执行 python 文件。
--nproc_per_node参数指定为当前主机创建的进程数。一般设定为=NUM_GPUS_YOU_HAVE当前主机的 GPU 数量,每个进程独立执行训练脚本。
这里是单机多卡,所以node=1,就是一台主机,一台主机上--nproc_per_node个进程
"""CUDA_VISIBLE_DEVICES=0,1,2,3 python -m torch.distributed.launch --nproc_per_node=4 main.py
参考文献
- https://zhuanlan.zhihu.com/p/356967195
- https://www.cnblogs.com/yh-blog/p/12877922.html
- https://medium.com/huggingface/training-larger-batches-practical-tips-on-1-gpu-multi-gpu-distributed-setups-ec88c3e51255
Pytorch 分布式训练中DP和DDP的原理和用法相关推荐
- Pytorch 并行训练(DP, DDP)的原理和应用
Pytorch 并行训练(DP, DDP)的原理和应用 1. 前言 并行训练可以分为数据并行和模型并行. 模型并行 模型并行主要应用于模型相比显存来说更大,一块 device 无法加载的场景,通过把模 ...
- PyTorch 分布式训练DDP 单机多卡快速上手
PyTorch 分布式训练DDP 单机多卡快速上手 本文旨在帮助新人快速上手最有效的 PyTorch 单机多卡训练,对于 PyTorch 分布式训练的理论介绍.多方案对比,本文不做详细介绍,有兴趣的读 ...
- 新手手册:Pytorch分布式训练
文 | 花花@机器学习算法与自然语言处理 单位 | SenseTime 算法研究员 目录 0X01 分布式并行训练概述 0X02 Pytorch分布式数据并行 0X03 手把手渐进式实战 A. 单机单 ...
- Pytorch - 分布式训练极简体验
由于工作需要,最近在补充分布式训练方面的知识.经过一番理论学习后仍觉得意犹未尽,很多知识点无法准确get到(例如:分布式原语scatter.all reduce等代码层面应该是什么样的,ring al ...
- 【Pytorch分布式训练】在MNIST数据集上训练一个简单CNN网络,将其改成分布式训练
文章目录 普通单卡训练-GPU 普通单卡训练-CPU 分布式训练-GPU 分布式训练-CPU 租GPU服务器相关 以下代码示例基于:在MNIST数据集上训练一个简单CNN网络,将其改成分布式训练. 普 ...
- PyTorch分布式训练
PyTorch分布式训练 PyTorch 是一个 Python 优先的深度学习框架,能够在强大的 GPU 加速基础上实现张量和动态神经网络.PyTorch的一大优势就是它的动态图计算特性. Licen ...
- 如何理解深度学习分布式训练中的large batch size与learning rate的关系?
问题详情: 在深度学习进行分布式训练时,常常采用同步数据并行的方式,也就是采用大的batch size进行训练,但large batch一般较于小的baseline的batch size性能更差,请问 ...
- pytorch分布式训练 DistributedSampler、DistributedDataParallel
pytorch分布式训练 DistributedSampler.DistributedDataParallel 大家好,我是亓官劼(qí guān jié ),在[亓官劼]公众号.CSDN.Git ...
- 【分布式】Pytorch分布式训练原理和实战
[分布式]基于Horovod的Pytorch分布式训练原理和实战 并行方法: 1. 模型并行 2. 数据并行 3. 两者之间的联系 更新方法: 1. 同步更新 2. 异步更新 分布式算法: 1. Pa ...
最新文章
- SQL快速入门 ( MySQL快速入门, MySQL参考, MySQL快速回顾 )
- 背光源:你究竟是怎样的波长?
- 第七届全国大学生智能汽车竞赛获奖名单
- 怎么查看python是否安装成功-如何查看python是否安装成功?
- scala学习笔记-数组转换(8)
- linux下jboss分析helloword,JBoss 中运行servlet 的helloworld程序(转)
- mysql full customer_mysql优化通常使用的几种方法
- 【警惕】大量未修复WebLogic WSAT组件RCE漏洞的主机被挖矿程序攻击
- stm32定时器编码器模式原理及配置
- Redis实战篇(视频学习来自黑马程序员)
- 运筹系列31:内点法python代码
- 旧手机利用(Android),当wifi,当mic,当ipcamera
- 书里都没的高清无码彩图【人人都是产品经理:9084】
- 485通信自动收发电路详解
- wap_supplicant介绍
- java第六章十七题_Java语言面试题十七
- Wembley record broken by U2 gig U2演唱会攻破温布利
- iOS开发者账户密码修改流程
- 垃圾填埋场渗滤液厌氧处理过程中沼气的综合利用
- 【网站翻译】【个人博客】【小牛翻译】嚯?我的博客网站没有翻译功能也能翻译了?一段代码给自己的博客网站添加多一份翻译~