ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

昇腾大模型训练实战:从环境搭建到性能调优的完整指南

昇腾大模型训练实战:从环境搭建到性能调优的完整指南 昇腾上的大模型训练真正让人头疼的不是把脚本跑起来而是怎么跑得稳、跑得快。我最近完整走了一遍昇腾环境下的模型训练全流程从环境搭建、脚本适配、分布式并行配置到性能分析和故障排查踩了不少坑也积累了一些实打实的经验。这篇东西不打算给你复述一遍官方文档而是按照实际操作的顺序把我认为最有用的调试调优思路和具体手段讲清楚适合正在接触昇腾训练、或者正准备从别的框架迁移过来的工程师参考。1. 从零搭建昇腾训练环境先把“地基”搞对很多人在昇腾上跑模型第一反应是赶紧装驱动、装框架然后拿训练脚本试跑。但大模型训练调试的第一步其实是把环境里最容易出问题的几层关系理顺硬件固件、驱动、CANN工具链、AI框架适配层这四者必须严格配套不然训练过程中会出现各种非常奇怪的随机问题。1.1 版本配套关系是一切的起点昇腾的软件栈跟常见的GPU平台不太一样。GPU平台上你装好驱动然后装CUDA再装PyTorch官方版本就基本能跑。昇腾这边多了一层CANNCompute Architecture for Neural Networks训练脚本真正调用的算子是通过CANN和相应的PyTorch适配层比如torch_npu传递到NPU上执行的。我第一次上手时犯的错就是没仔细看版本配套驱动和CANN版本不一致结果torch_npu在初始化阶段直接报错连设备都拿不到。后来养成习惯每次搭建环境前先查一张配套表固件版本、驱动版本、CANN版本、PyTorch版本、torch_npu版本、Python版本只要有一项不对齐后患无穷。我自己当前使用比较稳定的组合是这样的组件推荐版本方向固件与驱动5.1.RC2及以上具体视CANN版本而定CANN Toolkit7.0.RC1或更高Python3.8/3.9/3.10均可但必须与torch_npu的wheel包对应PyTorch2.1.0左右与torch_npu官方发布版本对应torch_npu与CANN版本一一对应发布页会标明这个表不是让你照抄而是提醒你每次建环境都先固定一个组合再照着官方文档装。另外CANN安装有Toolkit和Kernel两个包Kernel包含算子实现性能敏感的训练场景必须装上不能只装Toolkit就以为能跑出好性能。1.2 环境检查三件套驱动、固件、NPU状态装完之后不要急着跑训练。用下面几步确认环境是健康的npu-smi info查看NPU卡状态、显存占用、温度、版本号。如果命令不存在多半是驱动没装好或环境变量没刷。检查固件版本用npu-smi info里显示的固件版本和CANN要求的版本范围比对一下否则后续烧模型会踩到“算子执行失败”这种莫名其妙的问题。查看系统日志昇腾相关日志默认在/var/log/npu/目录下如果你的程序莫名其妙被杀了先翻日志里面通常有硬件或驱动报错。特别提醒多机训练时还要检查网卡和交换机的连通性RoCE或IB组网模式下网卡速率、MTU配置、IP路由都可能影响集合通信。多机环境里我建议先跑一次简单的ping和nccl_test昇腾对应的工具是hccl_test把通信链路验证后再上训练这能省掉后续调试时一半的抓狂。1.3 首个冒烟训练别急着上大模型环境就绪后我非常推荐先跑一段极小的冒烟代码验证“NPU能做事”。别上来就跑大模型不然一旦出问题你很难判断是环境问题还是模型代码问题。冒烟脚本可以做最简单的事定义两个张量送到NPU上做矩阵乘然后打印结果和设备名称。代码大致长这样import torch import torch_npu # 检查NPU是否可见 print(torch.npu.is_available()) print(torch.npu.device_count()) # 在NPU上做矩阵乘 x torch.randn(1024, 1024).npu() y torch.randn(1024, 1024).npu() z torch.mm(x, y) print(z.shape)如果这段能跑通说明驱动、CANN、torch_npu基本是通的。接下来再逐步加载真实模型每加一层复杂度定位问题的范围就小一圈。这是我个人调试的习惯环境越小越容易定位千万别把环境验证和模型验证混在一起。2. 训练脚本适配与迁移从GPU到NPU不是换驱动大模型训练脚本从GPU平台迁移到昇腾平台很多人以为只是把.cuda()换成.npu()就完事。真实情况是这只能解决最简单的张量搬运问题真正的坑在计算图构建、算子兼容性、混合精度策略、分布式通信这几块。我一共迁移过两套训练代码第一次花了整整一周第二次只花了一天差别就在于是不是摸清了适配的路径。2.1 最省力的迁移路径PyTorch torch_npu昇腾现在主流的训练开发方式是用PyTorch加上torch_npu适配层而不是强迫你换到MindSpore。如果你已经有完整的PyTorch训练代码迁移成本相对最低只需要在代码开头导入torch_npu然后把设备设置从CUDA改成NPU。最基本的改动形式import torch import torch_npu # 原来device torch.device(cuda) device torch.device(npu) # 原来model.cuda() model model.to(device) # 原来x x.cuda() x x.to(device)这种改法对大部分标准模型是够用的。但因为你偷了“少改代码”这个懒就必须要多花精力做验证。数据集加载、损失函数、优化器这些组件有些算子不一定在NPU上有原生实现运行到那里可能直接报“算子不支持”或者静默地走了CPU回退后者更危险因为训练不会挂但速度会突然掉下来。我的习惯是每一步关键操作后打上日志记录设备信息确认张量确实在NPU上而不是CPU。如果某个算子走了CPU训练时间长了你就会发现NPU利用率很低进程却很忙这种问题很难一眼看出来。2.2 逃不掉的计算图修改与算子适配大型模型里经常出现一些GPU平台上写习惯了的算子昇腾不一定完全对齐。最典型的就是动态shape问题GPU上PyTorch对动态shape容忍度较高而NPU上的很多高性能算子要求input的shape尽量静态动态shape会导致算子编译开销爆炸甚至直接编译失败。我在适配一个带变长输入的训练脚本时deepcopy模型结构后发现forward里有一处torch.catshape是随batch内样本长度变化的。在GPU上跑得很欢迁移到昇腾后训练速度惨不忍睹。最后我用padding把输入统一到最大长度把动态shape变成静态shape速度一下就正常了。所以遇到性能问题时先排查是不是有非必需的动态shape。另一个常见问题是自定义算子。模型里有些特殊算子NPU不支持先别急着写自定义算子优化思路是能不能用已有的算子组合实现同样功能如果必须自定义那就需要用昇腾的Ascend C算子开发能力这个难度就上去了非必要不轻易尝试。就算要做也先做单算子测试确认精度和性能达标后再集成到训练脚本里。2.3 我的迁移顺序建议先小后大、先跑通再调优迁移训练脚本时我遵循一套固定的顺序保证每个环节出问题都能迅速定位先小模型小batch跑通比如用单卡、batch size设为2只跑几个step不做完整训练。再跑完整训练流程加入checkpoint保存与加载验证训练能连续跑下去。然后加分布式先单机多卡再多机多卡每加一级都要做冒烟验证。最后调性能这时候才开始看Profiling数据调整算子、通信、数据加载等。这个顺序帮我避免了一个非常常见的悲剧直接把大模型和多卡并行全加进来结果环境、模型、分布式三方面问题混在一起排查了三天都没找到根因。3. 分布式并行策略选择DP、TP、PP怎么搭配大模型训练基本上逃不开分布式。昇腾上的分布式并行思路和GPU平台类似但落地细节有差异尤其是集合通信的实现方式不同。很多人一上来就把并行度拉满结果通信开销比计算还大训练效率一塌糊涂。3.1 读懂三种并行数据并行、张量并行、流水并行分布式并行的核心就是算力不够用多卡凑。但“多卡凑”有不同的凑法目标都是把大模型拆开只是拆的方式不同。数据并行Data ParallelismDP是最直观的每张卡放一份完整的模型把训练数据切成多份分给各卡每卡算自己的梯度然后全局同步。关键点是模型参数需要广播到所有节点各节点需要不断同步梯度。张量并行Tensor ParallelismTP是把模型某一层的计算按矩阵维度切分分到多张卡上。比如一个大的线性层可以按行切成两半放到两张卡上各自算完后再拼接结果。通信开销大但显存占用大幅下降。流水并行Pipeline ParallelismPP是把模型按层切段比如一个12层的Transformer第0到3层放在卡0第4到7层放在卡1数据从卡0流入再流到卡1。虽然通信次数少但存在设备空闲等待的“流水气泡”需要合理设计micro-batch数量来降低气泡影响。三种并行方式的核心差异在于“显存压力”和“通信开销”的权衡并行方式显存压力通信频率适用场景数据并行DP高每卡都有完整模型每次迭代同步梯度模型能塞进单卡显存张量并行TP低每卡只存部分层参数每层计算都通信超大单层显存极度紧张流水并行PP低每卡只存部分层段段间传输频率较低模型层数很深3.2 大模型场景下的并行组合思路真正训练大模型时单纯用某一种并行很少因为各自的短板太明显。比如一个千亿参数的模型单卡肯定放不下数据并行直接失效这时候必须用TP或PP把参数拆到多卡上。但TP每层都通信卡多了通信开销会非常夸张所以一般会限制TP的卡数。PP虽然通信压力小但空闲等待时间不可忽视。我实际调试中摸索出来的一个比较实用的组合策略是先按TP把单机内的卡组织起来控制TP的规模在4卡或8卡以内因为TP通信量最大放在同一台机器内走高速互联比较稳再用PP把模型层段切分到多台机器上每台机器处理一段连续层最后在PP之上叠加数据并行扩大整体吞吐。模型规模小时就别上TP和PP了直接用数据并行加梯度累积就够了。我见过一个团队用8张卡跑一个几亿参数的小模型硬是上了TP通信延迟比计算还长整体吞吐比单卡还差后来改成纯数据并行速度翻了几倍。所以选并行策略前先想清楚瓶颈在哪是显存放不下还是计算太慢还是数据来不及喂。3.3 并行配置的实操参数昇腾上配置分布式并行跟PyTorch的DDP思路差不多官方也更推荐在torch_npu上用torch.distributed来接。这里我列几个值得注意的参数梯度累积步数gradient_accumulation_steps显存放不下大batch时用小batch累加梯度模拟大batch效果。但这个参数会把通信频率一起降低因为每N步才同步一次梯度对小规模集群友好。学习率缩放梯度累积等效增加了batch size学习率也需要相应调整否则收敛不稳。常见做法是按“等效batch size / 原始batch size”的倍数做一定缩放。混合精度的loss scale大模型训练普遍用AMPAutomatic Mixed PrecisionNPU上对loss scale的处理有自己的一套机制。loss scale太大或太小都会出问题太大容易出现有穷值太小容易下溢要养成看训练日志里loss scale变化的习惯。实操层面我会先跑一个小的profiling观察通信算子比如AllReduce的耗时占比。如果通信占比超过30%说明并行策略可能有问题要嘛是TP规模太大要嘛是数据并行梯度同步太频繁这时候通常需要调整并行度或梯度累积步数。4. 性能瓶颈定位与调优让NPU真正跑满训练跑通只是第一步大模型训练贵在算力性能不达标的话资源成本是成倍增加。昇腾平台性能调优有一个我特别认可的思路不要靠猜一切用数据说话。开启profiling采集数据、分析算子耗时、找到真正的瓶颈然后针对性地做优化而不是听别人说哪个参数好用就去改。4.1 别瞎猜先开Profiling看数据昇腾上最常用的性能分析工具是msprof它可以采集训练过程中的算子耗时、通信耗时、NPU利用率、内存占用等信息。使用方式也很直接msprof --applicationpython train.py --output./profiling_data采集完成后输出的数据里有几个关键指标必须看NPU利用率正常情况下大模型训练应该在90%以上低于80%就要找原因。算子耗时分布耗时最高的前10个算子是什么有没有可以优化的空间。通信算子耗时AllReduce、AllGather这类通信在整体耗时中占比多少。Host到Device的数据搬运耗时如果DataLoader慢或者张量频繁在CPU和NPU之间搬运这项会很高。我遇到过一个典型的案例训练脚本里为了做验证每个epoch都往CPU搬运大量张量去算指标结果H2D/D2H耗时占了整体训练时间的15%把这段逻辑改成每隔N个epoch才验证一次训练时长明显缩短。这种问题如果不看profiling数据靠肉眼是发现不了的。4.2 数据IO是被低估的瓶颈大模型训练数据量动辄几十TB数据读取成为瓶颈的概率非常高。很多人把目光都集中在算子优化上忽略了一个事实如果NPU每轮训练都要干等数据利用率一定上不去。解决数据IO问题我有个固定的排查顺序看DataLoader的num_workers是否设了合理值。我一开始用默认值0结果数据加载在主进程里跑NPU利用率直接掉到50%左右。把num_workers设成CPU核数的一半左右利用率立刻回升。看数据存储介质。如果数据在机械硬盘上读取速度大概率是瓶颈。昇腾服务器一般都有SSD把数据集放到SSD上会快很多。看数据预处理复杂度。如果每个step都要做大量数据增强、解码而这些操作都发生在CPU上就会拖慢整个流程。推荐的思路是用基于缓存的数据管线尽量把解码和预处理的结果缓存下来减少重复计算。另外训练日志中如果发现DataLoader相关的时间特别高可以尝试开启预取prefetch功能让下一个batch的数据在训练当前batch时提前加载对流水线效率提升非常明显。4.3 通信与显存优化的几个细节通信和显存是两个容易出细节问题的地方。通信方面大模型训练最典型的就是集合通信的同步开销。数据并行下每次迭代都要AllReduce梯度卡数越多通信越重。一个非常有效的优化是“梯度压缩”在做AllReduce之前进行梯度量化或稀疏化。昇腾的集合通信库对这类操作有一定的内置优化建议先确认用的是否是官方推荐的通信设置再考虑更高级的压缩手段。显存优化方面最常见的手段是重计算recompute也就是不保存前向计算的中间激活值而在反向传播时重新计算一遍用额外计算量换取显存释放。在昇腾上开启重计算和GPU平台类似但要注意重计算层数的选择全开会导致训练时间明显变长一般只对最耗显存的几层开启。还有一个很容易忽略的显存坑checkpoint保存和评估时临时变量占用显存可能导致训练中途OOM。我的做法是保存checkpoint时先用torch.npu.empty_cache()释放缓存再执行保存逻辑能减少很多偶发的显存溢出。5. 训练故障排查与稳定性踩坑实录与速查昇腾大模型训练过程中最消磨耐心的不是性能不够而是各种突发故障。训练跑着跑着进程没了、loss不收敛、多卡训练hang住、显存莫名溢出这些问题我在实践里几乎都遇到过。下面这几个故障类型基本覆盖了日常训练调试中最常碰到的情况。5.1 经典故障一进程挂了、显存爆了模型训练跑了一半进程突然消失第一反应是看显存和系统日志。用npu-smi info看看显存占用是不是已经满了如果满得彻底多半是模型太大或者batch size太大。如果显存没满但进程还是挂了去看/var/log/npu/下的日志硬件或驱动层面的错误都会记录在这里。显存优化有几个好用的招调小batch size但要注意配合梯度累积保持等效batch size。开启激活重计算释放中间激活值。减小优化器状态例如使用Adafactor替代AdamW能显著减少优化器占用的显存。检查是否存在内存碎片训练中途如果频繁创建和释放大张量容易产生碎片必要时在关键步骤前空释放一次缓存。5.2 经典故障二loss不收敛或震荡loss不收敛的问题在框架迁移后特别容易出现因为很多细节在迁移时被忽略了。我遇到过的原因有几个第一个是混合精度缩放因子不当。loss scale过小梯度在fp16下容易下溢成0训练直接不更新loss scale过大梯度溢出成infloss猛涨。调优的方法是观察训练日志中的loss scale数值如果一直很小或者经常出现inf就要手动调整初始loss scale。第二个是学习率策略不对。大模型训练通常要配合warmup和余弦退火如果迁移脚本时把学习率策略丢了模型大概率不稳定。建议先从较小的学习率开始观察loss曲线的下降趋势再逐步调大。第三个是数据归一化不一致。如果训练脚本里对输入数据的归一化方式在迁移时被无意中改掉了模型看到的数据分布变了loss自然不收敛。排查方式是对比原始代码和迁移代码的数据预处理逻辑逐行确认。第四个是随机种子问题。框架不同、算子实现不同即使相同种子的计算结果也可能不完全一致这是正常的。但如果模型初始化的分布发生了巨大差异训练稳定性就会被影响可以在迁移后多跑几个不同种子的实验确认loss曲线整体形态合理。5.3 经典故障三训练hang住训练hang住是最让人崩溃的问题之一。多卡训练时某个进程卡住不动其他进程在等它同步整个训练看起来像冻住了一样。这种情况十有八九是集合通信出了问题。常见原因是某张卡的IP地址或网卡配置不对导致通信无法建立。排查方法是用hccl_tools里的检查脚本跑一遍通信测试如果测试挂掉检查机器之间的网络连通性和网卡配置。还有一种可能是某个rank在处理数据时异常退出其他rank在等它的通信消息。这种情况建议在训练脚本中开启超时检查机制一旦超过N分钟没收到通信消息就主动报错退出避免无休止的等待。训练hang还有一个我以前忽略的原因dataset的shuffle和sampler在多进程下行为不当导致某些rank拿到空数据集某个进程直接结束而其他rank还在等通信。加一个数据量校验确保每个rank都拿到了非空的数据集基本能避免这个问题。5.4 故障排查速查表为了方便快速定位问题我把日常遇到的情况整理成一个速查表遇到问题优先按这个表过一遍故障现象可能原因快速排查方向训练中途进程消失显存溢出、驱动异常npu-smi info看显存翻/var/log/npu/日志NPU利用率低数据加载慢、存在CPU回退算子开profiling看H2D耗时核对算子设备信息lossNaN或infloss scale异常、学习率过大检查loss scale值调低学习率多卡训练卡住集合通信异常、rank数据为空用hccl测试连通性检查数据集分配性能时快时慢动态shape触发算子重新编译检查输入shape是否稳定做padding保存checkpoint时OOM临时变量占用显存保存前主动释放缓存再执行保存昇腾大模型训练的调试调优说到底就是一个“环境—适配—并行—性能—稳定”五步走的过程每一步都有自己坑点但也有对应的套路可以借用。我在实际调优中越来越觉得稳定性才是大模型训练里最被低估的问题性能再好训练不能稳定运行超过一周也是空谈。所以除了关注吞吐和利用率这些性能指标我也建议把故障恢复和日志监控放到同等重要的位置训练脚本里埋好断点续训的逻辑自动记录step数和loss曲线一旦异常退出能够快速恢复而不是从头再来。最后分享一个我自己一直坚持的习惯每次训练调试都保存一份完整的实验记录包括环境版本、代码commit号、训练参数、profiling数据、遇到的问题和处理方式。大模型训练是长周期、高成本的技术活这份记录哪怕多花半小时下一次遇到同类问题时能省下的时间可能论天算。
返回列表