【笔记】PyTorch DDP 与 Ring-AllReduce

转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn]

 

文内若有错误,欢迎指出!


image.png

         今天我想跟大家分享的是一篇虽然有点老,但是很经典的文章,这是一个在分布式训练中会用到的一项技术, 实际上叫ringallreduce。 为什么要叫这个吗?因为现在很多框架,比如像pytorch他内部的分布式训练用到的就是这个。 所以知道他的原理的话也方便我们后面给他进行改进和优化。他是一项来自HPC的技术,但实际上现在分布式机器学习上的很多技术都是借鉴自HPC。下面的内容一部分来自论文,另一部分是来自网络。

        这里先介绍一点背景知识。
        以数据并行为例,在分布式训练中,需要将数据分布到不同的GPU上面进行训练,然后训练一个epoch后进行梯度更新。这里的更新可以分为同步和异步,为了方便理解,这里我画了几张图。 同步比较好理解,每个GPU在完成之后,需要等其他GPU也完成才能进行梯度更新。异步的话,就是说每个GPU可以独自进行梯度更新,并且在一定的时间点进行梯度交换,因此并不需要等其他的GPU也完成。而这两种方式中的梯度交换也引申出了很多研究内容。
        总的来说是基于两种方式,一种是使用参数服务器,另一种是通过reduce操作。 参数服务器的方式是通过指定一个服务器来协调计算每个GPU的梯度。他的缺点也很明显,随着GPU的增加,参数服务器的通信成为了瓶颈。 而reduce的方式是去除了参数服务器的存在,让每个GPU互相通信,他也分了map-reduce、all-reduce、ring-reduce、ring-allreduce等等。

https://zh.d2l.ai/chapter_computational-performance/parameterserver.html

image.png

        这里先介绍一下一些通信原语的概念,方便后面理解。 

image.png

        然后回到论文中来。
        在allreduce中用的比较多的是蝶形算法。在没有网络竞争的情况下,这个算法在延迟和带宽中都是最优的,但是事实上,这种通信模式会导致在许多当代集群中产生网络竞争,如广泛部署的SMP/多核集群,因为这些集群往往共享了一些网络资源。
在没有网络竞争的情况下,蝶形算法之所以在延迟和带宽方面都表现最优,主要有以下几个原因:
        1.对等通信模式: 蝶形算法采用了对等通信模式,即每个节点都与其他节点建立了直接连接。在没有网络竞争的情况下,节点之间的通信路径是独立的,不存在其他节点的干扰。这使得通信的延迟最小化,因为消息可以通过最短的路径尽快到达目标节点。
        2.逐级通信: 蝶形算法通过多个通信阶段逐级地将数据进行聚合。每个阶段中,节点与距离它最近的节点进行通信,然后逐渐扩展到更远的节点。这种逐级通信方式使得数据的聚合过程更加高效,减少了通信的次数和总延迟。
        3.负载平衡: 蝶形算法通过分阶段聚合数据,确保了在通信过程中负载的平衡。即使在节点之间的计算能力或带宽存在差异的情况下,蝶形算法仍能在通信过程中保持相对均衡的负载,最大限度地利用每个节点的计算资源。
        4.带宽优化: 蝶形算法在每个阶段的通信中只传输部分数据,而不是直接传输全部数据。这样可以减少单次通信的数据量,从而更好地利用带宽资源。在没有网络竞争的情况下,节点之间的通信通常能够占用整个可用带宽,因此通过优化单次通信的数据量,蝶形算法可以最大程度地提高带宽利用率。
        (蝶形全局求和的过程是,第一步将两个相邻的节点分作一组,互相通信他们的 sum,那么这个两节点小组的每个结点中的 sum 都是这个小组的局部和。第二步将四个节点分作一组,前半部分与后半部分相互通信,那么这个四节点小组的每个结点中的 sum 都是这个小组的局部和。循环进行这个步骤直到小组容量大于总进程数。)
        而作者提出的基于环的方式,声称可以在几乎所有当代集群中实现无争用通信,并且可以需要比较少的内存需求,也不需要2的幂个节点。但它也存在一些问题,比如只在带宽上有优化;而且可能存在精度问题。这个精度问题是指,由于并行计算中涉及到浮点数运算,不同节点上进行计算的结果可能受到舍入误差的影响,因为不同节点对于浮点数计算的精度可能会有差异。此外,Ring算法虽然在中等规模的运算中非常有优势,较小的传输数据量,无瓶颈,带宽完全利用起来。不过在大型规模集群运算中,巨大的服务器内数据,极长的Ring环,Ring的这种切分数据块的方式就不再占优势。

