AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


Imbue-70B 的 AI Infra:从0到1搭建和运维4088 H100集群的最佳实践
发布日期:2024-07-08 08:56:50 浏览次数: 2997 来源:AI闲谈


一、引言

最近 imbue 发布了其自研的 Imbue 70B 模型,各项能力与 LLaMA-3 70B 相当,在推理相关的任务上表现优于 zero-shot 的 GPT-4o。更难能可贵的是,Imbue 也进一步分享了他们从 0 到 1 构建一个大规模 GPU 集群的端到端指南(From bare metal to a 70B model: infrastructure set-up and scripts - imbue):包括网络拓扑,系统安装,模型训练遇到的各种异常,以及各种解决方案。除此之外,作者还开源了相关的工具和脚本:GitHub - imbue-ai/cluster-health。本文中我们对其进行介绍,并根据我们的经验进行注解和完善。

其实最近很多公司都公布了相关的 AI Infrastructure 以及工作,比如:

  • 字节跳动 MegaScale:[2402.15627] MegaScale: Scaling Large Language Model Training to More Than 10,000 GPUs

  • 上海 AI Lab 等 Acme:[2403.07648] Characterization of Large Language Model Development in the Datacenter

  • 阿里 C4:[2406.04594] Boosting Large-scale Parallel Training Efficiency with C4: A Communication-Driven Approach

  • 阿里 HPN:Alibaba HPN: A Data Center Network for Large Language Model Training

  • 腾讯星脉网络 2.0:大模型训练再提速20%!腾讯星脉网络2.0来了

  • 百度 HPN - AI Pod:彻底解决网络哈希冲突,百度百舸的高性能网络HPN 落地实践

  • 蚂蚁金服 DLRover:DLRover: An Automatic Distributed Deep Learning System


二、4088 H100 集群搭建

2.1 概览

如下图所示为 Imbue 从 0 开始搭建的大规模 GPU 集群。总共包含 511 个 8*H100 GPU 节点,共 4088 个 H100 GPU(PS:后文会介绍为什么不是 512 台 4096 GPU)。通过 3-Tier IB 网络实现无收敛(fully non-blocking)拓扑:


2.2 8*H100 Server

如下图所示为单个 8*H100 节点的配置:

  • GPU:包含 8 个 H100 SXM GPU,并且 8 个 GPU 使用 NVLink 互联,而没有使用 NVSwitch。(PS:这里提到了未使用 NVSwitch,如红框所示 “Avoid the term NVSwitch”,不理解为何不用 NVSwitch 实现全互联)

  • 后向网络:包含 8 个 ConnectX-7 的 InfiniBand NIC,带宽为 400 Gbps,其中每个 GPU 对应一个 NIC,并与 Leaf Switch 连接。

  • 前向网络:包含 2 个 Ethernet NIC,每个 100 Gbps。

    • 一个构建前向的数据传输网络,主要用于传输数据集、Checkpoint 以及其他数据。

    • 另一个用于组成辅助管理网络,纯粹用于配置和管理,允许访问 BIOS、电源等其他 low level 控制接口。如果没有这个网络,将不得不使用 USB 驱动器等方式手动配置节点,对于大规模集群来说不太现实。

  • 存储:一个 512GB 的硬盘用于安装 OS;还有一组 5 个 Raid2 NVME,总共 14TB 空间。

  • 管理:通过 iDRAC(戴尔的基板管理控制器)可以安装 OS;BMC(Baseboard Management Controller) 就是用于上述的辅助管理网络。

2.3 网络拓扑

其网络拓扑应该是参考了 NVIDIA H100 的标准方案,IB 网络采用的是 QM97xx 交换机,每个有 64 个 400Gbps 的 Port,在 Leaf 和 Spine 中都是 32 个下行 Port,32 个 上行 Port:

