手把手实战:五步验证 CANN 五层架构每层的状态 很多人用昇腾NPU 训练模型跑起来也没报错但不知道每层的状态是不是正常的。这一篇教你用五步验证 CANN 五层架构的每一层是不是在正常工作。每一步都有命令和预期输出照着做就行。第一步验证 Framework Adaptor控制面板是不是正常工作Framework Adaptor 是 CANN 的最上层负责把 PyTorch 的计算图翻译成 NPU 能执行的计算图。如果这一层不正常你的模型根本跑不起来。# step1_verify_framework_adaptor.pyimporttorchimporttorch_npuprint( 第一步验证 Framework Adaptor )# 检查1NPU 设备是否可用print(fNPU 设备是否可用:{torch.npu.is_available()})# 预期输出True# 检查2张量能否正确放到 NPU 上xtorch.randn(3,3).npu()print(f张量设备:{x.device})# 预期输出npu:0# 检查3简单计算能否在 NPU 上执行ytorch.matmul(x,x)print(f计算结果的设备:{y.device})# 预期输出npu:0# 检查4PyTorch 的算子是否路由到了 NPU 的实现# 如果 Framework Adaptor 正常下面的调用会走 NPU 的 matmul 实现torch.npu.synchronize()print(✅ Framework Adaptor 正常PyTorch 已正确路由到 NPU)# 检查5查看 Framework Adaptor 的日志可选importos os.environ[ASCEND_LOG_LEVEL]INFO# 重新运行上面的代码会输出 Framework Adaptor 的路由日志预期输出 第一步验证 Framework Adaptor NPU 设备是否可用: True 张量设备: npu:0 计算结果的设备: npu:0 ✅ Framework Adaptor 正常PyTorch 已正确路由到 NPU如果torch.npu.is_available()返回False说明 Framework Adaptor 没装好重新安装torch-npu包。第二步验证 ops-transformerAOL 算子库的算子是否可用ops-transformer 是 CANN 第二层 AOL 算子库中的一个子仓库提供了 Transformer 架构需要的高性能算子。如果这一层不正常你的模型能跑但性能会很差。# step2_verify_ops_transformer.pyimporttorchimporttorch_npuprint(\n 第二步验证 ops-transformer )# 检查1能否导入 ops-transformer 的算子try:fromflash_attention_opsimportflash_attention_npuprint(✅ ops-transformer 导入成功)exceptImportErrorase:print(f❌ ops-transformer 导入失败:{e})print(请检查 ops-transformer 是否正确安装参考 step3_install_ops_transformer.sh)exit(1)# 检查2算子能否在 NPU 上正常执行Qtorch.randn(4,32,2048,64,dtypetorch.float16).npu()Ktorch.randn(4,32,2048,64,dtypetorch.float16).npu()Vtorch.randn(4,32,2048,64,dtypetorch.float16).npu()try:outputflash_attention_npu(Q,K,V,causalTrue)torch.npu.synchronize()print(f✅ FlashAttention 算子执行成功输出 shape:{output.shape})# 预期输出torch.Size([4, 32, 2048, 64])exceptExceptionase:print(f❌ FlashAttention 算子执行失败:{e})exit(1)# 检查3算子结果是否数值正确和 PyTorch 原生实现对比output_nativetorch.nn.functional.scaled_dot_product_attention(Q,K,V,is_causalTrue)max_err(output.cpu().float()-output_native.cpu().float()).abs().max().item()print(fFlashAttention vs 原生实现最大误差:{max_err:.6f})ifmax_err1e-3:print(✅ 数值正确性验证通过)else:print(❌ 数值误差过大检查算子实现)# 检查4查看 ops-transformer 的版本可选importsubprocess resultsubprocess.run([pip,show,ops-transformer],capture_outputTrue,textTrue)print(fops-transformer 版本信息:\n{result.stdout})预期输出 第二步验证 ops-transformer ✅ ops-transformer 导入成功 ✅ FlashAttention 算子执行成功输出 shape: torch.Size([4, 32, 2048, 64]) FlashAttention vs 原生实现最大误差: 0.000456 ✅ 数值正确性验证通过 ops-transformer 版本信息: Name: ops-transformer Version: 1.0.0 ...如果导入失败参考第三步的安装脚本。第三步安装并编译 ops-transformer如果第二步失败了如果第二步验证失败需要重新安装并编译 ops-transformer。# step3_install_ops_transformer.sh#!/bin/bashset-eecho 第三步安装 ops-transformer # 检查1CANN 环境是否配置好if[-z$ASCEND_HOME];thenecho❌ ASCEND_HOME 环境变量未设置请先安装 CANNexit1fiecho✅ ASCEND_HOME 已设置:$ASCEND_HOME# 检查2CMake 是否可用if!command-vcmake/dev/null;thenecho❌ CMake 未安装请先安装 CMake 3.18exit1fiecho✅ CMake 版本:$(cmake--version|head-n1)# 步骤1克隆 ops-transformer 仓库if[!-dops-transformer];thengitclone https://atomgit.com/cann/ops-transformer.gitecho✅ ops-transformer 仓库克隆成功elseecho✅ ops-transformer 仓库已存在fi# 步骤2创建 build 目录并编译cdops-transformermkdir-pbuildcdbuild cmake..\-DCMAKE_INSTALL_PREFIX$HOME/ops-transformer-install\-DCMAKE_PREFIX_PATH$(python3-cimport torch; print(torch.utils.cmake_prefix_path))cmake--build.-j$(nproc)cmake--install.echo✅ ops-transformer 编译安装成功# 步骤3把编译好的算子库加到 PYTHONPATHexportPYTHONPATH$HOME/ops-transformer-install/lib:$PYTHONPATHechoexport PYTHONPATH$HOME/ops-transformer-install/lib:$PYTHONPATH~/.bashrcecho✅ PYTHONPATH 已更新# 步骤4运行示例验证cd../examples/ python3 flash_attention_example.pyecho✅ 示例运行成功ops-transformer 安装完成预期输出 第三步安装 ops-transformer ✅ ASCEND_HOME 已设置: /usr/local/Ascend ✅ CMake 版本: cmake version 3.18.0 ✅ ops-transformer 仓库克隆成功 [100%] Built target flash_attention ✅ ops-transformer 编译安装成功 ✅ PYTHONPATH 已更新 Output shape: torch.Size([4, 32, 2048, 64]) ✅ 示例运行成功ops-transformer 安装完成第四步验证 GE图引擎的融合是否生效GE 是 CANN 的第三层负责在编译期融合算子。如果这一层不正常你的模型能跑但性能会差很多。# step4_verify_ge_fusion.pyimporttorchimporttorch_npufromtorch_npu.profilerimportprofile,ProfilerActivityprint(\n 第四步验证 GE 融合 )# 检查1用 Profiler 抓 trace看 FlashAttention 是否融合成功Qtorch.randn(4,32,2048,64,dtypetorch.float16).npu()Ktorch.randn(4,32,2048,64,dtypetorch.float16).npu()Vtorch.randn(4,32,2048,64,dtypetorch.float16).npu()withprofile(activities[ProfilerActivity.NPU],export_namestep4_ge_fusion.json):outputtorch.nn.functional.scaled_dot_product_attention(Q,K,V,is_causalTrue)torch.npu.synchronize()print(Profiler trace 已保存到 step4_ge_fusion.json)print(请打开这个文件搜索 FlashAttentionKernel)print( - 如果搜到说明 GE 融合生效了 ✅)print( - 如果搜不到说明 GE 融合未生效 ❌)# 检查2查看 GE 的融合日志需要设置环境变量importos os.environ[ASCEND_GLOBAL_LOG_LEVEL]3os.environ[GE_LOG_TO_STDOUT]1# 重新运行一次outputtorch.nn.functional.scaled_dot_product_attention(Q,K,V,is_causalTrue)torch.npu.synchronize()# 在日志输出中搜索 fusion_pass 或 FlashAttentionFusion# 如果看到 FlashAttentionFusion: success说明融合成功# 检查3对比融合前后的性能importtime torch.npu.synchronize()starttime.time()for_inrange(100):outputtorch.nn.functional.scaled_dot_product_attention(Q,K,V,is_causalTrue)torch.npu.synchronize()endtime.time()print(f融合后 100 次耗时:{end-start:.2f}s)print(f单次耗时:{(end-start)/100*1000:.2f}ms)# 如果单次耗时 50ms (seq_len2048)说明融合大概率生效了预期输出 第四步验证 GE 融合 Profiler trace 已保存到 step4_ge_fusion.json 请打开这个文件搜索 FlashAttentionKernel - 如果搜到说明 GE 融合生效了 ✅ - 如果搜不到说明 GE 融合未生效 ❌ 融合后 100 次耗时: 3.45s 单次耗时: 34.50ms如果单次耗时 100ms说明融合可能没生效检查 GE 的融合日志。第五步验证 Runtime 的调度是否 overlapRuntime 是 CANN 的第四层负责调度算子执行和数据搬运。如果这一层不正常计算单元会经常等待数据。# step5_verify_runtime_overlap.pyimporttorchimporttorch_npufromtorch_npu.profilerimportprofile,ProfilerActivityprint(\n 第五步验证 Runtime 调度 )# 检查1用 Profiler 抓 trace看计算和数据搬运是否 overlapQtorch.randn(4,32,4096,64,dtypetorch.float16).npu()Ktorch.randn(4,32,4096,64,dtypetorch.float16).npu()Vtorch.randn(4,32,4096,64,dtypetorch.float16).npu()withprofile(activities[ProfilerActivity.NPU],export_namestep5_runtime_overlap.json):outputtorch.nn.functional.scaled_dot_product_attention(Q,K,V,is_causalTrue)torch.npu.synchronize()print(Profiler trace 已保存到 step5_runtime_overlap.json)print(请打开这个文件看计算 kernel 和数据搬运 kernel 的时间轴)print( - 如果计算 kernel 和数据搬运 kernel 有重叠说明 Runtime overlap 生效了 ✅)print( - 如果计算 kernel 和数据搬运 kernel 完全串行说明 Runtime overlap 未生效 ❌)# 检查2用 npu-smi 查看 NPU 的利用率importos os.system(npu-smi info -l step5_npu_util.txt)print(NPU 利用率已保存到 step5_npu_util.txt)print(查看利用率)print( - 如果 Compute Cube 利用率 80%说明 Runtime 调度得很好 ✅)print( - 如果 Compute Cube 利用率 50%说明计算单元在等数据 ❌)# 检查3对比 overlap 开启/关闭的性能需要设置环境变量os.environ[ASCEND_OVERLAP_DISABLE]1# 关闭 overlaptorch.npu.synchronize()starttime.time()for_inrange(50):outputtorch.nn.functional.scaled_dot_product_attention(Q,K,V,is_causalTrue)torch.npu.synchronize()endtime.time()print(foverlap 关闭后 50 次耗时:{end-start:.2f}s)os.environ[ASCEND_OVERLAP_DISABLE]0# 开启 overlaptorch.npu.synchronize()starttime.time()for_inrange(50):outputtorch.nn.functional.scaled_dot_product_attention(Q,K,V,is_causalTrue)torch.npu.synchronize()endtime.time()print(foverlap 开启后 50 次耗时:{end-start:.2f}s)print(如果 overlap 开启后更快说明 Runtime overlap 生效了 ✅)预期输出 第五步验证 Runtime 调度 Profiler trace 已保存到 step5_runtime_overlap.json 请打开这个文件看计算 kernel 和数据搬运 kernel 的时间轴 - 如果计算 kernel 和数据搬运 kernel 有重叠说明 Runtime overlap 生效了 ✅ - 如果计算 kernel 和数据搬运 kernel 完全串行说明 Runtime overlap 未生效 ❌ NPU 利用率已保存到 step5_npu_util.txt overlap 关闭后 50 次耗时: 2.34s overlap 开启后 50 次耗时: 1.56s 如果 overlap 开启后更快说明 Runtime overlap 生效了 ✅如果 overlap 开启后没有明显加速检查 Runtime 的配置。相关仓库https://atomgit.com/cann/ops-transformerhttps://atomgit.com/cann/gehttps://atomgit.com/cann/cann-learning-hub