从裸机到700亿参数大模型,这里有份教程,还有现成可用的脚本
- 2024-07-25 00:32:00
- admin 原创
- 116
我们知道 LLM 是在大规模计算机集群上使用海量数据训练得到的,机器之心曾介绍过不少用于辅助和改进 LLM 训练流程的方法和技术。而今天,我们要分享的是一篇深入技术底层的文章,介绍如何将一堆连操作系统也没有的「裸机」变成用于训练 LLM 的计算机集群。
这篇文章来自于 AI 初创公司 Imbue,该公司致力于通过理解机器的思维方式来实现通用智能。
当然,将一堆连操作系统也没有的「裸机」变成用于训练 LLM 的计算机集群并不是一个轻松的过程,充满了探索和试错,但 Imbue 最终成功训练了一个 700 亿参数的 LLM,并在此过程中积累了许多有用的经验。
本文将深入介绍该团队构建自己的 LLM 训练基础设施的全过程,并会分享他们为方便监控、检查和纠错而编写的诸多工具和脚本。
如果你有心构建自己的 LLM 训练基础设施或好奇 LLM 是如何炼成的,那么这篇文章值得你阅读和收藏。
以下是 Imbue 团队文章原文。
引言
我们这个由研究者和工程师组成的小团队用了几个月时间在自己的基础设施上从头开始训练了一个 700 亿参数量的模型,并且该模型在推理相关的任务上胜过了零样本的 GPT-4o。
今天,我们要分享的是设置所需基础设施的过程:从组合初始集群和安装操作系统到设置在训练期间遭遇错误时自动恢复。我们会详细说明在每一步遭遇到的难题和解决方法。除了这些心得之外,我们还将发布我们一路上开发的许多脚本,以便其他团队能更轻松地为自己的模型训练创建稳定的基础设施。
在整个过程中,我们的工程师团队与 Voltage Park 一起准备好了计算机集群,构建了生产应用的基础。这整个过程包括:
1. 配置各台机器
2. 配置 InfiniBand
3. 确保机器完全健康
4. 诊断常见的训练问题
5. 改进基础设施工具
下面将详细描述每个步骤。
背景:这是如何炼成的
我们执行计算的目标是确保能快速实验大型语言模型。为此,我们需要大量高速 GPU,并且这些 GPU 之间也能高速通信。
本文将重点关注一个集群,其中包含分散在 511 台计算机中的 4088 台 H100 GPU,也就是每台计算机 8 台 GPU。之所以有 511 台带 GPU 的计算机,是因为需要保留一些连接给统一结构管理器(Unified Fabric Manager)节点,其作用是管理 InfiniBand 网络。在 511 台带 GPU 的主机上,每台 GPU 都直接与一块 ConnectX-7 网卡相连,其能以 400 Gbps 的速度与该 InfiniBand 网络中的任意 GPU 传输数据。
我们的 InfiniBand 网络拓扑结构 的形式是「fully non-blocking」,即完全无阻塞;理论上讲,这能让 GPU 以最大速度互相通信。为此,我们使用了一种三层式 InfiniBand 网络架构:三层 InfiniBand 交换机。只要连接正确,便能让整个网络都获得这样高水平的吞吐量。下图展示了这个 InfiniBand 网络的概况:
请注意,训练网络时的通信发生在 InfiniBand 上,而不是以太网上。尽管这些机器也连接了以太网,但该网络的作用是传输数据集和检查点等数据。如果使用以太网来发送数据,速度会慢得多,因为数据会先从 GPU 传输到 CPU,然后再通过 100 Gbps 速度的以太网卡发出去。尽管也可以使用名为 RDMA over Converged Ethernet(RoCE)的技术基于以太网进行训练,但那需要在硬件和软件方面都做大量额外工作,并且可靠程度通常也不及 InfiniBand。详情可参阅这篇论文:https://arxiv.org/pdf/2402.15627
另外还有一个仅用于配置和管理的辅助以太网,从而可访问 BIOS(基本输入输出系统)、电源和其他低层机器接口的控制界面。如果没有这个管理网络,我们就必须通过 USB 驱动、键盘和显示器来手动设置每个节点。对于有几百台机器的情况,这并非一种可持续的方法。
要在这个集群上实现高性能训练,就需要每个组件(InfiniBand、以太网、GPU 和节点本身)都近乎完美地工作。如果这 12,000 多个连接中有任何一个有点不稳定,就会拖慢整体的训练运行速度。
本文接下来的内容就是介绍如何让这一切都完美且稳定地运行。
过程:如何将裸机变成完全可运行的集群
配置各台机器
在通过管理网络建立了与集群的初始以太网连接之后,就获得了基板管理控制器(BMC/baseboard management controller)的访问凭证。BMC 是一种远程监控主机系统的专用服务处理器,并且通常连接到一个分立的网络。它能让我们就像是亲身在现场一样操作机器,并还额外提供了硬件健康状况、BIOS 设置和电源管理的 API。
配备好这些组件后,我们就可以撸起袖子,开始设置集群了。
步骤 0:先配置好一台机器
我们首先使用 iDRAC(戴尔的基板管理控制器)在一台服务器上安装 Ubuntu 22.04,然后再基于这个操作系统设置其他一切。iDRAC 的一项能力是允许从本地计算机安装和启动 ISO 镜像,并通过浏览器提供一个虚拟控制台。理想情况下,这是该过程中唯一的手动安装步骤。
步骤 1:在每台机器上安装操作系统
在配置完第一台机器之后,继续安装 Ubuntu 的 Metal-as-a-Service (MAAS) 软件以帮助配置剩余的服务器。使用预启动执行环境协议(PXE)启动和自动化 iDRAC 工具,可指示每台机器从网络启动并配置 MAAS 以响应 PXE 启动请求。在执行初始的网络启动时,服务器会通过动态 IP 分配协议 DHCP 从 MAAS 获得一个 IP 和一个初始内核,而无需在本地驱动器上安装任何东西。这是用于自动重复执行操作系统安装的基本环境。从理论上讲,我们只需等待第一次启动,然后一切都会被处理好。但实际上,MAAS 与 BMC 的整合并不可靠,因此我们使用 iDRAC API 来事先收集每台机器的 MAC 地址(一种唯一的物理硬件标识符)。
在这整个训练过程中,MAAS 通常是椎栈中比较可靠的组件。但是,我们在开始时遇到了一些我们的设置特有的问题。举个例子,在配置前几台机器时,由于时钟相差太大,HTTPS 证书验证问题导致无法通过 apt 安装任何东西。与此相关的是,由于 MAAS 服务器必须负责很多事情(DHCP 服务器、用于将主机名解析成 IP 的 DNS 服务器、主机和官方 Ubuntu 软件包服务器之间的 HTTP 代理、NTP 服务器、cloud-init 配置管理、用于将 MAC 地址连接到 IP 到主机名再到自定义元数据的 ground truth 数据库),因此我们很难从根源上解决这些问题。此外,还有 MAAS 配置生命周期的学习曲线问题,因为是设计目标是处理管理绿地部署(greenfield deployment)的复杂性以及节点的逐步迁移和各种调试 / 不健康的中间状态。
步骤 2:诊断损坏的机器
我们发现大约 10% 的机器都无法启动,主要原因是服务器的物理问题。这是设置大型 GPU 集群的常见情况。我们遇到的情况包括:没接网线或接错了网线、iDRAC 中的硬件问题、电源单元损坏、NVME(快速非易失性内存)驱动损坏、内部线路缺失、网卡或 GPU 无法显示。我们自动检查了这些问题,将一些机器退回给了戴尔以重新测试,并为数据中心工作人员提交相应的工单。我们自己上手配置集群的一个优势是:在等待维护某些机器的同时就能立即使用健康的机器。
步骤 3:最小可行可观察机器
我们继续在每台服务器上进行如下设置:
1.Docker(以便更轻松地运行服务和训练作业)
2. 数据中心 GPU 驱动
3.Prometheus 节点导出工具(用于导出稳定的硬件 / 操作系统指标数据流)
4.DCGM 导出工具(用于从英伟达 GPU 导出额外的指标数据,如 GPU 状态、时钟、利用率)
5. 所有非操作系统驱动的 RAIDZ ZFS 池,这让机器在某个驱动失效时也能继续工作,同时还能免费提供透明的压缩(这对纯文本数据集和重复性日志尤其有用 —— 相比于不使用该工具,使用该工具通常能将可使用的空间增大 10 倍)
然后我们运行基本的 GPU 诊断以确定 GPU 是否大体功能正常 —— 不正常的通常会在几个小时内出现硬件问题。
在此期间,当我们试图同时在全部 400 个节点上安装软件包时,我们遭遇了带宽瓶颈。这是我们第一次在数据中心部署的多个组件上收到高温过热警报。这首批发热问题基本上都通过固件更新得到了解决。
步骤 4:单节点的 GPU 训练
下一步是确保每台机器都能够单独处理真实的 GPU 工作负载。很多机器都无法做到这一点,问题包括:
GPU 相关的错误,这类问题基本都可通过将 GPU 卡重新插入卡槽来解决:将 200 磅重的服务器从机架上滑出来,移除机盖和 GPU 之间的所有线缆,然后取出 GPU,再重新装上 GPU,之后再重新接上线缆并把服务器推回机架。
根据 Ubuntu 服务器日志,GPU 和 PCIe 总线或网卡之间的许多线缆都发出了这样的报错:「limited width: x4 < x16」。在更新 PCIe 交换机总线固件后,我们发现大约四分之一的主机需要重新安装内部 PCIe 线缆 —— 大概是因为外壳和 GPU 之间的线缆相当脆弱,这意味着每当对 GPU 进行维护时,这些线缆都会被推挤或拔掉。
还有一些杂项故障也影响了几台主机。戴尔通过固件升级帮助我们解决了一些问题:
NVMe 驱动器没有显示故障,但触摸时会锁定整台机器。
硬盘驱动器在 Linux 下以随机顺序显示,这给 MAAS 造成了混乱,并会导致操作系统被安装在错误的驱动器上。
温度读数错误,这会导致风扇一直全速运转。其原因可能是英伟达驱动有问题,这通过降级驱动版本而得到了解决。
CPU 的动态调频失控,将工作内核限制为 2 GHz。
直接的 GPU-GPU 通信(GDR 或 GPUDirect RDMA Peer Memory Client)无法成功应用。
配置 InfiniBand
步骤 0:安装 UFM
InfiniBand 的一个优势是其中心化的设计,这样一来整个网络就有了一个大脑。因此,对于整个网络结构中的 320 个网络交换机,我们只需处理其中一个实例。我们的首个任务是搞清楚哪台交换机连接了哪些机器,然后将其与接线图关联起来,并根据交换机的物理位置重新命名它们。
步骤 1:重新布线
一开始,UFM 无法检测到那 320 台交换机,更别说本应出现在网络结构中的主机了。在与我们的数据中心合作伙伴商讨之后,我们确认这些交换机已通电并接好了线,但依然无法检测到。在检查网络布线列表后,我们注意到该网络结构的顶层设计有误:这个结构不是统一的,而是分成了八个没有公共路由路径的互相脱离的网络。在重新接线之后,我们添加了检查步骤,以验证所有物理连接是否与新设计一致。
步骤 2:一万次 温度 告警( alert)
在解决了物理接线问题之后,InfiniBand 成功建立了与网络结构中所有 InfiniBand 交换机的联系。但是,几乎每个交换机端口都开始报告温度过高,有时候超过 70 ℃,即便它们还没有传输数据。我们发现这个问题源自同一机架中交换机之间的开放空间,这导致热空气回流到了前面。我们的数据中心合作伙伴帮助我们快速诊断出了该问题并制定了合适的解决方法。
步骤 3:1800 次告警
许多端口还有很高的错误率,或在正常和损坏状态之间来回变动,这被称为「抖动(flapping)」。这些问题只有在实际使用这些端口时才会出现,所以很难预先检测,因为我们的整个结构由 10,000 条高度冗余的链路组成。我们的数据中心合作伙伴帮助清洁和重新安装 告警的端口,我们在等待替换时禁用了剩余的警报收发器。
尽管 InfiniBand 能弹性地应对硬件故障,但一旦大约 10% 的结构开始出现问题,自适应路由等功能就无法可靠地运行,无法解决偶尔丢失链路的问题。
在此期间,我们成功使用 100 到 200 台机器运行了多节点训练。我们的流程比较即兴:我们有时会随机启动一组节点,观察它们的性能,然后尽力让其中尽可能多的节点保持运行。该方法可让我们找到该 InfiniBand 网络结构中一组可靠的子集,但难度却很大,因为每次都需要改变用于训练的节点集合,由此改变默认的 InfiniBand 链路。
步骤 4:InfiniBand 疯狂燃烧
为了更高效地诊断 InfiniBand 问题,我们专门为整个集群设计了一个工作负载,其作用是同时将尽可能多的数据推送经过整个结构中的每个端口。这不同于在整个集群上运行一个大型的 all-reduce 工作负载,这需要使用 NCCL 来优化各个节点之中的通信,方法是使用 NVLink 经由 Server PCIe Module (SXM) 插槽来实现 GPU 通信。
相反,我们选择了一种蛮力方法,并轻松取得了成功。UFM 会在大多数端口的数据传输量超过理论容量的 97% 时开始发出警报,同时一些交换机会暂时宕机。我们认为能坚持到当天结束时的每个端口都是足够稳健的,其余的都被禁用或移除以待维修。
步骤 5:GPUDirect RDMA
要让 GPU 通信时不产生 CPU 计算开销,我们启用了一个名为 GPUDirect RDMA 的功能,其允许 InfiniBand 网卡之间直接通信。这涉及两个关键步骤:
1. 启动一个额外的核模块
2. 确保 PCIe Access Control Service (ACS) 被禁用,以防止 immediate hangs(立即挂起)
步骤 6:扩增「黄金」服务器
要使用最新硬件构建 GPU 集群,一个经验法则是:每周都有大约 3% 的机器出问题,要做好准备。
但是,需要说明一点:并不是每台机器都统一有 3% 的几率发生故障,而是少量不对付的机器反复出现各种不同问题,直到将它们妥善修复。这就凸显了在同一网络结构中配备大量机器的优势。因此,我们的做法不是随便找些机器来运行大规模训练,就像打地鼠一样看哪些出问题,而是专注于扩增已知可靠的服务器,也就是「黄金」服务器。
步骤 7:维护
InfiniBand 的维护主要涉及到响应 UFM 警报、更换故障线缆和收发器,以及偶尔诊断更困难的错误(比如交换机故障)。导致大规模维护的因素通常有两个:
1. 固件更新,尤其是集群中仅有一半完成更新时,这可能导致 UFM 状态损坏并必需重启所有 InfiniBand 交换机上的 UFM。
2.GPU 盒同时大规模重启,这可能会向 UFM 状态灌入大量更新,并同样需要重启 UFM 服务。
确保机器完全健康
在此过程中,我们发现了单台机器的多种故障或减慢训练速度的方式。其中许多故障模式并不会立即显现,因此我们编写了许多健康检查脚本,以检查主机是否足够健康。我们在这里发布了这些代码:https://github.com/imbue-ai/cluster-health
请注意,这些健康检查中的很多都特定于我们的运行时环境,并不一定与基础硬件相关,也不一定容易修复或自动化。这是设计决定的:为了实现让我们的机器准备好训练的总体目标,我们想要一个可以直接了当地回答「是」或「否」的单一入口点,并且可以概括总结任意数量的细微细节。
GPU 健康检查
我们检查了 GPU 数量是否正确、ECC(错误更正代码)检查是否已启用以及是否存在 ECC 错误。我们还检查了 NVLink 拓扑(将 GPU 彼此连接起来)是否已启动且无错误。
磁盘空间健康检查
我们检查了主机的磁盘空间利用率是否超过 95%。
Docker 健康检查
我们检查了 Docker 能否在连接了 GPU 的情况下运行容器(即 NVIDIA Container Runtime 是否正常工作),还检查了与监控 / 分析相关的 Docker 容器是否已激活并获得了正确的主机权限。
Dmesg 健康检查
我们检查了 dmesg 中是否存在硬件 Xids 或 SXid 错误(由 NVIDIA GPU 或 GPU 间 NVIDIA 交换机引发的故障)。我们还读取了所有 dmesg 日志行,以验证它们是否都可以归类到「常见 / 预期日志行」列表中。
iDRAC 健康检查
我们检查了机器上的 iDRAC 错误,其中忽略了非致命错误消息。这是戴尔计算机特有的检查,所以没有被包括在我们开源的代码中。
磁盘健康检查
我们检查了 zpool 是否已安装,Docker 是否已正确连接到它,以及它是否真的可以在不锁定 CPU 的情况下触及它。
InfiniBand 健康检查
我们检查了 InfiniBand 的错误率是否会增加和 / 或驱动固件是否过时。
联系人: | 羊毛君 |
---|---|
Email: | soft850207@gmail.com |