news 2026/5/9 19:30:39

Add 算子测试报告

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Add 算子测试报告

【免费下载链接】cann-competitions本仓库用于 CANN 开源社区各类竞赛、开源课题、社区任务等课题发布、开发者作品提交和展示。项目地址: https://gitcode.com/cann/cann-competitions

===== 元信息(请如实填写,此区块将由组委会脚本自动解析,请保持字段名不变)=====

team_name: "不要垫底"

team_members:

  • "滕佳琳-广州大学"
  • "李楚湘-广州大学"

operator_name: "Add"

operator_library: "cann-ops-math"

report_date: "2026-04-25"


Add 算子测试报告

测试环境:Ascend 910 系列评测环境,SOC 参数为ascend910_93,CANN ops-math 仓库开启覆盖率编译。覆盖率统计采用gcov -b -c获取,以评测相关的 op_api 层文件为统计对象。不同 CANN 版本、SOC 配置与算子支持情况可能导致覆盖率与边界行为存在差异,本文记录本次实机运行结果。


一、算子理解

Add 算子执行带缩放系数的逐元素加法,核心数学形式为:

out = self + alpha * other

其中selfother可以是形状相同的张量,也可以是满足 broadcasting 规则的张量;alpha是标量系数,用于控制第二个输入对输出的贡献。当alpha=1时,算子退化为普通逐元素加法;当alpha=0时,输出应保持为self;当alpha为负数或非整数小数时,算子需要同时处理乘法缩放、加法累加以及数据类型转换带来的精度影响。

本次测试关注的接口包括aclnnAddaclnnAddsaclnnInplaceAddaclnnInplaceAdds以及aclnnAddV3。从输入形式看,既包含 tensor + tensor,也包含 tensor + scalar、scalar + tensor 以及 inplace 原地写回场景。Add 算子本身不是规约类算子,每个输出元素主要依赖对应位置的输入元素,因此不存在类似 Cumsum 的长序列误差累积问题;但它仍然具有若干值得重点验证的数值特征,包括大小数相加导致的小量丢失、正负抵消导致的有效位损失、FP16/BF16 量化误差、NaN/Inf 传播、次正规数处理以及整数溢出或截断行为。

在 dtype 方面,本次测试覆盖了 FLOAT32、FLOAT16、BF16、INT32、INT64、INT8、UINT8、BOOL 等常见类型,并补充了 FP16/BF16 与 FLOAT 混合输入的兼容性探索。浮点类型采用容差比较,整数类型采用精确匹配或按类型语义解释;特殊值场景则采用std::isinfstd::isnanstd::fpclassify等方式判断,避免用单一绝对误差处理跨量级或非有限值。


二、测试策略与用例设计

本次在test_aclnn_add.cpp中设计了 55 个端到端测试用例,测试目标不是只验证普通加法是否可运行,而是围绕 Add 算子的关键输入维度做分层覆盖:基础功能、数据类型、shape 与 broadcasting、API 变体、精度风险、特殊值、混合精度以及补充边界场景。每个正常计算用例均在 CPU 端计算期望值,并在 NPU 算子执行完成后将输出拷贝回 host 进行逐元素比对。

1. 基础功能与 alpha 参数覆盖。设计了alpha=1alpha=1.2alpha=0alpha=-2.5等场景,覆盖普通加法、非单位缩放、忽略第二输入、负系数减法化等典型路径。该部分能够直接验证out = self + alpha * other的基本语义是否正确,尤其是alpha=0与负数 alpha 这类容易暴露分支处理问题的边界值。

2. 多数据类型覆盖。用例覆盖 FP32、FP16、BF16、INT32、INT64、INT8、UINT8、BOOL。FP16 与 BF16 没有直接把uint16_t位模式当作数值参与比较,而是实现了floatToHalfhalfToFloatfloatToBF16bf16ToFloat等辅助函数,先完成编码/解码,再进行 CPU 参考值计算和输出解释。这样可以避免把半精度位模式误当作普通整数,保证 Oracle 与 NPU 输入在量化语义上保持一致。

