首页 > 其他分享 >大模型--训练 加速之 数据并行(DP, DDP与ZeRO)-上-12

大模型--训练 加速之 数据并行(DP, DDP与ZeRO)-上-12

时间:2024-11-08 17:46:48浏览次数:1  
标签:12 -- 梯度 DDP Worker Server 通讯 GPU DP

目录

1. 参考

https://zhuanlan.zhihu.com/p/617133971

2. 总结

以Google GPipe为代表的流水线并行范式,当模型太大,一块GPU放不下时,流水线并行,将模型的不同层放到不同的GPU上,
通过切割mini-batch实现对训练数据的流水线处理,提升GPU计算通讯比。
同时通过re-materialization机制(前向过程算完即废弃,反向需要再计算)降低显存消耗。
但在实际应用中,流水线并行并不特别流行,主要原因是模型能否均匀切割,影响了整体计算效率,这就需要算法工程师手调。
这里介绍一种应用最广泛,最易于理解的并行范式:数据并行。
数据并行的核心思想是:在各个GPU上都拷贝一份完整模型,各自吃一份数据,算一份梯度,最后对梯度进行累加来更新整体模型
理念不复杂,但到了大模型场景,巨大的存储 巨大的GPU间通讯量,就是系统设计要考虑的重点了。

三种主流数据并行的实现方式:
DP(Data Parallelism):最早的数据并行模式,一般采用参数服务器(Parameters Server)这一编程框架。实际中多用于单机多卡
DDP(Distributed Data Parallelism):分布式数据并行,采用Ring AllReduce的通讯方式,实际中多用于多机场景
ZeRO:零冗余优化器。由微软推出并应用于其DeepSpeed框架中。严格来讲ZeRO采用数据并行+张量并行的方式,旨在降低存储。-- 重点

数据并行(DP):

经典数据并行的过程如下:
若干块计算GPU,如图中GPU0~GPU2;1块梯度收集GPU,如图中AllReduce操作所在GPU。
在每块计算GPU上都拷贝一份完整的模型参数。 -- W
把一份数据X(例如一个batch)均匀分给不同的计算GPU。x0 x1 x2
每块计算GPU做一轮FWD和BWD后,算得一份梯度G。
每块计算GPU将自己的梯度push给梯度收集GPU,做聚合操作。(这里的聚合操作一般指梯度累加。当然也支持用户自定义。)

梯度收集GPU聚合完毕后,计算GPU从它那pull下完整的梯度结果,用于更新模型参数W。更新完毕后,计算GPU上的模型参数依然能保持一致。

聚合下发的操作,称为AllReduce。
实现DP的一种经典编程框架叫“参数服务器”,在这个框架里,计算GPU称为Worker,梯度聚合GPU称为Server。

实际应用中,为了尽量减少通讯量,一般可选择一个Worker同时作为Server。比如可把梯度全发到GPU0上做聚合。

补充:
1个Worker或者Server下可以不止1块GPU。
Server可以只做梯度聚合,也可以梯度聚合+全量参数更新一起做。--不然每个worker需要自己做全量的参数更新 但是pull数据量会大一点

DP的框架理解起来不难,但实战中确有两个主要问题:
存储开销大。每块GPU上都存了一份完整的模型,造成冗余。关于这一点的优化,我们将在后文ZeRO部分做讲解。
通讯开销大。Server需要和每一个Worker进行梯度传输。当Server和Worker不在一台机器上时,Server的带宽将会成为整个系统的计算效率瓶颈。

对通讯开销再做详细说明:
如果将传输比作一条马路,带宽就是马路的宽度,它决定每次并排行驶的数据量。例如带宽是100G/s,但每秒却推给Server 1000G的数据,消化肯定需要时间。
那么当Server在搬运数据,计算梯度的时候,Worker们在干嘛呢?当然是在:聚众摸鱼-哈哈哈
老板不愿意了:“打工系统里不允许有串行存在的任务!”,于是梯度异步更新这一管理层略诞生了。


在梯度异步更新的场景下,某个Worker的计算顺序为:

  • 在第10轮计算中,该Worker正常计算梯度,并向Server发送push&pull梯度请求。
  • 但是,该Worker并不会实际等到把聚合梯度拿回来,更新完参数W后再做计算。而是直接拿旧的W,吃新的数据,继续第11轮的计算。这样就保证在通讯的时间里,Worker也在马不停蹄做计算,提升计算通讯比。
  • 异步也不能太过份。只计算梯度,不更新权重,那模型就无法收敛。图中刻画的是延迟为1的异步更新,也就是在开始第12轮对的计算时,必须保证W已经用第10、11轮的梯度做完2次更新了。

