From external-gitcode-ascend-skills
Detects memory issues in Ascend C operators (illegal access, leaks, UB overruns) using mssanitizer. Auto-selects Python or C++ mode based on project type and generates problem reports.
How this skill is triggered — by the user, by Claude, or both
Slash command
/external-gitcode-ascend-skills:ascendc-operator-mssanitizerThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
系统化检测 Ascend C 算子的内存问题,生成详细分析报告。
系统化检测 Ascend C 算子的内存问题,生成详细分析报告。
mssanitizer(MindStudio Sanitizer)是 CANN 提供的内存正确性检测工具套件,用于检测 AscendC 算子开发中的内存问题,包括:
关键步骤:在执行检测之前,必须先判断算子工程类型,选择对应的检测模式。
算子工程目录
├── 存在 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
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 提供四种检测工具:
| 工具 | 命令参数 | 检测内容 |
|---|---|---|
| 内存检测 | -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 |
适用于无 op_graph/、无 examples/ 的自定义算子工程。
使用 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:要测试的数据类型列表(仅使用算子实际支持的类型)bash "${SKILL_DIR}/scripts/run_mssanitizer.sh" \
<project>/mssanitizer_test/<operator_name>_mssanitizer_test.py \
<cann_root>
参数说明:
$ASCEND_HOME_PATH)该脚本自动执行:
--check-device-heap=yes --leak-check=yes--check-cann-heap=yes --leak-check=yesmssanitizer_summary_<timestamp>.mdparse_mssanitizer_log.py 生成详细分析报告python3 "${SKILL_DIR}/scripts/parse_mssanitizer_log.py" \
./mssanitizer_logs/memcheck_device_<timestamp>.log \
--output ./mssanitizer_logs/memcheck_analysis_report.md
适用于 ops 算子仓(如 ops-nn 仓库),工程目录包含 op_graph/、examples/、op_host/op_api/ 等目录。
examples/test_geir_*.cpp,链接 ascendcl + ge_runner + graph + registerexamples/test_aclnn_*.cpp,链接 ascendcl + opapi + nnopbasegeir_ 前缀区分SKILL_DIR="/home/rcz/agent-skills/skills/ascendc-operator-mssanitizer"
bash "${SKILL_DIR}/scripts/run_mssanitizer_geir.sh" \
<project_dir> \
<cann_root>
参数说明:
/home/rcz/ops-nn/activation/gelu_quant)$ASCEND_HOME_PATH)脚本自动执行:
examples/test_geir_*.cpp 或 examples/test_aclnn_*.cppgeir_mssanitizer_summary_<timestamp>.mdparse_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
检测完成后在 <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 # 汇总报告
检测完成后在 <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
步骤 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 |
-g 编译选项后可获取源码位置症状:illegal write/read 错误
排查步骤:
DataCopy 的第三个参数是否正确典型错误:
// 错误:乘以 sizeof(T) 或其他系数
DataCopy(xLocal, xGlobal, totalLength * sizeof(T)); // ❌
DataCopy(xLocal, xGlobal, totalLength * 2); // ❌
// 正确:直接使用元素数量
DataCopy(xLocal, xGlobal, totalLength); // ✓
症状:memory leak 错误
排查步骤:
AllocTensor 是否有对应的 FreeTensorEnQue/DeQue 是否配对使用pipe.InitBuffer 的缓冲区管理典型错误:
// 错误:忘记释放
LocalTensor<T> xLocal = xQueue.AllocTensor<T>();
// ... 使用 xLocal
// 缺少 xQueue.FreeTensor(xLocal); // ❌
// 正确:配对使用
LocalTensor<T> xLocal = xQueue.AllocTensor<T>();
// ... 使用 xLocal
xQueue.FreeTensor(xLocal); // ✓
症状:UB address out of bounds 错误
排查步骤:
pipe.InitBuffer 分配的大小是否足够典型错误:
// 错误:缓冲区大小不足
pipe.InitBuffer(tmpBuffer, totalSize); // ❌ 未考虑临时空间需求
// 正确:根据算子需求分配足够空间
pipe.InitBuffer(tmpBuffer, totalSize * sizeof(T) + EXTRA_SPACE); // ✓
检查项:
ASCEND_HOME_PATH 指向正确的 CANN 根路径cann_root 参数原因: mssanitizer 启动时会修改 LD_LIBRARY_PATH,导致 CANN lib64 路径丢失
解决: run_mssanitizer.sh 已自动在 LD_LIBRARY_PATH 头部补充 CANN lib64 路径。若仍失败,手动执行:
export LD_LIBRARY_PATH=<cann_root>/lib64:$LD_LIBRARY_PATH
原因: 这两个选项互斥
解决: 分两次运行 memcheck(run_mssanitizer.sh / run_mssanitizer_geir.sh 已自动处理)
<unknown>:0原因: 算子编译时未添加 -g 调试选项
解决: 重新编译算子添加 -g -O0 选项
原因: mssanitizer 只在检测到错误时才写入日志文件
解决: 日志为 0 字节表示该检测项通过,无需处理。可通过 mssanitizer 内部日志(mindstudio_sanitizer_log/)确认工具是否正常运行。
检查项:
examples/ 目录下存在 test_geir_*.cpp 或 test_aclnn_*.cppop_graph/ 目录存在且包含算子 proto 头文件lib64/ 和 aarch64-linux/lib64/ 下有 libopapi.so 和 libnnopbase.soASCEND_HOME_PATH、LD_LIBRARY_PATH)libopapi.so 失败,检查 CANN 架构子目录路径(aarch64-linux/lib64)检查项:
-g -O0 以获取精确的代码位置npx claudepluginhub ascend-ai-coding/awesome-ascend-skills --plugin migration-ascend-torchnpu-skillsReviews Ascend C operator code for safety and compliance using hypothesis-driven methodology. Checks for memory leaks, integer overflows, null pointers, and coding standard violations.
Use AddressSanitizer to detect memory safety bugs in C/C++ programs. Identifies use-after-free, buffer overflow, memory leaks, and other memory errors.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.