已合并
【fix】: PowScalar性能问题优化 #1795
【fix】: PowScalar性能问题优化 #1795
已合并
liyuewei创建于 7 天前
liyuewei
liyuewei成员
7 天前

Pull Request

描述

PowScalar性能问题优化。

变更类型

请选择本次引入的变更类型:

关联的Issue

如何测试

描述测试此变更的步骤和前提条件:
NA

核对清单

其他信息

在此添加任何其他关于本次 PR 的说明。

likedislike
Pull Request已成功合入, 合并人@CANN-robot
(感谢 liyuewei 的贡献)
liyueweiliyuewei成员
7 天前 添加了label:enhancement
liyueweiliyuewei成员
7 天前 创建了 pull request,commit feddb700
atomgit-bot
atomgit-bot
7 天前 评论:

变更摘要

本 PR 主要针对 PowScalar 的幂运算性能问题进行优化。核心思路是在 Pow 接口的 float/bfloat16_t 分支中,当指数为 uint32 范围内的整数时,改用基于平方求幂(快速幂)的快速路径(先 Duplicate 结果并循环 Mul),替代原先直接调用通用 Power 的实现;同时在 autofuse/ascendc/api/utils.h 中新增位运算工具函数 IsIntegerWithinUint32Magnitude 用于判断浮点值是否为 uint32 量级内的精确整数,并补充了对应单元测试。

主要改动

  • 新增整数判断工具函数:在 autofuse/ascendc/api/utils.h 中新增 IsIntegerWithinUint32Magnitude,通过解析浮点的指数位与尾数位(kExponentMask/kFractionMask 等掩码)判断值是否为 uint32 量级内的整数,并显式排除 NaN、Infinity 及超范围值。
  • Pow 快速路径优化:在 autofuse/v35/ascendc/api_regbase/pow.hPow 函数中,对 float/bfloat16_t 类型先判断 IsIntegerWithinUint32Magnitude(src2),若成立则取指数绝对值并转 uint32_t,用平方求幂循环(按位右移 + 条件 Mul)计算,否则回退到原 Power 调用,从而降低标量幂运算开销。
  • 补充单元测试:在 autofuse/tests/ut/ascendc/api/test_utils.cpp 中新增两个测试用例,覆盖零值、正负整数、边界值(如 4294967040.0f)以及 NaN、Infinity 等非整数/非法输入场景。
likedislike
atomgit-bot
atomgit-bot
7 天前 评论:

代码审查

审查总结

已逐一审查全部 3 个变更文件:

1. autofuse/ascendc/api/utils.h
新增的 IsIntegerWithinUint32Magnitude 逐位分解逻辑经校验正确(NaN/Inf 拦截、2^32 边界(exponent≥159)、次正规数、(1U << (23-integer_bits)) 移位范围 [1,22] 无未定义行为、≥2^23 直接判整)。本文件无问题。

2. autofuse/tests/ut/ascendc/api/test_utils.cpp
新增用例调用了全仓库均未定义的 IsInteger(diff 实际新增的函数名是 IsIntegerWithinUint32Magnitude)→ 测试目标编译失败,P0

3. autofuse/v35/ascendc/api_regbase/pow.h
新增的整数指数快速幂分支存在两个独立缺陷:负整数指数计算出 x^|n| 而非 1/x^|n|is_negative 计算后从未使用,P1);Mul(src1, src1, src1) 原地改写 const 输入张量并多做一次无用平方,破坏只读契约与 dst==src1 原地场景(P2)。此外该高风险路径缺少关键测试(P2)。

发现统计: P0 × 1,P1 × 1,P2 × 2,共 4 项。

整体风险判断: 本次 PR 的优化思路(整数指数走快速幂)本身可行,但当前实现存在构建失败(测试引用未定义符号)与静默数值错误(负指数)两类阻断性问题,且输入张量被原地改写属于行为回归,建议修复后再合入。

类型 数量
🔴 阻塞 3
🟡 建议 1

⛔ 需要修改

likedislike
CANN-robot
CANN-robot成员
7 天前 评论:

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.
You can self-configure the PR merge rules for this repository. For more details, please refer to Here.
For more, you also can visit HICANN.


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 /approve or /lgtm
  • Commenting /approve implies both code review (lgtm) and intent to merge (approve)

CLA Signature Pass

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

