https://www.bilibili.com/video/BV1jz421h7CA/?spm_id_from=333.788&vd_source=d591262dc9ce1bba22682d1cba1ca930
通信特性 | NCCL | HCCL |
---|---|---|
通信算法 | ring/mesh + ring/Hav-Doub/Pair-Wise, etc. | ring + Tree ring, etc. |
通信链路 | 灵渠总线/PCIE | NVLink / NVSwitch / GPU-Direct / PCIE |
通信操作 | allreduce、broadcast、reduce、reduce | scatter、allgather、all2all、send、recv |
通信域管理 | 全局通信域、子通信域、基于全局/子通信域配置算法 | 全局通信域、子通信域、自定义通信域配置算法 |
通信算法: XCCL 集合通信库实现流量统一规划,满足复杂物理拓扑中流量有序交换,最大化集群通信性能;
通信原语/操作:提供不同 NPU 硬件上进程间的通信方式或者通信 API,即建立在通信算法上层概念,通过不同的通信算法来实现;
计算与通讯解耦
神经网络训练过程中,每一层神经网络都会计算出一个梯度Grad,如果反向传播得到一个梯度,马上调用集合通信AllReduce进行梯度规约,在集群中将计算与通信同步串行,那么集群利用率(MFU)性能就很差。
如GPT3 176B有96层Transformers对应Grad个数96×112,设计算梯度1ms,通信500ms,每次时间50Ims,总体需要501×96×12=577152ms,近5777s完成一次梯度迭代。
将计算与通信解耦,计算的归计算,通信的归通信,通过性能优化策略减少通信的次数 (分布式加速库:解耦计算和通信,分别提供计算、通信、内存、并行策略的优化方案。)
- 提升集群训练性能(模型利用率 MFU/算力利用率 MFU )
- 避免总信与计算假死锁(计算耗时长,通信长期等待)
xCCL在AI系统位置
通讯同步
AI对通讯的算法需求
传统服务器配备一张网卡用于节点间通信,为支持AI配置多个 GPU。Al 训练需要 GPU 间梯度同步多 GPU 并发访问网络,网卡成为系统瓶颈。PCle 链路带宽分配与路径长度密切相关,长路径获得带宽分配较低,跨 Socket 通信问题就变得严重。
网络架构主要解决 AI 训练中同步通信导致短板效应。
- 拥塞控制算法:对两个碰撞流进行限速,使其尽快达到均分物理带宽的目的,不能解决 AI训练集群通信效率。
- AI业务通信的同步性,每个通信最终性能决定于最慢的连接。均分带宽意味着事务完成时间的成倍提升,严重影响AI通信性能。
不同时期的需求
- 单一化业务,整个 AI系统只为大模型(LLM、LMM等)或者搜广推服务,几乎没有其他业务的复用性
- 用于超大规农的模型(百/千亿参数量)的训练、推理,L0 基础大模型算法研究的探索
- 训练大模型走极致性能优化路线 vs 虚拟化云服务和 AI 通用算力服务化走性价比路线;
大模型时代
-
大模型处于快速发展期,当前基于 Transformer 的模型结构固定,模型通信流量相对明确
-
面对超长序列、MOE 结构、低精度数据格式 FP8 等在通信流量仍然存在挑战和不确定性
并行模式 通信产生原理 通信操作 数据并行(纯数据并行) 反向梯度更新时需要进行 all reduce 将梯度聚合 All reduce ZeRO1(优化器状态并行) 只能更新部分权重,需要多执行一次 all gather 将权重聚合 All reduce
All GatherZeRO2(梯度并行) 每张卡只需要 reduce 部分梯度,更新部分权重后一样需要 all gather 将权重聚合 Reduce Scatter
All GatherZeRO3(权重并行) 每张卡只需要 reduce 部分梯度,更新部分权重,但是前向和反向时同样需要 all gather 将权重聚合 Reduce Scatter
All GatherPipeline(层间并行) 前向和反向时需要各 rank 传递激活值 Send
Recv (点对点通讯)并行方式 通信操作 总通信量 单次通信量 算法 Rank 间关系 数据并行 张量并行 All Reduce GB 25MB, PyTorch 可配置参数缓存 Bucket 大小 Ring 同序号卡通信 HD 同序号卡通信 Tree 同序号卡通信 MoE 并行 All2All GB 按 Token 发送,KB 级别 Pair-wise 夸序号卡通信 分层通信 同序号卡通信 流水并行 Send/Recv MB 按 BSH 发送,MB 级别 P2P 夸序号卡通信
集合通信难点
-
需要在固定网络互联结构(网络拓扑 Topology)约束下进行高效通信;
- 集合通信算法与物理网络互联结构强相关,需要充分发挥网络通信效率;
- 在效率与成本、带宽与时延间进行合理取舍。
信息同步
分布式 同步并行
- 必须等全部工作节点完成了本次通信之后才能继续下一轮本地计算
- 本地计算和通信同步严格顺序化,能够容易地保证并行的执行逻辑和串行相同
- 本地计算更早的工作节点需要等待其它工作节点处理,造成了计算硬件的浪费
分布式 异步并行
半同步
- 通过动态限制进度推进范围,有限定的宽松同步障的通信协调并行
- 跟踪节点进度并维护最慢节点,保证计算最快和最慢节点差距在一个预定的范围内
不等太慢的,以多数worker可以接受的时间完成同步
环同步 Ring Synchronization
GPU之间使用NVLink连接,每个GPU之间可以互相访问到,环有不同形状
最常见实现算法基于 Ring All Reduce,NVIDIA NCCLv1.x通信库采用该算法,每次跟相邻的两个节点进行通信,每次通信数据总量的 I/N
适用拓扑
- Star、Tree等小规模集群; 通信步骤: 2×(N - 1) Step;
优点
- 实现简单, 能充分利用每个节点的上行和下行带宽;
缺点
- 通信延迟随着节点数线性增加, 特别是对于小包延迟比较明显; Ring 大, Ring All Reduce 效率也会变得很低。
Ring 算法执行步骤
- Ring 算法将进程组织成一个逻辑环 (Ring),数据沿着环流动。该算法执行 2(N - 1) 步,每一步进程 r 向其邻居 (r + 1)%P 发送 P/N 的数据,并接收来自进程 (r - 1)%N 的数据,聚合接收到数据, 每个进程发送数据总量为 2P(N - 1)/N。
- 假设 N 为进程数, P 为需要聚合的总数据量,数据被分成 N 块, 一块为 P/N。
ring all reduce 算法 ,遍历两次所有GPU完成一次通信
-
Scatter-reduce,遍历完一个环每个GPU都有全数据的一个备份
-
all-gather 广播数据,遍历一次所有GPU都拥有所有数据的备份
Halving-Doubling 算法
基本介绍
- 每次选择节点距离倍增的节点进行通信, 每次通信量倍减 (或倍增),访问步长按指数衰减
- 如异步HCCL, 阿里ACCL均采用该算法
适用拓扑
- Fat-Tree 等; 通信步骤: log2 N
优点
- 通信步骤较少, 只有 2×log2 N 次 (N 为参与通信 Rank 数), 通信即可完成, 有更低延迟,并且可以同时并发访问其他XPU
缺点
- 固定并行算法 (如 TP=8 存在并性能劣化严重), 每一个步骤相互通信 Rank 均不相同, 链接回切换会带来额外开销
组网拓扑不同,并行配置不同,需要理解组网方式才能设置更好的并行策略。
算法 | 步骤数 | 发送数据量 | 优缺点对比 |
---|---|---|---|
Ring | 2×(N-1) | 2P(N-1)/N | 发送数据量少,聚合大数据性能好; 用于小规模节点数时优选; 每次通信域链接不用改变,较为固定; 连接方式更加稳定; |
Halving-Doubling | 2×log2 N | 2P(N-1)/N | 步骤数和发送数据量少,聚合大数据性能好; 用于大规模节点数时较优; 固定网络拓扑上可以做到全局无拥; 通信链接在变化,网络拓扑未知下容易遇到拥塞; |
通讯实现
https://github.com/chenzomi12/DeepLearningSystem/blob/main/061FW_AICluster/03.communication.pdf
通信实现方式
计算机网络通信中最重要两个衡量指标主要是 带宽和 延迟,分布式训练中需要传输大量的网络模型参数
CPU共享内存,PCIe插槽(CPU GPU之间),NVLink(GPU之间)
通信实现方式
点对点通信 Send/Recv
-
TCP/IP
-
RDMA
集合式通信 AII-Reduce
- TCP/IP
- NCCL
集合式通信原语
一对多 Scatter/ Broadcast
-
Broadcast
某个节点想把自身的数据发送到集群中的其他节点,那么就可以使用广播Broadcast的操作。
单个 rank 把自身的数据发送到集群中的其他 rank
用法
- 网络参数 Init Weight 的初始化
- 数据并行 DP 对数据分发初始化
- AlIReduce里的 broadcast + reduce组合里的 broadcast 操作
-
Scatter
将主节点的数据进行划分并散布至其他指定的节点。
将主节点的数据进行划分并散布至其他指定的 Rank
用法
- Reduce Scatter 组合里的 Scatter操作
- 流水并行里初始化时将模型 Scatter 到不同 Rank上
多对一 Reduce/Gather
-
Reduce
把多个 Rank 的数据规约运算到一个 Rank 上。 Reduce 称为规约运算,是一系列简单运算操作的统称。细分可以包括:SUM、MIN、MAX、PROD、LOR等类型的规约操作。
用法
-
AllReduce里的Broadcast,Reduce组合 Reduce操作
-
Reduce Scatter 组合里的 Reduce操作
-
大模型训练权重 CKPT 保存
-
-
Gather
将多个 Sender 上的数据收集到单个节点上,Gather 可以理解为反向的 Scatter。
对很多并行算法很有用,比如并行的排序和搜索
用法
- Gather 相对用得比较少,AIl Gather会在张量并行 TP 用得较多
多对多 All Reduce/ All Gather
-
AII Reduce则是在所有的节点上都应用同样的Reduce操作。AIl Reduce操作可通过Reduce + Broadcast 或者 Reduce-Scatter +AlI-Gather 操作作完成
用法
- 在专家并行、张量并行、序列并行中大量地使用 AII Reduce 对权重和梯度参数进行聚合。
- 数据并行 DP 各种通信拓扑结构比如Ring AlReduce、Tree AlReduce里的 AllReduce 操作;
-
两种实现方式差异 使用Reduce-Scatter +AlI-Gather
- Reduce + Broadcast
- 在Reduce+broadcast里,Reduce先将N张NPU梯度reduce sum到 master RankNPU0 上再通过 broadcast 将 NPU0 中平均梯度复制到其他 NPU:
- 通信数据: N 个 Rank 数据 reduce sum 到一个 Rank.
- e.g. 假设为一个节点 8 个 Rank, 每个 Rank 携带 100MB, 8 个 Rank 800MB, 导致 XPU0 在频繁发收数据, 剩余 Rank 空闲, 集群效率低;
- 通信带宽: NPU0 网络带宽会成为瓶颈, 所有 Rank 数据只能通过 NPU0 进行 reduce 和 broadcast, 数据量 较大 则 NPU0 成为瓶颈.
- e.g. Tensor Parallelism;
- 互联拓扑: NPU 不一定两两全部互联, N 个 Rank 每次 Reduce 或 broadcast, 受限网络互联实现, 最终需要采用 ring/tree 策略进行 reduce 或 broadcast, 集群效率低.
- **Reduce-Scatter +AlI-Gather **每个 NPU 都会从前向接受数据,并发送数据给后向,算法主要分为
- Reduce Scatter: 先 scatter 拆分数据块再进行 reduce,每块 NPU 都会包括完整融合的同维特度。
- Gather: 进行全局 Gather 同步,最后所有 NPU 都会得到完整的权重。
- 充分考虑到 NPU 上梯度 tensor 的情况
- e.g. 一个梯度 400MB, reduce scatter 将其分成 NPU 个数份, 假设为 8个, 即每份 50MB, 从而减少单个 NPU 计算量及节约带宽
- Reduce Scatter 通过将数据拆分成小块,同时进行 Reduce Scatter, 从而提高计算效率并减少通信时间, 进而提高 All Reduce 效率。
- Reduce + Broadcast
-
All Gather会收集所有数据到所有节点上。All Gather = Gather + Broadcast。发送多个元素到多个节点很有用即在多对多通信模式的场景
用法
- 在专家并行、张量并行、序列并行中大量地使用 AII Gather 对权重和梯度参数进行聚合。
- 模型并行里前向计算里的参数全同需要用 AIl Gather 把模型并行步,里将切分到不同的 GPU上的参数全同步到一张 GPU 上才能进行前向计算。
-
Reduce Scatter操作会将个节点的输入先进行求和,然后在第0维度按卡数切分,将数据分发到对应的卡上。
**用法 ** 可应用于数据并行 DP 和模型并行MP
- 数据并行 AlReduce 里的 Reduce Scatter,AlGather 组合里的 Reduce Scatter操作
- 模型并行前向 AIIGather 后的反向计算 Reduce Scatter
-
ALL to all 将节点i的发送缓冲区中的第j块数据发送给节点j,节点j将接收到的来自节点的数据块放在自身接收缓冲区的第i块位置
对All-Gather的扩展,但不同的节点向某一节点收集到的数据是不同的。
**用法 **
- 应用于模型并行中的 TP/SP/EP
- 模型并行里的矩阵转置
- DP 到模型并行的矩阵转置
通信域 Rank
MPI 通信在通信域控制和维护下进行,所有 MPI 通信任务都直接或间接用到通信域这一参数,对通信域的重组和划分可以方便实现任务的划分
通信域(communicator)
是一个综合的通信概念。其包括上下文(context),进程组(group),虚拟处理器拓扑(topology)。其中进程组是比较重要的概念,表示通信域中所有进程的集合。一个通信域对应一个进程组。
什么是进程与进程组
- 每个进程客观上唯一的(一个进程对应一个 Process lD)
- 同一个进程可以属于多个进程组(每个进程在不同进程组中有个各自 RankID)
- 同一个进程可以属于不同的进程组(PID),因此也可以属于不同的通信域
通信域与进程之间的关系
-
同一个进程,可以属于不同通信域
-
同一个进程,可以同时参与不同通信域的通信,互不干扰。
group: 进程组,一个分布式任务对应一个进程组,一般就是所有卡都在一个组里
world size:全局的并行数,一般情况下等于总的卡数 也有可能一个进程控制几张卡
node: 节点,可以是一台机器,或者一个容器,节点内包含多个GPU
rank(global rank): 整个分布式训练任务内的进程序号
local rank:每个node内部的相对进程序号
2机4卡分布式训练 node=2,world size=4,每个进程占用两个GPU
分布式训练集群
why
训练数据规模和单步计算量和模型相关相对固定,
- \[\mathrm{训练耗时}\;=\;\mathrm{训练数据规模}\;\ast\;\mathrm{单步计算量}/\mathrm{计算速率}\]
- \[\mathrm{计算速率}\;=\;\mathrm{单设备计算速率}(\mathrm{摩尔定律或者算法优化})\ast\mathrm{设备数}\;\ast\;\mathrm{多设备并行效率}(\mathrm{加速比})\]
但是可以提高计算速率
- 混合精度,算子融合,梯度累加 (单设备计算速率)
- 服务器架构,通信拓扑优化 (设备数)
- 数据并行 模型并行 流水并行 (加速比)
服务器架构
参数服务器
都是这三步:计算损失和梯度,梯度聚合, 参数更新并参数重新广播
- CPU作为参数服务器,CPU下发网络模型和参数给GPU卡计算损失和梯度,在CPU做梯度聚合,把所有参数更新到GPU卡
- GPU0作为参数服务器,CPU下发指令让每个GPU计算损失和梯度,在GPU0上梯度聚合,把所有参数更新到GPU卡
- 常用是第三种,CPU下发指令让每个GPU计算损失和梯度,通过通讯分布式并行梯度聚合,把所有参数更新到GPU卡
分布式训练系统
https://github.com/chenzomi12/DeepLearningSystem/blob/main/061FW_AICluster/05.system.pdf
硬件
软件
-
分布式用户接口
用户通过接口,实现模型的分布化
-
执行单节点训练
产生本地执行的逻辑
-
通信协调
实现多节点之间的通信协调
意义:提供易于使用,高效率的分布式训练
PyTorch 分布式训练通信依赖torch.distributed模块实现
- Point-2-Point 供send和recv 语义,用于任务间通信
- Collective Communication:提供scatter/broadcast/gather/reduce/all reduce/all gather 通信操作
不同 backend 在提供的通信语义上具有一定的差异性
Tensorflow:模型并行主要是计算图分布式切分,算子通信。数据并行的数据包括(模型的参数、梯度等)
Pytorch: 支持点对点(同步异步通信),集合通信 ,非常灵活。
组网互联
- 传统组网 传统方案中(<2018),GPU 互联采用 PCle,服务器节点间互联采用以太网 Ethernet.
- 现在大模型数据、参数量极大。服务器不同计算节点间,对超高带宽、超低延迟和超高可靠性的互联技术要求高。
目前趋势
- Die间,多芯粒互联技术和合封技术正加速崛起。(XPU 内部)
- 片间,由 PCle 向多节点无损网络演进 (XPU 之间,节点之间)
- 集群间,互联方式从 TCP/IP 向 RDMA 架构转变
DIE间
SoC 架构转向 Chilet 异构
大模型对算力需求持续增长,在工艺发展较慢情况下,继续提升算力,A芯片从传统 SoC 架构转向 Chiplet 异构。除了芯粒数量不断增加,为有效发挥片内算力,也引发芯粒间互联挑战。
随芯片系统变得越来越复杂,不同功能单元(芯粒),产生大量数据流需要专用的互联接口来实现数据的传输和调度。这种专用互联接口简称为 Die2Die接口,负责在不同芯粒间传输数据,协调调度数据流,确保芯片系统高效运行。
IO DIE
- 专用互联芯粒,作为数据传输和调度核心,整合存储单元。Die2Die 接口和多种高速接口,通过自定义算法实现数据流和信息流的分发调度IO Die
- 通常适用于 2.5D Chiplet 芯片架构。
Base Die
- 当芯片性能继续增高,平面维度也很难满足 Die间互次需求。于是,互联方式逐渐从 2D to 3D 垂直迭代。
- 芯片行业开始基于芯粒 3D 堆叠方式,进一步提升芯片算力密度
- 集成 die2die 3D 接口,Cache 等模块,实现更快垂直互联,减少片内存储延迟和功耗.
NPU之间互联
一般架构
节点内 NPU 间互联
- PCle
- 共享内存
- 私有协议直连(NVlink 多节点无损网络协议)
发展趋势
-
CPU host (DDR),NPU Devices(HBM ),其各自有本地内存;
- 在 AI集群下,NPU 之间需要高速交换数据,为了保证通信性能NPU 之间设计专用高速互联通道
- AI计算的发展逐渐让 H-D 间由传统 PCle 向多节点无损网络演进;
NVLink
NVLink 设计目的,突破 PCle屏障,实现 GPU2GPU 及 CPU2GPU 片间高效数据交互。NVLink 由软件协议组成,通过 PC 板上多对导线实现,让 GPU2GPU 间高速度收发显存数据。
通过 NVLink GPU 间互联链路采用点对点私有互联协议,绕开 PCle 总线直连多个 GPU 并组建成 GPU 计算阵列。
NVSwitch
NVSwitch 基于 NVLink 组成可实现多节点 GPU 直联。不但绕开服务器内 PCle 互联,还绕开服务器间以太网通讯,降低GPU 通讯延迟,增强 AI计算中数据同步效率。
NVSwitch 基于无损数据交间互联网络,并非一颗简单芯,而是一套复杂系统,需要系统的片间互联协议算法和匹配产品
NVIDIA DGX
NVIDIA DGX其系统中8个 GPU 上 NVLink 通过 NVSwitch 芯片共享快速、直接连接,共同组成了一个 NVLink 网络,使服务器中的每一个 GPU 都成为 AI 集群中一部分。
应该根据具体的服务器的形态和服务器的网络的拓扑去配置对应的分布式并行的策略或者去写对应的一个集合通讯的算法
片内互联挑战与技术壁垒
-
片间接口复杂性;
如何利用高速片间接口,使其满足芯片直连需求,又可完成设备交换功能
-
交换算法扩展性:
如何利用已有计算体系实现 AI集群内高速数据传输需求
-
网络协议适配性
如何构建覆盖 CPU、NPU、片内存储领域的网络协议,无缝适配已有硬件设备或上层软件系统。
节点间互联
计算节点间
- 通信TCP/IP 网络
- RDMA 网络
- InfiniBand
- ROCEI
- iWARP
万卡集群已经成为大模型训练标配,面对大模型规模庞大的数据交互,传统TCP/P 协议逐渐被RDMA (Remote Direct Memory Access) 技术全称远程直接内存访问技术取代。解决网络传输中服务器端数据处理的延迟而产生的。
没有经过OS层,直接从总线去获取device 的一个具体内存,然后通过网络进行传输
InfiniBand (NVIDIA 私有) | iWARP | RoCE 性价比 | |
---|---|---|---|
性能 | 最好 | 稍差(受TCP影响) | 与 InfiniBand 相当 |
成本 | 高 | 中 | 低 |
稳定性 | 好 | 差 | 较好 |
交换机 | IB交换机 | 以太网交换机 | 以太网交换机(可利用现有的) |
RDMA通过网络将数据从一个系统快速移动到另一个系统中,而不需要消耗计算机的处理能力。它消除了内存拷贝和上下文切换的开销,因而能解放内存带宽和 CPU 周期用于提升系统的整体性能。阿里RDMA
先看看最常见的 Kernel TCP,其收数据的流程主要要经过以下阶段:
- 网卡驱动从内核分配 dma buffer,填入收队列
- 网卡收到数据包,发起 DMA,写入收队列中的 dma buffer
- 网卡产生中断
- 网卡驱动查看收队列,取出 dma buffer,交给协议栈
- 协议栈处理报文
- 操作系统通知用户态程序有可读事件
- 用户态程序准备 buffer,发起系统调用
- 内核拷贝数据至用户态程序的 buffer 中
- 系统调用结束
可以发现,上述流程有三次上下文切换(中断上下文切换、用户态与内核态上下文切换),有一次内存拷贝。虽然内核有一些优化手段,比如通过 NAPI 机制减少中断数量,但是在高性能场景下, Kernel TCP 的延迟和吞吐的表现依然不佳。
使用 RDMA 技术后,收数据的主要流程变为(以send/recv为例):
- 用户态程序分配 buffer,填入收队列
- 网卡收到数据包,发起 DMA,写入收队列中的 buffer
- 网卡产生完成事件(可以不产生中断)
- 用户态程序 polling 完成事件
- 用户态程序处理 buffer
上述流程没有上下文切换,没有数据拷贝,没有协议栈的处理逻辑(卸载到了RDMA网卡内),也没有内核的参与。CPU 可以专注处理数据和业务逻辑,不用花大量的 cycles 去处理协议栈和内存拷贝。