说句实话,刚听到“OpenAI 把 10 万 GPU 训练网络压到两层”这个消息时,我的第一反应是不信。十万卡规模,意味着聚合带宽轻松到 PB 级(甚至几十 PB/s),传统做法都是接入层、汇聚层、核心层一层一层往上搭,结果你现在告诉我只留两层?后来仔细算了一笔账,又翻了近两年大型集群的公开网络架构资料,发现这事儿不仅可行,而且几乎是十万卡规模下唯一能落地的方案。这篇文章我想从一个做分布式训练基础设施的工程师视角,把这里的“两层”到底是什么、为什么能行、怎么算端口和带宽、运维时又会踩哪些坑,完整拆开讲清楚。
这套东西适合谁看?如果你在搞大规模 GPU 集群、做训练网络选型,或者你只是跑几十卡的小集群但想提前理解“大厂怎么规划网络”,这篇文章都能给你一个从原理到实操的完整参考。我不打算堆概念,所有结论都会给出计算逻辑和实测经验,争取让你看完后能直接拿去跟团队讨论方案。
1. 十万卡集群的真实挑战:算力越强,网络越容易拖后腿
1.1 为什么 10 万卡不是“把机器堆一起”就行
先聊一个很反直觉的事实:在大规模同步训练里,GPU 算得再快也没用,因为每一轮迭代结束都要做一次全局梯度同步。以最常见的 AllReduce 为例,每张卡算完梯度后,要把自己的梯度切块发给其他卡,同时收别人的梯度,最后在本地归约出完整梯度。这个过程的通信量跟模型参数量成正比,跟你集群多大没有关系——但通信次数会随着集群规模变大而变多。
举个例子,一个 1750 亿参数的模型,如果只用 1 张卡训练,梯度数据量大约是 700GB 量级(按 FP16 算,175B × 2 字节 × 2 份,一份用于发送、一份用于接收)。这数据量当然不可能一次性全发出去,NCCL 内部会切块、做流水线,把通信和计算重叠起来。但问题是,当集群扩展到 10 万卡,每一次集合通信都要跨过整个集群的所有交换机链路,中间任何一条路径的拥塞、抖动、丢包,都会让所有 GPU 停下来等最慢的那一跳。
所以在大规模训练里,网络不是“辅助设施”,它跟 GPU 本身一样是算力的一部分。你网络设计得不好,哪怕 10 万张 H100 摆在机房里,有效算力利用率可能连 50% 都到不了。OpenAI 把网络压到两层,本质上是把“通信路径变短、行为变可预期”,让每一轮同步的成本可控。
1.2 传统三层架构在十万卡规模下会怎样
传统数据中心常用三层架构:接入层(ToR)接服务器,汇聚层(Aggregation)收敛流量,核心层(Core)负责跨区域流量。三层的好处是层次清晰,适合南北向流量为主的传统业务,但到了十万卡训练集群里,问题非常明显。
第一是延迟。每多一层交换机,GPU 之间的通信就多一跳。别小看这一跳,在集合通信中,数据要经过“网卡 → Leaf → Spine → Leaf → 对端网卡”的路径。如果是三层,就多一次“汇聚层”的转发,端到端延迟至少增加 1~2 微秒。在千卡级别这可能无所谓,但在十万卡级别,同步次数极其频繁,哪怕每次只多 1 微秒,累积起来就是可观的效率损失。
第二是收敛比。三层架构里,汇聚层和核心层通常会做收敛,比如接入层 1:1 上联,汇聚层 3:1 收敛。这在传统互联网业务中没问题,因为流量模型是“多数时间不需要全速互相通信”。但训练集群是 ALL-to-ALL 流量,每张卡同时向成百上千张卡发数据,几乎不存在空闲窗口。一旦做了收敛,拥塞就是必然事件,GPU 就会开始等待。
第三是故障域。三层架构的故障路径更长,从 GPU 到 GPU 要经过 7~9 台设备,任何一台交换机掉线、任何一根光纤抖动,都可能导致大范围通信异常。在大规模集群里,每天物理链路出点问题几乎是常态,架构层数越多,排查链路就越费劲。
1.3 “压到两层”到底是什么
所谓两层,就是 Leaf-Spine 架构,也叫 Clos 网络。它只有两层交换机:Leaf 层负责接入 GPU 服务器,Spine 层负责把所有 Leaf 互联起来。任何两台 Leaf 下的 GPU 通信,路径都只有 4 跳:GPU → Leaf → Spine → Leaf → GPU。严格来说这是“二跳网络”,因为 Leaf 交换机是网络边缘,GPU 到对端 GPU 只经过两跳交换。
关键点在于,Spine 层是“横向扩展”的。三层架构里,核心层往往要承担总流量汇聚的角色,规模大了之后单个核心设备很难扛住;但 Spine 层不用,每一台 Spine 交换机只需要连接一部分 Leaf,所有 Spine 并行工作,整体带宽可以随着 Spine 数量的增加线性扩展。这就是为什么十万卡可以压到两层——不是靠某一台超级交换机撑起全场,而是靠大量中档交换机横向铺开。
我用一个生活化的类比帮新手理解:传统三层网络像一座购物中心,所有人要先坐扶梯到中间大平台,再分流到各个店铺;两层网络更像城市地铁网,每个站点直接把客流送到目的地,中间换乘的次数最少。训练场景下,GPU 之间的通信就是“客流”,你要做的就是让客流尽可能少换乘。
2. 两层网络的架构设计:端口、带宽、收敛比怎么算
2.1 先算一笔带宽账
要设计两层网络,第一件事是确定“不收敛”需要多少带宽。训练网络跟传统网络最大的区别是:我们要求任意两个 GPU 之间的通信带宽基本等价,不能有热点。
假设每个 GPU 配一块 400Gbps 的网卡(这是当前训练集群非常常见的配置,NVIDIA H100/H200 节点一般就是 8 卡 × 400G 网卡),10 万 GPU 的总接入带宽就是:
10 万 × 400Gbps = 40,000Tbps = 40Pbps
这是一个非常大的数。Leaf 交换机怎么选?假设我们选一台 128 端口的交换机,其中下行接 GPU,上行接 Spine。为了做到 1:1 无收敛,下行口和上行口数量要相等,也就是 64 个下行口 + 64 个上行口。如果每个 GPU 占一个下行口,一台 Leaf 可以接 64 个 GPU。10 万 GPU 需要约 1563 台 Leaf 交换机。
Spine 层怎么算?每台 Leaf 有 64 个上行口,所有 Leaf 的上行口总数是:
1563 × 64 = 100,032 个 400G 上行端口
如果 Spine 交换机同样是 128 端口,那这些端口全部要用在 Leaf 互联上,也就是说 Spine 端口总数至少要 10 万多个,折合约 782 台 128 端口 Spine 交换机。这个规模确实夸张,但在机房分散到多个建筑、多个楼层的前提下,并非不可实现。而且实际工程里不一定会每个 GPU 都配一块 400G 网卡,也可能会用 2×200G 聚合,或者部分节点用更高密度交换机,端口数量可以进一步压缩。
我在实际做 2 千卡规模集群规划时,基本也是按这套逻辑倒推的:先定单卡带宽,再定交换机端口密度,最后算 Leaf 和 Spine 的数量。千万别跳步,很多小集群网络跑不满,原因就是上行端口数不够,收敛比一算就不合格。
2.2 收敛比为什么必须接近 1:1
很多人问过我校验网络的时候要不要追求 1:1 不收敛,我的回答是:训练网络必须,最少最少也要做到接近 1:1。
原因很简单,集合通信的场景里网络负载是持续全速的。以 AllReduce 为例,数据是被切块的,每个节点同时在给其他节点发送数据,也同时在接收数据。如果任何一个上行端口出现拥塞,NCCL 的进度就会卡在那个端口上,整个簇的训练速度立刻被拖慢。传统网络可以做 3:1 甚至 5:1 收敛,因为业务流量的峰值往往低于理论值;但训练流量不是“打的满不满”的问题,它天生就是“必须打满”的流量。
还有一点很多人容易忽略:NCCL 本身有“拓扑感知”。它启动时会在集群内部探测网络结构,如果发现某些路径带宽不足,它会自动调整通信顺序和切块大小。但这个过程是“被动适应”,不会让网络变快,只会让你的训练更慢。与其让 NCCL 去绕路,不如从设计上把网络做成“处处等效”,这样无论它怎么调度,结果都稳定。
所以我的建议是:端口预算先按 1:1 算,如果实在做不了,再看具体流量模型能不能把某些跨 Spine 的流量绕开。但在十万卡这种规模,没有绕的空间,所有流量都是东西向,收敛比做低了等于白买 GPU。
2.3 网络层次变小,代价转移到了哪里
层数从三层变两层,看起来是“简化”,其实只是把复杂度转移了。
第一,Spine 交换机数量暴增。前面算了,十万卡可能需要几百台 Spine 交换机,这些交换机之间的连接不是点对点直连,而是通过 Leaf 间接连接。每一台 Spine 都要跟每一台 Leaf 相连,于是光纤数量会爆炸。假设 1563 台 Leaf 和 782 台 Spine 按 1:1 互联,需要的光纤跳线数量是:
1563 × 64 = 100,032 根
这还没算 Leaf 下行到 GPU 服务器、服务器内部网卡到交换机端口的跳线。十万卡集群的光纤总量是百万根级别的。OpenAI 在相关分享里也提到,大量时间其实花在光纤部署、理线、打标签这些“脏活”上。所以两层网络省的是设备跳数,增加的是物理布线的精细度。
第二,控制面配置简化,物理面检查繁琐。两层网络的协议配置比三层简单很多,一般就是 BGP 跑 underlay、ECMP 做等价多路径,或者用动态路由协议做自动收敛,没有太多分层路由策略。但网络越简单,问题越容易出现在物理层。光模块脏了、光纤弯曲半径不够、光衰偏大、FEC 错包,这些在层数多的时候可能被高一层掩盖,但两层网络下任何物理问题都会直接反馈到 GPU 训练速度上。
我在维护训练集群时有一条心得:网络层数越少,越要重视物理层监控。每根光纤、每个光模块,都要有在线监测和告警,不然排查链路比治协议故障痛苦得多。
3. 协议与控制面:稳定压过 10 万卡的关键细节
3.1 RoCE 还是 InfiniBand:训练网络的路线之争
聊到训练网络,绕不开一个经典问题:用 RoCE(RDMA over Converged Ethernet)还是 InfiniBand?从 OpenAI 公开一些演讲和招聘信息来看,它的集群逐步转到 RoCE/以太网阵营的概率很大,而且整个行业也有明显从 InfiniBand 迁移到 RoCE 的趋势。
InfiniBand 的好处是历史包袱少,天然支持 RDMA、可靠传输、无损网络,部署完基本不用额外调优。但它的劣势是生态封闭、价格贵、供应商绑定,而且尤其在高密度大规模场景下,IB 交换机上的自适应路由(Adaptive Routing)和显式拥塞通知功能虽然强,但运维门槛高。
RoCE 则是在标准以太网上跑 RDMA,生态成熟、成本低,而且随着 400G/800G 以太网和智能网卡的发展,RoCE 在大规模集群里的表现已经越来越接近 IB。代价是,它对网络质量要求极高,必须在无损或半无损网络上工作,需要把 PFC、ECN、ETS 这些机制配好,否则一有丢包性能直接断崖式下跌。
我的经验是:RoCE 方案在大集群中完全可行,前提是你愿意投入时间去调拥塞控制参数。十万卡级别的网络里,我不推荐“跑起来就行”的心态,必须有一套完善的流控矩阵配置,甚至要在智能网卡上做 QoS 队列隔离,让集合通信流量和控制流量互相不干扰。
3.2 负载均衡从 ECMP 到多路径演进
传统以太网最常用的负载均衡是 ECMP,把流量按照五元组哈希到多条等价路径上。问题出在两条:一是哈希“碰运气”,两个大流如果哈希到同一路径,一条路径拥塞另一条空闲,训练性能就会受影响;二是大流(比如 AllReduce 中的大象流)很难靠五元组散开,因为同一个通信流的五元组是固定的。
在大规模 RoCE 网络里,为了缓解这个问题,业界普遍在做两个方向的演进。一个方向是动态负载均衡(DLB),一些新交换芯片支持按报文或按流粒度动态调整路径,感知拥塞后把流量从拥塞路径迁移到空闲路径;另一个方向是端网协同,由智能网卡根据实时拥塞信息选择合适的路径,相当于把“路由决策”从交换机搬到网卡侧。GPU 直连网卡场景下,这个趋势非常明显。
还有一个常被忽略的技术是 Packet Spraying,就是把一个流的数据包打散到所有等价路径上。它的好处是路径利用率极高,几乎不可能出现“一条路堵死、另一条路闲置”的情况,但对交换机的能力要求很高,需要芯片支持乱序重排或者接收端能处理乱序。RoCE 是保序的,要做到逐包喷洒就必须在交换机侧完成排序逻辑,目前只有部分高端芯片支持。我在规模不大(几百卡)的环境下实测过,开启 DLB 后 AllReduce 的吞吐能提升 10%~20%,这种收益在训练场景里非常可观。
3.3 NCCL 视角:集合通信是怎么“压榨”网络的
NCCL 是 NVIDIA 的集合通信库,大规模 GPU 训练几乎都跑在它上面。很多人把它当作黑盒,其实它对网络拓扑的感知非常强。启动时会做一次拓扑探测,识别 GPU 之间的 NVLink 连接方式和跨节点网卡所在 PCIe 端口,然后自动选择一个通信方案。
在两层 Leaf-Spine 拓扑下,NCCL 看到的跨节点路径是很规整的:GPU 通过本地网卡 → Leaf → Spine → 对端 Leaf → 对端网卡。链路等价性高,NCCL 就能高效地把通信切块、打散到所有可用网卡上。反过来,如果路径不对等(比如有的 GPU 多一跳、有的少一跳),NCCL 会“迁就”慢路径,把通信速度拖下来。
实际操作中,我建议跑大任务之前先看 NCCL 日志里的拓扑信息,确认它识别到了预期的拓扑结构:
# 运行前打开 NCCL 调试,观察拓扑探测结果 NCCL_DEBUG=INFO NCCL_DEBUG_SUBSYS=GRAPHE /your_app/run_training.sh如果发现 NCCL 把跨节点的通信路径识别成了“非最优”,优先检查网卡的 PCIe 分配拓扑,以及是否有网卡被 CPU 的 NUMA hop 干扰。很多时候,性能瓶颈根本不在交换机,而在服务器的 PCIe Switch 和 NUMA 拓扑上。
还有一个小技巧:NCCL 支持通过NCCL_P2P_LEVEL和NCCL_NET_GDR_LEVEL调整不同通信层级的行为。在两层网络里,通常希望跨节点通信都走 RDMA 网卡,并且尽量用 GPU Direct RDMA(GDR),避免数据从 GPU 拷贝到 CPU 内存再发出。开启 GDR 后延迟能降低 2~3 微秒,吞吐提升也很明显。
4. 十万卡规模的运维实录:常见问题与排查路径
4.1 光模块和光纤问题:最容易被忽视的“隐形杀手”
十万卡集群跟小集群最大的区别在于:物理层故障的频率被放大了上千倍。早期做小规模集群时,一个光模块坏了也就是一块 GPU 训练慢,不影响全局;但十万卡场景里,任何一条链路出问题都可能导致大范围 AllReduce 卡顿,整个训练任务被迫暂停。
最常见的光纤问题有这么几类:
- 光模块收发功率异常,通常由于光口污染或光纤弯曲半径过小引起;
- 收发波长或速率不匹配,例如交换机模块是 400G SR8,网卡模块是 400G AOC,两端协商失败;
- 尾纤跳线松动,轻载时没问题,一旦流量上来就丢包;
- FEC 错误数持续增长,链路虽然没断,但纠错开销越来越大,有效带宽下降。
排查时先用 ethtool 看端口状态和丢包计数,再量光模块收发光功率:
# 查看物理链路状态和错误计数 ethtool -S enp175s0f0np0 | grep -E "rx_errors|tx_errors|fec_corrected|fec_uncorrectable" # 查看光模块信息(速率、温度、电压、收发光功率) ethtool -m enp175s0f0np0如果光模块收光功率在接收灵敏度附近,比如 400G SR8 模块,典型接收功率在 -7dBm 到 +2dBm 之间,如果掉到 -9dBm 以下,你就该考虑清端口或换跳线了。光模块温升也很重要,交换机高密度部署下,散热不好的端口会出现热漂移,表现为白天训练慢、晚上恢复,这种情况我看过不少。
4.2 PFC 死锁与拥塞风暴:RoCE 网络的“头号杀手”
RoCE 做无损依赖 PFC 暂停帧。每条队列水压达到阈值后,交换机反向发送暂停帧,让上游发送方停止发送。这在理论上很完美,但实际运行中会出现 PFC 死锁:排队链路的背压沿着链路逐级传播,最后形成拥塞树,所有流量都卡在树的根部,表现为集群通信整体瘫痪。
这个现象在跨 Leaf-Spine 的 RoCE 网络中尤其常见。当多个 Leaf 同时向同一台 Spine 发送大量流量时,这台 Spine 的入方向队列爆满,触发 PFC 反压;反压传回 Leaf,Leaf 又把暂停帧上送给所有 GPU 网卡,结果是所有 GPU 同时进入“暂停”状态,网络吞吐直接从 400G 掉到几百 Mbps。
排查 PFC 死锁要分几步。先在交换机上抓队列统计和暂停帧计数:
# 以 Mellanox 交换机为例,查看端口 PFC 计数 show interface pause counter # 查看交换机上每个优先级队列的缓存占用 show buffer queue statistics如果发现某个队列的 PFC Transmit 计数在训练高压时段猛涨,说明该队列对端的设备一直在发暂停帧,这基本就是拥塞风暴的起点。解决方案除了调整 PFC 阈值和加权调度外,还可以从应用侧入手:给 NCCL 流量设置更小的 PFC 队列,或者用 ECN 标记替代暂停帧,提前让端侧降速,而不是等交换机缓存满了再一刀切暂停。
4.3 我总结的十万卡网络避坑清单
基于我自己运维训练集群的经验,这里列几个通用性比较强的避坑点,字字都是“花钱买来的教训”。
- 不要盲目开启“全速率自协商”。RoCE 场景下,网卡和交换机模块如果速率协商不稳定,会出现周期性的链路闪断。大集群里最好把速率、FEC 模式都固定配置,例如 400G 固定用 RS-FEC,两端一定要一致。
- FEC 计数要监控,不是只看丢包。FEC 纠错本身是透明的,但如果 uncorrectable FEC 持续出现,说明链路质量差到纠错都救不了,这会直接导致重传和训练卡顿。对 uncorrectable 计数建议做成告警阈值,超过 1 就盯紧。
- 别把所有光模块当“免维护”。高密度槽位里,积灰、氧化、接头松动几乎是必然事件。新买的吹灰工具和光纤清洁笔,可能比换机还重要。
- 变更要克制。大规模集群里,最怕的不是硬件坏,而是人类变更。每次升级交换机固件、调整 PFC 参数、替换光模块,都要有完整方案和回滚预案。曾经一次调整 ECN 阈值的变更,导致整个集群性能波动了一整天,最后靠回滚才恢复。
- 日志一定要集中化。十万卡集群里,手动登录每台交换机查日志根本不现实。所有交换机的表项、日志、端口计数必须采集到统一平台,否则出问题你连“从哪查起”都不知道。
4.4 一张问题速查表,直接贴在工位上
我自己把平时遇到的高频问题整理成了一张表,遇到问题先对着表定位,效率能提升几倍。
| 现象 | 可能原因 | 排查路径 | 解决办法 |
|---|---|---|---|
| 单 GPU 训练奇慢,其他正常 | 光模块脏或者光纤弯曲过大 | ethtool -m 查看光功率和模块温度 | 清洁光口、换线、调整布线半径 |
| 所有 GPU 同时卡顿,吞吐趋近于零 | PFC 死锁或队列缓存打满 | 交换机上查 pause counter、queue statistics | 调整阈值、限制突发流量、重分布流量 |
| 训练开始时快,运行几小时后变慢 | 光模块热漂移或交换机散热问题 | 对比不同时段温度数据和 tc 丢包计数 | 清理通风道、降低供电温度、换备用模块 |
| AllReduce 带宽远低于理论值 | 网卡队列或 PCIe 拓扑不对,NCCL 未走最优路径 | NCCL_DEBUG=INFO 观察路径,查 lspci 拓扑 | 调网卡队列数量、调整进程绑定,启用 GDR |
| 偶发重传,时好时坏 | 设备端口缓存不足或 FEC 失效 | 长时间抓 ethtool -S 的 rx_crc_errors | 更换故障模块、确保同一速率和 FEC 模式 |
这张表未必覆盖所有场景,但训练网络的问题多数绕不开这五类。熟练之后,你甚至会从“查网络”变成“查物理”,省下的精力用来研究模型调优,不香吗?
5. 两层架构的价值与借鉴:不只是超大厂能这么干
5.1 中小集群也要有“两层思维”
有人可能会说:10 万卡才需要两层,我只有 200 卡,跟我有什么关系?我觉得恰恰相反。两层的核心不是“规模大”,而是“路径短且可预期”。哪怕只有几十张卡,如果你沿用三层的思路,虽然也许不会立刻出事故,但你在设计阶段就埋下了“路径长短不一”“核心瓶颈难拆”的隐患。
小集群更现实的做法是:提前按照 Leaf-Spine 的框架去做机柜规划和网络划分。比如 32 台 GPU 服务器,分在 4 个机柜里,每个机柜放一台 Leaf,两台 Spine 做互联,保证任意两台服务器之间的网络路径一致。等将来扩容到几百卡时,你要做的只是加 Leaf、加 Spine,而不是推翻重来。
另一方面,小集群也是验证新技术的最佳场地。像前面提到的 DLB、ECN+PFC 参数、NCCL 调优技巧,都可以先在小规模上做对照实验,一点点把参数调明白,等集群大了直接照搬成熟配置。我见过太多团队,小集群将就着跑,到大集群时发现一堆历史遗留问题,最后全部重排。
5.2 下一步演进:多路径、远端内存和光交换
OpenAI 把十万卡压到两层,不代表这就是终点。在我看来,训练网络下一步会往三个方向走。
第一是真正的多路径和智能网卡联动。随着网卡侧可编程能力增强,负载均衡会从交换机逐渐上移到端侧。GPU 网卡可以选择“主动测量哪条链路空闲”,然后把数据发到更优路径上。两层网络高度等价的拓扑,恰好是最适合这类端网协同方案的土壤。
第二是远端内存池化。训练过程里经常出现显存不够用,把部分状态卸载到远端内存。如果网络能提供更低的延迟和更大的带宽,远端内存就能更“透明”地参与训练,相当于把 GPU 的可利用显存扩大了。两层架构的短路径在这里价值巨大。
第三是光交换的引入。目前 Leaf-Spine 之间还是电交换芯片做包转发,未来可能引入光电路交换(OCS),让某两个 Leaf 之间的连接按需物理层直连。这样一来,“网络压到两层”甚至“压到几乎零层”也未必不可能,GPU 之间直接走光通路,速度和延迟都会有质变。
从行业趋势看,训练网络越来越像是“算力的一部分”,而不是独立的支撑系统。谁说网络工程师不是训练团队的一员呢?至少在十万卡集群里,网络掉链子的时候,训练主管第一个找的就是你。
最后再分享一个小经验:别被“压到两层”这种说法唬住。它不是一个魔术,而是把规模、成本、延迟、运维全部权衡之后的结果。你不需要真的拥有十万卡才能借鉴这一点——只要在设计网络的任何阶段,优先让路径变短、让行为变可预期、让排查变简单,你的集群就已经在“正确的方向”上了。