一、算子性能分析基础1.1 算子执行模型昇腾上每个算子的执行都会经历编译时优化→运行时调度→硬件执行。任何一个环节出问题都会导致性能下降。┌────────────────────────────────────────┐ │ 算子执行流程 │ ├────────────────────────────────────────┤ │ │ │ 编译时 │ │ 算子融合 → 图优化 → 内存规划 → 代码生成 │ │ ↓ │ │ 运行时 │ │ 任务提交 → Stream 调度 → 等待依赖 │ │ ↓ │ │ 硬件执行 │ │ Cube/Vector/Scalar → 同步结果 │ │ │ └────────────────────────────────────────┘1.2 常见瓶颈类型瓶颈类型表现定位方法计算瓶颈算子本身耗时长Profiling 时间线内存瓶颈带宽利用率高、延迟大内存 Profiling调度瓶颈Stream 空闲、等待久Timeline 分析同步瓶颈频繁等待、流水线断流Timeline 分析二、Profiling 定位瓶颈2.1 算子级 Profiling# 8.1 及之前基础 ProfilingexportASCEND_PROFILING_ENABLE1exportASCEND_PROFILING_OPTIONStensor_dump,trace ,output:/workspace/profiling_datapython train.py# 8.2 新增算子级 ProfilingexportASCEND_PROFILING_ENABLE1exportASCEND_PROFILING_OPTIONSop_stats,output:/workspace/op_profiling2.2 Timeline 分析Profiling 报告中的 Timeline 可以直观看出问题# 8.2 新增Timeline 事件标注importascend_profilingasap profilerap.Profiler()profiler.start()# ... 训练代码 ...profiler.stop()# 分析结果reportprofiler.report()foreventinreport.timeline_events:ifevent.duration1.0:# 耗时超过 1ms 的事件print(f{event.name}:{event.duration:.2f}ms)2.3 算子耗时排序# 8.2 新增算子耗时统计importascend_profilingasap profilerap.Profiler()profiler.start()# 运行训练forbatchindataloader:outputmodel(batch)loss.backward()profiler.stop()# 输出算子级别统计statsprofiler.operator_stats()sorted_statssorted(stats.items(),keylambdax:x[1],reverseTrue)print(Top 10 slowest operators:)forname,durationinsorted_stats[:10]:print(f{name}:{duration:.2f}ms)三、算子融合优化3.1 为什么融合能加速每执行一个算子都有固定开销Kernel Launch、数据移动等。融合多个算子可以减少这些开销同时让编译器做更好的优化。融合前融合后Conv2d → BN → ReLU3 次 Kernel LaunchConv_BN_ReLU1 次 Kernel Launch每次独立显存分配一次分配中间结果复用3.2 常见融合模式模式 1Conv BN Act 融合# 融合前三个独立算子classUnfusedModel(nn.Module):defforward(self,x):xself.conv(x)xself.bn(x)xself.relu(x)returnx# 融合后ATC 自动识别并融合# 用户只需确保算子顺序符合融合 patternclassFusedModel(nn.Module):defforward(self,x):# CANN 会自动识别 convbnrelu 并融合xself.conv_bn_relu(x)returnx模式 2MatMul Bias Act 融合# 融合前defunfused_attention(x,weight,bias):xtorch.matmul(x,weight)# MatMulxxbias# Addxtorch.relu(x)# ReLUreturnx# 融合后编译器自动识别# 不需要改代码保持正确顺序即可deffused_attention(x,weight,bias):returntorch.nn.functional.linear(x,weight,bias)# 编译器融合3.3 融合规则与例外算子组合可融合说明Conv2d BN✅训练和推理均可融合MatMul Add Act✅激活函数种类决定是否能融合MatMul Softmax✅编译器识别 patternConv2d Dropout❌Dropout 融合收益低MatMul Reshape❌Reshape 打断融合四、内存优化4.1 内存复用策略昇腾的 Unified Buffer 大小有限需要合理复用# 8.2 新增内存复用配置importascend_npuasnpu# 设置全局内存池npu.set_memory_mode(pool,max_memory_gb16)# 单算子内存优化npu.set_op_memory_reuse(MatMul,enabledTrue)npu.set_op_memory_reuse(Conv2d,enabledTrue)4.2 原地计算In-place# 原地计算可以省显存classInPlaceModel(nn.Module):defforward(self,x):# 原地 ReLU节省一个中间张量xtorch.relu_(x)# _ 表示 in-place# 原地操作列表# torch.relu_(x)# torch.sigmoid_(x)# torch.tanh_(x)returnx4.3 Gradient Checkpointing显存受限时可以用时间换空间# 8.2 新增Gradient Checkpointingfromtorch.utils.checkpointimportcheckpointclassCheckpointedModel(nn.Module):defforward(self,x):# 中间结果不保存反向时重新计算xcheckpoint(self.layer1,x)xcheckpoint(self.layer2,x)xcheckpoint(self.layer3,x)returnx五、数据加载优化5.1 数据预取训练中 GPU/NPU 等待数据是常见的瓶颈# 8.1 及之前单线程加载forbatchindataloader:databatch[image]# 等待加载完成才开始计算# 8.2 新增数据预取fromtorch.utils.dataimportDataLoader dataloaderDataLoader(dataset,batch_size32,num_workers4,# 多线程加载prefetch_factor2,# 预取因子pin_memoryTrue# Pinned memory 加速传输)# 配合 NPU 异步执行forbatchindataloader:datadata.npu(non_blockingTrue)# 异步传输outputmodel(data)5.2 混合精度数据加载# 数据加载时直接用 FP16classNPUDataLoader:def__init__(self,dataloader):self.dataloaderdataloaderdef__iter__(self):forbatchinself.dataloader:# 异步传输到 NPUbatch_npubatch[data].npu(non_blockingTrue)# 转 FP16如果模型用混合精度batch_npubatch_npu.half()yieldbatch_npu六、常见问题与解决问题诊断解决方案某算子耗时异常高Profiling 看 Timeline检查 shape 是否最优显存 OOMnvidia-smi / ProfilingGradient Checkpointing多卡训练慢通信 Profiling优化 HCCL 参数预热后还是慢检查 Core Type指定 Cube/Vector融合未生效检查算子顺序确保符合融合 pattern相关仓库ascend-toolkit- Profiling 工具 https://gitee.com/ascend/ascend-toolkittorch_npu- 数据加载优化 https://gitee.com/ascend/torch_npuASCEND- 算子融合规则 https://gitee.com/ascend/ascend
CANN 算子调优:榨干昇腾硬件性能
一、算子性能分析基础1.1 算子执行模型昇腾上每个算子的执行都会经历编译时优化→运行时调度→硬件执行。任何一个环节出问题都会导致性能下降。┌────────────────────────────────────────┐ │ 算子执行流程 │ ├────────────────────────────────────────┤ │ │ │ 编译时 │ │ 算子融合 → 图优化 → 内存规划 → 代码生成 │ │ ↓ │ │ 运行时 │ │ 任务提交 → Stream 调度 → 等待依赖 │ │ ↓ │ │ 硬件执行 │ │ Cube/Vector/Scalar → 同步结果 │ │ │ └────────────────────────────────────────┘1.2 常见瓶颈类型瓶颈类型表现定位方法计算瓶颈算子本身耗时长Profiling 时间线内存瓶颈带宽利用率高、延迟大内存 Profiling调度瓶颈Stream 空闲、等待久Timeline 分析同步瓶颈频繁等待、流水线断流Timeline 分析二、Profiling 定位瓶颈2.1 算子级 Profiling# 8.1 及之前基础 ProfilingexportASCEND_PROFILING_ENABLE1exportASCEND_PROFILING_OPTIONStensor_dump,trace ,output:/workspace/profiling_datapython train.py# 8.2 新增算子级 ProfilingexportASCEND_PROFILING_ENABLE1exportASCEND_PROFILING_OPTIONSop_stats,output:/workspace/op_profiling2.2 Timeline 分析Profiling 报告中的 Timeline 可以直观看出问题# 8.2 新增Timeline 事件标注importascend_profilingasap profilerap.Profiler()profiler.start()# ... 训练代码 ...profiler.stop()# 分析结果reportprofiler.report()foreventinreport.timeline_events:ifevent.duration1.0:# 耗时超过 1ms 的事件print(f{event.name}:{event.duration:.2f}ms)2.3 算子耗时排序# 8.2 新增算子耗时统计importascend_profilingasap profilerap.Profiler()profiler.start()# 运行训练forbatchindataloader:outputmodel(batch)loss.backward()profiler.stop()# 输出算子级别统计statsprofiler.operator_stats()sorted_statssorted(stats.items(),keylambdax:x[1],reverseTrue)print(Top 10 slowest operators:)forname,durationinsorted_stats[:10]:print(f{name}:{duration:.2f}ms)三、算子融合优化3.1 为什么融合能加速每执行一个算子都有固定开销Kernel Launch、数据移动等。融合多个算子可以减少这些开销同时让编译器做更好的优化。融合前融合后Conv2d → BN → ReLU3 次 Kernel LaunchConv_BN_ReLU1 次 Kernel Launch每次独立显存分配一次分配中间结果复用3.2 常见融合模式模式 1Conv BN Act 融合# 融合前三个独立算子classUnfusedModel(nn.Module):defforward(self,x):xself.conv(x)xself.bn(x)xself.relu(x)returnx# 融合后ATC 自动识别并融合# 用户只需确保算子顺序符合融合 patternclassFusedModel(nn.Module):defforward(self,x):# CANN 会自动识别 convbnrelu 并融合xself.conv_bn_relu(x)returnx模式 2MatMul Bias Act 融合# 融合前defunfused_attention(x,weight,bias):xtorch.matmul(x,weight)# MatMulxxbias# Addxtorch.relu(x)# ReLUreturnx# 融合后编译器自动识别# 不需要改代码保持正确顺序即可deffused_attention(x,weight,bias):returntorch.nn.functional.linear(x,weight,bias)# 编译器融合3.3 融合规则与例外算子组合可融合说明Conv2d BN✅训练和推理均可融合MatMul Add Act✅激活函数种类决定是否能融合MatMul Softmax✅编译器识别 patternConv2d Dropout❌Dropout 融合收益低MatMul Reshape❌Reshape 打断融合四、内存优化4.1 内存复用策略昇腾的 Unified Buffer 大小有限需要合理复用# 8.2 新增内存复用配置importascend_npuasnpu# 设置全局内存池npu.set_memory_mode(pool,max_memory_gb16)# 单算子内存优化npu.set_op_memory_reuse(MatMul,enabledTrue)npu.set_op_memory_reuse(Conv2d,enabledTrue)4.2 原地计算In-place# 原地计算可以省显存classInPlaceModel(nn.Module):defforward(self,x):# 原地 ReLU节省一个中间张量xtorch.relu_(x)# _ 表示 in-place# 原地操作列表# torch.relu_(x)# torch.sigmoid_(x)# torch.tanh_(x)returnx4.3 Gradient Checkpointing显存受限时可以用时间换空间# 8.2 新增Gradient Checkpointingfromtorch.utils.checkpointimportcheckpointclassCheckpointedModel(nn.Module):defforward(self,x):# 中间结果不保存反向时重新计算xcheckpoint(self.layer1,x)xcheckpoint(self.layer2,x)xcheckpoint(self.layer3,x)returnx五、数据加载优化5.1 数据预取训练中 GPU/NPU 等待数据是常见的瓶颈# 8.1 及之前单线程加载forbatchindataloader:databatch[image]# 等待加载完成才开始计算# 8.2 新增数据预取fromtorch.utils.dataimportDataLoader dataloaderDataLoader(dataset,batch_size32,num_workers4,# 多线程加载prefetch_factor2,# 预取因子pin_memoryTrue# Pinned memory 加速传输)# 配合 NPU 异步执行forbatchindataloader:datadata.npu(non_blockingTrue)# 异步传输outputmodel(data)5.2 混合精度数据加载# 数据加载时直接用 FP16classNPUDataLoader:def__init__(self,dataloader):self.dataloaderdataloaderdef__iter__(self):forbatchinself.dataloader:# 异步传输到 NPUbatch_npubatch[data].npu(non_blockingTrue)# 转 FP16如果模型用混合精度batch_npubatch_npu.half()yieldbatch_npu六、常见问题与解决问题诊断解决方案某算子耗时异常高Profiling 看 Timeline检查 shape 是否最优显存 OOMnvidia-smi / ProfilingGradient Checkpointing多卡训练慢通信 Profiling优化 HCCL 参数预热后还是慢检查 Core Type指定 Cube/Vector融合未生效检查算子顺序确保符合融合 pattern相关仓库ascend-toolkit- Profiling 工具 https://gitee.com/ascend/ascend-toolkittorch_npu- 数据加载优化 https://gitee.com/ascend/torch_npuASCEND- 算子融合规则 https://gitee.com/ascend/ascend