首页 > 其他分享 >MegaScale:字节万卡集群

MegaScale:字节万卡集群

时间:2024-03-30 15:32:53浏览次数:25  
标签:字节 训练 测试 内存 MegaScale 万卡 GPU 节点 检查点

随着训练集群扩展到超过数万个GPU,软件和硬件故障几乎不可避免。字节引入了一个健壮的训练框架,实现了自动故障识别快速恢复,在最少的人为干预下实现了容错,并且对正在进行的训练任务的影响可以忽略不计。

1. 训练流程

  1. 分配资源:在接收到提交的训练任务后,driver进程会与自定义的Kubernetes接口,为每个executor分配计算资源并启动相应的Pod。
  2. 创建训练:一个executor管理一个节点。一旦executor完成了一系列的初始化任务,它就会在每个GPU上创建训练进程,并创建一个训练守护进程,该守护进程定期向driver发送心跳。这些心跳封装了各种形式的信息,以实现实时异常检测并发出早期警告(第4.2节)。
  3. 定期检测异常:当driver在特定的训练过程中检测到异常状态,或者在预定的时间窗口内没有收到执行器的心跳时,触发故障恢复流程。
  4. 异常诊断:driver将暂停所有执行器上正在进行的训练任务,并命令它们运行一系列自检诊断(第4.3节)。这些诊断测试经过精心设计,既轻量级又全面,涵盖了大多数常见的硬件和软件故障。
  5. 替换节点:一旦确定了有问题的节点,驱动程序就会向Kubernetes提交要阻止的节点的IP地址,以及在其上运行的Pod的信息,Kubernetes会驱逐有问题的节点,并使用通过诊断测试的等量的健康节点来补充集群。
  6. 手动诊断:可以通过用户界面,手动驱逐节点,特别是对于那些通过手动分析识别的节点,如第5节。
  7. 恢复训练:driver从最新的检查点恢复训练。我们优化了检查点和恢复流程,以尽量减少训练进度的损失(第4.4节)

2. 数据采集和分析

心跳消息包括:

  • executor的基本信息,如IP地址、Pod名称、硬件信息等
  • 训练进程的当前状态,使驱动程序能够及时发现任何明显的异常。
  • 训练过程的stdout/stderr日志。它们将被即时汇总、过滤和分析。如果检测到特定的警告或错误关键字,驱动程序将报告实时诊断信息。
  • 包括RDMA流量指标,作为网络利用率和效率的指标。训练过程中的一些异常可能不会表现为显式错误,从而给出训练正在按预期进行的外观。在这种情况下,RDMA流量指标作为一个关键指标。鉴于训练任务的周期性,每个步骤的网络流量特征应该表现出相似的模式。因此,RDMA流量的任何显著下降或异常波动都是潜在异常的信号。一旦检测到此类违规行为,驾驶员将发出警报,进行人工调查。如果流量完全停止,驱动程序将自动启动故障恢复程序。

为了加强对训练稳定性和运动成绩的监控,我们研制了精度达到毫秒级的监控系统。采用不同级别的监控来跟踪各种指标。

秒级监控通常用于评估整体健康状态,并排除常见配置对训练的影响。例如,ECN/PFC/QoS配置、链路振荡或任何其他网卡问题。

毫秒级监控则是用来判断网络是否拥堵,数据并行和管道并行的数据传输速度是否达到物理极限。

3. 诊断测试

在自检诊断中,存在执行时间和精度之间的折衷。

延长的诊断持续时间会对有效的训练时间产生不利影响,而高误报率会导致不必要地排除实际上正常工作的机器。

通过迭代实验和优化,我们部署了一套轻量级诊断测试,有效地覆盖了实际训练过程中遇到的各种硬件和软件故障

