已合并
fix: 修复动态Shape下Reduce Tile 运行时轴重排的问题 #1537
fix: 修复动态Shape下Reduce Tile 运行时轴重排的问题 #1537
已合并
zhang_shengjie创建于 7月28日
zhang_shengjie成员
7月28日

描述

一、主要解决的问题

1.1 运行时换轴破坏 canonical 槽位语义

原实现通过交换 input.local_buffer_vars 中的指针选择 Reduce Tile 求解顺序。该数组同时被公式、约束、equal_order、PGO 候选和 tiling_data 按固定下标解释;交换 z1t/z2t 后会让轴身份与槽位含义不一致,存在回填错位和精度风险。

1.2 动态选择未完整作用于求解路径

原实现只交换两个变量,不能表达完整轴排列,也没有完整覆盖 WorkloadBalance 和 PGO/topn 的枚举顺序,动态决策无法稳定影响后续全部求解路径。

1.3 equal_order 与变量替换需要隔离

equal_order 依赖 AttAxis::order 的 canonical 分组;缺失、重复或多重 Expr 映射可能造成误分组。运行时 preferred order 中还可能包含常量或非 local-buffer Expr,需要先投影并校验。

二、修改方案

2.1 canonical 和 ordered 双视图

  • local_buffer_vars 保持 canonical 顺序,固定用于轴身份、equal_order、公式、约束、性能计算和 tiling_data 回填。
  • 新增 ordered_local_buffer_vars,仅用于普通 solver、WorkloadBalance 和 PGO/topn 的遍历顺序。
  • 新增 ordered_to_canonical,将 ordered 下标映射回 canonical 下标;两种视图共享同一 TilingVariable,不复制状态。

2.2 生成完整运行时规则

  • RuntimeReorderRule 使用原始 tail/reduce Expr、参数化阈值和完整 preferred_order
  • canonical 与 preferred 分别构建拓扑;只有 canonical 写入 AttAxis::order,preferred 只生成完整排列。
  • equal-order 组内相对顺序保持 canonical;非法、缺失或重复排列不生成运行时重排代码,安全回退 canonical。

2.3 求解和输出隔离

  • 运行时条件 tail < cache_line_size / dtype_sizereduce > vector_len_size / dtype_size 命中时,改写 ordered 视图及映射,不修改 canonical 数组。
  • equal_order 始终在 canonical 轴上识别和联合求解;普通求解按 ordered 遍历,并通过映射访问 canonical solved_axes
  • PGO 按 ordered 枚举和重置变量,候选值按 canonical 下标写回;topn 过滤及最终 tiling_data 均保持 canonical 布局。

三、代码修改流程图

flowchart TD
    A[ArgListReorder 分析 Reduce Tile] ==> B{shape 是否动态且满足生成条件}
    B ==>|否| C[仅保留 canonical 拓扑]
    B ==>|是| D[独立生成 canonical 与 preferred 拓扑]
    D ==> E[canonical 写入 AttAxis order]
    D ==> F[preferred 提取完整 Tile Expr 顺序]
    F ==> G[保持 equal-order 组内 canonical 相对顺序]
    G ==> H{投影后是否为 local-buffer 完整全排列}
    H ==>|否| C
    H ==>|是| I[保存 RuntimeReorderRule]
    C ==> J[Codegen 初始化 canonical ordered 和单位映射]
    I ==> J
    J ==> K{运行时 tail 小且 reduce 大}
    K ==>|否| L[ordered 保持 canonical]
    K ==>|是| M[ordered 切换 preferred 并更新映射]
    L ==> N{求解路径}
    M ==> N
    N ==>|equal-order| O[canonical 分组和联合求解]
    N ==>|普通与 WorkloadBalance| P[ordered 遍历并映射 canonical index]
    N ==>|PGO 与 topn| Q[ordered 枚举并按 canonical 下标保存候选]
    O ==> P
    P ==> R[公式 约束 性能计算读取 canonical]
    Q ==> R
    R ==> S[tiling_data 按 canonical 槽位回填]

四、核心类图

