十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CANN ops-nn 算子实战:aclnnEluBackward 两段式接口剖析与 ELU 反向梯度计算指南

CANN ops-nn 算子实战:aclnnEluBackward 两段式接口剖析与 ELU 反向梯度计算指南 人工智能算子库深度学习CANNAscend【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址https://gitcode.com/cann/ops-nn点击查看免费下载ELUExponential Linear Unit激活函数的反向传播是神经网络训练中的高频算子。本文基于 CANN 开源算子库 ops-nn 中experimental/activation/elu_grad_v2模块的官方接口文档结合仓库源码、示例与单测系统讲解aclnnEluBackward两段式接口的调用方式、参数约束、底层实现原理与精度行为帮助开发者快速在 Atlas A2 系列产品上完成 ELU 反向梯度的接入与验证。一、算子概述与产品支持情况aclnnEluBackward是 CANN 为 EluGradV2 算子提供的单算子 APIaclnn 接口用于完成 ELU 激活函数的反向计算给定上游梯度gradOutput与 ELU 前向的输入或输出计算前向输入对应的梯度gradInput。该算子已注册ascend910bAICore 配置产品支持情况如下产品是否支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品支持当前算子代码已注册ascend910bAICore 配置见 elu_grad_v2_def.cpp即面向昇腾 910B 系列芯片的 AICore 实现。二、功能说明与计算公式2.1 输入语义gradOutput上游梯度即损失对 ELU 输出的偏导dyselfOrResult当isResultfalse时表示 ELU 前向输入x当isResulttrue时表示 ELU 前向输出即elu(x)的结果。由于 ELU 前向输出与输入在正区间数值一致反向计算可以复用前向输出从而避免在前向输入不可得如内存释放、in-place 场景时额外保存输入张量。这一点与 PyTorch 等框架中backward 可基于 saved input 或 saved output 计算的惯例一致。2.2 计算公式记α为 ELU 激活系数alphascale为输出缩放系数inputScale为输入缩放系数isResult表示selfOrResult是否为前向输出。当selfOrResult 0时$$ gradInput gradOutput \times scale $$当selfOrResult \le 0且isResult false传入前向输入时$$ gradInput gradOutput \times \alpha \times scale \times inputScale \times \exp(selfOrResult \times inputScale) $$当selfOrResult \le 0且isResult true传入前向输出时$$ gradInput gradOutput \times inputScale \times (selfOrResult \alpha \times scale) $$公式推导演示标准 ELU 前向定义为 $elu(x) x \ (x0)$$elu(x) \alpha(e^{x}-1) \ (x \le 0)$。若不考虑 scale其导数为 $elu(x)1 \ (x0)$$elu(x)\alpha e^{x} \ (x \le 0)$。当传入前向输出 $oelu(x)$ 时$e^{x}o/\alpha1$于是负区间导数可改写为 $\alpha e^{x} o \alpha$。引入输入缩放inputScale作用于前向计算中的指数项与输出缩放scale后即得到上文三种分支的公式。2.3 与源码的印证在 Kernel 侧实现 elu_grad_v2.h 中tiling 数据被预计算为factorPos_ tilingData-scale; factorNeg_ tilingData-alpha * tilingData-scale * tilingData-inputScale; inputScale_ tilingData-inputScale; factorNegBias_ (inputScale_ 0.0F) ? 0.0F : (factorNeg_ / inputScale_);其中factorPos_对应正区间的scalefactorNeg_对应负区间的α × scale × inputScale而factorNegBias_ α × scale正是 result 模式isResulttrue下$\alpha \times scale$这一项之后 kernel 通过Adds Muls Mul完成gradOutput × inputScale × (selfOrResult α × scale)的计算。由此可见公式中的三个分支在 ComputeFloatResultMode / ComputeFloatExpMode 等 Kernel 计算函数中有精确的一一对应实现。三、函数原型两段式接口该算子遵循 CANN aclnn 单算子 API 的两段式接口规范必须先调用第一段aclnnEluBackwardGetWorkspaceSize获取计算所需的 workspace 大小与执行器再按该大小在 Device 侧申请内存后调用第二段aclnnEluBackward执行计算。aclnnStatus aclnnEluBackwardGetWorkspaceSize( const aclTensor* gradOutput, const aclScalar* alpha, const aclScalar* scale, const aclScalar* inputScale, bool isResult, const aclTensor* selfOrResult, aclTensor* gradInput, uint64_t* workspaceSize, aclOpExecutor** executor);aclnnStatus aclnnEluBackward( void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream);说明workspace 是除输入/输出外算子在 NPU 上完成计算所需的临时内存workspaceSize表示其大小。第二段接口不能重复调用即不允许GetWorkspaceSize → 执行 → 再执行的模式详见 两段式接口说明。在 Host 侧入口实现 aclnn_elu_backward.cpp 中第一段接口的执行流程为创建aclOpExecutor→ 参数校验 → 空 tensor 提前返回 → 将输入转为连续 tensorl0op::Contiguous→ 通过l0op::EluGradV2将算子加入 AICore 任务队列 → 结果Cast到gradInput的 dtype →ViewCopy写回输出 → 汇总返回 workspace 大小。第二段接口则调用框架能力CommonOpExecutorRun完成实际计算见 aclnn_elu_backward.cpp。四、aclnnEluBackwardGetWorkspaceSize 参数说明参数名输入/输出描述数据类型数据格式shape 约束非连续 TensorgradOutput输入ELU 反向的上游梯度FLOAT、FLOAT16、BFLOAT16推荐ND与selfOrResult、gradInputshape 完全一致维度数不超过 8支持alpha输入ELU 激活系数可转换为FLOAT的aclScalar-标量-scale输入输出缩放系数可转换为FLOAT的aclScalar-标量-inputScale输入输入缩放系数可转换为FLOAT的aclScalar-标量-isResult输入false表示selfOrResult为前向输入true表示selfOrResult为前向输出bool-标量-selfOrResult输入ELU 前向输入或前向输出FLOAT、FLOAT16、BFLOAT16且必须与gradOutputdtype 一致推荐ND与gradOutput、gradInputshape 完全一致维度数不超过 8支持gradInput输出反向计算输出即对前向输入的梯度需为gradOutput可转换到的类型通常与gradOutput保持一致推荐ND与gradOutput、selfOrResultshape 完全一致维度数不超过 8支持workspaceSize输出返回需要在 Device 侧申请的 workspace 大小uint64_t*---executor输出返回算子执行器包含计算流程aclOpExecutor**---4.1 参数约束与补充说明gradOutput、selfOrResult的 dtype 必须一致当前支持FLOAT16、FLOAT、BFLOAT16。gradOutput、selfOrResult、gradInput的 shape 必须一致不支持 broadcast。当isResulttrue时alpha不能小于 0。推荐输入输出使用ND格式接口内部会自动将非连续输入转为连续 tensor 处理l0op::Contiguous。三个标量属性alpha、scale、inputScale的默认值均为 1.0见 elu_grad_v2_def.cpp 中Attr(...).Float(1.0)/.Bool(false)的定义。在 Host 侧参数校验aclnn_elu_backward.cpp中上述约束被逐项落地CheckNotNull校验空指针CheckDtypeValid校验 dtype 一致性与支持列表BF16 仅在 DAV_2201 架构或 regbase 场景下开放、校验alpha/scale/inputScale能否转换为FLOAT、校验gradOutput能否 Cast 到gradInput类型CheckShape校验 shape 一致与维度数不超过 8MAX_DIM_LEN 8CheckAttributeValue校验isResulttrue时alpha ≥ 0。若输入为FORMAT_FRACTAL_NZ格式接口会打印警告提示可能存在精度风险。4.2 返回值说明aclnnStatus返回状态码具体可参考 aclnn 返回码。第一段接口会完成参数校验典型错误场景如下返回码错误码说明ACLNN_ERR_PARAM_NULLPTR161001gradOutput、alpha、scale、inputScale、selfOrResult、gradInput、workspaceSize或executor为空指针ACLNN_ERR_PARAM_INVALID161002gradOutput/selfOrResultdtype 不受支持ACLNN_ERR_PARAM_INVALID161002gradOutput与selfOrResultdtype 不一致ACLNN_ERR_PARAM_INVALID161002gradOutput、selfOrResult、gradInputshape 不一致ACLNN_ERR_PARAM_INVALID161002输入维度数超过 8ACLNN_ERR_PARAM_INVALID161002alpha、scale、inputScale不能转换为FLOATACLNN_ERR_PARAM_INVALID161002isResulttrue且alpha0此外当gradOutput为空 tensorshape 含 0时第一段接口直接返回ACLNN_SUCCESSworkspaceSize置 0见 aclnn_elu_backward.cpp。五、aclnnEluBackward 参数说明参数名输入/输出描述workspace输入在 Device 侧申请的 workspace 内存地址workspaceSize输入Device 侧申请的 workspace 大小由aclnnEluBackwardGetWorkspaceSize返回executor输入算子执行器包含完整计算流程stream输入指定执行任务的aclrtStream返回值为aclnnStatus具体可参考 aclnn 返回码。六、调用示例可编译运行示例代码位于 examples/test_aclnn_elu_grad_v2.cpp完整的编译与执行流程请参考编译与运行样例。下面给出核心调用流程解析。6.1 初始化与 tensor 构造首先完成 ACL 环境初始化固定写法并构造输入输出张量与三个标量int32_t deviceId 0; aclrtStream stream; auto ret Init(deviceId, stream); // aclInit / aclrtSetDevice / aclrtCreateStream std::vectorint64_t gradOutputShape {2, 2}; std::vectorint64_t selfOrResultShape {2, 2}; std::vectorint64_t gradInputShape {2, 2}; std::vectorfloat gradOutputHostData {-2, -1, 0, 1}; std::vectorfloat selfOrResultHostData {-2, -1, 0, 1}; std::vectorfloat gradInputHostData {0, 0, 0, 0}; float alphaValue 1.0f; float scaleValue 1.0f; float inputScaleValue 1.0f; bool isResult true;随后通过aclrtMalloc申请 Device 侧内存、aclrtMemcpy将 Host 数据拷贝到 Device再调用aclCreateTensor创建aclTensorACL_FORMAT_ND格式调用aclCreateScalar创建三个标量。示例中alphascaleinputScale1.0、isResulttrue此时根据 result 模式公式负区间梯度为gradInput gradOutput × (selfOrResult 1)例如输入gradOutput-2, selfOrResult-2时结果应为-2 × (-2 1) 2。6.2 两段式调用与结果获取uint64_t workspaceSize 0; aclOpExecutor* executor; // 第一段获取 workspace 大小与执行器 ret aclnnEluBackwardGetWorkspaceSize(gradOutput, alpha, scale, inputScale, isResult, selfOrResult, gradInput, workspaceSize, executor); CHECK_RET(ret ACL_SUCCESS, ...); // 按需申请 workspace 内存 void* workspaceAddr nullptr; if (workspaceSize 0) { ret aclrtMalloc(workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret ACL_SUCCESS, ...); } // 第二段执行计算 ret aclnnEluBackward(workspaceAddr, workspaceSize, executor, stream); CHECK_RET(ret ACL_SUCCESS, ...); // 同步等待任务执行结束 ret aclrtSynchronizeStream(stream); // 将结果从 Device 拷贝回 Host 并打印 aclrtMemcpy(resultData.data(), ..., gradInputDeviceAddr, ..., ACL_MEMCPY_DEVICE_TO_HOST);最后依次aclDestroyTensor/aclDestroyScalar释放张量与标量aclrtFree释放 Device 内存与 workspace并aclrtDestroyStream、aclrtResetDevice、aclFinalize完成资源回收。示例完整代码可参考 test_aclnn_elu_grad_v2.cpp。七、底层实现原理从 Host 到 Kernel 的完整链路7.1 Host 侧算子定义、推导与 tilingEluGradV2 在 Host 侧由三个文件协同完成算子定义elu_grad_v2_def.cpp声明输入dy、x输出y属性alpha、scale、input_scale、is_result。值得注意的是OpDef 通过位置索引匹配 dtype因此 mixed-output输入低精度、输出 float32场景被显式枚举支持(fp16,fp16,fp16)、(fp16,fp16,fp32)、(fp32,fp32,fp32)、(bf16,bf16,bf16)、(bf16,bf16,fp32)五种组合。shape/dtype 推导elu_grad_v2_infershape.cpp输出 shape 直接拷贝输入dy的 shape若输出 dtype 未指定则继承输入 dtype。tiling 计算elu_grad_v2_tiling.cpp根据输入 dtype、总长度、属性值与 UB 容量决策核心数最多 64 个 AIV 核、单核数据量、tile 大小、是否开启双缓冲bufferOpen并选择调度模式schMode。7.2 tiling 的多种调度模式Host 侧根据数据规模与 dtype 选择不同的调度路径对应 elu_grad_v2_tiling.cppsmall fast path总长度不超过ELU_GRAD_V2_CORE_CHUNK1024 元素时走 single-tile 路径单核直接处理float16 aligned fast pathFLOAT16且alphascaleinputScale1、isResultfalse且总长度按块对齐、不小于 4×1024 时走FLOAT16_EXP_FAST专用路径bfloat16 aligned fast pathBF16且总长度按块对齐时走MIXED_EXP_FAST/MIXED_RESULT_FAST专用路径generic 路径其余场景按SAFE_EXP/SAFE_RESULT模式依据avgCoreData与目标 tile 数的比较决定是否开启双缓冲多级流水。调度模式由 tiling keyGET_TPL_TILING_KEY(schMode)传给 KernelKernel 入口 elu_grad_v2.cpp 通过if constexpr (schMode ...)在编译期分派到对应的 Kernel 模板类KernelEluGradV2、KernelEluGradV2SingleTile、KernelEluGradV2MixedAlignedFast、KernelEluGradV2Float16AlignedFast、KernelEluGradV2ResultMixedOutput。7.3 Kernel 侧精度策略与计算流程Kernel 实现见 elu_grad_v2.h核心设计如下多核切分按coreNum将数据均分前bigCoreNum个核处理bigCoreDataNum元素其余核处理smallCoreDataNum元素末核以lastCoreDataNum兜底处理尾部流水线开启双缓冲时采用CopyIn(i) → Compute(i-1) → CopyOut(i-2)三级交错流水见Process()elu_grad_v2.h隐藏搬运与计算延迟精度策略对float16/bfloat16通用路径先将输入Cast提升到float32计算Exp、Mul、Adds、Select等运算均在 float32 下完成最后CastROUND_RINT取整模式回原精度兼顾了低精度下的计算精度正负分支合并通过CompareScalar(act, 0, CMPMODE::LE)生成掩码Select在正区间结果gradOutput × scale与负区间结果之间按元素选择单次遍历即可完成整个张量的计算单位系数优化kernel 通过IsNearlyOne判断scale、inputScale等系数是否为 1跳过对应的Muls/Exp等运算减少不必要的向量指令。八、单元测试与验证仓库在 tests/ut 下按 Host 侧与 API 侧组织测试其中 op_api 测试 test_aclnn_elu_backward.cpp 覆盖了以下场景用例验证内容case_001_float32_workspace_successFLOAT输入、alpha1.3, scale0.8, inputScale1.1、isResultfalse时第一段接口返回成功case_002_float16_workspace_successFLOAT16输入、默认系数、isResultfalse时接口成功case_003_bfloat16_workspace_success_on_910bBF16仅在ASCEND910B/ASCEND910_93平台上返回成功其余平台返回ACLNN_ERR_PARAM_INVALIDcase_004_nullptr_validation任一核心参数传nullptr返回ACLNN_ERR_PARAM_NULLPTRcase_005_dtype_validation不支持的 dtype如ACL_DOUBLE或gradOutput/selfOrResultdtype 不一致返回ACLNN_ERR_PARAM_INVALIDcase_006_shape_and_dim_validationshape 不一致或维度数超过 8 返回ACLNN_ERR_PARAM_INVALIDcase_007_negative_alpha_rejected_for_result_modeisResulttrue且alpha0返回ACLNN_ERR_PARAM_INVALIDcase_008_empty_tensor_success空 tensor 输入直接返回ACLNN_SUCCESS这些测试用例与第 4.2 节的返回码表格一一对应同时印证了第 7.1 节所述的 dtype 支持情况BF16 依赖平台判断。除 API 侧测试外仓库还提供 op_host 的 infershape/tiling 测试与 op_kernel 的核函数测试见 tests/ut 与 tests/ut可参考 tests/ut 目录下的构建说明进行本地验证。九、使用注意事项调用顺序必须严格遵循先 GetWorkspaceSize后执行的两段式顺序且第二段接口不可重复调用。dtype 一致性gradOutput与selfOrResultdtype 必须一致gradInput通常与gradOutput保持一致接口内部会自动完成 Cast。shape 严格一致三个 tensor shape 必须完全相同不支持 broadcast维度数不超过 8。isResulttrue与alpha的关系result 模式下alpha必须 ≥ 0若确实需要负斜率请使用isResultfalse传入前向输入的 out-of-place 版本。workspace 内存仅当workspaceSize 0时才需要申请申请后务必在结束时释放。BF16 平台限制BFLOAT16仅在 Atlas A2如 910B等支持平台上可用非支持平台会返回ACLNN_ERR_PARAM_INVALID。编译运行示例的编译与执行请参考编译与运行样例其中详细说明了 aclnn 样例的构建方式与依赖环境。赞分享人工智能算子库深度学习CANNAscend【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址https://gitcode.com/cann/ops-nn点击查看免费下载相关推荐CANN ops-nn 算子接口解析aclnnEluBackward 两段式调用与 ELU 反向梯度计算CANN ops nn 算子接口解析aclnnEluBackward 两段式调用与 ELU 反向梯度计算 本篇技术指南聚焦 CANN 神经网络算子库 ops人工智能算子库深度学习CANNAscendCANN ops-nn 算子解析aclnnSeluBackward 两段式接口实现 SELU 反向梯度计算CANN ops nn 算子解析aclnnSeluBackward 两段式接口实现 SELU 反向梯度计算 aclnnSeluBackward 是 CANN人工智能算子库深度学习CANNAscendCANN ops-nn 算子解析aclnnHardswishBackward 两段式 ACLNN 接口实现 HardSwish 反向梯度计算CANN ops nn 算子解析aclnnHardswishBackward 两段式 ACLNN 接口实现 HardSwish 反向梯度计算 导读 aclnn人工智能算子库深度学习CANNAscend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表