已合并
[sync]Symbolic dynamic-shape grouping for reductions #43088
zzll创建于 7月28日
[sync]Symbolic dynamic-shape grouping for reductions #43088
已合并
zzll创建于 7月28日
zzll
7月28日

#3428

【合入来源】

如有社区issue,请关联issue链接
请勿携带内部流程信息(需求链接、问题单、内部issue等)

【修改方案】

请描述修改内容的具体实现,涉及哪些组件之间进行交互,可以用1、2、3、...进行罗列
如果是需求或者重构类的PR,需要补充详细设计文档(说明上下游组件关系、时序图、类图、DFX能力等内容)
需求说明
ascend_custom_passes 模块目前注册了约 20 个图优化 pass(PRE 阶段作用于 dynamo 图、POST 阶段作用于 aten 化后的图),覆盖恒等消除(fold_expand/fold_slice/fold_reduce…)、结构改写(cat_to_view_pass/bool_cast_mul_to_where_pass…)、数值降级(dtype_optimal_pass/fold_iota_arithmetic_pass)和大型融合(batch_embedding_fusion_pass)。这些 pass 的匹配条件全部建立在"shape 是具体整数"这一前提上。当用户通过 torch._dynamo.mark_dynamic 或自动动态化触发动态 shape 编译后,张量维度变为 SymInt(如 s0、2*s0+1),该前提不再成立,优化整体退化为 no-op,动态 shape 图的执行性能显著劣于同一模型的静态 shape 图。
验证结果:
运行代码仓中测试用例:test/_inductor/test_dynamic_shape_fx_passes.py

【资料变更】

请确认是否涉及资料变更。如涉及,需要在PR中体现,并简要说明修改内容。如不涉及,需填写“不涉及”

【接口变更】

请确认是否涉及跨代码仓或者客户面可见的接口变更。如涉及,需要详细说明接口以及对应的变更内容,同时需要在资料中体现。如不涉及,需填写“不涉及”

【功能验证】

说明测试场景,测试方法。如果本次测试方式与常规单元测试不同,请详细说明您的测试步骤
新增/变更内容是否已新增/适配UT测试用例看护,并补充测试自验证截图

【CheckList】

PR提交人对以下CheckList自检项进行全量自检,自检通过或不涉及,均修改 [ ] 为 [x]

likedislike
Pull Request已成功合入, 合并人@ascend-robot
(感谢 zzll 的贡献)
Zzzll
7月28日 创建了 pull request,commit 366aa7ee
atomgit-bot
atomgit-bot
7月28日 评论:

变更摘要

此 PR 为 Ascend NPU Inductor 后端的图优化通道引入了符号化动态形状(symbolic dynamic-shape)支持,主要面向 reduction 操作。核心思路是新增 symbolic_shape_util 模块,提供无 guard 的三值逻辑(可证明为真/假/不确定),使原先仅在静态整数维度上触发的 fold/slice/expand/cat-to-view 等图优化,在动态符号维度上也能安全地触发(仅当可证明时)。同时在 codegen 层面为动态 reduction 增加了安全检查和分桶分组自调优(group autotune)能力,避免在 SIMT 模板上对 argmax/argmin/Welford 等不安全 reduction 类型错误计算。

主要改动

  • 新增 symbolic_shape_util.py 符号形状工具模块:提供 statically_known_eq、is_statically_one、shapes_statically_equal、resolve_size_arg、materialize_shape、statically_fits_int32 等三值逻辑原语,以及 refresh_fake_meta、dynamic_fx_pass_enabled 全局开关等辅助函数,为图优化 pass 提供无 guard 的符号推理基础。

  • 图优化 pass 全面符号化适配:ascend_graph_pass.py 中 fold_expand、fold_reduce、fold_slice、cat_to_view_pass、repeat_to_expand_pass、fold_iota_arithmetic_pass、batch_embedding_fusion_pass 等多个 pass 从原本仅处理静态 int 维度改为调用符号化三值比较,在动态形状可证明时触发优化;get_node_shape 新增 allow_symbolic=True 选项以返回含 SymInt 的形状。

  • 动态 reduction codegen 安全策略:ir.py(codegen)新增 _SIMT_TEMPLATE_UNSAFE_REDUCTION_TYPES 集合与 is_linear_dynamic_reduction 函数,检测 ModularIndexing/FloorDiv 中的符号界和 argmax/argmin/Welford 等不安全 reduction 类型,强制回退到社区 SIMT_ONLY 路径;ir.py(主)的 num_splits 对仅含单个动态 reduction 轴的情况保持 split==1,配合 tail mask 循环运行时 numel。

  • 动态 reduction 分桶分组自调优:split_tiling.py 新增 _dynamic_reduction_tiling_axis 与分桶边界(_REDUCTION_BUCKETS、_OUTER_BUCKETS),对含动态轴的 reduction 按运行时大小进行分组自调优;同时防止全 reduction 动态轴被错误设为 grid split axis(避免 grid>1 导致标量输出被覆盖);triton_heuristics.py 的 build_grouped_launch_policy 支持 reduction tiling 轴作为 primary group axis 时无 grid block 的场景。

  • 新增动态形状图优化单元测试:test_dynamic_shape_fx_passes.py 提供不依赖 NPU/CUDA 的纯 FX 级别测试,覆盖 symbolic_shape_util 三值检查、形状物化、值域分析以及各 pass 在动态形状下的可证明优化与边界安全(不确定情况不误折叠);test_sum.py 新增 1D 动态 sum 正确性测试(含 group autotune 开关)。

