1. 为什么须要分布式训练
随着人工智能与深度学习的倒退,大规模和超大规模的模型越来越受到业界的推崇。以NLP行业为例,从最开始的Bert-base只有1亿左右的参数量,到千亿级别的GPT-3,再到往年6月公布的目前寰球最大预训练模型“悟道2.0”,参数规模达到惊人的1.75万亿,整个业界都由一种向更大模型倒退的趋势。面对如此宏大的模型,必然也须要宏大的数据量能力进行训练,如果没有分布式训练的大算力加持,一个Epoch可能就要训练到天荒地老。抛开业界淬炼超大模型的场景,对于一个AI行业的一般算法工程师,面对日常的工作,分布式训练也能够大大减速模型的训练、调参的节奏、以及版本的迭代更新,在工夫如此宝贵的当下,置信没有工程师会抗拒分布式训练带来的收益。因而,咱们明天就聊聊深度学习中对于分布式训练的那些事儿。
2. 分布式训练策略
分布式训练策略依照并行形式不同,能够简略的分为数据并行和模型并行两种形式。
2.1 数据并行
数据并行是指在不同的GPU上都copy保留一份模型的正本,而后将不同的数据调配到不同的GPU上进行计算,最初将所有GPU计算的后果进行合并,从而达到减速模型训练的目标。因为数据并行会波及到把不同GPU的计算结果进行合并而后再更新模型,依据跟新形式不同,又能够分为同步更新和异步更新。在数据并行中,每个GPU只计算一个batch中的一部分数据,同步更新指的就是在期待所有的GPU都计算实现之后,而后再对立合并和更新网络的权重,并播送到所有的GPU中,随后进行下一轮的计算。而异步跟新不同,异步更新中每个GPU在独立计算实现之后,都无需期待其余GPU,能够立刻更新整体权重,而后播送到其余GPU中,随后马上进入下一轮的计算。由此可见,同步更新须要期待所有的GPU都计算实现能力更新,如果集群中某一个GPU训练慢了,或者集群中的通信呈现抖动,都会影响到整个网络的训练速度,相似木桶效应,最短板决定了最大的容量。而异步更新因为不必期待其余GPU节点,因而总体训练速度会快一些,然而会有一个重大的梯度生效的问题。即在异步的状况下,每一个节点实现训练之后,都会马上去更新,这会造成其余节点当初的模型参数和这一轮训练前采纳的模型参数可能不统一,从而导致此时的梯度过期。因而,异步更新尽管快,然而因为梯度生效问题,模型往往会陷入到次优解中。
2.2 模型并行
与数据并行不同,分布式训练中的模型并行是指将整个神经网络模型拆解散布到不同的GPU中,不同的GPU负责计算网络模型中的不同局部。这通常是在网络模型很大很大、单个GPU的显存曾经齐全装不下整体网络的状况下才会采纳。因为深度学习的模型通常蕴含很多层,层与层之间的运行有先后训练,前向流传和反向梯度计算的时候,后面的层和前面的层都会彼此依赖作为输入输出,因而这种串行的逻辑对减速造成了肯定的限度。然而相比起来,咱们也算能够通过模型并行的形式把一个超大模型训练起来,不然对于一个单GPU的话,超大模型是齐全没方法work的。
因而,比照起来,模型并行因为各个GPU只加载了模型的一部分网络结构,存在肯定的依赖关系,造成了规模的伸缩性比拟差,不能随便的增减GPU的数量,因而在理论中使用的并不多。而数据并行的形式,因为各个GPU互相独立,不便GPU的扩缩容,同时减速成果好,因而在理论中使用较多,然而在某些时候,咱们也能够同时联合数据并行和模型并行两种形式。
3. 基于Pytorch的分布式训练方法
在Pytorch中为咱们提供了两种多GPU的分布式训练计划:torch.nn.DataParallel(DP)和 torch.nn.parallel.Distributed Data Parallel(DDP)。
3.1 Data Parallel
DP模式应用起来非常容易,只须要对单GPU的代码批改其中一行就能够运行了,因为DP模式采纳的是PS架构,存在负载不平衡问题,主卡往往会成为训练的瓶颈,因而训练速度会比DDP模式慢一些。而且DP只反对单机多卡的形式,个别一台机器只能装置最多8张卡,当咱们要训练特地大型的工作时,8卡就会显得特地吃紧,因而会有肯定的限度。
# use DataParallelif torch.cuda.device_count() > 1: print("Let's use", torch.cuda.device_count(), "GPUs!") model = torch.nn.DataParallel(model)model.to(device)
3.2 DistributedDataParallel
与DP模式不同,DDP模式自身是为多机多卡设计的,当然在单机多卡的状况下也能够应用。DDP采纳的是all-reduce架构,根本解决了PS架构中通信老本与GPU的数量线性相关的问题。尽管在单机多卡状况下,能够应用DP模式,然而应用DDP通常会比DP模式快一些,因而DDP模式也是官网举荐大家应用的形式。革新现有的代码应用DDP也十分不便,通过上面几个步骤就能够轻松搞定。
# 1. init backend nccltorch.distributed.init_process_group(backend='nccl')# 2. config gpulocal_rank = torch.distributed.get_rank()torch.cuda.set_device(local_rank)device = torch.device("cuda", local_rank)# 3. use DistributedSamplertraining_loader = DataLoader(training_set, batch_size=TRAIN_BATCH_SIZE, sampler=DistributedSampler(training_set))# 4. move model to gpumodel.to(device)# 5. use DistributedDataParallelif torch.cuda.device_count() > 1: print("Let's use", torch.cuda.device_count(), "GPUs!") model = DistributedDataParallel(model, device_ids=[local_rank], output_device=local_rank)
3.3 Horovod
除了Pytorch原生提供的DP和DDP形式以外,也有很多优良的由第三方提供的分布式训练工具,其中Horovod就是比拟罕用的一款。Horovod是Uber开源的跨平台分布式训练框架(horovod名字来源于俄罗斯一种民间舞蹈,舞者手拉手站成一个圆圈跳舞,类比了GPU设施之间的通信模式,如果该框架是中国人或者华人开发的话,我预计可能就叫“锅庄”了吧^-^),从名字能够看进去,Horovod采纳all-reduce架构来进步分布式设施的通信效率。同时,Horovod不仅反对Pytorch,也反对TensorFlow等其余深度学习框架。训练中如果想应用Horovod的话,其实对代码的改变也比拟少,如下所示。
import horovod.torch as hvd# 1. init horovodhvd.init()# 2. Pin GPU to be used to process local rank (one GPU per process)torch.cuda.set_device(hvd.local_rank())# 3. Partition dataset among workers using DistributedSamplertrain_sampler = DistributedSampler(training_set, num_replicas=hvd.size(), rank=hvd.rank())training_loader = DataLoader(training_set, batch_size=TRAIN_BATCH_SIZE, sampler=train_sampler)# 4. Add Horovod Distributed Optimizeroptimizer = hvd.DistributedOptimizer(optimizer, named_parameters=model.named_parameters())# 5. Horovod: broadcast parameters from rank 0 to all other processes.hvd.broadcast_parameters(model.state_dict(), root_rank=0)
另外,字节跳动也开源了一款高性能的分布式深度学习训练框架BytePS(我的项目github地址:https://github.com/bytedance/...),该框架没有采纳热门的all-reduce,反而采纳了PS架构,通过利用额定的CPU资源作为Parameter Server等措施,晋升了通信性能,据说成果能够优于Horovod。而在几天之前,快手联结苏黎世理工也发表开源了一款分布式训练框架Bagua(八卦),Bagua专门针对分布式场景设计了特定的优化算法,实现了算法和零碎层面的联结优化,性能较同类晋升60%。感兴趣的同学也能够关注一下。我的项目github地址:https://github.com/BaguaSys/b...
4. 试验比照
这里咱们比照了Pytorch原生的DP和DDP模式,同时也抉择了第三方插件Horovod进行比照。试验抉择了基于bert-base的预训练语言模型进行文本分类的工作。具体试验参数如下:GPU型号: V100, learning_rate: 2e-5, batch_size: 128, max_len: 128, epochs: 1, train_set_size: 48w
因为DDP和Horovod都是采纳all-reduce架构,因而性能相当,可见Pytorch原生的DDP模式也曾经做得十分不错了。而DP相比其余模式性能就会差一些。因而在理论工作中,还是比拟举荐应用DDP或者Horovod进行分布式训练。
总结
本文探讨了深度学习中模型并行和数据并行的分布式策略,并基于Pytorch框架介绍了原生的DP和DDP模式,以及第三方Horovod分布式训练框架。从前面的试验比照能够看出,平时工作中比拟举荐应用DDP或者Horovod的形式。分布式训练是深度学习中十分重要的一环,除了Horovod,其余各大厂商也相继开源了本人的分布式训练框架,比方BytePS、DeepSpeed、Bagua等等,这些框架的开源也将进一步推动这个畛域的倒退,为深度学习提供更优良的工具。
作者简介
Hongyu OPPO高级NLP算法工程师
次要从事NLP、常识图谱及相干畛域的工作
获取更多精彩内容,扫码关注[OPPO数智技术]公众号