likedislike
CANN-robotCANN-robot成员
7 天前 将niuyuhu,yangyongqiang0606,xchu42,zhang_shengjie,depeng1994,wqtshg_wt,peiyang,shengnan666,XuebinYang,sjtulxh,zhanj,zhujingjing,xuyafei,wangxiaotian995设为评审人
CANN-robotCANN-robot成员
7 天前 添加了label:cann-cla/yes
CANN-robotCANN-robot成员
7 天前 将niuyuhu,yangyongqiang0606,xchu42,zhang_shengjie,depeng1994,wqtshg_wt,peiyang,shengnan666,XuebinYang,sjtulxh,zhanj,zhujingjing,xuyafei,wangxiaotian995设为审查人
atomgit-bot
atomgit-bot7 天前进行代码检视1
autofuse/tests/ut/ascendc/api/test_utils.cpp
已过期
@@ -48,2 +48,4 @@
4848}
4949 
50+TEST(TestUtilsApi, IsInteger_ShouldCheckExactFloatValue) {
51+ EXPECT_TRUE(IsInteger(0.0f));
atomgit-bot
atomgit-bot7 天前评论:

🔴 Critical

变更行:test_utils.cpp 新增的 TEST(TestUtilsApi, IsInteger_ShouldCheckExactFloatValue)(50-64 行)与 TEST(TestUtilsApi, IsInteger_ShouldRejectNanAndInfinity)(66-69 行)调用了 IsInteger(...)。

影响/契约:本 diff 只在 autofuse/ascendc/api/utils.h 中新增了 IsIntegerWithinUint32Magnitude(283-316 行);对 autofuse 全目录的检索显示 IsInteger 仅出现在本测试文件中,从未被定义。test_utils.cpp 第 17 行 #include "utils.h" 引入的正是这个 utils.h,其中并不存在 IsInteger。

失败模式:测试编译时报 “IsInteger was not declared in this scope”,UT 目标构建失败(P0 构建/编译错误)。测试的断言语义(0/±2/16777216/±4294967040 为真,0.5/±2.25/±4294967296/NaN/Inf 为假)与 IsIntegerWithinUint32Magnitude 的实现完全吻合,显然是笔误把函数名写错了。

修复:将测试中所有 IsInteger( 调用改为 IsIntegerWithinUint32Magnitude((或在 utils.h 中为 IsInteger 提供别名/包装),保证测试可编译。

建议:将测试中对 IsInteger 的调用统一改为 IsIntegerWithinUint32Magnitude(该函数的语义与测试断言完全一致),或在不改名的情况下于 utils.h 中补充 IsInteger 的定义/别名。

likedislike
atomgit-bot
atomgit-bot7 天前进行代码检视1
autofuse/v35/ascendc/api_regbase/pow.h
@@ -66,0 +70,4 @@
70+ }
71+ src_u32 >>= 1;
72+ Mul(src1, src1, src1, calCount);
73+ }
atomgit-bot
atomgit-bot7 天前评论:

🟠 High Priority

变更行:pow.h 62-73 行新增的整数指数快速幂分支。

影响/契约:第 63 行 const bool is_negative = src2 < 0.0f; 计算了符号,但该变量从未被使用;第 64-73 行直接用 |n|(abs_src2 → src_u32)做平方累乘,循环结果为 x^|n|。

失败模式:当 src2 为负数且幅值在 uint32 范围内(如 -2.0f、-3.0f、-4.0f 等;-1.0f/-0.5f 已被前面的分支拦截)时,IsIntegerWithinUint32Magnitude(-2.0f) 返回 true 进入快速路径,输出 x² 而非数学上正确的 1/x²,与基线 Power(exp2/log2 路径)语义不一致,静默产生错误数值。该问题对 T=float 与 T=bfloat16_t 均存在。

修复:仅对非负整数指数启用快速路径,其余(含所有负指数)回退到 Power<T, false, pow_config>。最小改动:把进入条件改为 IsIntegerWithinUint32Magnitude(src2) && !(src2 < 0.0f),并删除未使用的 is_negative/abs_src2。

建议:快速路径只应处理非负整数指数:将条件改为 if (IsIntegerWithinUint32Magnitude(src2) && !(src2 < 0.0f)),删除 is_negative/abs_src2 两行,直接 uint32_t src_u32 = static_cast<uint32_t>(src2);;负指数统一走 Power 基线路径。

改动建议
73
+ if (IsIntegerWithinUint32Magnitude(src2) && !(src2 < 0.0f)) {
73
- }
74
+ uint32_t src_u32 = static_cast<uint32_t>(src2);
75
+ Duplicate(dst, static_cast<float>(1.0), calCount);
应用建议
likedislike
atomgit-bot
atomgit-bot7 天前进行代码检视1
autofuse/v35/ascendc/api_regbase/pow.h
@@ -66,0 +70,4 @@
70+ }
71+ src_u32 >>= 1;
72+ Mul(src1, src1, src1, calCount);
73+ }
atomgit-bot
atomgit-bot7 天前评论:

