对于深度学习开发者和研究者们来说,高性能的算力是助力其研究成功的重要武器。对于影响深度学习训练快慢的因素,人们常常容易忽略网络传输在训练提速中的重要作用。特别是在大规模集群,分布式训练的场景中,网络的拥塞可能直接导致GPU算力的失效,就像空有一段段双向8车道的快速路,但如果道路规划凌乱,高速路也只能沦为大型停车场。
本期文章针对网络这个话题,分享一点幻方 AI 就这个方向上的思考和优化。
先聊聊网络拓扑
在幻方萤火集群中,大规模机器学习训练任务对通信和数据读取的性能要求非常高,所以我们使用了目前高性能计算中常用的高速网络来构建节点之间的互联。高速网络的网线和交换机如何排布,这就是我们需要考虑的第一个问题——网络拓扑。
网络拓扑的构建有点像修路,不但要保证任意两个节点之间都能互相访问,还要让从各个节点发出的数据包都能尽可能畅通无阻地到达目的地。
与畅通无阻相反的概念就是拥塞。这里用一个生活中塞车的例子来理解拥塞,假设现在所有车辆都具有相同的最高时速,并且会按照能跑到的最大速度去开。
-
某个路口有三条车道,源源不断地有车进来但只有一条车道可以出去。如果三条车道的车都遵守交替通行的规则,那么这三条车道的通行效率就只有 1/3。这就是发生了拥塞;
-
如果三条车道的某一条车道前面有个丁字路口,直行和右转在同一个车道。直行的车辆会通往拥堵的车道,而右转的车辆会前往另一条畅通的车道,但由于右转的车会被直行的车堵住,假设右转和直行的车辆刚好是交替的,那么这条车道的通行效率也只有 2/3。这就是拥塞扩散。
为了尽可能避免塞车的出现,就得有一个好的道路规划。网络拓扑也是同理。
Fattree 是如今大型 AI 集群常用的一种网络拓扑,如英伟达的 Super Pod 等。
Fattree 的原型,如上图所示。多个交换机用一棵树的形式相连,不同的层有不同的交换机数量,不同层之间的线缆的带宽也等比例变化,但每一层的总带宽都相等。这就是一个无阻塞的网络拓扑。我们还是用塞车的问题来理解这个拓扑,每个交换机可以理解成一个路口。我只要把市中心的路口的车道数加得特别多,就不容易堵车。
这个拓扑的路由规则也很简单,因为树的任意两个结点之间都只存在一条最短路径。从 a 点到 b 点的路径直接使用最短路径就可以了。
然而这样的拓扑显然是不实用的,它对网线和交换机的要求太过苛刻。既然没有带宽这么大的网线,我们可以用多根网线组合起来当成一根大的网线用;既然没有这么大的交换机,我们可以把大交换机也拆成多个小的交换机。于是就演化为了下图所示的 Fattree。
相比于 Fattree 的原型,上图所示的 Fattree 引入了一个新的问题:当一个数据包要从其中一个交换机发送到另一个交换机的时候,往往存在很多种可能的路径,如何判断该走那一条呢?如果大量数据包都同时需要通过同一条线路(链路复用),那还是会产生拥塞。根据幻方萤火的经验,链路复用可能会把集群的整体流量降到正常情况的一半,甚至更低。如何通过合理规划流量的路径,减少拥塞的发生和影响范围,这就是路由算法需要解决的问题。
MLNXSM的路由算法
现在的高速网络基本都是用 Mellanox 提供的 MLNXSM 来管理,MLNXSM 提供了针对 Fattree 拓扑结构的路由算法,虽然它的文档中并没有详细介绍,而且代码也没有开源,但众所周知 MLNXSM 是 OpenSM 的魔改版,有兴趣的读者可以通过 OpenSM 的源码来了解其细节。
核心思路
高速网络交换机的路由规则是,每个交换机上都有一个端口转发表,会根据每个数据包的目的地将数据包转发到对应的端口。而路由算法就是要为每个交换机生成这个端口转发表。
OpenSM 的 Fattree 会为每个叶子节点,也就是每张网卡,在 Fattree 的每一层分配一个下行链路,所有到达这一层的去往该目标网卡的流量都经由这个下行链路往下。同时,对这些下行链路做负载均衡,使得每条下行链路上分配到的目标网卡数量尽可能相等。从而减少从上层到下层的流量之间的链路复用。最理想的情况下,如果 Fattree 各层之间的带宽相等,也就是横截面流量之比为 1:1 时,可以完全避免从上到下的链路复用。这样,拥塞就只会在从下到上的流量中发生,拥塞扩散的范围也会变小。
这听起来很不错,但在实际应用 MLNXSM 的 Fattree 算法过程中,我们还是遇到了一些问题。
实际使用遇到的问题
-
萤火二号实际的网络拓扑并不是一个标准的 Fattree。除去计算机器和存储机器之外,我们还有一部分测试机器、开发机器和用于管理集群的机器等。它们对于网络带宽的要求相对低很多,因此我们使用更低带宽的网卡或是其他方式将它们接入核心网络。但 MLNXSM 的 Fattree 算法并不能很好地处理这一点,它并不会根据机器的应用类型来计算路由。结果就是,由于我们的机器网卡总带宽比 Fattree 的横截面带宽更大,所以 MLNXSM 算出来的路由表常常会把两个以上的网卡分配到同一个链路上,如果这两张网卡恰巧都是负载比较重的网卡,就会产生拥塞。
-
MLNXSM 的 Fattree 算法产生的路由表会有比较严重的负载不均衡的现象,标号靠前的几个交换机会分到更多的负载。猜测是因为枚举交换机的顺序导致。
-
Mellanox 交换机有一个很先进的功能叫 sharp,可以把一部分计算在交换机内完成。在实践中我们目前不打开 sharp,但路由算法仍然会给 sharp 节点计算负载。
-
如果有几个 Fattree 需要互相连接,路由算法的行为将会很难控制。
我们的一些实践
为了解决上述的这些问题,幻方AI自研了一套适配萤火二号的特性的路由算法。
主要思路如下:
-
将整体的网络在逻辑上切分成标准Fattree的部分和其他部分。
-
对于网络拓扑中标准 Fattree 的部分,采用上述的 Opensm Fattree 算法类似的思路,给每个叶子交换机上的端口分配一条独立的从上到下的链路,使得从上到下的流量完全没有链路复用。
-
对于其他部分,使用最短路等图论算法计算转发路径,但同时需要考虑链路的负载均衡。
-
对于 Fattree 与其他网络之间互联的部分,同样需要在互联线之间做负载均衡,使得每条互联线分配到的目的节点数量相等。
-
负载均衡的同时,需要根据目标机器类型把单个应用的流量分散到各个链路,最大化单个应用的峰值带宽。
-
对于不同带宽的网卡,在负载均衡时采用与带宽等比例的权重。
-
对于 sharp 节点,仅保证其连通性,而不考虑其负载。
-
类似于互联线和带宽较低的网卡,比较容易成为拥塞的源头。把经过它们的流量集中到部分交换机上,一旦发生拥塞,也能减小拥塞的影响范围。
-
发生网络故障时,需要把故障交换机上的负载转移到别的交换机上。
在萤火二号上经过长期的生产环境验证,幻方 AI 自研的这套路由算法很好地解决了原来 MLNXSM 路由算法在幻方集群上水土不服的问题,明显提升了集群的网络使用效率。
更优更灵活的路由方案,幻方AI继续持续探索,欢迎各方同行学者一起讨论,加入共建。