AI Infra 软核教程(二)GPU 集群基本结构与多机组网拓扑

前言

从这一章开始,就要开始 AI Infra 的正式教程篇章了,和大部分锦恢学生时代学过的教材一样,我打算先从底层硬件开始讲,其实第一版原本写了 collective 和 p2p 通信与 NCCL,但是被朋友吐槽说里面的硬件术语太多了,啥是 NvLink,啥是 NvSwitch,硬件拓扑是啥,为啥要考虑这个?那个又是啥?

所以我觉得在讲通信算法之前,得先讲讲硬件底层。避免各位观众阅读的时候流口水。

谁适合这篇教程?

自己装过机或者上操作系统/体系架构认真做实验的朋友。

对通信底层和硬件底层不感兴趣的、上过操作系统但是没认真做实验的、没有自己折腾过台式机的,可以酌情观看。

图片图片

在介绍通信抽象之前,我们先简单了解一台现代 GPU 服务器的基本结构。

从 PC 开始的 GPU 服务器硬件扫盲

一台用于大模型训练的服务器,通常包含以下几个主要部分:CPU、系统内存、GPU、PCIe 总线、网卡、本地存储。可以将其简化为下图:

图片图片

其实和你家自己打游戏,搭建服务器的电脑相比,没有太多变化。

比如这是我最近从垃圾堆里翻出来的 10 多年前的电脑,codex 花了半天时间帮我修好了这台机子,打算组一台 MC 服务器和朋友们一起打打游戏顺便聊聊天。这台计算机的主板就提供了两条 PCIex16 插槽(深蓝色的和黑色的),所以可以插两块 GPU(当然前提是供电支持)。插上两卡后,这台机子 “理论上” 就能进行单机双卡训练了。

图片图片

只是做 MC 服务器,所以显卡被我拔了,别找了,图里没显卡

GPU 和主板一般通过有效位宽为 x16(即 16 条 lane)的插槽连接,然后被识别为一个 PCIe 设备,这个 GPU 上和主板连接的玩意儿,土话一般叫做 GPU 的 “金手指”。比如下图我圈起来的地方就是 A100 的金手指。

图片图片

专业的 GPU 服务器,上面这样的 GPU 插槽更多,常见的有 8 卡插槽。比如下面就是一个 8 卡 B300 的解决方案:

图片图片