🟠 High Priority

changed line → affected behavior/contract → failure mode → suggested fix

本 PR 在 autofuse/v35/ascendc/api_regbase/pow.h 的标量指数 Pow 重载中新增了整数指数的快速路径(第 62-73 行)。第 63 行计算了 is_negative = src2 < 0.0f,第 64-65 行取绝对值 abs_src2 并转为 uint32_t src_u32,随后第 67-73 行循环只用 src_u32 做快速幂累乘,is_negative 变量被算出后从未使用,循环结束后直接 return(第 77 行),没有任何求倒数/回退逻辑。

新增的 IsIntegerWithinUint32Magnitude 明确忽略符号位(utils.h 第 299-302 行注释 "Ignore the sign bit"),因此负整数指数(如 -2.0f、-3.0f,对 bfloat16_t 还包括 -1.0f、-0.5f 因第 35/50 行特殊分支仅覆盖 float/half)会命中该快速路径。例如 Pow(dst, src1, -2.0f, ...) 应得 x^(-2)=1/x²,实际得到 x²;-1.0f 的 bfloat16 场景应得 1/x,实际得到 x。

失败模式:任何调用方传入负整数标量指数时,kernel 静默产出错误数值,无任何告警,属本次变更引入的回归(改动前该分支直接走 Power 通用实现,结果正确)。指数为 0.5/-0.5 等非整数不会命中此路径(IsIntegerWithinUint32Magnitude(±0.5) 返回 false),故该错误仅影响负整数指数,触发条件明确。

建议:在进入快速路径前增加非负判断,负指数回退到 Power 通用路径,例如将第 62 行改为 if (src2 >= 0.0f && IsIntegerWithinUint32Magnitude(src2)),并删除未使用的 is_negative/abs_src2 逻辑(或改为循环后对 dst 求倒数)。

likedislike
atomgit-bot
atomgit-bot7 天前进行代码检视1
autofuse/v35/ascendc/api_regbase/pow.h
@@ -66,0 +70,4 @@
70+ }
71+ src_u32 >>= 1;
72+ Mul(src1, src1, src1, calCount);
73+ }
atomgit-bot
atomgit-bot7 天前评论:

🟡 Medium Priority

变更行:pow.h 62-73 行新增的整数指数快速路径(本次 PR 的核心变更)。

影响/契约:本次改动触及 Pow 的核心计算路径——新增按位快速幂分支(改变计算结果来源)、原地改写输入张量 src1、并对负指数引入了语义变更;但同目录的 test_pow.cpp(UT 中唯一调用该 Pow 重载的用例文件)未做任何修改,新增测试只覆盖了 utils.h 的 IsInteger 函数。

失败模式:上述两个真实缺陷(负整数指数输出 x^|n| 而非 1/x^|n|;src1 被原地平方污染、dst==src1 时结果恒为 1.0)没有任何用例覆盖——只要新增一个 Pow(x, -2.0f) 或 Pow 原地调用用例即可暴露,当前改动即便存在这些回归也能通过 UT。这是高风险路径(复杂分支、数值语义、输入张量副作用)缺少关键测试。

修复:在 test_pow.cpp 中为 float/bfloat16 补充快速路径用例,至少覆盖:(1) 正整数指数(如 4、5、大指数)与数学期望/基线 Power 对比;(2) 负整数指数(如 -2、-3)验证 1/x^|n|;(3) 调用后复用 src1 以及 dst==src1 别名场景,防止输入张量被污染。

建议:在 test_pow.cpp 中补充对新增快速路径的用例:正/负整数指数结果验证、调用后 src1 复用与 dst==src1 别名场景,覆盖负数指数与输入污染这两类回归。

