资讯动态

CANN ops-nn 负对数似然损失反向算子 aclnnNLLLoss2dBackward 调用指南

发布时间:2026/9/23 7:35:54 来源:尧图企业网站定制
人工智能算子库深度学习CANNAscend【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址https://gitcode.com/cann/ops-nn点击查看免费下载本文以 CANN 开源算子库 ops-nn 中 loss/nll_loss_grad 目录下的 aclnnNLLLoss2dBackward 接口文档 为核心系统讲解 NLLLoss2d 反向算子的数学原理、两段式 aclnn 接口、全部入参约束与错误码、完整可运行的 C 调用示例并结合 op_api、op_host、op_kernel 源码与 tests 测试佐证底层实现。读完本文你将能够在 NPU 上独立完成 NLLLoss2d 反向梯度的计算编排、workspace 申请与结果回拷。一、算子功能与数学原理aclnnNLLLoss2dBackward实现负对数似然损失Negative Log-Likelihood Loss的反向传播即根据前向损失对输入的梯度gradOutput、前向输入self原始 log-probabilities和真实标签target计算得到输入self的梯度out。在 ops-nn 仓库中该算子的底层 IR 为NLLLossGrad其官方 READMEloss/nll_loss_grad/README.md给出了精确的分段计算公式x_grad[n][i] -y_grad[n] * weight , if i target 且 reduction none -y_grad / total_weight * weight , if i target 且 reduction mean -y_grad * weight , if i target 且 reduction sum 0 , if i ! target即只有命中真实标签target的位置才会回传梯度其余类别位置的梯度恒为 0梯度方向为负号因为 NLL 损失是负对数似然反向时取负mean模式下额外除以total_weight所有有效样本权重之和做归一化。对应前向语义2D NLL 损失的前向输入是形状为(N, C, H, W)的 log-probabilities而 2D 变体的标签为(N, H, W)形状——这正是该接口名为 2d 的原因self为四维、target为三维。二、产品支持情况根据 接口文档 与 README 产品支持表当前产品支持情况如下产品是否支持Ascend 950PR / Ascend 950DT支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品支持Atlas 200I/500 A2 推理产品不支持Atlas 推理系列产品310P不支持Atlas 训练系列产品910支持从算子注册源码 nll_loss_grad_def.cpp 可以看到该算子为ascend950与ascend350两个平台配置了 AICore 计算配置且DynamicCompileStaticFlag(true)、DynamicRankSupportFlag(true)、DynamicShapeSupportFlag(true)即支持动态编译、动态 rank 与动态 shape——这与文档中同时兼容 1D/2D/4D 输入的 infershape 实现见下文相互印证。三、两段式接口机制与 CANN 其他单算子 API 一致该算子采用两段式接口机制详见 docs/zh/context/two_phase_api.md第一段aclnnNLLLoss2dBackwardGetWorkspaceSize完成入参校验计算执行算子所需的 workspace 临时内存大小并生成包含完整计算流程的executor第二段aclnnNLLLoss2dBackward传入第一段申请的 workspace 与 executor在指定 stream 上真正执行计算。注意第二段接口不能重复调用。一次GetWorkspaceSize对应一次aclnnNLLLoss2dBackward调用重复调用第二段会产生异常。其中 workspace 是指除输入/输出外算子在 NPU 上完成计算所需的临时内存例如本算子内部做 transpose/reshape/类型提升时的中间缓冲其大小必须由第一段接口计算得出不能自行臆测。四、函数原型4.1 第一段接口aclnnStatus aclnnNLLLoss2dBackwardGetWorkspaceSize( const aclTensor *gradOutput, const aclTensor *self, const aclTensor *target, const aclTensor *weight, int64_t reduction, int64_t ignoreIndex, aclTensor *totalWeight, aclTensor *out, uint64_t *workspaceSize, aclOpExecutor **executor)4.2 第二段接口aclnnStatus aclnnNLLLoss2dBackward( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream)五、GetWorkspaceSize 参数详解第一段接口的入参与出参约束如下完整继承自 接口文档参数名输入/输出描述使用说明数据类型数据格式维度(shape)非连续TensorgradOutput (aclTensor*)输入输入 aclTensorshape 为三维第一维是 N或者一维且元素个数为 1FLOAT、FLOAT16、BFLOAT16ND-√self (aclTensor*)输入输入 aclTensorshape 为四维第一维 N 表示 batch size第二维 C 表示类别self 第 0/2/3 维 shape 必须与 target 第 0/1/2 维一致FLOAT、FLOAT16、BFLOAT16ND-√target (aclTensor*)输入表示真实标签公式中的 yshape 为 3 维各维分别与 self 第 0/2/3 维一致每个元素取值 ∈ [0, C-1]INT64、UINT8、INT32ND-√weight (aclTensor*)输入表示每个类别的缩放权重公式中的 wshape 为 (C,)与 self 一致ND(C,)√reduction (int64_t)输入指定要应用到输出的缩减支持 0(none)1(mean)2(sum)none 不缩减mean 表示总和除以输出元素数sum 表示求和reduction 为 0 时要求 target 与 gradOutput shape 一致INT64---ignoreIndex (int64_t)输入指定一个被忽略且不影响输入梯度的目标值-INT64---totalWeight (aclTensor*)输入归一化权重合计仅 reduction 为 mean 时生效按 target 取对应位置 weight剔除 ignoreIndex 对应项后求和其他 reduction 下默认不处理与 weight 相同ND(1,)-out (aclTensor*)输出计算结果shape 与 self 相同与 self 一致ND-√workspaceSize (uint64_t*)输出返回需要在 Device 侧申请的 workspace 大小-----executor (aclOpExecutor**)输出返回 op 执行器包含算子计算流程-----几个关键使用要点reduction 语义none逐元素回传梯度此时gradOutput必须与target同 shapemean/sum为标量缩减此时gradOutput必须是一维且元素个数为 1标量梯度。ignoreIndex 默认值算子定义源码 nll_loss_grad_def.cpp 中DEFAULT_IGNORE_IDX -100与 PyTorchnn.CrossEntropyLoss(ignore_index-100)的默认约定一致totalWeight在 mean 模式下会剔除该索引对应位置的权重。支持非连续 Tensor上表中标记√的入参/出参均支持非连续 tensor接口内部会先做Contiguous归一化再计算见第六节源码解析。六、返回值与错误码两个接口均返回aclnnStatus完整状态码语义参见 docs/zh/context/aclnn_return_code.md。第一段接口完成入参校验以下场景会报错返回值错误码描述ACLNN_ERR_PARAM_NULLPTR161001传入的 gradOutput、self、target、weight、totalWeight 或 out 是空指针ACLNN_ERR_PARAM_INVALID161002gradOutput、self、target、weight、totalWeight 或 out 的数据类型不在支持范围之内ACLNN_ERR_PARAM_INVALID161002gradOutput、self、weight、totalWeight、out 的数据类型不一致ACLNN_ERR_PARAM_INVALID161002target 非 3 维 tensorself 非 4 维 tensorACLNN_ERR_PARAM_INVALID161002weight 的元素个数不是 CACLNN_ERR_PARAM_INVALID161002self 的第 0/2/3 维元素个数与 target 的第 0/1/2 维元素个数不相等ACLNN_ERR_PARAM_INVALID161002totalWeight 的元素个数不是 1ACLNN_ERR_PARAM_INVALID161002reduction 为 none 时gradOutput 维数不是 3或 gradOutput 第 0/1/2 维元素个数与 target 不一致ACLNN_ERR_PARAM_INVALID161002reduction 非 none 时gradOutput 维数大于 1 或元素个数不为 1ACLNN_ERR_PARAM_INVALID161002reduction 值不在 0~2 范围之内这些校验逻辑在 op_api/aclnn_nll_loss2d_backward.cpp 的CheckParams中逐一对应实现CheckNotNullL70-L81空指针检查 → 161001CheckDtypeValidL83-L98校验 self 类型在支持列表内、五者类型一致、target 类型合法 → 161002CheckShapeL109-L155校验 gradOutput 与 target 的 shape 关系、self 为 4D、target 为 3D、weight 元素数等于 C、out 与 self 同 shape、totalWeight 元素数为 1 → 161002CheckReductionL100-L107reduction 必须在 [0, 2] 内 → 161002。另外值得注意的是第一段接口在self-IsEmpty()空 tensor时直接返回成功且workspaceSize 0不会执行计算L192-L197。七、第二段接口参数说明参数名输入/输出描述workspace输入在 Device 侧申请的 workspace 内存地址workspaceSize输入在 Device 侧申请的 workspace 大小由第一段接口 aclnnNLLLoss2dBackwardGetWorkspaceSize 获取executor输入op 执行器包含了算子计算流程stream输入指定执行任务的 Stream第二段接口在 aclnn_nll_loss2d_backward.cpp 中只是简单地调用框架统一的CommonOpExecutorRun(workspace, workspaceSize, executor, stream)完成异步执行真正的计算流程Contiguous → Cast → Reshape → Transpose → NLLLossGrad → ViewCopy已固化在由第一段接口生成的 executor 内部。八、约束说明确定性计算aclnnNLLLoss2dBackward 默认确定性实现即相同输入在相同软硬件环境下多次执行结果一致。相关背景可参见 docs/zh/context/determinism_compute.md。需要完整的 CANN 运行环境驱动、固件、CANN 软件包、ops 包等才能编译执行详见 docs/zh/context/compile_and_run_sample.md 的前提说明。九、完整调用示例以下示例代码可直接在仓库 examples/test_aclnn_nll_loss_grad_2d.cpp 中查看编译与执行流程参考 docs/zh/context/compile_and_run_sample.md。示例场景为N3, C5, H1, W1、reductionnone、ignoreIndex-100#include iostream #include vector #include acl/acl.h #include aclnnop/aclnn_nll_loss2d_backward.h #define CHECK_RET(cond, return_expr) \ do { \ if (!(cond)) { \ return_expr; \ } \ } while (0) #define LOG_PRINT(message, ...) \ do { \ printf(message, ##__VA_ARGS__); \ } while (0) int64_t GetShapeSize(const std::vectorint64_t shape) { int64_t shapeSize 1; for (auto i : shape) { shapeSize * i; } return shapeSize; } int Init(int32_t deviceId, aclrtStream* stream) { // 固定写法资源初始化 auto ret aclInit(nullptr); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclInit failed. ERROR: %d\n, ret); return ret); ret aclrtSetDevice(deviceId); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtSetDevice failed. ERROR: %d\n, ret); return ret); ret aclrtCreateStream(stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtCreateStream failed. ERROR: %d\n, ret); return ret); return 0; } template typename T int CreateAclTensor(const std::vectorT hostData, const std::vectorint64_t shape, void** deviceAddr, aclDataType dataType, aclTensor** tensor) { auto size GetShapeSize(shape) * sizeof(T); // 调用aclrtMalloc申请device侧内存 auto ret aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtMalloc failed. ERROR: %d\n, ret); return ret); // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 ret aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtMemcpy failed. ERROR: %d\n, ret); return ret); // 计算连续tensor的strides std::vectorint64_t strides(shape.size(), 1); for (int64_t i shape.size() - 2; i 0; i--) { strides[i] shape[i 1] * strides[i 1]; } // 调用aclCreateTensor接口创建aclTensor *tensor aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); return 0; } int main() { // 1.固定写法device/stream初始化参考acl API手册 // 根据自己的实际device填写deviceId int32_t deviceId 0; aclrtStream stream; auto ret Init(deviceId, stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(Init acl failed. ERROR: %d\n, ret); return ret); // 2. 构造输入与输出需要根据API的接口自定义构造 std::vectorint64_t gradShape {3, 1, 1}; std::vectorint64_t selfShape {3, 5, 1, 1}; std::vectorint64_t targetShape {3, 1, 1}; std::vectorint64_t weightShape {5}; std::vectorint64_t totalWeightShape {1}; std::vectorint64_t outShape {3, 5, 1, 1}; void* gradDeviceAddr nullptr; void* selfDeviceAddr nullptr; void* targetDeviceAddr nullptr; void* weightDeviceAddr nullptr; void* totalWeightDeviceAddr nullptr; void* outDeviceAddr nullptr; aclTensor* grad nullptr; aclTensor* self nullptr; aclTensor* target nullptr; aclTensor* weight nullptr; aclTensor* totalWeight nullptr; aclTensor* out nullptr; std::vectorfloat gradHostData {2.7, 2.6, 2.5}; std::vectorfloat selfHostData {4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5}; std::vectorint64_t targetHostData {2, 3, 1}; std::vectorfloat weightHostData {1.0, 1.0, 1.0, 1.0, 1.0}; std::vectorfloat totalWeightHostData {1.0}; std::vectorfloat outHostData {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; int64_t reduction 0; int64_t ignoreIndex -100; // 创建grad aclTensor ret CreateAclTensor(gradHostData, gradShape, gradDeviceAddr, aclDataType::ACL_FLOAT, grad); CHECK_RET(ret ACL_SUCCESS, return ret); // 创建self aclTensor ret CreateAclTensor(selfHostData, selfShape, selfDeviceAddr, aclDataType::ACL_FLOAT, self); CHECK_RET(ret ACL_SUCCESS, return ret); // 创建target aclTensor ret CreateAclTensor(targetHostData, targetShape, targetDeviceAddr, aclDataType::ACL_INT64, target); CHECK_RET(ret ACL_SUCCESS, return ret); // 创建weight aclTensor ret CreateAclTensor(weightHostData, weightShape, weightDeviceAddr, aclDataType::ACL_FLOAT, weight); CHECK_RET(ret ACL_SUCCESS, return ret); // 创建totalWeight aclTensor ret CreateAclTensor(totalWeightHostData, totalWeightShape, totalWeightDeviceAddr, aclDataType::ACL_FLOAT, totalWeight); CHECK_RET(ret ACL_SUCCESS, return ret); // 创建out aclTensor ret CreateAclTensor(outHostData, outShape, outDeviceAddr, aclDataType::ACL_FLOAT, out); CHECK_RET(ret ACL_SUCCESS, return ret); // 3. 调用CANN算子库API需要修改为具体的API名称 uint64_t workspaceSize 0; aclOpExecutor* executor; // 调用aclnnNLLLoss2dBackward第一段接口 ret aclnnNLLLoss2dBackwardGetWorkspaceSize(grad, self, target, weight, reduction, ignoreIndex, totalWeight, out, workspaceSize, executor); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnNLLLoss2dBackwardGetWorkspaceSize failed. ERROR: %d\n, ret); return ret); // 根据第一段接口计算出的workspaceSize申请device内存 void* workspaceAddr nullptr; if (workspaceSize 0) { ret aclrtMalloc(workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(allocate workspace failed. ERROR: %d\n, ret); return ret); } // 调用aclnnNLLLoss2dBackward第二段接口 ret aclnnNLLLoss2dBackward(workspaceAddr, workspaceSize, executor, stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnNLLLoss2dBackward failed. ERROR: %d\n, ret); return ret); // 4.固定写法同步等待任务执行结束 ret aclrtSynchronizeStream(stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtSynchronizeStream failed. ERROR: %d\n, ret); return ret); // 5. 获取输出的值将device侧内存上的结果拷贝至host侧内存需要根据具体API的接口定义修改 auto size GetShapeSize(outShape); std::vectorfloat resultData(size, 0); ret aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(copy result from device to host failed. ERROR: %d\n, ret); return ret); for (int64_t i 0; i size; i) { LOG_PRINT(result[%ld] is: %f\n, i, resultData[i]); } // 6. 释放aclTensor需要根据具体API的接口定义修改 aclDestroyTensor(grad); aclDestroyTensor(self); aclDestroyTensor(target); aclDestroyTensor(weight); aclDestroyTensor(totalWeight); aclDestroyTensor(out); // 7. 释放device资源 aclrtFree(gradDeviceAddr); aclrtFree(selfDeviceAddr); aclrtFree(targetDeviceAddr); aclrtFree(weightDeviceAddr); aclrtFree(totalWeightDeviceAddr); aclrtFree(outDeviceAddr); if (workspaceSize 0) { aclrtFree(workspaceAddr); } aclrtDestroyStream(stream); aclrtResetDevice(deviceId); aclFinalize(); return 0; }对上述示例的要点拆解资源初始化Init依次调用aclInit→aclrtSetDevice→aclrtCreateStream这是所有 aclnn 算子的固定前置步骤。Tensor 构造CreateAclTensor先aclrtMalloc申请 device 内存再aclrtMemcpy拷贝 host 数据到 device按连续内存计算 strides 后通过aclCreateTensor创建aclTensor。本例中gradOutput与target均为(3,1,1)、self与out均为(3,5,1,1)、weight为(5,)、totalWeight为(1,)与第五节的 shape 约束一一对应。两段式调用先调GetWorkspaceSize得到workspaceSize与executor若workspaceSize 0则aclrtMalloc申请临时内存再调aclnnNLLLoss2dBackward执行。同步与回拷aclrtSynchronizeStream等待异步任务完成随后aclrtMemcpyACL_MEMCPY_DEVICE_TO_HOST将结果取回 host 侧打印。资源释放依次aclDestroyTensor销毁 tensor、aclrtFree释放 device 内存与 workspace、aclrtDestroyStream/aclrtResetDevice/aclFinalize收尾。十、编译与运行在开发和运行环境合设同一台带 AI 处理器的机器场景下按 docs/zh/context/compile_and_run_sample.md 组织工程将上述示例代码保存为test_aclnn_nll_loss_grad_2d.cpp编写 CMakeLists.txt至少需要include_directories指向${ASCEND_PATH}/include与${ASCEND_PATH}/include/aclnntarget_link_libraries链接libascendcl.so、libnnopbase.so以及libopapi_nn.so本算子属于 NN 类算子头文件aclnn_nll_loss2d_backward.h位于aclnnop目录下ASCEND_PATH默认取/usr/local/Ascend/cann也可通过环境变量ASCEND_CUSTOM_PATH覆盖编译生成可执行文件后运行即可在 NPU 上完成 NLLLoss2d 反向计算并打印out梯度结果。十一、源码级实现解析11.1 接口层内部计算流水线op_api/aclnn_nll_loss2d_backward.cpp 中第一段接口完成校验后以l0op底层算子组合拼装出完整计算图。以非 regbase 平台L232-L293为例其流水线为类型提升gradOutput、self、weight、totalWeight先做Contiguous归一化再Cast到promoteType非 regbase 时 FLOAT16 会被提升为 FLOAT 参与计算L199-L202维度规整gradOutput在reductionnone时Reshape为 1Dself按{0,2,3,1}转置后Reshape为(-1, C)target展平为 1D 并Cast为 INT32核心计算调用l0op::NLLLossGrad(gradOutputIn, selfInput, targetCasted, weightCast, reductionStr, ignoreIndex, totalWeightCast, ...)结果还原将结果Reshape回(N, H, W, C)再按{0,3,1,2}转置回(N, C, H, W)Cast回out的数据类型最后ViewCopy写入可能非连续的out。regbase 平台L294-L312则直接以原始维度调用NLLLossGrad无需转置/reshape 的维度搬运。reduction数值到字符串的映射由GetReductionStrL59-L68完成0→none、1→mean、2→sum。另外接口层还根据 SoC 版本区分 dtype 支持列表ASCEND910B、ASCEND910_93及 regbase 平台支持 FLOAT/FLOAT16/BF16其余平台仅支持 FLOAT/FLOAT16L40-L57target统一支持 INT64/UINT8/INT32L47-L48。11.2 Host 侧算子定义、infershape 与 tiling算子定义nll_loss_grad_def.cpp注册输入x、y_grad、target、weight、total_weight与输出x_grad全部为FORMAT_ND属性reduction默认为meanignore_index默认为-100。infershapenll_loss_grad_infershape.cppInferShapeForNLLLossGrad对输入 rank 分流——1D[C]、2D[N,C]、4D[N,C,H,W]均按输入 shape 推导输出未知 rank 时输出设为(-2,)其他 rank 报错。InferDtypeForNLLLossGrad限定输入仅支持 FLOAT/FLOAT16/BF16输出 dtype 与输入一致。tilingnll_loss_grad_tiling_arch35.cpp将reduction属性映射为NONE_MODE0/MEAN_MODE1/SUM_MODE2按输出元素总数与 AIV 核数做blockPerCore/blockTailCore的负载切分并以batchNum*height*width维度计算参与核数workspace 固定申请16 * 1024 * 1024字节ASCENDC_TOOLS_WORKSPACE最大线程MAX_THREAD1024且要求 kernel 使用 SyncAll 的 batch 调度模式SetScheduleMode(1)。11.3 Kernel 侧SIMT 实现入口op_kernel/nll_loss_grad.cpp 为昇腾 AICore 上的 SIMT 风格 kernel 入口先通过SetSysWorkspace/GetUserWorkspace获取用户 workspace为空则直接返回再GET_TILING_DATA取 tiling 数据按KERNEL_TYPE_MIX_AIV_1_0任务类型实例化模板类KernelNLLLossGradDTYPE_X, DTYPE_TARGET并执行InitProcess。模板实现在 op_kernel/arch35/nll_loss_grad.h 中按 x 与 target 的不同数据类型组合编译出多份 kernel 实例。11.4 测试佐证ATK 接口级测试tests/st/aclnnNLLLoss2dBackward/executor_aclnnNLLLoss2dBackward.py 将本接口与 PyTorch 的torch.ops.aten.nll_loss2d_backward对齐CPU 侧非 FP32 时先提升到 FP32 计算再转回原精度用例参数由 atk_aclnnNLLLoss2dBackward.json 驱动从侧面印证了本算子与 PyTorch 前向/反向语义的一致性。UT 测试目录 tests/ut/op_host 下提供test_nll_loss_grad_infershape.cppinfershape 单测与test_aclnn_nll_loss2d_backward_l2.cppL2 接口层单测可在昇腾环境上用 tests/ut 的框架直接运行验证。仓库中同目录下还存在 aclnnNLLLossBackward.md 与 test_aclnn_nll_loss_grad.cpp对应非 2d 的通用 NLLLoss 反向接口两者的底层 kernel 与 tiling 完全复用NLLLossGrad算子见 README 调用说明读者可对照阅读。十二、总结aclnnNLLLoss2dBackward是 CANN ops-nn 中面向 2D 空间维 NLL 损失的确定性反向算子接口层负责参数校验与维度规整host 层负责 shape 推导与 SIMT tiling 切分kernel 层按reduction三种模式none/mean/sum回传命中target位置的加权负梯度。掌握其两段式调用范式、reduction/ignoreIndex语义与 shape 对齐约束后即可在 Ascend 950/A3/A2 等支持的平台上稳定集成 NLLLoss2d 的反向计算。赞分享人工智能算子库深度学习CANNAscend【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址https://gitcode.com/cann/ops-nn点击查看免费下载相关推荐CANN ops-nn 负对数似然损失反向算子 aclnnNLLLoss2dBackward 接口详解与实战CANN ops nn 负对数似然损失反向算子 aclnnNLLLoss2dBackward 接口详解与实战 导读 本文围绕 CANN ops nn 开源仓库人工智能算子库深度学习CANNAscendCANN ops-nn NllLossGrad 算子完全指南负对数似然损失反向传播原理、接口与 NPU 调用实战CANN ops nn NllLossGrad 算子完全指南负对数似然损失反向传播原理、接口与 NPU 调用实战 导读 NllLossGrad 是 CANN人工智能算子库深度学习CANNAscendCANN ops-nn 算子深度解析NllLossGrad 负对数似然损失反向传播算子的实现与 aclnn 调用实践CANN ops nn 算子深度解析NllLossGrad 负对数似然损失反向传播算子的实现与 aclnn 调用实践 导读 NllLossGrad 是 CAN人工智能算子库深度学习CANNAscend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价