Closed
[Bug-Report|缺陷反馈]: MoeDistributeDispatchV2/V4 未校验 x 与 expertIds 的 batch 维一致(V3 同类问题见 #5996) #6532
liuhanwen8Add on  24 days agoClosed at  18 days ago
liuhanwen8
liuhanwen8
24 days ago Create

问题描述

aclnnMoeDistributeDispatchV2 / V4 的 Host InferShape 只校验 x 与 expertIds 各维为正,没有校验两者首维(batch 维)相等:

  • x=[8,512] + expertIds=[9,1](ids 多一行)→ 两段接口均返回 0,正常出结果;
  • x=[8,512] + expertIds=[7,1](ids 少一行)→ 两段也返回 0,此时 kernel 按 x 的 batch 遍历 expertIds,会读到 expertIds 张量边界之外。

V3 的同类问题已由 #5996 跟踪;本 issue 报告的是 V2/V4 同样未校验(三者共用同一份
mc2/moe_distribute_dispatch_v2/op_host/moe_distribute_dispatch_v2_infershape.cpp,
V2/V4 的 aclnn 入口都走 GetAndCheckDispatchShapeV2),避免只修 V3 而漏掉 V2/V4。

环境信息

  • 仓库:cann/ops-transformer,源码核对点 origin/master@4dc31cf4
  • 硬件:Atlas A2 训练系列(910B2)×8;CANN 9.2.0
  • 通信域:HcclCommInitRootInfo(2, ...),epWorldSize=2、moeExpertNum=2、commAlg="fullmesh"、K=1

源码位置(origin/master@4dc31cf4)

mc2/moe_distribute_dispatch_v2/op_host/moe_distribute_dispatch_v2_infershape.cpp:

bs     = ((xDimNum == 1U) ? NEG_ONE : xShape->GetDim(0));
h      = ((xDimNum == 1U) ? NEG_ONE : xShape->GetDim(1));
int64_t bsTmp = ((expertDimNum == 1U) ? NEG_ONE : expertIdsShape->GetDim(0));
k      = ((expertDimNum == 1U) ? NEG_ONE : expertIdsShape->GetDim(1));
if ((bs <= 0) || (h <= 0) || (bsTmp <= 0) || (k <= 0)) {   // 只校验为正,未比较 bs 与 bsTmp
    ...
    return ge::GRAPH_FAILED;
}
return ge::GRAPH_SUCCESS;

bs 后续用于推导 expandX 等输出形状,bsTmp 只参与日志,因此不一致时既不报错也无人发现。

复现(自包含,双卡 2-rank)

复用 issue 中的同款双 rank 探针(HcclCommInitRootInfo(2, ...) + 预填 0xA5 金丝雀),只改 expertIds 的行数:

# x 8 行、expertIds 9 行
[rank 0] 第一段 rc=0 第二段 rc=0 expandX[0..7]=003C003C003C003C -> 已写出
[rank 1] 第一段 rc=0 第二段 rc=0 expandX[0..7]=003C003C003C003C -> 已写出

# x 8 行、expertIds 7 行(kernel 会越过 expertIds 读取)
[rank 0] 第一段 rc=0 第二段 rc=0
[rank 1] 第一段 rc=0 第二段 rc=0

最小改动点(相对上面的双 rank 程序):

int64_t idsRows = 9;                       // 或 7;x 固定 8 行
aclTensor *ids = Make({idsRows, 1}, ACL_INT32, (size_t)idsRows * 4, &pid);

期望行为

InferShape 中比较 bs == bsTmp,不一致返回 161002(或 561002,与资料错误码表一致即可),并补一条 shape 不匹配的 UT。

影响

P2:路由输入(expertIds)与特征输入(x)不能逐 token 对齐时仍返回成功,
ids 少于 x 的场景会越过 expertIds 读取(可能读到其他张量/未映射显存),结果不可预期且不报错。

likedislike
周云飞
周云飞Collaborators
24 days ago Comments:

感谢提供详细的输入形状、运行结果和环境信息。本条反馈的重点是 V2/V4 的校验覆盖,不能仅以 V3 的 #5996 处理情况代替这两个接口的确认。

问题分析

您贴出的校验逻辑只判断 bs、h、bsTmp 和 k 是否为正,没有比较 x 与 expertIds 的首维。因此,x=[8,512] 搭配 expertIds=[9,1] 或 [7,1] 都能通过这段检查。按您提供的运行结果,两种不匹配输入在 V2/V4 的两段接口中均返回了成功。

其中,expertIds 少一行的情况风险更高:如果 kernel 按 x 的 8 行索引路由信息,就会访问不存在的第 8 行。两段接口返回成功并不能说明输入合法或访问安全;具体越界访问路径仍需结合 kernel 实现确认。

处理方向

一个可行的方案是在共用形状检查中增加 bs == bsTmp 校验,不一致时记录两者的实际值并返回失败,同时确认 V2/V4 的入口都能传递该失败结果。回归用例可覆盖路由行数多于、少于特征行数,以及两者相等的正常输入,避免只覆盖 V3。

ge::GRAPH_FAILED 是内部形状推导状态,不能直接等同于公开接口的 161002 或 561002;最终错误码还需沿接口的错误转换路径确认。当前尚未独立复现上述运行结果,也未确认具体越界路径。

likedislike
游震Collaborators
23 days ago Comments:

/assign @luobaiqing

likedislike
CANN-robotCANN-robotCollaborators
23 days ago Assign luobaiqing as responsible person
luobqluobqCollaborators
22 days ago Assign SuperYuan as responsible person
luobqluobqCollaborators
22 days ago Removed responsible person luobaiqing
Simple_Bright&ManSimple_Bright&Man
20 days ago Associated pull request
CANN-robotCANN-robotCollaborators
18 days ago Close issue
CANN-robotCANN-robotCollaborators
18 days ago Added label: resolved
周云飞
周云飞Collaborators
4 days ago Comments:

已通过 PR #14593 补充参数校验:在 Dispatch V2–V4 共用的 ACLNN 入口检查 x 和 expertIds 均为二维,且 batch 维相等;不满足时返回参数错误。同时在 InnerV2 的形状推导中增加 batch 一致性检查,避免仅依赖形状推导进行校验。

关联 PR:PR #14593

likedislike