以昇腾NPU上的PyTorch推理任务为载体,演示runtime仓库中msprof性能采集、adump算子精度Dump、log模块日志导出的完整调优操作流程
前言
在昇腾NPU上做AI推理任务调优时,开发者经常遇到AI Core利用率低于30%的困扰,此时需要一套系统化的工具链来定位瓶颈所在。CANN社区在atomgit上开源的runtime仓库正是为此而生——它将昇腾NPU运行时所需的性能采集、精度Dump、日志管理三大维测能力整合到一个项目里。本文以一次PyTorch推理任务的端到端调优为线索,从源码编译到出报告,完整演示msprof采集性能数据、adump定位算子精度偏差、log模块保存异常现场的操作方法。整个流程不依赖任何第三方性能分析器,全部使用runtime仓库自带的工具完成。文中涉及的命令、环境变量、JSON配置项均来自runtime仓库源码和CANN官方文档,读者可以在自己的昇腾环境中直接复现。
环境安装:runtime源码编译与msprof/adump工具准备
runtime仓库的构建依赖CANN Toolkit包。开发者有两种路径获取编译环境:下载预编译的CANN包直接安装,或者基于源码自行编译。对于性能调优场景,安装预编译包是更直接的选择,省去了源码编译的等待时间。下面的命令以Ubuntu/x86_64环境为例,演示安装基础依赖和CANN Toolkit的过程。需要注意的是,Python版本要求不低于3.9.0(3.7和3.8官方已经停止维护,CANN将于2027年3月停止对这两个版本的支持),GCC版本要求不低于7.3.0,CMake版本不低于3.16.0:
sudo apt install python3 python3-pip python3-dev gcc-9 g++-9 libc6-dev cmake ccache autoconf gperf libtool make
chmod +x Ascend-cann-toolkit_${ver}_linux-x86_64.run
./Ascend-cann-toolkit_${ver}_linux-x86_64.run --install --install-path=/usr/local/Ascend
先装系统级编译工具链,再装CANN Toolkit——Toolkit包内部包含了msprof、adump等二进制工具,装完之后直接在PATH里可用,免去手动编译runtime源码的步骤。对于做性能调优的人来说,预编译包已经够用。
安装完成后需要验证驱动和CANN版本是否正确加载。npu-smi是昇腾NPU的设备管理命令,功能类似GPU领域的nvidia-smi,能够展示NPU芯片的温度、利用率、显存占用等实时状态。能正常输出设备信息说明驱动已就绪。紧接着用cat命令查看Toolkit版本号,这个信息在后续排查工具行为异常时是最关键的依据,因为不同CANN版本的msprof参数格式和adump配置字段可能存在差异:
npu-smi info
cat /usr/local/Ascend/cann/x86_64-linux/ascend_toolkit_install.info
npu-smi是昇腾NPU的设备管理命令,类似GPU领域的nvidia-smi。能正常输出设备信息说明驱动已就绪。第二行cat命令确认Toolkit版本号,后续遇到工具行为异常时,版本号是最关键的排查依据。
如果某些场景需要从源码编译runtime——比如要修改msprof或adump的内部逻辑,或者需要适配特定芯片版本(如Ascend 950PR/Ascend 950DT)的定制化功能——可以克隆仓库并执行构建脚本。源码编译主要面向深度定制场景,普通调优任务用预编译包即可。build.sh脚本会调用CMakeLists.txt定义的构建规则,产出与预编译包等价的二进制产物:
git clone https://gitcode.com/cann/runtime.git -b master
cd runtime && bash build.sh
源码编译主要用于深度定制场景。build.sh脚本会调用CMakeLists.txt定义的构建规则,产出与预编译包等价的二进制产物。普通调优任务不需要走这条路,直接用预编译包即可。
编译完成后,runtime目录结构中的src/dfx/msprof、src/dfx/adump、src/dfx/log三个子目录分别对应三大维测模块的源代码。include/dfx目录下存放对外头文件,定义了Profiling和Dump相关的数据结构。example目录下提供了基于ACL接口开发的样例代码,可以帮助理解工具的使用方法。如果只想了解工具的使用方法而不关心内部实现,直接使用预编译包中已经安装好的msprof、adump和msnpureport命令即可,无需编译源码。
对于在CentOS或EulerOS环境上工作的开发者,基础依赖的安装命令有所不同,需要用yum代替apt包管理器,其他配置步骤保持一致。如果使用Docker环境,runtime仓库的.devcontainer目录下提供了现成的容器配置,可以在容器内完成源码构建,避免宿主机环境冲突。容器化构建方式在多版本CANN共存或者需要精确控制编译环境的场景下尤为适用。
msprof性能采集:PyTorch推理任务的瓶颈拆解
环境就绪后,进入实战采集环节。本次演示的目标是一个基于ResNet-50的PyTorch推理任务,单batch size输入,跑在一张昇腾910B NPU上。msprof的采集方式是对整个推理过程做Instrumentation,记录每个算子在AI Core上的执行时间,并按流水线阶段(Vector、Cube、Scalar、MTE)做细粒度拆分。理解这四个阶段的含义对于后续的Profiling报告解读至关重要,每个阶段的耗时占比直接反映了算子的执行特征:Vector和Cube是AI Core上负责张量计算的两个核心单元,Vector处理逐元素运算和归约操作(如激活函数、BatchNorm),Cube处理矩阵乘法相关的卷积运算。Scalar负责标量运算和控制流逻辑,开销通常很小。MTE(Memory Transfer Engine)负责片上存储(Unified Buffer)与HBM之间的数据搬运,是算子性能的关键制约因素之一。
采集前的关键配置是设置环境变量,让msprof知道输出数据存放的位置以及采集粒度。这两个环境变量控制了Profiling会话的全部核心参数:
export MSPROF_PATH=/data/prof_output
export MSPROF_OPTIONS='{"output":"/data/prof_output","duration":10,"ai_core_profiling":true}'
MSPROF_PATH指定Profiling数据的输出根目录。MSPROF_OPTIONS用JSON格式控制采集参数:output指定子目录,duration限制采集时长(单位秒),ai_core_profiling打开AI Core级别的细粒度采集。duration不宜设太长,10秒对单次推理已经足够产生有统计意义的采样数据。
配置完成后,在推理脚本中插入msprof的启停调用。torch_npu是CANN提供的PyTorch扩展包,负责将PyTorch算子映射到昇腾NPU上执行。推理部分用torch.no_grad()包裹,避免梯度计算带来的额外开销污染性能数据。模型加载后需要调用eval()切换到推理模式,再通过.npu()将模型参数搬运到NPU设备上:
import torch_npu, torch
m = torch.load("resnet50_npu.pt")
m = m.eval().npu()
torch_npu.profiling._init_profiling()
torch_npu.profiling._start_profiling()
with torch.no_grad():
out = m(inp)
torch_npu.profiling._stop_profiling()
torch_npu.profiling._finalize_profiling()
torch_npu是CANN提供的PyTorch扩展包,负责将PyTorch算子映射到昇腾NPU上执行。_init_profiling到_finalize_profiling四步调用构成一个完整的Profiling会话,类似CUDA的nsys start/stop。推理部分用torch.no_grad()包裹,避免梯度计算带来的额外开销污染性能数据。
运行脚本后,msprof在/data/prof_output目录下生成一系列原始数据文件。这些数据需要用msprof自带的解析工具生成可读的HTML报告。解析过程会将原始二进制数据转换为包含Timeline视图、算子耗时排名、AI Core利用率等信息的可视化报告。msprof的–export参数触发整个导出流程,–source指向原始数据目录,–output指定报告输出位置:
msprof --export=on --output=/data/prof_output/report --source=/data/prof_output
–export=on触发数据导出流程,msprof会读取source目录下的原始二进制数据,生成包含Timeline视图、算子耗时排名、AI Core利用率等信息的HTML报告和配套CSV文件。报告默认存放在output指定目录。
Profiling报告解读:找到真正的瓶颈
打开生成的HTML报告,重点审视以下几个核心维度。
AI Core利用率曲线——报告首页展示推理过程中AI Core的利用率时序曲线。如果利用率长期低于30%,说明算子之间存在大量空闲等待,NPU计算单元没有被充分利用。此时瓶颈不在单个算子的计算速度,而在算子间的调度开销或者Host到Device的数据搬运环节。利用率曲线是判断整体调优方向的起点——高利用率说明瓶颈在算子内部,需要通过优化单个算子来解决;低利用率说明瓶颈在算子之间,需要通过改善调度或减少搬运来解决。
Task Duration按流水线拆分——msprof的核心能力是将每个算子的执行时间按AI Core内部流水线阶段拆分为Vector、Cube、Scalar、MTE四部分。这个拆分对于理解算子的实际行为至关重要。Vector和Cube是计算密集型阶段,代表NPU正在做有效计算。Scalar负责标量运算和控制流。MTE代表数据搬运。如果MTE阶段在一个算子的总耗时中占比超过40%,说明该算子受HBM带宽限制,片上存储放不下完整的中间数据,需要多次搬运才能完成计算。
以卷积算子为例:如果某个大尺寸卷积的Cube阶段耗时很低但MTE阶段很高,通常意味着feature map尺寸过大,片上统一缓冲区(UB)无法一次性容纳,需要将feature map切成多块反复搬运。这种情况下,调优方向是减小单次计算的数据量——可以通过调整Tiling参数或者对输入做padding对齐来改善。如果是深度可分离卷积,还可以考虑将Depthwise和Pointwise两个算子融合,减少中间结果的搬运次数。
算子耗时排名——报告中按总耗时降序列出所有执行过的算子。找到耗时最高的若干算子后,逐一检查其流水线拆分情况。耗时排名是粗筛工具,用来确定需要深入分析的候选算子。具体到每个候选算子,需要结合流水线拆分数据才能判断瓶颈类型——是计算瓶颈、带宽瓶颈还是调度瓶颈。
HBM带宽分析——当AI Core利用率低于30%时,HBM带宽瓶颈是最常见的诊断方向。msprof报告中的Memory Bandwidth图表展示每个时间点的HBM读写带宽。如果带宽已经打满但利用率仍然上不去,说明算子的计算密度不够高——NPU的计算单元在等待数据从HBM搬运到片上存储。这种场景下需要从算法层面优化,比如使用低秩分解减少矩阵乘法的计算量,或者将多个小算子融合减少搬运次数,或者增加batch size提高单次计算的吞吐量。
算子间Gap分析——报告中会显示相邻算子之间的Gap时间。如果两个相邻算子之间存在数百微秒以上的Gap,可能是因为调度器在等待某个Stream上的前序算子完成。这种调度开销在多Stream并发度不够时尤为明显。排查方向包括:检查推理脚本中是否有不必要的同步点(如.cpu()调用会强制Host等待Device完成),以及评估是否需要增加并发Stream的数量来提高算子间并行度。
综合以上维度的分析结果,可以确定瓶颈的精确位置。如果瓶颈在MTE阶段,优化方向是减少数据搬运量或改善数据局部性——具体手段包括使用AscendCL的内存管理接口预先分配HBM内存避免运行时碎片化、将连续多个小算子合并为一个大算子减少中间结果的读写次数、或者调整模型结构减少feature map的通道数和空间尺寸。如果瓶颈在算子间Gap,优化方向是提升调度并行度或消除不必要的同步——可以将不同分支的计算任务分配到不同的Stream上并行执行,或者移除推理脚本中隐含的设备同步操作。如果瓶颈在Cube或Vector阶段本身,说明该算子的计算密度已经很高,需要从算法层面寻找优化空间——比如将标准卷积替换为分组卷积或深度可分离卷积减少计算量,或者利用INT8量化将FP16的计算负载进一步压缩。
在解读报告时还有一个容易被忽略的细节:msprof会记录每个算子的调用次数。某些算子虽然单次执行时间很短,但由于被频繁调用(比如在循环结构中),累计耗时可能排在前几名。对于这类算子,优化方向不是降低单次执行时间,而是减少调用次数——可以通过算子融合将多次调用合并为一次,或者在图优化阶段消除冗余的算子节点。
另一个实用的分析技巧是对比不同batch size下的Profiling数据。当batch size从1增加到32时,如果AI Core利用率显著上升但推理延迟反而下降,说明瓶颈确实在调度开销而非算子计算。这种情况下,增加batch size本身就是一种有效的调优手段。反之,如果增加batch size后利用率没有明显变化,说明瓶颈在算子内部,需要从算法或Tiling层面优化。
adump精度问题定位
性能瓶颈解决之后,另一个常见需求是验证推理结果的数值精度。在昇腾NPU上,算子的计算精度可能因为FP16截断、算子融合策略或Tiling参数的差异,与GPU上的参考结果产生偏差。这种偏差在大多数场景下可以接受(cosine similarity大于0.999通常不影响下游任务的准确性),但在对精度敏感的场景(如量化训练、科学计算、自动驾驶感知模型)中,必须精确定位偏差来源。
runtime仓库中的adump模块专门处理算子精度的验证问题。它的工作原理是让NPU在执行目标算子时,将输入张量、输出张量、Workspace数据以及Tiling参数Dump到指定目录。开发者拿到这些数据后,可以与参考实现(比如PyTorch原生FP32计算结果)做逐元素对比,找出偏差的具体位置和幅度。adump的输出格式为NumPy的.npy文件,方便用Python直接加载分析。
adump的配置通过环境变量ACL_DUMP_CFG控制。这个环境变量接受一个JSON字符串,支持丰富的配置选项。下面展示一个典型配置,只Dump Conv2D算子的输出数据:
export ACL_DUMP_CFG='{"dump_path":"/data/adump_out","dump_mode":"output","dump_op_list":["Conv2D"],"dump_data_format":"NCHW"}'
ACL_DUMP_CFG是adump的核心配置项,采用JSON格式。dump_path指定Dump文件输出目录;dump_mode设为output表示只Dump算子输出(也可以设为input同时Dump输入);dump_op_list通过算子名称做白名单过滤,这里只关注Conv2D类算子;dump_data_format指定张量的存储格式为NCHW。通过白名单机制,开发者可以只Dump可疑算子,避免产出大量无关数据。
配置好环境变量后重新运行推理脚本。adump会在/data/adump_out下生成.npy文件,文件名包含算子名称和执行序号。加载这些文件与参考结果做对比时,需要关注三个核心指标:逐元素最大绝对差值、平均绝对差值和余弦相似度。最大绝对差值反映偏差的极端情况,平均绝对差值反映整体偏差水平,余弦相似度衡量两个张量在方向上的一致程度:
import numpy as np
a = np.load("/data/adump_out/Conv2D_output_0.npy")
b = np.load("/data/ref_conv2d_output_fp32.npy")
d = np.abs(a - b)
print(f"max abs diff: {d.max():.6f}")
print(f"mean abs diff: {d.mean():.6e}")
cs = np.dot(a.flatten(), b.flatten()) / (np.linalg.norm(a) * np.linalg.norm(b))
print(f"cosine sim: {cs:.6f}")
逐元素绝对差值和余弦相似度是衡量数值精度的两个标准指标。max abs diff反映最大偏差点,mean abs diff反映整体偏差趋势,cosine sim衡量方向一致性。对于FP16推理,cosine sim大于0.999通常被认为可接受。如果偏差集中在某些通道或空间位置,可能指向Tiling策略导致的边界处理差异。
除了精度验证,adump在排查AI Core Error问题时同样发挥着重要作用。当NPU上某个算子执行失败并返回错误码时,Dump出来的Tiling信息可以还原算子被切分成多少个子任务、每个子任务处理的数据范围。将enable_dump_tiling设为true后,adump会在输出目录中额外生成tiling_info.json文件,记录每个算子的Tiling参数(比如每个子块的高度、宽度、步长)。当算子因Tiling参数不合理触发AI Core Error时,这些信息是定位根因的关键依据——开发者可以将tiling_info中的参数手工填入单算子调试工具,在隔离环境中复现错误,避免在完整网络中反复调试的额外开销:
export ACL_DUMP_CFG='{"dump_path":"/data/adump_out","dump_mode":"all","dump_op_list":["MatMul"],"enable_dump_tiling":true}'
enable_dump_tiling设为true后,adump会在输出目录中额外生成tiling_info.json文件,记录每个算子的Tiling参数(比如每个子块的高度、宽度、步长)。当算子因Tiling参数不合理触发AI Core Error时,这些信息是定位根因的关键——开发者可以将tiling_info中的参数手工填入单算子调试工具,在隔离环境中复现错误。
在实际操作中,adump的Dump数据量可能非常大(尤其是Input+Output同时Dump时),建议先用白名单将范围缩小到可疑算子,确认方向后再逐步扩大范围。Dump完成后的数据分析可以用Jupyter Notebook进行交互式探索,结合热力图可视化偏差的空间分布。如果发现偏差集中在feature map的边界像素处,很可能是Tiling策略在边界区域使用了补零填充导致的,这种偏差通常可以通过修改算子的padding属性来消除。
adump还支持Dump Workspace数据。某些算子(如Sort、TopK)在执行过程中需要额外的Workspace空间作为临时存储,Workspace中的数据反映了算子内部计算的中间状态。对于这类算子的精度问题,同时Dump输出和Workspace可以提供更完整的调试信息。在ACL_DUMP_CFG中将dump_mode设为all即可同时获取输入、输出和Workspace三份数据。
log模块:异常时的现场保存
性能调优和精度排查之外,runtime仓库还提供了一套完整的日志体系。log模块的默认日志路径为/var/log/ascend_seclog,记录NPU运行时的进程执行信息、错误日志和系统级诊断信息。当推理任务在NPU上崩溃或算子返回异常错误码时,这些日志是诊断问题的基础材料。
Host侧日志——CANN运行时在Host侧产生的日志默认写入ascend_seclog目录,按日期和进程ID组织文件名。日志级别分为DEBUG、INFO、WARNING、ERROR四个等级,通过环境变量ASCEND_GLOBAL_LOG_LEVEL控制输出级别。调优期间推荐设为WARNING级别,既能捕获异常和警告信息,又不会因为DEBUG级别的海量输出淹没关键线索:
export ASCEND_GLOBAL_LOG_LEVEL=1
日志级别1对应WARNING,这是调优时的推荐设置——既能捕获异常和警告信息,又不会因为DEBUG级别的海量输出淹没关键线索。如果遇到难以复现的问题,可以临时设为0(DEBUG)获取完整上下文。
Device侧日志——NPU芯片内部产生的日志存储在Device侧存储中,Host侧无法直接读取。这些日志包括AI Core的硬件异常记录、ECC校验错误、地址越界告警等底层信息。runtime仓库提供了msnpureport工具来导出Device侧日志到Host侧指定目录。-d参数指定导出目标目录,-m all表示导出所有类型的Device侧日志(包括异常日志和诊断信息)。导出后的日志文件可以用文本编辑器直接查看:
msnpureport -d /var/log/ascend_seclog/device_log -m all
msnpureport的-d参数指定导出目标目录,-m all表示导出所有类型的Device侧日志(包括异常日志和诊断信息)。Device侧日志对于排查硬件级别的错误(如ECC校验失败、地址越界)是不可或缺的信息源。导出后的日志文件可以用文本编辑器直接查看。
日志联动调优策略——在实际调优流程中,log模块与msprof、adump形成互补关系:msprof告诉你哪个算子慢,adump告诉你哪个算子算得不准,log模块在底层异常发生时保存完整现场。三者在不同层面覆盖了昇腾NPU推理任务的完整可观测性需求。当msprof报告中出现大量标记为异常状态的算子时,应当立即检查ascend_seclog中对应时间段的ERROR日志,确认是软件调度层面的问题还是硬件层面的错误。msnpureport导出的Device侧日志则提供更底层的硬件视角,帮助区分是软件Bug还是芯片硬件异常。
日志文件的命名规则通常包含日期、进程ID和模块标识,方便在海量日志中快速定位特定时间段和特定模块的记录。在持续运行的推理服务中,建议配置日志轮转策略,避免日志文件占用过多磁盘空间导致系统异常。日志轮转可以通过CANN提供的配置接口设置最大文件大小和保留文件数量,当日志文件达到阈值时自动归档压缩。
在排查E2E级别的推理延迟抖动时,log模块记录的时间戳信息可以与msprof的Timeline视图交叉对比。msprof提供的是纳秒级的算子执行时间,log模块提供的是毫秒级的进程事件时间,两者的精度差异正好互补:msprof定位微观瓶颈,log模块追踪宏观流程。如果msprof显示某个时间段内没有算子在执行,而log模块在同一时间段记录了内存分配或设备初始化事件,就能确认延迟抖动的根因是Host侧的资源管理操作。
效率对比
下表总结了使用runtime仓库工具链前后,昇腾NPU推理任务调优效率的典型变化。数据来自多次PyTorch推理调优实践的综合观察,具体数值因模型结构和硬件配置差异而有所不同,这里用概括性描述呈现整体趋势:
| 调优环节 | 使用runtime前 | 使用runtime后 | 变化描述 |
|---|---|---|---|
| 性能瓶颈定位 | 依赖打印时间戳手动计算,无法拆分流水线阶段 | msprof按Vector/Cube/Scalar/MTE四阶段拆分Task Duration | 瓶颈粒度从算子级细化到流水线级,定位耗时缩短 |
| 算子精度排查 | 无法获取NPU内部中间结果,只能对比最终输出 | adump按算子名称Dump输入/输出及Tiling信息 | 问题定位范围从整个网络缩小到单个算子 |
| 异常现场保存 | Host侧日志分散,Device侧日志无法导出 | log模块统一管理日志路径,msnpureport导出Device侧日志 | 日志覆盖范围从仅Host侧扩展到Host加Device双侧 |
| 利用率诊断 | 只能凭经验猜测利用率低的原因 | msprof报告直接展示利用率曲线和HBM带宽时序 | 诊断依据从经验判断转变为数据驱动分析 |
结尾
runtime仓库将昇腾NPU运行时的三大维测能力——msprof性能采集、adump精度Dump、log日志管理——整合到一个统一的工具链中,源码完全开放,开发者可以按需定制和扩展。对于在昇腾NPU上做PyTorch推理调优的开发者而言,这套工具链提供了从性能瓶颈定位到算子精度验证再到异常现场保存的完整操作路径。本文演示的流程覆盖了环境安装、msprof采集与报告解读、adump配置与数据对比、log模块日志导出等核心环节,可以作为日常调优工作的操作参考。三个模块各有侧重又互为补充:msprof负责宏观的性能画像,adump负责微观的算子精度验证,log模块负责异常时刻的现场冻结。三者之间的协作逻辑也很清晰——先通过msprof定位到有问题的算子,再用adump获取该算子的详细计算数据,一旦发现硬件级异常则通过log模块调取完整的运行日志。
仓库地址:https://atomgit.com/cann/runtime
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐



所有评论(0)