尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

昇腾Benchmark基准测试实战:从工具选型到性能调优避坑指南

昇腾Benchmark基准测试实战:从工具选型到性能调优避坑指南 给昇腾做性能摸底这件事我这两年断断续续做了不少次。每次换模型、换CANN版本、换单卡和多卡第一件事都是先跑一把Benchmark把“这块芯片在当前配置下到底能跑多快”这个底数摸清楚。昇腾的Benchmark基准测试工具本质上就是一把量芯片性能的“标尺”。这篇文章就把我在实际项目里怎么选工具、怎么配参数、怎么看结果、怎么避坑的经验完整梳理一遍适合刚接触昇腾性能调优的开发者也适合正在做模型迁移或板卡选型的朋友参考。我一直觉得基准测试这件事看起来简单真正跑起来全是细节。同样的ResNet50换一个batch size结果能差出两倍同样的LLM推理脚本跑在310P3和910B上精度格式选FP16还是BF16吞吐量完全不是一个量级。所以这篇文章不只是罗列命令而是把每一个关键选择背后的原因讲清楚把我踩过的坑也一并写出来省得你再走一遍弯路。1. 先搞清楚Benchmark到底在“量”什么1.1 为什么需要一把“标尺”做昇腾相关的性能工作绕不开一个灵魂拷问这块NPU到底能跑多快很多人在刚开始接触昇腾的时候会习惯性地拿GPU的经验套上去比如直接看显存大小、看核数或者跑一个网上随手抄来的脚本拿了个数字就当结论。这样做很容易翻车因为NPU的架构特性和GPU并不完全一样算力峰值、带宽表现、算子调度方式差异很大单看某一个指标根本说明不了问题。Benchmark基准测试的价值就是给性能一个可复现、可对比的衡量标准。它解决的问题很具体同一份模型代码在昇腾设备上跑一次拿到一批能落地的数字——比如吞吐量、单次延迟、显存占用、算力利用率。有了这些数字你才能回答三个最关键的问题这个模型在当前硬件上能不能跑得动能跑到什么程度如果要优化瓶颈在哪我见过不少团队在昇腾上做模型迁移第一步不是跑基准测试而是直接闷头优化算子。结果优化了半天发现其实是数据加载卡住了NPU一直在等数据算力利用率只有百分之十几。如果一开始就跑了Benchmark把吞吐量和利用率两个数字摆出来瓶颈一眼就能看出来根本不用瞎猜。这就是“标尺”的意义——先把量级量出来再谈优化。1.2 昇腾场景下的Benchmark都测些什么昇腾平台的Benchmark通常分训练和推理两大场景测的指标侧重点不一样。训练场景下最关心的是吞吐量Throughput也就是每秒能处理多少个样本或者每秒能跑多少个Token。对CV模型来说就是images/s对NLP或大模型来说就是Tokens/s。这个数字直接决定了训练一个模型要花多少时间也决定了数据并行、流水线并行时卡间通信压力是否合理。训练Benchmark一般还会关注稳态功耗、显存占用和算力利用率特别是跑大模型的时候显存能不能塞下、带宽够不够都直接体现在这几个数字里。推理场景下除了吞吐量更关心延迟Latency和端到端首Token时间TTFT。比如一个在线推理服务用户请求进来多少毫秒能返回结果这个指标是业务方最敏感的。推理Benchmark还要区分单请求延迟和批量吞吐因为这两个数字在NPU上往往是跷跷板关系——batch size越大单次请求延迟越高但整体吞吐也越高。所以测试结果必须说清楚是在什么batch size下测的否则数字完全没法比较。另外昇腾场景下还会关注精度格式的选择。比如310P3在使用FP16还是BF16做推理时性能和精度表现差异很大这个我会在后面专门展开讲。Benchmark的作用就是把这些维度的数据都量化出来形成一张可对比的性能画像。2. 工具怎么选官方工具、ModelZoo脚本与社区神器2.1 先看官方家族ModelZoo与MindSpeed昇腾生态里最正统的Benchmark来源是官方维护的ModelZoo模型仓库。这个仓库里的每个模型都配套了训练和推理脚本很多脚本本身就内置了性能统计功能跑完会直接打印出吞吐量、显存占用等信息。我拿ResNet50做过验证ModelZoo的脚本在昇腾910B上跑出来的数字和官方发布的白皮书数据基本能对上说明脚本的统计逻辑是靠谱的。大模型训练场景下MindSpeed是绕不开的工具。它是昇腾专门做的大模型加速库内部实现了张量并行、流水线并行、序列并行等一系列并行策略同时也带了一套性能测试脚本。用MindSpeed跑一遍GPT类模型的pre-train脚本你能直接拿到不同并行配置下的吞吐量数据这对做大规模训练前的可行性评估非常有用。我建议做LLM训练的团队把MindSpeed的performance脚本当作标配每次改动并行配置或者优化算子之后都跑一遍作为回归测试。2.2 推理场景专业工具ais_bench与msame推理Benchmark的工具相对更专一些。msame是早期用得比较多的离线推理工具用法是先通过ATC工具把模型转换成昇腾的离线模型OM格式然后调用msame进行推理并统计时延。它的特点是简单直接一条命令跑完输出的数据很清晰适合验证单个模型的推理性能。但msame有个问题它是基于acl的顶层封装很多底层的性能细节看不出来。这两年我更推荐用ais_bench这是昇腾社区里维护得比较活跃的推理基准测试工具。ais_bench的优势在于支持更细粒度的性能统计包括模型加载时间、推理单次时延、吞吐量、设备利用率等而且支持动态shape对NLP模型特别友好——现在很多模型输入长度是可变的msame对动态shape的支持比较弱ais_bench就好很多。举个例子我在测一个BERT分类模型时需要在真实业务下按照实际请求的token长度分布去压测msame只能按固定shape跑测出来的数据根本没有参考价值。换成ais_bench之后能把动态seq_len场景下的P95时延、吞吐都测出来这个数据才能反馈给服务端做容量规划。如果你做的是推理服务性能评估我建议直接上手ais_bench。2.3 深度分析工具msprof与npu-smiBenchmark光拿到一个总耗时是不够的还得知道时间花在哪里。这时候就需要用到profiling工具。昇腾的官方性能分析工具是msprof它能把NPU上每个算子的执行时间、AI Core的利用率、内存读写带宽等信息统计出来。跑一次profiling你会看到一份算子级别的耗时排行哪些算子是大头哪些算子有空闲等待一目了然。npu-smi则更像是一个“随时开着的心电图”它负责查看NPU的实时状态包括芯片温度、功耗、显存使用率、AI Core利用率等。在跑Benchmark的时候我会并排开三个终端一个跑测试脚本一个用npu-smi info实时看利用率一个用msprof抓算子详情。这三样东西配合起来才能把一次Benchmark从“知道一个结果”升级到“理解一次结果”。很多人在Benchmark时只看最终打印的耗时然后就开始调参这是不够的。比如总耗时没变但npu-smi显示AI Core利用率只有30%那说明瓶颈根本不在计算而在数据搬运或算子等待如果AI Core利用率已经95%以上那说明计算本身已经接近饱和再调参空间也很有限。这些判断都依赖实时观测数据不是靠猜。3. 实战流程从零跑通一个昇腾Benchmark任务3.1 环境准备与版本匹配任何Benchmark的第一步都是先把环境检查好。昇腾这套体系版本匹配问题非常敏感CANN版本、固件版本、驱动版本、PyTorch适配版本之间必须严格对应。我统计过自己踩过的坑至少有一半是版本不匹配导致的玄学报错比如算子编译失败、设备ID找不到、莫名其妙的卡死。环境准备阶段我建议按顺序做三件事。第一用npu-smi info确认设备状态正常能看到芯片型号和显存信息。注意昇腾设备不像GPU那样直接叫显存它叫HBM但管理理念类似。第二检查CANN环境变量是否生效关键看toolkit路径下的set_env.sh有没有正确source通常安装CANN之后需要在~/.bashrc里追加source /usr/local/Ascend/ascend-toolkit/set_env.sh。第三确认PyTorch的昇腾适配版本torch_npu和CANN版本能对上官方文档里有对应关系表照着表核对就行。版本检查这一步我踩过的坑是在310P3机器上用了适配910B的torch_npu版本结果一跑就报算子不支持的错。后来把torch_npu降到对应版本问题马上消失。所以提醒大家昇腾的版本对应关系表一定要看别偷懒。环境变量方面有几个常用的需要知道。ASCEND_DEVICE_ID指定用哪张卡跑多卡时要分别设置。ASCEND_GLOBAL_LOG_LEVEL控制日志级别默认是1出问题排查时我会临时改成0看完整日志但正常跑Benchmark时一定要改回1否则日志量大到能拖慢程序。还有个环境变量ASCEND_SLOG_PRINT_TO_STDOUT打开后日志会输出到终端排查问题时很有用。3.2 模型准备与数据集预热Benchmark的模型准备通常有两种玩法一种是直接跑训练脚本或推理脚本一边跑一边统计另一种是先把模型转成OM离线格式再用推理工具测。前者灵活适合训练场景后者稳定适合推理性能验证。先说训练场景。以MindSpore或PyTorch的ResNet50为例训练脚本本身就有打印吞吐量的逻辑关键是选择合适的数据集和迭代次数。数据集我建议先用合成的dummy data也就是不加载真实图片直接生成随机数据喂给模型。这样做的好处是排除数据读取的干扰专门测计算性能。真实业务场景里数据加载通常用多进程DataLoader预取但Benchmark阶段我就是要看看纯计算能到什么程度所以dummy data是首选。迭代次数的设置也很有讲究。很多新手直接跑1000步就打印最终平均数据结果数字忽高忽低而且偏低。原因是前几十步存在warmup过程算子首次执行要做kernel编译、缓存填充、显存分配这些都会拖慢速度。我通常的做法是前100步作为warmup不做统计从第101步开始计时至少统计500步以上然后取平均值。这个数字才接近稳态性能。推理场景的话如果用msame或ais_bench模型要先通过ATC工具转换。ATC转换时除了模型路径还有几个关键参数framework指定原始模型格式ONNX是5soc_version指定芯片型号310P3就填Ascend310P3input_format指定输入格式NCHW或ND。转换成功后生成一个om文件这才是能跑推理的格式。整个转换过程可能遇到算子不支持的情况那是另一个故事了后面排查部分会说。3.3 关键参数解析与一次真实跑测把环境、模型都准备好后就可以开始正式跑测了。我拿一个实际做过的CV分类模型推理Benchmark为例完整跑一遍流程。首先用ATC把ONNX模型转成OM命令大致是这样atc --modelresnet50.onnx \ --framework5 \ --outputresnet50_310p3_fp16 \ --soc_versionAscend310P3 \ --input_formatNCHW \ --input_shapeinput:1,3,224,224 \ --precision_modeallow_mix_precision这里有两个值得说明的点。第一input_shape我固定成1,3,224,224这是batch size1的静态shape。如果是动态shape场景要用input_shape_range参数去定义范围。第二precision_mode我设置了allow_mix_precision这会让ATC自动把部分算子降到FP16执行以提升性能。310P3上FP16是主流精度BF16的支持情况要具体算子具体分析后面我会单独说。转完OM后用ais_bench跑推理命令大致是这样ais_bench --modelresnet50_310p3_fp16.om \ --batch_size1 \ --iterations1000 \ --warmup50--iterations是总共跑多少轮--warmup是前多少轮不计入统计。我习惯把warmup设成50iterations设成500以上数据比较稳定。跑完会得到一组输出核心数字包括模型加载时间、单次推理时延、每秒钟处理的图片数FPS、设备利用率。比如我当时跑的结果大致是单次时延1.8msFPS约520利用率60%左右。这个组合说明计算还没到瓶颈还有优化空间。后来我把batch_size提到8FPS变成1800左右利用率涨到85%说明批量推理对提高吞吐非常有效。训练场景的话我用MindSpeed跑过一个GPT-2规模的模型Benchmark核心关注的是吞吐量Tokens/s和显存峰值。跑的时候会加--recompute-granularity之类的参数尽量让显存和算力都利用起来。MindSpeed脚本跑完会把每一步的耗时和Tokens/s都打出来我取稳态阶段的平均值作为最终结论。4. 看懂结果精度、吞吐、延迟与资源利用率的真实意义4.1 310P3的精度选择FP16、BF16还是混合精度昇腾310P3在推理场景下精度格式的选择对性能影响极大。很多人问310P3使用什么精度合适我的实践结论是主流场景用FP16或混合精度BF16在部分算子上的支持还不够全面如果要整体走BF16需要先做算子兼容性验证。为什么这么说310P3的AI Core对FP16的计算效率远高于FP32大部分卷积、矩阵乘算子在FP16下能跑出接近峰值的性能。而BF16的优势在于动态范围和FP32一致不容易溢出但310P3上BF16的算子覆盖度不如FP16完整有些算子遇到BF16输入甚至会回退到FP32性能直接掉一截。所以我通常在ATC转换时用allow_mix_precision让工具自动选择最优的降精度策略这样既照顾了性能也兼顾了精度损失。在LLM推理场景里精度问题会更敏感。大模型的权重动辄几十亿参数如果全部用FP16权重范围大的层可能出现溢出如果全部用FP32显存又扛不住。这时候最稳妥的方案是混合精度敏感层如LayerNorm、Softmax保持FP32矩阵计算层走FP16。昇腾的ATC和推理引擎对这类混合精度策略支持得比较成熟实测下来精度损失控制在可接受范围内。我在一次LLM推理Benchmark里做过对比纯FP16推理的吞吐量比混合精度高约15%但生成文本的困惑度略有上升混合精度模式吞吐量只低一点输出质量更稳。所以如果你做的是对输出质量敏感的业务别一味追求最高吞吐建议跑一版混合精度的对比测试再下结论。4.2 吞吐量高不代表一切延迟和资源利用率要一起看很多人拿到Benchmark结果只看FPS高不高这其实是个误区。吞吐量高可能只是因为batch size开得大单次请求的延迟已经高到业务不可接受。所以我把Benchmark结果拆成三个维度看吞吐量Throughput、延迟Latency和资源利用率Utilization三者必须放在一起分析。延迟这个维度要区分平均延迟和P95/P99延迟。平均延迟低不代表用户体验好因为总有少量请求特别慢可能是排队等了很久也可能是动态shape下某个输入特别长。我会在ais_bench里打开延迟分布的统计把P95和P99数字单独记下来。如果P99比P50高出好几倍说明系统里有明显的抖动源需要排查是不是显存碎片、调度抖动或者某个算子在边界shape下耗时突增。资源利用率这个维度主要看AI Core利用率和HBM带宽。在推理场景AI Core利用率低于50%很常见因为推理请求可能稀疏或者图中有大量标量操作和同步等待。AIN Core利用率低本身不一定是坏事但如果你要提高吞吐就得知道瓶颈在哪是算力没用满还是带宽限制了还是算子切分粒度太粗导致流水线不饱和。msprof给出的算子流水图能清楚看到每个AI Core在哪些时间段是空闲的这比看总耗时有用得多。有一个经验可以分享看到“显存占用高”不要慌要区分是模型权重占的显存、激活值占的显存还是框架缓存占的显存。在跑大模型推理时有时候显存已经占了80%但AI Core利用率才30%说明权重和KV cache占了太多显存推理效率并不高。这时候要不要换精度格式降低权重内存要不要启用显存复用都要结合这组数据来判断。4.3 热词“昇腾960”带来的新思考最近工程群里经常有人聊昇腾960讨论新芯片在Benchmark上应该怎么测。我的看法是不管硬件怎么迭代“标尺”的逻辑不变先定场景再选工具最后把吞吐、延迟、资源利用率三个维度跑齐用同一套方法回归测试。芯片性能提升了Benchmark的数据自然会说话。但新芯片往往伴随新的算子库和新的CANN版本这意味着老版本环境下测出的数据在升级之后不一定还能复现。我建议团队在芯片或CANN升级后专门抽时间把历史Benchmark脚本全部回归一遍把新旧数据做对比这样才能判断性能提升到底来自硬件还是来自软件优化也能及时发现某些算子在新版本下性能回退的问题。5. 常见问题排查与踩坑实录5.1 测试结果忽高忽低怎么定位跑Benchmark最容易遇到的现象就是同一条命令连续跑几次FPS数字差出一大截。这种情况通常有三个原因系统里其他进程抢占资源、未做充分warmup、数据加载抖动。排查思路我一般是这样的先看npu-smi info确认NPU和HBM没有被其他任务占用再看CPU和内存的使用情况用top或npu-smi combo都能看到。如果系统很干净那就把warmup步数加大比如从50提到200再看结果稳定性。数据加载抖动的问题在训练场景更明显解决办法是改用dummy data或者确保DataLoader的prefetch足够大。还有一个容易被忽略的因素是电源和散热。NPU在长时间高负载下如果温度升高频率会下降导致性能回落。我跑长时间Benchmark时会在测试前先让设备空跑几分钟预热到稳定温度然后再开始计时这样拿到的数据更贴近真实长时间运行的表现。5.2 OOM与显存不足的常见解法昇腾设备上OOM报错也很常见尤其是跑大模型或在动态shape场景下。有个坑要特别注意静态shape模式下NPU会按照你设定的最大shape预留显存所以就算你只输入一个很小的tensor显存也可能已经占掉很多。应对方法是尽量让shape贴近真实业务分布而不是无脑设一个很大的上限。动态shape场景下显存使用会更复杂。因为框架需要为不同shape预留切换空间频繁变化shape还可能导致内存碎片累积跑着跑着就OOM了。我遇到过一次很诡异的OOM重启进程后就恢复了但跑几个小时又会复现。后来定位发现是动态shape切换次数太多导致显存碎片化。这个问题的解决思路是限制shape档位把动态范围切成分散的几档而不是完全连续变化能显著减少碎片。还有一点不要在环境下同时跑多个CANN程序却不清理缓存。CANN有内存池和算子缓存机制进程退出后有些缓存不会立刻释放。我养成一个习惯跑Benchmark前用npu-smi info确认显存已经清零必要时用工具重置设备状态再开始测试。5.3 精度不对和算子报错的排查经验Benchmark跑出来的数字异常不一定是性能问题也可能是精度问题。我开始做迁移的时候经常遇到推理结果完全不对的情况后来排查出来基本都是输入数据预处理不一致比如ONNX模型里要求输入是归一化到0~1我的脚本却直接喂了0~255的原始像素。这类问题在跑Benchmark时不会影响速度但结果明显不对需要先修正数据预处理再做性能评估。算子报错的排查相对容易一些关键是拿到详细的报错日志。先把ASCEND_GLOBAL_LOG_LEVEL改成0然后打开ASCEND_SLOG_PRINT_TO_STDOUT重新跑一次利用多输出的日志定位到具体是哪个算子、哪一步在报错。常见原因有两个一个是模型里用了昇腾还不支持的算子或特性比如某些自定义Op、某些控制流算子另一个是精度模式设置导致算子用降精度执行后溢出。处理方式也简单要么换一个精度模式要么在算子层面加白名单强制某些算子用FP32。说到精度我想单独提醒一下LLM推理场景下的精度问题。用FP16跑大模型如果输出质量明显下降先检查是否有梯度溢出的可能然后检查哪些层被降到了FP16执行。用msprof能导出算子执行精度信息一目了然。5.4 常见问题速查表把我在昇腾Benchmark中遇到的高频问题整理成一个速查表方便你有问题的时候直接对号入座。问题现象可能原因解决思路FPS数字忽高忽低其他进程抢占、未充分warmup、数据加载抖动清空环境、加大warmup、改用dummy data跑一会儿后性能和温度同步下降散热不足触发降频检查散热、先预热到稳定温度再测显存OOM但模型本身不大静态shape预留过大或内存碎片缩小shape上限、改用分档动态shape推理结果明显不对输入预处理不一致、精度溢出检查归一化参数、调整精度模式算子报错不支持模型用了不支持的算子或版本不匹配检查CANN版本、算子白名单MSprof抓不到算子详情日志级别过低或permission不足提高日志级别、检查运行权限多卡吞吐不对等环境变量未正确设置逐一核对ASCEND_DEVICE_ID与卡序列6. 进阶建议如何让Benchmark成为团队的基础设施Benchmark这件事做一次容易长期坚持很难。很多项目刚开始会认真测一版性能数据后面模型一改、代码一调就不再做回归结果性能悄悄退化了自己都不知道。我建议团队把Benchmark脚本沉淀成基础设施每次提交关键代码变更时自动跑一遍耗时短、结论清晰的Benchmark把通过/失败作为合并代码的门禁条件之一。具体做法上我倾向于维护一个benchmark_suite目录里面按场景分成train和inference两个子目录每个子目录下有多个完整的测试用例包含启动脚本、模型清单、测试参数和环境要求说明。跑的时候一个入口脚本按顺序执行所有用例最后汇总输出一份带时间戳的Markdown报告方便和之前的数据做对比。对于长期跟踪的项目性能和稳定性数据最好自动落库这样能画出一条性能变化曲线。曲线一旦出现突然的下滑就能立刻定位到是哪一次代码提交、哪一次CANN升级引起的。我就是靠这套方法在几次CANN升级后发现某个算子性能回退及时回退了版本避免了带病上线。回到“标尺”这个比喻一把标尺要真正发挥作用得保证每次测量都用同样的方法、同样的条件读数要能复现误差要在可控范围内。昇腾的Benchmark基准测试也一样它的价值不只在于第一次摸清硬件的底数更在于持续用它跟踪每一次优化、每一次升级、每一个模型变更带来的影响。我个人的体会是Benchmark数据积累得越久越能形成对芯片性能的敏锐感觉哪块板卡适合什么负载、哪个模型换到哪个卡上性能会怎样基本上测一次心里就有数了。最后再分享一个小技巧跑Benchmark之前把所有环境变量、版本号、模型文件哈希值都记下来和测试结果一起存档。这样做的好处是几个月后回看这份数据还能准确还原当时的测试环境不会出现“这个数字到底是在哪个版本下跑出来的”这种说不清的情况。基准测试的意义就在于可信、可追溯数据档案越完整标尺越可靠。
返回列表