5 分钟上手——跑通你的第一个算子检测
系列一 · 第 2 篇
上一篇我们把 msSanitizer 比作"给算子做体检"。这篇不说大道理,直接动手,从零跑通一次内存检测,看看这份"体检报告"到底长什么样。
先说前置。msSanitizer 已经集成在 CANN 里,只要你有一个标准化的 CANN 环境(容器里正确设置了 ASCEND_HOME_PATH 就能直接用),连安装都省了。我们拿官方仓库自带的 sample_memcheck 例子开刀——它故意在 kernel 里埋了一个 UB 越界写的 bug。
第一步,让编译器配合。 光有工具不够,工具得"看得见"算子的每一次内存操作,这需要在编译时埋点。做法很轻,给 kernel 的编译选项加上 -g --cce-enable-sanitizer(写成 --sanitizer 也一样),然后照常编译。这里有两件事值得说清楚。
一是为什么必须重新编译。msSanitizer 检测的"素材"来自编译期插入的桩函数,它们像埋在算子里的探针,负责在执行时记录每一次读写和同步。不重编译,探针就不存在,工具再厉害也是睁眼瞎。
二是 -g 的用途。它保留调试信息,让报告能从出错地址反查回源码行号。缺了它照样能查出"有错",但只能说"某处越界了",说不清"哪一行",定位能力天差地别。
第二步,包起来跑。 别直接执行你的算子程序,把它交给 mssanitizer:
mssanitizer -t memcheck ./demo
-t memcheck 是选内存检测(也是默认项,不写也行)。工具会自己把 demo 拉起来,不动声色地接管它的运行时,跑完给你一份报告。全程你不用改 demo 的一行主逻辑。
第三步,读报告。 这个例子里,kernel 申请了 64 个 float 的 UB 缓冲,却用 DataCopy 搬了 256 个元素进去,妥妥的越界写。报告关键的一行长这样:
ERROR: illegal write of size 768
at ... on UB
in block aiv(0) on device 0
#0 memcheck.asc:33
一行一行看。illegal write of size 768——越界写了 768 字节,正好是 (256−64)×4,多搬的那部分一眼算清。on UB 告诉你是统一缓冲区出了事。block aiv(0) 定位到是哪个核。最值钱的是末了那行 #0 memcheck.asc:33——直接点出源码第 33 行,就是那句 DataCopy。
顺带记住一个约定:报告级别分两种。ERROR 是确定性错误,越界、非法释放都属于它,看到了基本能拍板修;WARNING 是"有风险但不一定错",多核踩踏、分配了没用的内存都在这一类,得结合场景判断。别把 WARNING 当成 ERROR 一起恐慌。
到这里,一条完整闭环就走完了:编译埋点 → 包起来跑 → 读报告定位 → 回去修。下一篇,我们钻进内存检测的内部,看看工具到底是凭什么"看见"了那多出来的 768 字节——那背后是一个还挺漂亮的影子内存设计。
- 点赞
- 收藏
- 关注作者
评论(0)