
ops-cv 三维最近邻精确上采样反向算子aclnnUpsampleNearestExact3dBackward API 详解与 NPU 实现解析【免费下载链接】ops-cv本项目是CANN提供的图像处理、目标检测相关的算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-cv本文基于 ops-cv 仓库中的接口文档系统讲解aclnnUpsampleNearestExact3dBackward这一 5D 张量三维最近邻精确上采样反向梯度接口的数学定义、两段式调用方式、全部参数与错误码、容量与缩放约束并结合仓库内主机侧校验链路、L0 封装与 kernel 级 SIMT 实现帮助你既能直接写出可运行的调用代码又能理解其在 NPU 上的实际执行路径。算子定位与产品支持情况aclnnUpsampleNearestExact3dBackward是 aclnnUpsampleNearestExact3d三维最近邻精确上采样正向算子的反向计算接口用于将上采样输出侧的梯度gradOut累加回输入侧的gradInput。仓库中该算子的实现与文档位于 image/upsample_nearest_exact3d_grad 目录接口文档即 aclnnUpsampleNearestExact3dBackward.md。按文档与 算子 README 的产品支持表各产品的支持情况如下产品是否支持Ascend 950PR/Ascend 950DT√Atlas A3 训练系列产品/Atlas A3 推理系列产品√Atlas A2 训练系列产品/Atlas A2 推理系列产品√Atlas 200I/500 A2 推理产品×Atlas 推理系列产品×Atlas 训练系列产品×在 算子定义文件 中可以看到算子为ascend910b、ascend910_93、ascend950三类平台分别注册了配置与上表支持的产品线相对应其中ascend950配置开启了动态编译、动态 Rank 与动态 Shape 支持regbase 平台走动态编译静态标志扩展文件指向upsample_nearest_exact3d_grad_aptkernel 源文件。数学原理梯度累加窗口与 -0.5 偏移理解这个Backward接口的关键是它不是简单的逐点缩放而是对输出侧梯度在一个三维窗口内做累加。对于输入gradOut(N, C, d, h, w)输出gradInput上任意一点(N, C, D, H, W)满足$$ gradInput(N, C, D, H, W) \sum_{d srcD}^{srcDUp - 1}\sum_{h srcH}^{srcHUp - 1}\sum_{w srcW}^{srcWUp - 1}gradOut(N, C, d, h, w) $$其中缩放因子按如下规则确定当scalesD、scalesH、scalesW三者均大于 0 时直接取用户传入值否则用输出/输入空间尺寸之比回退计算$$ scaleD \begin{cases} scalesD scalesD0scalesH0scalesW0\ outputSize[0]/inputSize[2] Otherwise\ \end{cases} $$$$ scaleH \begin{cases} scalesH scalesD0scalesH0scalesW0\ outputSize[1]/inputSize[3] Otherwise\ \end{cases} $$$$ scaleW \begin{cases} scalesW scalesD0scalesH0scalesW0\ outputSize[2]/inputSize[4] Otherwise\ \end{cases} $$输入点(D, H, W)对应的输出侧累加窗口边界为outputSize[0/1/2]分别是输出 D、H、W 维长度$$ srcD Min(ceil(scaleD * D - 0.5), outputSize[0]) $$$$ srcDUp Min(ceil(scaleD * (D 1) - 0.5), outputSize[0]) $$$$ srcH Min(ceil(scaleH * H - 0.5), outputSize[1]) $$$$ srcHUp Min(ceil(scaleH * (H 1) - 0.5), outputSize[1]) $$$$ srcW Min(ceil(scaleW * W - 0.5), outputSize[2]) $$$$ srcWUp Min(ceil(scaleW * (W 1) - 0.5), outputSize[2]) $$这里-0.5的偏移正是Exact精确模式的语义所在它对应 PyTorchupsample_nearest_exact3d的反向定义与普通的upsample_nearest3d无 -0.5 偏移形成对照。这一细节可以在 kernel 共享实现中得到直接印证upsample_nearest3d_grad_simt_base.h 中ComputeOrig函数按isExtra模板开关选择ceil(idx * scale - 0.5)或ceil(idx * scale)本算子固定以isExtra true实例化见 upsample_nearest_exact3d_grad_apt.cpp 中Nearest3dGradSimtDTYPE_GRAD_OUTPUT, uint32_t, true, schId的第三个模板参数。两段式接口与函数原型按 CANN 的两段式接口规范该算子分为两个接口必须先调用第一段接口完成入参校验并计算所需 workspace 大小、拿到aclOpExecutor再调用第二段接口在指定流上执行计算。aclnnStatus aclnnUpsampleNearestExact3dBackwardGetWorkspaceSize( const aclTensor *gradOut, const aclIntArray *outputSize, const aclIntArray *inputSize, double scalesD, double scalesH, double scalesW, aclTensor *gradInput, uint64_t *workspaceSize, aclOpExecutor **executor)aclnnStatus aclnnUpsampleNearestExact3dBackward( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream)第一段接口 aclnnUpsampleNearestExact3dBackwardGetWorkspaceSize 参数说明参数名输入/输出描述使用说明数据类型数据格式维度(shape)非连续TensorgradOutaclTensor*输入表示反向计算的梯度Tensor对应公式中的gradOut。不支持空TensorgradOut的所有维度取值均小于等于(2^31-1)。FLOAT32、FLOAT16、BFLOAT16NCDHW、NDHWC5√outputSizeaclIntArray*输入表示输入gradOut在D、H和W维度上的空间大小对应公式中的outputSize。size为3且各元素均大于零。INT64---inputSizeaclIntArray*输入表示输出gradInput分别在N、C、D、H和W维度上的空间大小对应公式中的inputSize。size为5且各元素均大于零。INT64---scalesDdouble输入表示输出gradInput的depth维度乘数对应公式中的scalesD。取值小于等于50。----scalesHdouble输入表示输出gradInput的height维度乘数对应公式中的scalesH。取值小于等于50。----scalesWdouble输入表示输出gradInput的width维度乘数对应公式中的scalesW。取值小于等于50。----gradInputaclTensor*输出表示反向计算的输出张量对应公式中的输出gradInput。不支持空Tensor数据类型、数据格式、shape与入参gradOut保持一致指 N、C 维度一致gradInput的所有维度取值均小于等于(2^31-1)。FLOAT32、FLOAT16、BFLOAT16NCDHW、NDHWC5√workspaceSizeuint64_t*输出返回需要在Device侧申请的workspace大小。-----executoraclOpExecutor**输出返回op执行器包含了算子计算流程。-----返回值aclnnStatus状态码取值参见 aclnn 返回码说明。第一段接口完成入参校验出现以下场景时报错返回码错误码描述ACLNN_ERR_PARAM_NULLPTR161001传入的gradOut、outputSize、inputSize或gradInput是空指针。ACLNN_ERR_PARAM_INVALID161002gradOut的数据类型不在支持的范围内。ACLNN_ERR_PARAM_INVALID161002gradOut和gradInput的数据类型不一致。ACLNN_ERR_PARAM_INVALID161002gradOut的维度不为5维。ACLNN_ERR_PARAM_INVALID161002outputSize的size不等于3。ACLNN_ERR_PARAM_INVALID161002outputSize的某个元素值不大于0。ACLNN_ERR_PARAM_INVALID161002inputSize的size不等于5。ACLNN_ERR_PARAM_INVALID161002gradOut与inputSize在N、C维度上的size不同。ACLNN_ERR_PARAM_INVALID161002gradOut在D、H、W维度上的size与outputSize[0]、outputSize[1]、outputSize[2]不一致。ACLNN_ERR_PARAM_INVALID161002gradInput在N、C维度的size与inputSize[0]、inputSize[1]不一致。ACLNN_ERR_PARAM_INVALID161002gradInput在D、H、W维度上的size与inputSize[2]、inputSize[3]、inputSize[4]不一致。ACLNN_ERR_PARAM_INVALID161002scalesD、scalesH、scalesW的取值不满足约束要求。这些校验项与源码中的检查函数一一对应aclnn_upsample_nearest_exact3d_backward.cpp 中的CheckParams按固定顺序执行CheckNotNull空指针检查、CheckDtypeValid类型白名单且输入输出类型一致、CheckShape5 维检查、outputSize 长度为 3、inputSize 长度为 5、CheckInputElement各元素大于 0、shape 与 inputSize/outputSize 的逐维一致性、scale 上限以及CheckUplimit各维度不超过 INT32_MAX。其中类型白名单DTYPE_SUPPORT_LIST仅包含DT_FLOAT、DT_FLOAT16、DT_BF16同文件 L33-L34缩放上限常量MAX_SUPPORT_SCALE 50L37。第二段接口 aclnnUpsampleNearestExact3dBackward 参数说明参数名输入/输出描述workspace输入在Device侧申请的workspace内存地址。workspaceSize输入在Device侧申请的workspace大小由第一段接口aclnnUpsampleNearestExact3dBackwardGetWorkspaceSize获取。executor输入op执行器包含了算子计算流程。stream输入指定执行任务的Stream。返回值aclnnStatus参见 aclnn 返回码说明。约束说明文档给出的 shape 与容量约束如下调用前必须逐一核对参数gradOut、gradInput的 shape 约束每个维度的取值小于等于 2^20。参数gradInput的 N 轴和 C 轴与gradOut保持一致。内存占用需小于 60GB计算公式$$ N * C * (gradOut_D * gradOut_H * gradOut_W gradInput_D * gradInput_H * gradInput_W gradOut_D * gradOut_H * gradInput_W gradOut_D * gradInput_H * gradInput_W) * sizeof(dtype) 60 * 1024 * 1024 * 1024 $$其中 N 为输入和输出的 N 轴C 为输入和输出的 C 轴dtype 为输入张量的数据类型。N * C * gradOut_D * gradOut_H 2^31gradInput_W * gradInput_H 2^31参数gradOut、gradInput的数据格式不为 NCDHW 或 NDHWC 时输入的其他数据格式默认按 NCDHW 处理。反向接口的输入数据缩小倍数必须小于等于 50即$$ outputSize_D / 输出shape的深度D 50 $$$$ outputSize_H / 输出shape的高度H 50 $$$$ outputSize_W / 输出shape的宽度W 50 $$当scalesD、scalesH、scalesW的取值均大于 0 时参数inputSize、outputSize、scalesD、scalesH、scalesW需满足如下约束$$ outputSize_D floor(inputSize_D * scalesD) $$$$ outputSize_H floor(inputSize_H * scalesH) $$$$ outputSize_W floor(inputSize_W * scalesW) $$确定性计算aclnnUpsampleNearestExact3dBackward默认确定性实现。从源码结构看缩小倍数不超过 50的限制对应主机侧CheckInputElement中对回退 scaleComputeNearestExact3dGradScales即 scale ≤ 0 时用output_size / input_size反推的三重校验见 aclnn_upsample_nearest_exact3d_backward.cpp L128-L135这也解释了为什么文档把scales 取值不满足约束与 shape 校验统一归入 161002 错误码。源码实现链路解析第一段接口的内部编排Contiguous → Transpose → 计算 → ViewCopy阅读 GetWorkspaceSize 实现 可以看到该接口并非单一 kernel 调用而是一条 L0 算子编排链空 Tensor 短路gradOut为空时直接返回workspaceSize 0scales 归一化当scalesD/H/W均大于 0 时透传用户值、并把outputSize置为空数组否则向 kernel 传{0, 0, 0}的 scales由 kernel 侧依据outputSize/inputSize反推L222-L234。这与功能说明中 scale 的分段定义严格一致。注意文档参数表中gradOut、gradInput标记不支持空Tensor此处短路分支可理解为框架层的防御性处理。非连续 Tensor 拉直对gradOut调用l0op::Contiguous数据格式归一若gradOut存储格式为 NDHWC则先用l0op::Transposepermute 为{0, 4, 1, 2, 3}转为 NCDHW 再进入 kernel计算结果再按{0, 2, 3, 4, 1}转回 NDHWCL236-L256。从源码结构看kernel 本体只处理 NCDHW 布局NDHWC 通过前后两次转置支持这正是参数表同时列出 NCDHW、NDHWC 两种格式的原因。核心计算调用l0op::UpsampleNearestExact3dGradNcdhw生成gradInput中间结果结果写回l0op::ViewCopy把结果拷贝到可能非连续的gradInput输出张量上最后由GetWorkspaceSize()汇总整条链路的 workspace 需求。L0 封装 UpsampleNearestExact3dGradNcdhw 还负责输出 shape 构造以inputSize的 D、H、W 覆盖gradOut的对应维度以及低精度适配在非 regbase 平台上BFLOAT16/FLOAT16 输入会先Cast为 FLOAT 参与计算结果再Cast回原类型L58-L73保证半精度下的累加精度行为一致。Kernel 级实现SIMT 三级切分与累加窗口device 侧入口 upsample_nearest_exact3d_grad_apt.cpp 按调度模板schId分支schId 0时退化为纯拷贝输出完全等于输入否则实例化Nearest3dGradSimtDTYPE_GRAD_OUTPUT, uint32_t/uint64_t, true, schId执行真正的梯度累加。该实现复用了 upsample_nearest3d_grad 的 arch35 共享代码。从 upsample_nearest3d_grad_simt_base.h 可以读出与文档公式逐式对应的三层设计窗口边界计算ComputeOrigT2, isExtra(D, lenSrcD, scaleD, origD)依次求出origD/origH/origW即 srcD/srcH/srcW与D1/H1/W1对应的上界srcDUp/srcHUp/srcWUp并用min(orig, limit)钳位到输出尺寸——对应公式中Min(ceil(scale*(D1)-0.5), outputSize[0])的形式累加实现ComputeForSplitNcdhwL45-L60对d ∈ [origD, origDUp)、h ∈ [origH, origHUp)、w ∈ [origW, origWUp)三重循环求和gradOut累加过程使用float中间量最后写回outputGm[yGmIdx]——这正是文档中三重求和公式的逐行实现数据并行切分SimtComputeL104-L154将输出体展平索引按schId分为三类任务SCH_ID_1固定 N、C 只对 D/H/W 切分SCH_ID_2固定 N 按 C 切分SCH_ID_3对 N 切分每个任务块内部再以魔数除法GetUintDivMagicAndShift快速还原(D, H, W)坐标。线程数按索引位宽选择uint32 索引 2048 线程、uint64 索引 1024 线程upsample_nearest3d_grad_simt.h L81-L91。结合文档的 60GB 内存公式可以推断公式中额外的两项gradOut_D*gradOut_H*gradInput_W、gradOut_D*gradInput_H*gradInput_W即为主机侧为 NDHWC 前后转置与中间结果准备的临时缓冲预算上限。图模式IR调用与属性默认值除 aclnn 接口外该算子也可通过算子 IR 以图模式构图调用。算子名为UpsampleNearestExact3dGrad其输入输出与属性定义为参数名类型描述数据类型grad_output输入反向计算的梯度 Tensor对应公式中的gradOutput。FLOAT32、FLOAT16、BFLOAT16input_size属性必填输出分别在 N、C、D、H、W 维度上的空间大小size 为 5 且各元素大于零必须满足input_size[0] grad_output 的 N、input_size[1] grad_output 的 C。LISTINToutput_size属性可选输入grad_output在 D、H、W 维度上的空间大小size 为 3 且各元素大于零默认值{0, 0, 0}。LISTINTscales属性可选沿每个维度的缩放数组3 个元素分别对应scalesD、scalesH、scalesW默认值{0.0, 0.0, 0.0}。LISTFLOATy输出反向计算的输出张量对应公式中的gradInput类型与格式与grad_output一致shape 由input_size决定。FLOAT32、FLOAT16、BFLOAT16可见 aclnn 接口中scalesD/H/W为 0 且使用outputSize的用法等价于图模式下只填input_sizescales取默认值的场景两条路径语义一致。调用示例以下示例代码继承自接口文档可直接作为接入模板具体编译与执行流程请参考编译与运行样例。示例选取了一个 2 倍下采样反向前向的场景gradOut形状为{2, 2, 2, 2, 2}NCDHWgradInput形状为{2, 2, 1, 1, 1}scales全 0 走outputSize反推路径期望每个输入点累加对应 2×2×28 个输出梯度。#include iostream #include vector #include acl/acl.h #include aclnnop/aclnn_upsample_nearest_exact3d_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 shape_size 1; for (auto i : shape) { shape_size * i; } return shape_size; } 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_NCDHW, 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根据自己的需要处理 CHECK_RET(ret 0, LOG_PRINT(Init acl failed. ERROR: %d\n, ret); return ret); // 2. 构造输入与输出需要根据API的接口自定义构造 std::vectorint64_t gradOutShape {2, 2, 2, 2, 2}; std::vectorint64_t gradInputShape {2, 2, 1, 1, 1}; void* gradOutDeviceAddr nullptr; void* gradInputDeviceAddr nullptr; aclTensor* gradOut nullptr; aclTensor* gradInput nullptr; std::vectorfloat gradOutHostData {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; std::vectorfloat gradInputHostData {2.0, 2, 2, 2}; std::vectorint64_t outputSizeData {2, 2, 2}; std::vectorint64_t inputSizeData {2, 2, 1, 1, 1}; double scalesD 0.0; double scalesH 0.0; double scalesW 0.0; // 创建gradOut aclTensor ret CreateAclTensor(gradOutHostData, gradOutShape, gradOutDeviceAddr, aclDataType::ACL_FLOAT, gradOut); CHECK_RET(ret ACL_SUCCESS, return ret); // 创建gradInput aclTensor ret CreateAclTensor(gradInputHostData, gradInputShape, gradInputDeviceAddr, aclDataType::ACL_FLOAT, gradInput); CHECK_RET(ret ACL_SUCCESS, return ret); const aclIntArray* outputSize aclCreateIntArray(outputSizeData.data(), outputSizeData.size()); CHECK_RET(outputSize ! nullptr, return ACL_ERROR_INTERNAL_ERROR); const aclIntArray* inputSize aclCreateIntArray(inputSizeData.data(), inputSizeData.size()); CHECK_RET(inputSize ! nullptr, return ACL_ERROR_INTERNAL_ERROR); // 3. 调用CANN算子库API需要修改为具体的API uint64_t workspaceSize 0; aclOpExecutor* executor; // 调用aclnnUpsampleNearestExact3dBackward第一段接口 ret aclnnUpsampleNearestExact3dBackwardGetWorkspaceSize(gradOut, outputSize, inputSize, scalesD, scalesH, scalesW, gradInput, workspaceSize, executor); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnUpsampleNearestExact3dBackwardGetWorkspaceSize 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); } // 调用aclnnUpsampleNearestExact3dBackward第二段接口 ret aclnnUpsampleNearestExact3dBackward(workspaceAddr, workspaceSize, executor, stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnUpsampleNearestExact3dBackward 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(gradInputShape); std::vectorfloat resultData(size, 0); ret aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), gradInputDeviceAddr, size * sizeof(float), 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和aclScalar需要根据具体API的接口定义修改 aclDestroyTensor(gradOut); aclDestroyTensor(gradInput); // 7. 释放device资源需要根据具体API的接口定义修改 aclrtFree(gradOutDeviceAddr); aclrtFree(gradInputDeviceAddr); if (workspaceSize 0) { aclrtFree(workspaceAddr); } aclrtDestroyStream(stream); aclrtResetDevice(deviceId); aclFinalize(); return 0; }该示例的完整可编译版本含资源释放与错误处理细节见仓库样例 test_aclnn_upsample_nearest_exact3d_grad.cpp。测试体系与正确性验证仓库围绕该算子提供了分层测试可作为行为验证的依据主机侧接口 UTtest_aclnn_upsample_nearest_exact3d_backward.cpp 覆盖第一段接口的参数校验路径Kernel UTtest_upsample_nearest_exact3d_grad.cpp 配合数据生成与对比脚本gen_data.py、compare_data.py对 kernel 数值进行比对系统级ST标杆测试executor_aclnnUpsampleNearestExact3dBackward.py 以 PyTorch 的upsample_nearest_exact3d_backwardtorch_npu 后端作为标杆正向计算与算子输出做一致性对比进一步印证该算子与框架语义含 -0.5 偏移对齐。小结aclnnUpsampleNearestExact3dBackward是 5D 张量NCDHW/NDHWC最近邻精确上采样的梯度接口数学本质是对输出侧梯度在srcD..srcDUp等三维窗口内求和-0.5偏移是其Exact语义的来源调用遵循两段式接口第一段完成入参校验161001/161002 错误码体系、workspace 计算与 L0 算子链编排第二段在指定 stream 上执行实现上支持 FLOAT32/FLOAT16/BF16 三种类型与 NCDHW/NDHWC 两种格式NDHWC 经前后转置支持scales 与 outputSize 两种指定方式语义等价缩小倍数上限 50shape 与 60GB 内存约束需在调用前自查深入阅读入口主机侧校验与编排在 op_host/op_api/aclnn_upsample_nearest_exact3d_backward.cppL0 封装在 op_host/op_api/upsample_nearest_exact3d_grad.cppkernel 计算核心在 arch35/upsample_nearest3d_grad_simt_base.h。【免费下载链接】ops-cv本项目是CANN提供的图像处理、目标检测相关的算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-cv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考