尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CANN ops-nn 算子解析:aclnnSoftMarginLoss 接口使用与源码实现全指南

CANN ops-nn 算子解析:aclnnSoftMarginLoss 接口使用与源码实现全指南 人工智能算子库深度学习CANNAscend【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址https://gitcode.com/cann/ops-nn点击查看免费下载导读本文围绕 CANN 开源神经网络算子库ops-nn中experimental/loss 下的 SoftMarginLoss 算子展开系统讲解其数学原理、aclnn 两段式调用流程、参数与错误码约定、完整可运行的 C 示例并结合算子注册、InferShape、Tiling 与 Kernel 源码剖析其在 NPU 上的实际执行方式。读完本文你将能够独立完成 aclnnSoftMarginLoss 的工程接入并理解 float32/float16 两种精度下 none/mean/sum 三种归约模式的底层实现差异。关联文档experimental/loss/soft_margin_loss/docs/aclnnSoftMarginLoss.md一、算子功能与数学原理SoftMarginLoss 是二分类逻辑回归场景下的逐元素损失函数。它接收两个相同 shape 的张量预测值张量self公式中的 $x$与目标值张量target公式中的 $t$通常取值为 1 或 -1逐元素计算损失后按reduction参数归约输出。1.1 两种等价的数学表达aclnn 接口文档给出的逐元素定义为$$ \text{loss}_i \log!\left(1 e^{-\text{target}_i \times \text{self}_i}\right) $$算子的 README 则给出数值上更稳定的等价形式对exp的输入取绝对值避免中间量溢出$$ L_i \max(0, -t_i \cdot x_i) \log(1 \exp(-|t_i \cdot x_i|)) $$其中 $x_i self_i$$t_i target_i$。两种写法在数学上完全等价但第二种形式是 Kernel 内部实际采用的计算路径其数值稳定性更好。1.2 归约模式reductionreduction 取值语义输出 shape0none不归约逐元素输出损失与self相同1mean默认对所有元素求均值输出标量0 维 tensordimNum02sum对所有元素求和输出标量0 维 tensordimNum01.3 手工计算示例reductionnone以 README 中的示例为例设 $self [1, -1, 2, -2]$$target [1, 1, -1, -1]$则$$ \begin{aligned} L_0 \max(0, -(1)(1)) \log(1 e^{-|1|}) 0 \log(1 0.3679) 0.3133 \ L_1 \max(0, -(1)(-1)) \log(1 e^{-|-1|}) 1 \log(1 0.3679) 1.3133 \ L_2 \max(0, -(-1)(2)) \log(1 e^{-|-2|}) 2 \log(1 0.1353) 2.1269 \ L_3 \max(0, -(-1)(-2)) \log(1 e^{-|-2|}) 0 \log(1 0.1353) 0.1269 \end{aligned} $$输出 $output [0.3133, 1.3133, 2.1269, 0.1269]$。可以直观看到当预测与目标符号一致分类正确时损失较小符号相反分类错误时损失被max(0, -t·x)项显著放大——这正是逻辑回归损失惩罚错分样本的设计意图。二、支持的产品与硬件约束产品系列产品型号Atlas A2 训练系列产品Atlas 800T A2、Atlas 800I A2、Atlas 900 A2 PoD、Atlas 200I A2从算子注册代码 op_host/soft_margin_loss_def.cpp 可以看到该算子通过AICore().AddConfig()注册了ascend910b与ascend950两个 AI Core 配置其中PrecisionReduceFlag(true)表明算子具备精度优化能力DynamicShapeSupportFlag(true)与DynamicRankSupportFlag(true)表示支持动态 shape 与动态 rank。三、函数原型与 aclnn 两段式调用模型3.1 函数原型aclnnStatus aclnnSoftMarginLossGetWorkspaceSize( const aclTensor *self, const aclTensor *target, int64_t reduction, const aclTensor *out, uint64_t *workspaceSize, aclOpExecutor **executor); aclnnStatus aclnnSoftMarginLoss( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream);aclnn 算子统一采用两段式异步调用模型阶段一aclnnSoftMarginLossGetWorkspaceSize完成参数校验、shape 推导InferShape与 workspace 大小估算输出workspaceSize与executor阶段二aclnnSoftMarginLoss使用阶段一返回的 workspace 与 executor在指定 stream 上异步提交算子执行。3.2 aclnnSoftMarginLossGetWorkspaceSize 参数说明参数名输入/输出描述self输入预测值张量。数据类型float32、float16。数据格式ND。支持非连续 tensor。target输入目标值张量通常为 1 或 -1。数据类型须与 self 相同。数据格式ND。shape 须与 self 相同。reduction输入归约模式。int64_t 类型取值0none、1mean默认、2sum。out输出输出张量。数据类型与 self 相同。reduction0 时 shape 与 self 相同reduction1 或 2 时为标量0 维 tensor。workspaceSize输出算子执行所需 workspace 大小单位为 Byte。由本函数返回调用方须据此分配 workspace 内存。executor输出算子执行器包含算子计算流信息由本函数返回后传入 aclnnSoftMarginLoss 执行。3.3 aclnnSoftMarginLoss 参数说明参数名输入/输出描述workspace输入workspace 内存地址。若 workspaceSize 为 0可传入 nullptr。workspaceSize输入workspace 大小由 aclnnSoftMarginLossGetWorkspaceSize 返回。executor输入算子执行器由 aclnnSoftMarginLossGetWorkspaceSize 返回。stream输入ACL stream用于异步调度算子执行。两个接口的返回值均为aclnnStatus错误码详见下文第五节。四、约束说明self与target须为相同数据类型和相同 shape支持数据类型float32、float16reduction仅支持 0none、1mean、2sum其他值返回ACLNN_ERR_PARAM_INVALIDout的 shape 须与 reduction 模式匹配reduction0 时与 self 相同reduction1 或 2 时为0 维标量 tensor注意不是 shape[1]而是 dimNum0 的标量 tensor支持空 tensor元素数为 0此时 workspaceSize 为 0直接返回成功workspace 须在调用aclnnSoftMarginLoss之前分配在 stream 中算子执行完成后方可释放。此外README 补充了一条重要实现约束float16 输入在 Kernel 内部会提升至 float32 计算仅最终输出转回 float16从而保证计算精度。五、返回值与错误码错误码描述ACLNN_SUCCESS0执行成功。ACLNN_ERR_PARAM_NULLPTR161001输入/输出 tensor 指针为空。ACLNN_ERR_PARAM_INVALID161002参数非法包括数据类型不支持、self 与 target 数据类型不一致、reduction 值不在 {0,1,2} 范围内、out shape 与预期不一致等。ACLNN_ERR_INNER_CREATE_EXECUTOR内部创建算子执行器失败。ACLNN_ERR_INNER_NULLPTR内部 tensor 分配失败。ACLNN_ERR_INNER_INFERSHAPE_ERROR内部 InferShape 失败。六、完整调用示例reductionmean以下示例完整展示了 SoftMarginLoss 算子的 aclnn 调用流程输入为 fp32、shape[4, 8] 的张量对以 mean 模式归约输出标量损失#include iostream #include vector #include cmath #include acl/acl.h #include aclnn_soft_margin_loss.h int main() { // 1. 初始化 ACL 及设备 aclInit(nullptr); aclrtSetDevice(0); aclrtStream stream; aclrtCreateStream(stream); // 2. 准备输入数据fp32shape[4, 8] int64_t shape[] {4, 8}; int64_t strides[] {8, 1}; float self_host[] { 0.5f, 1.0f, -0.3f, 2.0f, 0.1f, -1.5f, 0.8f, -0.2f, -1.0f, 0.7f, 1.5f, -0.5f, 0.3f, 0.9f, -0.8f, 1.2f, 0.4f, -0.6f, 1.1f, -1.3f, 0.6f, -0.4f, 1.4f, 0.2f, -0.9f, 1.3f, -0.1f, 0.0f, 1.6f, -1.1f, 0.5f, -0.7f }; float target_host[] { 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f }; size_t nbytes 32 * sizeof(float); void *self_dev nullptr, *target_dev nullptr, *out_dev nullptr; aclrtMalloc(self_dev, nbytes, ACL_MEM_MALLOC_NORMAL_ONLY); aclrtMalloc(target_dev, nbytes, ACL_MEM_MALLOC_NORMAL_ONLY); aclrtMalloc(out_dev, sizeof(float), ACL_MEM_MALLOC_NORMAL_ONLY); aclrtMemcpy(self_dev, nbytes, self_host, nbytes, ACL_MEMCPY_HOST_TO_DEVICE); aclrtMemcpy(target_dev, nbytes, target_host, nbytes, ACL_MEMCPY_HOST_TO_DEVICE); // 3. 创建 aclTensor aclTensor *self_t aclCreateTensor(shape, 2, ACL_FLOAT, strides, 0, ACL_FORMAT_ND, shape, 2, self_dev); aclTensor *target_t aclCreateTensor(shape, 2, ACL_FLOAT, strides, 0, ACL_FORMAT_ND, shape, 2, target_dev); // reductionmean/sum 时 out 为 0 维标量 tensor aclTensor *out_t aclCreateTensor(nullptr, 0, ACL_FLOAT, nullptr, 0, ACL_FORMAT_ND, nullptr, 0, out_dev); // 4. 查询 workspace 大小并分配 int64_t reduction 1; // mean uint64_t workspaceSize 0; aclOpExecutor *executor nullptr; aclnnSoftMarginLossGetWorkspaceSize(self_t, target_t, reduction, out_t, workspaceSize, executor); void *workspace nullptr; if (workspaceSize 0) aclrtMalloc(workspace, workspaceSize, ACL_MEM_MALLOC_NORMAL_ONLY); // 5. 执行算子 aclnnSoftMarginLoss(workspace, workspaceSize, executor, stream); aclrtSynchronizeStream(stream); // 6. 取回结果 float out_host 0.0f; aclrtMemcpy(out_host, sizeof(float), out_dev, sizeof(float), ACL_MEMCPY_DEVICE_TO_HOST); printf(SoftMarginLoss (mean) %f\n, out_host); // 期望: 0.781925 // 7. 释放资源 if (workspace) aclrtFree(workspace); aclrtFree(self_dev); aclrtFree(target_dev); aclrtFree(out_dev); aclDestroyTensor(self_t); aclDestroyTensor(target_t); aclDestroyTensor(out_t); aclrtDestroyStream(stream); aclrtResetDevice(0); aclFinalize(); return 0; }reductionnone 示例若reduction0则out的 shape 须与self相同例如[4, 8]输出为逐元素的 loss 值。仓库中还提供了带 CPU golden 校验、支持 fp16 打印与任意 shape 的完整工程化样例examples/test_aclnn_soft_margin_loss.cpp。它使用std::log(1.0 std::exp(-target * self))在 CPU 端计算期望均值损失再与 NPU 输出对比是验证算子正确性的良好参考。七、源码级实现剖析7.1 算子定义OpDefop_host/soft_margin_loss_def.cpp 中SoftMarginLoss : public OpDef声明了两个必选输入self、target与一个输出output三者均为ge::DT_FLOAT / ge::DT_FLOAT16且仅支持ge::FORMAT_ND并统一设置了AutoContiguous()。属性reduction通过this-Attr(reduction).Int(1)注册默认值为 1mean与 aclnn 接口文档一致。7.2 shape 推导InferShapeop_host/soft_margin_loss_infershape.cpp 的InferShape4SoftMarginLoss逻辑非常简洁读取属性reduction默认 1reduction 0输出 shape 直接拷贝输入 shape否则mean/sum输出为gert::Shape()即dimNum0 的标量。这从实现层面印证了约束说明中reduction1 或 2 时 out 是 0 维标量而非 shape[1]的要求。7.3 Tiling切分与调度op_host/soft_margin_loss_tiling.cpp 中SoftMarginLossTilingFunc完成以下工作通过平台信息获取 UB 大小与 AI Core 数量GetCoreNumAiv读取输入 shape 与 dtype计算总元素数totalNum若totalNum 0空 tensor将各因子置 0、SetBlockDim(1)且 workspace 大小为 0——对应文档中空 tensor 直接返回成功的约束多核切分none 路径按CeilDiv(totalNum, coreNum)将元素均分到各 AI CoreblockFactorreduce 路径当前实现选择单核顺序处理blockFactor totalNumusedCoreNum 1避免跨核SyncAll协调开销UB 切分按每循环块可用的浮点等价缓冲区数计算ubFactor四种路径fp32/fp16 × none/reduce的缓冲区计数分别为 8/9/6/7见 tiling.cpp 的常量定义并通过FloorAlign对齐到 UB block sizeTilingKey 选择依据 dtype 与是否归约选择调度模式 0~3workspace 申请reduce 路径需usedCoreNum * 32字节每核 32 字节对齐none 路径为 0。这也解释了为何aclnnSoftMarginLossGetWorkspaceSize返回的 workspaceSize 在 none/空 tensor 场景下为 0。值得注意的细节是tiling 阶段对reduction属性做了兼容 int 与字符串两种存储形式的解析运行时按 none/mean/sum 字符串存储UT 框架按原始 int64 存储见 soft_margin_loss_tiling.cpp。7.4 Kernel 实现NPU 计算核心op_kernel/soft_margin_loss.cpp 定义了算子核函数soft_margin_loss通过模板参数schMode在编译期分发到四种实例对应 soft_margin_loss_tiling_key.h 中的 TilingKey 映射schMode组合实例0FLOAT32 NONESoftMarginLossNonefloat1FLOAT32 REDUCESoftMarginLossReducefloat2FLOAT16 NONESoftMarginLossNonehalf3FLOAT16 REDUCESoftMarginLossReducehalf核心类定义在 op_kernel/soft_margin_loss.h其实现要点9 步浮点计算流水ComputeLossCoresoft_margin_loss.hMul计算tx target * self→Muls(-1)得-tx→Abs取|tx|→ 再取负 →Exp→Adds(1)→Log→Maxs(0)截断-tx→Add得到最终损失。每一步都复用临时缓冲区txLocal/negTxLocal最大限度节省 UB 空间float16 内部升精度half 路径先Cast到 float32 计算最后以CAST_ROUND舍入回 half 输出与 README 约束一致none 路径采用深度为 2 的双缓冲BUFFER_NUM 2VECIN/VECOUT队列实现数据搬运与计算的流水线并行按ubFactor分块循环处理reduce 路径SoftMarginLossReduce逐块计算损失后调用ReduceSum累加localSum。当前 tiling 下usedCoreNum 1直接按reductionMode决定是否乘以invNumelmean 时并写出标量代码同时保留了usedCoreNum 1时的两阶段跨核归约骨架写 partialSum 到workspace[coreIdx * 8]→SyncAll()→ core 0 聚合后写最终标量为后续多核归约优化预留了扩展点。7.5 TilingData 结构各 Tiling 参数通过 op_kernel/soft_margin_loss_tiling_data.h 中定义的SoftMarginLossTilingData结构体在 Host 侧与 Device 侧之间传递包含totalNum总元素数、blockFactor每核元素数、ubFactor每轮 UB 循环元素数、reductionMode、invNumel1/totalNum仅 mean 使用与usedCoreNum六个字段Kernel 侧通过GET_TILING_DATA_WITH_STRUCT获取。八、总结aclnnSoftMarginLoss 是一个结构清晰、文档完备的 aclnn 算子数学上采用数值稳定的max(0, -t·x) log(1 exp(-|t·x|))形式调用上遵循标准的两段式异步模型实现上以OpDef 注册 → InferShape 推导 → Tiling 切分 → Kernel 分派四层架构贯通 Host 与 Device。理解该算子既有助于直接上手二分类损失计算也可以作为学习 ops-nn 仓库中 aclnn 算子工程规范的典型范本。如需进一步探索可继续阅读算子说明文档experimental/loss/soft_margin_loss/docs/aclnnSoftMarginLoss.md算子 README含数值示例experimental/loss/soft_margin_loss/README.md可运行样例含 CPU golden 校验examples/test_aclnn_soft_margin_loss.cpp同类 loss 算子对比参考experimental/loss如 soft_margin_loss_grad、binary_cross_entropy 等赞分享人工智能算子库深度学习CANNAscend【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址https://gitcode.com/cann/ops-nn点击查看免费下载相关推荐3步解决res-downloader证书配置难题从失败到成功的终极指南3步解决res downloader证书配置难题从失败到成功的终极指南 还在为res downloader无法拦截HTTPS资源而烦恼吗为什么明明启动了代理人工智能算子库深度学习CANNAscendCANN ops-nn 算子解析SoftmaxCrossEntropyWithLogits 原理、aclnn 接口调用与源码实现CANN ops nn 算子解析SoftmaxCrossEntropyWithLogits 原理、aclnn 接口调用与源码实现 SoftmaxCrossEn人工智能算子库深度学习CANNAscendCANN ops-nn 中 aclnnLogSoftmaxBackward 算子的接口详解与源码级实现解析CANN ops nn 中 aclnnLogSoftmaxBackward 算子的接口详解与源码级实现解析 本文围绕 CANN ops nn 算子库中的 acl人工智能算子库深度学习CANNAscend上一篇Metahuman-Stream终极配置指南从零搭建数字人直播系统下一篇TheOdinProject Rails表单与认证项目实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表