CANN ops-nn 的 ApplyFtrl 算子全解析:FTRL-proximal 原地更新原理、aclnn 两段式接口与 ascend910b 原生 AscendC 实现 人工智能算子库深度学习CANNAscend【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址https://gitcode.com/cann/ops-nn点击查看免费下载本文围绕 CANN ops-nn 仓库experimental/optim/apply_ftrl目录下的算子文档 docs/aclnnApplyFtrl.md 展开系统讲解 FTRL-proximalFollow-The-Regularized-Leader参数更新算子的数学原理、GE 图模式接口真值源、本实验扩展新增的派生 aclnn 两段式接口、约束条件与真实可运行的调用示例并结合仓库内 kernel、tiling、op_api 源码剖析其 ascend910bAtlas A2/A3DAV_2201原生 AscendC 实现细节。读完本文你将掌握ApplyFtrl的完整语义、aclnnApplyFtrlGetWorkspaceSize/aclnnApplyFtrl的调用骨架以及如何通过 GE 图模式或 Kernel 直调在真实 NPU 上验证该算子。产品支持情况ApplyFtrl算子在 CANN ops-nn 中的产品支持矩阵如下反映 mainline 本实验扩展的整体支持情况产品是否支持Ascend 950PR/Ascend 950DT√Atlas A3 训练系列产品/Atlas A3 推理系列产品√Atlas A2 训练系列产品/Atlas A2 推理系列产品√Atlas 200I/500 A2 推理产品×Atlas 推理系列产品√Atlas 训练系列产品√实验任务experimental范围本实验目录仅新增ascend910bAtlas A2/A3DAV_2201原生 AscendC kernel。ascend950arch35路径由 mainline optim/apply_ftrl 已提供本任务不改动既有实现。表内√反映ApplyFtrl算子整体mainline 本扩展的产品支持其中 ascend910b 相关能力由本实验算子补齐。功能说明FTRL-proximal 原地更新ApplyFtrl根据 FTRL-proximal 方案原地更新参数张量var并同步原地更新梯度平方累加器accum与校正项linear。该算法常用于带 L1/L2 正则的在线学习 / 大规模稀疏特征推荐、广告 CTR模型的参数更新功能对标tf.raw_ops.ApplyFtrl。计算公式逐元素下式右侧accum/linear/var为更新前值var的更新使用更新后的linear$$ accum_new accum grad \times grad $$$$ linear linear grad - \frac{accum_new^{-lr_power} - accum^{-lr_power}}{lr} \times var $$$$ quadratic \frac{accum_new^{-lr_power}}{lr} 2 \times l2 $$$$ var \begin{cases} \dfrac{sign(linear) \times l1 - linear}{quadratic}, |linear| l1 \[2ex] 0, |linear| \le l1 \end{cases} $$$$ accum accum_new $$其中 $sign(x) \in {-1, 0, 1}$var、accum、linear三者均原地写回。核心逻辑可概括为四步先累加梯度平方更新accum再用新旧累加值的幂差构造linear校正项随后按 L1 软阈值soft-threshold与 L2 二次项计算quadratic门控的分段结果最终把accum、linear、var三个 Ref Tensor 写回原存储。GE 图模式接口真值源ApplyFtrl通过 GE IR 构图下发其接口真值源是 mainline 的算子原型 optim/apply_ftrl/op_graph/apply_ftrl_proto.hREG_OP(ApplyFtrl)本实验复用同名 OpType 与端口结构REG_OP(ApplyFtrl) .INPUT(var, TensorType::NumberType()) .INPUT(accum, TensorType::NumberType()) .INPUT(linear, TensorType::NumberType()) .INPUT(grad, TensorType::NumberType()) .INPUT(lr, TensorType::NumberType()) .INPUT(l1, TensorType::NumberType()) .INPUT(l2, TensorType::NumberType()) .INPUT(lr_power, TensorType::NumberType()) .OUTPUT(var, TensorType::NumberType()) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ApplyFtrl)参数说明参数名输入/输出/属性描述数据类型数据格式var输入Ref原地更新待更新参数张量应来自 Variable。对应公式 var。shape 与 accum/linear/grad 一致。BFLOAT16、FLOAT16、FLOATNDaccum输入Ref原地更新梯度平方累加器应来自 Variable。对应公式 accum要求各元素 ≥ 0。BFLOAT16、FLOAT16、FLOATNDlinear输入Ref原地更新校正项应来自 Variable。对应公式 linear。BFLOAT16、FLOAT16、FLOATNDgrad输入当前步梯度张量。对应公式 grad。BFLOAT16、FLOAT16、FLOATNDlr输入学习率缩放因子标量0-D 或 1 元素。对应公式 lr要求 ≠ 0。BFLOAT16、FLOAT16、FLOATNDl1输入L1 正则化系数标量。对应公式 l1。BFLOAT16、FLOAT16、FLOATNDl2输入L2 正则化系数标量。对应公式 l2。BFLOAT16、FLOAT16、FLOATNDlr_power输入缩放因子的幂次标量。对应公式 lr_power。BFLOAT16、FLOAT16、FLOATNDuse_locking属性是否使用锁机制保护更新操作默认 False。仅支持 False。Bool-var输出更新后的参数张量与输入 var 共享存储。算子仅声明此 1 个输出端口accum、linear 经各自 input ref 端口原地更新。BFLOAT16、FLOAT16、FLOATND图模式构图调用样例GE 图模式构图调用的完整可运行样例见 experimental/optim/apply_ftrl/examples/test_geir_apply_ftrl.cpp与主线 optim/apply_ftrl/examples/test_geir_apply_ftrl.cpp 同构按var → accum → linear → grad → lr → l1 → l2 → lr_power串接 8 个Data输入4 个张量输入同 shape{2, 30}4 个 scalar 输入 shape{1}并调用set_attr_use_locking(false)。样例内部完成GEInitialize、Session建图、RunGraph下发并将输入/输出 dump 为.bin文件便于比对。派生 aclnn 两段式接口本实验新增标准 CANN 未部署标准 CANN OPP 中ApplyFtrl没有已部署的 aclnn 接口ACLNNTYPEaclnn_exclude也没有 PyTorch 等价。本实验扩展通过手写 op_apiop_api/aclnn_apply_ftrl.h op_api/aclnn_apply_ftrl.cpp以及 L0 层 op_api/apply_ftrl.h op_api/apply_ftrl.cpp提供了派生 aclnn 封装随cann-ops-nn-custom_*.run自定义算子包部署后aclnnApplyFtrlGetWorkspaceSize/aclnnApplyFtrl符号会在${ASCEND_CUSTOM_OPP_PATH}/op_api/lib/libcust_opapi.so中以extern C默认可见性导出可被 ATK pyaclnn 或链接调用标准 CANN OPP 仍不含该接口。下列签名即最终实现签名与 L0 实现一致。算子采用两段式接口先调用aclnnApplyFtrlGetWorkspaceSize获取 workspace 大小及执行器再调用aclnnApplyFtrl执行计算。aclnnStatus aclnnApplyFtrlGetWorkspaceSize( aclTensor *varRef, aclTensor *accumRef, aclTensor *linearRef, const aclTensor *grad, const aclTensor *lr, const aclTensor *l1, const aclTensor *l2, const aclTensor *lrPower, bool useLocking, uint64_t *workspaceSize, aclOpExecutor **executor)aclnnStatus aclnnApplyFtrl( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream)aclnnApplyFtrlGetWorkspaceSize 参数说明参数名输入/输出描述使用说明数据类型数据格式维度(shape)非连续TensorvarRefaclTensor*输入/输出待更新参数原地更新对应公式 var。支持空 Tensor与 accumRef/linearRef/grad 数据类型、shape 需完全一致。BFLOAT16、FLOAT16、FLOATND0-8×accumRefaclTensor*输入/输出梯度平方累加器原地更新对应公式 accum要求 ≥ 0。支持空 Tensor数据类型、shape 与 varRef 一致。BFLOAT16、FLOAT16、FLOATND0-8×linearRefaclTensor*输入/输出校正项原地更新对应公式 linear。支持空 Tensor数据类型、shape 与 varRef 一致。BFLOAT16、FLOAT16、FLOATND0-8×gradaclTensor*输入当前步梯度对应公式 grad。支持空 Tensor数据类型、shape 与 varRef 一致。BFLOAT16、FLOAT16、FLOATND0-8×lraclTensor*输入学习率标量对应公式 lr要求 ≠ 0。0-D 或 1 元素 1-D数据类型与 varRef 一致。BFLOAT16、FLOAT16、FLOATND0-1-l1aclTensor*输入L1 正则系数标量对应公式 l1。0-D 或 1 元素 1-D数据类型与 varRef 一致。BFLOAT16、FLOAT16、FLOATND0-1-l2aclTensor*输入L2 正则系数标量对应公式 l2。0-D 或 1 元素 1-D数据类型与 varRef 一致。BFLOAT16、FLOAT16、FLOATND0-1-lrPoweraclTensor*输入缩放因子幂次标量对应公式 lr_power。0-D 或 1 元素 1-D数据类型与 varRef 一致。BFLOAT16、FLOAT16、FLOATND0-1-useLockingbool输入是否加锁对应属性 use_locking。仅支持 false。仅支持传入 false。----workspaceSizeuint64_t*输出返回需在 Device 侧申请的 workspace 大小。-----executoraclOpExecutor**输出返回 op 执行器包含算子计算流程。-----注Atlas 训练系列产品是否支持 BFLOAT16 以最终实现及配套为准。返回值与错误码aclnnApplyFtrlGetWorkspaceSize/aclnnApplyFtrl均返回aclnnStatus状态码具体参见 aclnn 返回码。第一段接口完成入参校验出现以下场景时报错返回值错误码描述ACLNN_ERR_PARAM_NULLPTR161001varRef、accumRef、linearRef、grad、lr、l1、l2、lrPower 存在空指针。ACLNN_ERR_PARAM_INVALID161002输入数据类型不在支持范围BFLOAT16/FLOAT16/FLOAT之内。ACLNN_ERR_PARAM_INVALID161002各输入数据类型不一致或 lr/l1/l2/lrPower 非标量0-D 或 1 元素。ACLNN_ERR_PARAM_INVALID161002var/accum/linear/grad 的 shape 不一致。从 aclnn_apply_ftrl.cpp 的实现看校验顺序为CheckNotNull空指针 →ACLNN_ERR_PARAM_NULLPTR→CheckDtypeValiddtype 支持列表 跨输入一致性 →ACLNN_ERR_PARAM_INVALID→CheckShape四个张量 shape 完全一致 四个标量Numel()1→ACLNN_ERR_PARAM_INVALID。校验通过后还会走空 Tensor 快路径varRef-IsEmpty()时直接返回 workspaceSize0随后将三个 Ref 与 grad 转成连续 Tensor 交给 L0 层。aclnnApplyFtrl 参数说明参数名输入/输出描述workspace输入在 Device 侧申请的 workspace 内存地址。workspaceSize输入在 Device 侧申请的 workspace 大小由 aclnnApplyFtrlGetWorkspaceSize 获取。executor输入op 执行器包含算子计算流程。stream输入指定执行任务的 Stream。约束说明确定性说明aclnnApplyFtrl 默认确定性实现Elementwise 逐元素独立计算无跨元素/跨核归约。数据类型var/accum/linear/grad/lr/l1/l2/lrPower 与输出 var 的数据类型必须完全一致取值 ∈ {BFLOAT16, FLOAT16, FLOAT}无类型推导无混合精度入参。shapevar/accum/linear/grad 的 shape 必须完全一致lr/l1/l2/lrPower 必须为 0-D 或 1 元素 1-D 标量广播到张量 shape张量之间不做广播。原地更新var、accum、linear 均为 Ref Tensor算子执行后原地更新调用方需将其视为可被算子修改的存储。值域前置条件算子内不做运行时值域校验由调用方保证accum ≥ 0、lr ≠ 0。当accum_new 0且lr_power 0、或quadratic 0、或lr 0时幂/除法会产生 Inf/NaN行为与 TensorFlow 原生ApplyFtrl一致需由上游调用方规避。属性use_locking 仅支持 false。内部计算FLOAT16 / BFLOAT16 输入在算子内部 Cast 为 FLOAT32 完成中间计算再 Cast 回原数据类型输出。调用示例标准 CANN OPP 未部署 ApplyFtrl 的 aclnn 接口ACLNNTYPEaclnn_exclude也无 PyTorch 等价但本实验扩展通过手写 op_api 提供了派生 aclnn 封装安装本算子的自定义算子包cann-ops-nn-custom_*.run后aclnnApplyFtrl/aclnnApplyFtrlGetWorkspaceSize符号即在libcust_opapi.so中可链接调用ATK pyaclnn 测试经此使能。本节给出本实验算子目录examples/下真实可运行的两种调用样例以及上文「派生 aclnn 两段式接口」的调用骨架。可运行样例指向 examples/调用方式调用样例说明GE 图模式静态/动态 shapetest_geir_apply_ftrl.cpp通过算子 IR 构图下发ApplyFtrl按var → accum → linear → grad → lr → l1 → l2 → lr_power串接 8 个Data输入scalar 输入 shape{1}set_attr_use_locking(false)。运行需先把算子编译安装进 OPP 包bash build.sh --pkg --experimental --socascend910b --opsapply_ftrl→bash build.sh --run_example apply_ftrl graph。Kernel 直调已在 ascend910b 真实 NPU 验证 PASStest_kernel_direct_apply_ftrl.asc直接复用本算子 op_kernel/apply_ftrl_kernel.h 的NsApplyFtrl::ApplyFtrlT, PAD_TAIL, HAS_L1计算类与正式构建同一份 kernel 源码经 CUDA 风格在真实 NPU 上运行并与 fp64 CPU golden 比对三输出 var/accum/linear。一键编译 运行见 examples/run.sh。更完整的多 dtype / 多 shape 真实 NPU 验证见 tests/st/aclnnApplyFtrl/atk_ApplyFtrl.json。其中 Kernel 直调样例的一键运行方式为需先source CANN 安装路径/set_env.sh使ASCEND_HOME_PATH生效默认逻辑 device 0可用ASCEND_RT_VISIBLE_DEVICES1指定其他设备bash run.sh # 完整流程编译 运行 三输出精度比对 bash run.sh --skip-build # 复用已编译产物派生 aclnn 两段式调用骨架本实验新增派生标准 CANN 未部署安装本扩展自定义算子包后符号可链接libcust_opapi.so需export LD_LIBRARY_PATH${ASCEND_CUSTOM_OPP_PATH}/op_api/lib:$LD_LIBRARY_PATH未安装时不可链接请用上表 GE 图模式 / Kernel 直调样例。// 注意aclnnApplyFtrl / aclnnApplyFtrlGetWorkspaceSize 为派生原型非 CANN 已部署接口不保证可链接。 // 1. 第一段计算 workspace 大小并构造执行器 uint64_t workspaceSize 0; aclOpExecutor* executor nullptr; auto ret aclnnApplyFtrlGetWorkspaceSize( varRef, accumRef, linearRef, // 3 个 Ref Tensor原地更新 grad, lr, l1, l2, lrPower, // grad 张量 4 个标量0-D 或 1 元素 1-D /*useLocking*/false, // 仅支持 false workspaceSize, executor); // CHECK_RET(ret ACL_SUCCESS, ...); // 2. 按需申请 device workspace void* workspace nullptr; if (workspaceSize 0) { aclrtMalloc(workspace, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); } // 3. 第二段执行计算var/accum/linear 原地更新 ret aclnnApplyFtrl(workspace, workspaceSize, executor, stream); // CHECK_RET(ret ACL_SUCCESS, ...); aclrtSynchronizeStream(stream);源码级实现原理纵深剖析Kernel逐元素 FTRL 链与 fp32 内部计算ascend910b 原生 kernel 的入口见 op_kernel/apply_ftrl.cpp其计算类NsApplyFtrl::ApplyFtrlT, PAD_TAIL, HAS_L1见 op_kernel/apply_ftrl_kernel.h。几个关键设计点内部统一 fp32 计算bf16/fp16 输入在Compute入口经Cast升到 fp32末尾再以CAST_RINT舍入回原 dtypefp32 路径直接ReinterpretCast复用输入缓冲区不额外分配 fp32 源缓冲。幂运算分解$a^{-lr_power}$ 采用Exp(Muls(Ln(a), -lr\_power))实现与 canndevapply_ftrl_d.py的_pow exp(index·ln(data))一致要求底数 $a0$。这也是 tiling 中accum尾块 pad 值取1.0的原因——Ln(1)0可避免 pad 区产生Ln(0)-Inf级联。标量加载LoadScalar从 GM 读取 lr/l1/l2/lr_power 四个标量half/fp32 直接static_castbf16 因编译器限制需借道DataCopyPad到 UB 后 Vector CastInit阶段预计算invLr_、negLrPower_、twoL2_等派生值。L1 软阈值分段HAS_L1模板参数为 1 时走通用sign 软阈值 门控路径CompareScalar(GE)Select求x_resCompareScalar(GT)实现|linear_t| l1 ? x_res/quadratic : 0并内含l1 0运行时快路径直接var -linear_t / quadraticHAS_L10时编译期直接裁掉门控分支。两级尾块对齐DataCopyPad的 rightPadding 不能跨一个 32B 块因此尾块先按 32B DMA 粒度nDma补齐剩余 [nDma, nComp) 到 256B 计算宽度的间隙在 fp32 域用Duplicate填充pad 元素不会写回 GMCopyOutTile按精确字节长度回写只保证 UB 内计算稳定。Tiling多核切分、UB 预算与自适应 block dimTiling 策略见 op_host/apply_ftrl_tiling.cpp要点如下多核切分blockFactor CeilAlign(CeilDiv(total, coreNum), ubBlockSize)按 AI vector core 均匀切分并对齐到 32B DMA 粒度避免相邻核 GM 区域重叠SetBlockDim(CeilDiv(totalElements, blockFactor))设定实际核数。UB 预算先预留SELECT_TMP_BYTES8KBSelect mode1/2 框架临时区再按UB_FP32_SLOTS24与 kernel 侧kUbFp32Slots常量保持同步fp32 路径约 20.25 slots/element折算每 tile 元素数向下对齐 64 元素256B以满足CompareScalar/Select的 256B 计数规则目标 tile 为TILE_ELEM_NUM_TARGET2048。自适应 block dim性能优化MIN_ELEM_PER_CORE512对 blockFactor 设下限小/中 shape 减少实际使用核数以摊薄每核固定开销kernel 启动 4 次标量 GM 读取 缓冲初始化 多核调度。注释中给出了 ascend910b 上 msprof-op block-dim 扫描的实测数据N1024 从 32 核降至 2 核kernel Task Duration 由 4.76us 降至 3.48us约 -27%N4096 由 40 核降至 8 核6.02us → 3.86us约 -36%大 shape≥64K/≥1M不受影响。workspace 为 0这是纯 UB 计算的 Elementwise kernel无需用户 workspaceUSER_WORKSPACE_SIZE 0GetWorkspaceSize直接写 0。注释同时说明 mainline arch35 基线里的 16MB SYS_WORKSPACE 属于系统保留概念与本实现无关。TilingKey通过ASCENDC_TPL_SEL_PARAM(dTypeVar, padTail, hasL1)生成因 host 在 tiling 期读不到 Device GM 上的标量 l1HAS_L1强制为 1kernel 侧运行时走 l10 快路径HAS_L10的二进制仍会产出供 UT 直接驱动。L2 → L0 调用链派生 aclnn 接口L2 层在 aclnn_apply_ftrl.cpp 中的标准流程为CREATE_EXECUTOR→CheckParams→ 空 Tensor 快路径 →l0op::Contiguousvar/accum/linear/grad 转连续→l0op::ApplyFtrl→ 非连续 Ref 时l0op::ViewCopy回拷 →GetWorkspaceSize并释放执行器第二段aclnnApplyFtrl直接CommonOpExecutorRun执行。L0 层 apply_ftrl.cpp 中ADD_TO_LAUNCHER_LIST_AICORE将 8 个输入按位置绑定到端口var, accum, linear, grad, lr, l1, l2, lr_power输出端口仅 1 个OP_OUTPUT(varRef)绑定同一 varRef 实现原地写回use_locking不注册为 OpDef 属性不影响数学且 tiling/kernel 不读取从而保持 kernel 参数布局8 in 1 out workspace tiling不变。useLocking在第一段被记录但不下发仅支持 false。配套验证与部署UTCPU 孪生tests/ut/op_kernel/test_apply_ftrl.cpp经 tikicpulib 直跑主线 kernel覆盖尾块、l10 快路径、空 Tensor 等场景host 侧另有 infershape / tiling 单测tests/ut/op_host/。ATK 真机用例tests/st/aclnnApplyFtrl/atk_ApplyFtrl.json用例集定义与executor_ApplyFtrl.py执行脚本覆盖全 dtype × shape × 标量 0-D/[1] 组合。部署路径bash build.sh --pkg --experimental --socascend910b --opsapply_ftrl编译并安装自定义算子包后派生 aclnn 符号位于${ASCEND_CUSTOM_OPP_PATH}/op_api/lib/libcust_opapi.so链接时需将${ASCEND_CUSTOM_OPP_PATH}/op_api/lib加入LD_LIBRARY_PATH。更多细节算子级 README 见 experimental/optim/apply_ftrl/README.md其中还包含精度标准说明fp32 Threshold 2⁻¹³ ≈ 1.22e-4、fp16 2⁻¹⁰ ≈ 9.77e-4、bf16 2⁻⁷ ≈ 7.81e-3MERE Threshold 且 MARE 10×Threshold与奇点行为描述accum_new0且lr_power0、quadratic0、lr0时产生 Inf/NaN 均与 TensorFlow 原生行为一致。赞分享人工智能算子库深度学习CANNAscend【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址https://gitcode.com/cann/ops-nn点击查看免费下载相关推荐CANN ops-nn HardtanhGrad 算子解析数学原理、aclnn 两段式接口与 AscendC Kernel 实现CANN ops nn HardtanhGrad 算子解析数学原理、aclnn 两段式接口与 AscendC Kernel 实现 本篇文章以 CANN 神经网人工智能算子库深度学习CANNAscendCANN ops-nn Swish 算子全解析数学原理、两段式 aclnn 接口与 AscendC Kernel 实现CANN ops nn Swish 算子全解析数学原理、两段式 aclnn 接口与 AscendC Kernel 实现 本文以 CANN ops nn 仓库中人工智能算子库深度学习CANNAscendCANN ops-nn ReluGrad 算子深度解析数学原理、两段式 aclnn 接口调用与 AscendC Kernel 实现CANN ops nn ReluGrad 算子深度解析数学原理、两段式 aclnn 接口调用与 AscendC Kernel 实现 导读 本文聚焦 CANN人工智能算子库深度学习CANNAscend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考