Closed
[Bug-Report|缺陷反馈]: aclnnCdist 出参与 x1 的 batch 维不匹配时返回 561103 而非 161002 #3929
liuhanwen8Add on  13 days agoClosed at  8 days ago
liuhanwen8
liuhanwen8
13 days ago Create

现象

aclnnCdist 在 x1=[2,5]、x2=[1,5]、out=[1,1](out 与 x1 的 batch 维不一致)时,第一段返回 561103(ACLNN_ERR_INNER_NULLPTR);资料错误码表要求 161002。

  • 对照:x1=[1,5]、x2=[1,5]、out=[1,1] → 两段均 0。
  • 缺陷组:x1=[2,5]、out=[1,1] → 第一段 561103(应为 161002)。
  • CheckShape 只校验了维度个数与「x1/x2 最后一维相同」,没有校验 out 与 x1/x2 推导出的期望形状一致。

期望

out 形状与 x1/x2 推导出的结果形状不一致时,第一段返回 161002(ACLNN_ERR_PARAM_INVALID)。

环境

  • 昇腾硬件型号:Ascend 910B2(soc=Ascend910B2)
  • CANN 版本:9.2.0;ops-math 仓 master 提交 584b2ea6
  • 操作系统:Ubuntu 22.04 / g++ 11.4

复现步骤

  1. 取 ops-math 仓 math/cdist/op_api/aclnn_cdist.h;库用 CANN 的 libopapi.so / libnnopbase.so / libascendcl.so。
  2. 按下面命令构建并运行 repro:先跑对照(x1/x2/out 形状匹配),再跑缺陷组(x1 第 0 维改成 2、out 保持 [1,1])。
  3. 观察第一段返回码:对照 0、缺陷 561103。

复现脚本

g++ -std=c++17 -O1 repro.cpp -o repro \
  -I$ASCEND_HOME/include -I$ASCEND_HOME/aarch64-linux/include/aclnnop \
  -I<ops-math>/math/cdist/op_api \
  -I<ops-math>/common/inc/external -I<ops-math>/third_party/opbase/include \
  -L$ASCEND_HOME/lib64 -lopapi -lnnopbase -lascendcl
LD_LIBRARY_PATH=$ASCEND_HOME/lib64 ./repro 0
// aclnnCdist:x1 与 out 的 batch 维不一致(x1=[2,5]、out=[1,1])返回 561103;资料要求 161002。
// 对照:x1=[1,5]、x2=[1,5]、out=[1,1] → 两段均 0。
#include <acl/acl.h>
#include <cstdio>
#include <vector>
#include "aclnn_cdist.h"

static aclTensor* mk(std::vector<int64_t>& d, void* p)
{
    std::vector<int64_t> s(d.size(), 1);
    for (int i = static_cast<int>(d.size()) - 2; i >= 0; --i) { s[i] = s[i + 1] * d[i + 1]; }
    return aclCreateTensor(d.data(), d.size(), ACL_FLOAT, s.data(), 0, ACL_FORMAT_ND,
                           d.data(), d.size(), p);
}

static void run(const char* tag, std::vector<int64_t> d1, std::vector<int64_t> d2,
                std::vector<int64_t> dOut, aclrtStream st)
{
    auto numel = [](const std::vector<int64_t>& d) {
        size_t n = 1;
        for (auto v : d) { n *= static_cast<size_t>(v); }
        return n;
    };
    void *x1 = nullptr, *x2 = nullptr, *o = nullptr;
    aclrtMalloc(&x1, numel(d1) * 4, ACL_MEM_MALLOC_HUGE_FIRST);
    aclrtMalloc(&x2, numel(d2) * 4, ACL_MEM_MALLOC_HUGE_FIRST);
    aclrtMalloc(&o, numel(dOut) * 4, ACL_MEM_MALLOC_HUGE_FIRST);
    std::vector<float> h1(numel(d1), 1.0f), h2(numel(d2), 2.0f);
    aclrtMemcpy(x1, numel(d1) * 4, h1.data(), numel(d1) * 4, ACL_MEMCPY_HOST_TO_DEVICE);
    aclrtMemcpy(x2, numel(d2) * 4, h2.data(), numel(d2) * 4, ACL_MEMCPY_HOST_TO_DEVICE);
    aclTensor* t1 = mk(d1, x1);
    aclTensor* t2 = mk(d2, x2);
    aclTensor* to = mk(dOut, o);
    uint64_t ws = 0;
    aclOpExecutor* ex = nullptr;
    aclnnStatus r1 = aclnnCdistGetWorkspaceSize(t1, t2, 2.0f, 2, to, &ws, &ex);
    int r2 = -1;
    if (r1 == ACL_SUCCESS) {
        void* wsp = nullptr;
        if (ws > 0) { aclrtMalloc(&wsp, ws, ACL_MEM_MALLOC_HUGE_FIRST); }
        r2 = static_cast<int>(aclnnCdist(wsp, ws, ex, st));
        aclrtSynchronizeStream(st);
        if (wsp != nullptr) { aclrtFree(wsp); }
    }
    printf("%-32s phase1=%-7d phase2=%d\n", tag, static_cast<int>(r1), r2);
    fflush(stdout);
    aclDestroyTensor(t1); aclDestroyTensor(t2); aclDestroyTensor(to);
    aclrtFree(x1); aclrtFree(x2); aclrtFree(o);
}