3. shape 与 broadcasting 覆盖。构造了[4,1] + [1,4] -> [4,4][4,2] + [2] -> [4,2][1] + [4] -> [4][2,3,4]高维张量以及[256,256]较大张量场景。该部分重点检查形状对齐、广播展开、高维 stride 计算以及较大数据量下的正确性。对于 Add 算子而言,broadcasting 是比普通同形状加法更容易触发内部 shape 处理逻辑的输入形态,因此本次将其作为重点覆盖方向之一。

4. API 变体覆盖。aclnnAdd主入口外,还设计了aclnnAddsaclnnInplaceAddaclnnInplaceAddsaclnnAddV3相关用例,分别覆盖 tensor + scalar、原地更新、scalar + tensor 等使用方式。其中 inplace 场景直接从原输入地址拷贝回结果进行验证,能够检查算子是否正确写回 selfRef,而不是仅验证普通 out tensor 写入。

5. 精度与特殊值覆盖。精度专项包括大小数相加、正负抵消、非精确 alpha 缩放、极大值、极小 alpha 等场景;特殊值专项包括 Inf、NaN、Subnormal。测试目的不是把所有现象简单判为错误,而是区分“算子错误”和“数据类型固有行为”。例如大数加小数时,小数可能因 FP32 有效位限制而无法改变结果;正负抵消会放大相对误差;BF16/FP16 的尾数位较短,容差需要明显宽于 FP32。

Oracle 与容差设置。浮点测试以 CPU double 计算作为参考基准:

expected = (double)self + (double)alpha * (double)other

FP32 常规场景使用1e-6 ~ 1e-5量级容差,FP16 使用1e-3 ~ 1e-2量级容差,BF16 使用1e-1量级容差;特殊大数、极小 alpha 或混合精度场景根据输入量级适当放宽。整数场景以目标 dtype 的结果为基准进行精确比较,避免将浮点误差判断逻辑套用到整数算子。


三、覆盖率分析

本次通过如下方式提取评分相关文件覆盖率:

gcov -b -c $(find build -name "aclnn_add.cpp.gcda" | head -1) gcov -b -c $(find build -name "aclnn_add_v3.cpp.gcda" | head -1) gcov -b -c $(find build -name "add.cpp.gcda" | grep "/__/add/op_api/" | head -1)

实机运行后得到的覆盖率如下:

文件代码行数行覆盖率分支覆盖率说明
op_api/aclnn_add.cpp30330.69%(约 93 行)11.58%(约 179/1546)主 API 层,当前测试主要命中 Add/Adds/Inplace 相关正向执行路径
op_api/aclnn_add_v3.cpp770.00%(0 行)0.00%(0/426)V3 独立实现文件在当前运行环境下未形成有效覆盖率命中
op_api/add.cpp590.00%(0 行)0.00%(0/264)底层路由文件在本次 gcov 统计中未被有效命中

综合覆盖率按行数和分支数加权计算:

综合行覆盖率 = (93 + 0 + 0) / (303 + 77 + 59) = 93 / 439 ≈ 21.18% 综合分支覆盖率 = (179 + 0 + 0) / (1546 + 426 + 264) = 179 / 2236 ≈ 8.01%

从结果看,本次覆盖率主要集中在aclnn_add.cpp,说明测试用例已经有效触达 Add 主入口中的正常执行路径、alpha 参数处理、不同 dtype 输入、broadcasting 以及 inplace 等功能分支。aclnn_add_v3.cppadd.cpp当前为 0,并不代表测试设计完全没有涉及相关语义:测试源文件中已经补充了 AddV3、Adds、Inplace 等接口层用例,但在当前编译/运行环境与算子路由条件下,独立aclnn_add_v3.cpp和底层add.cpp未产生有效 gcov 命中。考虑到本次时间有限,报告中将该结果如实记录,同时把分析重点放在已经稳定运行并产生覆盖率的主入口文件上。

