6.5-分布式训练的通信协调

通信协调在分布式训练的整体性能中起到了举足轻重的作用。众多软硬件技术在深度学的发展过程中被提出和应用。本节以 GPU为例,介绍目前深度学习中所采用的主流通信技术。

按照方式,通信可分为:机器内通信和机器间通信。前者包含:共享内存、GPUDirect P2P over PCIe、GPUDirect P2P over NVLink [8],而后者包含:TCP/IP网络、 RDMA网络和GPUDirect RDMA网络。

6.5.1 通信协调的硬件

图示了两种常见的GPU硬件形式(上)以及连接方式(下):NVLink (300GB/s) vs. PCIe 4.0 (32GB/s)[1]。二者的链路带宽差距高达约10倍。众多实际训练表明,高带宽链路极大地提高了并行训练的总体性能。因此,我们可以看到无论是节点内的多设备以及节点间的网络,链路带宽近些年都取得了大幅提升。

除了NVIDIA之外,其它加速器硬件厂商也提出了类似的高速数据链路。下图分别是AMD和隧原科技[6]设计的加速器互联硬件。

而依据GPU的硬件互联结构,可以绘制出互联拓扑。目前的互联结构存在多种不同的拓扑。如下图所示,最为常见的 PCI only 连结仅使用标准的PCI/PCIe接口将加速卡与系统的其它部分连接起来。受限于PCIe的带宽限制(例如PCIe 4.0 x16 单向传输带宽为 31.508 GB/s)以及树形的连接拓扑,PCIe在设备互联上具有天然的障碍。因此,在GPU高性能计算中常配备专用高速链路实现高带宽的卡间互联,包括DGX-1/P9中的卡间直连,以及DGX-2/3中采用交换机形式的NVSwitch。

除了通信拓扑,通信的协议也在不断迭代。如下图的GPUDirect P2P[7],GPU可以直接访问另一GPU的显存,无需CPU介入或系统内存中转,从而实现“零拷贝(zero-copy)”。 开启这项功能的对于GPU以及之间的连接方式等硬件条件均有要求:GPU属于Tesla / Quadra 专业级别,并且GPU之间通过NVLink互联或者属于同一PCIe root(例如,不允许跨NUMA node)。

而在跨节点网络中也有类似的协议GPUDirect RDMA [8],实现了GPU中的数据通过网络直接发送,无需系统内存中转,也实现了“零拷贝(zero-copy)”。但这里网络操作仍需CPU发起,因此与GPUDirect P2P的纯GPU操作有所区别。

开启这项功能的条件,除了满足GPUDirect的基本条件之外,还需满足RDMA网卡与GPU也属于同一PCIe root。

6.5.2 通信协调的软件

分布式训练系统 通信库

为了更好地服务深度学习等GPU任务,NVIDIA提出了针对其GPU等硬件产品的通信库 NCCL: NVIDIA Collective Communication Library[12]

NCCL提供类似MPI的通信接口,包含集合式通信(collective communication)all-gather、 all-reduce、 broadcast、 reduce、reduce-scatter 以及点对点(point-to-point)通信send 和receive。

拓扑感知的通信 NCCL这样的通信库中目前能够提供的通信算法主要针对已有的标准硬件,相对比较有限的,而有研究工作(例如: SCCLopen in new window )根据连接拓扑和带宽延迟等信息,可以综合设计性能更为优化的通信算法。

除了NVIDIA之外,其它的厂商也发布了针对自身产品的高效通信库,例如AMD的RCCLopen in new window以及intel的OneCCLopen in new window

随着硬件的快速发展,带来了更高的性能和更大的优化机遇,因此软件研究方面的迭代,尤其是支持分布式深度学习训练的算法硬件协同设计的研究,依然存在这巨大的潜力。


6.5.3 课后实验:AllReduce的实现和优化

实验目的

  1. 理解并行训练的原理和实现
  2. 定制一个新的并行训练的通信压缩算法

实验环境(参考)

  • Ubuntu 18.04
  • PyTorch==1.5.0 (务必安装CPU版本)
  • OpenMPI
  • Horovod==0.19.4

实验原理:深度学习中,分布式训练算法和分布式训练系统的基本知识

实验内容

实验流程图:

