本次分享的主题是大模型训练稳定性思考和实践,由阿里云智能集团高级技术专家张彭城分享。
本次分享关于稳定性的话题,稳定性是一个原始问题,对于大模型训练,稳定性是一个非常关键的基础,没有这个基础,各种的性能优化和调度是没有任何意义的。
本次分享主要有三个部分,第一个部分是大模型训练稳定性关键挑战,第二个部分是阿里云大模型训练稳定性系统介绍,第三个部分是大模型系统稳定性关键问题实践分享。
一、大模型训练稳定性关键挑战
第一个挑战是首先模型训练一般在万卡以上,这个万卡情况下的训练任务又具有同步性特点,所以一个节点挂会导致整个任务全部挂,或者它性能被拖慢。其次是GPU和光模块故障率都很高,任务规模越大,故障率越高。Llama3.1平均3.1h中断一次。最后是恢复成本很高。下面是LIama 3.1 54天故障数据图,绿色的部分是正常训练,两个绿色部分的中间部分是任务中断,要回到上一个check point,定位故障节点,把任务重新拉起,所以成本是非常高的。
第二个挑战是故障定位是非常复杂的,第一个原因是训练任务具有同步性特点,任何一个节点出现问题,所有节点都会跟着一起表现异常,无法快速分辨出哪个节点是故障根节点。第二个原因是技术栈是比较复杂。从底层服务器硬件到网络,再到软件框架用户代码,任何一个技术栈都有可能导致任务失败,或者任务性能下降,下面是比较常见的问题,从GPU、Nvlinkg、Pcie、网络的组网、交换机、存储、业务都有可能出现问题。所以在一个复杂系统里面性能性能下降,很难定位出问题。
二、阿里云大模型训练稳定性系统介绍
下面解决这些挑战,第一点是在交付前做健康检测,确保交付的节点和集群网络都是健康的,第二点是在运行中肯定会出现故障,需要构建一个实时可观测系统,通过这系统快速发现故障,在此之上还需要一个故障自愈系统,和pass层的学习平台配合,让任务可以快速的迁移和恢复,这个是整体的一个架构。
下面分别对这几个系统做一个简单的介绍,第一个就是健康检测系统。
健康检测系统主要分成两部分,第一个是单机的检测,包括硬件的检测、软件的检测以及一些关键配置检测,也包括GPU的一些矩阵层的计算,以及一些机内集合通信检测,除了单一检测以外,因为一个训练是一个集群性的业务,还需要一些集群的检测,比如网络连通性的检测、RDMA网络性能检测,以及集群集合通信检测,除此之外可能需要存储IO路径E2E检测、模型E2E检测。
有些友商不仅把它作为一个交付前的检测,还把它做成一个故障定位的工具,我们的观点是不要用这个去做故障定位,因为很多的检测是有损的,做检测必须要把任务停掉,把所有检测跑一遍,可能是小时级或者十分钟级别的损耗。
这个东西只作为一个交付前的检测,不要作为一个故障定位手段,需要构建一个Runtime的监控系统,通过Runtime的监控定位故障。这个监控是数据越多越能定位到问题,把各种各样数据全采一遍,肯定是能定位出问题,但是数据采集的越多,这个存储的成本就很高,第二个是有数据是有损采集,比如任务层面的trace信息是需要侵入的,或者对性能是有损的。
现在的策略是对于基础设施层的监控基本上是Runtime全部采集,这部分是业务无损的,对于需要任务层的一些监控是有损的,比如集合通信和框架trace信息是有损的,这部分是按需开启的,比如出现故障时候开启,或者每几百次迭代会开启。其次基础设施层监控和任务层监控一定要给联动起来。
因为如果只去看基础设施层监控会发现很多故障,就是可能会有很多的告警,但是告警不一定真正的会影响业务性能和业务运行,所以需要把两个有机结合起来,才会有一个更高的定位效率。
基于这个可观的系统之上就是自愈系统。自愈系统分三部分,第一部分是把laas层的故障上报AI Pass平台,比如说GPU故障、内存的故障、网线网卡的故障。平台会把这些节点进行隔离,把任务重新再拉起来。
第二部分是AI Pass平台检测所有任务的日志,它会发现里面有各种报错,比如ECC error、Cuda error,它会把节点给做隔离,经过第一步和第二步之后,可能大部分故障定位上了,但是还有一部分故障没有报错,在这种情况下,构建C4D系统专门去检测这种疑难杂症的Hang行和Slow问题。
三、大模型系统稳定性关键问题实践分享
下面讲解集群和任务相关的,这个故障的定位和稳定性的实践。第一个问题是除了GPU故障以外,可能遇到最多的故障就是网络的link故障,现在这种集群工作比较大,功模块比较多,故障率非常高,首先阿里是一个双上联的网络架构,意味一个网卡是连到两台交换机上,一根链路中断以后,这个任务是不会断的,它可能性能是会受损,也是跟这个模型和通信占比有关,现在很多的模型的跨界通信都是被计算给flap掉了,在大多数情况下,断单网线对性能没有太大影响。断单网线就不需要把任务全部停掉,可以在线进行热维修。
第二个问题是交换机升级,单上联的交换机几乎是没法升级的,要把所有的机器全部迁移走后升级,这个成本是非常非常高的。双上联基本上解锁交换机在线升级的能力,基于双上联架构就可以使能网线热维修能力,这个能力实际上是把端侧和网侧的所有的链路的监控全部汇聚到一起。
因为很多故障看一侧看不出来,要把两边数据都汇到一起,比如CRC这种故障是单边。首先要把端侧和网侧全部汇聚到一起,基于此来做各种策略、阈值设置以及告警和维修策略,要防止机房换线换错,还要做各种容错校验机制,防止它犯错。这个实践下来发现链路故障大概是60%link down,20%link flapping,20%rx error。基于此的热维修系统,基本上95%的网线故障都是可以基于热维修去修复的。
还有一些情况是网线断了对性能有影响,可以跟机器学习平台做联动,可以设置,比如客户认为网线故障会造成性能影响,就可以说网线故障并推送给客户做一个私域。第二个问题就是集群网络故障如何定位,第一点首先高性能网络是一个端网融合的技术,它有需要网卡和交换机深度的配合,所以整个监控系统的设计也是基于端网协同,把端侧的所有的网络相关通信指标和网测指标做一个聚合,然后进一步跟任务信息进行聚合,因为发现一个任务通信其实是有规律的,任务信息进行结合后,定位效率又进一步提升。
例如发现通信的任务级的监控出现异常,可以自动化的关联到对应的任务,对应的网络集群也出现了对应的异常,然后就可以定位到故障对应,以及我们会有一些维修策略。第二个是网络在训练过程中是一个burst,比如这个dp的通信基本上是在200到300毫秒,tp和pp可能是在毫秒级别甚至微秒级别。通过秒级监控基本上看不到峰值。
所以在网络监控里面需要更高的精度,比如这个线上主流的毫秒级监控,毫秒监控可以很清楚的看到这一次迭代通信行为,比如reduce scatter和gather的整个通信行为,以及能很精确的看到某一个dp group没有打满。在一个很粗的力度网络监控上是根本发现不了性能问题。所以要定位性能问题就需要更高精度网络监控。
在dp做overlap以后,它和pp的通信是由以前的串行通信变成并行通信,就是以前pp通信之后做dp通信,但是现在发现其实pp和dp是同时在通信,它就会有影响,因为pp和dp通信都是找同一张网卡,所以在网卡上监控没法发现他们互相影响,所以就在交换机上做微秒级别的流级别监控,这样就很容易观察到pp和dp的通信在交换机上互相有影响。
通过这种更高精度的微秒级别的监控(dp的通信是微秒级别),可以发现细粒度的性能问题,下面分享一则数据,统计线上阿里内部的万卡level,它的整个训练过程中的稳定性数据,这个任务中断的时间就是在1%以内,在正常情况下,它的主要开销就是任务重启,比如每一次要十几分钟并且每天断两次,可能就是大概1%以内的性能的损失,统计另外一个数据就是性能的损失,发现性能的损失大概是在0.6%左右,来源于每隔几百个迭代,做一次框架trace,有时候也会超过这个值。引起这个性能抖动超出预期或者任务中断时间超出预期,都是因为这两个问题,一个是任务Hang住,另一个是任务性能slow,这两个问题是目前稳定性遇到最严重最麻烦最难搞两个问题。
下面解决这个问题,首先训练任务和集合通信都是同步的,所以就可以利用集合通信的同步的特点,把集合通信的所有日志采集出来,在中心做一个诊断,很容易发现哪一个节点出现的问题,比如图中每个rank都是按照计算通信的顺序,有一个rank就发现它计算后就没通信。因为它Hang行计算,所以通过统计集中通信数量,很容易定位出来哪个节点Hang住,其次slow其实也是同样的原理,就是这个时间会更长一点,说明计算变慢了,这是一个很好的思路。
这个方法的好处是它不需要去适配模型框架,它是个通用的,因为它只需要你去替换集收通信动态库,这个是没有侵入的,并且对性能性能是没有任何影响的,大量的客户都在使用这个方法去定位性能问题或者Hang问题。另外一个问题就是其实他很多问题不一定是某个硬件出问题,他可能是代码出问题,或者不是现在出现的问题,我们在通讯库的基础上又增加了一些扩大,对python更加细致的采集,现在的问题是数据量太大,就是G级别,核心要做的是把这个东西给搞成一个比较小的数据,才能把它统一汇聚到一个中心节上去做定位。
所以这里面做了一个特征提取,把关键的特征提取出来,最后放到中心化的去做一个这个诊断,这个分析报告是如下示意图,这两个能力在这个产品上都是可以用。
最后就是关于未来的一个展望,我觉得未来这个十万卡集群的稳定性可能和万卡不是一个level。可以想象一下,十万卡集群大概一个小时可能挂一次,现有的一些技术体系不一定能支撑。比如现在异步的check point,这是第一个问题。
第二个问题就是一个任务中断,其实不是硬件出现故障,任务立刻就中断,它其实是有个时间会Hang住,这个时间其实是很大的占比,所以我们现在也在想办法,怎么把这个Hang的时间检测出来第一时间就已经挂了,提前从任务退出。那这里面就有个trade off,比如现在把时间调短,data loader可能本来时间就可能需要个几分钟,但可能就因为data loader Hang住,所以这里面有很多功能要做,第二个是重启的初始化时间。
怎么把初始化时间能给它干到一分钟以内,这个也是一个很关键要探索的点,现在很多这个业界现在也在搞这个方向,比如集合通信,集合通信初始化时间比较长,好消息是看到最新版本上面也是做很多优化。最后一点是热迁移,因为现在整个训练任务中一个节点挂了,整个任务就挂了,然后全部拉集。如果十万卡的level节点挂了,十万卡全部重启会令人很崩溃。所以怎么把挂掉的节点信息和参数之类的信息传到另外的节点,通过一个新的communicator把它建起来到communicate组里面。我觉得这是未来重要的探索方向,目前是已经跑通demo,但是这个东西可能跟上面的框架模型有很大的耦合度,所以现在没有生产。