已关闭
[Bug-Report|缺陷反馈]: [工具检测] SwigluGroupQuantGrad racecheck 检出 2 条 UB WAR(输出读与下一轮搬入写复用同一 UB 地址,缺 MTE3→MTE2 反向同步) #6112
Goldfish_of_Siris创建于  21 天前关闭于  20 天前
Goldfish_of_Siris
Goldfish_of_Siris
21 天前 创建

Thanks for sending an issue! Please fill in the following template to help quickly solve your problem.

Describe the current behavior / 问题描述 (Mandatory / 必填)

2 条告警为同一类问题(同一函数缺失反向同步,仅涉及的 buffer 不同),已完成定位与修复验证。

告警明细(2 条)

# 地址 读方(MTE3) 写方(MTE2)
① WAR()+0x4000 pc 0x1134,serialNo:367,swiglu_group_quant_grad.h:466 pc 0x1494,serialNo:486,swiglu_group_quant_grad.h:156
② WAR()+0x6000 pc 0x113c,serialNo:368,swiglu_group_quant_grad.h:467 pc 0x14d4,serialNo:487,swiglu_group_quant_grad.h:158

两条均为 PIPE_MTE3 Read 与 PIPE_MTE2 Write 打在同一 UB 地址上,kernel 为 SwigluGroupQuantGrad_float16_high_performance_0。

源码结构:输出读与下一轮搬入写复用同一 UB buffer

CopyOutGradX 把 gradX 结果从 UB 搬出到 GM(466/467 行为非 float 分支):

DataCopyPad(gradXGm[gmOffset0], x0TLocalTensor, outCopyParams);   // 466: MTE3 读 UB
DataCopyPad(gradXGm[gmOffset1], x1TLocalTensor, outCopyParams);   // 467: MTE3 读 UB

xQueue 的 buffer 在 Process() 外层循环中反复复用,下一轮的 CopyInX 又把新输入搬入同一块 UB(156/158 行为非 float 分支):

DataCopyPad(xTLocalTensor, xGm[x0GmOffset], copyParams, padParams);          // 156: MTE2 写 UB
DataCopyPad(xTLocalTensor[...], xGm[x1GmOffset], copyParams, padParams);     // 158: MTE2 写 UB

即:同地址“上一轮输出读”与“下一轮输入写”重叠,二者之间必须保证“MTE3 读完 → MTE2 才覆盖”。

根因:缺少 MTE3→MTE2 反向同步

CopyOutGradX 中仅有 Vector→MTE3 的正向同步:

SetFlag<HardEvent::V_MTE3>(vToMte3);
WaitFlag<HardEvent::V_MTE3>(vToMte3);   // 只保证“算完才搬出”
... DataCopyPad(...) ...                // MTE3 读 UB → GM

搬出完成后没有 MTE3_MTE2 同步,MTE2 侧的下一轮写入不等待 MTE3 读完。

指令级证据(工具事件日志,block 0 / aiv-0,其它同步指令已省略):

367  MOV_ALIGN_V2  UB 0x4000 → GM           ← ①的读:CopyOutGradX 搬出
368  MOV_ALIGN_V2  UB 0x6000 → GM           ← ②的读
 ...  (中间为其它 tile 的计算与搬运,MTE2 上无“等 MTE3 读完”的同步)
484  GET_BUF       PIPE_MTE2 bufId:2 mode:0
485  RLS_BUF       PIPE_MTE2 bufId:2 mode:0
486  MOV_ALIGN_V2  GM → UB 0x4000           ← ①的写:下一轮 CopyInX 覆盖
487  MOV_ALIGN_V2  GM → UB 0x6000           ← ②的写

读(367/368) 与写(486/487) 之间,MTE2 流水上没有等待 MTE3 完成的同步手段;xQueue 的
FreeTensor/AllocTensor 队列复用协议只是软件层面的 buffer 生命周期管理,不构成流水间的
happens-before 关系
,无法阻止 MTE2 提前覆盖 MTE3 尚未读完的 UB。

修复与验证

在 CopyOutGradX 的 DataCopyPad 之后补充 MTE3→MTE2 反向同步(见附件 patch):

event_t mte3ToMte2 = static_cast<event_t>(GetTPipePtr()->AllocEventID<HardEvent::MTE3_MTE2>());
SetFlag<HardEvent::MTE3_MTE2>(mte3ToMte2);
WaitFlag<HardEvent::MTE3_MTE2>(mte3ToMte2);
GetTPipePtr()->ReleaseEventID<AscendC::HardEvent::MTE3_MTE2>(mte3ToMte2);

重新编译部署后 racecheck 2 → 0,Example completed successfully(输出与修复前一致)。

Environment Information / 环境信息 (Mandatory / 必填)

