首页 / 资讯中心 / 文章详情

800卡A100集群两层CLOS与Rail-Optimized组网实践

800卡A100集群两层CLOS与Rail-Optimized组网实践 ★ FEATURED ARTICLE
一个 800 卡 A100 的集群真正先在图纸上把人逼疯的不是算力、不是存储而是网络。算力好堆卡插满就行网络不行端口数、收敛比、跳数、布线长度、光模块型号哪一项算错都要推倒重来。我最近在推演一个 800 卡规模的训练集群核心约束给得很死只用 64 端口的交换机走两层拓扑做 Fat-Tree 架构。这个题目听起来很像教科书里的经典 CLOS 练习但真把数字代进去算一遍你会发现端口账、收敛比、Rail 亲和性三者互相咬着一步算偏就得返工。这篇文章就把我这几轮推演的过程完整拆开从 GPU 通信模式倒推带宽需求到两层 CLOS 的端口公式怎么列再到为什么最后选了 Rail-Optimized 的布线方式以及上电之后 RoCE 怎么调、NCCL 怎么验证、哪些坑是我在别的项目里真踩过的。内容偏工程实操适合正在做集群网络规划、或者准备从三层 Fat-Tree 收敛到两层 CLOS 的同行参考刚接触 RDMA 组网的读者也能顺着算一遍看懂逻辑。1. 先把账算清楚800 卡到底需要什么样的网络做拓扑设计最容易犯的错是先选交换机再想业务结果算到一半发现端口不够只能加收敛比凑数。正确的顺序反过来先看 GPU 之间怎么通信通信需要多少带宽、多少跳、什么样的时延倒推出网络的硬指标再去匹配交换机和端口数。800 卡这个规模卡在一个很微妙的位置三层 Fat-Tree 明显过剩单层又接不下两层 CLOS 几乎是唯一解但两层的具体形态有好几种选错了性能和成本都难看。1.1 从 AllReduce 流量模型反推单卡带宽需求大模型训练的主流并行方式无非三种数据并行、张量并行、流水并行。这三种对网络的胃口完全不同得分开看。数据并行的核心操作是 AllReduceRing 算法下传输量约等于2(N-1)/N × MN 是参与通信的 GPU 数。800 卡的时候 (N-1)/N 约等于 0.9987基本就是 2M也就是说每一份梯度数据要在网络上走两遍。这意味着 AllReduce 的时间几乎完全由最慢的那条链路决定任何一条链路出现拥塞或者 ECMP 哈希不均整个通信环就被拖住800 张卡一起等。张量并行是另一种画风。TP 组内的 GPU 要做 AllGather 和 ReduceScatter通信频繁、消息小、时延敏感对跳数特别挑剔。每多一跳交换机端到端时延大概增加 0.8 到 1.2 微秒含转发和排队TP 组内如果跨了三跳累积起来就是好几微秒对计算占比高的算子影响很明显。这也是为什么 TP 一般限制在单机 8 卡内靠机内高速互联解决。流水并行是点对点带宽需求相对温和但对带宽稳定性要求高因为 PP 的 bubble 时间直接取决于相邻 stage 之间的传输抖动。三种模式叠加网络的设计目标就很清楚了AllReduce 要带宽和均衡TP 要低跳数PP 要稳定。落到具体数字上单卡配 200G 网卡是一个比较均衡的起点——8 卡节点就是 1.6Tbps 的出口带宽配合两层 CLOS任意两张卡之间最多两跳交换机端到端时延能压在 5 微秒以内。这里有个容易被忽略的点单卡 200G 并不意味着 AllReduce 能跑到 200G。Ring AllReduce 的有效带宽只有链路带宽的一半左右因为数据要绕环走两遍。所以 200G 网卡的 AllReduce 实测 algbw 通常在 11 到 12.5GB/s 之间busbw 才能接近 25GB/s。验收的时候别拿 algbw 对标线速会误判。1.2 为什么是两层 CLOS而不是经典三层 Fat-Tree教科书上的 Fat-Tree 是三层结构core、aggregation、edgek 端口交换机可以支持 k³/4 个主机。k64 的时候理论上是 65536 台主机规模大得离谱但代价也大——每台主机要经过三跳交换机core 层的交换机和光模块数量惊人。800 卡拆成 100 台 8 卡服务器每台 8 个 200G 端口总共 800 个接入端口。这个量级用三层是杀鸡用牛刀而且多一跳就多一份时延和一份故障概率。两层 CLOS也就是常说的 Spine-Leaf在端口数和跳数之间取得了更好的平衡Leaf 层接服务器Spine 层只做 Leaf 之间的全互联任意两台服务器之间固定两跳。真正让两层方案成立的关键是上行端口和下联端口的比例可以被精确控制。一台 64 端口交换机如果拿 32 口下联、32 口上联那单台 Leaf 的下联带宽和上联带宽天然是 1:1无阻塞就是设计出来的不是调出来的。三层 Fat-Tree 反而很难做到这么干净的比例因为 core 层的端口要分摊给多个 pod。1.3 三条硬指标无阻塞、低时延、可预测把需求收敛成可验收的指标我一般会写三条指标目标值验收方式网络收敛比1:1Leaf 层上下行对称端口带宽核算任意两卡端到端时延≤ 5μs不含网卡处理打流仪逐对测量AllReduce busbw≥ 线速的 85%NCCL 全网压测故障切换收敛时间≤ 1sECMP 重哈希拔纤注入测试“可预测”这条比较虚但对训练集群特别重要。所谓可预测是指同样的通信模式下每次跑出来的带宽波动不超过 5%。波动大通常来自 ECMP 哈希不均或者 PFC 反压扩散这两个问题在后面的配置章节会重点讲。2. 端口账怎么算两层 CLOS 的三种可行解端口计算是整个设计里最像做数学题的部分但它有唯一解吗没有。同样的 64 端口交换机、同样的 800 卡规模至少有三种自洽的方案差别在收敛比、布线复杂度、扩展余量上。这一段我把公式列出来然后把三种方案摆在一起对比。2.1 三条约束公式先把可行域框住设 Leaf 交换机数量为 L每台 Leaf 下联端口数 d上联端口数 uSpine 交换机数量 S。约束条件有三条端口守恒d u 64因为一台交换机就 64 个口。接入覆盖L × d ≥ 800考虑 breakout 的话是 L × 2d ≥ 800。上行收敛S × 64 ≥ L × u。把这三条摆开再用“上下行对称”这个额外约束u d 32能立刻得到 L ≥ 25S ≥ 12.5 也就是 13。但这只是数学可行工程上未必是最优。如果放弃严格对称允许一定收敛比可行域会宽松很多。比如 L20、d40、u24此时 S ≥ 20×24/64 7.5取 8每台 Leaf 到每台 Spine 正好 3 条链路布线极其规整收敛比是 40:24 即 1.67:1。收敛比的算法要说清楚收敛比 下联总带宽 ÷ 上联总带宽。1.67:1 的意思是所有下联端口同时满速发送时上行方向会有 1.67 倍的超订。对于 AllReduce 为主的流量全网同时满速的概率不高1.67:1 在不少生产集群里是可以接受的但要做 ECN 和 PFC 调优兜底。2.2 方案对比标准 CLOS 与 Rail-Optimized矩阵算完落到具体形态其实有两个大方向这两个方向的差别不在端口数而在哪张 GPU 卡接到哪台 Leaf。标准 CLOS的做法是一台服务器上的 8 个网卡随便分给不同的 Leaf只要保证每台 Leaf 下联的服务器数量均衡。好处是布线灵活任意一台 Leaf 故障只影响它下面挂的那几十张卡。Rail-Optimized的做法更讲究所有服务器的第 0 号 GPU 都接到同一组 Leaf称为 rail 0第 1 号 GPU 接到 rail 1 的 Leaf以此类推。这样的好处是同一 rail 内的 GPU 通信只走一跳 Leaf跨 rail 才走 Spine。对于 TP 组和部分 AllReduce 场景这个优化能显著降低时延。我把两种方案的核心参数列出来对比对比项标准 CLOSRail-OptimizedLeaf 数量13 台按 800 口算16 台8 rail × 2 台Spine 数量8 台8 台单 Leaf 下联64 个 200G 口64 个 200G 口单 Leaf 上联32 个 400G 口32 个 400G 口满载时同 rail 通信跳数1 跳同 Leaf 内1 跳稳定保证接入端口利用率96%800/83278%800/1024扩展性差端口几乎用满好可扩到 1024 卡布线复杂度中等较高需跨柜标准 CLOS 接入效率高但没余量Rail-Optimized 浪费了 22% 的接入端口换来的是确定的通信路径和扩展空间。做训练集群我倾向于后者——训练集群的扩容是常态今天 800 卡明年可能就是 1024 卡端口预留的价值远大于那点交换机成本。2.3 最终定稿16 Leaf 8 Spine 的参数表定下来的方案是 Rail-Optimized 的两层结构完整参数如下参数数值说明服务器数量100 台每台 8 卡共 800 卡单卡网卡200G RoCEv2每卡一个端口单服务器上行8 × 200G 1.6Tbps8 个独立网卡Leaf 交换机16 台64 × 400G8 个 rail每 rail 2 台Leaf 下联32 口 400G 拆 64 × 200G每台接 64 张卡Leaf 上联32 口 400G满载8 台 Spine 各 4 条Spine 交换机8 台64 × 400G满配时 64 口全下联Spine 下联当前 48 口满配 64 口预留扩展总接入能力1024 卡当前使用 800 卡全网收敛比1:1Leaf 层上下行对称当前 800 卡的实际配置是8 个 rail 中每 rail 的第一台 Leaf 接 64 张卡上联 32 口第二台 Leaf 接 36 张卡上联先配 16 口。这样每台 Spine 收到 8×4 8×2 48 条链路用 48 个端口留 16 个口给未来扩容。补齐到 1024 卡的时候每 rail 第二台 Leaf 也会接满 64 张卡上联从 16 口升到 32 口全网链路数从 384 条变成 512 条8 台 Spine 各 64 口正好用满一根线都不用重新布。这个设计的前瞻性就体现在这里——当前配置不需要把机框插满但机框和端口的分配必须按满载来规划。3. 关键设计细节从端口拆分到机柜布线拓扑图好看落地全是细节。400G 端口怎么拆成 200G、光模块选 MPO-12 还是 MPO-16、线缆怎么走、标签怎么打这些东西在图纸上看不出来但在机房里能让你多干三天。3.1 400G 拆 200Gbreakout 的四个坑用 64 口 400G 交换机接 200G 网卡必须用 breakout端口拆分。一个 400G 口通过分支光缆拆成 2 个 200G 口这是最省交换机的做法一台 64 口交换机相当于 128 个 200G 口。第一个坑是光模块和分支缆的匹配。400G 端如果用的是 8 通道并行比如 400G-SR8 或者 400G-DR4 的并行形态拆成 2 个 200G 时分支缆一端是 MPO-12 或 MPO-16 接交换机另一端分出来两个 MPO-12 接网卡。极性Type A / Type B / Type C必须和主干保持一致接反了不通而且不通得毫无提示灯亮着但链路起不来。第二个坑是FEC 配置。200G 走 PAM4前向纠错默认是 RS-FEC544某些网卡在特定固件下需要显式打开或者降级到 FC-FEC否则误码率高得离谱表现为链路 up 但一跑流量就丢包。我一般是先在两端手动对齐 FEC 模式确认跑通再交给自动协商。第三个坑是分支缆长度。分支缆本身有一定长度常见 1 到 3 米从交换机端口分出来后要在机柜内绕到配线架。如果分支缆选短了端口位置和配线架位置对不上只能整根换。买之前拿卷尺在机柜上量一遍比看图纸靠谱。第四个坑是同一 400G 口的两个 200G 子口不能提前混用。一个 400G 口拆开后两个子口必须都归属同一台 Leaf 的同一组 rail不能一个接 rail 0 一个接 rail 3否则 breakout 的物理通道就乱了。在规划表里要把“物理端口号 → 逻辑端口号 → 服务器编号 → GPU 序号”四者的映射一次性定死。3.2 上行链路怎么分配LAG 还是 ECMP每台 Leaf 有 32 个 400G 上行口8 台 Spine每台 4 条链路。这 4 条链路有两种接法第一种是LAG链路聚合把到同一台 Spine 的 4 条链路捆成一个逻辑口。好处是配置简单坏处是哈希粒度粗同一个 LAG 内部容易极化而且一台 Spine 故障时整个 LAG 起不来重收敛慢。第二种是ECMP等价多路径4 条链路各自是独立的三层接口跑 eBGP 或者 OSPF靠路由的等价路径做负载。这是大集群的主流做法哈希粒度细到每一条物理链路单条链路故障只影响 1/32 的上行带宽重收敛在毫秒级。我选 ECMP。配置上的关键是把哈希字段配对。RoCEv2 的流量是 UDP 封装哈希必须包含源 IP、目的 IP、UDP 源端口、UDP 目的端口四个字段少配一个都会导致大量流量落在同一条链路上。有些交换机默认只哈希 IP 五元组里的三层信息对 RoCE 这种源端口随机的流量反而不友好得手动打开四层哈希。3.3 线缆规划与机柜布局13 个计算柜放 100 台服务器12 柜满配 8 台1 柜 4 台Leaf 集中放在两个网络柜里。这种放法的问题是服务器到 Leaf 的距离可能超过 30 米铜缆和 AOC 都够呛。实际方案是服务器到 Leaf 走MPO 主干光缆 配线架。每个机柜顶部配一个高密度光纤配线架服务器出来的分支缆先上配线架通过主干光缆拉到网络柜再从网络柜的配线架跳线到 Leaf。这样线缆长度可控后期改线也只需要动跳线不用重新穿线。主干光缆的数量按满载算当前 400 根下联分支缆、384 根上联主干。满载时是 512 根下联 512 根上联。主干光缆一次性按满载敷设分支缆按需买这是比较省钱的节奏。线缆类型数量当前数量满载备注400G 转 2×200G 分支缆400 根512 根服务器侧400G 上联主干384 根512 根Leaf 到 Spine200G 网卡侧模块800 个1024 个与网卡同厂兼容性最好配线架15 个15 个每柜一个含网络柜强烈建议主干光缆按满载一次布好。后期扩容时最贵的不是光模块是停机穿线的人工和风险。线缆在桥架里多躺一年不花钱等到要扩的时候再穿得停半层楼的业务。3.4 命名规范让排障时间缩短一半设备命名和端口标签看起来是小节实际上是排障效率的分水岭。我用的规则是Leaf 命名为lf-r{rail}-{序号}比如lf-r0-01、lf-r0-02Spine 命名为sp-01到sp-08。服务器命名为node-{三位编号}每个网卡端口标签写成node-001-g0到node-001-g7g 后面的数字就是 GPU 序号也是 rail 号。这样做的直接好处是NCCL 报错说mlx5_3通信异常你能立刻定位到第 3 号 rail 的 Leaf再顺着标签找到具体端口和服务器。没有这套命名机房排障就是大海捞针。端口描述也要写进交换机配置里格式统一为to:node-001-g0或者to:sp-03:e1/1。几个月后回头看配置这些描述能救命。4. 上电到通流配置顺序与调优参数设备上架、线缆插好、灯全绿这只是物理层通了离“能跑训练”还差一整套配置。这一段按我实际的操作顺序走一遍每一步都说明为什么这么做。4.1 网络层设计为什么用 L3 到 Leaf大集群的主流做法是L3 到 Leaf也就是服务器网关放在 Leaf 上Leaf 和 Spine 之间跑三层路由。早期的 L2 大二层方案VXLAN、STP 或者 TRILL在 800 卡这个规模下问题太多广播域过大、STP 收敛慢、故障域不可控。L3 到 Leaf 的好处是每个 Leaf 就是一个小型广播域故障被限制在局部。Leaf 和 Spine 之间跑 eBGP每台 Leaf 用自己的私有 ASNSpine 用一个公共 ASN配置量不大但扩展性好。ASN 规划我一般这么分Spine 用 AS 650008 台都用一个Leaf 从 65001 排到 65016一台一个。eBGP 邻居关系是每台 Leaf 和 8 台 Spine 全互联一台 Leaf 上有 8 个邻居一台 Spine 上有 16 个邻居。# Leaf 侧配置示意伪代码不同厂商语法有差异 router bgp 65001 neighbor 10.0.0.1 remote-as 65000 neighbor 10.0.0.2 remote-as 65000 ! ... 一直到 10.0.0.8 address-family ipv4 unicast network 10.100.1.0/24 ! 本 Leaf 下的服务器网段 maximum-paths 8 ! 开启等价多路径maximum-paths 8这行是关键不开的话 BGP 只选一条最优路径ECMP 就废了32 条上行链路只用 1 条带宽直接掉到 1/32。4.2 ECMP 哈希与全局负载均衡普通 ECMP 有个毛病叫哈希极化不同的 Leaf 之间流量模式不一样有的 Leaf 上行流量集中在少数几条链路上虽然总体带宽够用但局部已经打满了。根本原因是 ECMP 哈希用的是固定的五元组同一个流永远走同一条路而大量同源同目的的大流会让哈希分布严重偏斜。解决手段是GLB全局负载均衡。它的做法是在转发面动态感知每条链路的利用率把流量往空闲链路上引导而不是死守哈希结果。开启 GLB 之后长流的分配会随负载动态调整实测在 AllReduce 场景下链路利用率标准差能从 18% 降到 5% 以内。代价是 GLB 会导致少量的乱序。对 RoCE 来说乱序本身不是问题问题是乱序被网卡当成丢包触发重传反而恶化。所以开 GLB 之前必须确认网卡侧支持乱序容忍大多数现代 RDMA 网卡都支持并且把乱序容忍的窗口配大一点。4.3 RoCEv2 的三个核心参数PFC、ECN、DCQCNRoCEv2 的流量控制是三件套缺一不可PFC优先级流控兜底防止缓冲区溢出丢包。配置时要单独划分一个无损队列用 DSCP 值标记。我一般用 DSCP 26 对应优先级 3服务器侧和交换机侧必须完全一致有一处不一致就会变成有损队列。ECN显式拥塞通知主动标记让发送端提前降速。阈值设置有一套算法核心是带宽时延积BDP。400G 链路的 BDP 大约是 400Gbps × 1μs 50KB。ECN 的 Kmin 设成 BDP 的 3 倍150KB 左右Kmax 设成 BDP 的 30 倍1.5MB 左右标记概率从 0 线性升到 100%。DCQCN是网卡侧的速率控制算法靠 ECN 标记驱动。参数里最关键的是降速因子和恢复速率配得太激进会导致速率震荡配得太保守则收敛慢。参数推荐值调整依据PFC 队列Prio 3DSCP 26全网一致PFC 触发门限缓冲区 30%配合 headroom 调整ECN Kmin150KB3 × BDPECN Kmax1.5MB30 × BDPECN 标记概率0-100% 线性默认DCQCN 降速因子0.5实测震荡明显时上调到 0.7DCQCN 恢复速率5 Mbps/流大规模时降低MTU9000或 4200全网一致MTU 一定要全网统一。交换机和服务器两侧有一边是 9000 一边是 1500会表现为“小包能通、大包丢”排查起来极其费时。我的做法是在建网阶段就用大包 ping 逐段验证ping -M do -s 8972。4.4 NCCL 拓扑识别与 rail 亲和性验证网络配好了不代表 NCCL 用对了路径。NCCL 启动时会自己探测拓扑但如果 Linux 侧看不到正确的网卡到 GPU 的亲和关系它会选错网卡导致流量走错 rail。验证方法很直接先看亲和性映射# 查看每个网卡对应的 NUMA 和 GPU nvidia-smi topo -m # 检查 NCCL 识别到的网卡 NCCL_DEBUGINFO NCCL_DEBUG_SUBSYSINIT,NET \ all_reduce_perf -b 8 -e 128M -f 2 -g 8 21 | head -50输出里会打印NET/IB : Using [0]mlx5_0:1这类信息把用到的网卡列表和topo -m的映射对一遍如果 NCCL 用的网卡和预期不一致用环境变量锁定export NCCL_IB_HCAmlx5_0,mlx5_1,mlx5_2,mlx5_3,mlx5_4,mlx5_5,mlx5_6,mlx5_7 export NCCL_IB_GID_INDEX3 # RoCEv2 常用 export NCCL_SOCKET_IFNAMEbond0 # 控制面走普通网卡 export NCCL_IB_TC26 # 和 DSCP 26 对应NCCL_IB_TC这个参数很多人会漏它的作用是把 NCCL 发出的流量打到正确的无损队列上。不配的话
阅读完成 · 觉得有帮助?
咨询建站