您好,感谢反馈!按您报告的 cann/ops-math@584b2ea6cbaeba684a51a74296d82d4d50ab3b0f 核查,这里需要分别看“等于维度的边界口径”和“大于维度时的前置错误码”。
问题分析
共享 API 的 SafePadSum 负责溢出、负向裁剪及输出尺寸校验,没有正 padding 上界检查。进入 A2 对应的 arch22 tiling 后,各空间轴对正 padding 的拒绝条件实际是 pad > inputDim,并非 pad >= inputDim。因此,本条非负 padding 中 pad==dim 被接受,与该版本 A2 的比较逻辑一致,不能直接按“漏掉等号检查”处理。共享检查、A2 上界比较
资料中 950 参数说明“允许等于”,而两个接口的错误表又统一写“大于等于”,确有需要对齐的边界表述。对于 A2,仍应对应其实际版本说明支持范围,不能只根据这条通用错误项就新增等号拒绝。2d 资料、3d 错误项
pad>dim 则会在现有 A2 tiling 检查中返回失败,而前面的 aclnn 参数校验没有提前识别。您报告的 ret_gws=561103 发生在第一段准备阶段;当前源码能够确认这条前置检查缺口,具体运行时错误码映射仍需对应核实。
处理方向
可考虑在 2d/3d 共用的参数检查中,按该平台实际支持范围提前返回 ACLNN_ERR_PARAM_INVALID(161002),同时修正文档的等号边界与产品条件。直接按建议统一加入 >=dim 会改变当前可执行的等号调用,需要先确认正式支持策略及兼容影响。
调整还需保留溢出防护、输出 shape 关系和已有正负混合 padding 约束;正负混合时的可用范围不能只看原始维度。直接相关的验证可覆盖各轴的 dim-1/dim/dim+1 及单侧、混合情形。我们会继续确认边界说明与前置返回码的一致性。


