非真实问题
报错可稳定复现,但经核查,这是 mssanitizer 对 DataCopyPad(..., PaddingMode::Compact) 取数地址的建模偏差,不是算子真实越界,也不影响精度。
1. 复现
- 环境:CANN 9.3.0(
/home/LuckySun/Ascend)、Ascend950DT_9592(72 AIV)、TTK 3.0.0、mssanitizer 26.3.0.dev202611120100
mssanitizer --tool=memcheck --leak-check=yes --check-unused-memory=yes -- \
python3 -m ttk kernel -i <附件 trigger_cases.csv> \
--compile-opts op_debug_config=sanitizer --pc 1 --devices 0
| 用例 | r0=D·H·W | block | mSAN 报错 |
|---|---|---|---|
L0_003 |
16 | 72 | 无 |
L0_003_varp12 |
17 | 72 | size 34 × 2244 |
L0_003_varm140 |
15 | 72 | size 30 × 336 |
L0_018 |
187 | 46 | size 374 × 12、size 22 × 6 |
L0_018_varp117 / _varm155 |
— | — | 附件行本身非法(output_shapes[4]=None)→ reserve_space_2_out_ is null,编译失败,非算子问题 |
合计 2598 条 illegal read,records undetected = 0(覆盖完整,非漏扫);另有 129 条
WARNING: Unused memory of 512 byte(s)(内存卫生提示,非错误)。
与 issue 日志同签名(issue 2472 条 = 2148×34 + 324×30 + 12×374 + 6×22,其 56 核;本次 72 核,条数略多)。
2. 根因
一句话:工具以为每行数据之间有 32B 对齐填充,按"加大后的行距"去算读地址,于是算到了缓冲区外面;实际数据是紧挨着放的。
分四步:
-
搬运方式:输出 y 由
op_kernel/arch35/batch_norm3d_welford.h:423的
CopyY2Gm() → DataCopyPad<T1, PaddingMode::Compact>从 UB 搬回 GM,一次搬多行
(如 83 行),每行 =D×H×W个 fp16(187 元素 = 374 B;另一 shape 为 17 元素 = 34 B)。
UB 里这些行是紧凑连续摆放的,行间没有填充,缓冲也只按紧凑总长分配(83×374 = 31042 B ≤ 31072 B)。 -
工具怎么算:mssanitizer 把每行长度向上取整到 32 B 的倍数当作行距(374 → 384、34 → 64),
于是第 i 行读地址算成i×384。第 83 行算到 82×384 = 31488 B,超出 31072 B 的缓冲 → 报illegal read of size 374。
这与日志完全吻合:报错的 size 就是行字节数(374/34),地址间隔就是AlignUp(行字节数,32)(384/64)。 -
实际怎么取数:CANN 的实现里,Compact 模式的行步长直接用行字节数,不做 32 B 对齐;
只有 Normal 模式才对齐(asc/impl/basic_api/dav_3510/kernel_operator_data_copy_impl.h:102-123):
if constexpr (mode == PaddingMode::Normal) {
srcStride310 = srcStride * 32 + burstLength;
srcStride310 = DivCeil(srcStride310, 32) * 32; // 只有 Normal 强制 32B 对齐
} else {
srcStride310 = burstLength; // Compact:字节精确、忽略 srcStride
}
即实际第 83 行起点是 82×374 = 30668 B,读 374 B 到 31042 B,仍在缓冲区内。
- 旁证:若真按 384 步进,y 从第 2 行起就会整体错位,精度必然失败;而同一批 shape 带 golden 的
对照轮次精度全部 PASS。


【缺陷】BatchNorm3D 多核分支 UB 越界读 2148+324 条(illegal read size 34/30)
问题描述信息
【环境信息】:
【预置条件】:
【重现步骤】:
cd <ops仓> && bash build.sh --jit --soc=ascend950 --ops=batchnorm3d
mssanitizer --tool=memcheck --leak-check=yes --check-unused-memory=yes --
/npu/miniconda3/envs/CI_py310_aclnn/bin/python3 -m ttk kernel
-i batchnorm3d_cases.csv --compile-opts op_debug_config=sanitizer
--pc 1 --devices 0
【预期结果】:
无 mSAN ERROR(无越界读写、无内存泄漏)
【实际结果】:
mssanitizer memcheck 检出 2491 条 ERROR(illegal read of size 34×2148 + size 30×324 + size 374×12 + size 22×6 + LeakCheck×1),全部为 UB 越界读。触发 kernel 为 dyn_op_BatchNorm3D_L0_003 和 dyn_op_BatchNorm3D_L0_018,block 分布 aiv(0-55)(56 核满配)。
【用户影响】:
多核分支系统性 UB 越界读——可能读到相邻核数据导致精度错误或未定义行为
附件
责任田:张磊(目标仓:wangyueting/changwei)