主机内网络测试。为了诊断主机内网络中的潜在瓶颈,我们使用内部开发的工具来测试两件事。

  • 环回测试测量:从所有RDMA NIC(RNIC)到各种主机内端点(包括内存节点和GPU)的环回带宽。它在主机内进行全网状测试,覆盖所有可能的链路组合。这使我们能够根据端到端带宽结果推断出PCIe配置中特定于链路的带宽降级和不规则性。
  • 第二个RNIC-to-RNIC测试检查同一主机上不同RNIC之间的连接和带宽性能。这些。测试可以深入了解RNIC是否符合硬件速度规格,以及底层路由配置正确。

NCCL测试。为了识别GPU通信中的潜在故障,我们在单个节点中的GPU之间运行了一个all2all的测试,以观察带宽是否与预期的基准对齐。一旦主机内通信测试通过,每个节点还将与同一ToR交换机下的相邻机器进行all-reduce测试,以评估节点间GPU通信。

4. 快速的checkpoint和恢复

在识别和驱逐故障机器之后,驱动程序需要通过从最近的检查点加载模型权重和优化器状态来恢复训练。关键是确保最新的检查点尽可能接近故障发生时的训练进度状态,以尽量减少计算和时间上的损失。这就要求我们在训练过程中增加检查点的频率。

但是,我们也希望减少检查点过程引入的延迟,特别是关键路径上的时间,因为它阻碍了训练的进度,从而阻碍了整体系统的吞吐量。为了实现快速检查点,我们引入了一种优化的两阶段方法。

  • 在第一阶段,每个GPU worker将其片上状态写入主机内存,然后继续训练过程(片上->片外)。在优化了Pytorch的序列化机制并使用了pinned memory后,由于PCIe带宽高(多少?),这个过程可以缩短到几秒,从而最大限度地中断正在进行的训练过程。
  • 在第二阶段,一个后台进程接管,将状态从主机内存异步传输到分布式文件系统(我们部署中的HDFS)进行集中维护(片外内存->远程mem)。这种将操作解耦为两个阶段的做法允许GPU工作进程在转储其状态后几乎立即恢复训练,而将更耗时的写入HDFS的过程卸载到一个单独的非阻塞进程。

固定内存pinned memory,或者不可分页内存,它的一个重要特点是操作系统,不会对这块内存分页、并交换到磁盘上,从而保证了内存始终驻留在物理内存中。

所以,操作系统能够安全地使某个应用程序访问该内存的物理地址,因为这块内存将不会被破坏或者重新定位。

从检查点恢复的上下文中,没有最后一个检查点就无法开始训练,因为它位于关键路径上。

这里的瓶颈是HDFS的带宽,特别是当每个GPU工作节点需要读取其对应的状态分区时。为了缓解这一瓶颈,我们提出了一种优化的数据检索策略。

多个GPU worker经常共享相同的状态分区,例如,相同数据并行组中的worker。相应地,我们指定组中的单个worker从HDFS读取共享状态分区。然后,该worker将状态分区广播给共享相同数据的所有其他GPU worker。这种方法有效地缓解了HDFS的带宽限制,从而大大减少了恢复时间。

5. 使用CUDA事件监视器进行性能诊断

在数万GPU的规模下,我们观察到,与较小规模的实验不同,不同的运行表现出不同的计算效率

即使使用相同的配置,这种不一致性仍然存在,如图6所示。我们还观察到,在这种规模下,训练任务的性能并不一致。随着时间的推移,各种训练任务的MFU逐渐下降。虽然这导致我们怀疑单个机器之间的差异,但在单个GPU GEMM微基准下没有检测到明显的差异。为了诊断这些性能问题,我们开发了一个性能分析工具,它记录了运行期间每个机器上关键代码段的执行时间。与之前的工具(如火炬分析器或MegatronLM计时器)相比,我们的工具基于CUDA事件方法对事件进行计时。这种方法最大限度地减少了对CUDA同步的需求,从而防止了性能下降,允许我们在生产训练作业中始终如一地运行它。该工具提供了两种可视化模式,可以从不同的角度对收集到的数据进行分析。

