怎么做电影流量网站吗,长沙城乡建设部网站首页,单页网站多钱,cms 排名 wordpress转载请注明出处#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 文内若有错误#xff0c;欢迎指出#xff01; 今天我想跟大家分享的是一篇虽然有点老#xff0c;但是很经典的文章#xff0c;这是一个在分布式训练中会用到的一项技术#xff0c; 实际上叫ringallreduce。 … 转载请注明出处小锋学长生活大爆炸[xfxuezhang.cn] 文内若有错误欢迎指出 今天我想跟大家分享的是一篇虽然有点老但是很经典的文章这是一个在分布式训练中会用到的一项技术 实际上叫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 这里先介绍一下一些通信原语的概念方便后面理解。 然后回到论文中来。 在allreduce中用的比较多的是蝶形算法。在没有网络竞争的情况下这个算法在延迟和带宽中都是最优的但是事实上这种通信模式会导致在许多当代集群中产生网络竞争如广泛部署的SMP/多核集群因为这些集群往往共享了一些网络资源。 在没有网络竞争的情况下蝶形算法之所以在延迟和带宽方面都表现最优主要有以下几个原因 1.对等通信模式 蝶形算法采用了对等通信模式即每个节点都与其他节点建立了直接连接。在没有网络竞争的情况下节点之间的通信路径是独立的不存在其他节点的干扰。这使得通信的延迟最小化因为消息可以通过最短的路径尽快到达目标节点。 2.逐级通信 蝶形算法通过多个通信阶段逐级地将数据进行聚合。每个阶段中节点与距离它最近的节点进行通信然后逐渐扩展到更远的节点。这种逐级通信方式使得数据的聚合过程更加高效减少了通信的次数和总延迟。 3.负载平衡 蝶形算法通过分阶段聚合数据确保了在通信过程中负载的平衡。即使在节点之间的计算能力或带宽存在差异的情况下蝶形算法仍能在通信过程中保持相对均衡的负载最大限度地利用每个节点的计算资源。 4.带宽优化 蝶形算法在每个阶段的通信中只传输部分数据而不是直接传输全部数据。这样可以减少单次通信的数据量从而更好地利用带宽资源。在没有网络竞争的情况下节点之间的通信通常能够占用整个可用带宽因此通过优化单次通信的数据量蝶形算法可以最大程度地提高带宽利用率。 蝶形全局求和的过程是第一步将两个相邻的节点分作一组互相通信他们的 sum那么这个两节点小组的每个结点中的 sum 都是这个小组的局部和。第二步将四个节点分作一组前半部分与后半部分相互通信那么这个四节点小组的每个结点中的 sum 都是这个小组的局部和。循环进行这个步骤直到小组容量大于总进程数。 而作者提出的基于环的方式声称可以在几乎所有当代集群中实现无争用通信并且可以需要比较少的内存需求也不需要2的幂个节点。但它也存在一些问题比如只在带宽上有优化而且可能存在精度问题。这个精度问题是指由于并行计算中涉及到浮点数运算不同节点上进行计算的结果可能受到舍入误差的影响因为不同节点对于浮点数计算的精度可能会有差异。此外Ring算法虽然在中等规模的运算中非常有优势较小的传输数据量无瓶颈带宽完全利用起来。不过在大型规模集群运算中巨大的服务器内数据极长的Ring环Ring的这种切分数据块的方式就不再占优势。 这篇论文很长而且数学公式较多我们就不看数学证明直接来看他的实现流程。不过他对流程介绍的也少所以又从网上找了一些资料过来。 所提的方法主要是结合了三种现有技术于一身。以下图为例看一下他的执行流程。 首先将数据分为 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 Transferred2(N−1)*K/N (2(N−1)/N)*K随着 GPU 数量 N 增加总传输量恒定我的理解是随着N变大1/N不断减小总传输量趋近于固定值总传输量恒定意味着通信成本不随 GPU 数量增长而增长也就是说我们系统拥有理论上的线性加速能力。 allreduce的速度受到环中相邻GPU之间最慢最低带宽连接的限制。给定每个GPU的正确邻居选择该算法是带宽最优的并且是执行allreduce的最快算法假设延迟成本与带宽相比可以忽略不计。 在Pytorch中有两种实现分布式数据并行训练的方式分别是DP和DDP。DP由于只在主进程中管理多个任务和更新参数因此其计算量和通讯量都很重训练效率很低。 现在普遍用的较多的是DDP的方式简单来讲DDP就是在每个计算节点上复制模型并独立地生成梯度然后在每次迭代中互相传递这些梯度并同步以保持各节点模型的一致性。 而在pytorch中的DDP实际就是使用了Ring-ALLReduce来实现AllReduce算法。 DDP的执行流程大致如下 各个GPU首先进行环境初始化和模型的广播使初始状态相同。然后初始化模型bucket和reducer。在训练阶段通过采样获取数据计算前向传播然后进行反向传播和使用all-reduce进行梯度同步最后完成参数的更新。 这里说明了allreduce是在前向传播完成后用于梯度同步的并且提到了一个新词 bucket。 模型参数以大致与给定模型 Model.parameters() 相反的顺序分配到存储桶中。使用相反顺序的原因是DDP 期望梯度在向后传递期间大致按照该顺序准备就绪。 实际上DDP中的设计是通过将全部模型参数划分为无数个小的bucket然后在bucket级别建立allreduce。比如当所有进程中bucket0的梯度计算完成后就立刻开始通信而此时bucket1中梯度还在计算。 这样可以实现计算和通信过程的时间重叠。这种设计能够使得DDP的训练更高效可以在参数量很大时获得很好的加速效果。 简单总结一下前面的内容。 1、Pytorch中分布式训练用的比较多的是DDP 2、DDP中的Allreduce使用的是ring-allreduce并且使用bucket来引入异步 3、Allreduce发生在前向传播后的梯度同步阶段并且与反向传播计算重叠 4、Ring-allreduce优化了带宽适用于中规模的集群但其可能存在精度问题切不适合大规模的集群 5、allreduce的速度受到环中相邻GPU之间最慢连接的限制