已合并
[bugfix] Align A5 div scalar TrueDiv reciprocal and FloorDiv compute dtype with PyTorch CUDA #3531
wangqi_ai创建于 6月25日
[bugfix] Align A5 div scalar TrueDiv reciprocal and FloorDiv compute dtype with PyTorch CUDA #3531
已合并
wangqi_ai创建于 6月25日
wangqi_ai成员
6月25日

描述

对齐 A5(Ascend950 / DAV_3510 / RegBase)上 div 标量路径与 PyTorch CUDA 的计算口径,含两处修复:

  1. TrueDiv 标量计算口径与倒数:

    • fp16/bf16 self 经 PromoteLowPrecToFloat 提升到 float 再计算,标量不被提前降精。
      该提升同时覆盖 aclnnDivs 与 aclnnDivMods mode=0(trueDiv 入口)。
    • aclnnDivs 命中 CanUseMuls 倒数乘快路时,原实现 1.0f / other->ToFloat() 先把标量
      舍到 float 再取倒数;CUDA BinaryDivTrueKernel 在 cpu-scalar 分支以 high_prec(double)
      取倒数再单次舍入到 float。改为 static_cast(1.0 / other->ToDouble()),口径一致。
      注: 该倒数乘快路仅存在于 aclnnDivs;aclnnDivMods mode=0 走 RealDiv,无倒数乘。
  2. FloorDiv 计算 dtype(aclnnDivMods / aclnnInplaceDivMods mode=2):
    原实现对 fp16/bf16 self 推导出的 promoteType 仍为 fp16/bf16,使标量除数被
    ConvertToTensor 提前压到低精度;CUDA 在 accscalar_t(half/bf16→float)下计算
    floor div 并以 float 精度读取标量。将 PromoteLowPrecToFloat 的提升从仅
    MODE_REAL_DIV 扩展到同时覆盖 MODE_FLOOR_DIV,使 fp16/bf16 self + 标量在 float 下
    计算、标量保留精度,输出 dtype 不变(末尾 Cast 回 out)。

两处改动均隔离在 RegBase(IsRegBase 门禁)分支内;对整型/bool/complex 为 no-op
(PromoteLowPrecToFloat 幂等);A2/A3 非 RegBase 及 trunc 推导均不受影响。

回合说明

本 PR 为 PR #3342(master 分支已合入)在 9.1.0 分支的 cherry-pick 回合。

关联的Issue

  • #2042
  • 原始 Issue: #2002
  • 原始 PR: #3342

测试

新增 Ascend950 平台 UT(math/div/tests/ut/op_api/test_aclnn_div.cpp):

  • TrueDiv: fp16/bf16/fp32 self + float/double 标量的 aclnnDivs 倒数乘路径,aclnnDivMods
    mode=0 的 RealDiv 路径,及 inplace 委派路径。
  • FloorDiv: fp16/bf16 self + float/double 标量经 aclnnDivMods mode=2 的路径,及 inplace 委派路径。
    opapi UT 全量 43/43 通过。数值逐位对齐由真机精度用例覆盖。

文档更新

类型标签

  • Bug修复
  • 新特性
  • 性能优化
  • 文档更新
  • 其他,请描述:
