已合并
修复iou3d算子精度问题 #1197
yulianjie创建于 22 天前
修复iou3d算子精度问题 #1197
已合并
yulianjie创建于 22 天前
yulianjie
22 天前

描述

背景与根因

Iou3D 的 A5 实现与 MMCV CUDA 参考实现之间存在浮点运算路径差异,主要包括顶点生成顺序、交点收集与去重、极角排序分支以及面积累加顺序。完成几何路径对齐后,100 条用例的 TTK 原生 L1 三方校验仍有 iou3d_L2_008 失败。

隔离 AscendC::SinAscendC::Cos 后确认:该用例的剩余偏差来自默认 Cos|theta| 约为 2.8~3.0 的角度归约精度,不是 Sin。以 CPU FP64 golden 为基准时,修复前该用例的小值域 ErrorCount 为 NPU/GPU=13/6,Ratio=2.1666666667,超过 L1 门槛 2.0

修改内容

  1. 对齐 MMCV 几何计算路径:

    • BoxCorners 按 MMCV 的左下、右下、右上、左上顺序生成轴对齐顶点后逐点旋转;
    • CollectCorners 移除相对阈值去重,候选点上限由 8 调整为 16,并按 MMCV 顺序收集边交点和包含点;
    • SortPolygonArea 补齐 diamond-angle 第三象限分支 keyRaw = -2.0f - t,使排序与 atan2[-pi, pi] 分支一致;
    • 所有 m >= 3 的多边形统一使用排序后首顶点扇形叉积累加,末尾一次 abs / 2,对齐 MMCV 的 fp32 运算顺序;
    • 对有限输入增加 Z 轴无交集短路,避免 BEV 中间结果溢出后产生 NaN * 0
  2. 仅修复 Cos,保留原生 Sin:

    • 使用官方 AscendC::Cos<float, false, CosConfig{CosAlgo::RADIAN_REDUCTION}> 生成高精度候选值;
    • host 侧使用同一 CosConfig 调用 GetCosMaxMinTmpSize,通过新增的 cosTmpSize tiling 字段向 kernel 传递显式 shared temporary buffer 大小;
    • 默认 Sin/Cos 仍先按原路径执行,仅在 2.8 <= |theta| <= 3.0 且高精度值与默认值差异 > 5.9e-8 时覆盖默认 Cos;
    • 不按 testcase、shape、batch 或元素下标特判,Sin 调用和结果缓冲保持不变;
    • 删除实验阶段的自拟合 FittedCos、Cody-Waite 归约和 Chebyshev 多项式,最终只使用现成官方 API。

涉及文件:

  • objdetect/iou3d/op_kernel/arch35/iou3d.h
  • objdetect/iou3d/op_kernel/arch35/iou3d_tiling_data.h
  • objdetect/iou3d/op_host/arch35/iou3d_tiling_arch35.cpp

影响范围

  • 仅修改 arch35 的 Iou3D kernel/tiling 实现,不改变算子接口、输入输出 dtype、shape 或格式约束;
  • 100 条回归中仅 iou3d_L2_008 输出发生变化,其余 99 条逐元素完全一致;
  • iou3d_L2_008 改变 765/31250 个元素(2.448%),最大绝对变化 5.364418029785156e-7
  • 完整 100 条共改变 765/49791 个元素(1.5364%),无精度状态回退;
  • 算子仍按 Vector-bound 场景评估。

关联的 Issue

关联并修复:#666 Iou3D 算子精度问题

测试

测试方法

  • TTK kernel 直调;
  • kernel_iou3d.csv 选取 100 条覆盖不同 dtype、shape 和值域的用例;
  • CPU golden 使用 FP64 升精度,TTK 参数为 --golden-mode Promote
  • GPU golden 对齐 MMCV/PyTorch 实现;
  • 精度级别:L1;
  • 三方结果使用 TTK 原生 CrossCheckComparison 判定。

精度结果

项目 修复前 修复后
TTK kernel 直调基础精度 - 100/100 PASS
CPU FP64 / NPU / GPU 原生 L1 99/100 PASS 100/100 PASS
iou3d_L2_008 状态 FAIL PASS
iou3d_L2_008 MARE Ratio 1.0662077995 1.0662077995
iou3d_L2_008 MERE Ratio 1.0590700508 1.0399741779
iou3d_L2_008 RMSE Ratio 0.2802136132 0.2696275100
iou3d_L2_008 小值域 ErrorCount(NPU/GPU) 13/6 12/6
iou3d_L2_008 小值域 ErrorCount Ratio 2.1666666667 2.0(L1 PASS,位于门槛边界)

性能结果

同一固定输入下的 kernel 计时:

指标 结果
baseline A5 806.195 us
自拟合 Cos 实验版 A5 872.424 us
最终官方 API 版 A5 836.202 us
最终版相对 baseline +3.7221%
最终版相对自拟合版 -4.1519%
GPU NVTX CUDA-kernel p50 315.745 us
最终 A5 / GPU 2.6483x