需要说明的是,Add 算子的 API 层包含大量参数校验、类型组合、异常输入、设备路由和宏控制分支。分支覆盖率低于行覆盖率是合理现象:行覆盖只要求某行代码执行过,而分支覆盖要求条件表达式的 true/false 两侧都被触发。当前用例更偏向“保证可通过的正向路径”和“数值语义验证”,没有大量构造 nullptr、非法 dtype、形状不兼容等强异常路径,因此分支覆盖率相对保守。这种取舍有利于保证提交用例整体稳定通过,同时仍能展示较完整的功能与精度测试设计。


四、精度分析

Add 算子是逐元素运算,不涉及长序列累积,但仍会受到浮点有效位、舍入、特殊值传播和 dtype 转换的影响。本次精度分析围绕以下典型场景展开。

场景一:大小数相加导致小量贡献丢失

测试思路:构造类似1e8 + 1的输入。数学上结果应比1e8略大,但在 FP32 中,1e8附近相邻可表示数之间的间隔已经大于 1,因此小数值可能无法改变最终表示。

分析:这不是 Add 算子的实现错误,而是浮点数有效位有限导致的正常现象。FP32 只有约 7 位十进制有效数字,当一个很小的数加到一个很大的数上时,小数部分可能在对阶过程中被舍弃。本测试通过记录该现象,说明测试不仅关注 pass/fail,也关注用户在实际使用中可能遇到的静默精度损失。

场景二:正负抵消导致有效位损失

测试思路:构造大正数与大负数相加后只剩较小残差的场景,例如1e8 + (-1e8 + delta)。这类输入的绝对误差可能不大,但相对于最终残差的相对误差会被放大。

分析:正负抵消是加法算子中最典型的数值风险之一。两个大数相减后,高位有效数字相互抵消,输出主要依赖低位信息,而低位信息在输入量化或计算过程中可能已经损失。因此,本次没有简单套用固定相对误差,而是结合输入量级选择容差,并在报告中说明该现象属于浮点计算固有限制。

场景三:alpha 缩放引入的舍入误差

测试思路:使用alpha=0.3alpha=1.2alpha=2.5alpha=1e-10等非整数或极小系数。由于多数十进制小数无法被二进制浮点精确表示,alpha * other在进入加法前已经可能产生舍入误差。

分析:Add 算子实际包含“乘法缩放 + 加法”两个步骤,因此精度误差不仅来自加法本身,也来自 alpha 的二进制表示和乘法结果的舍入。对于 FP32 常规输入,本次采用1e-5级容差;对于极小 alpha 或边界值输入,则根据量级适当放宽,以避免把可解释的浮点舍入误差误判为算子错误。

场景四:FP16 与 BF16 的 dtype 差异

测试思路:使用同一语义输入分别构造 FP16、BF16 和 FP32 场景,并通过手写编码/解码函数解释半精度输出。

分析:FP16 尾数位较短,但指数范围也较小;BF16 保留了与 FP32 相同宽度的指数位,但尾数只有 7 位,因此在普通数值区间内分辨率明显低于 FP32。测试中对 FP16 采用1e-3 ~ 1e-2量级容差,对 BF16 采用1e-1量级容差,这与两种 dtype 的表示精度相匹配。报告中特别强调,半精度测试必须先将位模式解码为 float 再比较,否则 Oracle 本身会出错。

场景五:Inf、NaN 与次正规数处理

测试思路:构造 Inf 输入、NaN 输入以及极小次正规数输入。Inf 场景使用std::isinf判断,NaN 场景使用std::isnan判断,Subnormal 场景使用std::fpclassify或量级检查。

分析:对特殊值不能使用普通abs(actual - expected) <= atol + rtol * abs(expected)公式。例如 Inf 与任何有限 atol 比较都没有意义,NaN 与自身也不相等。通过单独设计特殊值判断逻辑,可以让测试更贴合 IEEE 浮点语义,也能避免将特殊值传播行为误判为普通数值误差。