1.png

2.png

3.png

1.png

4.png

5.png

6.png

7.png

8.png

9.png

10.png

        这篇论文很长,而且数学公式较多,我们就不看数学证明,直接来看他的实现流程。不过他对流程介绍的也少,所以又从网上找了一些资料过来。
        所提的方法主要是结合了三种现有技术于一身。以下图为例,看一下他的执行流程。
        首先将数据分为 N 个块,每个GPU负责1个块。
        然后,第N个GPU发送第N个块,并接收第N-1个块。
        ……
        这么做有什么好处呢?
        每个 GPU 在Scatter Reduce阶段,接收 N-1 次数据,N 是 GPU 数量;每个 GPU 在allgather 阶段,接收 N-1 次数据;每个 GPU 每次发送 K/N 大小数据块,K 是总数据大小;所以,每个GPU的Data Transferred=2(N−1)*K/N = (2(N−1)/N)*K,随着 GPU 数量 N 增加,总传输量恒定!(我的理解是,随着N变大,1/N不断减小,总传输量趋近于固定值?)总传输量恒定意味着通信成本不随 GPU 数量增长而增长,也就是说我们系统拥有理论上的线性加速能力。
        allreduce的速度受到环中相邻GPU之间最慢(最低带宽)连接的限制。给定每个GPU的正确邻居选择,该算法是带宽最优的,并且是执行allreduce的最快算法(假设延迟成本与带宽相比可以忽略不计)。

image.png

        在Pytorch中有两种实现分布式数据并行训练的方式,分别是DP和DDP。DP由于只在主进程中管理多个任务和更新参数,因此其计算量和通讯量都很重,训练效率很低。
        现在普遍用的较多的是DDP的方式,简单来讲,DDP就是在每个计算节点上复制模型,并独立地生成梯度,然后在每次迭代中互相传递这些梯度并同步,以保持各节点模型的一致性。
        而在pytorch中的DDP实际就是使用了Ring-ALLReduce来实现AllReduce算法。
        DDP的执行流程大致如下:
        各个GPU首先进行环境初始化和模型的广播,使初始状态相同。然后初始化模型bucket和reducer。在训练阶段,通过采样获取数据,计算前向传播,然后进行反向传播和使用all-reduce进行梯度同步,最后完成参数的更新。
        这里说明了allreduce是在前向传播完成后用于梯度同步的,并且提到了一个新词 bucket。
        (模型参数以(大致)与给定模型 Model.parameters() 相反的顺序分配到存储桶中。使用相反顺序的原因是,DDP 期望梯度在向后传递期间大致按照该顺序准备就绪。)

image.png

        实际上,DDP中的设计是通过将全部模型参数划分为无数个小的bucket,然后在bucket级别建立allreduce。比如当所有进程中bucket0的梯度计算完成后就立刻开始通信,而此时bucket1中梯度还在计算。
        这样可以实现计算和通信过程的时间重叠。这种设计能够使得DDP的训练更高效,可以在参数量很大时,获得很好的加速效果。

        简单总结一下前面的内容。
        1、Pytorch中分布式训练用的比较多的是DDP;
        2、DDP中的Allreduce使用的是ring-allreduce,并且使用bucket来引入异步;
        3、Allreduce发生在前向传播后的梯度同步阶段,并且与反向传播计算重叠;
        4、Ring-allreduce优化了带宽,适用于中规模的集群,但其可能存在精度问题,切不适合大规模的集群;
        5、allreduce的速度受到环中相邻GPU之间最慢连接的限制;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/51235.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用html+javascript打造公文一键排版系统8:主送机关排版

