Closed
[Bug-Report|缺陷反馈]: 五个接口的枚举标量参数未校验(paddedMode=true 4/4 放行、actSeqLenType=1/2/-1 全放行,资料均写「仅支持 X」) #6678
liuhanwen8Add on  16 days agoClosed at  10 days ago
liuhanwen8
liuhanwen8
16 days ago Create

现象

五个 aclnn 接口的枚举型标量参数在资料里已明确写死「仅支持某一个值」,但实现完全不校验,
传入资料未支持的值时两段接口与同步全部返回 0,静默按默认分支计算。

接口 参数 资料原文 实测
aclnnMoeTokenPermuteGrad paddedMode 「目前仅支持 false」 true → rc=0
aclnnMoeTokenUnpermuteGrad paddedMode 「目前仅支持 false」 true → rc=0
aclnnMoeTokenUnpermuteWithEpGrad paddedMode 「目前仅支持 false」 true → rc=0
aclnnMoeTokenPermuteWithEpGrad paddedMode 「目前仅支持 false」 true → rc=0
aclnnNsaCompressGrad actSeqLenType 「取值0或1,当前仅支持0」 1 → rc=0;2 → rc=0

环境

A2 910B2;CANN 9.2.0;cann/ops-transformer master 92d0f9c2。

期望

资料声明「仅支持 X」的参数,传入非 X 时应返回参数错误(161002 ACLNN_ERR_PARAM_INVALID)。
这类参数是 bool / int64_t 标量,host 侧一次比较即可,不存在性能问题。

复现步骤

  1. 保存下面的 r.cpp。
  2. 编译:g++ -std=c++17 r.cpp -o r -I$ASCEND_HOME_PATH/include -L$ASCEND_HOME_PATH/lib64 -lascendcl -lnnopbase -lopapi
  3. 运行:./r 4

复现脚本