classDiagram
    class RuntimeReorderRule {
        Expr condition_axis
        Expr compare_axis
        uint32 condition_threshold
        uint32 compare_threshold
        ExprVector preferred_order
    }
    class ModelInfo {
        RuntimeReorderRuleVector runtime_reorder_rules
        AttAxisVector arg_list
    }
    class ArgListReorder {
        SortArgList()
        SetRuntimePreferredOrder()
        GetTileSplitOrder()
    }
    class ArgsManager {
        GetAxesOrder()
        GetVarsRelations()
    }
    class SolverPassManager {
        InitSolverGen()
    }
    class AxesReorderSolverGen {
        SetAxesOrder()
        SetVarsRelations()
        GenRuntimeReorderRules()
        GetRuntimePreferredIndices()
    }
    class AxesReorderSolverInput {
        TilingVariablePointer local_buffer_vars
        TilingVariablePointer ordered_local_buffer_vars
        uint32Pointer ordered_to_canonical
    }
    class AxesReorderSolver {
        IdentifyEqualPriorityAxes()
        NaiveLocalBufTiling()
        BinaryLocalBufTilingCore()
        WorkloadBalance()
    }
    class AxesReorderPgoSolver {
        PgoSolverGenerateAllTilingDataInner()
    }
    class TilingVariable {
        size_t order
        int64 value
    }
    ArgListReorder ..> RuntimeReorderRule : 生成完整规则
    ModelInfo o-- RuntimeReorderRule : 保存
    ArgsManager ..> ModelInfo : 读取 canonical 信息
    SolverPassManager ..> ArgsManager : 获取 order 与变量关系
    SolverPassManager ..> AxesReorderSolverGen : 初始化 codegen
    AxesReorderSolverGen ..> RuntimeReorderRule : 解析 preferred order
    AxesReorderSolverGen ..> AxesReorderSolverInput : 生成双视图输入
    AxesReorderSolverInput o-- TilingVariable : 两种视图共享对象
    AxesReorderSolver ..> AxesReorderSolverInput : 普通求解
    AxesReorderPgoSolver ..> AxesReorderSolverInput : PGO 枚举

变更类型

关联的Issue

无。

如何测试

一、测试用例说明

1.1 单元测试

  • 完整 ATT UT:1022/1022 通过。
  • 新增规则生成、完整排列、非法排列回退、替换变量一对一映射、equal_order 隔离、WorkloadBalance ordered 遍历、PGO canonical 回填等覆盖。
  • 独立 review 定向用例:13/13 通过。

1.2 系统测试

  • att_st:通过。
  • inductor_topn_test_codegen:通过。
  • inductor_tail_brc_tail_reduce_test_codegen:通过。
  • pgo_add_abs_inductor_test_codegen:通过。

核对清单

其他信息

验证方法

  • git diff --check 通过。
  • changed-lines clang-format 检查通过,无额外格式化。
  • OAT 对变更源码和测试文件检查通过。
  • 构建产物时间晚于相关源码。
  • 独立代码 review 通过,无 Critical 或 Important。

注意事项

  • 本次不修改对外 API 或 ABI,不新增堆分配及设备侧逻辑。
  • 动态 Reduce 的真实设备侧 E2E 覆盖未包含在本 PR,作为非阻塞后续增强项。

提交记录

Commit 描述 修改文件数
4cb7547d 修复 Reduce Tile 运行时轴重排 16

修改文件清单

文件路径 修改类型 说明
autofuse/att/base/model_info.h 修改 RuntimeReorderRule 改为完整 preferred order
autofuse/att/gen_model_info/expr_gen/arg_list_reorder.cpp 修改 生成并校验 canonical 与 preferred 拓扑
autofuse/att/gen_model_info/expr_gen/arg_list_reorder.h 修改 增加 preferred 顺序辅助接口
autofuse/att/generator/preprocess/args_manager.cpp 修改 生成 canonical axis order 及唯一 fallback
autofuse/att/generator/preprocess/args_manager.h 修改 暴露 GetAxesOrder
autofuse/att/generator/solver_pass_gen/axes_reorder_solver/axes_reorder_solver_gen.cpp 修改 生成双视图、映射和完整运行时选择代码
autofuse/att/generator/solver_pass_gen/axes_reorder_solver/axes_reorder_solver_gen.h 修改 增加 order、变量关系及 preferred 投影接口
autofuse/att/generator/solver_pass_gen/solver_pass_manager.cpp 修改 向 codegen 传递 canonical order 和变量关系
autofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_data_struct.cpp 修改 AxesReorderSolverInput 增加 ordered 视图和映射
autofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_equal_priority.cpp 修改 跳过单轴组并在 canonical 上识别双轴组
autofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_local_buf.cpp 修改 普通 solver 和 WorkloadBalance 使用 ordered 遍历
autofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_autotuning.cpp 修改 PGO ordered 枚举和 canonical 候选回填
autofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_main.cpp 修改 初始化并展示 ordered 视图
autofuse/tests/ut/att/testcase/gen_model_info/expr_gen/test_arg_list_reorder.cpp 修改 补充规则生成和 equal-order 稳定性 UT
autofuse/tests/ut/att/testcase/preprocess/test_args_manager.cpp 修改 补充缺失与歧义 order fallback UT
autofuse/tests/ut/att/testcase/solver_pass_gen/axes_reorder_gen/test_axes_reorder_gen.cpp 修改 补充普通、PGO、WorkloadBalance 代码生成 UT
likedislike
Pull Request已成功合入, 合并人@CANN-robot
(感谢 zhang_shengjie 的贡献)
Zzhang_shengjie成员
7月28日 创建了 pull request,commit ad87b85e
atomgit-bot
atomgit-bot
7月28日 评论:

