oil-gas-ops-prospect性能调优实战:msprof上板采集与流水图仿真完整指南
【免费下载链接】oil-gas-ops-prospect面向油气勘探(oil & gas exploration)领域的昇腾自定义算子库。仓名即 oil-gas-ops(油气算子)+ prospect(勘探目标),面向地震成像、全波形反演等勘探计算场景项目地址: https://gitcode.com/cann/oil-gas-ops-prospect
在昇腾(Ascend 910B)上给油气勘探算子库 oil-gas-ops-prospect做性能调优,最难的一步不是改代码,而是把瓶颈看清楚。本文将带你完整走一遍两条核心采集链路:用msprof op做上板性能采集(拿 Kernel 耗时、核数、流水占比),以及用msprof 流水图仿真(看每个 AIV 核的指令级时间线),最后再补上业务 shape 的 Python 性能对拍方法,帮你建立"采集 → 分析 → 调优 → 回归"的完整闭环 🎯
一、先搞懂:上板采集 vs 流水图仿真的区别
oil-gas-ops-prospect 面向地震成像、全波形反演等勘探计算场景,仓库内置了ComplexMul(复数乘法)、FusedBiasSoftmax(融合注意力)等 AscendC 算子。性能分析时,官方推荐两种方式,各有分工:
| 维度 | 上板采集(msprof op) | 流水图仿真(msprof op simulator) |
|---|---|---|
| 运行环境 | 真实 910B NPU | 仿真库(无需上板热点指令级数据) |
| 看什么 | Kernel 耗时、Block 核数、各流水占比 | 单核指令流水时间线、指令级 cycles |
| 粒度 | 算子级摘要 | 指令级,比上板更细 |
| 结果形式 | OPPROF_*目录下的 CSV 摘要 | trace.json(Chrome Tracing 格式) |
一句话记住:先上板定位"慢不慢、慢在哪个流水",再上仿真定位"卡在具体哪条指令"。
二、一键准备:编译样例并验证功能
以仓库自带的ComplexMul样例为例(其它算子把路径换成examples/aclnn/<op>即可)。
第 1 步:加载 CANN 环境
source /usr/local/Ascend/cann-9.0.0/set_env.sh export ASCEND_HOME_PATH=/usr/local/Ascend/cann-9.0.0 export LD_LIBRARY_PATH=${ASCEND_HOME_PATH}/opp/vendors/customize/op_api/lib:${ASCEND_HOME_PATH}/lib64:${LD_LIBRARY_PATH}第 2 步:编译并跑通样例
bash examples/aclnn/complex_mul/run.sh这条命令会清掉旧的build/、output/目录,重新 cmake/make,并立刻跑一遍功能检查(脚本逻辑见 examples/_common/run_example.sh)。样例可执行文件会生成在examples/aclnn/complex_mul/output/下。
💡 提示:样例用的是
{2,2}小 tensor,Kernel 耗时只有数微秒——它用来验证采集链路,不能当业务性能数字。业务 shape 的性能数字请看第五节的 Python--perf对拍。
三、msprof 上板性能采集:一条命令拿到流水占比
确认功能正常后,在输出目录执行第二次 launch(默认预热 5 次):
cd examples/aclnn/complex_mul/output msprof op ./test_aclnn_complex_mul结果会落到同级OPPROF_<时间戳>_<随机串>/目录。本仓在真实 910B、CANN 9.0.0 上实测的输出摘要:
Op Name: ComplexMul_923973e39f803f5bc6ddb804acabf320_0 Op Type: vector Task Duration(us): 4.640093 Block Dim: 48 Device Id: 0其中Task Duration是 Kernel 耗时,Block Dim是实际执行的核数。结果目录各 CSV 文件速查表:
| 文件 | 含义 | 调优时看什么 |
|---|---|---|
OpBasicInfo.csv | 核名、Op Type、总耗时、Block Dim | 核数是否符合预期(Block Dim 是否用满 AIV 核) |
ArithmeticUtilization.csv | cube/vector 算力占比 | vector 算子看aiv_time / aiv_vec_ratio是否打满 |
PipeUtilization.csv | 各流水(VEC / MTE2 / MTE3 / SCALAR)耗时占比 | 瓶颈流水定位:占比最高的流水就是优化目标 |
Memory.csv | GM ↔ UB 带宽、搬运量 | 是否受限于搬运 |
MemoryUB.csv | UB 读写带宽 | UB 压力是否过大 |
L2Cache.csv | L2 命中 / miss | 数据复用性 |
ResourceConflictRatio.csv | bank / MTE 冲突与 wait 占比 | 冲突导致的等待 |
dump/op_basic_info.txt | 文本摘要 | 快速人读 |
分析要点:先看PipeUtilization.csv——如果 VEC 流水占比低而 MTE2/MTE3 占比高,说明是搬数瓶颈,应考虑切分(tiling)与双缓冲;如果 SCALAR 占比异常高,检查 kernel 里的标量循环。
四、msprof 流水图仿真:看到指令级时间线
当上板数据显示"VEC 没打满",却说不清卡在哪时,就上仿真。本仓默认SOC_VERSION=Ascend910B1,把仿真库加入LD_LIBRARY_PATH后:
export LD_LIBRARY_PATH=${ASCEND_HOME_PATH}/tools/simulator/Ascend910B1/lib:${LD_LIBRARY_PATH} cd examples/aclnn/complex_mul/output msprof op simulator --output=$PWD/pipeline_auto --kernel-name=ComplexMul ./test_aclnn_complex_mul⚠️ 关键细节:
--kernel-name填算子 OpType(ComplexMul),而不是入口符号complex_mul。本仓实测用 OpType 即可命中上板同一核名。
结果在pipeline_auto/OPPROF_<时间戳>_<随机串>/,核心产物结构:
└── simulator/ ├── trace.json # 全核 Chrome Tracing 事件(优先看这个) └── coreN.veccore0/ # 每个 vector 核一份;N 与 Block Dim 对应(本样例 0..47) ├── trace.json # 单核流水时间线 ├── coreN.veccore0_instr_exe.csv # 指令级:流水、cycles、耗时 └── coreN.veccore0_code_exe.csv # 源码行耗时;未编 -g 时只有表头怎么看:
- 用 Chrome 打开
chrome://tracing(或 MindStudio Insight),导入simulator/trace.json,即可看到 48 个核的泳道时间线; - 挑一个"看起来空闲时间长"的核,打开它目录下的
*_instr_exe.csv,定位阻塞的具体指令; - 结合 kernel 源码(如 ascendc/operators/complex_mul/op_kernel/complex_mul_impl.h)找到对应的切分或循环逻辑。
五、业务 shape 性能对拍:Python--perf才是"真数字"
上板样例是小 tensor,真正代表业务体量的对比走 Python 精度/性能对拍(输出相对误差与ms/call):
# 方式一:仓库根 bash build.sh -u --precision --perf --ops=complex_mul # 方式二:算子测试目录(会自动安装 OPP .run、编 pybind 再对拍) cd tests/ascendc/complex_mul && bash run_test.sh对拍脚本 tests/ascendc/complex_mul/test_complex_mul_npu.py 会按业务 shape 输出形如[perf] fwd torch=xx ms ascendc=xx ms speedup=x.xx x的加速比报告(脚本中--mode perf可只跑性能)。Triton 侧的 FFT 算子则用 tests/triton/real_fft/bench_opensource_perf.py 对比同设备torch.fft。
六、调优开关清单:改完代码怎么验证
| 调优动作 | 修改位置 | 验证顺序 |
|---|---|---|
| 改切分算法(核间均分、UB 分拍) | 各算子ascendc/operators/<op>/op_host/<op>_tiling_core.h | 先跑 ophost UT → 再上板看PipeUtilization |
| 调 FFT 行分块 | 环境变量OIL_GAS_OPS_FFT_BLOCK_M(默认 512) | 用 verify_triton_fft_real_128_3d.py 的--block-m覆盖 |
| 核对 Tiling 边界条件 | tests/ut/op_host/complex_mul/test_complex_mul_tiling.cpp | bash build.sh -u --ophost |
关于OIL_GAS_OPS_FFT_BLOCK_M:它控制 DFT-matmul 的行分块,受 910BL0C 中 fp32 累加器 ≤128KB约束,实现会按容量自动收缩、溢出时减半重试。手动扫一遍常见档位:
for m in 128 256 512; do OIL_GAS_OPS_FFT_BLOCK_M=$m python3 tests/triton/real_fft/verify_triton_fft_real_128_3d.py done📌 注意:
FusedSoftmaxGrad的 bf16 路径是 MIX(VEC+CUBE 混合),Op Type可能不是纯 vector,读 CSV 时要同时看 cube 与 vector 两列占比。
七、常见问题速查
- 采集时算子没生效(数字像 PyTorch 参考实现):AscendC 调用失败会静默回退。设置
export OIL_GAS_OPS_REQUIRE_ASCENDC_COMPLEX_MUL=1禁止回退,失败会直接报错; Block Dim远小于物理核数:多半是切分里aivNum计算有问题,先看 ophost UT 是否覆盖该 shape;- 仿真
--kernel-name不命中:确认填的是 OpType(ComplexMul)而非入口符号(complex_mul); - 仿真目录里没有
visualize_data.bin:CANN 9.0.0 本身不落这个文件,属正常现象,直接看trace.json。
总结:调优闭环四步走
- 上板采集:
msprof op拿PipeUtilization.csv,定位瓶颈流水; - 流水图仿真:
msprof op simulator导入trace.json,定位具体指令; - 改切分 / 分块参数:改
_tiling_core.h或OIL_GAS_OPS_FFT_BLOCK_M; - 回归验证:ophost UT + Python
--perf业务 shape 对拍,确认加速比不回退。
完整的调试与性能采集文档(含 Kernel 级printf/DumpTensor调试)见 docs/zh/debug/op_debug_prof.md,算子开发目录规范见 docs/zh/develop/operator_development_guide.md。掌握这套"上板 + 仿真"的组合拳,你的油气勘探算子调优就有了可靠的导航图 🧭
【免费下载链接】oil-gas-ops-prospect面向油气勘探(oil & gas exploration)领域的昇腾自定义算子库。仓名即 oil-gas-ops(油气算子)+ prospect(勘探目标),面向地震成像、全波形反演等勘探计算场景项目地址: https://gitcode.com/cann/oil-gas-ops-prospect
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考