尧图精选

CANN ops-nn 可变形卷积算子 aclnnDeformableConv2d 全解析:两段式接口、双线性插值原理与 NPU 实现

🕒 发布时间:2026/9/19 13:20:04 📁 来源:尧图网络
CANN ops-nn 可变形卷积算子 aclnnDeformableConv2d 全解析两段式接口、双线性插值原理与 NPU 实现【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-nn本文以 CANN ops-nn 仓库中 aclnnDeformableConv2d 接口文档 为核心系统讲解可变形卷积Deformable Conv2D在 Atlas NPU 上的实现方式与调用方法。你将掌握该算子的计算公式与双线性插值原理、两段式 aclnn 接口的函数原型与每个参数的确切约束、常见错误码的含义以及如何基于仓库示例在 Device 上完成一次可变形卷积的前向计算最后结合源码深入理解其在 AI Core 上的 tiling 与 kernel 实现。一、算子功能与产品支持情况aclnnDeformableConv2d是 CANN ops-nn 仓库conv/deformable_conv2d 目录提供的神经网络计算算子实现 2D 卷积功能同时支持可变形卷积与分组卷积。相比普通卷积可变形卷积通过额外的 offset偏移量张量使每个采样点可以在空间上自由偏移从而自适应地建模几何形变被广泛应用于目标检测、语义分割等视觉任务。算子原型定义在 deformable_conv2d_def.cpp其中通过AICore().AddConfig(ascend910b)与AICore().AddConfig(ascend910_93)声明了算子适配的 AI Core 平台配置。接口级的产品支持情况如下表产品是否支持Ascend 950PR/Ascend 950DT支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品支持Atlas 200I/500 A2 推理产品不支持Atlas 推理系列产品不支持Atlas 训练系列产品不支持二、数学原理与计算公式假定输入input的 shape 为[N, inC, inH, inW]输出out的 shape 为[N, outC, outH, outW]本接口采用 NCHW 视角与 README.md 中 NHWC 视角的写法相对应。1. 输出尺寸计算$$ outH (inH padding[0] padding[1] - ((K_H - 1) * dilation[2] 1)) // stride[2] 1 $$$$ outW (inW padding[2] padding[3] - ((K_W - 1) * dilation[3] 1)) // stride[3] 1 $$即输出尺寸由输入尺寸、padding上/下/左/右四侧、卷积核尺寸 K_H、K_W、dilation膨胀系数与 stride步长共同决定。2. 标准卷积采样点下标标准卷积在输出位置 (oh, ow) 处的采样点下标为$$ x -padding[2] owstride[3] kwdilation[3], \quad kw \in (0, K_W-1) $$$$ y -padding[0] ohstride[2] khdilation[2], \quad kh \in (0, K_H-1) $$3. 可变形偏移根据传入的 offset 张量对采样点施加偏移$$ (x,y) (x offsetX, y offsetY) $$4. 双线性插值偏移后的坐标通常不是整数需要取周围四个像素做双线性插值。取$$ (x_{0}, y_{0}) (int(x), int(y)), \quad (x_{1}, y_{1}) (x_{0} 1, y_{0} 1) $$四个插值权重为$$ weight_{00} (x_{1} - x) * (y_{1} - y) \ weight_{01} (x_{1} - x) * (y - y_{0}) \ weight_{10} (x - x_{0}) * (y_{1} - y) \ weight_{11} (x - x_{0}) * (y - y_{0}) $$插值结果为$$ deformOut(x, y) weight_{00} * input(x0, y0) weight_{01} * input(x0,y1) weight_{10} * input(x1, y0) weight_{11} * input(x1,y1) $$5. 卷积输出对插值结果执行常规卷积得到最终输出$$ \text{out}(N_i, C_{\text{out}j}) \text{bias}(C{\text{out}j}) \sum{k 0}^{C_{\text{in}} - 1} \text{weight}(C_{\text{out}_j}, k) \star \text{deformOut}(N_i, k) $$源码印证上述求标准下标 → 施加偏移 → 计算四邻域权重 → 双线性插值 → 卷积的计算流水线在 deformable_conv2d_base.h 的Process()主流程中一一对应CalculateStandard获取标准卷积原图像下标→AdjustStandard相邻 tile 下标复用→CalculateWeight计算周围四个点的权重→ProcessZero→BilinearInterp/BilinearInterpSmallC双线性插值小通道数走专用路径→Conv2d矩阵乘卷积。三、两段式接口与函数原型每个 aclnn 算子采用两段式接口先调用aclnnDeformableConv2dGetWorkspaceSize完成入参校验、构图并返回计算所需 workspace 大小与包含算子计算流程的执行器再调用aclnnDeformableConv2d传入 Device 侧申请的 workspace 与 executor真正执行计算。aclnnStatus aclnnDeformableConv2dGetWorkspaceSize( const aclTensor* x, const aclTensor* weight, const aclTensor* offset, const aclTensor* biasOptional, const aclIntArray* kernelSize, const aclIntArray* stride, const aclIntArray* padding, const aclIntArray* dilation, int64_t groups, int64_t deformableGroups, bool modulated, aclTensor* out, aclTensor* deformOutOptional, uint64_t* workspaceSize, aclOpExecutor** executor)aclnnStatus aclnnDeformableConv2d( void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream)源码印证两段式接口的实现位于 aclnn_deformable_conv2d.cpp。第一段接口在创建 executor 后依次执行CheckParams五步校验空指针 → 数据类型 → 数据格式 → 属性 → shape与CalculateDeformableConv2d构图并通过uniqueExecutor-GetWorkspaceSize()汇总 workspace 大小最后把 executor 所有权转移给调用方第二段接口则直接调用框架统一的CommonOpExecutorRun完成执行。四、aclnnDeformableConv2dGetWorkspaceSize 参数详解1. 参数说明参数名输入/输出描述使用说明数据类型数据格式维度(shape)非连续Tensorx输入表示输入的原始数据对应公式中的input不支持空 Tensorshape 为 [N, inC, inH, inW]其中 inH * inW 不能超过 2147483647FLOAT32、FLOAT16、BFLOAT16ND、NCHW4√weight输入表示可学习过滤器的 4D 张量对应公式中的weight不支持空 Tensor数据类型、数据格式与入参x保持一致shape 为 [outC, inC/groups, K_H, K_W]FLOAT32、FLOAT16、BFLOAT16ND、NCHW4√offset输入表示 x-y 坐标偏移和掩码的 4D 张量对应公式中的offset不支持空 Tensor数据类型、数据格式与入参x保持一致modulated为 True 时 shape 为 [N, 3 * deformableGroups * K_H * K_W, outH, outW]为 False 时为 [N, 2 * deformableGroups * K_H * K_W, outH, outW]FLOAT32、FLOAT16、BFLOAT16ND、NCHW4√biasOptional输入可选输入参数表示过滤器输出附加偏置的 1D 张量对应公式中的bias不支持空 Tensor数据类型与入参x保持一致不需要时为空指针存在时 shape 为 [outC]FLOAT32、FLOAT16、BFLOAT16ND1√kernelSize输入表示卷积核大小对应公式中的K_H、K_Wsize 为 2K_H, K_W各元素均大于零K_H * K_W 不能超过 2048K_H * K_W * inC/groups 不能超过 65535aclIntArray---stride输入表示每个输入维度的滑动窗口步长对应公式中的stridesize 为 4各元素均大于零维度顺序根据x的数据格式解释N 维和 C 维必须设置为 1aclIntArray---padding输入表示要添加到输入每侧顶部、底部、左侧、右侧的像素数对应公式中的paddingsize 为 4aclIntArray---dilation输入表示输入每个维度的膨胀系数对应公式中的dilationsize 为 4各元素均大于零维度顺序根据x的数据格式解释N 维和 C 维必须设置为 1aclIntArray---groups输入表示从输入通道到输出通道的分组连接数inC 和 outC 需都可被 groups 整除groups 大于零INT64---deformableGroups输入表示可变形组分区的数量inC 需可被 deformableGroups 整除deformableGroups 大于零INT64---modulated输入预留参数表示 offset 中是否包含掩码为 true 时 offset 中包含掩码为 false 时不包含当前只支持 trueBOOL---out输出表示输出的数据对应公式中的out不支持空 Tensor数据类型、数据格式与x保持一致shape 为 [N, outC, outH, outW]FLOAT32、FLOAT16、BFLOAT16ND、NCHW4√deformOutOptional输出可选输出表示可变形卷积采样点对应公式中的deformOut不支持空 Tensor数据类型、数据格式与x保持一致shape 为 [N, inC, outH * K_H, outW * K_W]FLOAT32、FLOAT16、BFLOAT16ND、NCHW4√workspaceSize输出返回需要在 Device 侧申请的 workspace 大小-----executor输出返回 op 执行器包含了算子计算流程-----源码印证参数表中的关键数值约束与 aclnn_deformable_conv2d.cpp 中的校验常量一一对应MAX_KERNEL_SIZE 2048、MAX_MATMUL_K 65535、INT_MAX_VALUE 2147483647并分别由CheckAttrs校验 kernelSize 尺寸 2、stride/padding/dilation 尺寸 4、K_HK_W 上限、stride/dilation 前两维为 1、groups/deformableGroups 大于零、modulated 必须为 true与CheckShape校验 inC 可被 deformableGroups 和 groups 整除、outC 可被 groups 整除、inHinW 上限、kH*kW*inC/groups 65535落地。CheckExpected还会依据公式反推 weight、offset、bias、out、deformOut 的期望 shape 并与实际传入做严格比对因此调用时 shape 必须与公式推导一致否则直接返回错误。2. 返回值与错误码第一段接口完成入参校验出现以下场景时报错返回码定义参见 aclnn 返回码返回码错误码描述ACLNN_ERR_PARAM_NULLPTR161001传入的 x、weight、offset、out 是空指针ACLNN_ERR_PARAM_INVALID161002x、weight、offset、out 的数据类型或数据格式不在支持的范围之内ACLNN_ERR_PARAM_INVALID161002deformOutOptional 不为空指针时数据类型或数据格式不在支持的范围之内ACLNN_ERR_PARAM_INVALID161002biasOptional 不为空指针时数据类型或数据格式不在支持的范围之内ACLNN_ERR_PARAM_INVALID161002x、weight、offset、biasOptional、out、deformOutOptional 的 shape 与参数说明中不一致ACLNN_ERR_PARAM_INVALID161002kernelSize、stride、padding、dilation 的 size 与参数说明中不一致ACLNN_ERR_PARAM_INVALID161002K_HK_W 超过 2048或者 K_HK_W*inC/groups 超过 65535源码印证CheckParams中的 161001/161002 返回码路径与上表逐条对应CheckNotNull失败返回ACLNN_ERR_PARAM_NULLPTRCheckDtypeValid、CheckFormat、CheckAttrs、CheckDimension、CheckShape任一失败均返回ACLNN_ERR_PARAM_INVALID。五、aclnnDeformableConv2d 执行接口参数参数名输入/输出描述workspace输入在 Device 侧申请的 workspace 内存地址workspaceSize输入在 Device 侧申请的 workspace 大小由第一段接口 aclnnDeformableConv2dGetWorkspaceSize 获取executor输入op 执行器包含了算子计算流程stream输入指定执行任务的 Stream返回值aclnnStatus状态码。六、约束说明确定性计算aclnnDeformableConv2d 默认确定性实现即相同输入与参数下多次执行结果可复现。数据格式按产品差异Atlas A2/A3 训练与推理系列产品支持 ND、NCHW 两种格式Ascend 950PR/Ascend 950DT 仅支持 NCHW。其余产品不受支持。七、调用示例与逐步解析示例代码参见仓库 examples/test_aclnn_deformable_conv2d.cpp编译与运行样例的具体流程可参考编译与运行样例。核心代码如下#include iostream #include vector #include acl/acl.h #include aclnnop/aclnn_deformable_conv2d.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]; } auto format shape.size() 1 ? ACL_FORMAT_ND : ACL_FORMAT_NCHW; // 调用aclCreateTensor接口创建aclTensor *tensor aclCreateTensor( shape.data(), shape.size(), dataType, strides.data(), 0, format, 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 xShape {1, 6, 2, 4}; std::vectorint64_t weightShape {4, 3, 5, 5}; std::vectorint64_t offsetShape {1, 75, 2, 4}; std::vectorint64_t biasShape {4}; std::vectorint64_t outShape {1, 4, 2, 4}; std::vectorint64_t deformOutShape {1, 6, 10, 20}; std::vectorint64_t kernelSize {5, 5}; std::vectorint64_t stride {1, 1, 1, 1}; std::vectorint64_t padding {2, 2, 2, 2}; std::vectorint64_t dilation {1, 1, 1, 1}; int64_t groups 2; int64_t deformableGroups 1; void* xDeviceAddr nullptr; void* weightDeviceAddr nullptr; void* offsetDeviceAddr nullptr; void* biasDeviceAddr nullptr; void* outDeviceAddr nullptr; void* deformOutDeviceAddr nullptr; aclTensor* x nullptr; aclTensor* weight nullptr; aclTensor* offset nullptr; aclTensor* bias nullptr; aclTensor* out nullptr; aclTensor* deformOut nullptr; std::vectorfloat xHostData(1 * 6 * 2 * 4, 1); std::vectorfloat weightHostData(4 * 3 * 5 * 5, 1); std::vectorfloat offsetHostData(1 * 75 * 2 * 4, 1); std::vectorfloat biasHostData(4, 0); std::vectorfloat outHostData(1 * 4 * 2 * 4, 0); std::vectorfloat deformOutHostData(1 * 6 * 10 * 20, 0); // 创建x aclTensor ret CreateAclTensor(xHostData, xShape, xDeviceAddr, aclDataType::ACL_FLOAT, x); 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); // 创建offset aclTensor ret CreateAclTensor(offsetHostData, offsetShape, offsetDeviceAddr, aclDataType::ACL_FLOAT, offset); CHECK_RET(ret ACL_SUCCESS, return ret); // 创建bias aclTensor ret CreateAclTensor(biasHostData, biasShape, biasDeviceAddr, aclDataType::ACL_FLOAT, bias); 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); // 创建deformOut aclTensor ret CreateAclTensor(deformOutHostData, deformOutShape, deformOutDeviceAddr, aclDataType::ACL_FLOAT, deformOut); CHECK_RET(ret ACL_SUCCESS, return ret); // 创建kernelSize aclIntArray const aclIntArray* kernelSizeArray aclCreateIntArray(kernelSize.data(), kernelSize.size()); CHECK_RET(kernelSizeArray ! nullptr, return ret); // 创建stride aclIntArray const aclIntArray* strideArray aclCreateIntArray(stride.data(), stride.size()); CHECK_RET(strideArray ! nullptr, return ret); // 创建padding aclIntArray const aclIntArray* paddingArray aclCreateIntArray(padding.data(), padding.size()); CHECK_RET(paddingArray ! nullptr, return ret); // 创建dilation aclIntArray const aclIntArray* dilationArray aclCreateIntArray(dilation.data(), dilation.size()); CHECK_RET(dilationArray ! nullptr, return ret); // 3. 调用CANN算子库API需要修改为具体的API uint64_t workspaceSize 0; aclOpExecutor* executor; // 调用aclnnDeformableConv2d第一段接口 ret aclnnDeformableConv2dGetWorkspaceSize( x, weight, offset, bias, kernelSizeArray, strideArray, paddingArray, dilationArray, groups, deformableGroups, true, out, deformOut, workspaceSize, executor); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnDeformableConv2dGetWorkspaceSize 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); } // 调用aclnnDeformableConv2d第二段接口 ret aclnnDeformableConv2d(workspaceAddr, workspaceSize, executor, stream); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclnnDeformableConv2d 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(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(x); aclDestroyTensor(weight); aclDestroyTensor(offset); aclDestroyTensor(bias); aclDestroyTensor(out); aclDestroyTensor(deformOut); // 7. 释放device资源需要根据具体API的接口定义修改 aclrtFree(xDeviceAddr); aclrtFree(weightDeviceAddr); aclrtFree(offsetDeviceAddr); aclrtFree(biasDeviceAddr); aclrtFree(outDeviceAddr); aclrtFree(deformOutDeviceAddr); if (workspaceSize 0) { aclrtFree(workspaceAddr); } aclrtDestroyStream(stream); aclrtResetDevice(deviceId); aclFinalize(); return 0; }示例 shape 的公式自洽性验证示例中各 shape 并非随意取值而是严格满足第一节的公式可作为自查调用参数是否合法的快速方法输入 x 为 [1, 6, 2, 4]kernelSize 为 [5, 5]stride/padding/dilation 均为全 1/全 2/全 1outH (2 2 2 − ((5−1)*1 1)) // 1 1 (6 − 5) 1 2outW (4 2 2 − 5) // 1 1 4故 out [1, 4, 2, 4] 成立weight 为 [outC, inC/groups, K_H, K_W] [4, 6/2, 5, 5] [4, 3, 5, 5]groups 2 成立modulated true 时 offset 通道数 3 * deformableGroups * K_H * K_W 3 * 1 * 25 75offset [1, 75, 2, 4] 成立deformOut 为 [N, inC, outHK_H, outWK_W] [1, 6, 25, 45] [1, 6, 10, 20] 成立。调用流程可归纳为七个步骤设备与 Stream 初始化 → 构造输入输出 aclTensor 与 aclIntArray → 调用第一段接口获取 workspaceSize 与 executor → 申请 workspace → 调用第二段接口执行 → 同步等待与回拷结果 → 释放资源。八、底层实现剖析tiling 与 kernel 流水1. workspace 估算与核切分在 deformable_conv2d_tiling.cpp 中RunBigKernelTiling根据数据类型的字节数预留 workspaceworkspaces[0] (n * outH * outW * kH * kW * inC) * dataTypeSize 16MB 预留SplitCore将n * outH维度的滑动向量按 AI Core 核数均分singleVecNum/tailVecNum同时根据deformableGroups * kH * kW与 2048 的关系决定 W 方向滑动粒度slideSizeW与分组粒度groupLenGetTCubeTiling则调用 matmul_tiling 库以outC/groups × outW × kH*kW*inC/groups作为矩阵乘的原型 shape 完成 Cube 侧 tiling。2. kernel 主循环deformable_conv2d_base.h 中的Process()展示了完整的 AI Core 流水for slideIdx in [slideStart, slideEnd): // 核内分配的 (n, outH) 向量 for ow in 0..outW step slideSizeW: // W 方向滑窗 for g in 0..deformableGroups step groupLen: // 可变形组滑窗 CopyInOffset // 拷入 x-y 偏移与掩码 CalculateStandard / AdjustStandard // 标准采样下标计算/复用 CalculateWeight // 计算四邻域插值权重 ProcessZero // 越界采样点置零处理 BilinearInterp / BilinearInterpSmallC // 双线性插值产出 deformOut Conv2d // 对 deformOut 做 matmul 卷积kernel 内部使用 VECCALC 上的多块TBuf缓冲xyBuf、offsetBuf、weightBuf、indexBuf、maskBuf、inputBuf 等承载中间数据并通过AllocEventID建立 V_MTE2、MTE2_V、V_MTE3、V_S、S_V、MTE3_V 等事件完成向量、搬运与标量单元间的流水同步。3. 平台分叉与精度策略在 aclnn_deformable_conv2d.cpp 的CalculateDeformableConv2d中可以看到明显的平台分叉Ascend 950 系列DAV_3510输入经Contiguous处理后直接保持 NCHW走DeformableConv2dV2路径——先调用DeformableOffsetsNHWC得到 deformOut再复用卷积前向的Conv2dV2NCHW完成分组卷积Atlas A2/A3 系列输入先经InputTransProcess做Contiguous与 Transposeperm {0,2,3,1}转换为 NHWC 内部布局若输入为 FLOAT16/BFLOAT16还会先 Cast 到 FLOAT32 计算以获得更高精度再在ResultViewProcess中 Cast 回原精度、经 Transposeperm {0,2,1,3}与ViewCopy写回用户 outbias 则通过Reshape为 [1,1,outC,1] 后以Add形式叠加。由此可以推断用户侧即使以 NCHW 视图传入数据框架内部也会完成布局转换与FP16/BF16 场景下的升精度计算最终输出与用户期望的 NCHW 布局一致。九、测试与验证仓库在 tests/st/aclnnDeformableConv2d/atk_aclnnDeformableConv2d.json 提供了大量随机化 st 测试用例覆盖 fp16/bf16/fp32 三种数据类型kernelSize 从 1×1 到 5×5、stride/dilation 从 1 到 10、padding 从 0 到 10、groups 从 1 到 5、deformableGroups 从 1 到 31 的广泛组合并配合 executor_aclnnDeformableConv2d.py 完成用例执行UT 侧另有 op_host 的接口级单测test_aclnn_deformable_conv2d.cpp与 tiling 单测test_deformable_conv2d_tiling.cpp可用于回归验证接口校验逻辑与 tiling 计算。十、关键文件索引接口文档conv/deformable_conv2d/docs/aclnnDeformableConv2d.md算子 READMEconv/deformable_conv2d/README.md两段式接口实现conv/deformable_conv2d/op_host/op_api/aclnn_deformable_conv2d.cpp算子原型定义conv/deformable_conv2d/op_host/deformable_conv2d_def.cpptiling 实现conv/deformable_conv2d/op_host/deformable_conv2d_tiling.cppkernel 入口与核心逻辑conv/deformable_conv2d/op_kernel/deformable_conv2d.cpp、conv/deformable_conv2d/op_kernel/deformable_conv2d_base.h可运行示例conv/deformable_conv2d/examples/test_aclnn_deformable_conv2d.cpp【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-nn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →