128+3 台 B300 推理集群 · 整体网络架构图
128 台在线推理节点 + 3 台热备机 | 8×B300/节点 | 800G Rail-Optimized Fabric | Prefill/Decode 分离推理。
集群整体网络总览(推理业务视角)

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


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


先把最根本的问题问清楚:为什么需要交换机分层?
一、起点: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 上? 两个原因:
- 容错——如果全插 SP-1,SP-1 一挂这台 Leaf 就彻底断了。均分之后,挂一台 Spine 只损失 1/8 的跨 Rail 带宽(约 12.5%),业务不中断。
- 负载分担——流量哈希到 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 的修正。这样评审时给不熟悉网络的人看会方便很多。
一次推理请求的完整通信路径(实际推理流程)

问题 Rail优化与 Leaf-Spine 的关系
你上边解释的 Leaf-Spine 架构 我看懂了,但是加入 Rail 优化之后,就看不懂、不明白了,为什么要这么优化,优化的逻辑是什么,结合 Spine leaf 再详细的解释下,并结合画图解释的可能更清晰一些。
理解的卡点我大概能猜到:Leaf-Spine 讲的是"交换机之间怎么分层",而 Rail 优化讲的是"服务器的网线该插到哪台 Leaf 上"。这是两个不同层面的问题,容易混在一起。
先给一句话答案,后面再展开:
传统接法按"物理位置"分组——同一个机柜的机器接同一台 Leaf。
Rail 优化按"通信关系"分组——所有机器的同号卡接同一台 Leaf。而 GPU 之间真实的通信对象,恰恰不是"隔壁机柜的机器",而是"所有机器的同号卡"。所以按物理位置接线,等于按错误的维度做了分组。
下面从流量说起。
第一步:先看清楚 GPU 之间的流量长什么样
Rail 优化的全部理由都藏在这里。
一个节点有 8 张 GPU、8 张网卡。当集群做 All-Reduce 时,NCCL 会把通信拆成 8 条并行的"通道",目的是同时用满这 8 张网卡(否则 8 张卡挤 1 张网卡,浪费 7/8 的带宽)。
拆分的方式很自然:通道 i 的跨机通信,由每台节点的 GPU-i 通过它自己的网卡 i 完成。于是流量呈现出一个非常规整的形状——

这张图是理解一切的钥匙:跨机流量是"横着走"的,永远发生在同一行(同号卡)之间。竖着走的需求(GPU3 要给 GPU5 传东西)在机箱内部用 NVLink 解决,根本不出机器。
现在带着这个认识,来看两种接线方式。
第二步:同样的设备、同样的线数,只是插的口不同
关键前提:这两种接法,Leaf 数量一样、Spine 数量一样、线的根数一样,成本几乎相同。 差别只在于——节点的 8 根线,是插到 1 台交换机,还是分插到 8 台。

左边那种接法,直觉上"很合理"——机器和交换机就在同一个柜子里,线最短最便宜。但把第一张图的流量叠上去就会发现问题:它把需要频繁对话的同号卡,恰好分散到了不同的交换机上。
第三步:把流量叠上去,差别就出来了
假设节点 001 的 GPU3 要给节点 047 的 GPU3 发数据——这是最典型、最高频的一种通信。

