ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

昇腾大模型训练全流程实战:从硬件底座到性能调优

昇腾大模型训练全流程实战:从硬件底座到性能调优 这几年大模型训练从拼显存、拼集群规模一路走过来真正在昇腾这套软硬件栈上把一条全流程完整跑通的人其实不算多。我自己的经历是从最早拿一张昇腾910B推理卡折腾小模型开始到后来在8卡节点上跑通百亿级参数的训练、调优、断点续训中间踩过的坑写出来能排好几页。这篇文章想把昇腾大模型训练的完整链路从硬件底座、软件栈、数据处理、并行策略到调试排查和性能调优按我实际操作的顺序全部捋一遍。适合两类人看一类是第一次接触昇腾手里有训练任务但不知道从哪下手的另一类是在别的框架上已经训练过大模型想快速把模型迁移到昇腾上又怕被各种细节卡住的。1. 先看清底座昇腾训练环境到底由什么构成1.1 硬件产品线从加速卡到整机形态很多刚接触昇腾的人第一反应是问“昇腾系列有哪些GPU”这里要纠正一个概念昇腾不是GPU是NPU也就是神经网络处理器。它的产品线分成训练和推理两条训练侧目前主流的是昇腾910系列尤其是910B系列。910B有几个细分型号B1、B2、B3我记得B3和B4更多是整机形态的差异比如910B3是双卡形态、910B4是八卡形态本质是同一个芯片的模组化组合。单卡HBM容量普遍到64GB这个显存规模在训练场景下够用但跟H100的80GB比还是得精打细算。实际部署时你接触到的往往不是裸卡而是整机比如Atlas 800T A2训练服务器一台机器就是8张910B卡卡间通过HCCS高速互联带宽大约392GB/s这个数字跟NVLink同代产品在同一水平线上。跨机通信走的是HCCL也就是华为的集合通信库对标的是NCCL。组网方面训练集群一般用RoCE或者infiniBand现在昇腾整机默认支持RoCE组网对绝大多数实验室和公司来说RoCE的性价比更高部署也简单不过需要额外配置交换机和网卡不能直接拿普通千兆交换机顶上。我自己踩过的一个坑是机间通信带宽不足导致训练效率上不去。8卡单机内部互联很快但是两个节点的网卡如果是25Gbps百亿模型跑起来通信等待时间非常明显跑分看着还行一上真实训练就露馅。所以做集群规划的时候建议节点间至少配100Gbps以上的RoCE网络最好是200Gbps否则分布式并行里的通信开销会直接吞掉算力增益。1.2 软件栈与框架适配CANN、torch_npu、MindSpore怎么选昇腾的软件栈最底层是驱动和固件上面是CANN统一异构计算架构再往上才是各种训练框架。CANN相当于昇腾的CUDA负责算子调度、内存管理、图编译这些脏活累活。CANN里面有个很重要的工具叫Ascend Graph引擎它会把训练脚本定义的算子构图编译成NPU能执行的整图或者子图这个编译过程对性能影响极大后面调优部分我会再展开。框架层现在有三条路可选。第一条是MindSpore这是昇腾的原生框架也是华为主推的路线优点是算子适配最全、性能优化最到位用静态图模式训练效果最好缺点是生态和PyTorch的差距还是存在很多现成模型代码不能直接搬。第二条是PyTorch加torch_npu插件这是目前社区里最常用的组合torch_npu就是一个适配层把PyTorch的算子调用桥接到CANN上让PyTorch代码在昇腾NPU上跑起来。第三条是MindFormers这类大模型套件它本身是基于MindSpore构建的内置了GPT、LLaMA、ChatGLM这些主流模型结构的实现同时支持数据并行、张量并行、流水线并行等策略的自动配置适合做大规模训练的用户。我个人的建议是如果你不是非PyTorch不可而且团队有精力学习新框架MindSpore路线的长线收益高尤其在图编译和融合算子这块昇腾自己东西适配自己的硬件性能上限更高。如果是急着把现有PyTorch代码迁移过来那torch_npu是务实的选择注意选对匹配版本就行比如PyTorch 2.1对应torch_npu 2.1.0CANN对应版本也有讲究这些在官方文档都有明确的配套表搬环境的时候一定要逐项核对版本不匹配会出现各种奇怪的行为后面调试章节会细讲。2. 训练前必须做对的数据与模型准备工作2.1 数据管线语料清洗、Token化与持久化格式很多人上手训练模型第一件事就是找模型结构、配环境反而把数据管线放到最后随便弄个DataLoader结果一训练就发现GPU利用率忽高忽低大量时间都花在等数据上。数据处理这件事在昇腾平台上尤其重要因为NPU和CPU之间的数据拷贝跟GPU平台不太一样不合理的数据管线会成为明确的性能瓶颈。数据准备阶段我一般按这个顺序走先是语料清洗把HTML标签、无关符号、重复段落、低质量文本过滤掉这一步很多人会省略但对训练质量影响非常大尤其对垂直领域模型数据和垃圾进垃圾出。清洗完之后是标准化统一编码格式、处理繁体简体、规整标点让文本进入Token化之前是一个干净、一致的状态。接着是Token化这一步要决定用现成的Tokenizer还是自己训练如果做中文场景建议在通用词表基础上做扩充或者重新训练词表考虑中文分词粒度比如基于sentencepiece训练一个中文BPE词表词表大小在32K到64K之间是比较合理的范围。词表太小会影响文本表示能力太大又会增加embedding的内存开销和通信量。Token化之后的数据需要落盘成便于高效读取的格式。昇腾平台上常用做法是转成MindRecord格式这是MindSpore的原生数据格式把样本打包成二进制文件读取时用MindDataset加载性能表现非常稳定。如果是PyTorch路线也可以用WebDataset或者简单的内存映射文件格式。这里补充一个关键细节不要用几百个小文件存数据文件数量太大会导致I/O瓶颈建议合并成10GB级别的大文件哪怕是同一个数据集也预先shuffle并切好分片让每个训练进程都只读自己的分片文件这是分布式训练数据管线的基本素养。2.2 模型迁移从CUDA代码到昇腾的常见改动如果手上是现成的PyTorch模型迁移到昇腾最理想的情况是只改设备指定例如把torch.device(cuda)改成torch.device(npu)model.cuda()改成model.npu().to(cuda)改成.to(npu)然后配上import torch_npu这个入口。但实际上很多模型会用到CUDA专属特性比如torch.cuda.amp混合精度接口、torch.nn.DataParallel这类并行封装这些在昇腾下往往有对应的替代方案比如amp可以用torch_npu提供的混合精度接口DataParallel可以用昇腾支持的DistributedDataParallel替代。算子兼容性是最容易卡壳的地方。CUDA里有些算子在昇腾上没有对应实现或性能极差典型如某些自定义的cuda extension、特定的attention实现。这时有两个选择一是改写模型结构用Ascend上已有的算子组合去实现同样功能二是走算子fallback路径torch_npu会尝试把不支持算子切回CPU执行这功能在调试期很省事但训练期会巨慢只能算应急不能作为常态。跑大规模训练前建议先花一天时间用小batch、少步数把整条链路过一遍用profiling工具看有没有CPU fallback算子。如果发现大量fallback趁早改代码不要等到大规模训练才暴露。另外一个容易忽略的是随机性对齐问题。如果迁移后要做精度对齐测试需要在代码里固定各种随机种子同时把CANN的确定性模式打开也就是设置环境变量让算子计算结果可复现。昇腾上不同的算子在不同shape下计算顺序可能有差异不定seed出来的loss曲线会对不上这会让人误判成模型代码问题实际上只是随机性问题。3. 大模型并行策略拆解从单卡到千卡集群3.1 三种基础并行方式DP、TP、PP到底在切什么分布式训练里的并行方式圈内简称“三种并行”DP、TP、PP。很多新手看到这三个缩写就懵其实用大白话解释特别简单。数据并行DP是最直白的方式相当于每个人拿一份完整模型的副本各学各的数据学完以后互相通报一下梯度大家取个平均再一起更新参数。这种方案的问题在于模型必须能装进单卡显存模型太大就放不下。张量并行TP则是把一个矩阵运算切碎到多张卡上计算好比把一个大型计算任务拆成小块分给多个计算员并行处理每个计算员只负责一小块结果最后拼起来。深度学习里最典型的是按头切分Attention层或者把线性层的权重矩阵按列切分。TP的好处是能把超大模型塞进多卡但坏处是每算一层都要跨卡通信通信量大通常只在单机内使用因为机间通信延迟太高会严重拖慢速度。流水线并行PP换个思路按层切分。想象一条流水生产线模型的第一层到第五层在卡A上算第六层到第十层在卡B上算数据像流水线上的产品一样逐层往后流。这种并行方式通信开销相对小但因为它是串行的所以会出现流水线气泡也就是某些卡处理完当前批次之后要等待前序卡的数据空转等待。气泡时间可以通过micro-batch调优把一个大batch拆成多个小batch依次灌进流水线减少等待间隙。3.2 昇腾场景下的3D混合并行与显存估算真正训练几百亿甚至上千亿参数模型时单一并行方式都不够需要把DP、TP、PP结合起来这就是常说的3D混合并行也常被叫做混合并行策略。我的经验是在昇腾平台上配置并行策略有个大原则TP优先控制在单机8卡内部因为它通信压力最大PP用来横向扩规模跨机的时候优先加PPDP在最后补足规模它的通信量最可控通用性也最好。举个例子如果要在32张910B上训练一个130亿参数模型单卡64GB显存常见的配置是4路TP乘以2路PP乘以4路DP也就是TP4保证单机内部做张量并行PP2让模型按层切成两个流水段DP4让四组流水线各自处理不同批次数据整个并行度计算下来是4×2×432正好等于总卡数。这种配置下每张卡的显存压力、通信压力和流水线气泡基本能平衡在比较合理的区间。显存估算方面有个经验公式可以先用起来。训练过程中显存主要被四个部分占用模型参数、优化器状态、梯度、中间激活值。以FP16混合精度训练为例参数是2字节每参数梯度也是2字节如果用AdamW优化器每个参数还要额外存一份主权重FP324字节加上一阶动量FP324字节和二阶动量FP324字节仅优化器状态就12字节每参数。因此粗略计算单卡显存需求参数总量乘以16字节再除以并行度。假设130亿参数除以TP和PP的乘积也就是130亿除以8得到单卡约16亿参数再乘以16字节约26GB这只是静态容量的保守估计还没算激活值。激活值这个变量很大取决于序列长度、batch size和模型结构通常再预留20GB到30GB比较安全。如果发现接近或超出64GB优先调小微批次大小减小序列长度或者开激活重计算这是释放显存最立竿见影的手段。4. 调试实战我踩过的高频报错与排查思路4.1 设备层问题卡不识别、驱动不匹配、HCCL通信失败昇腾训练调试和CUDA平台有个非常大的差异因为CUDA生态成熟很多问题能在更上层暴露但昇腾如果底层环境有偏差会直接表现为各种诡异现象。最常见的设备层问题就是执行npu-smi info时看不到卡或者卡的状态是异常。遇到这种情况我先查驱动和固件版本是不是和CANN配套这是头号原因。昇腾官方有一张软硬件兼容性列表驱动、固件、CANN版本必须严格对应比如CANN 7.0配的是哪个版本的驱动、升级CANN之后驱动没跟上、设备就会异常。解决方式很简单按官方配套表重装对应版本然后把内核重启一下。第二个高频问题是HCCL通信初始化失败。集群训练时多机HCCL初始化报错常见的现象是HCCL connect timeout这种多半是网络问题例如节点之间防火墙没放行通信端口或者RoCE网络没有正确配置。排查可以直接用hccl_tools.py脚本生成rank表然后跑一个简单的allreduce测试如果单机allreduce通过而多机失败问题基本就锁定在节点间网络上。另外rank表配置也要检查device_id和物理卡号是否一一对应IP地址是否写成了管理网地址这些都是我实际见过的坑。还有一个值得一说的是容器场景。昇腾NPU在容器里使用需要挂载设备需要设置昇腾专属的设备插件比如Ascend Docker Runtime。很多人本地跑通了一进容器就找不到设备原因就是容器运行时没配置好。Kubernetes集群里还要额外部署对应的NPU device plugin这部分和GPU的nvidia-device-plugin用法类似只是插件名和参数不同。4.2 训练过程问题loss不降、NaN、算子不支持和OOM训练过程中遇到的bug按我的经验可以分为四类loss不降、loss出现NaN、算子不支持、显存溢出OOM。loss完全不降先别急着怀疑优化器或者学习率。我会先确认数据是不是对上了比如tokenizer之后数据是否真的包含有效语义、标签是否和输入对齐。如果数据没问题再看模型输出层是否挂了正确的损失函数有些模型在迁移时会把损失函数漏掉或者写错。然后是学习率大模型训练一般要用warmup加余弦衰减如果用固定学习率且偏大很容易导致初始阶段loss震荡不收敛。最后检查梯度。做一个梯度打印看看回传的梯度数值是不是正常量级梯度为0或者梯度爆炸都能快速定位到具体层。loss出现NaN是另一个棘手问题。在混合精度训练下NaN最常见的原因是fp16的数值溢出表现为loss突然变NaN并且梯度里出现极大值。对策也明确一是使用动态loss scalingtorch_npu上调整对应混合精度缩放因子的策略二是改成bf16bf16的指数位和fp32一样动态范围更大但低精度尾数可能影响收敛精度需要具体任务测试。还有一个经常被忽略的原因是某些算子在低精度下对极端shape敏感比如LayerNorm在fp16下处理某些激活值会溢出这时需要把特定算子强制用fp32计算或者开启算子级别的精度补偿。算子和显存问题刚才讲模型迁移时已经提到了算子不支持这里补充OOM。OOM分两种一种是显存不足直接报错另一种是显存碎片导致的OOM。前者优先调减微批次大小为2的幂次、降低序列长度、开激活重计算后者在昇腾上可以通过设置内存管理环境变量让CANN做显存碎片整理开启block释放策略。每次调整batch size之后建议重新跑一遍profiling观察显存峰值而不是只盯着有没有报错。5. 性能调优关键手段利用率、通信与精度三者平衡5.1 监控先行npu-smi和profiling怎么看瓶颈性能调优第一步永远是量化分析。很多人一上来就调参数不看数据这跟盲人摸象差不多。昇腾上有一套完整的性能分析工具既有命令行工具也有可视化profiling工具。最简单的是执行npu-smi info查看实时算力利用率、温度和显存占用每几秒刷新一次。如果训练过程中NPU利用率长期低于80%说明训练流程中存在严重等待要么在等数据要么在等通信。数据加载瓶颈怎么看一个简单方法是把数据加载时间单独打点在训练循环里记录每个step的耗时把数据加载和forward/backward分开计时。如果数据加载时间占比超过10%就需要优化常见手段包括增加num_workers、开启数据预取、把数据落成MindRecord这类更高效的格式以及把数据文件分布到更快的NVMe磁盘上。训练中期我还会做一个实验把模型固定住不更新参数只跑forward和backward如果这个基准耗时远低于实际训练耗时通信或数据一定有问题。通信瓶颈的判断方法更直接。测不同并行配置下同一个step耗时比如同一模型分别用TP4和TP8各跑50步对比单步耗时变化。如果TP从4增加到8单步耗时反而显著上升那说明通信开销已经大于并行收益。这种时候就要调整并行配置把TP降下来用PP或者DP替代。profiling工具带出的信息还包括算子耗时排名。看单个算子耗时前20名通常会发现瓶颈集中在attention计算、LayerNorm、激活函数或者embedding上。昇腾平台上有些算子的融合版本明确比逐个算子快很多典型比如FusedRMSNorm融合归一化计算、FlashAttentionScore融合attention计算这些融合算子在框架层提供接口把对应模块替换掉单步速度提升10%到30%都不罕见。5.2 混合精度、梯度累积与静态图编译的调优实践精度策略是训练性能的关键变量。大模型训练在昇腾平台上我推荐的组合是FP16/BF16混合精度加动态loss scaling。FP16能大幅减少显存占用和计算量但前面提到的数值溢出问题需要靠loss scaling兜底。这里建议初始缩放因子设成65536之后让框架自动动态调整如果梯度超过阈值就降低缩放因子如果连续多步没有溢出就增加缩放因子。BF16不需要loss scaling因为它的动态范围和FP32接近但低精度尾数会让有些模型收敛变慢。实操中我会准备两套配置先跑小规模实验对比两者收敛曲线选效果更好的再上全量训练。梯度累积是解决显存不足的常用手段原理就是攒够多个小batch的梯度之后再更新一次参数效果等价于增大batch size。昇腾上做梯度累积有几个细节要特别注意梯度累积步数设成多少要看总的等效batch size是否符合模型训练的预期比如目标batch size是512单卡每次只能跑4条样本32卡数据并行下每步能跑128条样本那梯度累积步数是4。另外累计梯度期间BatchNorm这类依赖batch内统计信息的层会受影响大模型通常用LayerNorm不受此问题影响但如果是CNN类模型要谨慎。静态图编译是我强烈推荐的大模型训练加速手段。PyTorch默认是动态图模式边执行边构图灵活但开销大。昇腾的CANN本质上更适合静态图当训练脚本以静态图方式运行整个计算图会被完整编译优化算子融合、内存复用都能充分发挥。如果走torch_npu路线可以考虑把关键训练循环用图模式编译也可以用torch.compile配套昇腾后端。MindSpore默认调优就建议跑静态图模式性能提升立竿见影代价是动态shape处理要提前设计好比如输入序列长度不要频繁变化尽量padding成统一长度。这个约束在NLP训练场景下很自然。通信优化方面还有一个实用技巧调整HCCL的buffer大小。HCCL默认通信缓冲区可能不够在大模型场景下会造成频繁等待甚至通信超时把HCCL_BUFFSIZE设为256或更大往往能明显降低通信等待时间。另外开启梯度压缩或者使用梯度分桶通信机制让梯度数据分成小桶并行传输也能降低通信峰值压力。这些参数都藏在环境变量里不踩过坑的人很难主动去设置。6. 另一类全流程实践从3D重建到垂直行业微调6.1 昇腾跑3DGS三维重建的要点最近很火的三维重建方向3DGS也就是3D高斯泼溅很多人在昇腾上尝试跑通训练流程。3DGS的核心是CUDA实现的栅格化器和一系列自定义算子迁移到昇腾的主要工作就是把自定义CUDA算子替换成昇腾原生算子或者用torch_npu支持的算子重写。这一步绕不开也是最费时间的地方。我的建议是先梳理3DGS的算子清单找出哪些能用原生算子组合替代哪些必须自己开发。常见的高斯投影、alpha混合这些操作在昇腾上可以用组合算子和自定义算子的方式实现工程量大但对理解昇腾的算子开发框架有巨大帮助。如果只是想快速验证效果也可以考虑用纯PyTorch实现的高斯栅格化版本跑小场景实验性能差一些但能先把流程跑通。昇腾上做3DGS训练还有一个优势就是它的高显存容量对三维重建这种吃显存的任务比较友好。之前在单个游戏场景上做训练点云数量几十万级别单卡64GB完全够用。关键是OpenGL和pyrender这类依赖光栅化的库在NPU环境里不可用遇到渲染相关的预处理步骤要改用numpy和PyTorch纯张量操作来实现。整体来看3DGS迁移到昇腾是一个典型的算子迁移项目工程量集中在前端算子映射一旦算子打通训练流程和常规视觉模型训练没有本质差别。6.2 垂直行业大模型微调的数据来源与流程组织除了通用大模型垂直行业大模型的微调也是现在需求量非常大的方向比如之前讨论很多的数控机床维修垂直大模型。这类行业模型和通用大模型不一样的点在于数据来源高度分散训练流程很多时间其实花在数据工程上。以数控机床维修为例训练数据的来源至少可以列出六类一是在线数据包括维修论坛、行业社区、技术博客上的问题讨论和解决方案二是离线技术文档包括设备手册、维修手册、电路图纸说明、PLC程序注释这些需要OCR转成文本三是设备日志数据数控系统会记录大量报警代码、故障代码、主轴负载曲线和伺服驱动器参数这些时序数据和代码文本组合在一起能形成非常有价值的维修样本四是维修工单数据售后系统和报修记录里有大量历史故障描述、维修过程和结果这是真实的问答对五是专家经验通过访谈资深维修工程师把隐性经验转写成结构化的问答对六是标准规范包括国家标准、行业规范中的安全要求和操作规程。数据收集回来之后整理流程比通用语料更重。要做去敏感信息处理比如客户名称、地点、设备编号这类信息脱敏。要做问答案例清洗和重写把短答案扩写成完整的维修指导文本或者把长文本压缩成精准的问答对。垂直领域微调我更推荐用LoRA这类参数高效微调方式只需要在推理阶段前加载LoRA权重不用改动基座模型本身训练的算力和显存要求都低很多一张910B就能跑通中等规模数据的微调。6.3 开源训练平台与自己的落地选型建议聊到开源的大模型训练平台昇腾生态圈其实已经有不少可选项目。官方维护的MindFormers是一站式大模型训练套件支持从数据准备到分布式训练、评测、部署的完整流程内置多种主流模型结构也支持自定义模型迁移进来。基于MindSpore社区的ModelZoo里面也沉淀了大量模型案例可以直接参考训练配置。另外还有面向科学计算和行业应用的MindScience套件以及针对三维重建和其他图形任务的MindX系列工具覆盖的面越来越广。选平台的时候我的建议是不要盲目追求大而全而是看自己的团队现状。如果团队熟悉PyTorch又想尽量少改代码那么基于PyTorch的torch_npu加一套分布式训练框架就够用了先把代码跑通再逐步替换掉性能差的算子。如果是从零开始做训练平台建设MindFormers这类一站式套件的价值就体现出来了它把数据格式、并行配置、checkpoint管理这些细节都做了统一封装团队不需要自己重复造轮子。如果做的是科学计算或者三维重建这种算子自定义比例高的场景那么可能需要同时掌握MindSpore静态图开发和自定义算子开发两条路线。平台选型还有一个现实问题是调试工具链的成熟度。昇腾的调试工具在快速迭代但和CUDA生态的成熟度相比还有差距所以建议选平台时优先看它的profiling、算子分析和性能日志工具是否完整。真实训练时这些工具决定你排查问题效率的上限。最后再分享两个小经验第一训练脚本里从第一行开始就加上详细的日志每打印一次loss就记录当前学习率、全局步数、吞吐量、显存余量、数据加载耗时这些关键指标。我养成的习惯是每50步打一次摘要日志每500步触发一次profiling采样。很多难缠的性能问题事后复盘时靠这些日志就能直接定位省去大量重新排查的时间。第二昇腾环境做版本升级一定要先小规模验证再生产。每次升级CANN、torch_npu或者驱动先把之前跑通的训练任务在小数据集上重跑一遍观察loss曲线和单步耗时是否有变化确认指标不回退后再启动正式训练。我踩过一次大版本升级之后融合算子行为变化导致loss波动的情况排查了两天最后发现是版本升级后算子融合策略变化回退版本就恢复正常。版本升级后第一时间做回归测试这个习惯值得养起来。如果你正在从别的平台迁移大模型训练任务到昇腾不用一开始就追求全套性能指标达标先把全流程跑通再逐步做算子替换和性能优化这条路走起来最稳。昇腾这套生态还在高速发展期很多今天觉得麻烦的问题过几个月可能就已经被新版工具链解决掉了。
返回列表