likedislike
不准确?
atomgit-bot
atomgit-bot
7月28日 评论:

代码审查

现在我已经全面审查了所有 9 个文件。让我来完成最终汇总。

审查总结

我逐一审查了以下每个文件:

  1. test/_inductor/test_dynamic_shape_fx_passes.py(新增,+471 行)— 通过。测试套件结构良好,覆盖了三值逻辑、规范化、物化、范围、开关边界、以及每个 pass 在动态 shape 上的行为。"shim" 函数正确地隔离了缺失的 torch 内部组件。

  2. test/_inductor/test_sum.py(+36 行)— 通过。为 sum 操作添加了动态 shape 测试和分组自动调优测试。eval('torch.' + dtype) 使用方式对其硬编码常量列表来说是安全的。

  3. torch_npu/_inductor/codegen/ir.py(+48 行)— 发现 1 个问题。新增函数 is_linear_dynamic_reduction、其辅助函数 _loop_body_has_unsafe_reduction 以及常量 _SIMT_TEMPLATE_UNSAFE_REDUCTION_TYPES(约 40 行)在仓库中没有任何调用者。这是死代码,应该接入调用链或移除。

  4. torch_npu/_inductor/codegen/split_tiling.py(+110/-28 行)— 通过。动态全规约的 grid==1 保护、用于 reduction tiling 轴分桶的 _dynamic_reduction_tiling_axis、以及仅在动态轴存在时才生成特征的条件 _build_group_features,逻辑设计良好且自洽。_build_grouped_meta 中新增的 else 分支正确地处理了无动态 split 轴的情况,并与 triton_heuristics.py 中 build_grouped_launch_policy 的修改后契约对齐。

  5. torch_npu/_inductor/fx_passes/ascend_custom_passes/ascend_graph_pass.py(+189/-136 行)— 通过。所有 pass(fold_expand、fold_reduce、fold_slice、cat_to_view_pass、repeat_to_expand_pass、pad_slice_fold、cat_slice_cat_fold_pass、dtype_optimal_pass、fold_iota_arithmetic_pass、batch_embedding_fusion_pass 等)已正确适配为使用 symbolic_shape_util 中的三值逻辑。静态 shape 路径保持不变,动态 shape 路径在可证明时安全地进行优化。

  6. torch_npu/_inductor/fx_passes/utils/get_binary_fold_result.py(+70/-35 行)— 通过。get_node_shape 的 allow_symbolic 参数是一个向后兼容的添加。_fold_slice、_fold_slice_scatter 和 get_pad_dim_and_size 的修改正确使用了三值比较。新增的 shape is None 防护是一个良好的防御性修正。

  7. torch_npu/_inductor/fx_passes/utils/symbolic_shape_util.py(新增,+435 行)— 通过。设计良好的符号 shape 原语模块,提供无 guard 的三值逻辑、shape 物化、size 参数解析和 fake meta 刷新。全局开关 dynamic_fx_pass_enabled() 提供干净的降级行为。

  8. torch_npu/_inductor/ir.py(+9 行)— 通过。num_splits 的修改正确处理了单动态 reduction 轴的情况(保持 split=1 让运行时循环处理,而非退化分割)。

  9. torch_npu/_inductor/runtime/triton_heuristics.py(+17/-10 行)— 通过。移除的 guard 和修改后的 build_grouped_launch_policy 正确地处理了 reduction tiling 轴缺少 grid block 的情况,与 split_tiling.py 中的新 case 保持一致。

按优先级统计发现问题数:

  • P0:0
  • P1:0
  • P2:1(ir.py 中的死代码)
  • P3:0

整体风险评估:

此次变更是一次中等风险的合入(仅因死代码问题)。核心动态 shape 分组和 pass 适配逻辑是健全的、设计良好的,并通过测试充分覆盖。唯一的缺陷是 ir.py 中的死代码块,应在后续修订中接入或清理。

类型 数量
🔴 阻塞 0
🟡 建议 4

💬 仅评论

likedislike
不准确?
ascend-robotascend-robot成员
7月28日 添加了label:ascend-cla/yes
此处折叠了47条消息 查看更多
ascend-robot
ascend-robot成员
7月29日 评论:
流水线 pytorch_gitcode_PR_multiVersion#13308 [ commitID:7633170c ] 已完成
likedislike
Zzzll
8月6日 修改了pull request 的描述
ascend-robotascend-robot成员
8月6日 删除了label:ci-pipeline-passed
ascend-robot
ascend-robot成员
8月6日 评论:

Pull Request 已合并或已关闭。

If you want to solve this problem, you can click here to do it in the FAQs.

likedislike
Zzzll
8月6日 修改了pull request 的描述