likedislike
Pull Request已成功合入, 合并人@CANN-robot
(感谢 wangqi_ai 的贡献)
Wwangqi_ai成员
6月25日 创建了 pull request,commit 33e6b285
CANN-robotCANN-robot成员
6月25日 添加了label:cann-cla/yes
CANN-robot
CANN-robot成员
6月25日 评论:

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
math/div 宋恺, wangrui_ (2/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

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

likedislike
Wwangqi_ai成员
6月25日 修改了pull request 的描述
wangqi_ai成员
6月25日 评论:

compile

likedislike
Wwangqi_ai成员
6月25日 update merge request[project id: 7649531, iid: 3531, commit_id: 0715ddf98c9dd0eabab180717d220da4d208d3a0] virtual merging success
CANN-robotCANN-robot成员
6月25日 添加了label:ci-pipeline-running
CANN-robot
CANN-robot成员
6月25日 评论:

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

任务名称状态日志下载链接
Compile_Ascend_X86 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_X86_mobile_station ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_X86_experimental ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM_experimental ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_single ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_X86_A5 ✅ SUCCESS >>>>> >>>>>
Compile_Ascend_ARM_A5 ✅ SUCCESS >>>>> >>>>>
pre_comment ✅ SUCCESS >>>>>
Compile_harmony-infer ✅ SUCCESS >>>>>
Compile_X86_monitor_910b ✅ SUCCESS >>>>> >>>>>
Compile_X86_monitor_910c ✅ SUCCESS >>>>> >>>>>
Compile_X86_monitor_950 ✅ SUCCESS >>>>> >>>>>
Compile_harmony-infer-chs-math ✅ SUCCESS >>>>>
UT_Test ✅ SUCCESS
UT_Test_experimental ✅ SUCCESS
UT_Test_kernel ✅ SUCCESS
PreSmoke_A900 ✅ SUCCESS >>>>>
PreSmoke_ATK_Test_A2 ✅ SUCCESS >>>>>

[2026-06-25 10:13:21]    CI执行结束

likedislike
CANN-robot
CANN-robot成员
6月25日 评论:

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

任务名称状态日志下载链接
codecheck ✅ SUCCESS >>>>>
SCA ✅ SUCCESS >>>>>
antipoison ✅ SUCCESS >>>>>
codecheck_Pr ✅ SUCCESS
StaticCheck_codespell_check ✅ SUCCESS
StaticCheck_link_validity_check ✅ SUCCESS
StaticCheck_resource_existence_check ✅ SUCCESS
StaticCheck_tag_closed_check ✅ SUCCESS
StaticCheck_markdownlint ✅ SUCCESS
codecheck_codestyle ✅ SUCCESS >>>>>
codecheck_precommit ⚠️ WARNING >>>>> >>>>>

[2026-06-25 10:09:28]    CI执行结束

likedislike
atomgit-bot
atomgit-bot
6月25日 评论:

变更摘要

此 PR 修复了 A5 (Ascend950) 平台上 tensor-scalar 除法与 PyTorch CUDA 在 fp16/bf16 输入时的计算行为偏差,涉及 TrueDiv(逐元素真除)标量路径和 FloorDiv(向下取整除)标量路径。对于 TrueDiv 标量路径,fp16/bf16 类型被提升到 float 计算,且倒数在 double 精度域内计算后单次舍入到 float,对齐 CUDA 标量除法精度;对于 FloorDiv,PromoteLowPrecToFloat 的提升逻辑被扩展覆盖 MODE_FLOOR_DIV 模式。两项改动均限定在 IsRegBase(即 Ascend950)分支内。

主要改动

  • 新增 PromoteLowPrecToFloat 工具函数:在 aclnn_div.cpp 中新增内联函数,将 DT_FLOAT16DT_BF16 提升为 DT_FLOAT,其余类型原样返回,注释说明"对齐 CUDA acc_type"。

  • TrueDiv 标量路径(aclnnDivsGetWorkspaceSize:在 IsRegBase 分支内调用 PromoteLowPrecToFloat 将 fp16/bf16 提升到 float 计算,避免标量被提前降精度;同时在 CanUseMuls 为真的快路径中,将倒数计算改为 static_cast<float>(1.0 / other->ToDouble()),即在 double 域计算后再舍入到 float,对齐 CUDA 标量除法精度。

  • FloorDiv 标量路径(aclnnDivModsGetWorkspaceSize:将 PromoteLowPrecToFloat 的调用条件从仅 MODE_REAL_DIV 扩展为 MODE_REAL_DIV || MODE_FLOOR_DIV,使 FloorDiv 在 fp16/bf16 输入时同样在 float 精度下计算,标量不再被提前压到低精度类型。

  • 新增 13 个 Ascend950 专用单元测试用例:覆盖 TrueDiv 标量倒数乘路径(fp32/fp16/bf16 + float/double 标量)、FloorDiv 标量路径(fp16/bf16 + double/float 标量)、以及对应的 inplace 版本(aclnnInplaceDivs / aclnnInplaceDivMods),所有用例显示切换 ASCEND950 平台并校验 GetWorkspaceSize 成功。

likedislike
CANN-robotCANN-robot成员
6月25日 删除了label:ci-pipeline-running
CANN-robotCANN-robot成员
6月25日 添加了label:ci-pipeline-passed
atomgit-bot
atomgit-bot
6月25日 评论:

代码审查

经过全面审查,我发现这个 diff 中没有引入任何实际问题。以下是我的详细分析:

审查结论

文件 1: math/div/op_api/aclnn_div.cpp

变更 1 (第 45-52 行): 新增 PromoteLowPrecToFloat 函数

  • 逻辑正确:仅将 DT_FLOAT16/DT_BF16 提升为 DT_FLOAT,其他类型透传。
  • 被声明为 static inline,无额外编译开销。

变更 2 (第 706-707 行): aclnnDivsGetWorkspaceSize 中调用 PromoteLowPrecToFloat

  • 放置在 IsRegBase(npuArch) 保护块内,仅对 A5 生效。
  • 放置在所有其他 promoteType 调整之后,不会与后续逻辑冲突。
  • 当 self 为 fp16/bf16 时,self->GetDataType() == promoteType 变为 false,会走 cast + Muls 路径——这正是预期行为。

变更 3 (第 725-726 行): 倒数计算提升到 double 精度

  • 旧代码:1.0f / other->ToFloat()(float 精度)
  • 新代码:static_cast<float>(1.0 / other->ToDouble())(double 精度后单次舍入到 float)
  • 与 CUDA 标量除法精度对齐。对于 double 标量输入不会丢失精度。
  • 除零、极小值等边界情况行为与之前一致。

变更 4 (第 949-952 行): aclnnDivModsGetWorkspaceSize 中调用 PromoteLowPrecToFloat

  • 仅对 MODE_REAL_DIVMODE_FLOOR_DIV 生效,MODE_TRUNC_DIV 保持在 InferDivsModeDtype 中原有的 fp16/bf16→float 逻辑。
  • 放置在 CheckDivModComplexDtype 之前,由于只将低精度浮点提升为 float,不会触发 complex 类型检查失败。
  • isMixDataType 分支在 ASCEND950 上不可达(isMixDtypeScalarSupport 仅对 910B/910_93 返回 true),因此 PromoteLowPrecToFloat 仅影响非混合精度分支——正确。

文件 2: math/div/tests/ut/op_api/test_aclnn_div.cpp

  • 新增 11 个测试用例覆盖:a) aclnnDivs(trueDiv 标量)的 fp32/fp16/bf16 + float/double 标量组合;b) aclnnInplaceDivs;c) aclnnDivMods 的 trueDiv 和 floorDiv 路径;d) aclnnInplaceDivMods
  • 每个测试正确地设置 ASCEND950 平台并在结束时恢复 ASCEND910B。
  • 测试仅验证 GetWorkspaceSize 返回成功,与 PR 描述一致(逐位精度由真机用例覆盖)。

