概述¶
Horovod 是一个面向 TensorFlow、Keras、PyTorch 和 Apache MXNet 的分布式深度学习训练框架。 Horovod 的目标是让分布式深度学习变得快速且易于使用。

Horovod 由 LF AI & 数据基金会 (LF AI & Data) 托管。如果您是一家致力于在人工智能、机器学习和深度学习领域使用开源技术的公司,并希望支持这些领域的开源项目社区,请考虑加入 LF AI & 数据基金会。有关参与方以及 Horovod 如何发挥作用的详细信息,请阅读 Linux 基金会的 公告。
目录
为什么选择 Horovod?¶
该项目的主要动机是让单GPU训练脚本能够轻松地成功扩展到并行训练多个GPU。这包含两个方面:
将一个程序修改为分布式需要做多少改动,运行起来有多容易?
在分布式模式下运行速度能提升多少?
在Uber内部,我们发现MPI模型比之前的解决方案(如使用参数服务器的分布式TensorFlow)更加直观,且需要更少的代码更改。一旦为Horovod编写了可扩展的训练脚本,它就可以在单GPU、多GPU甚至多台主机上运行,无需任何额外的代码更改。 更多详情请参见Usage部分。
除了易于使用之外,Horovod 还非常快速。下图展示了在128台服务器上进行的基准测试结果,每台服务器配备4个Pascal GPU,并通过支持RoCE的25 Gbit/s网络连接:
Horovod 在 Inception V3 和 ResNet-101 上实现了 90% 的扩展效率,在 VGG-16 上实现了 68% 的扩展效率。 请参阅 基准测试 了解如何复现这些数据。
虽然安装MPI和NCCL本身可能看起来有些麻烦,但这只需要基础设施团队完成一次,而公司中构建模型的其他人则可以享受大规模训练的简便性。
安装¶
在 Linux 或 macOS 上安装 Horovod:
安装 CMake
如果你从PyPI安装了TensorFlow,请确保已安装
g++-5或更高版本。 从TensorFlow 2.10开始,将需要支持C++17的编译器,如g++8或更高版本。如果你从PyPI安装了PyTorch,请确保已安装
g++-5或更高版本。如果你从Conda安装了任一软件包,请确保已安装
gxx_linux-64Conda软件包。
安装
horovodpip 包。要在 CPU 上运行:
$ pip install horovod
要在 GPU 上使用 NCCL 运行:
$ HOROVOD_GPU_OPERATIONS=NCCL pip install horovod
有关安装支持 GPU 的 Horovod 的更多详细信息,请阅读 Horovod on GPU。
有关 Horovod 安装选项的完整列表,请阅读 安装指南。
如果你想使用MPI,请阅读Horovod with MPI。
如果你想使用 Conda,请阅读构建支持 GPU 的 Horovod Conda 环境。
如果你想使用Docker,请阅读Horovod in Docker。
要从源代码编译 Horovod,请遵循贡献者指南中的说明。
概念¶
Horovod 核心原则基于 MPI 概念,例如 size、rank、 local rank、allreduce、allgather、broadcast 和 alltoall。更多详细信息请参见 此页面。
用法¶
要使用 Horovod,请向您的程序添加以下内容:
运行
hvd.init()来初始化 Horovod。
将每个GPU固定到一个进程,以避免资源争用。
在典型的每个进程一个GPU的设置中,将此设置为本地排名。服务器上的第一个进程将被分配第一个GPU,第二个进程将被分配第二个GPU,依此类推。
根据工作节点数量缩放学习率。
在同步分布式训练中,有效批次大小会随工作节点数量成比例增加。 提高学习率可以补偿增大的批次大小。
将优化器包装在
hvd.DistributedOptimizer中。分布式优化器将梯度计算委托给原始优化器,使用 allreduce 或 allgather 对梯度进行平均,然后应用这些平均后的梯度。
将初始变量状态从等级0广播到所有其他进程。
当使用随机权重开始训练或从检查点恢复时,这能确保所有工作节点的一致初始化。
修改你的代码,仅在worker 0上保存检查点,以防止其他worker损坏它们。
使用 TensorFlow v1 的示例(完整训练示例请参见 examples 目录):
import tensorflow as tf
import horovod.tensorflow as hvd
# Initialize Horovod
hvd.init()
# Pin GPU to be used to process local rank (one GPU per process)
config = tf.ConfigProto()
config.gpu_options.visible_device_list = str(hvd.local_rank())
# Build model...
loss = ...
opt = tf.train.AdagradOptimizer(0.01 * hvd.size())
# Add Horovod Distributed Optimizer
opt = hvd.DistributedOptimizer(opt)
# Add hook to broadcast variables from rank 0 to all other processes during
# initialization.
hooks = [hvd.BroadcastGlobalVariablesHook(0)]
# Make training operation
train_op = opt.minimize(loss)
# Save checkpoints only on worker 0 to prevent other workers from corrupting them.
checkpoint_dir = '/tmp/train_logs' if hvd.rank() == 0 else None
# The MonitoredTrainingSession takes care of session initialization,
# restoring from a checkpoint, saving to a checkpoint, and closing when done
# or an error occurs.
with tf.train.MonitoredTrainingSession(checkpoint_dir=checkpoint_dir,
config=config,
hooks=hooks) as mon_sess:
while not mon_sess.should_stop():
# Perform synchronous training.
mon_sess.run(train_op)
运行 Horovod¶
以下示例命令展示了如何运行分布式训练。 更多详情请参阅运行 Horovod,包括RoCE/InfiniBand调优技巧以及处理卡顿问题的建议。
在一台拥有4个GPU的机器上运行:
$ horovodrun -np 4 -H localhost:4 python train.py
在4台机器上运行,每台机器有4个GPU:
$ horovodrun -np 16 -H server1:4,server2:4,server3:4,server4:4 python train.py
要在不使用
horovodrun包装器的情况下通过Open MPI运行,请参阅Running Horovod with Open MPI。要在Docker中运行,请参阅Horovod in Docker。
要在Kubernetes上运行,请参阅Helm Chart、Kubeflow MPI Operator、FfDL和Polyaxon。
要在Spark上运行,请参阅Horovod on Spark。
要在Ray上运行,请参阅Horovod on Ray。
要在Singularity中运行,请参阅Singularity。
要在LSF HPC集群(例如Summit)中运行,请参见LSF。
要在Hadoop Yarn上运行,请参阅 TonY。
Gloo¶
Gloo 是由 Facebook 开发的开源集体通信库。
Gloo 已包含在 Horovod 中,允许用户无需安装 MPI 即可运行 Horovod。
对于同时支持 MPI 和 Gloo 的环境,您可以通过向 --gloo 传递参数给 horovodrun 来选择在运行时使用 Gloo:
$ horovodrun --gloo -np 2 python train.py
mpi4py¶
Horovod 支持将 Horovod 集合操作与其他 MPI 库(如 mpi4py)混合使用,前提是 MPI 构建时支持多线程。
你可以通过查询hvd.mpi_threads_supported()函数来检查MPI多线程支持。
import horovod.tensorflow as hvd
# Initialize Horovod
hvd.init()
# Verify that MPI multi-threading is supported.
assert hvd.mpi_threads_supported()
from mpi4py import MPI
assert hvd.size() == MPI.COMM_WORLD.Get_size()
你也可以使用mpi4py子通信器来初始化Horovod,在这种情况下,每个子通信器将运行一个独立的Horovod训练。
from mpi4py import MPI
import horovod.tensorflow as hvd
# Split COMM_WORLD into subcommunicators
subcomm = MPI.COMM_WORLD.Split(color=MPI.COMM_WORLD.rank % 2,
key=MPI.COMM_WORLD.rank)
# Initialize Horovod
hvd.init(comm=subcomm)
print('COMM_WORLD rank: %d, Horovod rank: %d' % (MPI.COMM_WORLD.rank, hvd.rank()))
Tensor Fusion¶
Horovod 的独特之处在于它能够交错进行通信和计算,并结合对小规模 allreduce 操作的批处理能力,从而提升性能。我们将这种批处理功能称为 Tensor Fusion。
查看这里获取完整详情和调整说明。
Horovod Timeline¶
Horovod 具备记录其活动时间轴的能力,称为 Horovod Timeline。
使用 Horovod 时间线来分析 Horovod 性能。 查看这里获取完整详情和使用说明。
自动性能调优¶
选择合适的值以高效利用Tensor Fusion及其他高级Horovod功能可能需要大量试错。我们提供了一个名为自动调优的系统来自动化此性能优化过程,您只需通过一个命令行参数即可在horovodrun中启用该功能。
查看这里获取完整详情和使用说明。
Horovod Process Sets¶
Horovod 允许您在一场分布式训练中,同时在不同的进程组内执行不同的集合操作。设置 hvd.process_set 对象以利用此功能。
查看进程集获取详细说明。
引用¶
如果 Horovod 对您的研究有所帮助,请在您的出版物中引用它:
@article{sergeev2018horovod,
Author = {Alexander Sergeev and Mike Del Balso},
Journal = {arXiv preprint arXiv:1802.05799},
Title = {Horovod: fast and easy distributed deep learning in {TensorFlow}},
Year = {2018}
}
Publications¶
1. Sergeev, A., Del Balso, M. (2017) 遇见 Horovod:Uber 的开源分布式深度学习框架 for TensorFlow. 检索自 https://eng.uber.com/horovod/
2. Sergeev, A. (2017) Horovod - 分布式TensorFlow变得简单. 检索自 https://www.slideshare.net/AlexanderSergeev4/horovod-distributed-tensorflow-made-easy
3. Sergeev, A., Del Balso, M. (2018) Horovod: fast and easy distributed deep learning in TensorFlow. 检索自 arXiv:1802.05799
参考文献¶
Horovod 源代码基于 Andrew Gibiansky 和 Joel Hestness 编写的百度 tensorflow-allreduce 代码库。他们的原始工作在文章 Bringing HPC Techniques to Deep Learning 中有详细描述。
参与其中¶
Community Slack 用于协作和讨论
Horovod Announce 获取项目更新信息
Horovod Technical-Discuss 用于公开讨论
Horovod Security 报告安全漏洞