128+3 台 B300 推理集群 · 整体网络架构图

128 台在线推理节点 + 3 台热备机 | 8×B300/节点 | 800G Rail-Optimized Fabric | Prefill/Decode 分离推理。

集群整体网络总览(推理业务视角)

file

单台节点内部架构(每台服务器内部)

file

file

节点->Leaf->Spine布线细节(Rail-Optimized)

file

file

先把最根本的问题问清楚:为什么需要交换机分层?

一、起点:131 台机器怎么互相连

每台节点有 8 张网卡,全集群 131 × 8 = 1,048 个网口。这 1,048 个口要能互相通信。

最笨的办法是两两拉一根线,需要 1048 × 1047 ÷ 2 ≈ 54.8 万根线。物理上不可能。

所以引入交换机:一个盒子,上面有一排口,谁要发数据就交给它,它负责转到目标口。所有人只需要各拉一根线到这个盒子。1,048 根线,问题解决。

但交换机的口数有物理上限。 一台交换机的核心是一颗交换芯片,芯片的引脚数、封装面积、功耗、散热都有天花板。当前最强的 800G 级交换芯片大约支持 144 个 800G 端口(本方案选型的 Quantum-X800 Q3400 就是这个规格)。

于是矛盾出现了:需要接 1,048 个口,但一台交换机只有 144 个口。


二、Leaf 和 Spine 是什么

多台交换机必须组合使用。怎么组合?

错误做法:串联(菊花链)。 交换机 A 接 B,B 接 C。结果是 A 和 C 之间的所有流量都要挤过 B,B 成为瓶颈,而且距离越远跳数越多,延迟不均。

正确做法:分角色、分层。

角色 中文 干什么 接不接服务器
Leaf 叶交换机 / 接入层 服务器直接插在它上面
Spine 脊交换机 / 核心层 只连 Leaf,把所有 Leaf 串起来 绝不接

名字来自树的比喻:Spine 是脊柱/主干,Leaf 是末端的叶子。服务器挂在叶子上,叶子之间要通信就借道脊柱。

这个结构有三个名字,指的是同一个东西:

  • Leaf-Spine 架构——工程界最常用的叫法
  • 两层 Clos 网络——1953 年贝尔实验室的 Charles Clos 为电话交换设计的多级无阻塞结构,这是理论源头
  • 胖树 Fat-Tree——1985 年 Charles Leiserson 提出。普通树越往上越细会堵车,"胖树"要求上层带宽和下层一样粗

Spine 为什么绝不能接服务器? 因为一旦接了,网络就不对称了:挂在 Spine 上的服务器到别人只要 1 跳,挂在 Leaf 上的要 3 跳。路由算法依赖"所有节点地位相同"这个前提,破坏对称性会让负载均衡和故障切换全部失效。这是硬规矩。


三、核心计算:为什么一台 Leaf 只接 72 台服务器

这是你问的"值怎么算出来的"的关键。

一台 Leaf 有 144 个口。这 144 个口必须分成两部分

    ┌─────────── 144 个 800G 口 ───────────┐
    │                                       │
    │   72 个"上联口" ──→ 连 Spine          │
    │   ──────────────────────────────      │
    │   72 个"下联口" ──→ 接服务器          │
    │                                       │
    └───────────────────────────────────────┘

为什么正好一半一半?

考虑最坏情况:这台 Leaf 下面 72 台服务器同时要和外面(其他 Leaf 下的机器)满速通信。这些流量全都得从上联口出去。

  • 下联总带宽 = 72 × 800G = 57.6 Tb/s
  • 如果上联只有 36 个口 = 28.8 Tb/s,那就只能过一半,另一半排队 →

所以要不堵,必须 上联带宽 ≥ 下联带宽,即 72 = 72。

这个比值有个专门的名字:收敛比(也叫超配比 oversubscription ratio)= 下联 : 上联

收敛比 配置 含义 成本
1:1 72下 / 72上 无阻塞,任意时刻全速互通 基准(本方案采用)
2:1 96下 / 48上 一半机器满速时另一半要排队 交换机少约 40%
4:1 115下 / 29上 只在轻载时不堵 便宜,但训练场景不可接受

这就是 N-10 图纸末尾那个"能省 1,500 万"的可选优化项的技术含义。


四、本方案的完整推导