未发现问题。


审查统计:

  • P0: 0
  • P1: 0
  • P2: 0
  • P3: 0

整体风险评估: 此变更风险低。改动精准限定在 RegBase (A5) 分支的 tensor-scalar 除法路径,逻辑清晰,测试覆盖充分。

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

💬 仅评论

likedislike
atomgit-bot
atomgit-bot6月25日进行代码检视1
math/div/tests/ut/op_api/test_aclnn_div.cpp
@@ -414,0 +491,4 @@
491+ op::SetPlatformSocVersion(op::SocVersion::ASCEND950);
492+ auto self_tensor_desc = TensorDesc({4, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(10, 100);
493+ auto other_tensor_desc = ScalarDesc(static_cast<double>(3.0));
494+ auto out_tensor_desc = TensorDesc({4, 5}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.0001, 0.0001);
atomgit-bot
atomgit-bot6月25日评论:

🔵 Low Priority

在以下三个测试用例中,输出 TensorDesc 的数据类型为 ACL_FLOAT16,但 Precision 却设置为 0.0001(fp32 级别精度,约 7 位十进制有效数字),而 fp16 仅有约 3 位十进制有效数字,实际能达到的精度约为 0.001。

  • 第 494 行:ascend950_case_divs_fp16_double_scalar_opmath_float
  • 第 524 行:ascend950_case_divmods_fp16_double_scalar_realdiv_opmath_float
  • 第 556 行:ascend950_case_divmods_fp16_double_scalar_floordiv_acctype_float

对比同文件中其他 fp16 输出的测试用例(第 436 行 Precision(0.001, 0.001)、第 586 行 Precision(0.001, 0.001))均使用 0.001,这三个用例的 0.0001 不一致。

虽然当前这些用例仅调用 TestGetWorkspaceSize 而不实际运行计算,Precision 值暂不影响测试结果,但存在以下风险:

  1. 若后续有人基于这些用例添加 TestRun() 调用,fp16 输出无法满足 0.0001 精度,导致误报失败。
  2. 作为参考代码,会误导其他开发者对 fp16 精度期望的理解。
likedislike
Wwangqi_ai成员
6月25日 解决了最后一个问题
RuiWang_成员
6月25日 评论:

/lgtm

likedislike
songkai111成员
6月25日 评论:

/approve
/lgtm

likedislike
CANN-robotCANN-robot成员
6月25日 添加了label:lgtmapproved
CANN-robotCANN-robot成员
6月25日 关闭了关联的issue
CANN-robotCANN-robot成员
6月25日 合入了pull request