已合并
SeluGrad算子对齐竞品实现,修复int类型结果溢出问题 #8771
yulianjie创建于 22 天前
SeluGrad算子对齐竞品实现,修复int类型结果溢出问题 #8771
已合并
yulianjie创建于 22 天前
yulianjie成员
22 天前

描述

本 PR 修复 Ascend950 arch35 SeluGrad 与指定竞品 TensorFlow tf.raw_ops.SeluGrad 实现不一致的问题。

数学定义统一为:

outputs < 0  : y = gradients * (outputs + 1.7580993408473768...)
outputs >= 0 : y = 1.0507009873554805... * gradients

主要改动:

  • 将负分支判断从 outputs <= 0 调整为 outputs < 0,使零点进入 scale * gradients 分支。
  • FP16/BF16 改为在输入 dtype 上直接计算常量和中间结果,对齐 TensorFlow 的 dtype 原生计算行为。
  • 整数路径按类型调整:int8/uint8 上浮 FP16,int32 上浮 FP32。
  • 整数结果使用 CAST_RINT 直接回铸原 dtype,移除会导致 int32 精度损失的 integer -> FP16 -> FP32 旧中转路径。
  • 简化 Transit Kit 的 Cast 辅助函数和 UB 缓冲分配,并保持连续形状与广播路径共用相同计算语义。
  • 同步更新 arch35 示例程序中的公式、零点分支与期望值。

对标范围说明:本次产品契约明确以 TensorFlow tf.raw_ops.SeluGrad 为真值;outputs == 0 的行为有意与 PyTorch elu_backward(is_result=True)<= 0 语义区分。

关联的Issue

Fixes #4846

https://gitcode.com/cann/ops-nn/issues/4846

测试

  • Ascend950 构建:bash build.sh --pkg --ops=selu_grad --soc=ascend950 --vendor_name=custom_nn -j8
    • 构建成功。
    • 6/6 dtype 对象及 6 个运行时变体生成成功。
  • TTK 版本:3.0.0,revision 40f91a7
  • 竞品 Golden:TensorFlow tf.raw_ops.SeluGrad;整数按上述类型上浮和回铸规则处理。
  • 原确定性整数失败集:18/18 PASS,binary 100%,内存检查 PASS。
  • 全部非资源型整数回归:34/34 PASS。
    • int8:10/10
    • uint8:10/10
    • int32:14/14
  • FP16/BF16 防回归:17/17 PASS。
    • FP16:14/14
    • BF16:3/3
  • 4 条超大资源用例未纳入完整整数回归;其输入张量本身占用 1.365-1.974 GiB,原结果为 Golden 资源失败或 profile crash,不属于确定性精度不一致。

示例更新

  • 更新 activation/selu_grad/examples/arch35/test_aclnn_selu_grad.cpp 中的输出说明与零点判断。

类型标签

AI/Agent生成声明

likedislike
Pull Request已成功合入, 合并人@CANN-robot
(感谢 yulianjie 的贡献)
Yyulianjie成员
22 天前 创建了 pull request,commit 16f8826d
atomgit-bot
atomgit-bot
22 天前 评论:

变更摘要

该 PR 主要对 selu_grad 算子进行「对齐竞品实现」的调整,核心是将负分支的判断边界从 <= 0 改为 < 0,并重构不同 dtype 的计算路径:float/half/bfloat16 改为在原 dtype 上直算,整数类型则按竞品(canndev TBE)的精度策略上浮到 FP16FP32 计算后再回铸,同时简化了原有的中转 Cast 逻辑与缓冲区分配。

主要改动

  • 负分支判断边界调整: SeluGradSelectFp32CompareScalarCMPMODE::LE 改为 CMPMODE::LT,测试用例 test_aclnn_selu_grad.cpp 的判断逻辑也由 out > 0 分支改为 out < 0 分支,使零点归入 SCALE * grad 正分支。
  • 新增原 dtype 直算路径: 新增 SeluGradSelectTfNative<T>SeluGradDirectKit 不再仅支持 float,而是对 float 走原有 SeluGradSelectFp32,对 half/bfloat16 直接使用输入 dtype 计算。
  • 整数中转精度调整: SeluGradTransitKit 引入 ComputeTint32 映射为 floatint8/uint8 映射为 half),将原先「整型 → half → float」两步中转改为单次 Cast 上浮计算后,再以 CAST_RINT 回铸输出。
  • 删除旧的 Cast 辅助函数并简化缓冲: 移除 SeluGradCastInToFp32SeluGradCastFp32ToOut,将 kNeedsHalfTransit 重命名为 kIntegerTransit,并简化 SeluGradTransitKitTBuf 缓冲初始化。
  • dtype 调度规则调整: SeluGradOneDimOpSeluGradBroadcastOp 由「float 走 Direct、其余走 Transit」改为「整数类型走 Transit、float/half/bfloat16 走 Direct」。
likedislike
不准确?
atomgit-bot
atomgit-bot
22 天前 评论:

代码审查

审查总结

审查了全部 2 个变更文件:

  • activation/selu_grad/op_kernel/arch35/selu_grad.h:发现 1 个问题(P2)——SELU 梯度在 outputs == 0 边界处因 CMPMODE::LE → LT 选错分支,与 PyTorch selu_backward 及 ST 参考 torch.where(y > 0, ...) 不一致。
  • activation/selu_grad/examples/arch35/test_aclnn_selu_grad.cpp:发现 1 个问题(P3)——示例测试在 outputs == 0 处断言了与参考不一致的期望值,会掩盖上述边界回归。

按严重度统计:P0 0 个,P1 0 个,P2 1 个,P3 1 个。

总体风险判断:本次改动主体为"对齐竞品实现"的重构(half/bfloat16 原 dtype 直算、int8/uint8 走 FP16、int32 走 FP32),buffer 分配整体收敛、未引入新的 UB 溢出;唯一实质风险是负分支边界从 <= 0 收窄为 < 0,在 outputs == 0(即 x == 0)这一边界点上与声明的 PyTorch 兼容目标及 ST 参考产生约 40% 的相对偏差,建议将边界改回 LE 并同步修正示例测试的期望值。

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

💬 仅评论

likedislike
不准确?
CANN-robotCANN-robot成员
22 天前 添加了label:stat/needs-squash
CANN-robotCANN-robot成员
22 天前 添加了label:cann-cla/yes
此处折叠了106条消息 查看更多
CANN-robotCANN-robot成员
15 天前 删除了label:ci-pipeline-running
CANN-robotCANN-robot成员
15 天前 添加了label:ci-pipeline-passed
CANN-robotCANN-robot成员
15 天前 关闭了关联的issue
CANN-robotCANN-robot成员
15 天前 合入了pull request
CANN-robot
CANN-robot成员
15 天前 评论:

Pull Request 已合并或已关闭。

If you want to solve this problem, you can click here to do it in the FAQs.

likedislike