Pull Request已成功合入, 合并人@ascend-robot
(感谢 huyuchao 的贡献)变更摘要
本 PR 针对 torch_npu/_inductor/triton_experimental/ 后端的两类问题进行修复与优化:一是为 softmax 族算子新增 aclnn 回退路由(lowering.py::_register_softmax_aclnn_fallback),解决 Ascend 上带掩码 softmax 融合物化 [B,H,S,S] 掩码、loss 路径 log_softmax 拖带 gather 拆解、宽行 softmax 退化为单核串行扫描三类性能劣化;二是修复 npu_expand 在 accuracy 流程中的无限自递归(RecursionError)。改动仅涉及 Python 层 lowering.py / config.py / __init__.py,无 C++ 改动,新增 3 个可独立开关的内部调优配置项。
主要改动
-
softmax 三级路由(
lowering.py::_register_softmax_aclnn_fallback):将掩码复合算子aten._safe_softmax分解为aten._softmax(跳过 eager 复合实现的冗余-inf守卫链,交行宽路由接管);log_softmax族整体回退 aclnn(make_fallback移除其 lowering/decomposition 注册);纯aten._softmax按归约行宽路由,宽度超过softmax_aclnn_max_fuse_numel(默认 256)时回退aclnnSoftmax,否则保留 Triton 融合;行宽通过 sympy 静态求值并带size_hint兜底,异常时保守走 Triton。 -
npu_expand递归修复(lowering.py):将模块首次执行时的上游expand句柄暂存到永不被重载的上游模块属性_npu_upstream_expand_saved,_orig_expand恒取暂存值,避免模块二次执行时 from-import 绑定到已 patch 的npu_expand导致自递归;并为 tail-bcast 物化分支(Pointwise.create+realize)增加 threadlocal 重入哨兵_expand_reentry,重入时直接返回上游结果以终止循环。 -
新增配置开关(
config.py):新增safe_softmax_aclnn_fallback、log_softmax_aclnn_fallback(默认 True)与softmax_aclnn_max_fuse_numel(默认 256,0 = 关闭路由恒走 Triton),均可独立关闭用于 A/B 回归验证。 -
注册挂载(
__init__.py::_activate):在_activate()中与既有_register_npu_inductor_fallbacks()一并调用新注册函数_register_softmax_aclnn_fallback(),使 softmax 路由在 TE 后端激活时生效。


| 阶段 | 任务名 | 状态 | 详情 |
|---|---|---|---|
| 编译构建 | Build_X86 | ✅ | >>> |
| Build_ARM | ✅ | >>> | |
| Build_X86_torchair | 🛑 | >>> | |
| Build_ARM_torchair | 🛑 | >>> | |
| patch_test | 🛑 | >>> | |
| Build_X86_213 | ✅ | >>> | |
| Build_ARM_213 | ✅ | >>> | |
| 恶意代码检查 | Antipoison | ✅ | >>> |
| 编码安全与规范检查 | codecheck_pre-commit | ✅ | >>> |
| check_error | ✅ | >>> | |
| lintrunner | ✅ | >>> | |
| 开源片段检查 | SCA | ✅ | >>> |
| 开发者测试 | UT_ARM_A3_Part_01 | 🛑 | >>> |
| UT_ARM_A3_Part_02 | 🛑 | >>> | |
| UT_ARM_A2_Part_01 | ✅ | >>> | |
| UT_ARM_A2_Part_02 | ✅ | >>> | |
| UT_ARM_A2_Part_03 | ✅ | >>> | |
| UT_inductor_Part_01 | 🛑 | >>> | |
| UT_inductor_Part_02 | 🛑 | >>> | |
| UT_inductor_Part_03 | 🛑 | >>> | |
| UT_inductor_Part_04 | 🛑 | >>> | |
| UT_DIST_ARM_Part_01 | 🛑 | >>> | |
| UT_DIST_ARM_Part_02 | 🛑 | >>> | |
| UT_DIST_ARM_Part_03 | 🛑 | >>> | |
| UT_DIST_ARM_Part_04 | 🛑 | >>> | |
| UT_ARM_A2_Select_Part_01 | ✅ | >>> | |
| UT_ARM_A2_Select_Part_02 | ✅ | >>> | |
| UT_ARM_A2_Part_213 | ✅ | >>> | |
| UT_inductor_Part_213 | 🛑 | >>> | |
| UT_DIST_ARM_Part_213 | 🛑 | >>> | |
| UT_ARM_A2_Select_Part_213 | ✅ | >>> | |
| 流水线 | PR-pipeline_pytorch | ✅ | >>> |
- compile、compile_inductor、compile_torchair : 运行流水线
- retry : 重试流水线所有失败子任务
- retry <任务名> : 仅重试指定失败子任务
- stop : 停止流水线