参数服务器的框架下,延迟的步数也可以由用户自己决定,下图分别刻划了几种延迟情况:

a 无延迟
b. 延迟但不指定延迟步数。也即在迭代2时,用的可能是老权重,也可能是新权重,听天由命。
c. 延迟且指定延迟步数为1。例如做迭代3时,可以不拿回迭代2的梯度,但必须保证迭代0、1的梯度都已拿回且用于参数更新。

总结一下:
异步很香,但对一个Worker来说,只是等于W不变,batch的数量增加了而已,在SGD下,会减慢模型的整体收敛速度。--也就是Worker光埋头干活,迟迟pull不到最新的梯度

异步的整体思想是,比起让Worker闲着,倒不如让它多吃点数据,虽然反馈延迟了,但只要它在干活在学习就行。
batch就像活,异步就像画出去的饼,且往往不指定延迟步数,每个Worker干越来越多的活,但模型却没收敛取效,像不像整天加班到半夜却。。。

3. 分布式数据并行(DDP)

受通讯负载不均的影响,DP一般用于单机多卡场景。
DDP作为一种更通用的解决方案出现了,既能多机,也能单机。
DDP首先要解决的就是通讯问题:将Server上的通讯压力均衡转到各个Worker上。实现这一点后,可以进一步去Server,留Worker。

聚合梯度 + 下发梯度这一轮操作,称为AllReduce。
接下来我们介绍目前最通用的AllReduce方法:Ring-AllReduce。百度最先提出,非常有效地解决了数据并行中通讯负载不均的问题,使得DDP得以实现。

假设有4块GPU,每块GPU上的数据也对应被切成4份。AllReduce的最终目标,就是让每块GPU上的数据都变成箭头右边汇总的样子。

Ring-ALLReduce则分两大步骤实现该目标:Reduce-Scatter和All-Gather。

Reduce-Scatter:
定义网络拓扑关系,使得每个GPU只和其相邻的两块GPU通讯。每次发送对应位置的数据进行累加。每一次累加更新都形成一个拓扑环,因此被称为Ring。看到这觉得困惑不要紧,我们用图例把详细步骤画出来。



一次累加完毕后,蓝色位置的数据块被更新,被更新的数据块将成为下一次更新的起点,继续做累加操作。



3次更新之后,每块GPU上都有一块数据拥有了对应位置完整的聚合(图中红色)。此时,Reduce-Scatter阶段结束。

进入All-Gather阶段。目标是把红色块的数据广播到其余GPU对应的位置。

All-Gather
如名字里Gather所述的一样,这操作里依然按照“相邻GPU对应位置进行通讯”的原则,但对应位置数据不再做相加,而是直接替换。All-Gather以红色块作为起点。


以此类推,同样经过3轮迭代后,使得每块GPU上都汇总到了完整的数据,

手动推一次,加深理解。

Ring-AllReduce通讯量分析:
假设模型参数W的大小为
GPU个数为 。则梯度大小也为
,每个梯度块的大小为 对单卡GPU来说:
单卡总通讯量为 :
随着N的增大,可以近似为
全卡总通讯量为:

全卡总通讯量依然为
虽然通讯量相同,但搬运相同数据量的时间却不一定相同。
DDP把通讯量均衡负载到了每一时刻的每个Worker上,而DP仅让Server做勤劳的搬运工。
当越来越多的GPU分布在距离较远的机器上时,DP的通讯时间是会增加的。

但这并不说明参数服务器不能打(有很多文章将参数服务器当作old dinosaur来看)。事实上,参数服务器也提供了多Server方法,如下图:

请大家记住Ring-AllReduce的方法,因为在之后的ZeRO,Megatron-LM中,它将频繁地出现,是分布式训练系统中重要的算子。

4. 总结

  • 在DP中,每个GPU上都拷贝一份完整的模型,每个GPU上处理batch的一部分数据,所有GPU算出来的梯度进行累加后,再传回各GPU用于更新参数
  • DP多采用参数服务器这一编程框架,一般由若个计算Worker和1个梯度聚合Server组成。Server与每个Worker通讯,Worker间并不通讯。因此Server承担了系统所有的通讯压力。基于此DP常用于单机多卡场景。
  • 异步梯度更新是提升计算通讯比的一种方法,延迟更新的步数大小决定了模型的收敛速度。
  • Ring-AllReduce通过定义网络环拓扑的方式,将通讯压力均衡地分到每个GPU上,使得跨机器的数据并行(DDP)得以高效实现。
  • DP和DDP的总通讯量相同,但因负载不均的原因,DP需要耗费更多的时间搬运数据

