文件最后提交记录最后更新时间
[CANNBot]增加experimental下 AsinhV2 实现 Co-authored-by: wang-shilong32<wangshilong23@huawei.com> # message auto-generated for no-merge-commit merge: !2112 merge agent_asinh_950_exp into master [CANNBot]增加experimental下 AsinhV2 实现 Created-by: wang-shilong32 Commit-by: wang-shilong32 Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 增加experimental下 AsinhV2 实现。 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> https://gitcode.com/cann/ops-math/issues/1193 ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> 本地测试用例。 ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-math!21121 个月前
[CANNBot]增加experimental下 AsinhV2 实现 Co-authored-by: wang-shilong32<wangshilong23@huawei.com> # message auto-generated for no-merge-commit merge: !2112 merge agent_asinh_950_exp into master [CANNBot]增加experimental下 AsinhV2 实现 Created-by: wang-shilong32 Commit-by: wang-shilong32 Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 增加experimental下 AsinhV2 实现。 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> https://gitcode.com/cann/ops-math/issues/1193 ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> 本地测试用例。 ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-math!21121 个月前
[CANNBot]增加experimental下 AsinhV2 实现 Co-authored-by: wang-shilong32<wangshilong23@huawei.com> # message auto-generated for no-merge-commit merge: !2112 merge agent_asinh_950_exp into master [CANNBot]增加experimental下 AsinhV2 实现 Created-by: wang-shilong32 Commit-by: wang-shilong32 Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 增加experimental下 AsinhV2 实现。 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> https://gitcode.com/cann/ops-math/issues/1193 ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> 本地测试用例。 ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-math!21121 个月前
[CANNBot]增加experimental下 AsinhV2 实现 Co-authored-by: wang-shilong32<wangshilong23@huawei.com> # message auto-generated for no-merge-commit merge: !2112 merge agent_asinh_950_exp into master [CANNBot]增加experimental下 AsinhV2 实现 Created-by: wang-shilong32 Commit-by: wang-shilong32 Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 增加experimental下 AsinhV2 实现。 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> https://gitcode.com/cann/ops-math/issues/1193 ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> 本地测试用例。 ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-math!21121 个月前
[CANNBot]增加experimental下 AsinhV2 实现 Co-authored-by: wang-shilong32<wangshilong23@huawei.com> # message auto-generated for no-merge-commit merge: !2112 merge agent_asinh_950_exp into master [CANNBot]增加experimental下 AsinhV2 实现 Created-by: wang-shilong32 Commit-by: wang-shilong32 Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 增加experimental下 AsinhV2 实现。 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> https://gitcode.com/cann/ops-math/issues/1193 ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> 本地测试用例。 ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-math!21121 个月前
修改不易理解词汇-使能,并补齐op_list(math/random类) Co-authored-by: gitcode-chenjiao<chenjiao31@huawei.com> # message auto-generated for no-merge-commit merge: !2982 merge master into master 修改不易理解词汇-使能,并补齐op_list(math/random类) Created-by: gitcode-chenjiao Commit-by: gitcode-chenjiao Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> ①修改不易理解词汇-使能; ②排查op_list.md中math/random类下算子目录是否齐全 ③排查op_api_list.md是否齐全 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。--> <!-- 如果这个PR是为了解决特定的问题单,请在这里描述问题单单号。--> NA ## 测试 <!--描述进行了哪些测试来验证你的改动。包括但不限于二级冒烟、算子泛化等。--> 已验证 ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> op_list.md op_api_list.md ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [x ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-math!29825 天前
README.md

AsinhV2 算子用户指南

快速开始

算子概述

AsinhV2 是一个 Ascend C 自定义算子,对输入 tensor 的每个元素执行反双曲正弦(asinh)函数运算。

数学公式

y = asinh(x) = ln(x + sqrt(x^2 + 1))

该函数适用于全体实数,无定义域限制,输出值域为 (-∞, +∞)。

