:图模式下自动裁剪无意义计算的实战指南)
人工智能模型编译Ascend【免费下载链接】torchairTorchAir 支持用户基于PyTorch框架和torch_npu插件在昇腾NPU上使用图模式进行推理。项目地址https://gitcode.com/Ascend/torchair点击查看免费下载图模式Graph Mode编译过程中模型中常残留一些不影响计算结果的空转算子例如对整个张量做完整切片、重复次数全为 1 的 repeat、前后类型一致的 dtype 转换等。TorchAir 通过experimental_config.remove_noop_ops集成了 PyTorch 的冗余算子消除能力在 FX 图优化阶段自动识别并剔除这类冗余节点从而减少不必要的计算与调度开销。本文将围绕该功能的适用算子场景、使用方法、源码实现链路与测试验证展开帮助你在昇腾 NPU 图模式推理场景中正确开启、验证并规避消除失效的边界情况。功能简介TorchAir 的冗余算子消除功能针对图模式Ascend IR / GE 图编译场景设计能够在 FX 图生成后、送入图编译器之前自动识别并消除计算图中不影响程序逻辑或数据计算的冗余操作。这类操作不改变任何数据内容属于典型的空操作保留在图中只会增加算子调度、内存分配与 Kernel 执行的开销。典型冗余操作示例如下无实际意义的张量视图操作例如b tensor_a[:]对整张量做完整切片参数无效的特殊算子例如重复次数为 1 的repeat操作。该功能与 TorchAir 其他图优化策略如 pattern_fusion_pass 图算子融合相互独立、可叠加使用用户可通过开启/关闭组合进行优化对比从而为模型选择最佳编译方案。支持的冗余算子消除场景本功能依赖 PyTorch 2.2.0 或更高版本对应 TorchAir 在 npu_fx_compiler.py 中对torch._inductor.fx_passes.post_grad.remove_noop_ops的按版本导入逻辑不同 PyTorch 版本支持的优化场景可能存在差异。以 PyTorch 2.5.1 为例支持优化的算子包括但不限于下表各算子的详细语义请参见 PyTorch 源码| 算子名 | 冗余操作场景示例 | | -- | -- | | aten.slice | 对整个张量进行完整切片操作如tensor_a[:]。 | | aten.slice_scatter | 对整个张量进行完整切片操作如tensor_a.slice_scatter(tensor_b)。 | | aten.repeat | 张量在所有待重复维度上重复的次数为 1如tensor_a.repeat(1)。 | | aten.constant_pad_nd | 张量在所有待扩充维度上扩充的数量为 0如torch.nn.functional.pad(tensor_a, pad[0, 0, 0, 0], value3.5)。 | | torch.ops.prims.convert_element_type | 张量数据类型转换时转换前后类型一致。 | | torch.ops.prims.device_put | 张量设备类型转换时转换前后一致。 | | aten.ceil、aten.floor、aten.round、aten.trunc | 张量数据类型为整型取整类算子对整型数据无实际效果。 | | aten.pow | 张量指数运算时幂为 1。 | | aten.cat | 张量拼接时参与拼接的张量只有自身如torch.cat([tensor_a])。 | | aten.view.default、aten.view.dtype | — | | aten.copy、aten.alias、aten.clone | — |从仓库测试用例可以印证上述场景在 tests/st/torchair_fx_pattern_st.py 中分别针对x[:]完整切片、x.slice_scatter(y)完整切片写入、x.repeat(1, 1)、func.pad(x, pad[0, 0, 0, 0], value3.5)、torch.ops.prims.convert_element_type(x, torch.float32)、torch.ceil(x)、torch.pow(x, 1)、torch.cat([x], dim0)、x.clone()编写了独立的消除验证用例均断言优化后图中对应算子节点不再存在。同样的场景在 ACL Graph 后端也有对应覆盖见 tests/st/torchair_aclgraph_st.py。不进行冗余消除的场景冗余消除并非无条件执行。当算子的输入/输出 Shape 不一致或优化后在输入/输出之间引入了新的别名关系时不会进行冗余消除操作。这是因为消除这类节点会改变数据流语义Shape 变化或破坏张量别名约束可能导致后续算子行为异常。典型例证是 clone 算子的选择性消除在 tests/st/torchair_fx_pattern_st.py 中当x.clone()的结果被直接作为图输出test_enable_remove_noop_ops_clone_skipped时clone 节点被保留而当 clone 结果参与后续add_就地加等运算test_enable_remove_noop_ops_clone_inplace时clone 节点才被消除。这正是不引入新别名关系约束的实际体现——直接输出的 clone 承载了独立存储语义不可轻易移除。使用方法该功能通过 torchair.get_npu_backend 的compiler_config配置开启配置项位于config.experimental_config下。示例代码如下仅供参考不支持直接拷贝运行import torch_npu import torchair config torchair.CompilerConfig() # 冗余算子消除配置 config.experimental_config.remove_noop_ops True npu_backend torchair.get_npu_backend(compiler_configconfig) opt_model torch.compile(model, backendnpu_backend)表 1参数说明| 参数名 | 说明 | | -- | -- | | remove_noop_ops | 图模式中是否开启冗余算子消除布尔类型。False关闭。True默认值开启。 |参数默认值与解析实现从源码看该参数默认即为开启状态。experimental_config.py 中定义self.remove_noop_ops OptionValue(True, [True, False])OptionValue(True, [True, False])表示默认值为True合法取值集合为{True, False}。当配置非法取值时TorchAir 的配置校验机制会给出提示帮助用户规避拼写或取值错误。此外该配置项会随as_dict()输出进入编译选项字典local_experiment_option[remove_noop_ops] self.remove_noop_ops.value见 experimental_config.py作为图编译选项下发给后端。在 npugraph_ex 后端ACL Graph 图模式中对应的配置入口为torch.compile(model, backendnpugraph_ex, options{remove_noop_ops: True})默认值同样为开启True相关解析见 npugraphex_config.py 与 npugraph_ex/npugraph_ex/npu_fx_compiler.py。底层实现FX 图优化阶段的调用链路冗余算子消除并非在 GE 图侧实现而是在Python 层 FX 图优化阶段提前完成。其核心调用链路位于 npu_fx_compiler.py按版本导入优化函数文件头部尝试from torch._inductor.fx_passes.post_grad import remove_noop_ops若当前 PyTorch 版本低于 2.2.0或环境中缺少该模块则置为None并降级处理try: from torch._inductor.fx_passes.post_grad import remove_noop_ops except ImportError: remove_noop_ops None图优化入口调度在_optimize_fx中当config.experimental_config.remove_noop_ops为 True 时通过observer.apply_gm_pass(_optimize_noop_ops, optimize_noop_ops)注册该 Pass。该机制会在 Pass 执行前后自动记录图状态并与 debug_save 图调试信息保存 等调试能力联动if config.experimental_config.remove_noop_ops: observer.apply_gm_pass(_optimize_noop_ops, optimize_noop_ops)冗余消除执行与版本降级告警_optimize_noop_ops检查导入结果若为None则打印告警日志并跳过避免低版本 PyTorch 直接报错崩溃否则对 FX GraphModule 的graph执行原生消除逻辑if remove_noop_ops is None: logger.warning( Skip removing noop ops; check if your PyTorch version is above 2.2.0 and ensure the module torch._inductor.fx_passes.post_grad.remove_noop_ops exists ) else: remove_noop_ops(graph_module.graph)值得说明的是该 Pass 在_optimize_fx的 Pass 序列中位于自定义 pre-passpost_grad_custom_pre_pass之后、recover_view_inplace_pattern与pattern_fusion_pass之前因此它处理的是已经过用户自定义优化、尚未做视图就地化恢复的 FX 图消除结果会继续参与后续融合与视图优化流程。日志验证确认冗余算子已被消除设置成功后参考 TorchAir Python层日志打印 开启 Debug 日志from torchair import logger; logger.setLevel(logging.DEBUG)即可在日志中看到消除前后的图对比。消除冗余算子后的日志类似如下[DEBUG] TORCHAIR(1675418,python3):2025-10-31 16:13:28.281.364 [npu_fx_compiler.py:297]1675418 After removing noop ops, graph is graph(): %arg0_1 : [num_users0] placeholder[targetarg0_1] %arg1_1 : [num_users1] placeholder[targetarg1_1] %arg2_1 : [num_users1] placeholder[targetarg2_1] %add_3 : [num_users1] call_functiontargettorch.ops.aten.add.Tensor, kwargs {}) return (add_3,)从日志可见原本可能存在的slice等冗余节点已被移除%arg0_1的num_users降为 0成为死输入图中仅保留真正参与计算的aten.add.Tensor节点。若关闭该功能同样的模型图中会保留这些冗余节点二者对比即可量化该优化带来的图规模缩减。典型效果完整切片消除示例以对整个张量进行完整切片为例直观展示优化前后差异。当不开启冗余消除remove_noop_ops False时FX 图中保留aten.slice.Tensor节点graph(): %arg0_1 : [num_users1] placeholder[targetarg0_1] %arg1_1 : [num_users1] placeholder[targetarg1_1] %slice_1 : [num_users1] call_functiontargettorch.ops.aten.slice.Tensor, kwargs {}) %add : [num_users1] call_functiontargettorch.ops.aten.add.Tensor, kwargs {}) return (add,)开启后slice_1节点被消除add直接消费%arg0_1graph(): %arg0_1 : [num_users1] placeholder[targetarg0_1] %arg1_1 : [num_users1] placeholder[targetarg1_1] %add : [num_users1] call_functiontargettorch.ops.aten.add.Tensor, kwargs {}) return (add,)可见冗余aten.slice操作被完全消除图中算子节点数量减少编译产物更精简。测试验证与质量保障TorchAir 仓库为该功能提供了较为完整的自动化测试覆盖可作为功能行为的事实依据tests/st/torchair_fx_pattern_st.pyAscend IR 后端包含test_disable_remove_noop_ops关闭时 slice 节点保留、以及 slice、slice_scatter、repeat、pad、convert_element_type、ceil、pow、cat、clone 等算子开启后的消除断言所有用例均以unittest.skipIf(torch.__version__ 2.2.0, )标记进一步印证依赖 PyTorch 2.2.0的版本约束tests/st/torchair_aclgraph_st.pyACL Graph 后端覆盖x[:]完整切片消除、zeros_like copy_组合下的冗余消除与死代码消除联动、以及关闭开关时冗余节点保留的对照用例tests/st/torchair_debug_log_st.py在开启 Debug 日志、图 dumppbtxt以及自定义 pre/post pass 组合场景下验证功能可正常参与编译流程冒烟测试 tests/smoke/ge_test.py、tests/smoke/aclgraph_test.py 中则以remove_noop_ops False关闭该优化用于隔离验证其他图优化 Pass 的行为从侧面说明该功能默认开启、且可在测试中按需关闭。小结与建议冗余算子消除是 TorchAir 图模式编译流水线中默认开启的一项基础优化对包含大量视图、类型转换、拼接等空转算子的模型收益明显。实际使用建议如下保持默认开启True仅当需要与其他优化策略做对比实验、或排查疑似由优化引发的异常时才显式关闭确认 PyTorch 版本不低于 2.2.0否则功能自动降级跳过并打印 warning 日志结合 Debug 日志或 graph_dump 图转储功能 对比消除前后的 FX 图确认冗余节点确被裁剪注意 Shape 不一致或引入新别名关系的场景不会触发消除属预期行为而非功能异常。赞分享人工智能模型编译Ascend【免费下载链接】torchairTorchAir 支持用户基于PyTorch框架和torch_npu插件在昇腾NPU上使用图模式进行推理。项目地址https://gitcode.com/Ascend/torchair点击查看免费下载相关推荐TorchAir RefData 类型转换详解GE 图模式下消除 Ref 类算子冗余内存拷贝的优化机制TorchAir RefData 类型转换详解GE 图模式下消除 Ref 类算子冗余内存拷贝的优化机制 在昇腾 NPU 的大模型推理场景中KV Cache人工智能模型编译Ascend从 0 到 1 开发 CLI 工具ConfigArgParse 新手入门实例教程从 0 到 1 开发 CLI 工具ConfigArgParse 新手入门实例教程 ConfigArgParse 是 argparse 的替代品它为命令行工具开发工具从新手到专家Ruma开发进阶之路解锁Matrix协议高级功能从新手到专家Ruma开发进阶之路解锁Matrix协议高级功能 Ruma是一套用Rust编写的Matrix协议交互工具集帮助开发者轻松构建Matrix聊天网上一篇洛雪音乐音源完整指南免费解锁全网音乐资源的终极方案下一篇终极指南GoCD数据迁移后功能验证的完整测试计划与实用案例创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考