标签:12,--,梯度,DDP,Worker,Server,通讯,GPU,DP
From: https://www.cnblogs.com/cavalier-chen/p/18535554

相关文章

  • SNI简介
    ServerNameIndication(SNI)是TLS(传输层安全协议)中的一个扩展,允许客户端在建立安全连接时,告诉服务器它要访问的具体主机名(域名)。这个信息通常在SSL/TLS握手过程中被传递,特别是在客户端和服务器之间交换加密信息之前。SNI解决了一个关键的问题:多个域名共享同一个IP......
  • 劫持微信聊天记录并分析还原 —— 合并解密后的数据库(三)
    本工具设计的初衷是用来获取微信账号的相关信息并解析PC版微信的数据库。程序以Python语言开发,可读取、解密、还原微信数据库并帮助用户查看聊天记录,还可以将其聊天记录导出为csv、html等格式用于AI训练,自动回复或备份等等作用。下面我们将深入探讨这个工具的各个方面及......
  • Python中find()的用法
    Python中find()函数是字符串对象的方法,只能在字符串上调用,用于检测查询字符串中的目标字符(串),并返回索引。有目标字符(串),则返回目标字符(串)第一次出现的索引(字符串中字符索引从左到右,从0开始计算);无目标字符(串),则返回-1。语法:str.find(string,start,end)str:待查询的字符串。stri......
  • 使用 Python 流式 Websocket 传输 Binance 订单更新 附代码
    对于从事加密货币行业的任何人来说,使用RESTapi从交易所查询实时数据并不总是最佳做法,原因有很多效率低下:每个查询都需要时间,并且会显着影响性能,尤其是对于高频策略。交易所施加的限制很容易被打破,例如Binance的硬限制为每分钟1200个请求权重您只能检索有限数量的历史数......
  • 无限申请的免费通配符证书
    获取不限量的免费通配符证书可以通过JoySSL平台实现。以下是详细的申请流程:第一步:注册JoySSL账号访问JoySSL官方网站:JoySSL官网点击“注册”按钮创建新账号。在注册过程中,需填写特定的注册码(230925)获取免费领取通配符证书的权限。点击:免费SSL证书快速申请 第二步:选择证书......
  • 怎么从入门到精通:《IDEA 问题库》常见问题及解决方案
    《IDEA问题库​》是一个非常广泛的话题,涉及到许多不同的问题和解决方案。以下是一些常见问题及解决方案: 报错:unableto establish loopbackconnection。问题:无法建立环回连接。解决方案:关闭防火墙。IDEA看不到编译后的target文件。问题:控制台提示编译成功,但左边......
  • 一年期的免费SSL证书服务
    随着互联网技术的快速发展,教育机构越来越多地依赖在线平台进行教学、管理和沟通。然而,随着网络攻击和数据泄露事件的频发,确保在线教育平台的安全性变得尤为重要。SSL证书可以为教育机构提供必要的数据保护和信任建立。JoySSL是一家专业的HTTPS安全方案服务商,专注于提供SSL/TLS......
  • 如何获取IP地址专用SSL证书
    随着网络安全意识的不断提高,越来越多的网站和服务开始采用SSL证书来加密数据传输,保护用户信息的安全。对于那些仅通过IP地址访问的服务来说,获取IP地址专用SSL证书就显得尤为重要。1.准备阶段确认公网IP地址确保您拥有一个可以在互联网上访问的公网IP地址。2.注册账号和......
  • 掌握 IntelliJ IDEA,开启高效编程之旅
    在当今的编程世界中,IntelliJIDEA已成为众多开发者的首选工具。它以其强大的功能和高效的特性,为开发者提供了一个卓越的编程环境。掌握IntelliJIDEA,无疑是开启高效编程之旅的关键一步。IntelliJIDEA拥有智能的代码提示和自动完成功能,这使得编程变得更加快捷和流畅。它能......
  • 第二周学习笔记Linux:Linux用户权限管理 |文本处理|shell基础
    用户权限命令以及ACL权限相关命令1.Linux安全模型资源分派:Authenticaton:登陆认证,验证用户身份Authorization:授权,不同的用户设置不同权限Accouting:审计,检查用户的时候行为即Linux的AAA认证,是针对网络设备的网络访问控制策略和安全模型1用户Linux是多系统用户,可以......