已合并
【PR】: fix reduce layer norm #1891
czways创建于 9 天前
【PR】: fix reduce layer norm #1891
已合并
Pull Request已成功合入, 合并人@CANN-robot
(感谢 czways 的贡献)9 天前 添加了label:enhancement
atomgit-bot
9 天前 评论:
9 天前 评论:
变更摘要
本 PR 旨在修复 reduce 算子调度用例生成中的切分逻辑(标题 fix reduce layer norm),主要重构了 ReducePartitionCaseGenerator::ReducePartitionMultipleCitations:不再简单收集多输出节点后逐个切分,而是按"引用组"(source/citation/reduce 三元组)组织多输出节点,仅沿数据边查找 reduce,并借助并查集合并共享 reduce 的组、以组内 reduce id 最小的锚点为基准去重切分,避免重复切分与潜在依赖环;同时为 PartitionByNode 增加边替换跟踪日志,并新增对应单元测试。
主要改动
- 重构多引用切分逻辑:
ReducePartitionMultipleCitations由收集multi_output_nodes改为构造Citation结构(source/citation/reduce)组成的citation_groups,按 reduce id、citation id 排序后分组,并只统计GetOutDataNodes().size() > 1且非 Load/Store/Workspace 的节点。 - 并查集合并与锚点去重:引入
parent/find_root并查集,合并共享同一 reduce 的引用组,每组以 reduce id 最小的节点作为group_anchors锚点,仅对非锚点且未被partitioned_edges记录过的边调用PartitionByNode,防止重复切分。 - 改为仅沿数据边查找 reduce:
FindOutputReduce及遍历逻辑由GetOutNodes()改为GetOutDataNodes(),reduce 查找与引用方向均只沿数据边(data edges)进行。 - 切边替换跟踪与日志:
PartitionByNode中新增replaced_edge标记,实际移除 src->dst 边时置位并打印[TEMP_REDUCE]日志,若未找到直接边替换则输出告警日志GELOGW。 - 新增单元测试:
test_reduce_schedule_case_generator.cpp增加TestReduce_Multi_Cita_Multi_Out_NoDependencyCycle,使用AscGraphBuilder构造Sum被Abs/Tanh/Add/Relu多引用的图,验证GeneratorTask返回成功且任务列表非空。


不准确?
atomgit-bot
9 天前 评论:
9 天前 评论:
代码审查
审查结论
变更文件审查确认
- autofuse/optimize/task_generator/reduce_schedule_case_generator.cpp — 已审查。核心变更:重写
ReducePartitionMultipleCitations(citation 收集 + union-find 分组 + anchor 选取 + 切分去重)、FindOutputReduce改为仅沿数据边递归、PartitionByNode增加replaced_edge跟踪与日志。发现 2 个问题(见下)。 - autofuse/tests/ut/optimize/task_generator/test_reduce_schedule_case_generator.cpp — 已审查。新增
TestReduce_Multi_Cita_Multi_Out_NoDependencyCycle,其构建图仅含一个 reduce,ReducePartitionMultipleCitations在入口处即提前返回,新增测试未执行任何被重写的逻辑。发现 1 个问题(见下)。
Findings 统计
| 优先级 | 数量 | 摘要 |
|---|---|---|
| P2 | 1 | 新增测试未覆盖重写后的切分逻辑(测试图仅 1 个 reduce,函数在 IsOnlyHasOneOrLessReduce 处提前返回,407-500 行新代码一行未执行) |
| P3 | 1 | 生产 pass 中遗留约 10 处 [TEMP_REDUCE] 临时 GELOGI/GELOGW 调试日志,线上 INFO/WARN 刷屏 |
| P3 | 1 | 新 anchor 分组语义与旧实现不一致(多源共享 reduce 时切分边集合改变、单引用源节点可能被切、重复调用 PartitionByNode 会向已改写锚点重复附加 store/workspace/load 链),且无测试兜底(低置信度) |
总体风险评估
本 PR 对 ReducePartitionMultipleCitations 的切分算法进行了完整重写,算法内部(union-find 合并、anchor 选取、去重)逻辑自洽,未发现必然崩溃或数据损坏类缺陷;但存在两方面风险:其一,唯一新增测试因图结构只有一个 reduce 而完全未触达新逻辑,重写的复杂分支逻辑处于零回归保护状态;其二,新旧实现切分边集合在跨源共享 reduce 场景下明显不同,属行为变更,在缺少测试与明确语义说明的情况下存在功能回归隐患。此外遗留的临时调试日志应在合并前清理。整体风险中等,建议补齐能真正执行新逻辑的测试用例后再合入。
| 类型 | 数量 |
|---|---|
| 🔴 阻塞 | 0 |
| 🟡 建议 | 1 |
💬 仅评论


