已关闭
[Bug-Report|缺陷反馈]: [工具检测] ops-math 仓 stateless_random_normal_v2 算子样例报 UB 越界,定位为 DataCopy 对齐粒度错误 #3179
Goldfish_of_Siris创建于 9月14日关闭于 22 天前
Goldfish_of_Siris
9月14日 评论:
9月14日 评论:
xujiachen8
9月15日 评论:
9月15日 评论:
您好,感谢反馈!经过分析,Float32Conversion 的 float 分支将字节单位的 BLOCK_SIZE 用作元素数对齐粒度,与您给出的 UB 越界日志吻合:calCount=4 时按 32 个 float 搬运,实际为 128 字节,而缓冲区按 32 字节分配,差值正好是 96 字节。
该分支可考虑将对齐粒度改为 BLOCK_SIZE / sizeof(T),使 float 按 8 个元素对齐,并核对调用方的缓冲区大小和后续计算范围。V2 接口实际调用 V3 kernel,公共函数也被 random_standard_normal_v2 使用,因此修正与验证需覆盖这些调用路径;您提供的修正后结果是有价值的验证依据。
另外,触发范围不宜仅限定为小于 32 个元素:是否越界取决于两种对齐后的字节数与实际缓冲区容量是否一致。例如 33 个 float 按 32 元素对齐会搬运 256 字节,按 32 字节对齐只需 160 字节,因此大于 32 的非整块尾部也需要核对。
我们将尽快分析确认这一公共搬运逻辑的修正方案。


xujiachen8
9月15日 评论:
9月15日 评论:
/assign wu-shuai2580


9月15日 将 wu-shuai2580 设为负责人
9月15日 移除了负责人 wu-shuai2580
9月15日 将 wu-shuai2580 设为负责人
9月15日 移除了负责人 wu-shuai2580
9月15日 将 wu-shuai2580 设为负责人
22 天前 关闭了 issue
21 天前 添加了label:resolved
liuchenghao
14 天前 评论:
14 天前 评论:
【Multica 同步】状态:done;说明:社区侧已由 PR !5710(zyf0712:「修复随机数算子DataCopy越界问题」,2026-09-29 合入)解决本需求,Multica 跟踪单同步关闭,感谢社区贡献者 zyf0712;详情:Multica issue AI4ME-175