likedislike
liyueweiliyuewei成员
5 天前 update merge request[project id: 8005834, iid: 1795, commit_id: 8cd979e545e739a424d740dbe6634674391cea73] virtual merging success
此处折叠了8条事件消息 查看更多
CANN-robotCANN-robot成员
4 天前 添加了label:cann-cla/yes
liyuewei
liyuewei成员
4 天前 评论:

compile

likedislike
liyueweiliyuewei成员
4 天前 update merge request[project id: 8005834, iid: 1795, commit_id: 7301a9035ee1b5460913576c83abd2958c826dc2] virtual merging success
CANN-robotCANN-robot成员
4 天前 添加了label:ci-pipeline-running
CANN-robot
CANN-robot成员
4 天前 评论:

流水线任务触发成功
任务链接 [7561884c8e594cb3b92c667a6b11874b][流水线指导]

任务名称状态日志下载链接
UT_Test_Python_superkernel ✅ SUCCESS >>>>>
ST_Test_Python_superkernel ✅ SUCCESS >>>>>
UT_Test_superkernel ✅ SUCCESS >>>>>
UT_Test_autofuse_framework ✅ SUCCESS >>>>>
ST_Test_autofuse_framework ✅ SUCCESS >>>>>
UT_Test_autofuse_ascendc_api ✅ SUCCESS >>>>>
ST_Test_autofuse_ascendc_api ✅ SUCCESS >>>>>
ST_Test_autofuse_e2e ✅ SUCCESS >>>>>
pre_comment ✅ SUCCESS >>>>>
UT_Test_Report ✅ SUCCESS >>>>>
ST_Test_Report ✅ SUCCESS >>>>>

[2026-08-24 18:43:44]    CI执行结束

likedislike
CANN-robot
CANN-robot成员
4 天前 评论:

流水线任务触发成功
任务链接 [b7e2051cc70c4465a0c766eda7d42d98][流水线指导]

任务名称状态日志下载链接
codecheck ❌ FAILED >>>>>
SCA ✅ SUCCESS >>>>>
antipoison ✅ SUCCESS >>>>>
codecheck_checkpr ✅ SUCCESS
pre_comment ✅ SUCCESS >>>>>
codecheck_codestyle ⚠️ WARNING >>>>>
codecheck_precommit ✅ SUCCESS >>>>>
likedislike
CANN-robot
CANN-robot成员
4 天前 评论:

流水线任务触发成功
任务链接 [922ec7a87614449986450406d4a350ce][流水线指导]

任务名称状态日志下载链接
Compile_Ascend_X86 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM ✅ SUCCESS >>>>> >>>>>
pre_comment ✅ SUCCESS >>>>>
PreSmoke_A900_npupool ✅ SUCCESS >>>>>

[2026-08-24 18:15:30]    CI执行结束

likedislike
CANN-robotCANN-robot成员
4 天前 删除了label:ci-pipeline-running
CANN-robotCANN-robot成员
4 天前 添加了label:ci-pipeline-failed
CANN-robotCANN-robot成员
4 天前 删除了label:ci-pipeline-failed
CANN-robotCANN-robot成员
4 天前 添加了label:ci-pipeline-running
CANN-robot
CANN-robot成员
4 天前 评论:

流水线任务触发成功
任务链接 [6701b83f438c4fb29a4ee5ba145497c5][流水线指导]

任务名称状态日志下载链接
codecheck ✅ SUCCESS >>>>>
SCA ✅ SUCCESS >>>>>
antipoison ✅ SUCCESS >>>>>
codecheck_checkpr ✅ SUCCESS
pre_comment ✅ SUCCESS >>>>>
codecheck_codestyle ⚠️ WARNING >>>>>
codecheck_precommit ✅ SUCCESS >>>>>

[2026-08-24 19:23:06]    CI执行结束

likedislike
CANN-robotCANN-robot成员
4 天前 删除了label:ci-pipeline-running
CANN-robotCANN-robot成员
4 天前 添加了label:ci-pipeline-passed
xchu42
xchu42成员
4 天前 评论:

/lgtm

likedislike
xuyafei成员
4 天前 评论:

/lgtm

likedislike
CANN-robotCANN-robot成员
4 天前 添加了label:lgtm
张德鹏成员
4 天前 解决了最后一个问题
张德鹏成员
4 天前 评论:

/approve

likedislike
CANN-robotCANN-robot成员
4 天前 添加了label:approved
CANN-robotCANN-robot成员
4 天前 合入了pull request