公文一般在标题和正文之间还有主送机关,相关规定为: 主送机关 编排于标题下空一行位置,居左顶格,回行时仍顶格,最后一个机关名称后标全角冒号。如主送机关名称过多导致公文首页不能显示正文时,应当将主送机…

redis的并发安全问题:redis的事务VSLua脚本

redis为什么会发生并发安全问题? 在redis中,处理的数据都在内存中,数据操作效率极高,单线程的情况下,qps轻松破10w。反而在使用多线程时,为了保证线程安全,采用了一些同步机制,以及多…

20.3 HTML 表格

1. table表格 table标签是HTML中用来创建表格的元素. table标签通常包含以下子标签: - th标签: 表示表格的表头单元格(table header), 用于描述列的标题. - tr标签: 表示表格的行(table row). - td标签: 表示表格的单元格(table data), 通常位于tr标签内, 用于放置单元格中的…

C语言枚举与联合体详解

本篇文章带来枚举与联合体相关知识详细讲解! 如果您觉得文章不错,期待你的一键三连哦,你的鼓励是我创作的动力之源,让我们一起加油,一起奔跑,让我们顶峰相见!!! 目录 一…

InnoDB引擎底层逻辑讲解——架构之内存架构

1.InnoDB引擎架构 下图为InnoDB架构图,左侧为内存结构,右侧为磁盘结构。 2.InnoDB内存架构讲解 2.1 Buffer Pool缓冲池 2.2 Change Buffer更改缓冲区 2.3 Adaptive Hash Index自适应hash索引 查看自适应hash索引是否开启: show variable…

Modbus TCP/IP之异常响应

文章目录 一、异常响应二、异常码分析2.1 异常码0x012.2 异常码0x022.3 异常码0x032.4 异常码0x062.5 异常码0x04、0x05等 一、异常响应 对于查询报文,存在以下四种处理反馈: 正常接收,正常处理,返回正常响应报文;因为…

部署问题集合(十八)Windows环境下使用两个Tomcat

下载Tomcat Tomcat镜像下载地址:https://mirrors.cnnic.cn/apache/tomcat/进入如下地址:zip的是压缩版,exe是安装版 修改第二个Tomcat配置文件 第一步:编辑conf/server.xml文件,修改三个端口,有些版本改…

【Rust日报】2023-07-28 使用 Cargo-PGO 优化 Rust 程序

使用 Cargo-PGO 优化 Rust 程序 去年,作者致力于改进用于构建 Rust 编译器的配置文件引导优化 (PGO) 工作流程。在这样做的过程中,虽然 PGO 对于 Rust 工作得很好,但它并不像希望的那样易于使用和发现。这促使我创建了 cars-pgo,这…

【雕爷学编程】Arduino动手做(175)---机智云ESP8266开发板模块2

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&am…

【Vue3】递归组件

1. 递归组件mock数据 App.vue <template><div><Tree :data"data"></Tree></div> </template><script setup lang"ts"> import { reactive } from vue; import Tree from ./components/Tree.vue; interface Tr…

CentOS 8 上安装 Nginx

Nginx是一款高性能的开源Web服务器和反向代理服务器&#xff0c;以其轻量级和高效能而广受欢迎。在本教程中&#xff0c;我们将学习在 CentOS 8 操作系统上安装和配置 Nginx。 步骤 1&#xff1a;更新系统 在安装任何软件之前&#xff0c;让我们先更新系统的软件包列表和已安…

