Pull Request已成功合入, 合并人@CANN-robot
(感谢 zhangyiyi 的贡献)变更摘要
本次提交修复了 BoundingBoxEncode kernel 在极端坐标范围(如 anchor 坐标接近 FP32 最大值、ground-truth 坐标极小)下的精度问题。当 rw = gw / pw 下溢趋近于零时,NPU 硬件 AscendC::Ln 指令会返回 -inf,而 CPU/GPU 的 log 能正确返回有限值。为此在 BoxDeltaCalc 结构体中新增 FixLnResult 后处理守卫函数和 SoftLnPositive 软件兜底 ln 实现,并在 ComputeFp16Path 和 ComputeFp32Path 两条计算路径中同步接入该守卫逻辑,确保 NPU 输出与 CPU/GPU 行为对齐。
主要改动
-
新增
FixLnResult后处理守卫函数:对origInput进行 NaN/零/负数分类处理,并检测npuLnResult == -inf && origInput > 0.0的下溢场景,将其路由至SoftLnPositive软件兜底;正常值域下原样透传硬件Ln结果,保持零开销。 -
新增
SoftLnPositive软件ln实现:通过反复乘/除 2 将输入分解为尾数m ∈ [1, 2)和指数e,再以atanh泰勒级数(6 项展开)计算ln(m),最终返回2 * atanh(z) + e * ln(2),在硬件Ln产出-inf的退化场景下提供与 CPU/GPU 一致的有限值。 -
新增
MakeNegInf和MakeNan工具函数:通过union { uint32_t; float }位操作构造 FP32 的-inf(0xFF800000)和 NaN(0x7FC00000),供FixLnResult和SoftLnPositive使用。 -
ComputeFp16Path路径接入守卫逻辑:dw/dh计算改为先从buf1读取原始rw/rh,经FixLnResult处理后再做(lnRw - means) / stds归一化,替换原先直接消费buf2.GetValue(base+2)的方式。 -
ComputeFp32Path路径同步接入守卫逻辑:与 FP16 路径一致,改为从aFp32读取原始rw/rh,经FixLnResult处理后再归一化,保证两条计算路径行为统一。


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/ops-cv | ✅ 汤平川, 周奇龙 (2/2) | ✅ 周奇龙, 汤平川 (2/1) |
💡 Tip:
- Committer can comment
/approveor/lgtm- Commenting
/approveimplies both code review (lgtm) and intent to merge (approve)
CLA Signature Pass
ugzhangyiyi, thanks for your pull request. All authors of the commits have signed the CLA. 👍


/compile


流水线任务触发成功
任务链接 [90ac79de163d408bad279cebbe7c7226][流水线指导]
| 任务名称 | 状态 | 日志 | 下载链接 |
|---|---|---|---|
| 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_X86_A5 | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_Ascend_ARM_A5 | ✅ SUCCESS | >>>>> | >>>>> |
| pre_comment | ✅ SUCCESS | >>>>> | |
| Compile_Pre | ✅ SUCCESS | >>>>> | |
| Compile_Ascend_X86_ubuntu24 | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_Ascend_X86_mobile_station_ubuntu24 | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_Ascend_X86_experimental_ubuntu24 | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_Ascend_X86_A5_ubuntu24 | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_Ascend_ARM_ubuntu24 | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_Ascend_ARM_experimental_ubuntu24 | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_Ascend_ARM_A5_ubuntu24 | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_X86_monitor_910b | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_X86_monitor_910c | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_X86_monitor_950 | ✅ SUCCESS | >>>>> | >>>>> |
| Compile_classify | ✅ SUCCESS | >>>>> | |
| Compile_Ascend_X86_mobile_station_9030_ubuntu24 | ✅ SUCCESS | >>>>> | >>>>> |
| UT_Test | ✅ SUCCESS | ||
| PreSmoke_A900 | ✅ SUCCESS | >>>>> | |
| API_Check | ✅ SUCCESS | >>>>> | |
| PreSmoke_ATK_Test_A2 | ✅ SUCCESS | >>>>> | |
| UT_Test_report_lcov | ✅ SUCCESS |
[2026-08-13 21:27:04] CI执行结束


