ascendc-mssanitizer
Ascend C 算子 mssanitizer 内存检测分析技能。用于检测和分析算子内存问题:非法内存访问、非法释放、内存泄漏、UB地址越界,生成问题报告。自动识别算子工程类型(ops算子仓用GE IR模式,自定义算子用Python模式)。触发关键词:mssanitizer、内存检测、内存泄漏、非法访问、illegal free、内存错误。
How do I install this agent skill?
npx skills add https://github.com/ascend/agent-skills --skill ascendc-mssanitizerIs this agent skill safe to install?
- Gen Agent Trust Hubpass
This skill provides a memory safety analysis tool for Huawei Ascend C operators. It automates the detection of memory leaks and illegal access by generating and executing test scripts and C++ binaries using the vendor's official mssanitizer utility.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
What does this agent skill do?
Ascend C 算子 mssanitizer 内存检测分析
系统化检测 Ascend C 算子的内存问题,生成详细分析报告。
概述
mssanitizer(MindStudio Sanitizer)是 CANN 提供的内存正确性检测工具套件,用于检测 AscendC 算子开发中的内存问题,包括:
- 内存泄漏(Memory Leak)
- 非法内存访问(Illegal Access)
- 未初始化内存使用(Uninitialized Memory)
- 数据竞争(Data Race)
- 同步问题(Sync Issues)
触发条件
- 用户需要对 Ascend C 算子进行内存检测
- 用户请求内存泄漏检测
- 用户需要验证算子内存安全性
- 用户提到 "mssanitizer"、"内存检测"、"内存泄漏"、"非法访问" 等关键词
工程类型判断与检测模式选择
关键步骤:在执行检测之前,必须先判断算子工程类型,选择对应的检测模式。
判断逻辑
算子工程目录
├── 存在 op_graph/ 目录? ─── 是 ──→ ops 算子仓 → C++ 模式
├── 存在 op_host/op_api/ 目录? ── 是 ──→ ops 算子仓 → C++ 模式
├── 存在 examples/test_geir_*.cpp? ── 是 ──→ ops 算子仓 → C++ 模式 (GE IR 子模式)
├── 存在 examples/test_aclnn_*.cpp? ── 是 ──→ ops 算子仓 → C++ 模式 (aclnn 子模式)
└── 以上均无 ──→ 自定义算子仓 → Python 模式
检测模式对比
| 特性 | Python 模式 | C++ 模式 (GE IR) | C++ 模式 (aclnn) |
|---|---|---|---|
| 适用工程 | 自定义算子仓 | ops 算子仓 | ops 算子仓 |
| 工程特征 | 无 op_graph/、无 examples/ | 有 op_graph/、有 test_geir_*.cpp | 有 examples/、有 test_aclnn_*.cpp |
| 测试载体 | Python 脚本(torch_npu 调用) | C++ 可执行文件(GE IR 图调用) | C++ 可执行文件(aclnn API 调用) |
| 测试脚本 | gen_test_script.py 生成 | examples/test_geir_*.cpp | examples/test_aclnn_*.cpp |
| 执行脚本 | run_mssanitizer.sh | run_mssanitizer_geir.sh | run_mssanitizer_geir.sh |
| 链接库 | torch_npu | ascendcl, ge_runner, graph, register | ascendcl, opapi, nnopbase |
| 日志前缀 | memcheck_device_ | geir_memcheck_device_ | geir_memcheck_device_ |
| 汇总报告 | mssanitizer_summary_ | geir_mssanitizer_summary_ | geir_mssanitizer_summary_ |
| 优势 | 覆盖多种 shape/dtype | 直接调用算子 kernel,更贴近真实执行 | 无需 op_graph,构建更简单 |
| 劣势 | fallback 可能绕过自定义算子 | 需编译 C++ 可执行文件 | 需编译 C++ 可执行文件 |
注意:
run_mssanitizer_geir.sh脚本已自动支持两种 C++ 子模式,会优先查找test_geir_*.cpp,找不到时自动回退到test_aclnn_*.cpp。
工具脚本
本 skill 提供以下脚本,位于 scripts/ 目录:
| 脚本 | 用途 | 模式 |
|---|---|---|
scripts/gen_test_script.py | 根据算子名称自动生成 Python 测试脚本 | Python |
scripts/run_mssanitizer.sh | Python 模式:执行全部 5 项检测并生成汇总报告 | Python |
scripts/run_mssanitizer_geir.sh | C++ 模式:自动构建+检测+生成汇总报告(支持 GE IR 和 aclnn) | C++ |
scripts/parse_mssanitizer_log.py | 解析 memcheck 日志生成问题分析报告 | 通用 |
SKILL 根目录: /home/rcz/agent-skills/skills/ascendc-operator-mssanitizer
前置条件
必需的环境变量
| 环境变量 | 说明 | 获取方式 |
|---|---|---|
ASCEND_HOME_PATH | CANN 安装路径 | CANN set_env.sh 设置 |
LD_LIBRARY_PATH | 动态库路径 | 包含 CANN lib64 |
环境激活
source /root/miniconda3/bin/activate cann_env
source /root/miniconda3/envs/cann_env/Ascend/cann-8.5.0/set_env.sh
关键约束(实战经验)
- CANN 版本锁定:容器中可能存在多套 CANN(如 cann-8.5 和 cann-9.0),
set_env.sh设置的ASCEND_HOME_PATH可能指向错误版本。脚本会显式覆盖为用户指定路径,确保 mssanitizer 使用正确版本。 --check-device-heap与--check-cann-heap互斥:不能同时启用,必须分两次跑 memcheck。libhccl.so依赖:mssanitizer 修改LD_LIBRARY_PATH后可能丢失libhccl.so,导致torch_npu导入失败。脚本已自动补全 CANN lib64 路径。- 容器兼容性:脚本只使用
grep(非rg),确保 Docker 容器内可用。 - 日志为空 = 无错误:mssanitizer 只在检测到错误时才写入日志文件。日志文件大小为 0 表示该检测项通过,不是工具未运行。
检测工具类型
mssanitizer 提供四种检测工具:
| 工具 | 命令参数 | 检测内容 |
|---|---|---|
| 内存检测 | -t memcheck | 非法内存访问、非法释放、内存泄漏、UB地址越界 |
| 竞争检测 | -t racecheck | 多核并行竞争条件、数据竞争 |
| 未初始化检测 | -t initcheck | 未初始化内存读取 |
| 同步检测 | -t synccheck | 同步错误、同步点问题 |
常用参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
-t <tool> | 指定检测工具 | memcheck |
--leak-check=<yes/no> | 是否检测内存泄漏 | no |
--check-device-heap=<yes/no> | 检测 Device 接口泄漏 | no |
--check-cann-heap=<yes/no> | 检测 AscendCL 接口泄漏(与 device-heap 互斥) | no |
--log-file=<file> | 日志输出文件 | stdout |
--log-level=<level> | 日志级别(warn) | warn |
--kernel-name=<name> | 只检测指定名称的 kernel | all |
--block-id=<id> | 只检测指定 block | all blocks |
--cache-size=<size> | 单 block 记录缓存大小(MB) | 100 |
检测流程
━━━━━━━━━━ 模式 A:Python 模式(自定义算子仓)━━━━━━━━━━
适用于无 op_graph/、无 examples/ 的自定义算子工程。
阶段 1:生成测试脚本
使用 gen_test_script.py 自动生成针对指定算子的测试脚本:
SKILL_DIR="/home/rcz/agent-skills/skills/ascendc-operator-mssanitizer"
python3 "${SKILL_DIR}/scripts/gen_test_script.py" \
--operator <operator_name> \
--fallback <fallback_function> \
--dtypes float16 float32 \
--output <project>/mssanitizer_test/<operator_name>_mssanitizer_test.py
参数说明:
--operator:自定义算子名称(对应torch.ops.customize.<name>)--fallback:torch.nn.functional中的回退函数名(如gelu、relu)。当自定义算子未注册时自动使用,确保 NPU 通路仍会执行并被 mssanitizer 监控--dtypes:要测试的数据类型列表(仅使用算子实际支持的类型)
阶段 2:执行检测
bash "${SKILL_DIR}/scripts/run_mssanitizer.sh" \
<project>/mssanitizer_test/<operator_name>_mssanitizer_test.py \
<cann_root>
参数说明:
- 第 1 个参数:测试脚本路径(阶段 1 生成的)
- 第 2 个参数:CANN 安装根路径(可选,默认取
$ASCEND_HOME_PATH)
该脚本自动执行:
- memcheck (device-heap) —
--check-device-heap=yes --leak-check=yes - memcheck (cann-heap) —
--check-cann-heap=yes --leak-check=yes - racecheck — 数据竞争检测
- initcheck — 未初始化内存检测
- synccheck — 同步问题检测
- 生成汇总报告 —
mssanitizer_summary_<timestamp>.md - 解析 memcheck 日志 — 调用
parse_mssanitizer_log.py生成详细分析报告
阶段 3:单独解析日志(可选)
python3 "${SKILL_DIR}/scripts/parse_mssanitizer_log.py" \
./mssanitizer_logs/memcheck_device_<timestamp>.log \
--output ./mssanitizer_logs/memcheck_analysis_report.md
━━━━━━━━━━ 模式 B:C++ 模式(ops 算子仓)━━━━━━━━━━
适用于 ops 算子仓(如 ops-nn 仓库),工程目录包含 op_graph/、examples/、op_host/op_api/ 等目录。
特点
- 通过 C++ 可执行文件调用算子,更贴近真实执行路径
- 自动识别测试源文件类型:
- GE IR 子模式:使用
examples/test_geir_*.cpp,链接ascendcl + ge_runner + graph + register - aclnn 子模式:使用
examples/test_aclnn_*.cpp,链接ascendcl + opapi + nnopbase
- GE IR 子模式:使用
- 自动构建 C++ 可执行文件(若尚未构建)
- 日志文件以
geir_前缀区分
一键执行
SKILL_DIR="/home/rcz/agent-skills/skills/ascendc-operator-mssanitizer"
bash "${SKILL_DIR}/scripts/run_mssanitizer_geir.sh" \
<project_dir> \
<cann_root>
参数说明:
- 第 1 个参数:算子工程目录路径(如
/home/rcz/ops-nn/activation/gelu_quant) - 第 2 个参数:CANN 安装根路径(可选,默认取
$ASCEND_HOME_PATH)
脚本自动执行:
- 检测算子工程结构,定位
examples/test_geir_*.cpp或examples/test_aclnn_*.cpp - 自动构建测试可执行文件(若尚未构建),根据源文件类型选择 GE IR 或 aclnn 构建方式
- 依次执行 5 项检测(memcheck_device → memcheck_cann → racecheck → initcheck → synccheck)
- 生成汇总报告
geir_mssanitizer_summary_<timestamp>.md - 调用
parse_mssanitizer_log.py生成详细分析报告
手动分步执行(可选)
如需更细粒度的控制,可手动执行:
# 1. 构建测试可执行文件(首次需要)
cd <project>/mssanitizer_test/build
cmake . && make -j$(nproc)
# 2. 逐项执行检测
MSSAN=<cann_root>/tools/mssanitizer/bin/mssanitizer
LOGDIR=<project>/mssanitizer_logs
TS=$(date +%Y%m%d_%H%M%S)
$MSSAN -t memcheck --check-device-heap=yes --leak-check=yes \
--log-file=$LOGDIR/geir_memcheck_device_$TS.log \
-- ./test_geir_<op_name> float
$MSSAN -t memcheck --check-cann-heap=yes --leak-check=yes \
--log-file=$LOGDIR/geir_memcheck_cann_$TS.log \
-- ./test_geir_<op_name> float
$MSSAN -t racecheck --log-file=$LOGDIR/geir_racecheck_$TS.log \
-- ./test_geir_<op_name> float
$MSSAN -t initcheck --log-file=$LOGDIR/geir_initcheck_$TS.log \
-- ./test_geir_<op_name> float
$MSSAN -t synccheck --log-file=$LOGDIR/geir_synccheck_$TS.log \
-- ./test_geir_<op_name> float
# 3. 解析日志
python3 ${SKILL_DIR}/scripts/parse_mssanitizer_log.py \
$LOGDIR/geir_memcheck_device_$TS.log \
--output $LOGDIR/geir_memcheck_device_analysis_$TS.md
输出文件
Python 模式输出
检测完成后在 <project>/mssanitizer_logs/ 下生成:
<project>/mssanitizer_logs/
├── memcheck_device_<ts>.log # memcheck device-heap 原始日志
├── memcheck_device_report_<ts>.json # memcheck device-heap 测试结果
├── memcheck_device_analysis_<ts>.md # memcheck device-heap 解析报告
├── memcheck_cann_<ts>.log # memcheck cann-heap 原始日志
├── memcheck_cann_report_<ts>.json
├── memcheck_cann_analysis_<ts>.md
├── racecheck_<ts>.log
├── racecheck_report_<ts>.json
├── initcheck_<ts>.log
├── initcheck_report_<ts>.json
├── synccheck_<ts>.log
├── synccheck_report_<ts>.json
└── mssanitizer_summary_<ts>.md # 汇总报告
GE IR 模式输出
检测完成后在 <project>/mssanitizer_logs/ 下生成:
<project>/mssanitizer_logs/
├── geir_memcheck_device_<ts>.log # memcheck device-heap 原始日志
├── geir_memcheck_cann_<ts>.log # memcheck cann-heap 原始日志
├── geir_racecheck_<ts>.log
├── geir_initcheck_<ts>.log
├── geir_synccheck_<ts>.log
└── geir_mssanitizer_summary_<ts>.md # 汇总报告(含解析)
注意:日志文件大小为 0 表示该检测项通过,未检测到错误。mssanitizer 只在检测到错误时才写入日志内容。
分阶段检测策略
根据 CANN 软件栈结构,memcheck 分两阶段定位内存泄漏位置:
┌─────────────────────────────────────┐
│ 用户代码(Host 侧) │
├─────────────────────────────────────┤
│ AscendCL 接口(CANN API) │
├─────────────────────────────────────┤
│ Device 接口(驱动层接口) │
└─────────────────────────────────────┘
步骤 1:检测 Device 接口泄漏
mssanitizer -t memcheck --check-device-heap=yes --leak-check=yes -- python3 test.py
# 或 GE IR 模式:
mssanitizer -t memcheck --check-device-heap=yes --leak-check=yes -- ./test_geir_op float
- 无泄漏输出 → 泄漏发生在 Device 侧应用
- 有泄漏输出 → 继续步骤 2
步骤 2:检测 AscendCL 接口泄漏
mssanitizer -t memcheck --check-cann-heap=yes --leak-check=yes -- python3 test.py
# 或 GE IR 模式:
mssanitizer -t memcheck --check-cann-heap=yes --leak-check=yes -- ./test_geir_op float
错误类型与严重程度
严重程度分类
| 严重程度 | 错误类型 | 处理优先级 |
|---|---|---|
| 🔴 严重 | illegal_write, illegal_read, illegal_free | 立即修复 |
| 🟡 中等 | memory_leak | 尽快修复 |
| 🟢 轻微 | 未初始化内存使用 | 建议修复 |
日志关键字段说明
| 字段 | 说明 | 示例 |
|---|---|---|
at 0x... on GM | 全局内存地址 | 0x12c000000010 |
in block on device N | 设备和 block 信息 | device 0 |
serialNo:N | 指令序列号,用于定位代码位置 | serialNo:22 |
size N | 访问的字节数 | size 8 |
问题定位技巧
- 使用 serialNo 定位:serialNo 对应编译后的指令序列号,添加
-g编译选项后可获取源码位置 - 地址分析:GM 地址可用于分析内存布局和越界情况
- 大小分析:访问大小可帮助判断数据类型和操作类型
- illegal_free 关联分析:如果 illegal_free 伴随 illegal_write 出现,通常是越界写入破坏了内存管理结构,应先修复 illegal_write
常见问题排查清单
1. DataCopy 参数错误
症状:illegal write/read 错误
排查步骤:
- 检查
DataCopy的第三个参数是否正确 - 确认元素数量计算是否正确(注意:参数是元素数量,不是字节数)
- 检查源/目标地址是否越界
典型错误:
// 错误:乘以 sizeof(T) 或其他系数
DataCopy(xLocal, xGlobal, totalLength * sizeof(T)); // ❌
DataCopy(xLocal, xGlobal, totalLength * 2); // ❌
// 正确:直接使用元素数量
DataCopy(xLocal, xGlobal, totalLength); // ✓
2. 内存分配/释放不配对
症状:memory leak 错误
排查步骤:
- 检查所有
AllocTensor是否有对应的FreeTensor - 检查
EnQue/DeQue是否配对使用 - 检查
pipe.InitBuffer的缓冲区管理
典型错误:
// 错误:忘记释放
LocalTensor<T> xLocal = xQueue.AllocTensor<T>();
// ... 使用 xLocal
// 缺少 xQueue.FreeTensor(xLocal); // ❌
// 正确:配对使用
LocalTensor<T> xLocal = xQueue.AllocTensor<T>();
// ... 使用 xLocal
xQueue.FreeTensor(xLocal); // ✓
3. UB 缓冲区大小不足
症状:UB address out of bounds 错误
排查步骤:
- 检查
pipe.InitBuffer分配的大小是否足够 - 确认数据类型大小计算是否正确
- 检查是否需要 32 字节对齐
典型错误:
// 错误:缓冲区大小不足
pipe.InitBuffer(tmpBuffer, totalSize); // ❌ 未考虑临时空间需求
// 正确:根据算子需求分配足够空间
pipe.InitBuffer(tmpBuffer, totalSize * sizeof(T) + EXTRA_SPACE); // ✓
故障排除
问题: 未找到 mssanitizer
检查项:
- 确保
ASCEND_HOME_PATH指向正确的 CANN 根路径 - 确保 CANN 版本支持 mssanitizer(8.0+)
- 容器中可能存在多套 CANN,需显式传入
cann_root参数
问题: torch_npu 导入失败 (libhccl.so)
原因: mssanitizer 启动时会修改 LD_LIBRARY_PATH,导致 CANN lib64 路径丢失
解决: run_mssanitizer.sh 已自动在 LD_LIBRARY_PATH 头部补充 CANN lib64 路径。若仍失败,手动执行:
export LD_LIBRARY_PATH=<cann_root>/lib64:$LD_LIBRARY_PATH
问题: CANNOT enable both --check-device-heap and --check-cann-heap
原因: 这两个选项互斥
解决: 分两次运行 memcheck(run_mssanitizer.sh / run_mssanitizer_geir.sh 已自动处理)
问题: 日志显示 <unknown>:0
原因: 算子编译时未添加 -g 调试选项
解决: 重新编译算子添加 -g -O0 选项
问题: 日志文件大小为 0
原因: mssanitizer 只在检测到错误时才写入日志文件
解决: 日志为 0 字节表示该检测项通过,无需处理。可通过 mssanitizer 内部日志(mindstudio_sanitizer_log/)确认工具是否正常运行。
问题: C++ 模式构建失败
检查项:
- 确认
examples/目录下存在test_geir_*.cpp或test_aclnn_*.cpp - GE IR 模式:确认
op_graph/目录存在且包含算子 proto 头文件 - aclnn 模式:确认 CANN 的
lib64/和aarch64-linux/lib64/下有libopapi.so和libnnopbase.so - 确认 CANN 环境已正确激活(
ASCEND_HOME_PATH、LD_LIBRARY_PATH) - 检查 CMake 输出中的编译错误
- 如链接
libopapi.so失败,检查 CANN 架构子目录路径(aarch64-linux/lib64)
问题: 未检测到错误但程序失败
检查项:
- 尝试其他 mssanitizer 工具(racecheck、initcheck)
- 检查逻辑错误
- 使用其他调试工具
注意事项
- 性能影响:mssanitizer 会显著降低程序运行速度(可能慢 10-100 倍),仅用于调试
- 内存开销:检测过程需要额外内存记录分配信息,可能需要更大的内存
- 多次运行:某些问题可能不是每次都复现,建议多次运行检测
- 模式选择:ops 算子仓优先使用 C++ 模式(脚本自动识别 GE IR / aclnn),能直接调用算子 kernel,检测结果更准确
最佳实践
- 添加调试信息: 编译时添加
-g -O0以获取精确的代码位置 - 执行所有检测模式: 运行全部检测模式(脚本已默认执行全部 5 项)
- 按优先级修复: 先解决非法访问问题,再处理内存泄漏
- 重新验证: 修复后重新运行 mssanitizer 确认问题已解决
- 定期检测: 在算子开发完成后、修改内存相关代码后、提交代码前进行检测
- 选择正确模式: ops 算子仓用 C++ 模式(脚本自动识别 GE IR / aclnn),自定义算子用 Python 模式
相关文档
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/ascend/agent-skills/ascendc-mssanitizer">View ascendc-mssanitizer on skillZs</a>