已合并
fix: ensure deterministic codegen and reliable PGO fallback #1662
zhang_shengjie创建于 21 天前
fix: ensure deterministic codegen and reliable PGO fallback #1662
已合并
Pull Request已成功合入, 合并人@CANN-robot
(感谢 zhang_shengjie 的贡献)21 天前 创建了 pull request,commit 3729bb90
atomgit-bot
21 天前 评论:
21 天前 评论:
变更摘要
本次 PR 旨在修复跨进程 codegen 产物不确定的问题。根因在于 VF(Vector Function)分区中的并行节点/边界锚点排序依赖插入顺序或节点 ID,以及临时 Buffer 分配间接受 std::map 裸指针键遍历顺序影响。修改通过引入基于节点名和 anchor index 的稳定排序策略,并为临时 Buffer 记录确定的 allocation_order 字段,使 TensorGroup 排序以生命周期、allocation order 和 group ID 为稳定键,从而确保相同静态图在不同进程中生成一致的源码和缓存 hash。
主要改动
- VF 分区节点排序稳定化: 在
vector_func_partitioner.cpp中,将BuildDependencyAwareRanks和TopologicalSortingForVfGraph中的回退比较从仅比较GetId()改为(GetName(), GetId())对,确保同名节点优先按节点名确定顺序。 - VF 边界锚点排序稳定化: 新增
SortBoundaryAnchors函数,对输入边界 (load_to_peer_in_anchors) 和输出边界 (store_to_peed_in_anchors) 按节点名和 anchor index 排序,并在BuildSubgraph中调用,消除锚点插入顺序对子图构建的影响。 - 临时 Buffer 分配顺序稳定化: 在
TensorInfo和TensorGroup中新增allocation_order字段;在InitNodeTmpBuffInfo中按遍历顺序递增赋值;在MemReuseManager中新增TensorGroupLifeLess比较器(按merged_life_start→allocation_order→group_id排序),并将其应用于AllocForTQue、AllocForCalc以及重构后的AllocTmpBuff/AllocTmpBuffGroup,消除 map 裸指针键遍历顺序对 Buffer ID 分配的影响。 - 新增确定性行为单元测试:
test_vf_partition.cpp新增测试验证不同并行节点插入顺序下 VF 输出消费者顺序和图节点顺序一致;test_buf_que_allocator.cpp新增测试验证临时 Buffer 在地址顺序与生命周期顺序相反时仍按生命周期稳定分配 ID。


atomgit-bot
21 天前 评论:
21 天前 评论:
21 天前 添加了label:cann-cla/yes
CANN-robot
21 天前 评论:
21 天前 评论:
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 | ✅ 张德鹏, xchu42, xuyafei (3/2) | ✅ 张德鹏 (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. 👍


此处折叠了80条消息 查看更多
16 天前 添加了label:approved
16 天前 合入了pull request
15 天前 修改了pull request 的描述
15 天前 修改了pull request 的描述
描述
一、主要解决的问题
1.1 跨进程 codegen 产物不确定
相同静态图在独立进程中可能生成不同的源码和缓存 hash,导致 Inductor PGO 无法稳定复用 codegen 结果。根因包括:
1.2 PGO skip 场景未可靠回退
1.3 共享低精度 Cast 被删除导致计算分支舍入语义变化
问题发生在一个 FP32 中间结果显式降精度到 BF16/FP16 后,同时被两个分支消费的场景:
对应用例:P0-NET-01
该问题由 Inductor baseline/PGO 对比验证中的 RMSNorm 组合用例
P0-NET-01暴露。真实 PyTorch 构图如下:def net01(x, residual, weight): add = x + residual add_fp32 = add.to(torch.float32) inv_rms = torch.rsqrt(torch.mean(torch.pow(add_fp32, 2), dim=-1, keepdim=True) + 1e-6) out = weight * (add_fp32 * inv_rms).to(torch.bfloat16) return add, inv_rms, out输入规格:
三个输出具有不同的精度合同:
关键数据依赖为:
add既是直接输出,又是 RMSNorm 计算输入,因此它的 BF16 舍入是可观察语义。eager 计算要求后续 RMSNorm 使用:旧
ImprovePrecision删除共享低精度 Cast 后,Store 分支会重新补 BF16 Cast,但计算分支直接使用升精度后的 Add 结果,等价于:两者在 BF16 舍入边界附近并不等价,会进一步影响
inv_rms和out。修复必须保留add对应的共享 BF16 舍入边界,并只在计算分支将这个已舍入值升回 FP32。原
ImprovePrecision会删除所有浮点类型间 Cast,再根据下游节点补 Cast。对于上述共享节点,旧流程会把降精度 Cast 只补到 Store 分支,计算分支则直接使用未舍入的 FP32 值:这会破坏多输出图的数值语义:低精度输出仍然正确,但后续计算输出不再基于同一个已舍入中间值。该问题不是 PGO 特有问题;PGO 或泛化测试可能暴露它,但根因位于通用
ImprovePrecision图预处理。修复后,满足以下全部条件的 Cast 被识别为共享舍入边界并保留:
后续预处理会在计算分支补回 BF16/FP16 到 FP32 的升精度 Cast,因此计算仍使用已舍入值:
单 Store、单计算分支、低精度升 FP32 以及其他数据类型的 Cast 删除行为保持不变。
二、问题解决前后对比
flowchart LR subgraph Before[解决前] B1[VF 顺序受 ID 和插入顺序影响] --> B2[边界顺序不稳定] B2 -->|影响| B3[Buffer ID 受指针地址影响] B3 -->|导致| B4[源码和缓存 hash 波动] B5[PGO skip 返回 0] --> B6[误判调优成功] B7[测试缺少直接 include] --> B8[optimize_ut 编译失败] end subgraph After[解决后] A1[节点名和控制依赖稳定拓扑] --> A2[稳定边界锚点] A2 -->|保证| A3[稳定生命期分配] A3 -->|实现| A4[源码和缓存 hash 一致] A5[PGO skip 返回 1] --> A6[回退原始解] A7[显式 include] --> A8[optimize_ut 编译通过] end B4 -.修复.-> A4 B6 -.修复.-> A6 B8 -.修复.-> A8三、修改方案
3.1 VF 排序稳定化
3.2 Buffer 分配稳定化
3.3 PGO 回退可靠化
3.4 保留共享低精度舍入边界
ShouldDeleteCastNode增加消费者信息,只对 FP32→BF16/FP16 且同时连接 Store 和计算分支的 Cast 禁止删除。ProcessOtherComputeNodes在低精度 Cast 到计算节点之间补回升精度 Cast,使后续计算继续以 FP32 执行,但输入值与原图一致。enable_autofuse_pgo,对经过ImprovePrecisionForAscGraph的通用 Autofuse 图生效。3.5 Review 阻塞项修复
变更类型
关联的 Issue
无。
如何测试
一、本地验证
定向回归覆盖:
二、远端 compile
三、系统与上板验证
核对清单
其他信息
兼容性与影响
提交记录
修改文件清单