Thanks for sending an issue! Please fill in the following template to help quickly solve your problem.
Describe the current behavior / 问题描述 (Mandatory / 必填)*
在使用 msSanitizer 对 ops-math 仓(9.1.0 分支)算子执行四项检测(memcheck / racecheck / initcheck / synccheck)时,
stateless_random_normal_v2(291 号)算子的 4 个 eager 样例每个都报出 2 条 UB 越界告警(合计 8 条):定位结论:算子实现的真实越界,不是工具误报。 判定过程:
DataCopy(random_kernel_base.h:218),且越界长度只有 96 字节、不是整段访问 → 判断是「搬运量算多了」而非「访问了无关地址」;0x1054)的指令记录为lenBurst:4, nBurst:1(单位 32B block)⇒ 实际搬运 128 字节;CeilAlign(calCount × 4, 32)= 32 字节(本例calCount = 4),而DataCopy写成CeilAlign(calCount, BLOCK_SIZE)——BLOCK_SIZE = GetUbBlockSize() = 32是字节数,被当成元素个数用,对 float 放大了 4 倍(32 元素 = 128 字节);asc-devkit的DataCopy实现里断言写明count * sizeof(T) must be 32B align⇒count是元素个数,正确对齐粒度应为BLOCK_SIZE / sizeof(T)(float 时 = 8);BLOCK_SIZE / sizeof(T)重新编译检测,四个工具均 0 告警、样例输出值不变。触发条件:
currUbTilingSize_ < 32(本例min(singleBufferSize, curCoreProNum_) = 4);当它 ≥ 32 时CeilAlign(N, 32) == N、两侧恰好相等因而不越界 —— 这也是该缺陷此前未被发现的原因。涉及算子如下(共 2 个):
Environment / 环境信息 (Mandatory / 必填)*
npu-smiName 列)npu-smi info)ops-math,分支 9.1.0(git rev-parse --abbrev-ref HEAD)bash build.sh --pkg --soc=ascend950 --ops=<算子> --mssanitizer -j128bash build.sh --run_example <算子> eager --soc=ascend950cd build && time timeout 600 mssanitizer -t <tool> --log-level=error -- ./test_aclnn_<算子>--log-level=errorSteps to reproduce the issue / 重现步骤 (Mandatory / 必填)*
# 1) 环境 source <CANN 安装路径>/set_env.sh export MSSANITIZER_ENABLE_DEBUG_LOG=1 # 2) 编译算子(V2 与 V3 必须一起编译:V2 的 aclnn 接口内部转发到 V3) bash build.sh --pkg --soc=ascend950 --ops=stateless_random_normal_v2,stateless_random_normal_v3 --mssanitizer -j128 # 3) 安装 ./build_out/cann-ops-math-custom_linux-x86_64.run # 4) 编译并运行样例(生成样例二进制 build/test_aclnn_stateless_random_normal_v2) bash build.sh --run_example stateless_random_normal_v2 eager --soc=ascend950 # 5) 执行检测 -> 报 UB 越界 cd build && time timeout 600 mssanitizer -t memcheck --log-level=error -- ./test_aclnn_stateless_random_normal_v2Describe the expected behavior / 预期结果 (Mandatory / 必填)*
DataCopy的对齐粒度(random/random_common/op_kernel/arch35/random_kernel_base.h的Float32Conversion):// 修改前(错误:把 32 字节当 32 个元素对齐) DataCopy(yOutput, normalFloatResult, Ops::Base::CeilAlign(calCount, static_cast<uint32_t>(BLOCK_SIZE))); // 修改后(元素级对齐:32 字节 / sizeof(T),float 时为 8 个元素) DataCopy(yOutput, normalFloatResult, Ops::Base::CeilAlign(calCount, static_cast<uint32_t>(BLOCK_SIZE / sizeof(T))));random_standard_normal_v2(op_kernel/arch35/random_standard_normal_v2.h)也调用同一个Float32Conversion,T=float且currUbTilingSize_ < 32时存在同样问题,建议一并修正;GetUbBlockSize()(字节数)当作元素个数用于DataCopy对齐的位置 —— 仓内既有正确写法可参考stateless_random_choice_with_mask.h:alignFactor = GetUbBlockSize() / valueSize。Related log / screenshot / 日志 / 截图 (Mandatory / 必填)*
详细日志见附件压缩包。
1) 现象:初次检测的告警原文(修复前)
memcheck 报告(1 个样例,另 3 个样例完全相同):
racecheck / initcheck / synccheck 三个工具均为 0 告警。
工具日志中同一 pc(
0x1054)的指令记录(定位依据):2) 修改方式
--- a/random/random_common/op_kernel/arch35/random_kernel_base.h +++ b/random/random_common/op_kernel/arch35/random_kernel_base.h @@ -215,7 +215,7 @@ __aicore__ inline void Float32Conversion( LocalTensor<T> yOutput, LocalTensor<float> normalFloatResult, const uint32_t calCount) { if constexpr (AscendC::IsSameType<T, float>::value) { - DataCopy(yOutput, normalFloatResult, Ops::Base::CeilAlign(calCount, static_cast<uint32_t>(BLOCK_SIZE))); + DataCopy(yOutput, normalFloatResult, Ops::Base::CeilAlign(calCount, static_cast<uint32_t>(BLOCK_SIZE / sizeof(T)))); } else if constexpr (AscendC::IsSameType<T, half>::value) {3) 修复后验证
修复后重新编译(
--ops=stateless_random_normal_v2,stateless_random_normal_v3)、安装、跑样例与四项检测:修复后 memcheck 报告:
四工具耗时:memcheck 11.2s / racecheck 12.2s / initcheck 12.6s / synccheck 11.3s;样例输出值与修复前一致(无功能影响)。
4) 附件说明
修复前_20260912/mssanitizer_origin_*.txt)与工具日志(mssanitizer_*.log,含MSTX_STUB/MOV_UB_TO_UB指令记录,是根因定位的关键证据)修复后_20260914/compile_after_fix.logrun_example_after_fix.log