Closed
[Bug-Report|缺陷反馈]: aclnnUnfoldGrad 空指针返回 561103 而非文档承诺的 161001,且 len(inputSizes)=3 时 dim=0 未被拒绝 #3795
liuhanwen8Add on 21 days agoClosed at 16 days ago
21 days ago Added label: bug-report
陈思
20 days ago Comments:
20 days ago Comments:
您好,感谢反馈!已收到三个空指针用例及 inputSizes={2,3,4} 的 dim 对照结果。
问题分析
核对 cann/ops-math@3e45432d 的 CheckParams,空指针检查确实返回 ACLNN_ERR_INNER_NULLPTR,与文档的 161001 不一致;dim 校验允许所有满足 0 <= dim < rank(gradOut)-1 的轴,也与文档仅支持末两轴的表述不同。
这里需区分 rank(gradOut)=len(inputSizes)+1:末两轴应以 len(inputSizes) 为基准,不能直接套用正文建议中的 gradOut rank 表达式。另外该版本文档将 dim 约束列在 561002 下,并非 161002,返回码也需要与 #3797 一并梳理。
处理方向
可以考虑规范空指针返回码,并结合实际支持轴与兼容性确认 dim 的公开契约,再统一校验和文档。由 @chen_0715 接单继续确认;本条保留空指针和 dim 两项诉求。


陈思
20 days ago Comments:
20 days ago Comments:
/assign @chen_0715


20 days ago Assign chen_0715 as responsible person
20 days ago Added label: pending-confirmation
20 days ago Assign tangkaidi as responsible person
20 days ago Removed responsible person chen_0715
20 days ago Removed label: pending-confirmation
tangkaidi
18 days ago Comments:
18 days ago Comments:
你好,感谢你的关注和反馈,该issue提到的问题已经确认。
修复PR链接:https://gitcode.com/cann/ops-math/pull/6650
- 修复aclnn阶段如果入参为空指针时的返回错误码。
- 修改资料内对允许传入的dim的范围。
将会尽快合入修复代码。


