
CANN ops-cv GridSampler2D 算子完全指南二维网格采样、坐标变换与 NPU 实现解析【免费下载链接】ops-cv本项目是CANN提供的图像处理、目标检测相关的算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-cv本文围绕 CANN ops-cv 仓库中的 GridSampler2D 算子文档系统讲解该算子的功能语义、坐标变换公式、参数与约束、NPU 侧的实现链路并结合仓库源码算子定义、InferShape、Tiling、SIMT Kernel 与图模式示例给出可直接落地使用的调用方式。读完本文你将掌握在 Ascend 平台上通过 GE IR 构图调用 GridSampler2D 的完整方法并理解其与 PyTorchgrid_sample对齐的插值、填充与精度处理细节。产品支持情况GridSampler2D 算子在当前仓库中面向以下产品提供支持摘自 README产品是否支持Ascend 950PR/Ascend 950DT√Atlas A3 训练系列产品/Atlas A3 推理系列产品√Atlas A2 训练系列产品/Atlas A2 推理系列产品√Atlas 200I/500 A2 推理产品×Atlas 推理系列产品×Atlas 训练系列产品×从源码结构看算子的宿主侧实现存放于 op_host/arch35内核实现位于 op_kernel/arch35二进制配置注册于 op_host/config/ascend950/grid_sampler2_d_binary.json可以推断当前版本主要面向 arch35Ascend 950 系列编译与验证。功能说明算子语义GridSampler2D 根据grid提供的归一化坐标对四维输入x进行二维网格采样支持**双线性bilinear、最近邻nearest和双三次bicubic**三种插值方式。该算子与 PyTorch 的grid_sample语义兼容这一点在算子原型注释中明确说明见 grid_sampler2_d_proto.h。输入输出尺寸各张量的 shape 约定如下$$ x: (N, C, H_{in}, W_{in}) $$$$ grid: (N, H_{out}, W_{out}, 2) $$$$ y: (N, C, H_{out}, W_{out}) $$grid的最后一维依次存放 x 和 y 坐标坐标通常归一化到[-1, 1]。实际输入坐标由align_corners决定align_cornerstrue角像素中心对齐$$ x \frac{grid_x 1}{2}(W_{in}-1), \quad y \frac{grid_y 1}{2}(H_{in}-1) $$align_cornersfalse像素中心位于半像素偏移处$$ x \frac{(grid_x 1)W_{in}-1}{2}, \quad y \frac{(grid_y 1)H_{in}-1}{2} $$越界坐标按照padding_mode指定的zeros、border或reflection方式处理再按照interpolation_mode指定的bilinear、nearest或bicubic方式计算输出。内核中对这两种归一化路径有完整实现UnnormalizeNoClip对应上述两套公式其中align_cornersfalse路径使用fmaf(scalingFactor, coord 1.0f, -0.5f)单次舍入以对齐 PyTorch x86 编译产物的 FMA 行为见 grid_sampler2_d_simt.h。参数说明以下参数表完整继承自 GridSampler2D 算子文档参数名输入/输出/属性描述数据类型数据格式x输入输入特征图shape 为 (N, C, H_in, W_in)。FLOAT16、FLOAT32NCHWgrid输入采样网格shape 为 (N, H_out, W_out, 2)数据类型必须与 x 一致。FLOAT16、FLOAT32NHWCinterpolation_mode可选属性插值模式支持 bilinear、nearest 和 bicubic默认值为 bilinear。STRING-padding_mode可选属性填充模式支持 zeros、border 和 reflection默认值为 zeros。STRING-align_corners可选属性是否将输入和输出的角像素中心对齐默认值为 false。BOOL-y输出采样结果shape 为 (N, C, H_out, W_out)数据类型与 x 一致。FLOAT16、FLOAT32NCHW上述参数在算子原型注册中均有对应定义见 grid_sampler2_d_proto.hx、grid、y均仅支持DT_FLOAT16/DT_FLOAT三个属性均为可选属性interpolation_mode默认bilinear、padding_mode默认zeros、align_corners默认false。在宿主侧算子定义grid_sampler2_d_def.cpp中可以看到更细的格式约定x为FORMAT_NCHWgrid为FORMAT_ND输出y为FORMAT_NCHW三者均声明为AutoContiguous()该定义同时开启了动态 Shape、动态 Rank 支持DynamicShapeSupportFlag(true)、DynamicRankSupportFlag(true)并注册了ascend950的 AICore 配置ExtendCfgInfo(opFile.value, grid_sampler2_d_apt)、ExtendCfgInfo(opInterface.value, grid_sampler2_d)。约束说明x与grid均为 4 维张量数据类型一致且仅支持float16或float32。grid的最后一维必须为 2且x与grid的 batch 维必须一致。x的H_in和W_in必须大于 0grid产生空输出时支持空 tensor。x的高宽乘积、grid的 batch 与输出高宽乘积均不能超过INT32_MAX。interpolation_mode仅支持bilinear、nearest、bicubic。padding_mode仅支持zeros、border、reflection。这些约束在代码中有两层校验InferShape 阶段grid_sampler2_d_infershape.cpp校验x/grid均为 4 维、grid最后一维为 2未知维UNKNOWN_DIM除外、batch 一致、输入高宽大于 0随后推导输出 shape——y的N取x的 batch、C取x的通道、H/W取grid的 H/W。数据类型校验则在图推导阶段grid_sampler2_d_graph_infer.cpp完成要求grid与x同类型且输出数据类型继承自x。Tiling 阶段grid_sampler2_d_tiling.cpp再次核对维度数、grid最后一维为 2、batch 一致、各维非负且输入高宽大于 0并做INT32_MAX溢出防护——H_in * W_in与N * H_out * W_out均不能超过INT32_MAX。Tiling 同时把三个属性字符串解析为整型枚举interpolation_mode映射为 0bilinear、1nearest、2bicubicpadding_mode映射为 0zeros、1border、2reflection见 grid_sampler2_d_tiling.cpp。算子实现原理源码级1. Tiling 与核间划分Tiling 逻辑位于 grid_sampler2_d_tiling.cpp核心步骤通过平台接口获取 AIV 核数coreNum与 UB 内存大小ubSize计算输出像素总数totalPixels N * H_out * W_out采用“两步核划分”策略先按perCoreElements CeilDiv(totalPixels, coreNum)估算每核元素数若小于PER_CORE_MIN8192则抬高到 8192再反推实际需要的核数needCoreNum从而在小张量场景下避免过度占用核资源预留DCACHE_SIZE128 KiB后设置本地内存大小将interpolationMode编码进 TilingKey0/1/2使内核在编译期通过模板参数分发到 bilinear/nearest/bicubic 三条路径见 grid_sampler2_d_tiling.cpp。Tiling 数据结构定义在 grid_sampler2_d_tiling_data.h包含N/C/H_in/W_in/H_out/W_out以及三个属性枚举。2. SIMT Kernel 与坐标处理内核实现为 SIMTSingle Instruction Multiple Threads风格入口见 grid_sampler2_d_apt.cpp通过DTYPE_X宏自动按数据类型实例化interpMode由 TilingKey 在编译期确定。核心逻辑在 grid_sampler2_d_simt.h线程组织索引宽度模板化——最大地址不超过INT32_MAX时使用int32_t索引每 block 1024 线程否则退化为int64_t索引512 线程除法优化idx / WOut、hw / HOut等常量除法被替换为Simt::UintDivmagic number shift避免除法指令开销坐标计算ComputeSourceIndex依次执行反归一化UnnormalizeNoClip、按padding_mode处理zeros不做裁剪、border做ClipCoordinates、reflection先ReflectCoordinates再裁剪、NaN 坐标归零等三种插值BilinearSample取坐标 floor 后的四个邻域像素按双线性权重加权NearestSample采用BankerRoundToInt四舍六入五成双即 PyTorch 默认的 round-half-to-even确定最近邻BicubicSample使用A -0.75的三次卷积核CubicConvolution1/2先在 x 方向对 4×4 邻域做 4 次加权和再在 y 方向聚合。精度对齐代码注释详细记录了与 PyTorch CPU 向量化内核逐位对齐的调优过程——对 float32 双三次路径反归一化与加权和采用fmaf()匹配 PyTorch x86 的 FMA 链而三次卷积系数计算则通过volatile变量 文件级#pragma clang fp contract(off)禁止 FMA 合并NPU 的 fmaf 舍入行为与 x86 不同从而在 NPU 上复现 PyTorch 的舍入语义见 grid_sampler2_d_simt.h。3. 二进制注册grid_sampler2_d_binary.json 为 ascend950 平台注册了 float16 与 float32 两套high_performance二进制条目输入输出均使用ND格式、FormatAgnostic匹配模式三个属性作为可空value 为 null采用默认值的可选属性。调用说明当前仓库提供的调用方式为图模式GE IR调用方式样例代码说明图模式test_geir_grid_sampler2_d.cpp通过算子 IR构图方式调用 GridSampler2D 算子参见算子调用完成编译和验证。示例程序的核心流程如下对应 test_geir_grid_sampler2_d.cpp初始化 GE调用ge::GEInitialize设置ge.exec.deviceId与ge.graphRunMode1图模式构图创建ge::Graph用op::Data声明xNCHW、DT_FLOAT与gridNHWC、DT_FLOAT两个输入节点并指定set_attr_index(0/1)挂接算子节点op::GridSampler2D(grid_sampler2_d)通过set_input_x/set_input_grid连接输入通过set_attr_interpolation_mode(bilinear)、set_attr_padding_mode(zeros)、set_attr_align_corners(true)设置属性建 Session 并运行session-AddGraph后构造输入 TensorMakeFloatTensor完成 host 端数据装载调用session-RunGraph(graphId, inputs, outputs)校验结果CheckOutput逐元素比对误差阈值1e-4f。示例选用 1×1×2×2 的输入x {1, 2, 3, 4}grid取四个角点坐标-1/-1、1/-1、-1/1、1/1在align_cornerstrue且 bilinearzeros 配置下输出应与输入张量完全一致角像素中心对齐时四个角点恰好落在输入四角像素中心因此该用例同时验证了坐标变换公式的正确性。如需完整的编译与验证流程算子注册、二进制生成、用例编译运行等请参考 算子调用指南 以及仓库根目录的 CONTRIBUTING.md 与构建脚本说明。【免费下载链接】ops-cv本项目是CANN提供的图像处理、目标检测相关的算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-cv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考