关键特性

  • 多类型支持:9 种数据类型(float16, float32, int8, int16, int32, int64, uint8, bool, double)
  • 高效实现:使用 Ascend C 高阶 API,性能优化充分
  • 完整覆盖:4 路 TilingKey,支持单/双缓冲策略,覆盖小/大数据量场景
  • 精度达标:float16 atol/rtol=0.001,float32 atol/rtol=0.0001,与 PyTorch torch.asinh 对齐
  • 多架构支持:Ascend950DT/PR(arch35)

安装与编译

环境要求

项目 要求
CANN 版本 >= 9.0.0
Ascend 芯片 Ascend950DT/PR
操作系统 Ubuntu 18.04+ / CentOS 7.6+
编译工具 g++ 7.3+,cmake 3.13+

编译步骤

第一步:进入算子目录

cd ops/asinh_v2

第二步:执行编译

# 编译 arch35(Ascend950,可选)
bash build.sh --soc=ascend950

第三步:查看编译产物

# 编译产物位置
build/op_kernel/ascendc_kernels/binary/
build/op_host/cust_opapi.so
custom_opp_ubuntu_aarch64.run         # 安装包

第四步:安装自定义算子

# 解压安装包
chmod +x custom_opp_ubuntu_aarch64.run
./custom_opp_ubuntu_aarch64.run

# 验证安装
ls $ASCEND_OPP_PATH/vendors/customize_op/

API 使用

ACLNN 接口

AsinhV2 算子通过 ACLNN(Ascend C Logical Neural Network)接口提供两段式调用方式。

接口原型

// 获取工作空间大小
aclnnStatus aclnnAsinhV2GetWorkspaceSize(
    aclTensor *inputTensor,
    aclTensor *outputTensor,
    uint64_t *workspaceSize,
    aclHandle *handle);

// 执行算子
aclnnStatus aclnnAsinhV2(
    aclHandle *handle,
    aclTensor *inputTensor,
    aclTensor *outputTensor,
    void *workspaceAddr,
    uint64_t workspaceSize,
    aclrtStream stream);

调用示例(C/C++)

#include <acl/acl.h>
#include "aclnn_asinh_v2.h"

int main() {
    // 初始化 ACL
    aclInit(nullptr);

    // 创建输入 tensor(shape=[1024], dtype=float32)
    int64_t shape[] = {1024};
    aclTensor *inputTensor = aclCreateTensor(shape, 1, aclDataType::ACL_FLOAT32,
                                             aclMemType::ACL_DEVICE);
    float *inputData = (float*)malloc(1024 * sizeof(float));
    // ... 填充 inputData ...
    aclrtMemcpy(aclGetDeviceAddr(inputTensor), 1024 * sizeof(float),
                inputData, 1024 * sizeof(float), aclMemcpyKind::ACL_MEMCPY_HOST_TO_DEVICE);

    // 创建输出 tensor
    aclTensor *outputTensor = aclCreateTensor(shape, 1, aclDataType::ACL_FLOAT32,
                                              aclMemType::ACL_DEVICE);

    // 获取工作空间大小
    uint64_t workspaceSize = 0;
    aclHandle *handle = aclrtGetCurrentStream();
    aclnnAsinhV2GetWorkspaceSize(inputTensor, outputTensor, &workspaceSize, handle);

    // 分配工作空间
    void *workspaceAddr = nullptr;
    aclrtMalloc(&workspaceAddr, workspaceSize, aclMemType::ACL_DEVICE);

    // 执行算子
    aclrtStream stream = aclrtGetCurrentStream();
    aclnnAsinhV2(handle, inputTensor, outputTensor,
                        workspaceAddr, workspaceSize, stream);

    // 获取结果
    float *outputData = (float*)malloc(1024 * sizeof(float));
    aclrtMemcpy(outputData, 1024 * sizeof(float),
                aclGetDeviceAddr(outputTensor), 1024 * sizeof(float),
                aclMemcpyKind::ACL_MEMCPY_DEVICE_TO_HOST);

    // 清理资源
    aclrtFree(workspaceAddr);
    aclDestroyTensor(inputTensor);
    aclDestroyTensor(outputTensor);
    aclFinalize();

    return 0;
}