自动流水线

截至 2026-07-31、PR head 96ae285cdeb532d2636dd054aa37c2688407c6ff:编译矩阵、API_CheckPreSmoke_A900PreSmoke_ATK_Test_A2 已通过;UT_TestSCA 仍显示失败,具体状态和后续重跑结果以 PR 页面实时流水线为准,本描述不将其误标为通过。

文档更新

无对外 API 或 README 文档变更;仅同步更新 kernel/tiling 实现注释。

类型标签

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

变更摘要

此 PR 主要将 IOU3D 算子中多个几何计算路径从自研实现切换为严格对齐 MMCV CUDA 参考实现(iou3d_cuda_kernel.cuh / golden.py),以修复因顶点顺序、去重策略、排序分支和面积累加方式差异导致的 fp32 精度偏差。核心改动涉及 BoxCorners 顶点顺序与旋转方式、CollectCorners 弃用去重并扩展候选点上限至 16、SortPolygonArea 的极角键三分支对齐 atan2 及首顶点扇形面积累加、以及 Z 轴无交集时的有限输入短路优化。

主要改动

  • BoxCorners 顶点顺序与旋转方式对齐 MMCV:改为先生成轴对齐的四角点(左下、右下、右上、左上),再逐点绕中心旋转,替代原先直接计算左上/右上/右下/左下并一次性叠加旋转分量的方式,确保顶点序与 MMCV 完全一致。

  • CollectCorners 弃用去重并将候选点上限从 8 提升至 16:移除基于 IOU3D_DEDUP_TOL / IOU3D_DEDUP_REL 的幅值相对强去重逻辑,改为按 golden 顺序先收集 16 组边交点、再依次收集包含点(框2顶点在框1内、框1顶点在框2内),常量 IOU3D_MAX_INTER 由 8 改为 16,对齐 MMCV 的 cross_points[16]

  • SortPolygonArea 极角键三分支与首顶点扇形面积:diamond-angle 键新增 xr<0, yr<0 分支(key = -2 - t)以对齐 atan2 负半轴排序;面积累加由质心基准的有符号鞋带改为以 order[0] 为首顶点的扇形叉积和(末尾一次 abs/2),消除浮点运算顺序差异带来的 1 ULP 偏差。

  • 移除 TriArea 函数与 PolygonAream==3 的三角形直算分支:所有 m>=3 的多边形统一进入 SortPolygonArea 的 MMCV 路径,原先的三角形面积函数被删除。

  • ComputePairIou 新增 Z 轴无交集时有限输入短路:当 realD==0 且两个框的 7-DoF 均为有限值时直接返回 0.0,避免超大有限坐标在 fp32 BEV 几何运算中溢出为 NaN/Inf 后与 0 相乘产生 NaN 的异常传播。

likedislike
atomgit-bot
atomgit-bot
22 天前 评论:

代码审查


审查总结

各文件审查结果

文件 结果
objdetect/iou3d/op_host/arch35/iou3d_tiling_arch35.cpp ✅ 无问题(仅注释修改:多边形顶点 <=8有效顶点 <=16,无代码变更)
objdetect/iou3d/op_kernel/arch35/iou3d.h ⚠️ 2 个发现

发现按优先级统计

  • P2: 1 个(CollectCorners 移除中间缓冲区后缺乏越界写守卫)
  • P3: 1 个(SortPolygonArea 面积循环 k=0 迭代恒贡献 0,可优化)

整体风险评估

中等风险。核心算法改动(diamond-angle 三分支排序键修复第三象限顶点错序、MMCV 对齐的首顶点扇形面积、BoxCorners 重写对齐 MMCV 顶点序、移除去重、Z 轴零重叠有限输入短路)均方向正确,有效解决了精度问题。P2 发现是防御性编程问题——旧代码有 32 元素中间缓冲区做安全网,新代码移除了这层防护;虽然对两凸四边形实际不会触发越界,但降低了代码鲁棒性。P3 发现为微小冗余,不影响正确性。

⚠️ 已识别出整体风险,但无法提取行内评论,请参考整体评估。

likedislike
CANN-robotCANN-robot成员
22 天前 添加了label:cann-cla/yes
CANN-robot
CANN-robot成员
22 天前 评论:

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

CLA Signature Pass

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

likedislike
此处折叠了96条消息 查看更多
CANN-robot
CANN-robot成员
15 天前 评论:

The MR can not be merged, because of CodeReview discussion not resolved

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

likedislike
wang-xing001成员
15 天前 评论:

/lgtm
/approve

likedislike
Wwang-xing001成员
15 天前 解决了最后一个问题
CANN-robotCANN-robot成员
15 天前 关闭了关联的issue
CANN-robotCANN-robot成员
15 天前 合入了pull request