// 枚举标量参数未校验:paddedMode / actSeqLenType
#include <cstdio>
#include <cstdlib>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_moe_token_permute_grad.h"
static aclTensor *mk(const std::vector<int64_t> &sh, aclDataType dt, void *dv) {
    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];
    return aclCreateTensor(sh.data(), sh.size(), dt, st.data(), 0, ACL_FORMAT_ND,
                           sh.data(), sh.size(), dv);
}
int main(int argc, char **argv) {
    aclInit(nullptr); aclrtSetDevice(argc > 1 ? atoi(argv[1]) : 0);
    aclrtStream s = nullptr; aclrtCreateStream(&s);
    // aclnnMoeTokenPermuteGrad:tokens=8 topk=4 hidden=16 -> total=32
    const int T = 32, H = 16;
    std::vector<int64_t> gs{T, H}, is{T}, os{T, H};
    size_t bg = (size_t)T * H * 4, bi = (size_t)T * 4;
    void *dg, *di, *do_;
    aclrtMalloc(&dg, bg, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc(&di, bi, ACL_MEM_MALLOC_HUGE_FIRST);
    aclrtMalloc(&do_, bg, ACL_MEM_MALLOC_HUGE_FIRST);
    std::vector<float> hg(T * H, 1.f);
    std::vector<int> hi(T); for (int i = 0; i < T; ++i) hi[i] = i;
    aclrtMemcpy(dg, bg, hg.data(), bg, ACL_MEMCPY_HOST_TO_DEVICE);
    aclrtMemcpy(di, bi, hi.data(), bi, ACL_MEMCPY_HOST_TO_DEVICE);
    aclTensor *tg = mk(gs, ACL_FLOAT, dg), *ti = mk(is, ACL_INT32, di), *to = mk(os, ACL_FLOAT, do_);
    // 资料「目前仅支持 false」,这里传 true
    for (int k = 0; k < 2; ++k) {
        bool padded = (k == 1);
        uint64_t ws = 0; aclOpExecutor *ex = nullptr;
        auto r1 = aclnnMoeTokenPermuteGradGetWorkspaceSize(tg, ti, 4, padded, to, &ws, &ex);
        int r2 = -999, r3 = -999;
        if (r1 == 0) {
            void *wp = nullptr; if (ws) aclrtMalloc(&wp, ws, ACL_MEM_MALLOC_HUGE_FIRST);
            r2 = aclnnMoeTokenPermuteGrad(wp, ws, ex, s);
            r3 = aclrtSynchronizeStream(s);
        }
        printf("  paddedMode=%-5s GWS=%-7d Exec=%-7d Sync=%-7d\n",
               padded ? "true" : "false", (int)r1, r2, r3);
    }
    return 0;
}

实测输出:

  paddedMode=false GWS=0       Exec=0       Sync=0
  paddedMode=true  GWS=0       Exec=0       Sync=0      ← 资料写「仅支持 false」,却放行

aclnnNsaCompressGrad 的 actSeqLenType(独立小程序,同一模式):

  actSeqLenType=0    GWS=0  Exec=0  Sync=0   **放行**(合法值)
  actSeqLenType=1    GWS=0  Exec=0  Sync=0   **放行**(资料:当前仅支持 0)
  actSeqLenType=2    GWS=0  Exec=0  Sync=0   **放行**(连"取值0或1"都不在范围内)
  actSeqLenType=-1   GWS=0  Exec=0  Sync=0   **放行**

影响

  1. 静默按默认分支计算:paddedMode=true 时算子不会走 padded 路径,而是当 false 处理,
    调用方以为开了 padded 模式,拿到的却是非 padded 的结果 —— 形状常常恰好对得上,
    数值语义已变而无任何提示;
  2. actSeqLenType 选 1/2(表示不同的 seqLen 解读方式:累加和 vs 逐 batch 长度)时同样被
    按 0 处理,多 batch 场景下 seqLen 会被解读错,导致输出整体偏移;
  3. 两者都是 bool / int64_t 标量,host 校验零成本,属于该做而未做。

建议

  1. 在各接口 op_api 的 CheckParams 里加断言:
    paddedMode == false(四个 Moe 接口)、actSeqLenType == 0(NsaCompressGrad);
    返回 ACLNN_ERR_PARAM_INVALID(161002);
  2. 若后续要真正支持 paddedMode=true / actSeqLenType=1,则先把资料与实现同步,
    在此之前保持「资料写仅支持 X ⇒ 必须拒绝非 X」;
  3. 参考同仓已有正确做法:#6515 里 aclnnMatmulAllReduce 的 commTurn(资料仅支持 0)
    是返回 561002,说明本仓对这类参数有拦截先例,此处属遗漏。

备注

  • 对照测试说明不是「整批不校验」:同一批用例里 aclnnNsaCompressGrad 的
    compressBlockSize=24(非 16 倍数)被正确拒绝(561002),
    aclnnMoeTokenPermuteGrad 的 numTopk=513 被正确拒绝(361001),
    证明这些接口都有标量校验通道,只是枚举型参数这一分支漏了;
  • 与「tensor 取值不校验」无关:paddedMode 是 bool、actSeqLenType 是 int64_t,
    都是标量,host 侧校验零成本。
likedislike
liuhanwen8liuhanwen8
16 days ago Added label: bug-report
周云飞
周云飞Collaborators
16 days ago Comments:

感谢提供详细的环境、复现程序和对照结果。您反馈的是主机侧标量参数的支持范围校验,与张量内容校验是两类问题。

问题分析

aclnnMoeTokenPermuteGrad 的接口声明包含 bool paddedMode,但其 CheckParams 实现只接收三个张量参数,执行非空和数据类型检查,没有接收或检查 paddedMode。这能确认该处存在校验缺口,但尚不能据此断定后续调用链如何处理该参数,也不能直接推广到其余四个接口。

您提供的测试结果显示,在所述 A2 910B2、CANN 9.2.0 环境中,不支持的取值仍能通过第一段接口、执行接口和流同步。如果资料确实限定 paddedMode=false、actSeqLenType=0,这些取值被接受就与资料声明不一致。不过,返回成功本身不能证明实际采用了默认分支;是否产生所述数值偏差,还需结合参数传递和计算路径确认。

处理方向

一个可行的解决方案是在五个接口第一段接口的主机侧参数检查中,显式拒绝四个 Moe 接口的 paddedMode=true,以及 aclnnNsaCompressGrad 的 actSeqLenType!=0,并保持合法取值的现有行为。这类标量比较不需要读取设备端张量数据,适合放在计算任务提交之前完成。

错误返回方向应是明确的参数非法错误;您提出的 ACLNN_ERR_PARAM_INVALID 及数值 161002,仍需结合这些接口的公开错误码定义和返回路径确认。其他参数返回的 561002、361001 不能直接作为本次错误码映射的依据。

当前已明确一处局部校验缺口,其余接口的完整校验路径、资料适用范围和数值影响仍需继续确认。使用时建议先遵循资料限定,传入 paddedMode=false、actSeqLenType=0,不要将返回成功视为其他取值已受支持。

likedislike
liuhanwen8
liuhanwen8
16 days ago Comments:

本轮补充证据(独立 C++ 直调,不依赖内部 harness)

在 master 0f6fad56(A2 910B2 / CANN 9.2.0)上用纯 aclnn 两段式接口复测 aclnnNsaCompressGrad 的 actSeqLenType,
四个取值全部放行,与本 issue 的现象一致:

actSeqLenType 第一段 rc 第二段 rc sync rc
0(资料唯一支持值) 0 0 0
1 0 0 0
2 0 0 0
-1 0 0 0

最小复现代码(g++ -std=c++17 -O2 repro.cpp -I$ASCEND_HOME_PATH/include -L$ASCEND_HOME_PATH/lib64 -lascendcl -lopapi -lnnopbase):

#include <cstdio>
#include <vector>
#include <cstdint>
#include "acl/acl.h"
#include "aclnn/acl_meta.h"
#include "aclnnop/aclnn_nsa_compress_grad.h"

static aclTensor* mk(const std::vector<int64_t>& sh, aclDataType dt, void* dv) {
  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];
  return aclCreateTensor(sh.data(), sh.size(), dt, st.data(), 0, ACL_FORMAT_ND,
                         sh.data(), sh.size(), dv);
}
static void* dev(size_t bytes) {
  void* p = nullptr; size_t n = bytes ? bytes : 32;
  aclrtMalloc(&p, n, ACL_MEM_MALLOC_HUGE_FIRST);
  aclrtMemset(p, n, 0, n);
  return p;
}
int main() {
  aclInit(nullptr); aclrtSetDevice(3); aclrtStream s = nullptr; aclrtCreateStream(&s);
  const int BLK = 32, STRIDE = 16, S = 128, HD = 2, D = 32, NBLK = (S - BLK) / STRIDE + 1;
  std::vector<int64_t> gs{NBLK, HD, D}, is{S, HD, D}, ws{BLK, HD};
  void *dg = dev(NBLK * HD * D * 2), *di = dev(S * HD * D * 2), *dw = dev(BLK * HD * 2);
  void *dig = dev(S * HD * D * 2), *dwg = dev(BLK * HD * 2);
  int64_t sv = S; aclIntArray* sl = aclCreateIntArray(&sv, 1);
  for (int t : {0, 1, 2, -1}) {
    aclTensor *tg = mk(gs, ACL_FLOAT16, dg), *ti = mk(is, ACL_FLOAT16, di), *tw = mk(ws, ACL_FLOAT16, dw);
    aclTensor *tig = mk(is, ACL_FLOAT16, dig), *twg = mk(ws, ACL_FLOAT16, dwg);
    uint64_t wsz = 0; aclOpExecutor* ex = nullptr;
    aclnnStatus r1 = aclnnNsaCompressGradGetWorkspaceSize(tg, ti, tw, sl, BLK, STRIDE, t,
                                                          (char*)"TND", tig, twg, &wsz, &ex);
    int r2 = -999, r3 = -999;
    if (r1 == 0) {
      void* wp = wsz ? dev(wsz) : nullptr;
      r2 = (int)aclnnNsaCompressGrad(wp, wsz, ex, s);
      r3 = (int)aclrtSynchronizeStream(s);
      if (wp) aclrtFree(wp);
    }
    printf("actSeqLenType=%-3d gws=%d exec=%d sync=%d\n", t, (int)r1, r2, r3);
  }
  return 0;
}

源码侧补充:attention/nsa_compress_grad/op_host/nsa_compress_grad_tiling.cpp:112 取了
seqLenTypePtr = attrs->GetAttrPointer<uint32_t>(INDEXTWO),其后没有对该值做取值判断;
nsa_compress_grad_def.cpp:48 只声明 Attr("actSeqLenType")。资料 README.md:36 写「0表示cumsum结果,1表示每个batch序列大小,当前仅支持0」。

likedislike
周云飞周云飞Collaborators
14 days ago Assign yu-xinjie62、azyuli as responsible person
memorecoolmemorecoolCollaborators
13 days ago Removed responsible person yu-xinjie62
memorecoolmemorecoolCollaborators
13 days ago Assign hz36amy_00 as responsible person
yf_zhouyf_zhouCollaborators
11 days ago Associated pull request
azyuliazyuliCollaborators
10 days ago Associated pull request
CANN-robotCANN-robotCollaborators
10 days ago Close issue
CANN-robotCANN-robotCollaborators
10 days ago Added label: resolved