数据类型支持

输入 dtype 输出 dtype 处理路径 说明
float16 float16 Kernel 原生路径 直接调用 AscendC::Asinh(T=half)
float32 float32 Kernel 原生路径 直接调用 AscendC::Asinh(T=float)
int8 float32 op_api Cast 路径 在 op_api 层转换为 float32 后执行
int16 float32 op_api Cast 路径 在 op_api 层转换为 float32 后执行
int32 float32 op_api Cast 路径 在 op_api 层转换为 float32 后执行
int64 float32 op_api Cast 路径 在 op_api 层转换为 float32 后执行
uint8 float32 op_api Cast 路径 在 op_api 层转换为 float32 后执行
bool float32 op_api Cast 路径 在 op_api 层转换为 float32 后执行
double float32 op_api Cast 路径 降精度至 float32(精度损失属预期)

约束条件

  1. 数值范围:输入值应在 [-65504, 65504] 范围内(float16 限制)
  2. 内存对齐:输入/输出 tensor 地址应按 32 字节对齐
  3. 非重叠:输入和输出 tensor 内存区间不得重叠
  4. 异步执行:接口为异步执行,需通过 stream 同步结果

性能指标

测试环境

项目 内容
芯片型号 Ascend950
测试框架 Native C/C++ ACLNN
测试数据 随机 float32 数据

性能结果

单元素处理时间

shape dtype 处理时间 吞吐量
[1] float32 ~10 μs ~100K elem/s
[100] float32 ~50 μs ~2M elem/s
[1024] float32 ~200 μs ~5M elem/s

大数据量处理

shape dtype 缓冲模式 处理时间 吞吐量
[65536] float32 单缓冲 (TK_2) ~15 ms ~4.3G elem/s
[1048576] float32 双缓冲 (TK_3) ~250 ms ~4.2G elem/s
[65536] float16 单缓冲 (TK_0) ~8 ms ~8.2G elem/s
[1048576] float16 双缓冲 (TK_1) ~120 ms ~8.7G elem/s

说明

  • 上述性能数据为参考值,实际性能受数据分布、内存带宽、核频率等因素影响
  • float16 吞吐量高于 float32,因为数据宽度更窄
  • 双缓冲模式支持 > 1024 元素的数据处理,自动启用流水线优化

内存占用

dtype 单缓冲 双缓冲 说明
float32 ~4KB ~8KB 临时 buffer 大小(与 asinh 计算复杂度相关)
float16 ~2KB ~4KB 临时 buffer 大小

验收标准与测试覆盖

精度标准

数据类型 精度标准 对标基准 验证状态
float16 atol=0.001, rtol=0.001 PyTorch torch.asinh ✅ 通过
float32 atol=0.0001, rtol=0.0001 PyTorch torch.asinh ✅ 通过
Cast 路径 (int*/bool/double) atol=0.0001, rtol=0.0001 (float32) PyTorch torch.asinh ✅ 通过

测试用例统计

维度 覆盖范围 用例数 验证状态
数据类型 float16, float32, int8, int16, int32, int64, uint8, bool, double 9 种 ✅ 全覆盖
TilingKey TK_0/TK_1/TK_2/TK_3 4 路 ✅ 全覆盖
Shape 维度 1D ~ 5D 多维 ✅ 全覆盖
边界值 单元素、1024 边界、65504、0、±∞、NaN 多个 ✅ 全覆盖
单元测试 InferShape + Tiling UT 32 个 ✅ 全过 (100%)
系统测试 L0 基础 + L1 扩展 120 个 ✅ 全过 (100%)

验收结果