五、反思与改进

本次测试的主要优点在于:用例数量较多,覆盖维度较全面,不仅验证了普通 FP32 加法,还覆盖了 alpha 边界、整数类型、半精度类型、broadcasting、高维 shape、较大 tensor、inplace 写回、scalar 变体、特殊值和精度风险场景。相比只打印输出的示例测试,本次每个主要用例都包含 CPU Oracle 与逐元素比对,具备自动判断 pass/fail 的能力;同时,FP16/BF16 通过显式编解码处理,避免了半精度测试中常见的 Oracle 错误。

当前覆盖率的主要局限在于:覆盖率命中集中在aclnn_add.cppaclnn_add_v3.cppadd.cpp在本次环境下没有形成有效 gcov 命中。后续如果继续优化,可以优先从三个方向入手:第一,确认 AddV3 在当前 SOC 与 CANN 版本下的真实路由条件,使 V3 用例能够稳定进入独立实现文件;第二,补充更多 shape 不兼容、nullptr、非法 dtype、空 tensor 等异常路径,以提升参数校验分支覆盖;第三,针对底层add.cpp的设备路由条件,构造更贴近其分发逻辑的 dtype 与 shape 组合。

总体而言,本次测试策略优先保证了端到端运行稳定性、结果验证完整性和精度分析深度。在比赛提交场景下,这种设计能够较好体现测试代码的实用性:即使部分底层覆盖率受环境和路由影响,测试本身仍覆盖了 Add 算子的主要用户可见行为,并对容易出错的数据类型和数值边界给出了明确验证。

【免费下载链接】cann-competitions本仓库用于 CANN 开源社区各类竞赛、开源课题、社区任务等课题发布、开发者作品提交和展示。项目地址: https://gitcode.com/cann/cann-competitions

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 19:26:44

边缘计算安全实战:从架构威胁到AI驱动的防护体系

1. 项目概述&#xff1a;当边缘计算遇上安全攻防最近几年&#xff0c;边缘计算&#xff08;MEC&#xff09;火得不行&#xff0c;几乎成了5G、物联网、工业互联网这些热门领域的“标配”。我身边不少做网络、做应用的朋友&#xff0c;项目里要是不提一嘴边缘计算&#xff0c;好…

作者头像 李华
网站建设 2026/5/9 19:25:44

MagiskBoot深度解析:Android启动镜像修改机制与架构设计

MagiskBoot深度解析&#xff1a;Android启动镜像修改机制与架构设计 【免费下载链接】Magisk The Magic Mask for Android 项目地址: https://gitcode.com/GitHub_Trending/ma/Magisk MagiskBoot作为Magisk生态中的核心二进制工具&#xff0c;专为Android启动镜像&#…

作者头像 李华
网站建设 2026/5/9 19:22:39

FireRedASR-AED-L入门必看:1.1B参数大模型本地化部署全流程

FireRedASR-AED-L入门必看&#xff1a;1.1B参数大模型本地化部署全流程 1. 项目简介 FireRedASR-AED-L是一个基于1.1B参数大模型开发的本地语音识别工具&#xff0c;专门为中文、方言和中英混合语音识别而设计。这个工具最大的特点是完全本地运行&#xff0c;不需要网络连接&…

作者头像 李华
网站建设 2026/5/9 19:18:54

为OpenClaw工具配置Taotoken作为后端大模型服务提供方

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 为OpenClaw工具配置Taotoken作为后端大模型服务提供方 OpenClaw是一款功能强大的AI智能体开发工具&#xff0c;它允许开发者构建和…

作者头像 李华
网站建设 2026/5/9 19:18:36

独立开发者如何借助 Taotoken 模型广场为不同任务选择最佳模型

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 独立开发者如何借助 Taotoken 模型广场为不同任务选择最佳模型 对于独立开发者或小微工作室而言&#xff0c;项目需求往往是多样且…

作者头像 李华