流水线任务触发成功
任务链接 [4f3e72e3685c4824a48cd384e545f928][流水线指导]
| 任务名称 | 状态 | 日志 | 下载链接 |
|---|---|---|---|
| SCA | ✅ SUCCESS | >>>>> | |
| antipoison | ✅ SUCCESS | >>>>> | |
| codecheck_checkpr | ✅ SUCCESS | ||
| StaticCheck_codespell | ✅ SUCCESS | ||
| StaticCheck_link_validity | ✅ SUCCESS | ||
| StaticCheck_resource_existence | ✅ SUCCESS | ||
| StaticCheck_tag_closed | ✅ SUCCESS | ||
| StaticCheck_markdownlint | ✅ SUCCESS | ||
| codecheck_precommit | ✅ SUCCESS | >>>>> |
[2026-08-13 21:22:45] CI执行结束


/lgtm
/approve


描述
本次提交修复了
BoundingBoxEncodekernel 在处理极端或失配坐标范围的边界框(例如 anchor 坐标接近 FP32 最大值 ~3.4e38、ground-truth 坐标 ~0.01)时的精度问题。该场景下rw = gw / pw会下溢趋近于零,触发 NPU 硬件Ln指令返回-inf而非有限负数值。根因: NPU
AscendC::Ln硬件指令对极小正数输入(接近 FP32 下溢阈值 ~1e-38)返回-inf,而 CPUnumpy.log与 GPUcuda::log能正确返回有限值(如log(1e-30) ≈ -69.07)。原始 kernel 在 FP16 和 FP32 两条计算路径中均直接消费Ln原始输出,当rw/rh下溢时,编码后的dw/dh变为-inf,经(dw - means) / stds归一化后输出包含-inf或NaN,导致与 CPU golden 的精度比对失败。修复方法 — 在
BoxDeltaCalc中新增FixLnResult+SoftLnPositive兜底逻辑:FixLnResult(origInput, npuLnResult)—— 后处理守卫函数,同时检查原始输入和 NPULn结果:origInput为 NaN → 返回 NaN(符合 IEEE 754)origInput == 0.0→ 返回-inf(符合log(0))origInput < 0.0→ 返回 NaN(符合log(负数))npuLnResult为 NaN → 返回 NaN(传播硬件错误)npuLnResult == -inf && origInput > 0.0→ 转入SoftLnPositive软件兜底(核心修复点)npuLnResult(正常路径,零开销)SoftLnPositive(x)—— 针对-inf兜底场景的软件ln实现,采用atanh泰勒级数:x归一化为尾数m ∈ [1, 2)和指数e(通过反复乘/除 2 实现)z = (m - 1) / (m + 1),再算atanh(z) ≈ z * (1 + z²/3 + z⁴/5 + z⁶/7 + z⁸/9 + z¹⁰/11)2 * atanh(z) + e * ln(2),其中ln(2) = 0.69314718ComputeFp16Path和ComputeFp32Path同步更新:dw/dh计算改为先从 buffer 读取原始rw/rh,经FixLnResult处理后再做(lnRw - means) / stds归一化,替换原先直接消费buf2.GetValue(base+2)的方式。影响范围: 正常值域(
rw ∈ [0.5, 2.0])不受影响 ——FixLnResult原样透传硬件Ln结果,行为零变化。该修复仅在硬件会产出-inf的退化输入场景下激活,使 NPU 输出与 CPU/GPU 行为对齐。关联的Issue
https://gitcode.com/cann/ops-cv/issues/734
测试
test_geir_bounding_box_encode):FP32(2,4)单节点图编译 + NPU 执行 —— PASStest_geir_bounding_box_encode_dynamic):[-1,-1]5 种 shape +[-2](unknown rank)5 种 shape —— 10/10 PASStest_geir_intercept):14 例矩阵(合法/非法 dtype、shape、rank、means/stds 长度、stds=0)—— 13/14 PASS(1 例结构性不可拦截:dtype 不一致被内置 proto V1 InferShape 屏蔽 + FE 自动插 Cast)FixLnResult正确将rw=1e-30路由至SoftLnPositive,产出≈ -69.07与 CPUnumpy.log(1e-30)一致;正常rw=1.07原样透传硬件Ln,误差 ≤ 3.3e-7类型标签