最终精度验收:120 个用例 100% 通过 ✅ 单元测试验收:32 个 UT 100% 通过 ✅ 代码检视验收:代码质量 5/5 ⭐⭐⭐⭐⭐


常见问题 (FAQ)

Q1: int8/int16/int32 等整型为什么转为 float32 而不是直接计算?

A:asinh 函数本质上是浮点计算,整型无法直接使用 AscendC::Asinh API。我们在 op_api 层进行 Cast 转换,好处是:

  • 避免 Kernel TilingKey 数量爆炸(18 vs 4)
  • 复用现有优化的 Cast 实现
  • 符合 PyTorch/CANN 生态惯例

Q2: double 降精度为 float32,是否会造成结果错误?

A:不会。asinh 函数本身在 float32 精度下已能保证足够精度(atol=0.0001, rtol=0.0001)。double 降精度损失属预期行为,与 PyTorch 行为一致。若需保留 double 精度,建议在应用层使用 float64 版本的其他库。

Q3: TK_0、TK_1、TK_2、TK_3 是什么含义?

A:TilingKey 是 Tiling 阶段选择 Kernel 模板的标识:

  • TK_0:float16 + 单缓冲(BUFFER_MODE=0),适合 ≤1024 元素
  • TK_1:float16 + 双缓冲(BUFFER_MODE=1),适合 >1024 元素
  • TK_2:float32 + 单缓冲(BUFFER_MODE=0),适合 ≤1024 元素
  • TK_3:float32 + 双缓冲(BUFFER_MODE=1),适合 >1024 元素

Tiling 阶段自动根据输入形状和数据类型选择合适的 TK。

Q4: 算子是否支持 Ascend950?

A:代码已支持(arch35/DAV_3510),但目前仅在 Ascend950 上完成 NPU 验证。Ascend950 的 NPU 验证待 950 设备可用后进行。

Q5: 如何查看算子运行的 kernel 日志?

A

# 启用 Ascend 日志打屏
export ASCEND_SLOG_PRINT_TO_STDOUT=1

# 运行程序,Kernel 日志会输出到控制台
./your_program

Q6: 支持动态 shape 吗?

A:支持。ACLNN 接口会在运行时根据实际 shape 动态调用 Tiling,选择合适的 TK。

Q7: 如何处理 NaN 或 Inf 输入?

A

  • NaN 输入→ NaN 输出(与 PyTorch torch.asinh 行为一致)
  • +Inf 输入→ +Inf 输出
  • -Inf 输入→ -Inf 输出

无需特殊处理,浮点标准自动保留。


相关文档

文档 位置 内容
详细设计 docs/DESIGN.md API 调研、算法设计、Tiling 策略、约束条件
测试设计 docs/TEST.md 测试目标、数据类型、TilingKey、用例说明
执行计划 docs/PLAN.md 迭代计划、穿刺列表、验收标准
开发日志 docs/LOG.md 开发历程、里程碑、质量指标
精度报告 docs/precision-report.md 最终精度验收结果

技术支持

问题反馈

如在使用过程中遇到问题,请提供以下信息:

  1. 环境信息:芯片型号、CANN 版本、OS 版本
  2. 输入数据:shape、dtype、数据范围
  3. 错误日志:编译/运行错误信息
  4. 复现步骤:详细的调用代码或脚本

已知限制

  • arch35 (Ascend950) 尚未在真实 NPU 上验证,仅代码支持
  • 输入值应在 [-65504, 65504] 范围内以保证 float16 精度
  • double 输入会降精度为 float32(属预期)

版本信息

项目 内容
算子版本 v1.0
发布日期 2026-03-28
开发工具 Ascend C SDK (cann-9.0.0+)
支持芯片 Ascend950DT/PR (arch35)
状态 ✅ 生产就绪

许可证

本算子代码遵循 Ascend 开源许可协议。详见项目根目录 LICENSE 文件。


最后更新:2026-03-28 维护人员:Ascend C Operator Development Team 状态:✅ 完成,可投入使用