Pull Request 已合并或已关闭。
If you want to solve this problem, you can click here to do it in the FAQs.




关联 issue: #4384
【合入来源】
triton_experimental 后端两类问题:①softmax 族 Triton 融合在 Ascend 上性能劣化(带掩码注意力 softmax 融合物化 [B,H,S,S] 掩码矩阵、损失路径 log_softmax 拖带 gather 拆解、宽行 softmax
退化为单核串行扫描);②
npu_expand降低链在 accuracy 流程无限递归(RecursionError)。【修改方案】
涉及组件:
torch_npu/_inductor/triton_experimental/(Python 层,lowering.py/config.py/__init__.py),与 Inductor 降低注册表(torch._inductor.lowering的 lowerings/decompositions 表)交互,无 C++改动。
1. softmax 三级路由(
lowering.py::_register_softmax_aclnn_fallback,_activate挂载)上游 softmax 分解为三段式
amax→exp→÷sum(两次归约真依赖),调度上 ≤1024 行宽走持久归约(行驻留、可邻域融合),更宽行本应走split_reductions跨核拆分,但 TE 已显式关闭 split(历史 OOB 规避)→宽行退化为每行单 program 串行扫描。msprof(910B2)实测宽行(30k/50k)Triton softmax 比 aclnnSoftmax 慢 2.5–2.8x。据此分三类路由:
aten._safe_softmax(掩码复合):分解为aten._softmax。两种旧路径均劣化——Triton 融合会把掩码物化进 kernel(TrOCR 实测 10.3 ms/iter 额外设备时间);直接 fallback 则 eager 复合实现运行冗余-inf守卫链
IsNegInf→SWhere→All(4.6 ms/iter,输入已被 masked_fill 预掩码)。分解后交行宽路由接管。log_softmax族:整体 aclnn 回退(损失路径 Triton log_softmax 慢于 aclnnLogSoftmax,且融合拖带Gather_AsStrided拆解 +2.9 ms/iter)。softmax_aclnn_max_fuse_numel=256):行宽 ≤256 保留 Triton 融合(邻域融合正收益,BertForMaskedLM 实证),>256 回退 aclnnSoftmax。行宽取 sympy 静态求值(size_hint兜底,异常时保守走 Triton)。
2.
npu_expand递归修复(RecursionError)模块体先
from torch._inductor.lowering import expand as _orig_expand,随后 monkeypatchlowering.expand = npu_expand。模块二次执行时 from-import 绑定到已 patch 的 npu_expand →_orig_expand自别名 →npu_expand:385无限自递归(accuracy 流程先跑 eager 改变加载时序触发;perf 流程及缓存命中不触发,长期掩盖)。修复双保险:_npu_upstream_expand_saved,_orig_expand恒取暂存;Pointwise.create+realize拖拽惰性输入求值可绕回 broadcast 链)加 threadlocal 重入哨兵,重入即返回上游结果。3. 新增配置开关(
config.py):safe_softmax_aclnn_fallback/log_softmax_aclnn_fallback(默认 True)、softmax_aclnn_max_fuse_numel(默认 256,0 = 关闭路由恒走 Triton),均可独立关闭用于 A/B 回归。【资料变更】
不涉及
【接口变更】
不涉及跨代码仓/客户面接口。仓内
triton_experimental.config新增 3 个内部调优开关(见修改方案 3),仅影响本后端内部降低策略。【功能验证】
测试场景:Ascend 910B2 + torch 2.13 + torch_npu(triton_experimental) + triton-ascend 3.2.2,torchbench/huggingface benchmark runner(
--backend inductor --npu-backend triton --inference --disable-aclgraph),全部在清空缓存后全新编译降低条件下执行(排除缓存命中假阳性)。测试方法:
--performance,30 迭代中位数(eager vs compile);--accuracy(tolerance 1e-4),并确认无 RecursionError;torch_npu.profiler(msprof 集成)逐 kernel 设备时间对账,4.64 ms/iter 残差 100% 定位到-inf守卫链;结果:
回归:resnet18 1.66x / drq 1.23x / yolov3 持平(无 softmax 路径模型不受影响);修改前 accuracy 流程 RecursionError 必现的 4 个 torchbench 模型(resnet18/drq/fastNLP_Bert/yolov3)修复后全部正常完成且 Rec=0。
UT:本 PR 未新增 UT,看护方式为端到端 benchmark + 精度流(上述);后续可在
pytorch/test/_inductor/补 softmax 路由的降级断言用例(区分_safe_softmax分解、log_softmax 回退、宽行路由三分支)。【CheckList】