第一步:如果不做 Rail 优化(标准算法)

端点总数 = 131 × 8                    = 1,048
Leaf 数  = ⌈1,048 ÷ 72⌉               = 15 台
上联总数 = 15 × 72                    = 1,080 条
Spine 数 = ⌈1,080 ÷ 144⌉              = 8 台
交换机合计                             = 23 台

第二步:加上 Rail 优化的约束

Rail 优化要求:所有节点的第 i 张 GPU,必须接到同一台(组)Leaf 上。这就把"1,048 个端点随便分"变成了"8 条 Rail,每条 Rail 独立分"。

每条 Rail 的端点数 = 131 台节点 × 每台 1 张卡  = 131 个

131 > 72(单台 Leaf 下联上限)
  ↓
每条 Rail 需要 2 台 Leaf,131 个端点分成 66 + 65

Leaf 总数 = 8 条 Rail × 2 台                  = 16 台

第三步:单台 Leaf 的端口账本

下联 66 口 ──→ 66 台节点的同号 GPU
上联 66 口 ──→ 分散连到 8 台 Spine(1:1 无阻塞)
空闲 12 口 ──→ 扩容余量
────────────────────────────────
合计 144 口

第四步:Spine 数量

上联总数 = 16 台 Leaf × 66 条            = 1,056 条
每台 Spine 144 口
Spine 数 = ⌈1,056 ÷ 144⌉                 = 8 台
每台 Spine 实际占用 = 1,056 ÷ 8          = 132 口(还空 12 口)

交换机合计 = 16 + 8 = 24 台。 图上标的所有数字都从这四步来。


五、图里那些交叉线是什么意思

你看到 Leaf 和 Spine 之间密密麻麻的线,规则只有一条:

每一台 Leaf,都必须和每一台 Spine 有直接链路,且条数尽量均等。

具体分配:一台 Leaf 的 66 条上联要分给 8 台 Spine,66 ÷ 8 = 8.25,所以是 2 台 Spine 各分 9 条 + 6 台 Spine 各分 8 条(18 + 48 = 66)。

为什么要这样均分,而不是把 66 条全插在 SP-1 上? 两个原因:

  1. 容错——如果全插 SP-1,SP-1 一挂这台 Leaf 就彻底断了。均分之后,挂一台 Spine 只损失 1/8 的跨 Rail 带宽(约 12.5%),业务不中断。
  2. 负载分担——流量哈希到 8 条不同路径,避免某一条被打满。

这也回答了"为什么 Spine 要 8 台而不是 1 台大的":Spine 的数量就是跨 Rail 通信的冗余度。


六、节点与节点到底怎么通信:四种情况

这是最核心的部分。假设节点 001 的某张卡要给节点 047 的某张卡发数据。

情况 A:同一台机器内(GPU0 → GPU3)

GPU0 ──NVLink──> NVSwitch ──NVLink──> GPU3

根本不经过任何以太/IB 交换机,不出机箱。延迟约 2–3 µs,带宽 1.8 TB/s。

情况 B:跨机器、同号卡(节点001-GPU3 → 节点047-GPU3)★最重要

两张卡都插在 LF-3a(Rail-3 的 a 组 Leaf)上:

节点001-GPU3 ──光纤──> LF-3a ──光纤──> 节点047-GPU3
                        ↑
                  只经过 1 台交换机

这是 Rail 优化的全部意义。 延迟约 2–3 µs,完全不占用 Spine 带宽。

情况 C:跨机器、跨号卡(节点001-GPU0 → 节点047-GPU5)

GPU0 在 LF-0a 上,GPU5 在 LF-5a 上,两台不同的交换机,必须借道 Spine:

节点001-GPU0 ──> LF-0a ──> SP-3 ──> LF-5a ──> 节点047-GPU5
                            ↑
                    经过 3 台交换机

延迟约 4–5 µs,且占用 Leaf-Spine 上联带宽。

关于"跳数"的说法,我在图纸里的用词需要澄清一下。 图上写的"1 跳 / 2 跳"是业界习惯口径,指的是穿越了几层网络(情况 B 只穿 Leaf 层,情况 C 穿了 Leaf→Spine→Leaf)。如果按"经过几台交换机"数,情况 B 是 1 台、情况 C 是 3 台。两种口径都常见,看文档时注意上下文。