16 days ago Close issue
16 days ago Added label: resolved
问题描述
aclnnUnfoldGrad存在两处与文档契约直接冲突的校验缺陷,且都在第一段接口即可复现:gradOut/inputSizes/gradIn任一传nullptr161001561103(ACLNN_ERR_INNER_NULLPTR)len(inputSizes)=3时传dim=01610020(SUCCESS,被接受)契约依据(
conversion/unfold_grad/docs/aclnnUnfoldGrad.md)::127len(inputSizes)-1或者len(inputSizes)-2。」:217gradIn为空指针 → 错误码161001:227len(inputSizes)-1且 dim 不等于len(inputSizes)-2轴。」→ 错误码161002源码根因
conversion/unfold_grad/op_api/aclnn_unfold_grad.cpp:// :121 空指针统一返回内部错误码,而非 161001 CHECK_RET(CheckNotNull(gradOut, inputSizes, gradIn), ACLNN_ERR_INNER_NULLPTR); // :128 只实现了「上界」约束,未实现文档要求的「双轴」约束 int64_t dimNum = gradOut->GetViewShape().GetDimNum(); CHECK_RET(dim >= 0 && dim < dimNum - 1, ACLNN_ERR_PARAM_INVALID);两处问题:
UG-02:
ACLNN_ERR_INNER_NULLPTR(561103)属内部错误码段,而空指针是调用方的入参错误,文档明确承诺161001。调用方按文档写的if (ret == 161001)分支永远不会命中,错误被归因到「算子内部异常」。UG-03:
:128只判dim >= 0 && dim < dimNum - 1,是单边界。文档要求的是「len-1或len-2两个取值」,即dim ∈ {dimNum-1, dimNum-2}。当len(inputSizes)=3时,dim=0满足0 <= 0 < 2,因此被放行;而文档:227明确这种情况应返回161002。环境信息
npu-smi26.1.1cann/ops-mathHEAD3e45432d(2026-10-21)重现步骤
1. 编译
g++ -std=c++17 -O2 unfold_grad_probe.cpp -o unfold_grad_probe \ -I$ASCEND_HOME_PATH/include -L$ASCEND_HOME_PATH/lib64 \ -lascendcl -lopapi -lnnopbase2. 运行
3. 用例构造
inputSizes(aclIntArray):{2, 3, 4},即len=3,故合法dim只能是2(len-1)或1(len-2)gradIn:fp32[2,3,4](等于inputSizes)gradOut:按文档推导形状(..., (sizedim-size)/step+1, size),size=2, step=1:dim=2→[2,3,3,2]dim=1→[2,2,4,2]dim=0→[2,3,4,2]4. 完整探针源码(可直接保存为
unfold_grad_probe.cpp)// ============================================================================ // aclnnUnfoldGrad 实测:UG-02(空指针返回码)/ UG-03(dim 双轴约束未实现) // // 文档契约(conversion/unfold_grad/docs/aclnnUnfoldGrad.md): // :127 「dim 仅支持 len(inputSizes)-1 或者 len(inputSizes)-2」 // :217 gradIn 为空指针 -> 161001 // :227 dim 不等于 len(inputSizes)-1 且不等于 len(inputSizes)-2 -> 161002 // // 源码现状(op_api/aclnn_unfold_grad.cpp): // :121 CHECK_RET(CheckNotNull(...), ACLNN_ERR_INNER_NULLPTR) <- 返回 561103,非 161001 // :128 CHECK_RET(dim >= 0 && dim < dimNum - 1, ...) <- 只拦上界,未实现「双轴」约束 // // 判据: // UG-02: 三个空指针(gradOut / inputSizes / gradIn)-> 实测 561103 即缺陷(文档要 161001) // UG-03: len(inputSizes)=3 时 dim=0 -> 文档要求 161002;实测 0 即缺陷 // 同时 dim=1(len-2) 与 dim=2(len-1) 应放行,作为对照 // ============================================================================ #include <cmath> #include <cstdio> #include <cstring> #include <cstdint> #include <vector> #include "acl/acl.h" #include "aclnn/aclnn_base.h" #include "aclnnop/aclnn_unfold_grad.h" struct H { std::vector<int64_t> sh, st; aclTensor* t = nullptr; }; static H* mk(std::vector<int64_t> s, aclDataType d, void* p, aclFormat f = ACL_FORMAT_ND) { auto* h = new H(); h->sh = std::move(s); h->st.assign(h->sh.size(), 1); for (int i = static_cast<int>(h->sh.size()) - 2; i >= 0; --i) h->st[i] = h->st[i + 1] * h->sh[i + 1]; h->t = aclCreateTensor(h->sh.data(), h->sh.size(), d, h->st.data(), 0, f, h->sh.data(), h->sh.size(), p); return h; } static void* M(size_t b) { void* p = nullptr; if (b == 0) b = 256; aclrtMalloc(&p, b, ACL_MEM_MALLOC_HUGE_FIRST); return p; } static const char* rn(int rc) { switch (rc) { case 0: return "SUCCESS"; case 161001: return "161001 NULLPTR"; case 161002: return "161002 PARAM"; case 561002: return "561002 INNER"; case 561103: return "561103 INNER_NULLPTR"; case 361001: return "361001 RUNTIME"; default: return "other"; } } static int g_bad = 0; // 构造一套合法 shape 并调用;传 nullptr 的实参用来测 UG-02 // inputSizes = {2,3,4}(len=3),dim 由参数指定,size=2, step=1 // gradOut 推导:shape (..., (sizedim-size)/step+1, size) 去掉附加维后 // 对 dim=2: gradOut = [2,3,(4-2)/1+1, 2] = [2,3,3,2] // 对 dim=1: 同理 gradOut = [2,(3-2)/1+1,4,2] = [2,2,4,2] // gradIn = inputSizes = [2,3,4] static void runCase(int64_t dim, bool nullGradOut, bool nullSizes, bool nullGradIn, const char* tag, int expectRc) { // gradIn 固定为 inputSizes 形状 const size_t inElems = 24; void* dIn = M(inElems * sizeof(float)); void* dOut = M(64 * sizeof(float)); int64_t isBuf[3] = {2, 3, 4}; aclIntArray* inputSizes = aclCreateIntArray(isBuf, 3); std::vector<int64_t> gradOutShape; if (dim == 2) gradOutShape = {2, 3, 3, 2}; else if (dim == 1) gradOutShape = {2, 2, 4, 2}; else gradOutShape = {2, 3, 4, 2}; // dim=0 时的「直觉」形状,仅用于让校验走到 dim 判断 H* gradOut = mk(gradOutShape, ACL_FLOAT, dOut); H* gradIn = mk({2, 3, 4}, ACL_FLOAT, dIn); uint64_t ws = 0; aclOpExecutor* ex = nullptr; aclnnStatus st = aclnnUnfoldGradGetWorkspaceSize( nullGradOut ? nullptr : gradOut->t, nullSizes ? nullptr : inputSizes, dim, 2, 1, nullGradIn ? nullptr : gradIn->t, &ws, &ex); const int rc = static_cast<int>(st); const bool ok = (rc == expectRc); if (!ok) ++g_bad; printf(" %-46s dim=%-2ld rc=%-6d %-22s %s\n", tag, static_cast<long>(dim), rc, rn(rc), ok ? "符合预期" : (expectRc == 0 ? "!! 合法用例被拒" : "*** 不符合文档契约 ***")); if (ex != nullptr) aclDestroyAclOpExecutor(ex); aclDestroyIntArray(inputSizes); } int main() { aclInit(nullptr); aclrtSetDevice(0); printf("========================================================================\n"); printf(" aclnnUnfoldGrad: UG-02 空指针返回码 / UG-03 dim 双轴约束\n"); printf(" 文档: :127「dim 仅支持 len(inputSizes)-1 或 -2」; :217 空指针->161001; :227 dim 越界->161002\n"); printf(" 源码: :121 空指针->ACLNN_ERR_INNER_NULLPTR; :128 仅 dim>=0 && dim<dimNum-1\n"); printf("========================================================================\n\n"); printf("--- UG-03: len(inputSizes)=3,合法 dim 只能是 2(len-1) 或 1(len-2) ---\n"); runCase(2, false, false, false, "对照: dim=2 (=len-1, 合法)", 0); runCase(1, false, false, false, "对照: dim=1 (=len-2, 合法)", 0); runCase(0, false, false, false, "dim=0 (既非 len-1 也非 len-2)", 161002); // 也测一下更极端的:dim 远小于 len-2 runCase(0, false, false, false, "dim=0 重复确认稳定性", 161002); printf("\n--- UG-02: 三个必选参数分别传 nullptr(文档要求 161001)---\n"); runCase(2, true, false, false, "gradOut = nullptr", 161001); runCase(2, false, true, false, "inputSizes = nullptr", 161001); runCase(2, false, false, true, "gradIn = nullptr", 161001); printf("\n========================================================================\n"); printf(" 不符合契约的用例数: %d\n", g_bad); printf("========================================================================\n"); aclrtResetDevice(0); aclFinalize(); printf("\nDONE\n"); return 0; }预期结果
dim=2(len-1)0(合法对照)dim=1(len-2)0(合法对照)dim=0(既非len-1也非len-2)161002gradOut=nullptr161001inputSizes=nullptr161001gradIn=nullptr161001日志 / 截图
A2 910B2 / CANN 9.2.0 实跑:
两个合法对照(
dim=2、dim=1)均返回0,证明 shape 推导与调用链正确,dim=0的rc=0不是用例构造错误导致的误判。备注
影响
561103属内部错误段。调用方按文档构造161001分支做「参数缺失」处理时会失效,错误被误判为算子内部故障,排查成本高。三个必选参数无一例外。dim取值非法时被静默接受并执行。虽然实测dim=0的梯度结果与 float64 参考一致(见下),但契约失效本身意味着:若后续实现调整dim语义或优化路径,非法取值将不再有保护,且调用方无法在参数阶段发现自己的错误。dim越界被接受属「校验缺失」类问题,与结果正误是两个层面——本次未对dim=0的输出数值下结论,仅主张契约未实现。查重说明
已检索
cann/ops-math存量 unfold 相关 issue(10 条),确认非重复:aclnn_unfold_grad.cpp:143-148),与本单的**空指针返回码(561103 vs 161001)**和 dim 值域约束是完全不同的两个检查点。inputSizes的长度校验,非空指针返回码,也非 dim 约束。aclnnUnfoldGrad空指针返回 561103 而非 161001」或「len(inputSizes)=3时dim=0未被拒绝」的存量单。建议修复
161001:// op_api/aclnn_unfold_grad.cpp:121 CHECK_RET(CheckNotNull(gradOut, inputSizes, gradIn), ACLNN_ERR_PARAM_NULLPTR);// op_api/aclnn_unfold_grad.cpp:128 int64_t dimNum = gradOut->GetViewShape().GetDimNum(); CHECK_RET(dim == dimNum - 1 || dim == dimNum - 2, ACLNN_ERR_PARAM_INVALID);nullptr断言161001;len(inputSizes)=3时dim=0断言161002。当前tests/ut/未见覆盖。