Horovod架构

架构

Horovod主要由数据通信层、通信控制层、深度学习框架接口层、启动层四部分组成。其中启动层通过horovodrun或mpirun启动训练进程,之后每个训练进程通过调用TensorFLow、PyTorch、MXNet等框架(python train.py)进行单个结点的数据输入、参数更新,在每个进程完成一个或多个batch计算后,得到的Tensor(参数)通过MPI或GLoo控制进行ring-allreduce,ring-allreduce 的通信可以基于MPI、NCLL、DDL、MLSL或GLoo。PS: Horovod 本身会在每一个worker 上启动一个进程(运行工作组件),然后内部 执行 python train.py 启动tf 框架进程,与框架融合的代码会负责 将tf 框架的 操作指令发给 Horovod 进程 干活。这就有点类似于 k8s 中的CNI 插件,CNI 插件一般分为两部分,一部分按照k8s的规范 提供执行接口(cni binary),另一部分独立运行在容器内 作为service,cni binary 会把 k8s 的指令 转给 service
  common        // 主要是c的部分
  data
  keras
  mxnet         // 与mxnet融合
  runner        // horovodrun 实现
  tensorflow    // 与tensorflow 融合,比如将allreduce 算子注册tf上,挂到Optimizer的 _compute_gradients 逻辑中

与tf 融合
Horovod 不依托于某个框架,自己通过MPI建立了一套分布式系统,完成了allreduce, allgather等collective operations通信工作。PS:类似于上图 driver 组成的部分
Horovod 定义的这套HVD OP是跟具体深度学习框架无关的,比如使用 TensorFlow时候,是无法直接insert到TF Graph中执行的,所以还需要注册TF的OP。针对 TensorFlow 模型分布式训练,Horovod 开发了 TensorFlow ops 来实现 Tensorflow tensor 的 AllReduce。而且这些 op 可以融入 TensorFlow 的计算图中,利用 TensorFlow graph 的 runtime 实现计算与通信的 overlapping,从而提高通信效率。以 TensorFlow 模型的 AllReduce 分布式训练为例,Horovod 开发了 allreduce ops 嵌入 TensorFlow 的反向计算图中,从而获取 TensorFlow 反向计算的梯度并进行梯度汇合。allreduce ops 可以通过调用 gloo 提供的 allreduce API 来实现梯度汇合的。

horovodrun 做了什么

建立 RendezvousServer,这个会被底层 Gloo C++ 环境使用到;
- Horovod 在进行容错 AllReduce 训练时,除了启动 worker 进程外,还会启动一个 driver 进程。这个 driver 进程用于帮助 worker 调用 gloo 构造 AllReduce 通信环。
- Driver 进程需要给 Gloo 创建一个带有 KVStore 的 RendezvousServer,其中 KVStore 用于存储通信域内每个节点的 host 和 其在逻辑通信环分配的序号 rank 等信息。
- 这个 RendezvousServer 运行在 Horovod 的 driver 进程里。driver 进程拿到所有 worker 进程节点的地址和 GPU 卡数信息后,会将其写入RendezvousServer 的 KVStore 中,然后 worker 就可以调用 gloo 来访问 RendezvousServer 构造通信环。
host_alloc_plan = get_host_assignments 来根据host进行分配slot,就是horovod的哪个rank应该在哪个host上的哪个slot之上运行;
get_run_command 获取到可执行命令;
slot_info_to_command_fn 来得到在slot之上可执行的 slot command;
依据 slot_info_to_command_fn 构建 args_list,这个 list 之中,每一个arg就是一个 slot command;
多线程执行,在每一个 exec_command 之上执行每一个 arg(slot command);
 
worker 负责训练和模型迭代。
- 每个 worker 节点会向 RendezvousServer 发起请求来得到自己的邻居节点信息,从而构造通信环。
- 在这个通信环之中,每个 worker 节点有一个左邻居和一个右邻居,在通信过程中,每个 worker 只会向它的右邻居发送数据,只会从左邻居接受数据。
 
Horovod 在进行容错 AllReduce 训练时,除了启动 worker 进程外,还会启动一个 driver 进程。这个 driver 进程用于帮助 worker 调用 gloo 构造 AllReduce 通信环。
driver 进程中会创建一个带有 KVStore 的 RendezvousServer,driver 会将参与通信的 worker 的 ip 等信息存入 KVstore 中。
然后 worker 就可以调用 gloo 来访问 RendezvousServer 构造通信环了。


posted @ 2024-02-25 09:12  muzinan110  阅读(27)  评论(0编辑  收藏  举报