如下图所示为其对应的网络拓扑,和 NVIDIA 的 SuperPod 基本一致,总共 320 个 Switch(PS:详细介绍可以参考我们之前的文章):

  • 128 个 Leaf Switch(T2):共 16 组,每组 8 个 Switch,连接 32 个 Node。每组中的 0 号 Switch 连接 32 个 Node 中的 0 号 NIC(GPU),7 号 Switch 连接 32 个 Node 中的 7 号 NIC(GPU)。

  • 128 个 Spine Switch(T3):共 8 组,每组 16 个 Switch,连接 16 个 Leaf Switch。每一组 Spine Switch 都会与 Leaf Switch 中的对应位置互联。比如,第 5 个 Spine Switch Group 会把 16 组 Leaf Switch 中的第 5 号 Switch 连接起来。(PS:这样的好处是,集群中同卡号 GPU 通信最多只用经过 Spine Switch,而不用经过 Super Spine Switch)

  • 64 个 Super Spine Switch(T4):每一个 Super Spine Switch 都会连接 64 个 Spine Switch,也就是可以分 2 组,每组 32 个,连接 64 个 Spine Switch。

2.4 NVIDIA DGX H100 SuperPod 

如下图 Figure 5 所示为一个 127 Node 的 NVIDIA DGX SuperPod。理论上应该可以连接 128 个 Node,但是 Leaf Switch 有一部分连接了 UFM(Unified Fabric Manager),所以实际上只有 127 个 Node。

如下图 Table 3 所示,使用 QM9700 Switch,2 级 Fat-Tree 最多可以实现 64*64/2=2048 GPU 的无阻塞网络;3 级 Fat-Tree 最多可实现 64*64*64/4=65536 GPU 的无阻塞网络。不过 Imbue 采用的是 16 SU 方案,最多可以连接 4096 GPU(PS:实际上还有 UFM,所以是 4088 GPU):

2.5 4096 GPU or UFM?

 为什么要引入 UFM 而不是构成 512 Node 的完全对称结构呢?可能是两个方面的考虑:

  • 通过引入 UFM,可以实现更高效、更可靠的网络管理,从而提升整体系统性能和稳定性。

  • GPU Node 故障率很高,很难保证长时间无异常,Node 异常后通常需要屏蔽,此时也就无法实现完全对称。如果想依旧保持对称,就需要增加冗余节点,像阿里的 HPN:Alibaba HPN: A Data Center Network for Large Language Model Training,但是这又会导致无法实现完全的无收敛网络。

三、集群初始化

3.1 Node 初始化

通过辅助管理网络和 BMC(Baseboard Management Controller,即使 OS 未启动或 Node 宕机,BMC 依然可以工作,提供对系统的访问和控制),可以与每台机器进行交互,实现对硬件的监控和管理。

3.1.1 安装一个 Node

首先使用 iDRAC(戴尔的基板管理控制器)在单个 Node 上安装 Ubuntu 22.04,该 Node 将用于设置其他所有内容。IDRAC 允许从本地计算机挂载和启动 ISO image,并在浏览器中提供一个虚拟控制台。理想情况下,这个是唯一的手动安装过程。

3.1.2 安装其它 Node

安装完第一个 Node 之后,可以继续安装 Ubuntu 的 Metal-as-a-Service (MAAS) 软件来帮助配置剩余的服务器。借助 PXE(Preboot eXecution Environment)和 iDRAC 工具,可以指示每个 Node 从网络启动,并配置 MAAS 以响应 PXE 启动请求,然后就可以执行相应的安装工作。当然,安装并非一帆风顺,作者也遇到了一系列问题,比如时钟相差太大,导致 HTTPS 证书验证有问题,进而导致 apt 无法安装其他包。

3.1.3 诊断异常 Node

与其他大规模 GPU 集群初始化一样,Imbue 发现大约 10% 的机器无法启动主要是硬件问题,比如:以太网网线未连接或者接错、iDRAC 中的硬件问题、电源损坏、NVME 驱动器损坏、网卡或 GPU 无法连接。部分机器甚至返回戴尔进行进一步的测试。

3.1.4 软件安装

