感谢提供完整的对照用例和环境信息。您报告的三个异常都发生在 aclnnMoeGatingTopKBackwardGetWorkspaceSize 阶段,关注点是非法参数的错误码分类,而不是算子的计算结果。
问题分析
按您提供的实测结果,合法输入返回 0,而以下三种输入均返回 561002:
expertIdx[4,3]与gradY[4,2]的形状不一致;xNorm为三维,而接口要求二维;out[4,9]与xNorm[4,8]的形状不一致。
这些结果与您引用的资料中 161002(ACLNN_ERR_PARAM_INVALID)的说明不一致,也确实会影响调用方对参数错误和内部故障的区分。当前可见的 tiling 定义将 xNorm、gradY、expertIdx 和输出均设为二维,但现有代码片段尚不足以确认第一阶段的具体校验顺序,以及校验失败如何转换为公开错误码。因此,“参数检查下沉到 tiling 后被映射为 561002”目前仍是需要进一步确认的原因,不能仅凭返回值就确定完整调用路径。
处理方向
一个可行的处理方向是在 GetWorkspaceSize 的参数检查中,先检查各张量的维数,再检查 gradY 与 expertIdx、out 与 xNorm 的形状是否分别一致;对资料明确列为非法参数的情况返回 161002。tiling 中可以保留相应检查作为兜底,而不是将所有 tiling 失败统一改成参数错误,以免掩盖真正的内部故障。
这一调整需要保持合法输入的现有行为,并保留空指针返回 161001 的处理;您报告的 out=nullptr 用例不属于本次问题范围。现有复现信息已足以支持继续定位,无需重复补充环境或脚本。后续需重点确认您所用 CANN 9.2.0 中的第一阶段检查及错误码转换路径。


本轮独立复核(2026-10-25,CANN 9.2.0,master 5d75099):单文件 C++ 直调结果 —— expertIdx[4,18] vs gradY[4,2] → 561002(tiling CheckExpertIdx:Must match gradY on dimension 1);out[4,7] vs xNorm[4,8] → 561002(tiling CheckOutShape:gradX must match xNorm on dimension 1);K>N(gradY[4,9]/xNorm[4,8])→ 561002;xNorm 提到 3D → 561002。对照组 0/0。与 #6688 结论一致,特此追加 E1 证据。


/assign @licheng261


现象
aclnnMoeGatingTopKBackward对 rank/shape 违例返回 561002(ACLNN_ERR_INNER_TILING_ERROR),而资料声明应为 161002(ACLNN_ERR_PARAM_INVALID)。expertIdx[4,3]与gradY[4,2]shape 不一致xNormrank 3(应为 2)out[4,9]与xNorm[4,8]shape 不一致期望
资料「返回值」表在 161002 下列出三行:
xNorm、gradY 或 expertIdx 的 shape 维度不在支持的范围之内、gradY 与 expertIdx 的 shape 不一致、out 与 xNorm 的 shape 不一致。这三类都应在第一段返回 161002,而不是把校验下沉到 tiling 后返回 561002。环境
cann/ops-transformermaster5f9cdcf3c868e4598893b8cfe75657f0055da5b7moe/moe_gating_top_k_backward/op_host/moe_gating_top_k_backward_tiling*.cpp(shape 校验在 tiling 阶段,错误码被映射成ACLNN_ERR_INNER_TILING_ERROR)同类问题(其他接口):#6541(AlltoAllQuantMatmul 561002 vs 161002)、#6517(QuantMatmulAllReduce 561002 vs 161002);本条接口不同,且三项 rank/shape 违例逐条给出。
复现步骤
source $ASCEND_HOME_PATH/set_env.shrepro.cppCONTROL(legal) ret_gws=0,三个违例行全部561002复现脚本
#include <acl/acl.h> #include <aclnnop/aclnn_moe_gating_top_k_backward.h> #include <cstdio> #include <vector> static aclTensor* mkT(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); } static void* z(std::vector<int64_t> sh, size_t e) { int64_t n = 1; for (auto v : sh) n *= v; void* d = nullptr; aclrtMalloc(&d, (size_t)n * e, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMemset(d, (size_t)n * e, 0, (size_t)n * e); return d; } static void run(int sc, const char* tag) { std::vector<int64_t> xs = {4,8}, gs = {4,2}, is = {4,2}, os = {4,8}; if (sc == 1) is = {4,3}; if (sc == 2) xs = {1,4,8}; if (sc == 3) os = {4,9}; aclTensor* tx = mkT(z(xs,4), xs, ACL_FLOAT); aclTensor* tg = mkT(z(gs,4), gs, ACL_FLOAT); aclTensor* ti = mkT(z(is,4), is, ACL_INT32); aclTensor* to = mkT(z(os,4), os, ACL_FLOAT); uint64_t ws = 0; aclOpExecutor* ex = nullptr; int r1 = (int)aclnnMoeGatingTopKBackwardGetWorkspaceSize( tx, tg, ti, 0, 1, 2.5, 1e-20, to, &ws, &ex); printf("%-26s ret_gws=%d\n", tag, r1); } int main() { aclInit(nullptr); aclrtSetDevice(0); run(0, "CONTROL(legal)"); run(1, "expertIdx shape mismatch"); run(2, "xNorm rank 3"); run(3, "out shape mismatch"); aclrtResetDevice(0); aclFinalize(); return 0; }g++ -std=c++17 -O2 repro.cpp -o repro -I$ASCEND_HOME_PATH/include \ -L$ASCEND_HOME_PATH/lib64 -lascendcl -lopapi -lnnopbase && ./repro # 实测输出: # CONTROL(legal) ret_gws=0 # expertIdx shape mismatch ret_gws=561002 # xNorm rank 3 ret_gws=561002 # out shape mismatch ret_gws=561002影响
out=nullptr返回 161001(与资料一致),不在本条范围内建议
把
CheckXNorm/CheckGradY/CheckExpertIdx/CheckGradX中的 rank/shape 断言放在GetWorkspaceSize阶段并返回ACLNN_ERR_PARAM_INVALID(161002);tiling 内的同类断言仅作为兜底,不再承担用户参数校验职责。