Pull Request已成功合入, 合并人@CANN-robot
(感谢 zhang_shengjie 的贡献)变更摘要
此 PR 修复了 Reduce Tile 运行时轴重排的机制缺陷:原先通过直接交换 local_buffer_vars 中两个轴指针的方式无法真正影响下游求解遍历顺序,且可能破坏 z1t/z2t 槽位语义。核心改动是将 canonical 轴(承载轴身份、equal_order、约束、公式及 tiling_data 槽位)与 ordered 轴(仅影响求解遍历顺序)隔离,运行时决策生成完整排列并通过新引入的 ordered_local_buffer_vars 和 ordered_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 的映射表),所有求解器(NaiveLocalBufTiling、BinaryLocalBufTilingCore、WorkloadBalance、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_vars和ordered_to_canonical的全量赋值,并拒绝重复索引或不完整排列。


代码审查
基于对全部 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 移除旧的单轴赋值;新增 GetTileSplitOrder、SetRuntimePreferredOrder 逻辑正确,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_vars 和 ordered_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 映射的栈数组;GenRuntimeReorderRules 在 GenInput 之后、solver 构造之前生成运行时重排代码;ResolveLocalBufferVarIndex 和 GetRuntimePreferredIndices 正确解析并校验完整排列 |
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 调用 SetAxesOrder 和 SetVarsRelations |
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() 以提高防御性。
⚠️ 已识别出整体风险,但无法提取行内评论,请参考整体评估。


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
/approveor/lgtm- Commenting
/approveimplies 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. 👍


/approve


描述
一、主要解决的问题
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。AttAxis::order,preferred 只生成完整排列。2.3 求解和输出隔离
tail < cache_line_size / dtype_size且reduce > vector_len_size / dtype_size命中时,改写 ordered 视图及映射,不修改 canonical 数组。solved_axes。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 单元测试
1.2 系统测试
att_st:通过。inductor_topn_test_codegen:通过。inductor_tail_brc_tail_reduce_test_codegen:通过。pgo_add_abs_inductor_test_codegen:通过。核对清单
其他信息
验证方法
git diff --check通过。注意事项
提交记录
4cb7547d修改文件清单
autofuse/att/base/model_info.hautofuse/att/gen_model_info/expr_gen/arg_list_reorder.cppautofuse/att/gen_model_info/expr_gen/arg_list_reorder.hautofuse/att/generator/preprocess/args_manager.cppautofuse/att/generator/preprocess/args_manager.hautofuse/att/generator/solver_pass_gen/axes_reorder_solver/axes_reorder_solver_gen.cppautofuse/att/generator/solver_pass_gen/axes_reorder_solver/axes_reorder_solver_gen.hautofuse/att/generator/solver_pass_gen/solver_pass_manager.cppautofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_data_struct.cppautofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_equal_priority.cppautofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_local_buf.cppautofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_autotuning.cppautofuse/att/generator/solver_pass/axes_reorder_solver_code/axes_reorder_solver_main.cppautofuse/tests/ut/att/testcase/gen_model_info/expr_gen/test_arg_list_reorder.cppautofuse/tests/ut/att/testcase/preprocess/test_args_manager.cppautofuse/tests/ut/att/testcase/solver_pass_gen/axes_reorder_gen/test_axes_reorder_gen.cpp