继续在每个 node 上安装以下软件:

  • GPU Driver(PS:集群正常运行中想要升级 GPU Driver 通常比较困难,代价很高,因此通常会安装较新的 GPU Driver,以便降低后续升级的代价)

  • Docker

  • Prometheus node exporter(PS:主要是暴露 OS 和硬件的各种指标,可以参考 GitHub - prometheus/node_exporter: Exporter for machine metrics

  • DCGM exporter(PS:主要是暴露各种 GPU 相关监控指标,可以参考 GitHub - NVIDIA/dcgm-exporter: NVIDIA GPU metrics exporter for Prometheus leveraging DCGM

  • RaidZ ZFS pool

Imbue 在并行安装软件包时甚至遇到了带宽瓶颈(PS:需要访问集群外,带宽相对集群内要小得多),并第一次收到了各种组件的高温报警,这一问题通过固件更新进行修复。

3.1.5 单 Node 验证

在安装完基础的可运行环境之后,通常还要确保每个 Node 都能独立处理真正的 GPU Workload。在这个过程中作者也发现了一系列的问题:

  • GPU 相关错误:主要是通过重新插拔 GPU 解决,需要将 Node 从机柜中取出,并重新插拔对应 GPU。

  • 固件问题:作者通过 Ubuntu 日志发现 GPU 或网卡等设备有许多 “limited width:x4 <x16” 的错误,通过更新 PCIe Switch 固件后解决。(PS:我们也遇到了 NIC 固件需要升级的情况?)

  • 线缆问题:作者也发现集群中大约 1/4 的 PCIe 线缆需要重新调整,这可能是脆弱的线缆位于外壳和 GPU 之间,每当有人对 GPU 维护的时候它们都可能被挤压或拔掉。

  • 杂项问题:这些问题通常只影响个别 Node,通常需要硬件厂商协助。

    • NVMe Driver 未显示故障,但 touch 时会死机。

    • 硬盘在 Linux 下随机顺序显示,导致 OS 安装在错误的盘上。(PS:我们遇到过 OS 被安装在数据盘的情况? )

    • 错误的温度计数,导致风扇一直 100% 转速工作。作者发现部分是 NVIDIA Driver 导致,通过降级解决。

    • CPU 的睿频异常,被限制在 2GHz。

    • Direct GPU-GPU 通信(GDR 或 GPUDirect RDMA Peer Memory Client)无法使用。

PS:在这些软件安装完之后就可以正常使用。不过通常还会进行一系列的 Benchmark 测试,比如使用 NVIDIA 的 GitHub - NVIDIA/nvbandwidth: A tool for bandwidth measurements on NVIDIA GPUs. 测试 GPU 的各种通信带宽,例如 CPU 和 GPU 之间以及 GPU 和 GPU 之间。此外,也经常会使用 GitHub - NVIDIA/cuda-samples: Samples for CUDA Developers which demonstrates features in CUDA ToolkitNVIDIA/nccl-tests

  • 有些时候一些初始化的配置不符合预期也可能导致性能不符合预期,通过 benchmark 可以发现部分问题,比如说 Troubleshooting — NCCL 2.22.3 documentation 中提到打开 IO 虚拟化(VT-d or IOMMU)有可能导致性能下降。

  • 如下图所示,我们曾经在这个阶段发现 Device to Host 的带宽明显低于 Host to Device,不符合预期,最终定位发现在初始化时不小心打开了 Intel 的 Sub NUMA Clustering(SNC),关闭之后再测试就一切正常,但是为什么 SNC 会导致 dtoh 和 htod 通信带宽不一致我们没有找到答案。

PS:通常也可以在单 Node 上执行一些真正的训练任务(比如 Resnet,Bert),并与 Benchmark MLPerf Training | MLCommons Version 2.0 Results 中的结果对比,以便验证单 Node 是否有性能瓶颈:

3.2 安装 IB

3.2.1 安装 UFM

InfiniBand 的一个优点是其中心化设计,因为它有一个用于整个网络的大脑,因此只用处理 320 个 IB Switch 中的一个实体。首要任务是弄清哪些 Switch 连接哪些 Node,然后将其与接线图相关联,并重新命名 Switch。

3.2.2 重新布线

起初,UFM 无法检测到 320 台 IB Switch,更不用说相应的 Node,最后发现其结构设计有问题:不是一个单一的统一结构,而是 8 个独立的网络。重新布线后,再次检查并验证所有物理连接与新的设计对齐。

3.2.3 上万个温度报警

在解决了物理布线后,UFM 与所有 Switch 建立连接。然而,此时还没有传输数据,但几乎每个 Switch Port 都开始报警温度过高,有些甚至超过 70 摄氏度。最终发现是网络 Rack 中 Switch 之间的空间问题,导致热空气重新循环会前部,经重新调整后解决了这个问题。

3.2.4 1800 个报警

许多 Port 依然表现出很高的错误率,或者在工作状态和损坏状态之间波动,也就是 flapping。这类问题只有 port 被使用时才出现,因此很难预先识别。此时需要数据中心合作伙伴协助清理或重新插拔,也可能需要更换光模块。虽然 IB 对硬件故障具有很强的容错能力,但一旦有 10% 的结构开始出现问题,自适应路由功能就可能无法可靠的运行。

在此期间,Imbue 尝试使用 100 到 200 个 Node 进行多 Node 训练。并尽可能的在一组随机 Node 启动,然后观察它们的性能,试图找到 IB 网络中的可靠子集。但事实证明这很难办到,每次改变训练的 Node 子集时,默认的 IB 连接子集也在变化。

3.2.5 IB 压测

为了诊断 IB 问题,Imbue 专门设计了一个针对整个集群的 Workload,该 Workload 侧重于同时尽可能地在每个 Port 发送尽量多的数据。这与大型的 AllReduce 不同,AllReduce 可以充分利用节点内的 NVLink。当大多数 Port 发送的数据量超过理论容量 97% 时,UFM 开始报警,一些 Switch 也可能崩溃。经过一天的压测,那些依旧正常的 Port 被认为足够稳定,可以继续使用,剩余的将被禁用并进行维修。相关代码可以查看:https://github.com/imbue-ai/cluster-health/tree/master/ib_burn

3.2.6 启用 GPUDirect RDMA

为了使 GPU 通信时不占用 CPU,作者打开了 GPUDirect RDMA,允许直接通过 IB NIC 通信。这涉及两个关键步骤:

  • 启用额外的内核模块:Chapter 42. GPUDirect RDMA Peer Memory Client

  • 确保 PCIe ACS(Access Control Service) 被关闭,以避免出现 Hang 的问题:Troubleshooting — NCCL 2.11.4 documentation

3.2.7 构建稳定机器组合

使用最新硬件的 GPU 集群的经验法则:预计每周约有 3% 的机器会故障。然而,有一个关键的差别可能被遗忘:并不是每台机器都有 3% 的故障率;相反,少数机器可能反复故障,直到被彻底修复。这凸显了在同一 Fabric 上拥有大量机器的优势,与其在使用随机机器的大型训练中“打地鼠”,不如专注于构建一组已知稳定的机器。

3.2.8 维护

IB 的维护主要涉及响应 UFM 报警,更换故障线缆和收发器,以及偶尔诊断更困难的错误,例如故障的交换机。大规模问题通常有两个因素引起:

  • 固件升级,可能会导致 UFM 状态异常,通常需要重启 UFM。

  • 同时大规模启动 GPU,可能同时触发 UFM 状态更新,导致问题,同样也需要重启 UFM。

四、全面的健康检查

在使用的过程中,作者发现许多因素都会导致训练失败或者速度变慢,并且许多都不会立刻展现。因此作者编写了一系列运行状态检查工具,以确保 Node 足够健康,可以用于训练。相关的脚本已经开源在 Github:https://github.com/imbue-ai/cluster-health/tree/master/health_checks

具体的检查包含以下几种:

  • GPU:检查 Node 上 GPU 数量是否正确,ECC 是否打开,是否存在 ECC Error,以及 NVLink 的拓扑等。

  • 硬盘

    • 检查硬盘使用是否超过 95%。

    • 检查 zpool 已经挂载。

  • Docker:检查 Docker 能正确运行 GPU 容器,以及监控、剖析相关容器能被赋予正确权限。

  • Dmesg:检查 dmesg 中是否有 Xids 或 SXid 错误(GPU 或 NVSwitch 相关故障)。(PS:我们通常也用来检测 OOM 相关问题,有些时候平台化的方式无法很好捕获 OOM 相关错误,比如 OOM 后被 kill,或者监控采样周期问题导致没有监测到突发的 OOM)

  • iDRAC:Imbue 采用的戴尔服务器,因此也会检查戴尔特有的 iDRAC 错误,但会忽略非致命错误。

  • IB:检查是否存在 IB 错误率增加,或者驱动进程固件过时。

  • NVLink:检查机器上的 NVLink 错误,通常不会导致训练失败,但可能导致训练降速。

  • GDR:检查是否已经启动 GDR。

  • VBIOS:检查 GPU 的 VBIOS 以及 H100 的 baseboard 是否为最新版本。

  • Flint:作者使用 flint 和 hca_self_test 来检查 Mellanox OFED 驱动、固件以及收发器固件是否是正确版本,以及它们是否适配 NVIDIA 驱动。

除此之外,还会进行一系列的测试,检查 PSB(PCIe Switch Bus)是否健康,具体来说,检查 GPU 和网卡相关的连接速度和带宽是否符合预期。也会有一系列复杂的健康检查:

  • 使用 Pytorch 初始化矩阵计算,并测量其 NVLink 带宽,GPU 计算速度以及内存。也会通过设置 GDR flag 来测试 IB 和 NVLink。

  • 使用带有 –use_cudaib_write_bw 来通过 IB NIC 发送数据并测量 PCIe 和 IB 带宽。会运行 15 分钟,以捕获不稳定的 IB 连接。

  • 运行多节点诊断程序,以检查 NCCL 初始化能力以及是否会随机失败。作者也 fork 了 NCCL 代码来添加更多的日志记录。通常需要运行 12-24 小时才能发现问题,因此通常只对新 Node 或者怀疑有问题的 node 运行。(PS:其实各个大厂也都有基于 NCCL 改造的 CCL,比如百度 BCCL,阿里 ACCL,腾讯 TCCL 等)

  • 检查 DCGM 导出的各种指标中是否有任何不符合预期的现象。比如 GPU clock 受限等。

五、诊断训练问题

硬件准备好之后即可启动正式的训练,这里作者进一步梳理了训练中的问题。

5.1 启动崩溃

从某种程度上来说,这是最好的错误,因为它们通常很容易复现并修复。首先会检查代码是否正确、配置和环境变量是否准确,虽然很基础,但也是常见的问题。然后会进一步检查机器是否都正常运行,可以通过堆栈、日志聚合平台来追踪,比如使用 Loki、Prometheus 和 Grafana。最后,作者也构建了一个失败时自动重启的系统,此时日志和错误聚合也就更加重要,避免不同任务出现混淆。

作者常遇到的错误包括:

  • 不同 Rank 间参数传递不匹配,比如“Forward order differs across ranks: rank 0 is all-gathering 43 parameters while rank 1228 is all-gathering 1 parameters”,这可能是 Pytorch FSDP 的问题,通过重启可解决。

  • GPU OOM,通常是代码问题,比如部分代码没有指定 GPU Device,导致都用了 0 号 GPU,通常可以检查最新修改的代码。

  • CPU RAM OOM,有些时候从错误日志中不太容易发现,通常最好通过 Docker 容器外 Node 上的 demsg 日志检测。

5.2 训练中崩溃

首要任务是构建自动运行系统,重新运行所有诊断检查工具,然后驱逐异常机器,并自动重新启动训练任务。有些异常通过重启可以解决,但也有些错误需要返厂或更换,比如无法纠正的 ECC Error。

此外,作者也遇到训练数据导致的异常。比如,语料库中一个非常大的单个文件可能导致 CPU 或 GPU OOM。为了防止这种问题,通常需要一个完全确定性的 DataLoader,可以指定 epoch 或 step 数,以便复现或跳过部分数据。(PS:训练中有些时候 loss 会存在 spike,也需要跳过部分 step)。

最后,通过聚合网络或 Node 的统计数据也很有帮助,有些短暂的问题可能不容易被发现,聚合后会更容易。

5.3 Hang 住(没有堆栈信息)

由于缺乏有用的信息,通常很难可靠的复现这类错误,因此调试起来非常困难。如下所示为常见的令人头疼的信息,因为训练通常是同步方式,所以可能所有节点都有同样的错误,不能区分具体是哪一个有问题:

Watchdog caught collective operation timeout: WorkNCCL(SeqNum=408951, OpType=_ALLGATHER_BASE, … , Timeout(ms)=600000) ran for 600351 milliseconds before timing out

为了解决这个问题,作者 Fork 了 NCCL 代码库,并添加了相应的时间戳(https://github.com/boweiliu/nccl/commit/0966031bdb5905b8ea5aef3fb2a8ce6317040234),以便更好地显示崩溃发生时正在执行的消息或操作,从而确定哪个 Node 或 GPU 可能阻塞了:

此外,为了识别可能存在问题的 Node,经常会找出哪些 Node 没有生成某些日志消息,缺少此类消息表明该 Node 的工作进程落后或者已经崩溃。其他没有有用错误信息的响应实例通常可能与硬件相关,为了区分 NCCL 挂起,驱动进程挂起或 Python 代码中的死锁等问题,作者使用 Py-SpyGDB 等工具来实时调试 Hang 住的进程,使用此方法能够捕获一些特定的问题。

5.4 训练变慢(MFU 下降)

这一类问题可能更加令人头大,除了 Py-Spy、堆栈跟踪检查和 GDB 外,作者也会使用 NVIDIA Nsight 等 Profiling 工具,其中的一些工具在大规模分布式环境比较难使用。

速度变慢,MFU 降低可能是多种原因引起的。首先可以检查配置、代码和环境变量是否正确。作者遇到过使用了错误的模型,Batch Size,UFM 或 NCCL 设置,以及错误的 CUDA_DEVICE_MAX_CONNECTIONS,这些都可能导致性变差。此外,测量细粒度的 MFU 也很有帮助,可以帮助诊断一系列问题:

  • 开始就是极低的 MFU(预期 1/10),并保持稳定:通常是 IB 网络硬件问题,比如 IB 交换机故障。也可能是 GPU 和 NIC 之间的硬件问题导致的。

  • 30% 预期 MFU,并且保持稳定:通常是某一个 Node GDR 设置不正确,或者 GDR 环境变量不正确造成的。

  • 60%-80% 预期 MFU,并且保持稳定:通常是 IB 链路故障导致,特别是某个 GPU 的 NIC 故障,导致流量通过 NVLink 绕行。

  • 单个 Batch MFU 突然急剧下降(下降 10 倍),并且经常发生:这通常与 Checkpointing 有关,可以检查是否与 Checkpointing 同步,针对这种情况如果添加 MFU 异常报警,将会存在很多误报。

  • 单个 Batch MFU 突然急剧下降(下降 10 倍),并且偶尔发生:这可能与其他繁重的 CPU 负载有关,比如 DataLoader 瓶颈,作者为数据加载、Checkpointing 以及非 NCCL 代码添加了计时统计,最终证明其非常有帮助。

  • MFU 曲线逐渐下降,并且在重启后恢复:理论上这可能是 Switch 上热量累积的结果,不过作者通过 Profiling 发现可能是垃圾回收机制导致,禁用自动垃圾回收和计划垃圾回收后该问题骤然消失。(PS:字节在 [2402.15627] MegaScale: Scaling Large Language Model Training to More Than 10,000 GPUs 中提到了类似的问题)

  • 一开始良好,然后突然下降(预期 70%),并以高频率持续(每 15s):最终发现这个可能与 GPU 的自动调频有关,可以通过 DCGM 收集。这通常是散热不好,温度过高或者电源故障,电压不稳等原因导致。

  • MFU 良好,但偶尔会有噪声(降到预期的 90%):这通常是网络中较高的链路(比如 T3,T4)抖动。遗憾的是,许多问题并不能追溯到特定的 Node,与 IB 相关的问题尤其难以排查。

作者也总结了一系列用于快速调试吞吐量下降的措施:

  1. 是否之前有效果而现在不行?

  2. 最近更改了哪些内容(代码,驱动)?

  3. 是否运行在健康的机器上,依赖的服务是否正常运行?

  4. 运行的代码、环境、配置、版本、机器列表、Rank 顺序、随机种子是否与上次完全相同?

  5. 是否可复现?

  6. 是否与其他任何事情相关?比如,每日 crontab、机器、DCGM 或 UFM 指标?

  7. 指标是否正确?

  8. 缩减实现(较小的模型、伪造的数据,不保存和加载 Checkpoint)时,问题是否能够复现?

六、改进 Infra 工具

经过以上的措施通常能在训练时获得良好的性能。本节中,介绍一些工具和系统,旨在确保训练继续顺利运行,理想情况下,人为干预尽量少。

几乎所有训练运行中的问题都可以归咎于 Node 或者网络组件故障,这些故障在大型集群中经常发生,因此必须自动执行故障 Node 驱逐以及请求维修过程。

6.1 故障机器

作者开发了一个系统,用于任务异常时自动从最新的 Checkpoint 启动。重新启动中将在每个可用 Node 上运行健康检查,并根据检查结果进行分类,然后从最健康的 Node 上重新启动训练作业。

6.2 网络组件故障

作者观察到所有网络组件故障都被 UFM 检测到并记录在 UFM Event 日志中,因此响应网络组件故障只需解析 UFM 日志并针对每个 Event 采取适当的操作即可。

UFM Event 系统相当复杂,包含数十种类型。然而,在实践中,作者发现只有极少数 Event 表明存在问题,主要与链路断开或高的符号错误数量有关。识别到这些 Event 之后,就能够编写相应的脚本来禁用与最近 Event 相关的连接或 Port。

6.3 本地文件缓存

主要是进出集群的以太网带宽比较小,如果很多人同时下载数据集或者 Checkpoint 可能存在瓶颈。因此,作者在本地构建了 Cache 系统,并且为了避免机器异常导致数据流失,作者采用了 3 副本配置,并使用一致性哈希来均匀分配负载。集群存储空间有限,因此还需要开发各种工具来跟踪文档的生命周期,及时清理不相关文档

6.4 本地镜像仓库

作者还使用 Kraken 来实现 Docker 镜像的点对点传输,并且使用中没有遇到任何问题。

6.5 各种性能监控工具

作者配置了默认的 Torch Profiler 和 NVIDIA Nsight。后者有助于准确捕获前向/后向传播以及 NCCL 通信时间,并有助于确定在给定模型大小和工作线程数量下,是否受到通信或计算的瓶颈。但是,Nsight 使用起来有些困难,而且需要在特权模式下运行 Docker,并且要禁用与性能监控事件相关的安全检查,此外,保存相关文档时也需要停止训练过程。

作者发现自己编写工具来检查缓慢的训练 Batch 并了解缓慢的潜在原因很有帮助,其中最有用的工具可以监控每个 Batch 花费的时间,并在异常慢时转存每个 worker 堆栈,以便进一步识别细微的硬件或软件问题。

6.6 对集群进行细分,以排查故障机器

在使用集群的最初几个月里,经常遇到这样的情况:在一组特定的机器上运行训练任务会失败,但不清楚是哪台机器有故障。为了查明故障,作者将机器划分为更细粒度的子集,并在每个子集上启动较小的作业。例如,如果一组 48 台机器的作业失败,可以将其划分为 6 个 8 台机器的子集分别启动任务;然后可以在 8 个 6 台集群的子集分别启动任务,经过交叉比对都失败的组即可得到异常的机器。(PS:蚂蚁的 DLRover: An Automatic Distributed Deep Learning System 中也提到了类似方案)

七、经验和教训

在构建和维护该训练 Infrastructure 的过程中,作者整理了一系列有用的经验教训:

  • 提供可置换的冗余 Node 非常有帮助。对于给定的训练任务,提供比运行所需 Node 多 10%-20% 的 Node 很有帮助(PS:阿里最新的 HPN 中,甚至牺牲无收敛性,为每 128 个 Node 提供了 8 个物理冗余备份),这样就可以在有 Node 故障时轻松重启作业。因为集群是全互联的,意味着可以使用集群中的任何子集。

  • 为遇到的每种硬件或软件故障编写测试或自动化解决方案很有必要,因为在训练中可能随时再次发生各种问题。此外,对于每个不透明的错误信息,编写工具使错误更易于理解也很有必要。

  • 可复现性是科学解决问题的关键。作者坚持的一条准则是:“一次只改变一件事”,即使是最简单的事。

  • 信任,但要验证。每当流程中引入外部工具或引入新人时,无论是外部或内部,都会确保仔细检查相关声明,尤其是在后续步骤取决于这些结果的情况下。


53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询