使用 Apache MXNet 和 Horovod 进行分布式学习

文章的翻译是在课程开始前夕准备的 “大数据上的工业机器学习”

在多个高性能计算实例上进行分布式训练可以将现代深度神经网络对大量数据的训练时间从几周缩短到几小时甚至几分钟,使得这种训练技术在深度学习的实际应用中普遍存在。 用户必须了解如何跨多个实例共享和同步数据,这反过来对扩展效率产生重大影响。 此外,用户还应该知道如何将在单个实例上运行的训练脚本部署到多个实例。

在本文中,我们将讨论使用开放深度学习库 Apache MXNet 和 Horovod 分布式学习框架来快速轻松地进行分布式学习的方法。 我们将清楚地展示 Horovod 框架的性能优势,并演示如何编写 MXNet 训练脚本,使其以分布式方式与 Horovod 一起工作。

什么是 Apache MXNet

Apache MXNet 是一个开源深度学习框架,用于创建、训练和部署深度神经网络。 MXNet 抽象了与实现神经网络相关的复杂性,具有高性能和可扩展性,并为流行的编程语言(例如 蟒蛇, C + +中, Clojure的, 爪哇岛, 朱莉娅, R, 斯卡拉 和其他人。

使用参数服务器在 MXNet 中进行分布式训练

MXNet 中的标准分布式学习模块 使用参数服务器方法。 它使用一组参数服务器从每个工作人员收集梯度,执行聚合,并将更新的梯度发送回工作人员以进行下一次优化迭代。 确定服务器与工作人员的正确比例是有效扩展的关键。 如果只有一个参数服务器,它可能会成为计算的瓶颈。 相反,如果使用太多服务器,多对多通信可能会堵塞所有网络连接。

什么是霍罗沃德

霍罗沃德 是 Uber 开发的开放式分布式深度学习框架。 它利用高效的跨 GPU 和跨节点技术,例如 NVIDIA 集体通信库 (NCCL) 和消息传递接口 (MPI),跨 vorec 分发和聚合模型参数。 它优化了网络带宽的使用,并且在使用深度神经网络模型时可以很好地扩展。 目前支持几种流行的机器学习框架,即 MX网、Tensorflow、Keras 和 PyTorch。

MXNet 和 Horovod 集成

MXNet 通过 Horovod 中定义的分布式学习 API 与 Horovod 集成。 Horovod 通信 API horovod.broadcast(), horovod.allgather() и horovod.allreduce() 使用 MXNet 引擎的异步回调实现,作为其任务图的一部分。 通过这种方式,MXNet 引擎可以轻松处理通信和计算之间的数据依赖关系,以避免因同步而造成的性能损失。 Horovod 中定义的分布式优化器对象 horovod.分布式优化器 展开 优化 MXNet 中,以便调用相应的 Horovod API 进行分布式参数更新。 所有这些实施细节对最终用户都是透明的。

快速启动

您可以在 MacBook 上使用 MXNet 和 Horovod 快速开始在 MNIST 数据集上训练小型卷积神经网络。
首先,从 PyPI 安装 mxnet 和 horovod:

pip install mxnet
pip install horovod

注意:如果您在执行过程中遇到错误 pip 安装霍罗沃德也许你需要添加一个变量 MACOSX_DEPLOYMENT_TARGET=10.vv哪里 vv – 这是您的 MacOS 版本的版本,例如,对于 MacOSX Sierra,您需要编写 MACOSX_DEPLOYMENT_TARGET=10.12 pip install horovod

然后安装OpenMPI .

最后,下载测试脚本 mxnet_mnist.py 并在MacBook终端的工作目录中运行以下命令:

mpirun -np 2 -H localhost:2 -bind-to none -map-by slot python mxnet_mnist.py

这将在处理器的两个核心上运行训练。 输出如下:

INFO:root:Epoch[0] Batch [0-50] Speed: 2248.71 samples/sec      accuracy=0.583640
INFO:root:Epoch[0] Batch [50-100] Speed: 2273.89 samples/sec      accuracy=0.882812
INFO:root:Epoch[0] Batch [50-100] Speed: 2273.39 samples/sec      accuracy=0.870000

性能演示

在具有 50 个实例的 1 个 GPU 上的 ImageNet 数据集上训练 ResNet64-vXNUMX 模型时 p3.16x大 EC2,每个在AWS云上包含8个NVIDIA Tesla V100 GPU,我们实现了45000张图像/秒的训练吞吐量(即每秒训练的样本数)。 44 个 epoch 后,训练在 90 分钟内完成,最佳准确率为 75.7%。

我们将其与 MXNet 的分布式训练方法进行了比较,该方法在 8、16、32 和 64 个 GPU 上使用参数服务器,单个参数服务器和服务器与工作线程的比例分别为 1:1 和 2:1。 您可以在下面的图 1 中看到结果。 左侧 y 轴上的条形代表每秒训练的图像数量,线条反映右侧 y 轴上的缩放效率(即实际吞吐量与理想吞吐量的比率)。 可以看到,服务器数量的选择会影响扩展效率。 如果只有一台参数服务器,则在 38 个 GPU 上,扩展效率会下降到 64%。 为了实现与 Horovod 相同的扩展效率,您需要将相对于工作人员数量的服务器数量增加一倍。

使用 Apache MXNet 和 Horovod 进行分布式学习
图 1. 使用 MXNet 与 Horovod 和参数服务器进行分布式学习的比较

在下面的表 1 中,我们比较了在 64 个 GPU 上运行实验时每个实例的最终成本。 将 MXNet 与 Horovod 结合使用可以以最低的成本提供最佳的吞吐量。

使用 Apache MXNet 和 Horovod 进行分布式学习
表 1.Horovod 和 Parameter Server 之间的成本比较(服务器与工作人员比率为 2 比 1)。

重现步骤

在接下来的步骤中,我们将向您展示如何使用 MXNet 和 Horovod 重现分布式训练的结果。 要了解有关 MXNet 分布式学习的更多信息,请阅读 这个帖子.

步骤1

使用 MXNet 版本 1.4.0 或更高版本和 Horovod 版本 0.16.0 或更高版本创建同构实例集群以使用分布式学习。 您还需要安装用于 GPU 训练的库。 对于我们的实例,我们选择了 Ubuntu 16.04 Linux,带有 GPU 驱动程序 396.44、CUDA 9.2、cuDNN 7.2.1 库、NCCL 2.2.13 通信器和 OpenMPI 3.1.1。 您也可以使用 亚马逊深度学习 AMI,其中这些库已预先安装。

步骤2

将使用 Horovod API 的功能添加到您的 MXNet 训练脚本中。 以下基于 MXNet Gluon API 的脚本可以用作简单的模板。 如果您已经有相应的训练脚本,则需要粗体行。 以下是使用 Horovod 学习时需要做出的一些关键更改:

  • 根据本地 Horovod 等级(第 8 行)设置上下文,以了解训练是在正确的图形核心上执行的。
  • 将初始参数从一个工作线程传递给所有工作线程(第 18 行),以确保所有工作线程以相同的初始参数开始。
  • 创建霍罗沃德 分布式优化器 (第25行)以分布式方式更新参数。

要获取完整脚本,请参阅 Horovod-MXNet 示例 MNIST и 影像网.

1  import mxnet as mx
2  import horovod.mxnet as hvd
3
4  # Horovod: initialize Horovod
5  hvd.init()
6
7  # Horovod: pin a GPU to be used to local rank
8  context = mx.gpu(hvd.local_rank())
9
10 # Build model
11 model = ...
12
13 # Initialize parameters
14 model.initialize(initializer, ctx=context)
15 params = model.collect_params()
16
17 # Horovod: broadcast parameters
18 hvd.broadcast_parameters(params, root_rank=0)
19
20 # Create optimizer
21 optimizer_params = ...
22 opt = mx.optimizer.create('sgd', **optimizer_params)
23
24 # Horovod: wrap optimizer with DistributedOptimizer
25 opt = hvd.DistributedOptimizer(opt)
26
27 # Create trainer and loss function
28 trainer = mx.gluon.Trainer(params, opt, kvstore=None)
29 loss_fn = ...
30
31 # Train model
32 for epoch in range(num_epoch):
33    ...

步骤3

登录其中一名工作人员以使用 MPI 指令开始分布式培训。 在此示例中,分布式训练在四个实例上运行,每个实例有 4 个 GPU,集群中总共有 16 个 GPU。 随机梯度下降 (SGD) 优化器将与以下超参数一起使用:

  • 小批量大小:256
  • 学习率:0.1
  • 动量:0.9
  • 重量衰减:0.0001

当我们从一个 GPU 扩展到 64 个 GPU 时,我们根据 GPU 的数量线性缩放训练速率(从 0,1 个 GPU 的 1 到 6,4 个 GPU 的 64),同时将每个 GPU 的图像数量保持在 256 个(来自一批 GPU)。 256 个 GPU 为 1 个图像,16 个 GPU 为 384 个图像)。 权重衰减和动量参数随着 GPU 数量的增加而变化。 我们使用混合精度训练,使用 float64 数据类型进行前向传递,使用 float16 进行梯度训练,以加速 NVIDIA Tesla GPU 支持的 float32 计算。

$ mpirun -np 16 
    -H server1:4,server2:4,server3:4,server4:4 
    -bind-to none -map-by slot 
    -mca pml ob1 -mca btl ^openib 
    python mxnet_imagenet_resnet50.py

结论

在本文中,我们研究了使用 Apache MXNet 和 Horovod 进行分布式模型训练的可扩展方法。 我们在训练 ResNet50-v1 模型的 ImageNet 数据集上展示了与参数服务器方法相比的扩展效率和成本效益。 我们还提供了可用于修改现有脚本以使用 Horovod 运行多实例训练的步骤。

如果您刚刚开始使用 MXNet 和深度学习,请转到安装页面 MXNe首先构建 MXNet。 我们还强烈建议您阅读这篇文章 60 分钟内完成 MXNet开始。

如果您已经使用过 MXNet 并想尝试使用 Horovod 进行分布式学习,那么请查看 Horovod安装页面,从 MXNet 构建它并遵循示例 MNIST или 影像网.

*成本计算依据 每小时费率 适用于 EC2 实例的 AWS

了解有关课程的更多信息 “大数据上的工业机器学习”

来源: habr.com

添加评论