OpenAI的Chat-GPT为我们揭示了通用人工智能的潜力,而GPT4-Turbo的发布进一步拓宽了我们对通用人工智能的想象边界,国内各种大型模型如同雨后春笋般涌现。同时,大模型训练所带来的各种工程化问题也接踵而至。 大模型训练通常涉及大量的参数、巨大的计算需求和复杂的网络结构,这使得整个训练过程变得极其复杂。在这种情况下,训练过程中可能出现的故障可以来自硬件、软件、网络、应用等多个方面,这使得故障定位和排除工作变得异常困难。 训练过程中的任何故障都可能导致训练中断,从而损失从上一个检查点到中断时的所有计算。重新启动训练任务也需要一定的时间,而昂贵的计算资源使得每一秒都显得尤为重要,毕竟“时间就是金钱”。 本文将专注于大模型训练的故障的定位,尝试提供一些解决思路和方法,希望能为读者带来一些帮助和启示。
在介绍大规模模型训练的方法之前,我们首先需要了解模型训练的基本过程。模型训练通常包括以下几个关键步骤:
由于模型参数的数量和计算量非常庞大,传统单机训练方法通常需要较长的时间才能完成训练。为了解决这一问题,研究人员提出了大规模模型训练的分布式训练方法。这些方法可以将训练任务分散到多个计算节点上同时进行,从而大大缩短训练时间。
下面我们将简要介绍几种常见的分布式训练方法:
在整个训练过程中,需要涉及到多种技术,如:图形处理单元(GPU)、远程直接内存访问(RDMA)网络、虚拟专用云网络(VPC)技术、虚拟化技术以及存储等。这些技术在训练过程中发挥着重要的作用,例如:
综上所述,大规模模型训练是一个复杂的过程,涉及到多种技术。采用合适的训练方法和技术,可以有效地提高训练效率,缩短训练时间。
如图所示,应用程序通常部署在多台计算机上,通过VPC网络进行应用程序的部署和管理。在训练启动阶段,通常会使用VPC网络建立TCP连接(例如NCCL初始化),用于交换基本数据。在训练启动后,训练数据通常采用CFS存储,以实现多计算机共享。在获取数据后,GPU负责执行具体的计算任务。在训练过程中,参数的同步将通过集合通信方式使用RDMA网络进行传输。故障可能发生任意一个节点的任意阶段,排查和定位故障点,需要对整个训练的过程和相关技术栈有一定的了解,如何快速定位更是一个巨大的挑战。
“战胜敌人首要的条件是了解敌人”,我们将故障按照其出现的位置划分为以下几类:应用层故障、集合通信层故障、GPU层故障以及网络层故障。根据故障的现象,我们也可以将其大致分为环境问题、性能问题和网络问题。
从上一章节中的分类,我们根据故障出现的位置将问题划分为:包括应用层问题、集合通信层问题、GPU层问题和网络层问题。
针对各层次的问题,我们可以从现象出发,尝试重现问题,并运用一定的工具挖掘更多信息,进行详细分析,最终确定根本原因,并解决问题。在此过程中,我们将把分析定位的经验反馈至工具,不断完善工具,提升整体故障排除的效率。
在每个层级的问题,目前都有一些工具帮助分析和处理问题。
针对实际故障,我们可根据实际情况,灵活选择和运用上述工具来分析定位问题。
在集群规模较小的情况下,上述问题定位和处理思路在一定程度上可以发挥作用。然而,随着模型参数量的增加和训练复杂性的提高,所需的集群规模会越来越大。因此,我们需要不断将问题的处理经验进行工程化,并不断优化,同时应该站在更高的维度,去分析和处理故障,基于此,我们可以将整个故障处理的流程平台化。
从上述常规故障排查思路出发,我们可以进一步扩展,一种简单的思路是,按照 防范故障 → 监测故障 → 处理故障的步骤,将平台划分为三个模块:
在大规模集群中,故障的分析处理涉及大量数据。例如,一个包含156台机器的千卡集群,共有1248个rank,需要分析每个rank的数据,如果对网络层的数据进行处理,一台设备,若上联 16 个端口,则需要需要处理2596个端口的数据。
通常情况下,对于排障任务场景,我们可以简单地将任务分配给具体的节点机器,执行具体的检测或诊断逻辑(串行或并行可以根据实际情况进行编排),然后将结果收集并进行分析。
在分析过程中,通常需要进行以下三种分析:
故障现象:在某次训练中,使用 48 台机器训练某个任务,任务在持续一个月后,开始出现训练 hang 问题,应用层无日志输出,所有GPU功耗降低知 100w左右,但是 GPU 利用率持续为 100%。任务重启后,可以恢复训练,但是持续一段时间后就重新出现 hang。
故障排查处理过程:
# 开启torch集合通信的耗时统计
export TORCH_CPP_LOG_LEVEL=INFO
export TORCH_DISTRIBUTED_DEBUG=DETAIL
# 启用pytorch集合通信监控,出现异常或超时时不再hang住,直接崩溃并打印调用栈
export NCCL_ASYNC_ERROR_HANDLING=1
5. 问题复现后,使用 cuda-gdb 对所有 rank 进行调试分析,发现所有进程均hang在 ncclKernel_AllGather_Ring_LL_Sum_int8_t()
中,确定和 NCCL 相关。
6. 添加`export NCCL_ASYNC_ERROR_HANDLING=1 ` 后,应用层日志显示,所有线程均卡在 WorkNCCL(SeqNum-5586566, OpType=_ALLGATHER_BASE,
这个操作中,确定 hang在集合通信层。
7. 明确未 NCCL问题后,开始对NCCL相关代码进行分析,发现类似问题:https://github.com/NVIDIA/nccl/pull/898。 分析: a. 集合通信中,任意两个节点的之间通信,每次告知对方需要读取什么数据时,会用到一个引用计数(comm->fifohead),每次通信后都会+1。
b. int 最大值,int 4 个字节 -2147483648 到 2147483647。int超过最大值后,会进行反转,从最小值重新开始。uint64, 8个字节 0~18446744073709551615。
c. 当 slots[x].idx > int_max 时,就会判定失败,会导致通信无法完成。
8. 升级 NCCL修复的版本,并进行验证,问题消除。
在本案例的排查与处理过程中,我们首先借助平台的能力,对集群的各项指标及相关告警进行排查,以检测是否存在异常现象,排除机器故障或网络侧问题。同时,我们使用NCCL-TEST来验证RDMA网络问题。在缺乏线索的情况下,我们开始对应用层进行分析。首先,借助集群排障工具,对整个集群的应用环境进行检测,以检查每个节点的环境是否存在不一致之处。最后,我们对应用层进行分析,增加一些环境变量,增加程序hang超时退出时的日志,并利用集群排障工具,对所有rank,使用cuda-gdb进行调用栈分析,以检测是否有进程或线程存在不一致的情况。最终确认所有进程均挂起在NCCL集合通信中,进而并对NCCL层进行详细代码解读与分析,最终解决问题。
在大模型训练中,故障根因错综复杂,一些应用层和集合通信的故障,目前尚不能使用指标完全覆盖检测,需要我们静下来心来深入分析,一步步挖掘真相。
针对一些疑难杂症,也可以参考下面的一些基本思路,进行处理:
# 注意下面的文件版本和具体位置,请以实际为准, 可以使用 ldconfig -p | grep libcudadebugger 确定实际位置
VolumeMounts:
- mountPath: /lib64/libcudadebugger.so.535.129.03
name: libcudadebugger
volumes:
- name: "libcudadebugger"
hostPath:
- path: /lib64/libcudadebugger.so.535.129.03
4. 对所有数据进行分析整理,找到可疑点。
5. 对可疑点相关代码进行深入分析。
本文概括性地介绍了大型模型训练中遇到的问题分类、基本排查方法以及排障工具平台构建的基本思路。随着大型模型的发展以及参数数量的增加,所需的计算资源也将逐步增加,集群规模的扩大以及对训练稳定性和集群排障效率的挑战也将愈发严峻,本文仅是抛砖引玉,提供了一些粗浅的思考,希望能给大家带来一些帮助。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。