具体步骤:

  1. 安装依赖支持:OpenMPI, Horovod

  2. 编写程序,使用Horovod库,增加数据并行训练支持

    1. 参照Horovod with PyTorch参考文档,修改 mnist_basic.py 文件, 另存为 pytorch_mnist_horovod.py,使用Horovod库实现数据并行
      • mnist_basic.py原始文件地址:https://github.com/pytorch/examples/blob/master/mnist/main.py
      • Horovod with PyTorch文档地址:https://github.com/horovod/horovod/blob/master/docs/pytorch.rst
    2. 记录每个step的运行时间和正确率(accuracy)
  3. 理解Horovod的执行逻辑,利用Numpy实现float8(8bit), float16(16bit)编码方案的压缩/解压缩

    1. 克隆GitHub上Horovod库
    2. 修改 /horovod/torch/compression.py 文件,增加Bit8Compressor和Bit16Compressor类,实现compress和decompress函数。(提示:torch.Tensor没有8-bit float类型支持,所以Bit8Compressor还需实现float32和float8类型的相互转化)
  4. 修改Horovod库中代码,增加对float8(8bit), float16(16bit)格式的压缩

    1. 修改 /horovod/torch/mpi_ops.py 文件,利用Horovod内嵌的AllGather通信和压缩接口,增加对float8(8bit), float16(16bit)格式的压缩代码的调用。
    2. 重新build Horovod库。
  5. 修改MNIST样例代码,增加压缩功能。

  6. 测试代码正确性,比较原始代码、数据并行、加入压缩算法三者的性能差别。

  7. [选做项目] 利用C++/CUDA API实现更为高效的压缩/解压缩编码

实验报告

实验环境:

硬件环境服务器数目                                       
网卡型号、数目
GPU型号、数目
GPU连接方式
软件环境OS版本
GPU driver、(opt. NIC driver)
深度学习框架
python包名称及版本
CUDA版本

实验结果:

比较原始串行训练,用Horovod并行训练,加入压缩算法三者,在同样epoch条件下的训练时间和结果正确率。

Epoch size: ___________

训练算法        训练时间                结果正确率        
串行训练
用Horovod并行Device# == 2
Device# == 4
float8(8bit)压缩Device# == 2
Device# == 4
float16(16bit)压缩Device# == 2
Device# == 4

参考代码

  1. 安装Horovod

    安装OpenMPI:sudo apt install openmpi-bin

    安装Horovod:python3 -m pip install horovod==0.19.4 --user

  2. 利用Horovod并行化pytorch MNIST模型训练 2.1. Device# == 1

    运行命令:python3 pytorch_mnist_horovod.py

    2.2. Device# == N (e.g., N == 2, 4, 6, 8)

    运行命令:horovodrun -n 2 python3 pytorch_mnist_horovod.py –hvd True

    参考代码: https://github.com/horovod/horovod/blob/master/examples/pytorch_mnist.py

基于Horovod(v0.19.4)库增加bit-16和bit-8的并行训练的通信压缩算法

  1. Build Horovod

    运行命令:HOROVOD_WITHOUT_MXNET=1 HOROVOD_WITHOUT_GLOO=1 HOROVOD_WITHOUT_TENSORFLOW=1 HOROVOD_WITH_PYTORCH=1 python setup.py build

  2. 在horovod库中需要修改的文件和代码片段: bit8,bit16.git_diff

  3. 执行压缩算法进行训练

    mpirun -n 2 python pytorch_mnist_compress.py --bit8-allreduce
    mpirun -n 2 python pytorch_mnist_compress.py --bit16-allreduce
    

小结与讨论

思考题:为什么模型训练通常需要分布式进行,而分布式模型预测并不常见?

  • 计算模式不同:预测任务占用存储更小,更容易放在单个设备中

  • 训练需要各个工作节点(Worker)保持通信,从而协调统一地更新模型参数;

  • 预测中的模型参数是固定的,各个工作节点分别使用只读副本,无需相互通信协调

参考文献

  1. NVIDIA A100 GPUopen in new window
  1. Sylvain Jeaugey, NVIDIA, DISTRIBUTED DEEP NEURAL NETWORK TRAINING: NCCL ON SUMMITopen in new window
  1. DGX A100 review: Throughput and Hardware Summaryopen in new window
  1. Performance considerations for large scale deep learning training on Azure NDv4 (A100) seriesopen in new window
  1. An Open Accelerator Infrastructure Project for OCP Accelerator Module (OAM)open in new window
  1. Enflame T10 Manualopen in new window
  1. CUDA 4.0 Overviewopen in new window
  1. NVIDIA GPUDirect: Enhancing Data Movement and Access for GPUsopen in new window
  1. SCCL: Synthesizing optimal collective communication algorithmsopen in new window
  1. RCCL: ROCm Communication Collectives Libraryopen in new window
  1. OneCCL: Intel oneAPI Collective Communications Libraryopen in new window
  1. NCCL: The NVIDIA Collective Communication Libraryopen in new window
  1. Horovod with PyTorch 文档open in new window
  1. Horovod MNIST并行训练参考代码open in new window
Last Updated 2023-04-02 14:55:00