情况 D:软件的巧妙规避(NCCL 实际在做的事)

情况 C 其实大多数时候可以避免。NCCL 会这样改写:

第一步(机内):节点001-GPU0 ──NVLink──> 节点001-GPU5     约 2 µs
第二步(跨机):节点001-GPU5 ──LF-5a──>  节点047-GPU5     约 3 µs

用一次几乎免费的 NVLink 搬运,把"跨 Rail 2 层"换成了"同 Rail 1 层"。

这才是 Rail 优化真正的威力:它不是让跨 Rail 通信变快,而是让绝大多数通信根本不需要跨 Rail。Spine 层在正常训练/推理中利用率很低,主要作为兜底和故障时的备用路径存在。


七、一个数据包的物理旅程(情况 B 的完整展开)

# 发生了什么 耗时
1 NCCL 下发指令,网卡通过 GPUDirect RDMA 直接从 GPU 显存读数据(不经 CPU 内存) ~0.5 µs
2 网卡封装 IB 数据包,写入目标 LID(本地标识符,由子网管理器统一分配的地址) ~0.3 µs
3 电信号进 OSFP 光模块,调制成 8 路光信号(8 × 100G,这就是 "SR8" 里 8 的含义) ~0.1 µs
4 多模光纤传输 30 米(光在光纤里约 20 万 km/s) 0.15 µs
5 到达 LF-3a 的光模块,还原成电信号 ~0.1 µs
6 交换芯片查转发表(表由 UFM 子网管理器预先算好下发),确定从第 47 号口出去 ~0.3 µs
7 再经光纤 30 米到节点 047 的网卡 0.15 µs
8 网卡 GPUDirect 直写目标 GPU 显存 ~0.5 µs
单向端到端合计 ≈ 2–3 µs

有意思的是:光纤传播和交换机转发加起来还不到总延迟的 20%,大头在两端的网卡与协议栈处理。这也是为什么把 Leaf 放机房中央(30 米 vs 60 米)主要省的是光模块的钱,而不是延迟。

补充一个容易混淆的点:文档里 N-06 图写的"跨节点 IB ≈ 25–40 µs"和这里的 2–3 µs 不矛盾。前者是集合通信(All-Reduce)的延迟——8 张卡要多轮交换、同步、归约,是几十次点对点通信的总和;后者是单次点对点延迟。看到延迟数字时一定要确认是哪一种。


八、两层架构的天花板在哪

既然两层这么好,什么时候需要三层?

每台 Spine 最多 144 口,每台 Leaf 至少要连它 1 条
  ↓ 所以 Leaf 数量上限 = 144 台
每台 Leaf 最多接 72 台服务器
  ↓
两层架构理论上限 = 144 × 72 = 10,368 个端点

本方案 1,048 个端点,只用了理论容量的 10%,两层绰绰有余。

顺带说明 R-01 里提到的方案 B(131 台 GB300 NVL72,9,432 个端点):它 9,432 已经逼近 10,368 这个上限,虽然理论上塞得下,但一点扩容和冗余余量都没有了,所以实践中会直接上三层。


九、一个我需要修正的地方

推导过程中发现方案里有处不一致,应当告诉你:

G-01 图纸写的是"交换机端口全部按 160 节点配"。但按上面的账本核对:

当前 16 台 Leaf,每台下联上限 72
  ↓
每条 Rail 上限 = 2 × 72 = 144 个端点
  ↓
本架构的扩容天花板是 144 台节点,不是 160

要扩到 160 台,每条 Rail 需要 3 台 Leaf,Leaf 总数从 16 增到 24 台,Spine 也要相应增加。

建议的修正:机电部分(机柜、母线、CDU、液冷管路)继续按 160 节点预留,这部分成立且必要;网络部分明确写"当前配置支持扩容至 144 台,超出需增补 8 台 Leaf"。招标时把这句话写进技术要求,避免二期扩容时才发现端口不够、被迫停机改造。


要不要我把这套基础原理整理成一张新图纸(X-02 网络基础原理)加进 HTML 方案里?包含端口预算示意图、四种通信路径的对比图,以及上面这条 144/160 的修正。这样评审时给不熟悉网络的人看会方便很多。

一次推理请求的完整通信路径(实际推理流程)

file

为者常成,行者常至