不准确?
9 天前 添加了label:stat/needs-squash
此处折叠了54条消息 查看更多
yangyongqiang
7 天前 评论:
7 天前 评论:
/approve


7 天前 添加了label:approved
CANN-robot
7 天前 评论:
7 天前 评论:
The MR can not be merged, because of CodeReview discussion not resolved
If you want to solve this problem, you can click here to do it in the FAQs.


7 天前 解决了最后一个问题
7 天前 合入了pull request
Pull Request
Inductor LayerNorm 双链多引用断图方向不一致导致 SortSubGraphsByDependency 依赖环编译失败
描述
请清晰准确地描述本次 Pull Request 的意图和变更内容。
变更类型
请选择本次引入的变更类型:
关联的Issue
Closes #293
如何测试
描述测试此变更的步骤和前提条件:
1.
2.
核对清单
其他信息
在此添加任何其他关于本次 PR 的说明。
PR #1891 修改说明:fix reduce layer norm
1. 问题现象
Inductor 场景执行 LayerNorm 融合用例
tc_af_inductor_layernorm_backend_0193(输入 shape=(128,6,23),模型为两条 LayerNorm 路径 + 三路输出:sum(layernorm(x.transpose(0,1)))、mean(layernorm(x))、abs(layernorm(x)))时,Autofuse Optimize 阶段在SortSubGraphsByDependency报sorted[4] != total[7],拓扑排序卡死,整体编译以Optimize fail ret 1343225857中断。7 个子图中只排出 4 个,子图 1 与子图 3 互相等待——本 PR 修复该依赖环的根因。
2. 根因分析
2.1 图结构前提
Inductor 将整个模型融合为单张 HintGraph,含两条几乎镜像的 LayerNorm 计算链(A 链 = transpose 后 LN,B 链 = 原始输入 LN),两链之间无直接数据边,但共享同一批输入节点:
broadcast2(÷23 常量)、broadcast8(beta 权重)、broadcast9(gamma 权重)、scalar1(eps)。2.2 断图机制
GenerateGeneralCase依次执行三个断图 pass(ReducePartitionPostFusion → PartitionNorm → ReducePartitionMultipleCitations)。断开一条边的标准产物是 4 个新节点:写侧句柄与读侧句柄是两个不同节点、同一个名字,运行时靠同名配对传递内存。剪哪条边就是在决定"谁供谁"——pre 落在生产侧子图,post 落在消费侧子图,形成一条"生产方必须先执行"的跨子图依赖。
2.3 故障机制:断图方向不一致制造真实依赖环
ReducePartitionMultipleCitations(修复前)对每个多输出共享节点独立决策:"保留第一个遍历到的 consumer 方向,断开其余"。由于各节点 consumer 遍历顺序不同,方向互相矛盾:broadcast2(÷23)broadcast8(beta)broadcast9(gamma)子图依赖图:
原图是无环 DAG;环完全由断图方向不一致制造,且每条依赖边都对应真实 workspace 数据流(非名称匹配假依赖),无法在排序层补救。
2.4 已证伪的备选方案(避免重走弯路)
GetOutNodes()换成GetOutDataNodes()mean_Load)确实拥有多个数据输出,API 切换挡不住,必须按节点类型过滤3. 修复思路与实现
3.1 共享引用链统一 anchor(断图方向全局裁决)
ReducePartitionMultipleCitations(reduce_schedule_case_generator.cpp/.h)重写为两阶段,并拆分为三个职责单一的函数:阶段一:收集 citation(先于任何本 pass 内的断边,避免被自己改写过的图污染)
!IsLoad && !IsStore && !IsOps<Workspace> && GetOutDataNodes().size() > 1——显式排除 synthetic 节点(断图产物 Store/Load/Ws 虽确实有多个数据输出,但不是用户图的真实共享节点);FindOutputReduce仅沿数据边(GetOutNodes()→GetOutDataNodes())递归探测每个输出最终流到的 Reduce,形成 citation 三元组(source, citation, reduce);不处理控制边是正确选择——下游依赖矩阵(HasDataDependency)本身只按数据边推导,方向决策必须与被保护的约束同构;阶段二 a:共享链合并与 anchor 选取
阶段二 b:统一方向断图
citation.reduce == anchor的路径保留原始数据边;其余路径统一调用PartitionByNode断开。所有断边方向一致把非 anchor 侧(sum3 侧)隔离为纯消费侧,依赖图在构造上不可能成环;PartitionByNode(src, dst)只剪断 src→dst 单边(实现含peer == dst_node守卫,不改道 src 其余出边)。修复前的旧实现通过reduce_nodes集合隐式按 (source, reduce) 去重——首个 Reduce 方向保留直连,每个新出现的 Reduce 只切一次;按 (source, citation) 边去重会切掉同一 source 流向同一非 anchor Reduce 的全部 citation 边,切分边集合较旧实现扩大、属行为变更,故对齐旧语义(每个非 anchor Reduce 只切一条 citation 边,其余保持直连,行为保守且不引入额外跨分量依赖)。3.2 与旧实现的行为对比
GetOutNodes().size() > 1(含控制边、含 synthetic 节点)3.3 真实图验证(2026-08-31 bugshot 回归)
修复后
[TEMP_REDUCE]插桩日志(验证时临时添加,PR 已清理)逐条确认:b2→truediv、b9→add3、b8→mul5、rsqrt→broadcast11、add3→sum3、scalar1→add)方向一致断向 sum3 侧——对照修复前b2→truediv1断向 sum2 侧的方向反转,反向依赖对消除;1 ⇄ 3环消失,SortSubGraphsByDependency通过。4. 变更文件清单
autofuse/optimize/task_generator/reduce_schedule_case_generator.cppReducePartitionMultipleCitations重写(拆分三函数);FindOutputReduce数据边化;新增<map>/<numeric>/<set>头autofuse/optimize/task_generator/reduce_schedule_case_generator.hCitation/CitationGroups类型与三个函数声明(均在private:段,无 ABI 影响)autofuse/tests/ut/optimize/task_generator/test_reduce_schedule_case_generator.cpp5. 测试设计
TestReduce_Multi_Cita_Multi_Out_NoDependencyCycleIsOnlyHasOneOrLessReduce早退);断言调度成功 +kCommon模板 + 两组 workspace 断点对恰各一对TestReduce_Multi_Cita_SameReduce_NoDuplicatePartition已执行的验证:
asc_tiling.py)6. 性能影响
FindOutputReduce无 memo,重汇聚宽图存在重复子遍历(可观测但非运行时问题)7. 遗留与后续
GetCacheReuseInfo修复由他人交付后,在真实 bugshot 环境联合重跑:确认asc_tiling.pyhost C++ 编译通过 → 设备端三路输出精度校验通过(E2E 闭环);FindOutputReduce增加节点级 memo(node → 首个可达 reduce)与 visited 保护:重汇聚图上避免重复子遍历,总复杂度降为 O(V+E),同时消除理论上的递归栈溢出风险(阶段一无图改写,memo 安全);PartitionByNode对多输出口 source 会为每个 out_anchor 建 Store/Ws 写链——dst 未连接的端口产生无读者的悬空写链;本 PR 场景 source 均单口未触发。