Closed
[Bug-Report|缺陷反馈]: aclnnInplaceDivMod shape 校验分支日志码 161001(空指针)与实际返回码 161002 不一致 #3962
liuhanwen8Add on  14 days agoClosed at  8 days ago
liuhanwen8
liuhanwen8
14 days ago Create

现象

aclnnInplaceDivMod 在 selfRef 的 shape 不等于 broadcast 结果时,同一个错误路径上出现三个不同的错误码:

位置 码 语义
aclnn_div.cpp:1085 的 OP_LOGE 161001 ACLNN_ERR_PARAM_NULLPTR(空指针)
aclnn_div.cpp:1164 的外层 OP_LOGE 561000 ACLNN_ERR_INNER(内部错误)
函数实际返回 161002 ACLNN_ERR_PARAM_INVALID(参数非法)

实测(ASCEND_SLOG_PRINT_TO_STDOUT=1):

[ERROR] OP(...):[aclnn_div.cpp:1085][CheckInplace] errno[161001] Expected shape of selfRef should be [4, 8], but got [1, 8].
[ERROR] OP(...):[aclnn_div.cpp:1164][aclnnInplaceDivModGetWorkspaceSize] errno[561000] Check ret == ACLNN_SUCCESS failed.
  [CTRL   selfRef=[4,8] other=[4,8]] GetWorkspaceSize = 0
  [DEFECT selfRef=[1,8] other=[4,8]] GetWorkspaceSize = 161002

期望

日志码应与返回码一致。CheckInplace 中这个分支做的是 shape 校验:

op::Shape broadcastShape;
OP_CHECK(BroadcastInferShape(selfRef->GetViewShape(), other->GetViewShape(), broadcastShape),
         OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Shape of selfRef and other can't broadcast, ..."),
         return ACLNN_ERR_PARAM_INVALID);
OP_CHECK(selfRef->GetViewShape() == broadcastShape,
         OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, "Expected shape of selfRef should be %s, but got %s.",
                 ...),
         return ACLNN_ERR_PARAM_INVALID);   // <-- 日志写 NULLPTR,返回却是 PARAM_INVALID

上一个分支(不能 broadcast)正确地用了 ACLNN_ERR_PARAM_INVALID;本条分支(shape 不等于 broadcast 结果)
同样返回 ACLNN_ERR_PARAM_INVALID,但 OP_LOGE 写成了 ACLNN_ERR_PARAM_NULLPTR。
建议把 aclnn_div.cpp:1083 的日志码改为 ACLNN_ERR_PARAM_INVALID,与返回保持一致。

环境

Atlas A3(Ascend910_93)单 die;CANN 9.2.0;driver 26.1.1 / 固件 7.8.0.6.201;
源码基线 cann/ops-math master 584b2ea6(已 git fetch,local 与 origin 同 sha)。

复现步骤

  1. source /usr/local/Ascend/ascend-toolkit/set_env.sh
  2. 保存下方 repro.cpp
  3. g++ -std=c++14 -O2 -I$ASCEND_HOME_PATH/include -I$ASCEND_HOME_PATH/include/aclnnop repro.cpp -o repro -L$ASCEND_HOME_PATH/lib64 -lascendcl -lopapi -lnnopbase -lpthread
  4. ASCEND_SLOG_PRINT_TO_STDOUT=1 ./repro
  5. 看输出:缺陷组返回 161002,但其上方的日志行写的是 errno[161001]

复现脚本

#include <acl/acl.h>
#include <aclnnop/aclnn_div.h>
#include <cstdio>
#include <vector>
#define CK(x, m) do { int _r = (x); if (_r != ACL_SUCCESS) { \
    printf("  [ERR] %s ret=%d\n", m, _r); return _r; } } while (0)
class Buf {
 public:
  void* p = nullptr; aclTensor* t = nullptr;
  ~Buf() { if (t) aclDestroyTensor(t); if (p) aclrtFree(p); }
};
static int MakeF32(Buf& b, const std::vector<int64_t>& sh, float fill) {
  int64_t n = 1; for (size_t i = 0; i < sh.size(); ++i) n *= sh[i];
  size_t by = (size_t)n * sizeof(float);
  std::vector<float> h((size_t)n, fill);
  CK(aclrtMalloc(&b.p, by, ACL_MEM_MALLOC_HUGE_FIRST), "malloc");
  CK(aclrtMemcpy(b.p, by, h.data(), by, ACL_MEMCPY_HOST_TO_DEVICE), "h2d");
  std::vector<int64_t> st(sh.size(), 1);
  for (int i = (int)sh.size() - 2; i >= 0; --i) st[i] = sh[i + 1] * st[i + 1];
  b.t = aclCreateTensor(sh.data(), sh.size(), ACL_FLOAT, st.data(), 0, ACL_FORMAT_ND,
                        sh.data(), sh.size(), b.p);
  return b.t ? 0 : -1; }
