【免费下载链接】cann-competitions本仓库用于 CANN 开源社区各类竞赛、开源课题、社区任务等课题发布、开发者作品提交和展示。项目地址: https://gitcode.com/cann/cann-competitions
===== 元信息(请如实填写,此区块将由组委会脚本自动解析,请保持字段名不变)=====
team_name: "别骂了在练了" team_members:
- "成员1:钟华利-广州职业技术大学"
- "成员2:卢泽艺-广州职业技术大学"
- "成员3:黄鸿祥-广州职业技术大学" operator_name: "Cumsum" operator_library: "cann-ops-math" report_date: "2026-04-25"
Cumsum 算子测试报告
测试环境:Ascend 910B (ascend910_93),CANN 工具链版本 8.0.RC1。环境修复说明:已针对
math/cumsum/CMakeLists.txt中的SUPPORT_TILING_DIR配置进行修正,将映射关系由arch32调整为arch35,从而确保了 Host 层(Tiling)覆盖率数据的正常采集。
一、算子理解
1. 数学定义
Cumsum(累积求和)算子用于计算张量在指定维度(dim)上的前缀和。其数学定义为: $$y[i] = \sum_{j=0}^{i} x[j]$$ 其中输出的第 $i$ 个元素是输入前 $i+1$ 个元素的累积和。
2. 规格与功能
- 支持的数据类型:FLOAT32, FLOAT16, BF16, DOUBLE, INT32, INT64, INT8, UINT8, BOOL 等。
- API 变体:
aclnnCumsum(self, dim, dtype, out):标准累积求和。aclnnCumsumV2(self, dim, exclusive, reverse, out):支持exclusive(排他性,结果不含当前元素)和reverse(反向累加)参数。
- 核心特性:
- 误差累积:浮点数的累加特性使其容易产生舍入误差的累积效应。
- 硬件加速:在特定条件下(如满足 Batch 和 Dim 的最小值要求且为特定 Dtype)支持走 Cube 快速路径。
二、测试策略与用例设计
1. 测试思路
采用白盒驱动的测试策略,通过分析 Host 层 Tiling 代码逻辑(如 NGreaterCl, RNGreaterCl, Sklansky 树形归约等),构造特定 Shape 的输入来覆盖不同的执行路径。
2. 参考实现 (Oracle) 与容差设定
- Oracle 选择:
- 浮点数:在 CPU 端使用
double(FP64) 精度进行顺序累积计算,以作为基准真值。 - 整数:显式使用无符号类型(如
uint32_t)模拟二进制补码的截断(回绕)行为。
- 浮点数:在 CPU 端使用
- 精度阈值:
- FLOAT32: $atol=1e-5, rtol=1e-5$
- FLOAT16: $atol=1e-3, rtol=1e-3$
- BF16: $atol=1e-2, rtol=1e-2$
3. 用例分布
共设计59 个测试用例:
- 基础用例:覆盖所有支持的 Dtype、不同维度的 V1 和 V2 API。
- Tiling 逻辑驱动:构造触发 Cube 路径、NGreaterCl、借轴 R 分核、双向 Sklansky 等复杂切分逻辑的 Shape。
- 精度挑战用例:包含长序列累加、极小值/极大值混合、相消灾难等场景。
- 负向用例:空指针、非法维度索引(超过 Rank 或小于 -Rank)、不支持的 Dtype、空 Tensor 等。
三、覆盖率分析
针对决赛要求的 5 个核心评分文件,统计结果如下:
| 文件路径 | 层级 | 行覆盖率 | 分支覆盖率 | 说明 |
|---|---|---|---|---|
op_api/aclnn_cumsum.cpp | API | 94.2% | 88.5% | 覆盖了参数校验、Cube 判定及 V1/V2 路由逻辑。 |
op_api/cumsum.cpp | API | 91.5% | 83.3% | 覆盖了设备路由及各 Dtype 支持检查。 |
op_host/arch35/cumsum_tiling.cpp | Host | 96.0% | 92.0% | 覆盖了 Tiling 入口及 Float/Int 分发路径。 |
op_host/arch35/cumsum_tiling_ascendc_arch35.cpp | Host | 89.7% | 84.1% | 覆盖了 Sklansky 归约及借轴策略。 |
op_host/arch35/cumsum_tiling_ascendc_int_arch35.cpp | Host | 91.3% | 87.2% | 覆盖了整数类型的硬件调整逻辑。 |
| 综合覆盖率 (行数加权) | -- | ~91.1% | ~85.4% | 性能与路径覆盖表现优秀。 |
四、精度分析
典型精度风险场景
场景 1:长序列累加误差 (P01)
- 输入:FLOAT32, 长度 4096, 填充
0.1f。 - 分析:由于
0.1无法在二进制下精确表示,其自带的量化误差随序列长度线性累积。在 4096 次累加后,实测值与double参考值的绝对误差约为 $1.5 \times 10^{-4}$,符合 IEEE 754 舍入预期。
场景 2:大数吃小数 (Swamping) (P02)
- 输入:
[1e8, 1.0, 1.0, -1e8, 1.0]。 - 分析:当累加器达到 $10^8$ 时,其 ULP (最小精度步进) 已经超过了 $1.0$,导致加 $1.0$ 的操作在对阶过程中被舍弃,产生了显著的精度截断。
场景 3:FP16 停滞效应 (Stagnation) (P03)
- 输入:FP16, 长度 2048, 填充
0.001f。 - 分析:FP16 尾数仅 10 位。当总和达到 $2.048$ 时,加上 $0.001$ 会因为落入舍入区间而导致数值不再增长,产生“停滞”现象。
场景 4:相消灾难 (P04)
- 输入:
[100.0, 0.1, -100.0]。 - 分析:大数相减导致有效位丢失,使得原本隐藏在低位的舍入误差被放大至高位,输出变为 $0.09999...$。
场景 5:整数溢出回绕 (P05)
- 输入:INT32,
[INT_MAX, 1]。 - 分析:NPU 遵循二进制补码截断规则,
INT_MAX + 1变为INT_MIN,与 CPU 侧无符号强转逻辑一致。
五、反思与改进
1. 测试局限性
- 内存边界:当前用例尚未完全覆盖接近硬件内存极限(2GB)的大规模数据搬运路径。
- 异常拦截:部分底层驱动错误的分支(如
aclrtMalloc失败)难以通过应用层用例触发。
2. 方法论收获
- 升精度 Oracle 的必要性:直接用
float累加作为参考会导致无法界定是 NPU 还是 CPU 的精度问题,必须使用double乃至更高精度的参考实现。 - Tiling 修复的价值:修正
CMakeLists.txt的架构映射是提升 Host 层覆盖率的关键前提。
3. 对 CANN 链的建议
- 误差预警工具:建议在 Profiling 工具中集成累积误差分析功能,自动检测长序列累加中的 Stagnation 或 Swamping 风险。
- 高精度模式:对于 FP16 累加,可考虑在 Host 层提供 Kahan Summation 选项,供对精度极度敏感的场景使用。
【免费下载链接】cann-competitions本仓库用于 CANN 开源社区各类竞赛、开源课题、社区任务等课题发布、开发者作品提交和展示。项目地址: https://gitcode.com/cann/cann-competitions
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考