原文链接:https://arxiv.org/abs/2402.15627

标签:字节,训练,测试,内存,MegaScale,万卡,GPU,节点,检查点
From: https://blog.csdn.net/u011486857/article/details/137174394

相关文章

  • 面了字节 NLP 算法工程师(含大模型方向),跪了。。。
    节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学,针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。汇总合集:《大模型面试宝典》(2024版)发布!......
  • Qt 大小端字节序转换的方法
    在Qt中,可以使用qToLittleEndian和qToBigEndian两个函数来实现大小端字节序之间的转换。1.转换为小端字节序:1quint32num=0x12345678;2quint32littleEndianNum=qToLittleEndian(num);//转换为小端字节序2.转换为大端字节序:1quint32num=0x12345678;2quint......
  • Qt QByteArray中存储的字节顺序转换
    在QByteArray中,可以使用Qt的函数来实现字节顺序的转换。具体而言,可以使用 qFromBigEndian 和 qFromLittleEndian 函数将大端和小端字节顺序的数据转换为主机字节顺序的数据。同样地,可以使用 qToBigEndian 和 qToLittleEndian 函数将主机字节顺序的数据转换为大端......
  • Modbus通讯协议中的四种字节顺序
    国内设备基本上是ABCD顺序,国外设备基本上是BADC顺序。低位优先字节交换。使用两个寄存器。使用IEEE754规范,如显示不正常可进行字节顺序交换位置即可。如下:FloatBig-endian字节顺序:ABCDFloatLittle-endian字节顺序:DCBAFloatBig-endianbyteswap......
  • Siemens 西门子 PLC Modbus写入float字节排列
    写保存寄存器功能码16示意:在西门子PLC中,实数,float,的保存方式遵循“高字节低地址,低字节高地址”的方式。假设使用16功能码向PLC的40005写入一个float,先利用BitConverter.GetBytes(f)得到要写的float的byte[]A。根据PLC中的存储方式,要想获得正确的float,在字40005的低......
  • java实现字节数组转int(采用IEEE 754标准)
    /***字节数组转int*采用IEEE754标准**@parambytes*@returnfloat*/publicintbytesToInt(byte[]bytes){//获取字节数组转化成的2进制字符串StringbinaryStr=bytesToBinaryStr(bytes);//符号位......
  • 从字节码的角度看 python swap
    从字节码的角度看pythonswap背景从一道算法题开始:反转链表classListNode:def__init__(self,v)->None:self.val=vself.next=Nonedefadd_next(self,v):new_node=ListNode(v)self.next=new_noderetur......
  • 字节跳动面试面经
    面试方向岗位是后端开发实习生——番茄小说。职位JD没写什么,想要准备还得是广撒网。我当时的基本情况正在一个技术岗位实习,一个微服务项目,为了提升自己,在在线简历上面写了一个自己简单玩玩的ORM框架,手里就只有这些筹码。面经部分自我介绍这是个基本流程了。本人第一次面试大......
  • 【Web】随便聊聊应用ASM CoreAPI修改字节码那些事
    目录前言ASM概念Java字节码&ClassFile核心理念:拆分修改重组修改字节码最简化模型代码示例ASM修改类的基本信息ASM修改类的字段ASM修改类的方法常规实现AdviceAdapter实现前言本文速通下ASM最最萌新直观的部分,理解浅薄,纯小白文pom依赖<dependencies><depe......
  • 为什么使用类型化数组来进行字节操作而不是普通的 javascript 数字数组
    1.javascript中的数字数据类型默认为64位(8字节),无论任何数字。这意味着可以在不损失精度的情况下表示-2⁵³+1到2⁵³–1范围内的数字。这意味着即使我们想存储10个,也会消耗8个字节的内存,而这是根本不需要的。当内存效率是一个问题时,特别是在处理大型整数数组或二进制数......