现象
aclnnCircularPad2d/aclnnCircularPad3d对padding的上界校验与资料不一致:padding == self 对应维度被接受并算出正确结果,padding > 维度返回561103(内部 tiling 错),而资料要求两者都返回161002。aclnnCircularPad2d(self=float32[1,2,4,4]):[1,1,1,1]ret_gws=0 ret_exec=0[3,3,3,3](dim-1)ret_gws=0 ret_exec=0[4,4,4,4](==dim)ret_gws=0 ret_exec=0,输出与循环填充逐元素一致(288/288)[5,5,5,5](>dim)ret_gws=561103[3,0,0,0](单侧==dim,self末维 3)ret_gws=0 ret_exec=0aclnnCircularPad3d(self=float32[1,2,4,4,4])同款:[4,4,4,4,4,4]返回 0 且输出正确(3456/3456),[5,5,5,5,5,5]返回561103,[3,0,0,0,0,0]返回 0。期望
资料《aclnnCircularPad2d》《aclnnCircularPad3d》错误码表
161002子项写明:"padding的数值大于等于self对应维度的大小。" 即padding >= dim(含相等)应返回161002。参数表对 Ascend 950(Arch35)另注"允许等于",但同时写明"其他产品以对应版本约束为准";本复现的 910B2 属"其他产品",应按错误码表返回161002。环境
cann/ops-math,master 最新提交584b2ea6(复现前git fetch核对,SafePadSum仍只有下界/溢出校验)复现步骤
repro_circpad.cpp。g++ -std=c++17 -O2 repro_circpad.cpp -o repro_circpad -I$ASCEND_HOME_PATH/include -L$ASCEND_HOME_PATH/lib64 -lascendcl -lopapi -lnnopbase./repro_circpad lt,打印ret_gws=0 ret_exec=0。./repro_circpad eq(padding=4 == dim=4),打印ret_gws=0 ret_exec=0(应为 161002)。./repro_circpad gt(padding=5 > dim=4),打印ret_gws=561103(应为 161002)。复现脚本
// aclnnCircularPad2d: padding>=self 维度未被 host 校验(资料要求 161002) // build: g++ -std=c++17 -O2 repro_circpad.cpp -o repro_circpad \ // -I$ASCEND_HOME_PATH/include -L$ASCEND_HOME_PATH/lib64 -lascendcl -lopapi -lnnopbase // run: ./repro_circpad lt ; ./repro_circpad eq ; ./repro_circpad gt #include <acl/acl.h> #include <aclnnop/aclnn_circular_pad2d.h> #include <cstdint> #include <cstdio> #include <cstring> #include <vector> static aclTensor* mk(void* d, std::vector<int64_t> sh, aclDataType dt) { std::vector<int64_t> st(sh.size()); int64_t acc = 1; for (int i = (int)sh.size() - 1; i >= 0; --i) { st[i] = acc; acc *= (sh[i] ? sh[i] : 1); } return aclCreateTensor(sh.data(), sh.size(), dt, st.data(), 0, ACL_FORMAT_ND, sh.data(), sh.size(), d); } int main(int argc, char** argv) { aclInit(nullptr); aclrtSetDevice(0); aclrtStream stream = nullptr; aclrtCreateStream(&stream); int64_t H = 4, W = 4; std::vector<int64_t> pads = {1, 1, 1, 1}; const char* tag = "[对照组 CTRL] pad=1 < dim=4"; if (argc > 1 && std::strcmp(argv[1], "eq") == 0) { pads = {4, 4, 4, 4}; tag = "[缺陷组 DEFECT] pad=4 == dim=4"; } if (argc > 1 && std::strcmp(argv[1], "gt") == 0) { pads = {5, 5, 5, 5}; tag = "[缺陷组 DEFECT] pad=5 > dim=4"; } std::vector<int64_t> sh = {1, 2, H, W}; std::vector<int64_t> outSh = {1, 2, H + pads[2] + pads[3], W + pads[0] + pads[1]}; int64_t n = 1, on = 1; for (auto v : sh) n *= v; for (auto v : outSh) on *= v; std::vector<float> h(n); for (int64_t i = 0; i < n; ++i) h[i] = (float)(i * 3 + 1); void *dIn = nullptr, *dOut = nullptr; aclrtMalloc(&dIn, n * 4, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc(&dOut, on * 4, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMemcpy(dIn, n * 4, h.data(), n * 4, ACL_MEMCPY_HOST_TO_DEVICE); aclTensor* self = mk(dIn, sh, ACL_FLOAT); aclTensor* out = mk(dOut, outSh, ACL_FLOAT); aclIntArray* pa = aclCreateIntArray(pads.data(), (uint64_t)pads.size()); uint64_t ws = 0; aclOpExecutor* ex = nullptr; printf("%s self=[1,2,4,4] out=[1,2,%lld,%lld] -> ", tag, (long long)outSh[2], (long long)outSh[3]); fflush(stdout); int r1 = (int)aclnnCircularPad2dGetWorkspaceSize(self, pa, out, &ws, &ex); int r2 = -1; if (r1 == 0) { void* dWs = nullptr; if (ws) aclrtMalloc(&dWs, ws, ACL_MEM_MALLOC_HUGE_FIRST); r2 = (int)aclnnCircularPad2d(dWs, ws, ex, stream); aclrtSynchronizeStream(stream); if (dWs) aclrtFree(dWs); } std::vector<float> got(on, -1.0f); if (r1 == 0 && r2 == 0) aclrtMemcpy(got.data(), on * 4, dOut, on * 4, ACL_MEMCPY_DEVICE_TO_HOST); printf("ret_gws=%d ret_exec=%d out[0..3]=%.0f,%.0f,%.0f,%.0f\n", r1, r2, got[0], got[1], got[2], got[3]); aclDestroyIntArray(pa); aclDestroyTensor(self); aclDestroyTensor(out); aclrtFree(dIn); aclrtFree(dOut); aclrtDestroyStream(stream); aclFinalize(); return 0; }影响
调用方按资料会在 host 侧放过
padding >= dim的配置,实际拿到两种不一致结果:等于维度时被静默接受(输出正确但违反契约),大于维度时拿到561103(tiling 内部错)。561103在上层通常被当成"内部错误/环境问题"而不是"参数非法",排障会走偏;对自动调优/参数扫描,等于把非法配置当合法配置继续执行。建议
在
circular_pad_common.h的SafePadSum之外补一条 host 侧上界校验:对每个 pad 维度,pad_front >= dim || pad_back >= dim(按资料口径含相等)直接返回ACLNN_ERR_PARAM_INVALID(161002),不要留到 tiling。2D/3D 共用同一模板,一处修改即可覆盖两个接口。