变更摘要

此 PR 修复了 Reduce Tile 运行时轴重排的机制缺陷:原先通过直接交换 local_buffer_vars 中两个轴指针的方式无法真正影响下游求解遍历顺序,且可能破坏 z1t/z2t 槽位语义。核心改动是将 canonical 轴(承载轴身份、equal_order、约束、公式及 tiling_data 槽位)与 ordered 轴(仅影响求解遍历顺序)隔离,运行时决策生成完整排列并通过新引入的 ordered_local_buffer_varsordered_to_canonical 间接层传递,确保所有求解路径一致使用重排后的顺序而不修改 canonical 数据结构。

主要改动

  • RuntimeReorderRule 结构体重构:移除 preferred_axis / fallback_axis 字段,新增 std::vector<Expr> preferred_order,将原来仅交换两个轴改为传递完整 preferred 排列。

  • 求解器输入新增 ordered 间接层:在 AxesReorderSolverInput 结构体中引入 ordered_local_buffer_vars(指向重排后的变量指针数组)和 ordered_to_canonical(ordered index 到 canonical index 的映射表),所有求解器(NaiveLocalBufTilingBinaryLocalBufTilingCoreWorkloadBalance、PGO 枚举)均改为通过该间接层访问变量。

  • ArgListReorder 新增完整排列构建:新增 GetTileSplitOrder()SetRuntimePreferredOrder() 方法,从拓扑序提取 tile-split 轴顺序,并在 equal_order 组内保持 canonical 相对顺序,最终校验 preferred 排列为 canonical 轴的完整无重复排列后才写入 rule.preferred_order

  • ArgsManager::GetAxesOrder() 新增轴 order 分配:对搜索变量中的每个轴分配 order,对缺失、重复映射(多变量指向同一原始轴)或 ambiguous 的情况使用唯一递增 fallback 值,避免 equal_order 误分组。

  • 运行时重排代码生成改为全排列投影GenRuntimeReorderRule 不再生成交换两个 local_buffer_vars 的代码,而是通过 ResolveLocalBufferVarIndex() 解析 preferred_order 中每个轴对应的 local buffer var 索引,生成对 ordered_local_buffer_varsordered_to_canonical 的全量赋值,并拒绝重复索引或不完整排列。

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

代码审查

基于对全部 16 个变更文件的逐项审查,以下是审查结论:


审查发现汇总

  • P0: 0
  • P1: 0
  • P2: 0
  • P3: 1(GetAxesOrder 中使用 at() 的防御性不足)

各文件审查结果