你能看到,专业的工业级服务器的 GPU 插槽更多,磁盘存储插口越多,供电更猛,整机用料更好,当然,更贵(x 我经手的大部分服务器,当然,也包括 NVIDIA 全家桶,基本都是 8 卡插槽。不过逻辑上的基本结构和我们常用的 PC 差不多的,所以如果你自己装过机,应该很快能理解 8 卡 GPU 服务器的基本内部结构。

更多的卡,更多的算力,更多的麻烦

单台 GPU 服务器并非是卡越多越好,更多的卡意味着:

更大的供电:满载 8 卡 B300 功率 14.5 kW,相当于 10 台吹风机一直工作,所以我不知道那帮想要本地部署还嫌 code plan 贵的人是脑子进水了还是家里电不要钱。

更好的散热:大功率散热风扇或者服务器级别冷却液。风扇散热很吵,非常吵,让我梦回该死的风洞实验,进机房换磁盘要带专门的隔音耳机。当然,一些大厂(比如阿里云)自研了不会让你的 GPU 接触后就爆炸短路的冷却液,直接把主板泡在冷却液里,还有机器人自动进行配件更换,那种就安静很多。但是也更贵。

然后有小朋友会问,为啥只能是 8 卡,16 卡,我们不能造一个 20 卡,100 卡的服务器吗?通过后续的学习你就会明白,卡的数量最好是 2 的次幂,这样才能更好做并行算法。其次,8 卡服务器的耗电量几乎就已经接近单机的极限,16 卡已经很少见了,想要把单机的显卡插槽做得更多会有这么几个问题:

功耗可能达到数十千瓦,且更多的卡挤在一个空间内,需要新的供电和散热方案。而上游硬件的迭代周期很长,嗯,比某些人的职业生涯还要长。

单机故障率显著上升,32 卡的服务器一张卡出问题做排查就要让整个机器全部停转。相比于 8 卡,32 卡的故障率和损失会更大。这一点和火箭的推进器数量引入的系统复杂度问题非常像,感兴趣的朋友可以了解一下。

GPU 间通信路径不均匀,我们下面讲单机多卡的拓扑时会提到。

所以综合考虑下来,目前最流行的方案仍然是单机 8 卡,单机 16 卡在一些高端云厂商的库存中能见到,算是未来的一个趋势。所以我们本系列没有额外的说明,所有后续算法和讨论上下文都是 N 台 8 卡服务器。

单机内的通信:认识 PCIe 和 PCIe Switch

PCIe 是计算机内各个组件的纽带,GPU、网卡、SSD 和各种扩展设备都可以使用 PCIe 连接在一起并通过操作系统完成访问。我们上文讨论了为啥单机八卡是目前的主流,那么让我们将目光移动到单机八卡的内部吧。

单机八卡架构下,常见的服务器都是双路的,也就是有两个 CPU 插槽,每个 CPU 连同自己那一侧的 4 张卡、内存和其他设施共同组成一个 NUMA (Non-Uniform Memory Access,非一致内存访问)节点。

图片图片

单个 NUMA 内的 CPU 和 PCIe 设备(比如内存,gpu 等)的相互访问是一致的,但是不同的 NUMA 之间的设备访问往往需要走专门的 CPU2CPU 的跨 NUMA 通信协议,这取决于 CPU 是谁生产的。服务器 CPU 市场几乎就是 Intel 和 AMD 的天下,如果是 Intel 的 CPU,那么就是 UPI;如果是 AMD 的 CPU,那么就是 Infinity Fabric。

这套设计在过去的小模型时代完全没问题,但是大模型时代已经无法满足需求了。训练过大模型的朋友都应该知道,决定一个集群好不好用的因素一半都在通信性能上。因为后续提到的并行算法,对底层的通信带宽提出新的要求。

比如常见的 TP 算法,会将两张巨大的矩阵进行切分,并在计算后进行一次通信,这个通信极有可能就发生在 GPU0 到 GPU1 之间。那么在现在这个架构下,数据通信极有可能是:

GPU 0 ── CPU Root Complex ── GPU 1

这个过程由 DMA 驱动完成,如果当前系统不支持 PCIe p2p,那么此次通信会借用 pinned memory 进行中转,产生额外的通信开销。TP 往往是成对进行通信的,大概率此时 GPU2 和 GPU3 之间也需要通信,在通信数据量大的时候,memory 就会成为当前通信的主要瓶颈。

假设 GPU 使用 PCIe 5.0 x16 接口,其理论单向带宽约为 63 GB/s。不过,实际 GPU-to-GPU 有效带宽还会受到 GPU 接口代际、PCIe 拓扑、Root Complex、P2P 支持和链路竞争等因素影响,在某些具体系统中可能只能测得 23~29 GB/s。

本文如果没有特别说明,带宽均指单向带宽。双向聚合带宽表示两个方向可以同时传输时,两侧吞吐量之和。

假设下游需要对一个 48 层的 decoder-only Transformer LLM 进行分布式训练,我们只考察 TP 这一个并行算法的通信需求。假设 TP=8,hidden size 为 8192,序列长度为 4096,micro batch size 为 1,每个 micro batch 的计算耗时大约需要 0.25~0.5 秒,按 BF16、每层训练 4 次 ring all-reduce 粗略估算,每个 micro batch 每卡需要传输约 21 GiB,对应约 42~84 GiB/s 的通信需求。也就是说,在通信与计算不重叠的简化假设下,23~29 GB/s 的有效带宽可能让约 60%~80% 的时间花在通信上,等待通信的这段时间计算卡的利用率极低。显然,这是一套非常糟糕的方案。

针对这个问题,我们往系统中加入了 PCIe Switch 模块,直接连接同一 NUMA 下的所有 GPU,让 GPU 绕开 pinned memory 这个中间商,直接在 Switch 内完成横向的通信。

图片图片

此时,GPU0 和 GPU1 的通信拓扑就变成了:

GPU 0 ── PCIe Switch ── GPU 1

此时的通信带宽可以提升到 48~58 GB/s,接近翻了一倍,但是显然,还是无法满足训练任务的要求。在上述简化假设下,通信时间占比可能降低到约 42%~65%。

这里补充一点,我们刚刚的讨论都是在单个 NUMA 节点内的。不同 NUMA 节点通过各个 CPU 厂商自己的通信协议连接;以 Intel Xeon 6 为例,UPI 2.0 的单链路速率最高为 24 GT/s,整机聚合带宽则取决于具体 SKU、链路数量和通信方向,不能直接等同于单个 GPU 对之间的有效带宽。一般全力工作的训练机还存在一定的通信延时和带宽竞争,所以我们姑且可以认为跨 NUMA 通信延迟更高、有效带宽更低。

如果你们的服务器是用的英伟达的显卡做的训练(大概率),那么通过如下的命令来查看当前的 8 卡拓扑:

nvidia-smi topo -m

可能的输出:

        GPU0  GPU1  GPU2  GPU3  GPU4  GPU5  GPU6  GPU7  CPU Affinity
GPU0     X    PIX   PXB   PXB   SYS   SYS   SYS   SYS   0-31
GPU1    PIX    X    PXB   PXB   SYS   SYS   SYS   SYS   0-31
GPU2    PXB   PXB    X    PIX   SYS   SYS   SYS   SYS   0-31
GPU3    PXB   PXB   PIX    X    SYS   SYS   SYS   SYS   0-31
...

下面是表格里面每一个缩写的解释:

标记含义两张 GPU 之间最多经过一颗 PCIe Switch经过多级 PCIe Bridge/Switch,但不经过 CPU Host Bridge路径经过 PCIe Host Bridge / CPU Root Complex经过同一 NUMA 节点内的多个 Host Bridge跨 NUMA 节点或跨 CPU Socket通过若干条 NVLink 连接当前 GPU 自身

大家如果手头有空闲的 8 卡服务器,可以试试用这个命令看看结果。通常,在一些 NCCL 兼容性测试时,我们会查看当前的 gpu 拓扑来排除一些可能的选项。

从 PCIe 到 Nvlink

PCIe Switch 虽然提升了带宽,但是引入了额外的问题:由于 Switch 到 CPU PCIe Root 的上行链路总带宽有限,四张卡如果有两张是满载的状态,那么剩下两张到 CPU 的数据传输就会产生竞争。

而 PCIe (5.0 x16)本身的理论最大单向通信带宽就是 63GB/s,也就是说,如果我们不提高 PCIe 代际或增加链路数量,那么单条 PCIe 5.0 x16 链路的理论极限就是 63GB/s,还是无法满足要求。

为了打破 PCIe 本身的通信极限,NVIDIA 这家公司在 10 年前(也就是 2016 年)于 P100 芯片上推出了一款叫做 NVLink 的技术来满足高带宽通信的需求。P100 最多提供 4 条 NVLink 1.0,每条双向聚合带宽为 40GB/s,整卡合计为 160GB/s,这已经基本满足我们上面举例的训练需求。

简单说就是,这帮人在 GPU 金手指的对面的位置上,给 GPU 开了几个新的接口。还是拿 A100 举例,在 A100 上面的位置上,如下图,有三个可以被打开的塞盖,仔细看一下。

图片图片

这几个塞盖拔开,里面就是 A100 专用的 NVLink 接口。使用 NVIDIA 推出的 NVLink Bridge 就可以连接邻近的两块 A100,单个 A100 NVLink Bridge 提供的总双向通信带宽是 200 GB/s(即单向 100 GB/s)。三个就是 600 GB/s, NVLink Bridge 目前国外的市场价折合为人名币约为一块 3000 元。

下图就是一个四张 A100 组成的单机四卡服务器的 NVLink Bridge,A100 两个两个通过三个 NVLink Bridge 连接。

图片图片

你能注意到一个特点,那就是每张 A100 只能和唯一的一个邻居 A100 构成连接。其实这也是合理的,假设 GPU0 可以和 GPU1 用一个 NVLink Bridge 连接,然后 GPU1 又可以和 GPU2 通过一个 NVLink Bridge 连接,那么假设 GPU0 想要向 GPU2 传输数据,就需要通过 GPU1 了,通信延时就无法保证一致了,这样多卡组建集群,一来不好分配 NVLink Bridge 的插槽顺序,二来内部的通信模型不对称了,后续的 NCCL 算法不好施行。

但是这样一做,我们只能保证 GPU0-GPU1 和 GPU2-GPU3 之间可以通信,我想要从GPU0 发送 tensor 到 GPU2 看起来还得走 PCIe ?

很遗憾,但是 A100 PCIe 因为设计上的局限,只能两两连接成这样的孤岛,不过即便如此,也能完成很多的任务了,我们先看一下 8 张 A100 PCIe 两两连接 NVLink 后的一个基本拓扑吧!

图片图片

不够抽象,再抽象一点。

图片图片

可以看到,这种情况下,卡与卡的通信可以抽象为三类:

GPU0 --> NVLink --> GPU1 : 图中紫色箭头, 带宽最大,延迟低
GPU0 --> PCIe Switch0 --> GPU1 : 图中蓝色箭头,带宽中等,延迟低
GPU0 --> PCIe Switch0 --> CPU0 --> UPI --> CPU1 --> PCIe Switch1 --> GPU1 : 图中橙色箭头 + 蓝色箭头, 带宽中等,延迟高

可以再输出一下拓扑

nvidia-smi topo -m

输出

        GPU0  GPU1  GPU2  GPU3  GPU4  GPU5  GPU6  GPU7  CPU Affinity  NUMA Affinity
GPU0     X    NV3   PIX   PIX   SYS   SYS   SYS   SYS   0-31          0
GPU1    NV3    X    PIX   PIX   SYS   SYS   SYS   SYS   0-31          0
GPU2    PIX   PIX    X    NV3   SYS   SYS   SYS   SYS   0-31          0
GPU3    PIX   PIX   NV3    X    SYS   SYS   SYS   SYS   0-31          0
GPU4    SYS   SYS   SYS   SYS    X    NV3   PIX   PIX   32-63         1
GPU5    SYS   SYS   SYS   SYS   NV3    X    PIX   PIX   32-63         1
GPU6    SYS   SYS   SYS   SYS   PIX   PIX    X    NV3   32-63         1
GPU7    SYS   SYS   SYS   SYS   PIX   PIX   NV3    X    32-63         1

可以看到,这样一个“数学性质”很对称的拓扑上,其实还是可以做一些事情的,比如 TP 往往单次通信量大,但是通信频率不大,而 PP 单次通信量小,通信频率更高,利用这些不同通信的特点,合理规划通信路径,就能最大化训练时的效能。而我们后面讲到了底层通信的抽象——NCCL,其实就会帮我们智能地完成这件事。

嗯,感觉可以出一道数学建模 B 题去折磨下一届了

所以实际中,我们可以暂时性忽略底层的 gpu 之间的通信差异,你只需要知道为什么会存在通信差异,以及如何查询它们即可。在一些极端情况下,你可以硬编码通信方案来完成性能的极致压榨,但是那些都属于很高阶的玩法了,此处按下不表。

SXM 模组与 NVSwitch

有些读者朋友会觉得,太麻烦了,怎么 A100 PCIe 只支持最多两卡的 NVLink 高速互联呢?我手里预算足够,就没有更加粗暴简单费钱的方案吗?

有的,兄弟,有的,你都说不缺预算了,那还说啥呢。

图片图片

A100 的两种物理封装

A100 这类 AI 计算卡其实存在两种物理封装,我们前面介绍的含金手指的其实属于 A100 PCIe 封装,A100 和后续的全部专用计算卡(H200,B200,B300 等)还有另外的封装形态 —— SXM 模组。

这是 NVIDIA 面向高功耗数据中心(这就是你把消费级显卡打入冷宫的原因?) GPU 设计的专用模组形态,它专门用于一些为 AI 计算而生的运算设备主板上。比如单个 A100 SXM4 模组(不叫卡了)长这个样子:

图片图片

A100 SXM 形态的市场价是 A100 PCIe 版本的接近两倍,并且必须配合专门的 HGX/DGX 底板才能驱动。昂贵的代价带来的好处是:我们可以使用 NVSwitch 一劳永逸解决上面的问题了。

TIP: 为什么叫“底板”而不是“主板”:由于 NVSwitch 本身的布局、Nvlink 排线等等各方面都有要求,一般的主板不能满足要求,只有使用专门集成了 SXM GPU、NVLink 走线和 NVSwitch 的 GPU Baseboard 才能承载 NVSwitch 和 SXM 模组,这个 Baseboard 就是我们这边指的底板,它本身并不是完整的服务器主板。NVIDIA 本身提供了底板的设计标准,各个下游的服务器厂商还需要设计方案把这些底板整合到服务器主板里面。

单机八卡数据互联的终极方案——NVSwitch

前面介绍的 NVLink Bridge,只能将 GPU 两两连接。如果不被同一对儿 NVLink Bridge 连接的 GPU,它们之间通信还是得走 PCIe。

而 NVSwitch 所做的事情,就是在多张 GPU 之间加入一个专门用于转发 NVLink 数据的交换芯片,比如常见的 DGX A100 单机八卡解决方案会采用六颗 NVSwitch 芯片完成 8 卡的数据互联:

图片图片

每张卡从 NVLink 插槽上引出 12 条线,分摊连接到 6 颗 NVSwitch 上。任意两个卡想要发生通信时,NVSwitch 会决定怎么帮助这两个卡“牵线搭桥”来完成高速通信。

理论上,此时你能看到的拓扑就是:

        GPU0 GPU1 GPU2 GPU3 GPU4 GPU5 GPU6 GPU7
GPU0     X   NV12 NV12 NV12 NV12 NV12 NV12 NV12
GPU1    NV12  X   NV12 NV12 NV12 NV12 NV12 NV12
...
GPU7    NV12 NV12 NV12 NV12 NV12 NV12 NV12  X

值得一提的是,由于封装形态的变化,类 HGX 底板方案中的 NVLink 并不以 NVLink Bridge 的物理形态出现,而是以「模组触点+底板内部高速 PCB 铜走线」的形态存在,这也进一步解释了为什么 8 卡高速互联需要特制的底板而不能在现有的服务器主板上打补丁去支持了。

多机通信

上文我们主要讲了单机八卡的机器中内部通信的问题,显然,为了训练更大的大模型,只是单机八卡往往是不够的,我们需要多机多卡。用 A100 全量训练 30B 以上模型时,是否必须使用多机取决于显存容量、优化器状态精度、并行与分片策略等因素;而产品级别的大模型,比如已公开总参数量达到 2.8 万亿的 Kimi K3,以及未公开参数量的 GPT 5.6、Claude Fable,其训练通常都需要大规模集群。训练这种级别的商业模型,千卡万卡只是入场券,那涉及到的服务器数量自然也就要上升到几百台,甚至上千台这个量级了。

多机多卡遇到的最大的问题就是跨机通信。如果说在之前,我们还能依靠 NVLink + NVSwitch 的强大能力在单机内畅通无阻的话,那么多机就要开始难受了。

因为我们首先需要解决的问题就是不同的计算机之间要如何通信。

一般来说,单机多卡的通信都是发生在一台计算机上的,这种通信我们称之为 intra-node communition,简称 intra-node。而多机多卡的通信就要发生在机器与机器之间了,我们一般称之为 inter-node。嗯,这让我想到了以前学习 Fisher 判别法时的优化目标,里面也是有 intra-class 和 inter-class 的说法,总之,都是一个意思了,很多复杂系统类学科都有类似的概念,结合记忆你将完成快速记忆。

大家第一个想到的就是通过网口,服务器上一般都有以太网接口,找一根网线,一头插在服务器 A 的网口,另一头插在服务器 B 的网口,不就能连接了吗?数据传输走 tpc 协议啥的都行,反正能相互 ping 到 IP,就能传输数据。

你真别说,我还真干过,在 笔记本和树莓派直接进行连接的问题 这篇文章里,我把树莓派和我的笔记本用一根网线“邪修”般地连接在了一起。然后这两台计算机就能通过网络协议栈互相传输数据。

图片图片

但是用在大模型训练场景下,这个方案想当然是不适用的。原因还是带宽。都说我家宽带千兆,万兆,网速够快了吧?下表是服务器常见网口带宽的汇总。

图片图片

传统服务器常见的 100 Gb/s 网口约为 12.5 GB/s,仍然难以满足大规模训练的通信需求。不过,现代 AI 服务器已经开始使用 200、400 乃至 800 Gb/s 的高速网络,对应的理论单向带宽分别约为 25、50 和 100 GB/s。

而且除此之外,常规的基于网口的 GPU 网络数据传输需要 CPU 和内存参与其中:

图片图片

你说为什么不能让显卡显存直接走网络传输?傻瓜,因为不支持呀!当年网卡设计师怎么会想到多年之后人们会需要拿网卡传输一堆的显卡里面存储的向量和矩阵?所以,我们需要先把显卡转到内存里,然后利用成熟的网络栈,把内存的数据传输到另一台计算机上。在模型训练中,这多了两层的中转进一步增加了通信开销:

CPU 内存复制会消耗带宽;

内核协议栈会增加延迟;

CPU 需要不断参与数据搬运;

大规模 collective 很容易受到网络拥塞影响。

为了同时解决这两个问题,让我们的显卡可以尽量不走中间商和另一台计算机的显卡晚上数据通信,并且带宽还足够大,

IB 卡(InfiniBand)的故事

时间退回上个世纪 90 年代,彼时 CPU 的性能越来越强,但服务器之间、服务器与存储之间的数据通道开始成为瓶颈。为了应对这个变化,所以当年几大企业搞了几套不同的技术方案,当时存在两套竞争方案:

Intel、Microsoft、Sun 等推动的 NGIO;

IBM、Compaq、HP 等推动的 Future I/O。

为了防止长期竞争导致的资源浪费,协议不互通和一些其他麻烦的事情,并防止市场规模被进一步拆散,1999 年,这几家公司成立了 InfiniBand Trade Association(简称 IBTA),并制定了名为 InfiniBand 的行业标准,由各个下辖的厂商负责从网卡,线缆到软件栈的研发生产。IBTA 的官方网站时至今日,仍在维护他们的标准内容,感兴趣的读者可以访问看看他们的官网:https://www.infinibandta.org/about-infiniband/

随着时间推移,标准不断修订,厂商不断迭代更新,Mellanox 这家公司成为了 InfiniBand 最重要的商业实现厂商之一,他们对包含符合 InfiniBand 标准的交换机、HCA 网卡、RDMA 软件进行长期生产和技术迭代,在此积累了丰富的经验。

作为 InfiniBand 标准的践行者,Mellanox 生产的 HCA 网卡设备允许两台服务器直接绕过 CPU,在获取授权的情况下可以直接发起内存数据的交换。是不是有点眼熟?没错,Mellanox 的技术可以用来解决上面提到的普通网卡通信性能不足的问题。即便那个时代还不存在大模型。

锦恢最喜欢说的一句话就是,没有毫无成果的天才,没有从零到一的创新。凡有分殊,必有因果,这也是我讲技术必须讲历史的原因。只有这样,才能获得正确、富足、完整的因果。

NVIDIA 很早就看到了这一点,并提前预测了未来 AI 技术的走向。2019 年,NVIDIA 宣布以约 69 亿美元收购 Mellanox,并于 2020 年以 70 亿美元的交易价值完成收购,获得了 Mellanox 在 InfiniBand HCA 网卡上的技术,这些技术被用于构建了 NVIDIA 的超级壁垒。InfiniBand HCA 网卡后来也被称为 InfiniBand 卡,简称 IB 卡。

说点题外话,都说业内有一个笑话,不懂行人的说 NVIDIA 的壁垒是单卡性能,是多少多少 flops,懂行的人都明白,NVIDIA 最厚的壁垒是 cuda 和 nccl,是基于这些协议和软件栈做起来的超级生态、硬件上下游、行业标准。如今的 NVIDIA 甚至把自己的显卡和 DGX 集群作为投资筹码投资初创公司,其他公司投资的都是自己本年的营收,NVIDIA 可以直接把自己的产品作为投资筹码,而且供不应求,足以看到 NVIDIA 作为如今 AI 生态链上的统治地位。

目前 NVIDIA 的 IB 卡主要是 ConnectX 系列,比如 DGX A100 官方原装底板配置的就是 8 张 ConnectX-6 VPI 适配器,一张 ConnectX-6 VPI 卡如下图所示。(ConnectX-6 VPI 就是 IB 卡,不过它也可以切换为普通的以太网卡)

图片图片

你可以看到,一张 ConnectX-6 VPI 提供两个端口,每个端口提供 25GB/s 的跨机通信带宽。ConnectX-6 实际上分为单端口和双端口两个版本。上图是双端口版本,在 DGX A100 官方提供的 8 张其实是单端口版本,这样单端口就能独享 PCIe x16,但是双端口在高峰数据传输时有可能会在 PCIe x16 上发生数据竞争。

加入了 ConnectX-6 这张 IB 卡后,两台 8 卡服务器就能形成高速互联了:

图片图片

这样,我们就可以使用计算机科学最伟大的发明,抽象了。一旦我们确定两台服务器之间的连接没什么问题,且它们的内部通信也没问题,那么我们就可以放弃观测内部细节了。在我们眼里,现在的多机多卡进一步抽象为了下图:

图片图片

嗯,然后让我们进入下一幕。

交换机与单层 Clos

okok,喝口水我的朋友,能看到这里相信比我语音输入到这里更加不容易。不过,你以为这就结束了吗?

上面只是两台服务器,如果是 8 台服务器呢?你会说,我们继续全部接入 IB Switch 交换机里面,嗯,不赖,这个时候是 8 机 64 卡,勉强能全量训一个上了 zero 的 qwen 397b:

图片图片

如果是 16 台机器呢?好像也能接入,更多呢?显然 IB 交换机的接口容量不是无限,以 NVIDIA 的 QM8700 交互机为例,这是与 ConnectX-6 VPI 配套的交换机,向外暴露 40 个单端口速率为 25 GB/s 的端口。

我们刚刚也说了,一台标准的 DGX A100 服务器内置 8 个单端口的 IB 卡(也就是说上面两张图的每条紫色线等等于 8 根 IB 卡连线),显然一台 QM8700 交换机只能最多连接 5 台 DGX A100。别说 16 台机器,8 台机器都连不进去。

所以一台交换机自然是不够滴,我们需要更多的交换机,这个时候,学过高性能网络的朋友们应该能够立刻想到多台交换机下要怎么连接。既然每台服务器都有 8 个 IB 网口,如果把一台服务器的 8 张 IB 卡全部插到同一台交换机里面,那么交换机的端口很快就会捉襟见肘。那自然会想到一个办法:把网络拆成多个平面。每台服务器的第 N 个 IB 卡,就连接到第 N 个交换机中;这样所有服务器的第 N 张 IB 卡共同组成一个独立的网络通道。比如下图中,我们就将四台服务器,每台服务器的第1张IB卡都接入到第一台交换机里面,然后它们的第二张IB卡都接入到第二个交换机里面,以此类推。

由全部服务器的第 N 张 IB 卡和第 N 台交换机组成的网络,显然是相互独立的,我们就把这样一个子网络称为 Rail。比如下图就展示了由全部服务器的第 1 张 IB 卡和第一台交换机组成的 Rail 0。

图片图片

一次类推,还有 Rail1,Rail2, … Rail7,因为每台机子是 8 张 IB 卡嘛,所以就有 8  个 Rail。

这种设计其实非常符合高性能网络里面传统的组网思路。你们可以自己考察一下,这样连接之后,首先,是不是每一个 Rail 自己内部是每个节点都是彼此可达的?是不是任意一台服务器中的显卡都可以和任意服务器中的显卡互相通信了?答案是显而易见的。

没学过的朋友可以读一下我的高级计算机网络系列文章:https://kirigaya.cn/blog/collection?name=高级计算机网络

这也是最经典的 8-Rail 网络拓扑,按照 QM8700 的规格,8-Rail 拓扑设计可以容纳最多 40 台 A100 GPU 服务器,一共 320 张 A100 的集群。

显然,当前拓扑系统中的交换机只有一层,所以也被称为 One-Tier Clos,或者简单点,单层 Clos。

还能递归?双层 Clos

那么如果我们想要接入更多卡怎么办?如果你看上面的高级计算机网络博客或者有计算机网络的基础,就能想到,应该再往上做拓展,把 8-Rail 看成是一个节点,然后把好多的 8-Rail 连接到一个上行交换机里面。由于在结构上看,这显然构成了一棵树,所以在这个情况下 8-Rail 中的每台和 GPU 服务器直连的交换机被我们称为 Leaf。这个连接 8-Rail 的上行交换机被我们称为 Spine。

需要注意的是,由于我们需要让 8-Rail 这个网络平面可以接入 Spine,所以 8-Rail 里面的原本的 8 台交换机需要预留几个接口来接入 Spine 中。

TIP: 能够组成独立网络的系统被我们称为网络平面,显然 8-Rail 是一个网络平面。

显然,我们不能只预留一个 IB 接口,因为这样带宽就不够了,每个交换机只预留一个 IB 口也就意味着这 8 个 IB 口要承载整个 Leaf 里面所有 A100 的通信(也就是 320 - 8 = 312 块 A100),这显然是不合理的。

这里我们选择把 40 拆分为 32 + 8,这两个数字都是 2 的次幂,而还有一个好处,你等我画一个图就全明白了。

图片图片

我们把 40 拆分为 32 + 8 后,我们将原本的服务器+8 个交换机的网络平面看成一个 Leaf,那么这个 Leaf 是不是对外就变成了 8 台交换机每台交换机 8 个空着的 IB 口?这个是不是就是和单个 8-Rail 内,N 台服务器对外暴露 8 个空着的 IB 口一样了?这样我们就可以递归地完成拓扑的构建了。

在这个系统内,Rail0 的定义依然存在,Rail0 就变成了每一个 Leaf 节点的每一台 GPU 服务器的第一个 IB 卡和这个 Leaf 里面的第一台交换机与第一台 Spine 组成的网络平面。很神奇吧?递归和分治是计算机里面最为重要的思想之一,它在 GPU 集群的拓扑设计中仍然发挥着作用。

这样的架构有 leaf 和 spine 两层交换机,所以也被称为 Two-Tier Clos,双层 Clos。

我们来算一下,加了一层 Spine 后这个集群最多能放多少块 A100。每个包含 8 个 Leaf 的节点都含有 32 × 8 = 2 ^ 8 张卡,双层 Clos 一共可以包含 40 个这样的 Leaf 节点,所以一共是 40 × 2 ^ 8 = 10240 张卡。恭喜你,成功规划了一个至少理论上成立的万卡集群。

但是总觉得哪里有点奇怪?事情真的有这么简单吗?

我们考察一个极端情况,Leaf 0~7 的全部 GPU 上行流量全部拉满,由于每个 leaf 的 40 个端口被我们分为了 32 + 8 的形式,也就是 4:1 的比例,其中 4 这个比例的端口承接全部 GPU 的上行流量,1 这个比例的端口负责把数据交给 spine 做进一步的交换,显然,这个时候对于 Leaf 来说,它的下行和上行比例变成了 4:1,属于严重的失衡,数据来得多,但是送出去慢,有效带宽就会在这一层在极端情况下会下降 75%。为了避免这个情况,NVIDIA 官方在 DGX 超节点设计指导手册 NVIDIA DGX SuperPOD: Scalable Infrastructure for AI Leadership 中将 Leaf 的 40 个端口分为了 20 + 20,保证上行下行总带宽一致,但是 spine 的端口此时因为 leaf 上行端口的增加就不够用了,所以还需要继续往上抽象,抽象出三层 Clos 结构:

图片图片

第三层的交换机就叫做 Core,然后包含了 8 个交换机和 20 个 GPU 服务器的网络平面就被称为一个 SU(Scalable Unit 的简称)。具体可以去看看手册里的内容。

可以看到,在 NVIDIA 这份三层 Clos 参考方案中,最大配置包含 1120 张 GPU。针对不同数量的卡,NVIDIA 给出了一份如下的拓扑设计建议表。

DGX 节点数A100 数量SU 数量LeafSpineCore网络层级10800.5820两层201601840两层40320216100两层80640432200两层100800540200两层1209606488024三层14011207568028三层还能拓展?万卡集群的终极方案

上面的表里面最大也只达到了 1120 张卡,距离万卡集群还差不少。那么我们怎么样才能解决这个问题呢?

吐槽一下:不少组织把“拥有一万张卡”就对外宣传成“万卡集群”,但是从严格的定义上来说,这两者中间差的预算可让他们再买“一万张卡”。国内外真正能做到把一万张卡连成一片高速互联集群的组织屈指可数。

这就不得不请出 fat tree 算法了。关于 fat tree 算法,推荐看一下我过去的博客:https://kirigaya.cn/blog/article?seq=249。对于对算法细节不感兴趣的朋友们,你们只需要知道这个算法就是通过提供更多的冗余交换机来从拓扑上达成节点之间访问高效性。

给一张图,让大家温故一下 fat tree 的基本结构。

图片图片

上图是传统计算机网络,假设每个路由器只有四个接口,为了方便才画的,如果是我们教程里面 40 个接口的交换机,实际的拓扑结构会更加复杂,难以绘制。所以此图只为示意图。

有关 fat tree 的技术细节我就不多说了,之前的博客里有写过,而且我估计你们也不感兴趣(x

满载 fat tree 和其在多层 Clos 架构上的移植与变种基本就是目前千卡万卡超节点的拓扑连接方案了。但是考虑到部分朋友读到这里已经快要睡着了。剩下的部分大家已经完全可以自己去和 AI 刨根问底了,你们已经建立起基本的 big picture 了,知道如何提出问题了。

多机多卡一体化解决方案——NVL72

当然,上面的东西如果太多了,看得你脑子发痛,NVIDIA 也提供了一体化的方案,也就是目前业界瞩目,根本买不到货,也不买起的 NVL72 GPU 集群。

下图是我的老朋友出去玩时实拍的 NVIDIA 最新的 GPU 集群方案 Vera Rubin NVL72,含有 72 张 NVIDIA Rubin GPU,单块卡显存 288GB,通信方面,inter-node 能达到 20TB/s 以上,intra-node 能达到 260 TB/s。散热方案采用了整机液冷。这家伙全功率运转的能耗相当于 100 台 1500w 功率的吹风机。

所以我说欧洲人搞不出大模型是有道理的。

不同于之前提到的 SXM 封装,NVL72 超级计算机中含有的计算卡都是 NVL 封装形态,具体就不说了,因为我也没有亲手拆开来看过。所以目前能看到 NVIDIA 给计算卡一共准备了应对不同场景的 PCIe,SXM,NVL 三种不同类型的封装形态。

图片图片

我 chovy,我感觉能出一张试卷了,但是暂时不出课后题吧,因为真的很累。

当然,NVL72 价格同样美丽,2026 年,目前 NVL72 集群的市场成交价是约 5800 万—6800 万元人民币/柜,如果不走量的要现货的话,价格会继续上涨到 7000 多万/柜。市面上也因此衍生出了一批灰色产业,此处就不赘述了。

NEWS: NVIDIA 正在研发 NVL144

更多的多机通信解决方案

并非只要有了 IB 卡就能理所当然地让不同的 GPU 在集群中完成复杂的数据传输,还需要配合软件与协议栈才能使用。而想要了解启动 IB 卡的软件栈,就不得不提 OpenFabric 了。

OpenFabric

OpenFabrics Alliance,简称 OFA,是一个围绕 RDMA、内核旁路和高性能网络软件建立的开放行业组织。他们的官网:https://www.openfabrics.org/。这个组织成立于 2004 年,一开始名字叫做 OpenIB Alliance,专门给 InfiniBind 做 Linux 适配的,不过随着业务扩大,他们后来也做一些基于以太网口的 RDMA,比如下文提到的 RoCE。

学过 HPC 的朋友应该都对 OpenMPI 这个项目不陌生,这个项目所需要使用的上游网络接口,很多都是 OpenFabrics 生态提供的。

OFA 推行的最知名的一套协议就是 OFI (OpenFabrics Interface)了,libfabric 则是对于 OFI 的一套实现。这玩意儿的提出主要是因为,早期在开发高性能计算软件时,比如你用 OpenMPI 写一个分布式数据仓储程序,然后底层的网络设备用的是 IB 卡、普通的 TCP 还是 SHM 可能都要单独适配一套。为了避免这个麻烦,OFA 针对这样一个场景对底层的设备进行了抽象,所以提出了 OFI 标准并开发了 libfabric 库,这样,各个厂商只需要实现自己对于 libfabric 的 provider 就能让上层的分布式软件直接跑起来了。

AWS 的通信方案 EFA 的软件栈中的 aws-ofi-nccl 的 ofi 就是这个 ofi

但是除了分布式计算的调度外,RDMA 也是非常重要的特性,为了让 Linux 用户(因为有高性能计算需求的几乎都是商业服务器,商业服务器几乎都是 Linux)可以直接在 Linux 以用户态提交 RDMA 操作,有了 verbs ,而 libibverbs 则是 verbs 对应的库。

verbs 的归属比较复杂:Verbs 是 InfiniBand 和 OpenFabrics 生态中形成的底层 RDMA 编程模型。历史上,libibverbs 等组件由 OpenFabrics 基础设施分发;今天,Linux 上的 verbs 实现主要并入 rdma-core,由 Linux RDMA 开源社区和各硬件厂商共同维护。

更多的多机通信解决方案

并非只有 NVIDIA 已加提供了能用的多机通信解决方案,毕竟这可是一块肥肉,自然聚集了大量厂商。

下表罗列了目前成熟的多机通信解决方案,包含了我们上面提到的 InfiniBand。值得一提的是,InfiniBand 也是目前性能最好,bug 最少,工程师用着最舒服的一版方案,嗯,除了贵都是优点。

方案底层网络NCCL 接入路径RDMA/GPU Direct典型环境InfiniBand专用 IB FabricNCCL → verbs → IB支持 GPUDirect RDMANVIDIA DGX、HPC、AI 集群RoCEv2以太网上的 RDMANCCL → verbs → RoCE支持 GPUDirect RDMA自建以太网 AI 集群AWS EFAAWS 专用云 FabricNCCL → aws-ofi-nccl → libfabric → EFA支持设备 RDMA,因实例而异AWS EC2 P 系列HPE SlingshotHPE Cray 高性能 FabricNCCL → Slingshot NCCL 插件平台相关HPE Cray 超算Google GPUDirect-TCPX/TCPXOGoogle 云网络 + gVNICNCCL → Google NCCL Net PluginGPU 直接数据路径Google Cloud A3Google gIBGoogle 云 RDMA FabricNCCL/gIB 插件支持高性能 RDMA 路径Google A3 Ultra、A4、A4X

在做模型训练时,我们可以在训练脚本中加入如下来开启 NCCL 不同级别的调试日志:

export NCCL_DEBUG=INFO
export NCCL_DEBUG_SUBSYS=INIT,NET,GRAPH

然后跑模型,或者跑一跑 nccl-tests:nvidia/nccl-tests,通过查看日志来了解目前 GPU 服务器的多机通信解决方案。

下表展示了不同标准下,可能存在的 NCCL 日志内容:

多机通信方案典型 NCCL 日志关键词InfiniBand、、、RoCEv2、、、AWS EFA、、、普通以太网 TCP、

一般情况下,直接让 AI 帮你看就能看出现在的 GPU 服务器是哪种方案。目前的 AI,比如 gpt5.6 已经搭载了很强的 infra 领域的垂直知识。但是这不代表一个不懂 infra 的人就能拿它提供切实可靠的技术服务。

结论

这次也是花了我不少时间呀,希望大家多多点赞,下一章开始,就要开始讲一下 NCCL 和集合通信原语了。

okey dokey,这里是 00 后全栈工程师锦恢,一个正在尝试撰写全网最小白最全面最系统的 AI 全栈系列教程(Agent + 大模型算法 + AI Infra)的学徒。我们最新做的 Agentic RL 框架 Dressage 也开源了,欢迎大家 star 支持一下:Accio-Lab/Dressage,欢迎想要了解和学习大模型底层技术的相关朋友来阅读讨论。

图片图片