大模型具有更多的参数量和更复杂的模型结构,在训练过程中需要耗费更多的计算资源和时间。尤其在AI框架动态图模式下易于开发调试带来了极大的灵活性,但也暴露了更多的性能及内存问题。本文将重点介绍昇思动态图下,大模型性能及内存常见的调优方法,以及如何使用工具快速分析并解决瓶颈,帮助大模型开发者们快速上手模型性能调优,提升训练效率,降低训练成本。
典型性能统计指标
- 单步时间(s):执行完一个完整BS的时间。
- 吞吐(Samples/s):网络模型在单位时间内可以处理的最大输入的训练样本数据。throughput =BS ∗N /step _time。其中,BS为每个数据并行维度的batch size大小,N为集群中数据并行维度的大小,step_time为在分布式集群中,执行完一个完整BS的时间(单位为s)。
- MFU(%):Model FLOPs Utilization,即模型算力利用率,是指模型一次前反向计算消耗的矩阵算力与机器算力的比值。它直接反映了模型在训练过程中对计算资源的有效利用程度。MFU的值受到多种因素的影响,包括但不限于:
- 模型架构:不同架构的模型在分布式训练中的算力利用率可能存在显著差异。例如,Transformer架构的模型由于其并行性和矩阵运算密集的特点,通常能够在分布式训练中实现较高的MFU。
- 分布式训练策略:包括数据并行、模型并行、流水线并行等不同的并行策略及这些策略的具体实现方式(如梯度累积、张量并行等),都会对MFU产生重要影响。
- 硬件环境:显卡型号、数量、网络连接速度等硬件因素都会限制分布式训练的性能和算力利用率。
- 软件优化:包括编译器优化、库函数优化、自动混合精度训练等软件层面的优化措施,也能在一定程度上提升MFU。
- 数据集和批次大小:数据集的大小和复杂性,以及训练时使用的批次大小,也均会影响每次迭代中的计算量和算力利用率。
- 线性度:单卡训练扩展到多卡、多机多集群后的效率度量指标称为线性度,又名加速比。一般根据吞吐率计算得到。即集群线性度为多机总吞吐率/(单机吞吐率*集群卡数)。线性度的取值范围为0~1,数值越接近于1,其性能指标越好,一般大于0.8认为较优。
MindSpore动态图机制介绍
动态图PyNative框架
MindSpore PyNative动态图模式采用pybind算子直调方法,提升API性能。2.3版本前,大部分API使用了小算子进行拼接,同时采用了单算子子图进行执行,需要进行单算子子图构图、编译优化、算子选择、算子编译等一系列操作,首轮性能较差。针对这两点进行性能优化,提出了算子直调的方式,即正向算子执行直接pybind调用到底层算子接口,减少整体流程和数据结构转换开销。不同API,性能提升0.5~4倍。此外,提供了基础分布式能力接口,如硬件相关接口、重计算接口、通信基础接口等。
详细介绍见:动态图支持算子直调
性能调优
为了优化前文介绍的性能度量指标,提升训练效率,一般从如下几个维度拆解优化。
- 数据处理耗时:指模型加载训练数据和权重的时间,包括将数据从硬件存储设备读取到CPU、在CPU中进行数据的预处理、以及CPU数据传输到NPU的过程。对于需要切分到若干张NPU上的模型,数据加载时间还包括从一张NPU广播到其他NPU上的时间。
- Host下发耗时:指Python侧脚本逻辑及api接口launch的时间,一般希望这部分耗时与Device执行流水起来,避免Device空闲。
- Device执行耗时:NPU侧执行各个算子计算逻辑的时间。
- 通信耗时:指在分布式训练中,设备之间进行通信传输的时间,可以通过优化网络拓扑、减少通信频率等方式来减少通信耗时。同时,通信和计算通常可以并行执行,并行库提供的并行技术会保证部分通信时间被掩盖。
用户编程checklist
- 关闭确定性计算
ms.set_context(deterministic='OFF')
- 关闭流同步
ms.set_context(pynative_synchronize=False)
- 使用高性能API
- mint:MindSpore提供了对标PyTorch的mint系列接口,绝大多数情况下,其性能会持平或高于原ops系列接口。详情参考API列表:mint接口列表
- 大模型融合算子,如RotaryPositionEmbedding、Swiglu等。
- 避免冗余的数据拷贝
- 尽量采用原地更新接口,减少冗余Tensormove操作
- 减少不必要的转连续操作:当前aclnn算子大多支持非连续输入,尽量减少在脚本中大量使用.contiguous(),或可以先is_contiguous()判断后再调用。
- 避免频繁数据拷贝:需要数据拷贝时,尽量采用.from_numpy接口,当数据连续时,会通过免拷贝方式将Numpy数组转换为张量。mindspore.Tensor.from_numpy
- 减少原生Python累加等函数使用,如.sum()(建议替换成mint.sum())
高阶优化特性
- JIT:将Python函数编译为可调用的MindSpore静态图,MindSpore可以在运行时对图进行优化,提升该模块性能,一般选择在优化器构造函数处添加@jit标签。详见:jit介绍