摘要
在运行大规模机器学习(ML)基础设施时,可靠性是一个关键挑战,尤其随着ML模型和训练集群规模的不断扩大,这一问题愈发突出。尽管已有数十年的基础设施故障研究,但不同规模下作业失败的影响仍不明确。本文分享了管理两个大型多租户ML集群的经验,提供了量化分析、操作见解以及我们在理解和解决大规模可靠性问题方面的视角。我们的分析显示,尽管大型作业最容易受到故障影响,但小型作业在集群中占多数,因此应被纳入优化目标中。我们还识别了关键的工作负载特性,并在不同集群中进行比较,展示了大规模ML训练所需的核心可靠性要求。我们提出了一套故障分类体系及关键可靠性指标,分析了两个最先进ML环境中11个月的运行数据,这些环境总共涵盖了超过1.5亿小时的A100 GPU使用时间和400万个作业。基于这些数据,我们构建了故障模型,预测了不同GPU规模下的平均故障间隔时间(MTTF)。
此外,我们还提出了一种方法来估算相关指标——有效训练时间比率,并用该模型来评估在大规模环境下潜在的软件缓解措施的效果。我们的研究为提升AI超级计算集群的可靠性提供了宝贵的洞见,并指明了未来的研究方向,强调了灵活、与工作负载无关且具备可靠性意识的基础设施、系统软件和算法的必要性。
1 引言
加速迈向通用人工智能的创新正不断挑战当今计算基础设施的能力,推动了大规模模型训练方面的系统突破。各大公司纷纷投入巨资建设包含数千个GPU和高速互连网络的大规模集群。例如,Meta推出了其AI超级计算机,连接了2000台NVIDIA DGX A100系统(共计1.6万个A100 GPU),配备1600 Gb/s的InfiniBand网络和数PB的存储容量。短短两年内,Meta就推出了两套2.4万个GPU的训练集群,以加速生成式AI技术的发展。同时,谷歌也在下一代Tensor Processing Units(TPUs)上进行了投资,这些TPU是其AI超级计算机的核心。每个TPU v5p机架包含8960个芯片,通过每芯片4800 Gb/s的互连网络,以3D环形拓扑结构进行通信。如此庞大的基础设施投入无疑使现有系统架构承受着巨大的压力。随着大型语言模型(LLMs)的兴起,如Megascale、LLaMa、Gemini和GPT-4,机器学习训练的规模已从几十个加速器扩展到上万台,展现了前述基础设施投资的实际应用。在这种规模下,故障的发生已不再是“是否”而是“何时”的问题。因此,系统设计在集群的运行、效率和可靠性方面带来了新的、不可预见的挑战,迫切需要新的解决方案。实际上,硬件故障只是问题的一部分,尽管单独来看这些故障很少见,但在大规模环境中却变得更可能发生,这需要从硬件到机器学习集群调度器设计等多方面的解决方案。在本文中,我们分享了训练大规模模型的基础设施经验,包括早期的基础模型,这些模型随着使用的普及变得更加重要,其中最大的任务使用了4000个以上的GPU。与以往研究不同,我们的硬件和软件基础设施专门设计,以支持多样化的工作负载——尽管使用4000个GPU的大型任务占我们任务总数的不到1%,但却消耗了集群中12%的GPU资源。我们在处理大小规模任务时的经验,展示了基础设施需求的多样性,这种多样性在那些仅专注于LLM的专业集群中很少见。理解作业失败的根本原因——无论是硬件、系统软件、应用程序,还是这些因素的组合——对于提高训练可靠性和推进大型模型开发至关重要。在本文中,我们展示了从先进的AI研究集群中收集的11个月数据,这些集群的利用率超过80%。基于实际训练系统的数据分析突出了跨两个集群的研究工作负载多样性,这些集群合计使用了2.4万个NVIDIA A100 GPU。我们的重点是作业级别的失败,主要通过调度器和服务器级健康检查的视角来审视失败情况,并提供了一些网络级别的可靠性经验。最后,我们分享了在大规模环境中减轻故障、追踪可靠性指标、进行基础设施变更以及诊断常见应用问题的经验,并提出未来改进的建议。在此过程中,我们提供并分析了服务器级组件的故障率,包括平均故障间隔时间(MTTF)的预测。据我们所知,这是首次对10w卡GPU规模的机器学习研究工作负载进行基础设施分析。我们的贡献包括以下几点:- 引入了我们用于集群运行的故障分类体系和关键可靠性指标,旨在减少额外复杂性,同时最大限度地提高运行从1个到4000多个GPU的ML工作负载的灵活性。
- 基于对已部署ML训练系统的分析,指出了提高可靠性的机会。我们对两个最先进机器学习环境中为期11个月的训练数据进行了分析,这些数据涵盖了超过1.5亿小时的A100 GPU使用和400万个作业。我们发现,研究集群中的任务比LLM工作负载所暗示的更为多样,这激发了与工作负载无关的基础设施技术的需求。
- 基于故障数据验证不同GPU规模下的平均故障间隔时间(MTTF)预测。我们的预测与理论一致,并在规模达4000个GPU的作业数据上得到了验证。
- 设计并验证了一种分析估算器,能够根据各种作业参数和数据统计推算预期的有效训练时间比率。该方法适用于其他集群和工作负载。
- 提出了针对影响AI超级计算集群的基础设施问题的软件缓解方案,并对其进行了评估,包括自适应路由、健康检查和故障节点检测的经验。我们利用这些经验预测未来工作负载中故障的影响。
在本文的其余部分中,我们在第II节概述了我们的集群,在第III节深入探讨了故障数据,在第IV节提出了缓解措施,并在第V节总结未来方向,最后在第VI节讨论相关研究。
2 系统基础设施
在本节中,我们描述了工作负载如何影响我们集群的设计。虽然可以专门设计集群以优化特定的工作负载,但集群研究根据定义,预计会有不断变化的工作负载和可能出现的未预见需求。因此,我们认为集群研究应当具备通用性,最大化生产力,最小化偶发复杂性。我们的两个姐妹集群,RSC-1和RSC-2,遵循下面讨论的同一设计模板。RSC-1是一个具有16k GPU规模的通用机器学习集群(例如,用于训练一些知名的LLM),而RSC-2则专注于视觉应用,其GPU规模为8k。我们稍后(在第III部分)会讨论,这些工作负载差异会体现在不同的使用方式上——例如,RSC-2上的工作负载大部分倾向于使用1个GPU的作业,同时也有作业使用的GPU数量高达1k。2.1 调度器和存储基础设施总览
我们在设计RSC-1和RSC-2时,优先考虑了易用性,同时也倾向于简单性。我们设计的优点在于,整个系统都已经成熟,并且不需要大量的定制数据中心设计,这使我们的上市时间缩短至只有1.5年。另外,我们的目标是为用户提供所需数量的GPU,无任何附加条件,以此来最大限度提高生产力——用户无需处理新型硬件或虚拟化形式的复杂性。图1提供了一个关于用户如何与我们的集群交互的概述。用户提交一个包含很多任务的作业,每个任务可以在节点的GPU上运行。调度器:倾向于使用高性能计算(HPC)堆栈,我们的集群在裸机分配的基础上使用Slurm调度器。集群配置为用户组有最大的GPU配额,这是由项目特定的分配决定的。用户使用shell脚本(sbatch)或Python封装器(submitit )提交作业。然后,Slurm会试图根据物理网络拓扑将任务集中在一起。作业在运行2小时后有可能被抢占,并且它们的最大生命周期为7天。调度器试图根据优先顺序来调度作业,这取决于许多变量,包括项目的分配和作业的年龄。机器学习工作负载遵循gang调度语义。gang调度确保所有所需资源在多个任务之间同时分配。这种协调对于优化大规模机器学习工作负载的性能和效率至关重要。然而,如图1所示,一个任务的失败可能会迫使整个作业重新分配。这激发了一些容错策略,如检查点和冗余,这些都可以用于gang调度。检查点允许作业从保存的作业状态中恢复,最小化对整个作业进度的影响,而冗余则降低了作业失败的可能性,最小化了失败率。提交作业的用户可以得到我们基础设施的保证——如果健康检查失败导致作业终止,系统会自动将作业重新加入队列,作业ID保持不变,如图1所示。总的来说,我们的集群平均每天提交的作业数量为RSC-1的7.2k和RSC-2的4.4k,集群利用率分别为83%和85%。存储:预期作业的输入和输出数据以及检查点应该是持久的,并且与特定作业的生命周期解耦。我们的集群提供三种存储方案:1、一种基于闪存并通过NFS协议提供的POSIX兼容存储方案;2、一种定制的、高带宽的、专注于数据集的AirStore;3、一种具有高容量和高吞吐量的对象存储,ObjectStore。第一种方案便于使用,为用户提供了主目录、Python环境,以及执行常见模式(如检查点)的读写操作的能力。对于第二种方案,使用定制的高性能只读缓存服务AirStore加速了数据集访问,也是基于大量闪存。最后,当NFS端点不足时,我们有一个对象存储接口(ObjectStore)用于检查点和存储文件。检查点在容错方面至关重要。多种选项的可用性使用户能够在易用性和性能之间进行权衡。高性能计算(HPC)集群的核心硬件组件包括计算、网络和存储(上文已讨论)。用户通过向调度器提交作业,提供利用这些组件的指令。我们集群的拓扑结构如图2所示,其中展示了节点的系统布局以及单个服务器的内容。计算:我们在本文中介绍的两个集群都是基于DGX 的裸机集群,每个服务器(节点)配备双AMD Rome 7742 CPU和8个NVIDIA A100 80GB的GPU。这些GPU通过高带宽的NVSwitch连接。网络:在实践中,一个作业可能会使用数百个服务器。服务器通过两种类型的互连,前端和后端,进行连接。前端网络通过以太网管理控制平面(即调度和TCP连接)和存储流量。同时,后端网络使用Infiniband fabric进行神经网络训练期间的低延迟模型梯度交换。服务器通过链路优化的Infiniband后端网络连接,部分在图2中显示。链路优化的拓扑意味着同一服务器的GPU通过本地连接,绕过一级交换机。通信被分组到逻辑域:每个机架有两个服务器,十个机架通过链路优化的网络连接,形成一个pod。Pod之间的通信通过下一级的交换机(spine交换机)进行。调度器和模型训练框架(如PyTorch [13])预计将大部分网络复杂性抽象化——提供一个传统的基于集合的通信模型,该模型在各种可能的作业分配中都应该是可移植和高效的。关键是,后端网络软件能够利用本地性(例如,选择使用高带宽的NVSwitch而不是通过顶部机架交换机的铁路连接的Infiniband链路)。然而,正如我们下文(§V)所讨论的,现今的HPC风格的集合确实存在一些缺点。洞察1:集群的uptime至关重要。我们的集群完全负载。任何停机时间都会导致过度排队,被视为重大事件。集群必须在线适应故障,理想情况下,自动重新排队与基础设施相关的故障。健康检查:由于机器学习作业的gang调度语义,故障对整个作业的可靠性有很大影响——一个系统组件的单一故障可能导致数千个GPU处于空闲状态。重要的是,我们集群的运行规模之大,可能导致组件故障之间的时间足够小以至于造成干扰。由于可能的故障范围大,以及透明恢复故障所带来的开销,我们的基础设施设计为检查作业是否在健康的硬件上运行,如果出现故障,就在不同的节点上重新启动作业。这可以被视为一种合作恢复策略,因为应用程序仍然负责正确实现检查点和恢复逻辑。为了找到、检测和移除失败的节点,调度器会对集群中的每个节点定期进行一系列健康检查。我们在§III中通过这些健康检查分析作业失败。我们的训练集群设计的一个核心理念是努力实现不让坏节点导致第二次作业失败——失败的节点是一个糟糕的调度候选者。Slurm可以在作业运行前后进行检查。此外,我们还有健康检查,这些检查被定期安排每五分钟运行一次,并返回表示成功、失败或警告的代码。每个健康检查都检查某些节点健康的方面,范围从GPU错误(如XID错误[9])到文件系统挂载,以及服务状态(即,调度器)。请注意,检查可能会在故障域中产生重叠的信号。例如,PCIe失败表示GPU无法访问,即使GPU本身没有发生相应的XID事件。在我们的日志中,这种情况在RSC-1上出现了57%的时间(在RSC-2上是37%)。因此,即使有一个检查在应该触发的时候没有触发,另一个重叠的检查也有希望捕获到故障。最极端的情况是NODE_FAIL,当节点对正在节点本身上运行的其他健康检查无响应时,它通过Slurm心跳充当一个全能捕捉器。定期的健康检查对于防止同一不健康节点的重复作业失败至关重要。此外,这些检查被调整以具有低的误报率——它们已经过之前的校准,使得成功完成的作业中有不到1%的作业观察到了健康检查失败,尽管我们只能观察到相关性,而不能观察到因果关系。不同的检查有不同的严重性。高严重性检查失败将立即向调度器处理程序发送信号,以移除节点并重新安排在节点上执行的所有作业,而低严重性检查将在节点上运行的作业完成后,无论成功与否,向调度器发送信号以移除节点进行修复。在第一类检查中包括以下内容:GPU无法访问,NVLink错误,不可纠正的ECC,行重映射失败,PCI或IB链接错误或块设备错误,以及缺少挂载点。未失败任何健康检查的节点可用于调度作业。当节点的健康检查失败时,节点将转变为修复状态,并且在修复并通过所有检查前,将无法用于调度。转到修复可以立即发生(对于高严重性检查)或在当前作业完成后发生。通过可能在不健康的节点上调度的反事实,可以激发对健康检查的重视。即使只有一小部分节点不健康,作业占用不健康节点的概率也会随着规模的增加呈指数级增长。我们强调,健康检查是确保可靠计算基础设施的第一道防线——尽管应用程序必须继续保持主动——这引导我们到下一节。洞察2:一个不好的节点会损坏一堆。健康检查可以防止由于在有缺陷的节点上重复调度(“重启循环”)而导致的相关故障。无法将此类节点从容量中移除将导致无法有效运行大型的,gang调度的作业,严重削弱集群的效率。只有在可以可靠地淘汰有缺陷的节点后,才能有效地从随机故障中恢复。
2.4 指标
机器学习集群性能的三个关键指标是:有效训练时间比(ETTR)、模型 Flops 利用率(MFU)和吞吐率。有效训练时间比(ETTR):ETTR 定义为有效运行时间与作业运行的可用挂钟时间的比率。一个作业运行包括一个或多个与同一逻辑作业相关的调度作业。例如,一个为期数周的 LLM 预训练运行可能由多个不同的作业组成,这些作业由抢占和基础设施故障划分(我们忽略了用户空间故障对 ETTR 的影响,只关注集群稳定性的影响)。作业运行的可用挂钟时间定义为在多作业运行中的一个作业是 1)调度或者 2)有资格被调度但在队列中等待的总时间。有效运行时间指的是在此期间对工作负载进行有意义进展的调度时间。有效运行时间的确切定义根据上下文有所不同,但我们认为有两种无效的调度时间:
从最近保存的检查点开始追赶:在最近的检查点和作业中断之间进行重新训练。
重启开销:在重启后需要执行的所有初始化任务,否则不需要。
这两者都高度依赖于作业,我们目前缺乏一种可靠的方法来跟踪这两者。然而,我们将这些视为需要探索的自由参数,用我们在与各研究团队合作中偶然遇到的合理值来填充。
ETTR 可以从 0(作业永远不会取得任何有意义的进展)变化到 1(100% 的挂钟时间都用于取得有意义的进展,即没有排队或无效运行时间)。ETTR 类似于经典的作业减速度度量,定义为挂钟时间与给定作业的调度时间的比率。然而,ETTR 还额外考虑了无效的运行时间,并对比率进行了反转,以获得更好的可解释性。
类似ETTR的指标,如追踪作业运行直到失败的时间,最初被用来追踪我们的LLM(如LLaMa[41])的训练效率,因为基础设施问题正在迭代诊断。此后,这些指标被概括为ETTR,并继续对最近的LLM[33]以外的集群有用。例如,Google Cloud定义了一个等效的指标,他们称之为“运行时吞吐量”[3]。为了区分我们在本文中提到的吞吐量指标(它只包括来自浪费计算的影响,而不是例如等待时间),我们创造了有效训练时间比(ETTR)这个术语。模型 Flops 利用率(MFU):在整个行业中使用的一个相关指标是模型 flops 利用率(MFU)。这个指标对应于模型理论上利用的 FLOPs 数量与硬件峰值 FLOPs 的比较。由于 ETTR 是模型不可知的,并考虑作业重启和排队,因此它提供了一个更一般的集群可靠性和吞吐量实现的度量。然而,与 MFU 不同,ETTR 并未捕获性能下降或次优的实现。它们都可以在某种意义上进行比较,因为它们测量的是开销运行时间与理想值的比率,并且在0和1之间,尽管 ETTR 通常更高(例如,超过80%,而 LLM MFU 更小,例如对于LLaMa 3[33]为38-43%)。吞吐率:以上两个指标都可以被视为每个作业的效率指标。整个集群可以用吞吐量来衡量,吞吐量是单位时间内完成的有效工作的总量。吞吐量可以被规范化,通过最大可能的吞吐量产生在0到1范围内的利用率。本文讨论的集群在高利用率下运行(所以潜在的吞吐量只受到容量而不是可用工作的限制),因此作业抢占、资源碎片化和故障是丢失吞吐量的主要来源。故障归因是指将作业失败的原因归咎于某一因素的过程。我们的经验表明,故障归因是一个充满挑战且复杂的过程。例如,NCCL超时现象就相对常见。在PyTorch中,每当一个节点发现诸如AllReduce之类的集体操作在几分钟内未完成时,就会发生NCCL超时。这既可能意味着出现了某些网络问题,也可能意味着其他节点由于某种原因(例如,在尝试为下一次迭代加载数据时卡住)而根本没有启动相同的操作。在这种情况下,超时的节点本身是完全正常的。出错的节点可能由于用户软件或基础设施错误(这些错误可能发生在链路或交换机级别)而无法响应。要从用户级堆栈跟踪中追溯根本原因,可能需要多层精确且分布式的日志记录,从机器学习应用程序一直追踪到分布式集体操作和底层基础设施。
因此,我们的故障分类法(如表I所示)基于以下原则:对于任何给定的症状,都可能有多种潜在的根本原因,而限制假设空间的唯一方法就是排除不太可能的原因。因此,我们提议通过跨故障域的鉴别诊断来诊断和找出根本原因——使用各种性能指标来标记可能出错的位置,从而将特定的故障限制在可能原因的一个小子集中。我们的故障域涵盖了用户代码、系统软件(如驱动程序、PyTorch、操作系统)和硬件(在第II节中介绍的组件)。与先前的工作[24]类似,我们观察到症状可以映射到多个故障域。在典型情况下,用户应确保他们的程序没有明显的错误。从集群管理员的角度来看,硬件错误必须根据是瞬时的(例如ECC错误、链路抖动)还是永久的(例如需要供应商维修或更换的硬件降级)来进一步分类。与这种故障分类法相关的信息跟踪必须自动管理(例如,通过健康检查第II-A节),因为1)程序与机器的配对是非确定性的;2)故障往往是罕见事件。我们发现,拥有涵盖硬件和系统软件各个方面的丰富信息,可以使我们更快地确定导致特定症状的原因。在某些情况下,甚至可能预期多个同时触发的健康检查会指向同一个错误(例如,PCIe事件可能会影响GPU)。洞察3:谨防误导性线索。具有多种潜在原因的故障很难诊断。像NCCL超时这样的错误可能被简单地归因于近因(例如网络问题),而不是死锁。网络具有较大的“影响范围”,会在整个堆栈中引发错误。一些错误是瞬时的,无法一致地重现——表现为可以通过整个集群的健康检查观察到的统计过程。其他错误与特定的节点硬件相关,并且随着它们的出现,错误发生的可能性会更高。表I概括了我们的分类法和经验。