static int One(const char* tag, std::vector<int64_t> sref, std::vector<int64_t> sother) {
  Buf A, B;
  if (MakeF32(A, sref, 2.0f) || MakeF32(B, sother, 1.5f)) {
    printf("  [%s] SETUP_FAIL\n", tag); return -1; }
  uint64_t ws = 0; aclOpExecutor* ex = nullptr;
  int r1 = (int)aclnnInplaceDivModGetWorkspaceSize(A.t, B.t, 0, &ws, &ex);
  printf("  [%s] GetWorkspaceSize = %d\n", tag, r1);
  return r1; }
int main() {
  CK(aclInit(nullptr), "aclInit"); CK(aclrtSetDevice(0), "setDevice");
  int c1 = One("对照组 CTRL selfRef=[4,8] other=[4,8]", { 4, 8 }, { 4, 8 });
  int d1 = One("缺陷组 DEFECT selfRef=[1,8] other=[4,8]", { 1, 8 }, { 4, 8 });
  printf("\n===== summary =====\n");
  printf("  CTRL   return code = %d   (expect 0)\n", c1);
  printf("  DEFECT return code = %d   (expect 161002)\n", d1);
  aclrtResetDevice(0); aclFinalize(); return 0; }

实测输出(节选,日志行为 ASCEND_SLOG_PRINT_TO_STDOUT=1 打印):

[ERROR] ... [aclnn_div.cpp:1085][CheckInplace] errno[161001] Expected shape of selfRef should be [4, 8], but got [1, 8].
[ERROR] ... [aclnn_div.cpp:1164] errno[561000] Check ret == ACLNN_SUCCESS failed.
  [CTRL   selfRef=[4,8] other=[4,8]] GetWorkspaceSize = 0
  [DEFECT selfRef=[1,8] other=[4,8]] GetWorkspaceSize = 161002

影响

按错误码排障的人会被引向错误方向:资料里 161001 的唯一含义是「传入的 selfRef、other 是空指针」,
与本场景(shape 不匹配)无关。用户拿着 errno[161001] 去查空指针,会白查一轮。
外层再打一行 561000(内部错误)进一步干扰——真正的原因(shape 不等于 broadcast 结果)
反而只在日志的文字部分才能看到。

建议

  1. aclnn_div.cpp:1083 的 OP_LOGE 首参改为 ACLNN_ERR_PARAM_INVALID,与 return 一致;
  2. 额外一行:本条建议只改日志码,不改返回码(161002 本身是对的,因为 shape 不匹配确实是参数非法)。
likedislike
liuhanwen8liuhanwen8
14 days ago Added label: bug-report
陈思
陈思Collaborators
13 days ago Comments:

您好,感谢提供日志与返回值对照。按您报告的 584b2ea6cbaeba684a51a74296d82d4d50ab3b0f 核查,CheckInplace这个 shape 分支确实将日志标成 ACLNN_ERR_PARAM_NULLPTR,同时返回 ACLNN_ERR_PARAM_INVALID;这里应把日志标签统一为 161002,保留实际返回码。

本例两输入能广播到 [4,8],但原地输出 selfRef 只有 [1,8],不能据此扩大原地 Tensor,属于形状参数不合法。外层 CHECK_RET 的 561000 是另一条检查诊断,并不意味着函数改为返回内部错误;本项可先限定为修正具体 shape 分支的日志标签,真实空指针分支继续使用 161001。我们会继续确认日志与返回码的对齐方式。

likedislike
陈思陈思Collaborators
13 days ago Assign chen_0715 as responsible person
陈思陈思Collaborators
13 days ago Added label: pending-confirmation
陈思陈思Collaborators
13 days ago Removed label: pending-confirmation
CchenyifengCollaborators
10 days ago Assign sakuraqqz as responsible person
CchenyifengCollaborators
10 days ago Removed responsible person chen_0715
CANN-robotCANN-robotCollaborators
8 days ago Close issue
CANN-robotCANN-robotCollaborators
8 days ago Added label: resolved