ascendc-mssanitizer について
Ascend C オペレーター開発者向けのメモリ検査スキルです。プロジェクト構成に応じて Python または C++ の手順を選び、mssanitizer を実行して概要と問題分析レポートを作成します。
主な機能
- 01構成に応じた検査モードの選択
- 02メモリ・競合・初期化・同期の検査
- 03C++ テストプログラムの自動ビルド
- 04概要とログ分析レポートの作成
活用シーン
- 01不正アクセスやメモリリークの調査
- 02並列処理のデータ競合と同期問題の確認
- 03修正後のオペレーターのメモリ安全性検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ascend/ agent-skills --skill ascendc-mssanitizerインストール後、Claude Code で/ascendc-mssanitizerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/error_types.mdmssanitizer_usage_guide.mdscripts/gen_test_script.pyparse_mssanitizer_log.pyrun_mssanitizer_geir.shrun_mssanitizer.sh詳細
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 を 2 段階で実行してメモリリークの発生箇所を特定します:
┌─────────────────────────────────────┐
│ 用户代码(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の 3 番目のパラメーターが正しいか確認します- 要素数の計算が正しいか確認します(注意:パラメーターはバイト数ではなく要素数です)
- コピー元/コピー先のアドレスが範囲外でないか確認します
典型的なエラー:
// 错误:乘以 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 は CANN の lib64 パスを LD_LIBRARY_PATH の先頭に自動的に追加します。それでも失敗する場合は、手動で実行してください:
export LD_LIBRARY_PATH=<cann_root>/lib64:$LD_LIBRARY_PATH
問題: CANNOT enable both --check-device-heap and --check-cann-heap
原因: この 2 つのオプションは同時に指定できません
解決策: memcheck を 2 回に分けて実行してください(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 模式