拓冰建站拓冰建站
首页 / 资讯中心 / 正文

CANN ops-math 算子 AsinGrad 深度解析:aclnn 两段式接口调用与 NPU 反向梯度实现

CANN ops-math 算子 AsinGrad 深度解析aclnn 两段式接口调用与 NPU 反向梯度实现【免费下载链接】ops-math本项目是CANN提供的数学类基础计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-math导读本文围绕 CANN 开源数学算子库 ops-math 中的 AsinGrad 算子展开完整讲解反正弦函数 Asin 反向梯度的数学原理、aclnnAsinGrad 两段式接口的调用方式与参数约束并结合仓库中的算子定义、Shape 推导、Tiling 切分与 Kernel 实现源码剖析其在 Atlas A2/A3 系列产品上的真实计算路径。读完本文你将掌握 AsinGrad 算子的完整使用姿势并能从算子定义、调度到向量指令三级理解这类逐元素反向梯度算子的落地方法。算子概述与产品支持AsinGrad 是 CANN ops-math 仓库experimental/math/asin_grad中面向昇腾 NPU 的数学类基础算子用于计算Asin反正弦函数的反向梯度是神经网络训练中链式求导回传链路上的一环。仓库中该算子的宿主侧文档为 README.md接口级说明见 aclnnAsinGrad.md。产品支持情况如下产品是否支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品√Atlas A2 训练系列产品 / Atlas A2 推理系列产品√该支持情况在算子定义文件 asin_grad_def.cpp 中也有对应证据AICore 侧通过aiCore.AddConfig(ascend910b)与aiCore.AddConfig(ascend910_93)显式注册了两种昇腾 AI Core 配置分别对应 A2910B与 A3910_93系列产品。功能说明与数学原理计算公式AsinGrad 算子的功能是计算反正弦函数Asin的反向梯度计算公式为z dy / sqrt(1 - y * y)其中y表示 Asin 反向计算的输入张量即前向asin的输入也就是反向时需要代入梯度公式的中间变量dy表示上游梯度张量z表示输出梯度张量。数学推导该公式源于反正弦函数的导数。对f(x) asin(x)有f(x) 1 / sqrt(1 - x²)。在反向传播中若上游梯度为dy则对输入y的梯度为dz/dy dy * f(y) dy / sqrt(1 - y²)由于梯度公式中只涉及逐元素乘法、减法、sqrt与除法AsinGrad 本质上是一个逐元素elementwise算子计算密度低、数据搬运占比高因此其性能优化重点在于 Tiling 切分与多核并行这一点会在下文源码剖析中看到。Kernel 中的实现对应关系在 asin_grad.h 的 Kernel 实现中公式被分解为五条向量指令逐步完成Mul(yLocal, yLocal, yLocal, n); // y * y Muls(yLocal, yLocal, -1.0f, n); // -y * y Adds(yLocal, yLocal, 1.0f, n); // 1 - y * y Sqrt(yLocal, yLocal, n); // sqrt(1 - y*y) Div(zLocal, dyLocal, yLocal, n); // dy / sqrt(1 - y*y)每条指令之间通过PipeBarrierPIPE_V()插入向量流水线屏障保证数据依赖正确。参数说明参数名输入/输出/属性描述数据类型数据格式Shape 规格y输入表示 Asin 反向计算的输入张量对应计算公式中的y。FLOAT、FLOAT16、BFLOAT16ND0-8 维dy输入表示上游梯度张量对应计算公式中的dy。数据类型与y保持一致NDShape 与y保持一致z输出表示输出梯度张量对应计算公式中的z。数据类型与y保持一致NDShape 与y保持一致上述数据类型与格式约束在算子定义文件中有直接的源码佐证asin_grad_def.cpp 中对y、dy、z三个张量统一声明了ge::DT_FLOAT / ge::DT_FLOAT16 / ge::DT_BF16三种数据类型与ge::FORMAT_ND格式并声明为REQUIRED必选且开启AutoContiguous()自动连续化处理。约束说明使用 AsinGrad 算子时必须满足以下约束y、dy、z的数据类型需要保持一致支持 FLOAT、FLOAT16、BFLOAT16。y、dy、z的 shape 需要保持一致不支持 broadcast。仅支持 ND 数据格式。支持 0-8 维输入。精度路径差异FLOAT16 路径在 half 精度上直接计算BFLOAT16 路径将输入转换为 FLOAT 后计算再将结果转换回 BFLOAT16。当1 - y * y小于 0 或分母为 0 时结果遵循硬件sqrt和div指令对 NaN/Inf 的处理行为即不做额外钳位或特殊处理。约束在源码中的体现这些约束并非仅停留在文档层面而是被层层落实到了算子实现中Shape 一致性校验Tiling 阶段 asin_grad_tiling.cpp 的CheckInput会逐一比对y、dy、z的 origin shape不一致时直接返回失败维度数超过MAX_DIM_COUNT 8同样报错。数据类型一致性校验CheckInput中通过IsSupportedDtype检查y的数据类型并强制dy、z与y的类型一致。Shape 推导asin_grad_infershape.cpp 中的InferShape4AsinGrad直接执行*zShape *yShape从图编译层面保证输出与输入 shape 完全一致。精度路径分工asin_grad.cpp 的 kernel 入口使用if constexpr (std::is_same_vD_T_Y, float)在编译期分流FLOAT 走KernelAsinGradFp32FLOAT16 与 BFLOAT16 走KernelAsinGradCast后者内部再次以std::is_same_vT, half区分——half 直接计算bfloat16 则先Cast到 float32 计算、最后用Cast(..., RoundMode::CAST_RINT, ...)转回。aclnnAsinGrad 两段式接口说明接口调用模型与 CANN 算子库中所有 aclnn 接口一致AsinGrad 采用两段式接口第一段aclnnAsinGradGetWorkspaceSize完成入参校验获取计算所需的 workspace 大小并创建包含算子计算流程的执行器executor第二段aclnnAsinGrad使用第一段返回的 workspace 与 executor 在指定 Stream 上真正执行计算。函数原型如下aclnnStatus aclnnAsinGradGetWorkspaceSize( const aclTensor *y, const aclTensor *dy, aclTensor *z, uint64_t *workspaceSize, aclOpExecutor **executor); aclnnStatus aclnnAsinGrad( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, const aclrtStream stream);aclnnAsinGradGetWorkspaceSize 参数说明参数名输入/输出描述使用说明数据类型数据格式维度 / (shape)非连续 Tensoryconst aclTensor*输入表示 Asin 反向计算的输入张量对应计算公式中的y。支持空 Tensor数据类型、数据格式和 shape 需与dy、z保持一致。FLOAT、FLOAT16、BFLOAT16ND0-8 维√dyconst aclTensor*输入表示上游梯度张量对应计算公式中的dy。支持空 Tensor数据类型、数据格式和 shape 需与y、z保持一致。数据类型与y保持一致NDShape 与y保持一致√zaclTensor*输出表示输出梯度张量对应计算公式中的z。支持空 Tensor数据类型、数据格式和 shape 需与y、dy保持一致。数据类型与y保持一致NDShape 与y保持一致√workspaceSizeuint64_t*输出返回需要在 Device 侧申请的 workspace 大小。-----executoraclOpExecutor**输出返回 op 执行器包含了算子计算流程。-----返回值与错误码两段接口均返回aclnnStatus状态码具体参见 aclnn 返回码。第一段接口完成入参校验以下场景会报错返回值错误码描述ACLNN_ERR_PARAM_NULLPTR161001y、dy、z、workspaceSize或executor存在空指针。ACLNN_ERR_PARAM_INVALID161002y、dy或z的数据类型不在支持范围内。ACLNN_ERR_PARAM_INVALID161002y、dy和z的数据类型不一致。ACLNN_ERR_PARAM_INVALID161002y、dy和z的 shape 不一致。ACLNN_ERR_PARAM_INVALID161002y、dy或z的维度超过 8 维。这套校验逻辑在 UT 中也有对应实现可查证单元测试 test_aclnn_asin_grad.cpp 的 mock 版aclnnAsinGradGetWorkspaceSize依次检查空指针返回ACLNN_ERR_PARAM_NULLPTR、维度数超限、数据类型不一致、shape 不一致均返回ACLNN_ERR_PARAM_INVALID与文档错误码表格逐条对应。aclnnAsinGrad 参数说明参数名输入/输出描述workspace输入在 Device 侧申请的 workspace 内存地址。workspaceSize输入在 Device 侧申请的 workspace 大小由第一段接口 aclnnAsinGradGetWorkspaceSize 获取。executor输入op 执行器包含了算子计算流程。stream输入指定执行任务的 Stream。确定性说明aclnnAsinGrad 为默认确定性实现文档明确声明即相同输入在多次执行中输出可复现。从实现看AsinGrad 为纯逐元素算子、不含任何归约或原子操作多核切分不引入跨核依赖天然具备确定性。调用示例与完整运行流程两段式接口的核心调用骨架// 调用 aclnnAsinGrad 第一段接口 uint64_t workspaceSize 0; aclOpExecutor *executor nullptr; auto ret aclnnAsinGradGetWorkspaceSize(y, dy, z, workspaceSize, executor); // 根据第一段接口返回的 workspaceSize 申请 workspace并调用第二段接口执行计算 void *workspaceAddr nullptr; if (workspaceSize 0) { ret aclrtMalloc(workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); } ret aclnnAsinGrad(workspaceAddr, workspaceSize, executor, stream);完整可运行示例仓库提供了完整的端到端调用样例 test_aclnn_asin_grad.cpp其运行流程如下运行时初始化aclInit(nullptr)→aclrtSetDevice(deviceId)→aclrtCreateStream(state.stream)设备号优先从环境变量ACL_DEVICE_ID读取缺省为 0。构造输入数据示例采用 shape 为{4}的一维张量输入y {-0.5, 0.0, 0.5, 0.75}、上游梯度dy {1.0, 2.0, -1.0, 0.5}并在 Host 侧同步计算期望输出expected[i] dy[i] / sqrt(1 - y[i]*y[i])用于结果校验。创建 aclTensor通过aclCreateTensor创建 ND 格式ACL_FORMAT_ND的y、dy、z张量描述strides 由MakeStrides按连续排布计算数据通过aclrtMallocaclrtMemcpyACL_MEMCPY_HOST_TO_DEVICE拷入 Device。两段式执行先调aclnnAsinGradGetWorkspaceSizeworkspaceSize 0时用aclrtMalloc(..., ACL_MEM_MALLOC_HUGE_FIRST)申请 workspace再调aclnnAsinGrad最后aclrtSynchronizeStream同步等待执行完成。结果校验与清理aclrtMemcpyACL_MEMCPY_DEVICE_TO_HOST回拷输出与期望值按1e-4容差比对CheckOutput随后依次释放 workspace、设备内存、张量描述与 StreamaclrtResetDeviceaclFinalize收尾。该样例同时验证了算子对非连续 Tensor 的支持路径aclCreateTensor传入独立 strides 数组这一点与接口文档中非连续 Tensor√的标注一致。编译算子包从仓库根目录可使用如下命令编译算子包注意--experimental标志AsinGrad 位于实验特性目录下bash build.sh --pkg --experimental --socascend910b --opsasin_grad -j16 bash build.sh --pkg --experimental --socascend910_93 --opsasin_grad -j16其中ascend910b对应 Atlas A2 系列、ascend910_93对应 Atlas A3 系列与产品支持表及算子定义中的 AICore 配置一一对应。该算子的编译接入通过 CMakeLists.txt 中的add_all_modules_sources(OPTYPE asin_grad ACLNNTYPE aclnn)完成即同时注册了 op 算子类型与 aclnn 接口类型。源码级实现剖析算子定义OpDefasin_grad_def.cpp 中通过OP_ADD(AsinGrad)注册算子为y、dy、z统一设置REQUIRED参数类型、三种浮点数据类型与 ND 格式并声明ascend910b、ascend910_93两个 AICore 配置。Shape 推导InferShapeasin_grad_infershape.cpp 的InferShape4AsinGrad从输入 0y拷贝 shape 到输出 0z从编译图层面保证输出与y同 shape、不支持 broadcast这一约束。Tiling 切分Host 侧Tiling 逻辑集中在 asin_grad_tiling.cpp核心策略为多核均分 尾核处理按totalLength / coreNum计算每核基准长度向上对齐到 cache line512B对应的元素数CACHE_LINE_BYTE_LENGTH同时保证每核至少处理MIN_CORE_BYTES 4096字节最后生成formerNum前序核数、formerLength前序核长度与tailLength尾核长度三段式切分参数并通过SetBlockDim(usedCoreNum)设置实际使用的核数。UB 内 Tile 尺寸tileLength ubSize / 缓冲区系数其中 FP16 缓冲区系数为 16、FLOAT 为 28HALF_BUFFER_COEFFICIENT/FLOAT_BUFFER_COEFFICIENT再向下对齐到 32B 对齐元素数——之所以同时考虑 T 类型 DMA 拷贝与 FP32 计算的对齐是因为 BFLOAT16 路径需要在 FP32 缓冲区上计算见 asin_grad_tiling.cpp 中的注释。Workspace 申请GetWorkspaceSize通过平台接口GetLibApiWorkSpaceSize()查询并上报 lib API 所需的 workspace 大小返回给第一段接口的workspaceSize。空 Tensor 处理totalLength 0时走FillEmptyTiling仅写空 tiling 数据并SetBlockDim(1)。切分结果写入 asin_grad_tiling_data.h 定义的AsinGradTilingData结构体formerNum/formerLength/tailLength/tileLength/dtypeId通过REGISTER_TILING_DEFAULT注册后由 kernel 侧读取。Kernel 实现Device 侧Kernel 入口 asin_grad.cpp 根据模板参数D_T_Y在编译期选择实现类核心逻辑在 asin_grad.h基类AsinGradKernelBase负责 GM↔UB 数据搬运与流水线管理。CopyIn使用双缓冲队列BUFFER_NUM 2并发搬运y、dy两个输入尾块不足 32B 对齐时用DataCopyPad/DataCopyPadExtParams补零填充Process通过ProcessTiles按 tile 循环执行CopyIn → Compute → CopyOut充分利用向量流水线InitBlockGm依据formerNum/formerLength/tailLength计算当前核的 GM 偏移。KernelAsinGradFp32FLOAT 路径直接复用yLocal缓冲区原地完成y*y → -y*y → 1-y*y → sqrt → div五步节省一个 UB 缓冲区。KernelAsinGradCastFP16/BF16 路径half 直接计算bfloat16 则在InitExtraBuffers中额外申请三个 VECCALC 位置的 FP32 缓冲区先Cast(yFp32, yLocal, RoundMode::CAST_NONE, ...)升精度计算最终以RoundMode::CAST_RINT舍入模式转回 BF16 输出。这与文档中BFLOAT16 路径将输入转换为 FLOAT 后计算再将结果转换回 BFLOAT16的约束描述完全吻合。单元测试验证仓库在 tests/ut/op_api/test_aclnn_asin_grad.cppaclnn 接口层与 tests/ut/op_host/test_asin_grad_tiling.cppTiling 层提供 UT。aclnn 层测试通过op::SetPlatformSocVersion(op::SocVersion::ASCEND910B)指定平台后覆盖 FP32 成功路径case_001_fp32_success以及空指针、类型不一致、shape 不一致、超维度等异常入参分支可作为理解接口校验语义与自行扩展测试的参考。总结与扩展建议AsinGrad 是一个结构清晰、约束明确的逐元素反向梯度算子数学上等价于dy / sqrt(1 - y*y)工程上由 OpDef 定义 → InferShape 推导 → Tiling 切分 → AscendC Kernel 计算四层构成并通过 aclnn 两段式接口对外暴露。其三种精度的差异化计算路径FP32 原地计算、FP16 直接计算、BF16 升精度计算、基于formerNum/formerLength/tailLength的多核切分模型以及双缓冲 尾块填充的搬运策略均值得作为编写同类 elementwise 反向算子的参考范式。如需在 AtanGrad、AcosGrad 等同类三角/反三角算子中复用该模式可重点参考 asin_grad.h 的基类设计若希望为本算子贡献功能增强或修复请先阅读仓库贡献指南 CONTRIBUTING.md 与文档贡献说明 CONTRIBUTING_DOCS.md。【免费下载链接】ops-math本项目是CANN提供的数学类基础计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-math创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门