int main(int argc, char** argv)
{
    int dev = (argc > 1) ? atoi(argv[1]) : 0;
    aclInit(nullptr);
    aclrtSetDevice(dev);
    aclrtStream st = nullptr;
    aclrtCreateStream(&st);
    run("[对照] x1[1,5] x2[1,5] out[1,1]", {1, 5}, {1, 5}, {1, 1}, st);
    run("[缺陷] x1[2,5] x2[1,5] out[1,1]", {2, 5}, {1, 5}, {1, 1}, st);
    aclrtDestroyStream(st);
    aclrtResetDevice(dev);
    aclFinalize();
    return 0;
}

实测输出:

[对照] x1[1,5] x2[1,5] out[1,1] phase1=0       phase2=0
[缺陷] x1[2,5] x2[1,5] out[1,1] phase1=561103  phase2=-1

影响

形状参数错误未被参数校验拦下,返回内部错误码,调用方无法据码定位;非法形状继续进入 reshape/broadcast 构图路径,后续报错点与真正原因脱节。

建议

math/cdist/op_api/aclnn_cdist.cpp 的 CheckShape 增加出参联动校验:按 p/维度关系推导期望 out 形状([x1.dim0, x2.dim0] 等)并与 out 的 view shape 逐维比较,不一致返回 ACLNN_ERR_PARAM_INVALID;参考同仓 aclnnSplitTensor 的同类修复(#3918)。

likedislike
liuhanwen8liuhanwen8
13 days ago Added label: bug-report
陈思
陈思Collaborators
13 days ago Comments:

您好,感谢提供对照用例!按您报告的 584b2ea6cbaeba684a51a74296d82d4d50ab3b0f 核查,CheckShape确实没有比较 out 与预期结果形状,这一校验缺口需要处理。

问题分析

这里有两点需要澄清:对于二维输入 [P,M],第一维是点数 P,并非 batch 维。因此 x1=[2,5]、x2=[1,5] 的合法输出是 [2,1]。更一般地,输出应为 broadcast(x1[:-2], x2[:-2]) + [P,R];p 决定距离范数,不参与输出形状推导,也不能要求 x1、x2 的点数相同。

当前实现只在前置检查中限制秩和尾部特征维 M,之后才广播输入、构建结果,并在末尾通过 ViewCopy 写入 out;该处空返回会映射为内部错误。因此漏检允许错误 out 继续进入构图,存在返回内部错误的路径。不过,本次 561103 具体在哪一步触发,仍需结合第一段日志确认,不能仅由返回码认定是 reshape、broadcast 或最终复制中的某一步。

文档已经规定输出形状关系,但该版本错误码表没有单列“out 与推导结果形状不一致”这一项;建议补充明确说明,而非把现有“维度不在支持范围内”直接等同于完整形状关系校验。

处理方向

可在第一段参数检查中先验证前导维广播关系、推导预期输出,再逐维比较 out,不匹配统一返回 161002。这项检查应放在空输入提前返回及后续构图之前,兼顾零点数、零特征维的现有语义。

回归可覆盖本例、正确的 [2,1] 输出、合法的不同点数 P/R、带前导维广播和错误输出秩/各轴长度,以及空 Tensor 分支。以上为固定版本源码核查,尚未独立设备复验;我们会继续确认具体报错点及前置校验方案。

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