Imbue-70B 的 AI Infra:从0到1搭建和运维4088 H100集群的最佳实践
最近大模型赛道又有新动静:Imbue 发布了自研的 70B 参数模型,性能直接对标 LLaMA-3 70B,在某些推理任务上甚至超过了 zero-shot 的 GPT-4o。但更值得关注的是,Imbue 还顺手公开了一份从零搭建大规模 GPU 集群的端到端实操指南——从裸机到跑起 70B 模型,网络拓扑怎么搭、系统怎么装、训练中踩过哪些坑、怎么填的,全写出来了。配套的工具和脚本也一并开源在 GitHub。本文就围绕这份指南展开,结合我们自己的实战经验做些补充和注解。
其实最近不少公司都晒出了自家的 AI 基础设施方案,比如字节跳动的 MegaScale(万卡级训练)、上海 AI Lab 的 Acme、阿里的 C4 和 HPN、腾讯的星脉网络 2.0、百度的 HPN-AI Pod,还有蚂蚁的 DLRover。这个领域正在加速从“能不能跑”进入“怎么跑得稳、反赌”的阶段。
二、4088 H100 集群搭建
2.1 概览
Imbue 整个集群有 511 个 8×H100 GPU 节点,合计 4088 块 H100。为什么不是 512 台、4096 块?后面会解释。网络用的是 3 层 InfiniBand 胖树,实现了无收敛(fully non-blocking)拓扑。
2.2 8×H100 Server
单个节点的硬件配置如下:
- 8 块 H100 SXM,通过 NVLink 互联,但没有用 NVSwitch。原文特别注明了“A void the term NVSwitch”,这一点比较有意思——不用 NVSwitch 怎么实现全互联?可能和他们的拓扑设计有关。
GPU:
- 8 个 ConnectX-7 InfiniBand 网卡,每块 400 Gbps,每个 GPU 对应一个网卡,直连到 Leaf 交换机。
后向网络:
- 2 个以太网卡,每个 100 Gbps。
前向网络:
- 一个用于传输数据集、Checkpoint 等数据。
- 另一个组成辅助管理网络,专门用于配置和管理,可以访问 BIOS、电源等底层控制接口。没有这个网络的话,大规模集群中手动配置每个节点基本不现实。
- 一块 512GB 硬盘装操作系统;一组 5 块 NVMe 组成 Raid2,共 14TB。
存储:
- 通过 iDRAC(戴尔基板管理控制器)安装系统,BMC 用于辅助管理网络。
管理:
2.3 网络拓扑
IB 网络采用了 NVIDIA 的标准方案,交换机型号 QM97xx,每个 64 个 400Gbps 端口,Leaf 和 Spine 均配置 32 个下行、32 个上行。整体拓扑和 NVIDIA SuperPod 基本一致,总共 320 台交换机:
- 分 16 组,每组 8 台,连接 32 个节点。每组中第 0 号交换机连接 32 个节点的 0 号网卡,第 7 号连接 7 号网卡。
128 个 Leaf Switch(T2):
- 分 8 组,每组 16 台,连接 16 个 Leaf。每组 Spine 与 Leaf 中对应编号的交换机互联。这样同卡号的 GPU 通信最多只经过 Spine,不用绕 Super Spine。
128 个 Spine Switch(T3):
- 每个连接 64 个 Spine,分成 2 组,每组 32 台。
64 个 Super Spine Switch(T4):
2.4 NVIDIA DGX H100 SuperPod
参考 NVIDIA 的 DGX SuperPod,127 个节点。理论上可以到 128,但因为 Leaf 交换机有一部分要连接 UFM(统一结构管理器),所以实际只用了 127 个节点。
用 QM9700 交换机,2 级胖树最多支持 2048 个 GPU 无阻塞;3 级胖树最多 65536 个。Imbue 采用 16 SU 方案,理论上能连 4096 个 GPU,算上 UFM 占用,实际是 4088。
2.5 4096 GPU or UFM?
为什么不凑到完整的 512 节点对称结构?可能有两点考虑:一是 UFM 能带来更高效可靠的网络管理,提升整体稳定性和性能;二是 GPU 节点故障率不低,很难长期无异常。一旦节点出问题需要隔离,对称结构就被打破了。如果硬要维持对称,就得加冗余节点(比如阿里 HPN 的做法),但那又会导致无收敛网络无法实现。
三、集群初始化
3.1 Node 初始化
通过辅助管理网络和 BMC(即使系统未启动或宕机也能工作),可以远程与每台机器交互,实现硬件监控和管理。
3.1.1 安装第一个 Node
先用 iDRAC 在单台节点上装 Ubuntu 22.04,这台节点将作为后续所有配置的母机。iDRAC 支持从本地挂载 ISO 镜像并在浏览器中提供虚拟控制台。这是整个过程中唯一需要手动操作的部分。
3.1.2 批量安装其他 Node
装好第一台后,用 Ubuntu 的 MAAS(Metal-as-a-Service)来完成剩余服务器的自动安装。通过 PXE 和 iDRAC 工具,让每个节点从网络启动,MAAS 响应 PXE 请求并执行安装。当然过程不会一帆风顺:Imbue 遇到了时钟偏差导致 HTTPS 证书验证失败,进而影响 apt 安装软件包。
3.1.3 诊断异常 Node
和所有大规模集群初始化一样,大约 10% 的机器无法正常启动,基本都是硬件问题:以太网线没插或插错、iDRAC 硬件故障、电源损坏、NVMe 损坏、网卡或 GPU 无法识别。部分机器甚至直接退回戴尔做进一步检测。
3.1.4 软件安装
在每个节点上安装以下软件:
- GPU Driver(建议装新版,因为后续升级代价高)
- Docker
- Prometheus node exporter(暴露 OS 和硬件指标)
- DCGM exporter(暴露 GPU 监控指标)
- RaidZ ZFS pool
有趣的是,Imbue 在并行安装时居然遭遇了带宽瓶颈——访问集群外的带宽远小于内部,导致下载卡住。同时第一次收到了各种高温报警,后来通过固件更新解决。
3.1.5 单 Node 验证
装完环境后,需要确认每个节点能独立跑 GPU 负载。这个过程中发现问题还真不少:
- 基本靠重新插拔解决,得把节点从机柜里抽出来操作。
GPU 错误:
- Ubuntu 日志显示 GPU 或网卡有“limited width:x4 < x16”错误,更新 PCIe Switch 固件后解决。我们之前也遇到过 NIC 固件需要升级的情况。
固件问题:
- 约 1/4 的 PCIe 线缆需要重新调整。这些线缆位于外壳和 GPU 之间,每次维护 GPU 都可能被挤压或拔松。
线缆问题:
- 包括 NVMe 看似正常但 touch 会死机、硬盘在 Linux 下随机排序导致 OS 装错盘(我们踩过同样的坑)、温度传感器异常导致风扇全速转(降级驱动解决)、CPU 睿频被限制在 2GHz、GDR 无法使用等。
杂项:
这些软件装完基本就能用了,但通常还会跑 benchmark 做验证,比如用 nvbandwidth 测 GPU 通信带宽,用 nccl-tests 做性能测试。有些初始配置不符合预期会导致性能偏差,比如 IO 虚拟化(VT-d/IOMMU)可能引起性能下降。我们曾在这个阶段发现 Device to Host 带宽明显低于 Host to Device,最后定位是初始化时不小心打开了 Intel 的 Sub NUMA Clustering(SNC),关掉后恢复正常。至于 SNC 为什么会导致带宽不对称,至今没找到明确答案。
此外也可以单节点跑一些真实训练任务(如 ResNet、BERT),对照 MLPerf 结果验证有无瓶颈。
3.2 安装 IB
3.2.1 安装 UFM
InfiniBand 的好处是有一个中心化的“大脑”——UFM。首先要搞清楚哪些交换机连哪些节点,然后对应接线图,重命名交换机。
3.2.2 重新布线
刚开始 UFM 检测不到全部 320 台 IB 交换机,更别提节点了。后来发现结构设计有误:本来应该是一个统一结构,却被搭成了 8 个独立的网络。重新布线后再逐一核对物理连接。
3.2.3 上万个温度报警
布线搞定后 UFM 与所有交换机建立了连接,但数据还没跑,几乎每个端口都开始报温度过高,有些甚至超过 70℃。最后发现是机柜内交换机之间的空间问题导致热空气回流,调整后解决。
3.2.4 1800 个报警
很多端口依然报高错误率,或者在正常和损坏状态之间来回切换(flapping)。这类问题只有在端口被使用时才暴露,所以很难提前发现。需要数据中心伙伴协助清理或重新插拔,有时还得换光模块。IB 对硬件故障有很强的容错能力,但一旦有 10% 的结构出问题,自适应路由功能就可能不可靠。Imbue 尝试用 100~200 个节点做多节点训练,但每次换节点子集,默认的 IB 连接子集也在变,很难定位问题。
3.2.5 IB 压测
为此他们专门设计了一个高负载测试:尽可能在每个端口同时发送大量数据,而不是 AllReduce(因为 AllReduce 会大量利用 NVLink)。当大部分端口负载超过理论容量 97% 时,UFM 开始报警,有些交换机直接崩溃。持续压测一天后,仍然正常的端口被视为稳定,剩下的被禁用等待维修。相关代码已开源。
3.2.6 启用 GPUDirect RDMA
为了让 GPU 通信时绕过 CPU,需要打开 GPUDirect RDMA。两个关键步骤:启用额外内核模块(nvidia-peermem),并关闭 PCIe ACS(Access Control Service)以避免系统挂死。
3.2.7 构建稳定机器组合
使用最新硬件 GPU 集群的经验法则是:每周约 3% 的机器会故障。但要注意,并非每台机器都是 3%——少数机器可能反复故障直到彻底修复。这就是大规模集群的优势:与其在随机机器上“打地鼠”,不如集中精力组建一组已知稳定的机器。
3.2.8 维护
IB 维护主要就是响应 UFM 报警、更换故障线缆和收发器,偶尔诊断交换机故障。大规模问题通常有两种:固件升级导致 UFM 状态异常(需重启 UFM),以及同时大规模启动 GPU 导致 UFM 状态更新冲突(同样需要重启 UFM)。
四、全面的健康检查
实际使用中发现,很多因素会导致训练失败或降速,而且不少问题不会立刻显现。于是 Imbue 写了一套健康检查工具(已开源),确保节点足够健康再投入训练。具体包括:
- 检查数量、ECC 是否开启及有无错误、NVLink 拓扑等。
GPU:
- 使用率不超过 95%,zpool 已挂载。
硬盘:
- 能正确运行 GPU 容器,监控、剖析相关容器权限正确。
Docker:
- 检查是否有 Xids 或 SXid 错误(GPU/NVSwitch 故障)。我们也会用它检测 OOM 问题,因为有些 OOM 在监控采样周期内可能漏掉。
Dmesg:
- 检查戴尔特有错误,忽略非致命项。
iDRAC:
- 错误率、驱动/固件版本。
IB:
- 错误通常不影响训练但会导致降速。
NVLink:
- 确认已启用。
GDR:
- GPU 和 baseboard 固件是否为最新。
VBIOS:
- 检查 Mellanox OFED 驱动、固件及收发器固件版本是否匹配。
Flint:
此外还会检查 PCIe Switch Bus(PSB)是否健康,确认 GPU 和网卡的相关连接速度和带宽符合预期。更复杂的健康检查包括:
- 用 PyTorch 初始化矩阵计算,测量 NVLink 带宽、GPU 计算速度和显存,并通过 GDR flag 测试 IB 和 NVLink。
- 用
ib_write_bw --use_cuda通过 IB 网卡发送数据并测量 PCIe 和 IB 带宽,跑 15 分钟以捕捉不稳定的 IB 连接。 - 运行多节点诊断程序检查 NCCL 初始化和随机失败情况。Imbue 还自己 fork 了 NCCL 代码加了更多日志。这套测试通常要跑 12~24 小时才能发现问题,所以一般只对新节点或可疑节点运行。各大厂也都有基于 NCCL 改造的 CCL,比如百度 BCCL、阿里 ACCL、腾讯 TCCL 等。
- 检查 DCGM 导出的指标是否有异常,比如 GPU clock 受限等。
五、诊断训练问题
硬件就绪后正式开训,Imbue 整理了一系列训练中可能遇到的问题。
5.1 启动崩溃
这类错误最好处理,因为容易复现。先检查代码、配置和环境变量,虽然基础但常出问题。然后确认机器是否都正常,用 Loki、Prometheus、Grafana 等日志聚合平台追踪。Imbue 还构建了失败自动重启系统,此时日志和错误聚合就变得尤为重要,避免不同任务混淆。常见错误包括:
- 不同 Rank 间参数传递不匹配(例如“Forward order differs across ranks”),可能是 PyTorch FSDP 的问题,重启可解决。
- GPU OOM,通常是代码问题,比如部分代码没指定 GPU 设备导致全挤到 0 号卡。可以检查最近修改的代码。
- CPU RAM OOM,日志里不太容易发现,最好通过容器外节点的 dmesg 检测。
5.2 训练中崩溃
首要任务是搭建自动诊断系统:重新运行所有健康检查,驱逐异常机器,然后自动重启训练。有些错误重启就能解决,有些则需要返厂或更换,比如不可纠正的 ECC 错误。Imbue 还遇到过训练数据导致的问题,比如语料库中一个超大文件触发了 CPU 或 GPU OOM。为防止这种情况,需要一个完全确定性的 DataLoader,能指定 epoch 或 step 数,方便复现或跳过。训练中 loss 有时会出现 spike,也需要跳过部分 step。最后,聚合网络或节点的统计信息很有帮助——有些短暂问题不聚合很难发现。
5.3 Hang 住(没有堆栈信息)
这是最难调试的一类,因为没有有效信息,很难可靠复现。常见信息如 NCCL 超时错误:所有节点都可能显示同样的超时,没法区分具体是哪台出了问题。Imbue 为此 fork 了 NCCL 代码,添加时间戳,以便确认崩溃发生时正在执行的操作,从而定位阻塞的节点或 GPU。他们还通过“反向定位法”——找出哪些节点没有生成某些日志消息,来判断工作进程是否落后或崩溃。此外,用 Py-Spy 和 GDB 实时调试挂起的进程,能捕获到一些特定问题。
5.4 训练变慢(MFU 下降)
这种问题更让人头疼。除了 Py-Spy、堆栈检查和 GDB,还可以用 NVIDIA Nsight 等 Profiling 工具,不过在大规模分布式环境下不太好用。MFU 下降的原因多样:
- 通常是 IB 网络硬件问题,比如交换机故障,也可能是 GPU 和网卡之间的硬件问题。
一开始就极低(预期 1/10)且稳定:
- 通常是一个节点的 GDR 设置不对,或环境变量配置错误。
30% 预期 MFU 且稳定:
- 通常是 IB 链路故障,比如某块 GPU 的网卡坏了,导致流量绕道 NVLink。
60%~80% 预期 MFU 且稳定:
- 通常和 Checkpointing 有关。如果配置了 MFU 异常报警,可能会有很多误报。
单个 Batch MFU 突然下降 10 倍且频繁:
- 可能与其他繁重 CPU 负载有关,比如 DataLoader 瓶颈。Imbue 为数据加载、Checkpointing 和非 NCCL 代码加了计时统计,效果很好。
单个 Batch MFU 突然下降 10 倍且偶尔发生:
- 理论上可能是交换机热量累积,但 Profiling 发现是垃圾回收机制导致的。关闭自动垃圾回收并改为计划回收后问题消失。字节的 MegaScale 论文中也提到过类似现象。
MFU 逐渐下降,重启后恢复:
- 可能与 GPU 自动调频有关,通过 DCGM 可以收集。通常是散热不好、温度过高,或者电源故障、电压不稳。
一开始良好,突然下降到 70% 且每 15 秒一次:
- 往往是网络中较高链路(如 T3、T4)的抖动。遗憾的是,很多问题无法追溯到特定节点,IB 相关问题尤其难查。
MFU 良好但偶尔有噪声(降到 90%):
Imbue 总结了一套快速调试吞吐量下降的 checklist:
- 之前有效现在不行吗?
- 最近改了哪些内容(代码、驱动)?
- 机器是否健康?依赖的服务是否正常?
- 代码、环境、配置、版本、机器列表、Rank 顺序、随机种子是否与上次完全一致?
- 是否能复现?
- 是否与其他任何事情相关,比如 crontab、机器、DCGM 或 UFM 指标?
- 指标是否正确?
- 缩小规模后(小模型、伪造数据、不做保存/加载检查点)问题能否复现?
六、改进 Infra 工具
经过前面的措施,训练通常能跑出不错的效果。但要让训练持续顺利运行,还需要一些自动化的工具和系统,尽量减少人工干预。几乎所有训练故障都可归结为节点或网络组件失效——在大规模集群中这是常态,所以自动驱逐故障节点并启动修复流程是必须的。
6.1 故障机器
Imbue 开发了一套系统:任务异常时自动从最新 Checkpoint 重启。重启时在所有可用节点上运行健康检查,根据结果分类,然后从最健康的节点上重新启动训练。
6.2 网络组件故障
所有网络组件故障都被 UFM 检测并记录在事件日志中。所以只需要解析 UFM 日志,针对每个事件采取相应操作。UFM 事件系统很复杂,有几十种类型,但实践中只有少数几种真正表明有问题:主要是链路断开或高符号错误。识别出这些事件后,可以写脚本自动禁用相关连接或端口。
6.3 本地文件缓存
进出集群的以太网带宽相对较小,多人同时下载数据集或 Checkpoint 容易成为瓶颈。Imbue 在本地搭了缓存系统,用 3 副本配置加一致性哈希均匀分配负载。集群存储空间有限,所以还得开发工具跟踪文档生命周期,及时清理无用文件。
6.4 本地镜像仓库
使用 Kraken 实现 Docker 镜像的点对点传输,运行下来没有遇到问题。
6.5 各种性能监控工具
默认配置了 Torch Profiler 和 NVIDIA Nsight。Nsight 能准确捕获前向/后向传播及 NCCL 通信时间,帮助判断在给定模型大小和线程数下,瓶颈在通信还是计算。但 Nsight 用起来有点麻烦:Docker 需要特权模式,还要禁用与性能监控事件相关的安全检查,保存文档时也得停训练。Imbue 发现自己编写工具来检查缓慢的 Batch 并了解原因更实用——最有用的工具是监控每个 Batch 的耗时,在异常慢时转存每个 worker 的堆栈,从而定位细微的硬件或软件问题。
6.6 对集群进行细分,以排查故障机器
早期经常遇到训练任务在一组机器上失败却不知道具体哪台有问题。Imbue 的做法是把机器分成更小的子集,在每个子集上启动小作业。比如一组 48 台机器失败,就分成 6 个 8 台子集分别跑;如果还有问题,再在 8 组 6 台集群的子集上跑,交叉比对就能锁定异常机器。蚂蚁的 DLRover 中也提到过类似方案。
七、经验和教训
总结下来,有几点值得记取:
- 对于给定的训练任务,提供比实际需求多 10%~20% 的节点会很有帮助(阿里 HPN 中甚至牺牲无收敛性,为每 128 个节点配了 8 个物理冗余备份)。这样节点故障时可以轻松重启作业,因为集群是全互联的,任何子集都可以用。
冗余节点很重要:
- 遇到的每种硬件或软件问题都值得写一个测试或自动修复脚本,因为下次训练很可能再次出现。另外,对于每个不透明的错误信息,最好写工具使其更易理解。
为每种故障编写自动化方案:
- 坚持“一次只改变一件事”的准则,即使那件事看起来最简单。
可复现性是解决问题的关键:
- 当流程中引入外部工具或新人时,无论内外,都要仔细检查相关声明,尤其是后续步骤依赖这些结果的情况下。
信任,但要验证:
-
- 关于宇宙的好的网名有哪些
- 角色扮演 | 1
- 网名