为什么"确定性"比"平均更快"更重要
这里要说一个容易被忽略的点,也是我认为最能说服人的理由。
有人会反驳:传统接法下,如果通信双方恰好在同一台 Leaf 下,不也是 1 跳吗?确实如此。但这个"恰好"是不可控的。
| 传统接法 | Rail 接法 | |
|---|---|---|
| 同号卡在同一台 Leaf 下 | 1 跳 ✓ | 1 跳 ✓ |
| 同号卡在不同 Leaf 下 | 3 跳,上 Spine | 仍然 1 跳 |
| 作业节点被打散分配时 | 大部分跨 Spine | 不受影响 |
| 多作业并发互相干扰 | 在 Spine 上争抢 | 不接触 Spine |
传统接法的性能取决于调度器分到的节点恰好挨在一起。生产集群同时跑多个作业,节点分配必然是碎片化的——今天分到 A01/A03/B07/C02,明天完全不同。性能因此变得不可预测。
Rail 接法把这件事变成了结构性保证:只要是同号卡,无论是哪两台节点、无论怎么调度,永远 1 跳。
这一点在训练场景表现为吞吐稳定,在推理场景表现为 P99 尾延迟可控——而尾延迟正是在线服务的生死线。
跨号卡怎么办
Rail 接法看似有个明显短板:节点 001 的 GPU0 要给节点 047 的 GPU5 发数据,两张卡分属 Rail-0 和 Rail-5,必须借道 Spine。
但 NCCL 会自动改写这个路径:
原路径:001-GPU0 ──Rail-0──> Spine ──Rail-5──> 047-GPU5 3 台交换机
改写后:001-GPU0 ──NVLink──> 001-GPU5 ──Rail-5──> 047-GPU5 1 台交换机
第一步是机内 NVLink 搬运,1.8 TB/s、约 2 µs,成本几乎为零。用一次免费的机内搬运,把跨 Rail 变成了同 Rail。
这才是 Rail 优化真正的完整形态:它不是"让跨 Rail 更快",而是让跨 Rail 这件事基本不再发生。Spine 层因此在正常运行中几乎空闲,主要作为兜底路径和故障时的备份存在。这也解释了 N-10 图纸里那个"计算网利用率只有 2%"的数字——不是网络设计过剩,是流量被成功地按在了 Leaf 层。
回到 131 这个具体数字
现在再看方案里的推导,应该就清楚了:
Rail 的定义:每条 Rail 收纳所有节点的同号卡
↓
每条 Rail 的端点数 = 131 台 × 每台 1 张卡 = 131 个
单台 Leaf 的下联上限 = 72(1:1 无阻塞的约束)
131 > 72
↓
每条 Rail 必须用 2 台 Leaf,131 个端点拆成 66 + 65
↓
Leaf 总数 = 8 条 Rail × 2 台 = 16 台
这就是"a 组 / b 组"的由来——它不是人为分区,是端口数不够被迫拆的。
所以 N-07 图纸里那条编排规则也就有了意义:如果 Prefill 和 Decode 节点都落在 a 组(编号 ≤66),KV 传输是 1 跳;一旦跨组配对(a 组发给 b 组),即使是同号卡也要走 Leaf-0a → Spine → Leaf-0b,退化成 3 台交换机。推理路由器把同组配对作为首选,就是为了守住这 1 跳。
代价必须说清楚
Rail 优化不是免费的:
| 项目 | 传统接法 | Rail 接法 | 差额 |
|---|---|---|---|
| Leaf / Spine 数量 | 15 / 8 | 16 / 8 | 基本持平 |
| Leaf-Spine 光模块 | 2,160 | 2,112 | 持平 |
| 主机侧线缆 | 柜内 2 m 铜缆 | 机房中央 30 m 光纤 | — |
| 主机侧光模块 | 几乎为零 | 2,096 个 | 多约 2,000 万元 |
| 布线复杂度 | 每柜一捆,简单 | 每节点 8 根去 8 个方向 | 显著增加 |
2,000 万,买的就是"同号卡永远 1 跳"这一条保证。
这也直接解释了 A-01 平面图里那个决定——网络核心岛必须放在机房正中。因为 Rail 接法逼着每根主机线都要跑到机房中央,居中布置能把最远距离压在 32 米以内,让所有链路都用得起便宜的多模 SR8;如果核心岛偏在一头,最远要走 60 米以上,被迫改用单模 DR8,光模块单价翻倍,那 2,000 万会变成 4,000 万。
一句话总结
Leaf-Spine 解决的是"交换机不够大,怎么堆"。
Rail 优化解决的是"服务器的线该插哪台交换机"。前者是拓扑结构,后者是端口映射。两者叠加,才有了"24 台交换机 + 同号卡永远 1 跳"这个结果。
要不要我把这三张图和上面这套推导,整理成一张新图纸 X-02 网络基础原理加进 HTML 方案里?放在 N-01 之前作为前置阅读,评审时给不熟悉网络的人看会顺很多。顺便可以把上一轮提到的那个 144/160 扩容口径的修正一并写进去。
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)