项 值
硬件 Ascend 950PR(NPU)
CANN / 工具 CANN 9.1.0;mssanitizer 26.0.0,-t racecheck --log-level=error,MSSANITIZER_ENABLE_DEBUG_LOG=1
算子 ops-nn activation/swiglu_group_quant_grad(arch35,kernel SwigluGroupQuantGrad_float16_high_performance_0)
检出日期 2026-09-21

Steps to reproduce the issue / 重现步骤 (Mandatory / 必填)

cd ops-nn

# 1) 编译(注入检测桩 + 调试信息)并部署
bash build.sh --pkg --soc=ascend950 --ops=swiglu_group_quant_grad -j96 --mssanitizer
./build_out/cann-ops-nn-custom_linux-x86_64.run
export LD_LIBRARY_PATH=${ASCEND_HOME_PATH}/opp/vendors/custom_nn/op_api/lib/:${LD_LIBRARY_PATH}

# 2) 编译并运行样例(生成检测载体)
bash build.sh --run_example swiglu_group_quant_grad eager cust --soc=ascend950

# 3) 运行竞争检测
cd build
MSSANITIZER_ENABLE_DEBUG_LOG=1 mssanitizer -t racecheck --log-level=error -- \
  ./test_aclnn_swiglu_group_quant_grad

结果:补丁前 2 条 UB WAR;打补丁后 0 条。

Describe the expected behavior / 预期结果 (Mandatory / 必填)

  1. CopyOutGradX 在 GM 搬出完成后补齐 MTE3→MTE2 反向同步,使下一轮 CopyInX 覆盖同一 UB 地址前
    先等待前序 MTE3 读完成,不再报 UB WAR(见附件 patch,两个 dtype 分支统一处理);
  2. 若算子侧刻意依赖 TQue 的 AllocTensor/FreeTensor 协议来保证「上一轮用完才覆盖」,
    建议改用显式流水同步(如 MTE3_MTE2 事件)表达该依赖,避免依赖隐式队列语义。

附件 zip(74_swiglu_group_quant_grad_racecheck.zip):

  • logs/racecheck_before_fix.log —— 补丁前 racecheck 全量日志(2 条 UB WAR)
  • logs/racecheck_after_fix.log —— 补丁后 racecheck 全量日志(No error detected)
  • logs/mssanitizer_detail_before_fix.log —— 补丁前工具事件级明细(含 367/368 读、486/487 写的完整指令序列)
  • logs/mssanitizer_detail_after_fix.log —— 补丁后工具事件级明细
  • logs/compile.log / logs/install.log / logs/example_after_fix.log —— 编译、安装与样例运行日志
  • source/swiglu_group_quant_grad_relevant_before.h / _after.h —— 相关代码片段(补丁前 / 后)
  • patch/patch_add_mte3_mte2_sync.diff —— 修复补丁

74_swiglu_group_quant_grad_racecheck.zip

Special notes for this issue/备注 (Optional / 选填)

likedislike
yuning_chen
yuning_chen成员
21 天前 评论:

初步分析

感谢反馈,我们已开始核对这个问题。

现象理解:SwigluGroupQuantGrad 高性能路径被 racecheck 报 2 条 UB WAR:上一轮 CopyOutGradX 的 MTE3 读与下一轮 CopyInX 的 MTE2 写复用同一 UB 地址,二者之间可能缺少 MTE3→MTE2 同步。
当前判断:初步判断,待复现确认。队列复用本身不构成流水 happens-before,缺反向同步的假设合理,但告警是否必现、补同步后是否仍正确,需按给出步骤复测。
涉及范围:activation/swiglu_group_quant_grad 的 CopyOutGradX / CopyInX(arch35 高性能 kernel)。
下一步:我们会对照源码核对搬出与下一轮搬入的同步,并评估是否补 MTE3→MTE2 事件。

likedislike
yuning_chenyuning_chen成员
20 天前 将 east_yang 设为负责人
yuning_chen
yuning_chen成员
20 天前 评论:

您好,问题已收到,当前 @east_yang 正在处理中。

likedislike
Sshilulu成员
20 天前 关联了pull request:修复工具检测SwigluGroupQuantGrad racecheck 检出 2 条 UB WAR
Eeast_yang成员
20 天前 关联了pull request:fix: ForeachRoundOffNumberV2 dtype 白名单与 SwigluGroupQuantGrad UB WAR 修复 (#6101 #6112)
Sshilulu成员
20 天前 关联了pull request:修复工具检测SwigluGroupQuantGrad racecheck 检出 2 条 UB WAR
CANN-robotCANN-robot成员
20 天前 关闭了 issue
CANN-robotCANN-robot成员
20 天前 添加了label:resolved