读发布!设计与部署稳定的分布式系统(第2版)笔记26_安全性上

1. 安全问题 1.1. 系统违规并不总是涉及数据获取&#xff0c;有时会出现植入假数据&#xff0c;例如假身份或假运输文件 1.2. 必须在整个开发过程中持续地把安全内建到系统里&#xff0c;而不是把安全像胡椒面那样在出锅前才撒到系统上 2. OWASP 2.1. Open Web Application…

Godot 4 源码分析 - 动态导入图片文件

用Godot 4尝试编一个电子书软件&#xff0c;初步效果已经出来&#xff0c;并且通过管道通信接口可以获取、设置属性、调用函数&#xff0c;貌似能处理各种事宜了。 其实不然&#xff0c;外因通过内因起作用&#xff0c;如果没把里面搞明白&#xff0c;功能没有开放出来&#x…

【SpringCloud Alibaba】(六)使用 Sentinel 实现服务限流与容错

今天&#xff0c;我们就使用 Sentinel 实现接口的限流&#xff0c;并使用 Feign 整合 Sentinel 实现服务容错的功能&#xff0c;让我们体验下微服务使用了服务容错功能的效果。 因为内容仅仅围绕着 SpringCloud Alibaba技术栈展开&#xff0c;所以&#xff0c;这里我们使用的服…

详解Mybatis之分页插件【PageHelper】

编译软件&#xff1a;IntelliJ IDEA 2019.2.4 x64 操作系统&#xff1a;win10 x64 位 家庭版 Maven版本&#xff1a;apache-maven-3.6.3 Mybatis版本&#xff1a;3.5.6 文章目录 一. 什么是分页&#xff1f;二. 为什么使用分页&#xff1f;三. 如何设计一个Page类&#xff08;分…

【玩转python系列】【小白必看】使用Python爬虫技术获取代理IP并保存到文件中

文章目录 前言导入依赖库打开文件准备写入数据循环爬取多个页面完整代码运行效果结束语 前言 这篇文章介绍了如何使用 Python 爬虫技术获取代理IP并保存到文件中。通过使用第三方库 requests 发送HTTP请求&#xff0c;并使用 lxml 库解析HTML&#xff0c;我们可以从多个网页上…

《Kali渗透基础》11. 无线渗透(一)

kali渗透 1&#xff1a;无线技术特点2&#xff1a;IEEE 802.11 标准2.1&#xff1a;无线网络分层2.2&#xff1a;IEEE2.3&#xff1a;日常使用标准2.3.1&#xff1a;802.112.3.2&#xff1a;802.11b2.3.3&#xff1a;802.11a2.3.4&#xff1a;802.11g2.3.5&#xff1a;802.11n …

python的包管理器pip安装经常失败的解决办法:修改pip镜像源

pip 常用的国内镜像源&#xff1a; https://pypi.tuna.tsinghua.edu.cn/simple/ // 清华 http://mirrors.aliyun.com/pypi/simple/ // 阿里云 https://pypi.mirrors.ustc.edu.cn/simple/ // 中国科技大学 http://pypi.hustunique.com/ // 华中理…

stm32通过ESP8266接入原子云

1. ESP8266模块需要烧录原子云固件&#xff0c;此原子云固件和正常的ESP8266固件相比添加了ATATKCLDSTA 和 ATATKCLDCLS 这两条指令&#xff1a; 2. 原子云账号注册及设备建立 设备管理-新增设备-ESP8266 新建设备后新建分组&#xff0c;将设备加入到此分组中&#xff1a; 至此…

【算法基础:贪心】6. 贪心

文章目录 区间问题905. 区间选点&#xff08;排序 贪心&#xff09;908. 最大不相交区间数量&#xff08;排序 贪心&#xff09;906. 区间分组&#xff08;排序 优先队列 贪心&#xff09;⭐907. 区间覆盖&#xff08;排序 贪心&#xff09; Huffman树148. 合并果子&#…