文件 结论
autofuse/att/base/model_info.h 无问题 — RuntimeReorderRule 结构体将 preferred_axis/fallback_axis 替换为 preferred_order 向量,变更合理
autofuse/att/gen_model_info/expr_gen/arg_list_reorder.cpp 无问题 — TryBuildReduceTileRuntimeReorderRule 移除旧的单轴赋值;新增 GetTileSplitOrderSetRuntimePreferredOrder 逻辑正确,equal_order 组内 canonical 序保持、完整排列校验正确;SortArgList 重建 prefer_reduce_tile graph 并 fallback 到 canonical 序
autofuse/att/gen_model_info/expr_gen/arg_list_reorder.h 无问题 — 新增方法声明与实现一致
autofuse/att/generator/preprocess/args_manager.cpp 1 项 P3(见上)— GetAxesOrder 整体逻辑正确:为缺失/歧义/多重映射轴分配唯一 fallback,避免 equal_order 误分组;at() 替换为 find() 后无其他问题
autofuse/att/generator/preprocess/args_manager.h 无问题 — 新增 GetAxesOrder() 声明
autofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_autotuning.cpp 无问题 — PGO 枚举使用 ordered_local_buffer_vars 遍历、ordered_to_canonical 回写 canonical 位置,逻辑正确
autofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_data_struct.cpp 无问题 — 新增 ordered_local_buffer_varsordered_to_canonical 字段
autofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_equal_priority.cpp 无问题 — IdentifyEqualPriorityAxes 新增跳过 size<2 的分组,修复了旧代码在首个 size=1 分组时提前返回 false 导致遗漏真正等优分组的 bug
autofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_local_buf.cpp 无问题 — 各求解循环使用 ordered_local_buffer_vars + ordered_to_canonical 将 canonical 语义隔离;solved_axes 按 canonical_idx 索引,IdentifyEqualPriorityAxes 仍用 canonical 数组构建分组
autofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_main.cpp 无问题 — WorkloadBalance 使用 ordered_local_buffer_vars
autofuse/att/generator/solver_pass_gen/axes_reorder_solver/axes_reorder_solver_gen.cpp 无问题 — SetTilingVars 生成 identity 映射的栈数组;GenRuntimeReorderRulesGenInput 之后、solver 构造之前生成运行时重排代码;ResolveLocalBufferVarIndexGetRuntimePreferredIndices 正确解析并校验完整排列
autofuse/att/generator/solver_pass_gen/axes_reorder_solver/axes_reorder_solver_gen.h 无问题 — 新增成员 axes_order_vars_relations_ 和方法声明
autofuse/att/generator/solver_pass_gen/solver_pass_manager.cpp 无问题 — InitSolverGen 调用 SetAxesOrderSetVarsRelations
autofuse/tests/ut/att/testcase/gen_model_info/expr_gen/test_arg_list_reorder.cpp 无问题 — 覆盖 runtime reorder rule 和 canonical 序保持
autofuse/tests/ut/att/testcase/preprocess/test_args_manager.cpp 无问题 — 覆盖缺失/歧义/多重映射轴的 fallback 行为
autofuse/tests/ut/att/testcase/solver_pass_gen/axes_reorder_gen/test_axes_reorder_gen.cpp 无问题 — 覆盖完整排列、歧义拒绝、ordered 轴使用、canonical 索引保持等场景

整体风险评估

低风险。此变更的核心设计——将 canonical 轴身份与 ordered 遍历顺序隔离——是正确的修复方案。canonical 数组(local_buffer_vars)始终保持轴身份、约束槽位和 tiling_data 槽位不变,而 ordered_local_buffer_vars + ordered_to_canonical 仅影响求解遍历顺序。所有求解路径(NaiveLocalBufTiling、BinaryLocalBufTilingCore、WorkloadBalance、PGO)均已统一迁移到 ordered 数组。运行时重排生成完整排列并校验完整性,fallback 到 identity 映射。唯一值得注意的改进点是 GetAxesOrder 中的 at() 用法,建议替换为 find() 以提高防御性。

⚠️ 已识别出整体风险,但无法提取行内评论,请参考整体评估。

likedislike
不准确?
CANN-robotCANN-robot成员
7月28日 添加了label:cann-cla/yes
CANN-robot
CANN-robot成员
7月28日 评论:

Thanks for your pull-request.
The full list of commands accepted by me can be found at here
You can get sig-info at here


PR Approval Progress

Congratulations! All modules have met the lgtm and approve requirements.

Module Approval Details

module lgtm status approve status
repo-cann/graph-autofusion zhanj, wangxiaotian995, xchu42, xuyafei (4/2) zhanj (1/1)

💡 Tip:

  • Committer can comment /approve or /lgtm
  • Commenting /approve implies both code review (lgtm) and intent to merge (approve)

CLA Signature Pass

zhang_shengjie, thanks for your pull request. All authors of the commits have signed the CLA. 👍

likedislike
此处折叠了42条消息 查看更多
CANN-robotCANN-robot成员
7月28日 删除了label:ci-pipeline-running
CANN-robotCANN-robot成员
7月28日 添加了label:ci-pipeline-passed
zhanj
zhanj成员
7月28日 评论:

/approve

likedislike
CANN-robotCANN-robot成员
7月28日 添加了label:approved
CANN-robotCANN-robot成员
7月28日 合入了pull request