msMemScope 显存数据采集与解读

SkillDocs & knowledge

Embedded memory analysis, optimization, and leak detection

Use msMemScope 显存数据采集与解读 in Claude, ChatGPT or Ahel Desktop

Free. Sign in, add msMemScope 显存数据采集与解读 and connect your AI. About a minute.

Also: Claude Code · Cursor · Codex

Then ask your AI: use the msMemScope 显存数据采集与解读 skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

msMemScope 显存数据采集与解读Start free

What this skill tells your AI

The instructions your AI receives, as published by a5c-ai/babysitter in library/specializations/embedded-systems/skills/memory-analysis/SKILL.md and read by ahel’s review.

技能目标

本 Skill 覆盖显存数据全链路:采集指导 → 数据解读 → 问题诊断。根据用户的实际诉求,选择正确的采集方式与参数组合,生成可直接执行的命令或代码,指导用户完成采集并确认产物完整可用;随后对采集产物做系统性解读(曲线趋势、显存大头、峰值占比),并对典型显存问题(泄漏、OOM)做根因定位与原因分析。

整体链路:

用户诉求 → 采集方案 → 执行采集 → 产物确认 → 数据解读 → 问题诊断

提示:流程中任一步出现明显报错或异常,先停下排查、修好再继续,不要硬往下走;典型问题已汇总在 Part A 文末「常见问题与兜底」,遇到问题先查那里。

解读是证据驱动的:所有结论必须引用 dump 数据中的具体证据(数值、占比、事件、调用栈),以「问题 → 证据 → 建议」的结构组织输出,而不是描述你做了哪些操作;证据不足时不下结论,明确列出还缺哪些信息(缺调用栈、缺拆解数据等)。

流程入口:先判断数据是否已有

用户状态走哪个分支
尚无采集数据(先明确诉求,见 Part A 决策树)→ Part A 采集
已有 dump 数据(memscope_dump_*.csv/db、memory_compare_*.csv 或产物目录)→ Part B 解读与诊断

何时用 / 何时不用

用本 Skill:

  • 用户提出显存问题(OOM、显存泄漏、显存占用过高、Step 间显存差异)且尚无采集数据,需要采集数据用于分析
  • 用户需要采集显存快照、显存拆解(权重/梯度/优化器/kv_cache 等)数据
  • 用户要求"帮我采集显存数据""帮我看下内存都花在哪了""帮我采个数分析 OOM"
  • 用户提供 msMemScope 采集产物(memscope_dump_*.csv / *.db / memory_compare_*.csv 或产物目录),要求解读或诊断
  • 用户询问显存曲线趋势、显存大头、峰值占比,或询问是否存在显存泄漏、OOM 根因

不要用本 Skill:

  • 非显存维度问题(计算/通信/调度等性能瓶颈)→ 使用 ascend-* 系列性能技能
  • 需要排查内存踩踏→ 本 Skill 当前不覆盖
  • 需要可视化展示数据 → 可引导用户使用 MindStudio Insight 可视化(csv 数据先用 scripts/convert_dump.py --to-db 转 db 再导入;本 Skill 只做数据解读)

Part A 显存数据采集

本部分适用于尚无采集数据的场景。若用户已有 dump 数据,直接跳到 Part B。

A1 前置条件检查

  1. 确认工具已安装:

    msmemscope --version
    

    命令不存在或版本过低时,先安装/升级 msMemScope 工具,再进行后续步骤。

  2. 确认运行环境:采集需要目标训练/推理脚本可运行的环境(CANN 环境变量已 source、Ascend NPU 可用)。

  3. (Python 接口方式)注入环境变量:使用 Python 接口采集前必须执行:

    source msmemscope --load-api-env
    

    ⚠️ 硬性要求:使用完毕后,必须执行 source msmemscope --unload-api-env 清除环境变量,避免与后续操作产生冲突。若未及时清除,后续执行 set_env 类操作或手动设置 LD_PRELOAD、LD_LIBRARY_PATH 等 LD 类环境变量时,可能产生不可预知的错误。详见 references/msmemscope_usage.md(§5 环境变量管理)。

A2 采集决策树(核心)

根据用户诉求选择采集方案,必须先明确诉求再决定配置,不要默认使用同一套参数:

用户诉求
   │
   ├─ OOM / 显存不足 ─────────────► analysis=oom[:K](联动 alloc/free)+ call_stack
   ├─ 怀疑显存泄漏 ───────────────► 在线:analysis=leaks;离线:mstx mark A/B/C + check_leaks
   ├─ 显存大头 / 占比拆解 ─────────► analysis=decompose(自动使能钩子)+ describe 自定义标签
   ├─ Step 间差异 / 显存增长 ──────► 先分次采集两个 Step 数据,再 --compare 对比
   ├─ 整体曲线 / 趋势 ────────────► events=alloc,free(曲线由 used/device_used 事件驱动)
   └─ 推理 / 强化学习场景 ─────────► 一键分析 init_framework_hooks(vLLM/verl 快照)
        │
        ▼
   场景适配(训练/推理/FSDP/verl 约束检查,见「场景适配表」)
        │
        ▼
   格式:默认 csv(采集快、可直接脚本分析)——仅当用户明确要 MindStudio Insight 可视化时才用 db,见 A5 第 10 条
        │
        ▼
   生成可执行命令 / Python API 代码 → 执行 → 确认产物(见「产物确认」)

诉求 → 采集方案映射表

用户诉求推荐方案关键配置采集方式
OOM / 显存不足--analysis=oom[:K]自动联动 alloc/free;建议加 --call-stack 便于归因;K∈[1,1000] 默认 10命令行或 Python 接口
怀疑显存泄漏(在线)--analysis=leaks--events 含 alloc,free命令行
怀疑显存泄漏(离线)mstx mark A/B/C 打点 + 事后 check_leaksmark 打点标记 A→B→C 范围;采集时 --events 含 alloc,freemstx 打点 + Python 接口
显存大头 / 占比拆解--analysis=decompose自动使能框架钩子;必要时用 describe 自定义标签命令行或 Python 接口
显存快照(单点)take_snapshot()device_mask、name 可选Python 接口(独立调用)
Step 间差异 / 显存增长分次采集两个 Step + --compare采集时 --steps=N(一次一个 Step);对比时 TASK_QUEUE_ENABLE=0、--compare --input-path=p1,p2命令行
整体曲线 / 趋势events=alloc,free(+可选 launch)建议加 --call-stack 辅助定位命令行或 Python 接口
推理(vLLM-Ascend)快照/拆解一键分析 init_framework_hooks框架 vllm_ascend 11.0 / worker / decompose 或 snapshotPython 接口
强化学习(verl)快照一键分析 init_framework_hooks框架 verl 0.7.0 / TaskRunner / snapshotPython 接口

若用户诉求不明确(如"帮我采集数据看看"),先追问用户想解决什么问题(是否 OOM、是否怀疑泄漏、是否想知道内存花在哪),再按上表选择方案,不要替用户猜测。

A3 采集方式与参数详解

msMemScope 支持三种采集方式,各有适用场景:

采集方式适用场景说明
命令行采集非 Python 场景(bash 脚本拉起训练等)msmemscope [options] bash user.sh 或 msmemscope [options] -- <prog> [args];VLLM-Ascend 不支持
Python 接口采集Python 训练/推理脚本,需精细控制采集范围config/start/stop/step/take_snapshot 组合;推荐方式
mstx 打点采集结合 mstx 标记 Step 边界/泄漏分析范围;C 脚本mstx.range_start("step start") / mstx.mark;仅支持单卡局部数据

采集范围评估:局部 vs 全局(生成采集方案前先评估)

原则:先分析用户任务,从理论上评估 Python 接口局部采集(start()/stop() 包裹目标代码段)能否支撑当前分析诉求;能支撑就用局部采集(数据量小、时间轴聚焦、分析快、资源占用低),不足以支撑时才用全局采集。避免"全量采集再分析"——全量数据往往数十万~百万行,后续分析引入不必要的困难。

诉求 → 采集范围决策表:

用户诉求局部采集可支撑?理由与推荐做法
OOM 定位✅ 常可OOM 通常发生在特定阶段(profile 段、某 batch、图捕获等),start()/stop() 包住触发段即可;需要调用栈时补 --call-stack
单阶段拆解 / 大头占比✅ 常可包住目标阶段(如权重加载段、训练循环内一个 Step),数据量小且拆解归因完整
局部泄漏验证(段内申请段内释放)✅ 可包住"申请逻辑 + 释放逻辑"相互独立的一段代码,验证段内块能否全部释放
泄漏趋势判断(在线/离线)❌ 常不足算法 A/B 需要多个周期(Step)的 used 曲线对比"是否回基线",局部单段无法判断周期性增长——至少覆盖多个 Step 或全局采集
整条曲线全貌 / 进程生命周期❌ 不足需要启动→稳态→退出全过程事件
未知阶段的排查❌ 不足(第一轮)不知道问题出在哪个阶段时,先全局采集看轮廓,再用局部采集聚焦复验
Step 间对比✅ 可分次局部采集两个 Step 数据(--steps=N),再 --compare

局部采集的注意点:

  • 存量显存只统计不分析:start() 前已分配未释放的块只参与总量统计,不参与泄漏/拆解分析——若怀疑对象可能在 start 前申请、start 后持续持有,局部采集会漏,需要将 start 提前或全局采集。
  • 幽灵机制不变:局部窗口内的 shadow 判别规则与 Part B 泄漏诊断一致(见 references/leak_diagnosis_guide.md §1/§4)。
  • 局部采集期间若需要跨 stop 继续观察,用多段 start()/stop(),注意 shadow 块在每段 start 时转正参与统计。

命令行采集模板

# 方式一(推荐):user.sh 为用户脚本
msmemscope [options] bash user.sh

# 方式二:直接指定程序
msmemscope [options] -- <prog_name> [prog_options]

常用示例(格式默认 csv,无需写 --format;仅用户明确要 MindStudio Insight 可视化时追加 --format=db):

# OOM 分析(K=50,含调用栈)
msmemscope --analysis=oom:50 --call-stack=python:10,c:20 --events=alloc,free bash train.sh

# 显存泄漏检测
msmemscope --analysis=leaks --events=alloc,free --call-stack=python:10 bash train.sh

# 显存拆解(训练场景,自动使能框架钩子)
msmemscope --analysis=decompose --events=alloc,free --output-path=/home/user/output bash train.sh

# 采集指定 Step(供后续 Step 间对比,一次一个 Step)
msmemscope --steps=5 --level=kernel --events=alloc,free bash train.sh

# Step 间对比(采集两个 Step 后执行,与 --input-path 必须成对)
msmemscope --compare --input-path=/home/user/step1,/home/user/step2 --level=kernel

采集模板(Python 接口 / mstx 打点)

Python 接口模板(config/start/stop 组合)、mstx 打点模板(range_start/range_end + mark 离线泄漏打点)与 config 参数对应关系见 references/msmemscope_usage.md(§2 Python 接口速查);assets/collection_template.py 为可运行参考模板。局部采集(包住目标代码段)见上方「采集范围评估」小节。

关键参数速查

参数可选值默认值说明
--eventsalloc,free,launch,access,traceback,nonealloc,free,launchalloc/free 不成对配置会导致配对信息缺失;traceback 仅 API 方式可用
--analysisleaks,decompose,oom[:K],noneleaks分析功能;none 表示不启用
--levelop,kernelop采集算子 or kernel 粒度(旧值 0/1 已废弃)
--call-stackpython[:N],c[:N]深度默认 50采集调用栈,N∈[0,1000];泄漏归因必需
--steps1~5 个整数全部指定 Step 采集;与分析功能互斥
--devicenpu、npu:{id}、cpunpucpu 仅锁页内存
--collect-modeimmediate,deferredimmediatedeferred 需配合 start()/stop();deferred 模式分析功能不可用
--formatdb,csvcsv默认 csv,推荐:采集快、体积小、便于脚本分析;仅需要在 MindStudio Insight 做可视化时才选 db(采集慢且不利于脚本分析,需转 csv 才能用本 Skill 脚本)
--output-path路径memscopeDumpResults输出目录
--compare / --input-path成对使用-Step 间内存对比
--log-leveldebug,info,warning,errorinfo日志级别

完整参数说明(含废弃参数对照)见 references/msmemscope_usage.md(§1 命令行参数全表)。

A4 场景适配表

不同场景支持的采集/分析能力不同,必须按用户实际场景核对;下表为重点约束,完整矩阵与一键分析框架/版本/组件功能表见 references/msmemscope_usage.md(§4 场景与采集配置矩阵)。

场景支持的采集/分析能力关键注意
训练(Ascend for PyTorch 原生)全量:泄漏/拆解/OOM/快照/对比拆解细分类需调用过 optimizer.step();aten 细分类需 PyTorch ≥ 2.3.1 且 --level=op
训练(pytorch fsdp1/fsdp2)拆解(对应版本区间)拆解内容:激活值、分片权重、all-gather 缓冲、梯度等
推理(vLLM-Ascend 11.0)拆解(decompose)、快照(snapshot)仅 Python 接口(一键分析);命令行采集、泄漏分析不支持
强化学习(verl)/ 训练(mindspeed_llm)快照(snapshot)一键分析开启;verl 拆解暂不支持

完整矩阵与一键分析框架/版本/组件表见 references/msmemscope_usage.md(§4 场景与采集配置矩阵)。

一键分析(推理/RL 场景专用)

vLLM/verl/mindspeed_llm 场景需通过一键分析接口开启快照或拆解:

import msmemscope
msmemscope.config(events="alloc,free", data_format="csv", output="/home/user/output")  # csv 默认;仅需可视化时改 db
msmemscope.cleanup_framework_hooks()                                       # 清空历史注册
msmemscope.init_framework_hooks("vllm_ascend", "11.0", "worker", "snapshot")  # 框架/版本/组件/功能
msmemscope.start()
# ... 训练或推理逻辑 ...
msmemscope.stop()

A5 硬性约束(MUST DO)

  1. 环境变量用后必清:使用 --load-api-env 注入环境变量后,结束采集必须执行 source msmemscope --unload-api-env。
  2. 分析功能必须含 alloc/free:使用 --analysis 时,--events 必须包含 alloc 和 free,否则泄漏分析结果不准确、时间线展示不完整。
  3. --steps 与分析功能互斥:使用内存分析功能时不要设置 --steps。
  4. VLLM-Ascend 限制:不支持命令行采集、不支持泄漏分析;请使用 Python 接口 + 一键分析。
  5. deferred 模式限制:--collect-mode=deferred 时内存分析功能不可用;内存块监测、拆解只对采集范围内数据可用。
  6. 离线泄漏分析需 mstx mark:离线 check_leaks 必须先用 mark 打点标记 A/B/C 三个点。
  7. 对比功能必须成对:--compare 和 --input-path 必须一起使用,单个使用无效;对比前需设置 TASK_QUEUE_ENABLE=0。
  8. 根因优先采集调用栈:需要做泄漏/OOM 归因分析时,务必配置 --call-stack,否则后续无法定位代码位置。
  9. 不替用户改脚本:Python 接口采集需用户脚本配合(加入 start/stop),如用户脚本未集成,告知用户自行集成后重采,不要替用户修改训练代码。
  10. 默认用 csv 格式采集:默认全部使用 csv(--format 缺省即 csv;Python 接口 data_format="csv")。仅当用户明确需要 MindStudio Insight 可视化时才改用 db;禁止"先采 db 再转 csv 分析"的绕路做法——csv 采集更快、体积小,可直接用本 Skill 脚本分析;db 采集慢且无法直接分析,转 csv 是纯浪费。生成采集方案时:无可视化诉求 → csv(不出现 --format=db);有可视化诉求 → 采集 db,分析侧另转 csv(或让用户同时产出 csv)。

A6 产物确认

采集完成后,确认产物结构与预期一致(默认输出目录 memscopeDumpResults):

memscopeDumpResults/
├── memscope_{PID}_{timestamp}_ascend/          # Python 接口采集的输出目录
│   ├── config.json                             # 采集配置信息
│   └── device_{device_id}/dump/
│       ├── memscope_dump_{timestamp}.csv       # 内存事件数据(--format=csv)
│       ├── memscope_dump_{timestamp}.db        # 内存事件数据(--format=db)
│       └── python_trace_{TID}_{timestamp}.csv  # Python Trace(可选)
└── compare/
    └── memory_compare_{timestamp}.csv          # Step 间对比结果(仅对比场景)

确认要点:

  • 文件存在且非空:memscope_dump_*.csv/db 已生成。
  • 含预期事件类型:OOM 场景检查是否存在 Event=OOM_DETAIL 的记录;泄漏场景检查是否有泄漏回显。
  • OOM 快照:OOM 通常发生在采集区间内,OOM 前后快照会落盘(Event=SNAPSHOT,查看 Attr 与 Call Stack 字段)。
  • 采集数据确认无误后,继续本 Skill Part B 进行解读与诊断(解读前的数据完整性校验、按时间戳排序及 csv/db 格式转换在 Part B 开头一次性完成,采集侧无需处理)。

A7 常见问题与兜底

现象原因 / 处理
source msmemscope --load-api-env 后其他工具异常LD_PRELOAD/LD_LIBRARY_PATH 被注入,使用完毕后必须 source msmemscope --unload-api-env 清理;详情见 references/msmemscope_usage.md(§5 环境变量管理)
运行报错但无具体日志加 --log-level=debug 重跑定位
OOM 场景下 dump 中无 OOM_DETAIL 记录确认 --analysis=oom 已配置;OOM 需发生在采集区间内(immediate 模式为整个运行期)
泄漏分析结果不准确/时间线不完整检查 --events 是否同时含 alloc 和 free
使用 --level=kernel 且用 HuggingFace tokenizers 时出现"fork 并行被禁用"告警属已知告警,可忽略;或设置 export TOKENIZERS_PARALLELISM=false
workspace 内存未采集到配置 TASK_QUEUE_ENABLE=2 可采集 task_queue 算子下发队列 Level 2 优化的 workspace 内存
mstx 打点采集不到数据确认单卡局部场景;可配置 PYTHONMALLOC=malloc(对小内存申请有一定影响)
采集产物目录与预期不符检查 --output-path(默认 memscopeDumpResults);Python 接口以 config 中 output 为准

Part B 数据解读与问题诊断

本部分适用于已有采集数据的场景。若用户尚无数据,先按 Part A 完成采集。

B1 数据产物确认

解读前先确认数据,不要在没有数据或数据不完整时强行分析。

  1. 定位 dump 文件:用户提供路径,或查找默认输出目录:

    memscopeDumpResults/                                     # 命令行采集
    memscopeDumpResults/memscope_{PID}_{ts}_ascend/device_{id}/dump/   # Python 接口采集
    

    涉及的文件:memscope_dump_{ts}.csv(事件数据)、memscope_dump_{ts}.db(db 格式)、memory_compare_{ts}.csv(对比数据)、config.json(采集配置)。

  2. 核对采集配置(config.json 或询问用户):确认数据是否满足解读前提:

    解读目标前提配置不满足时
    显存大头 / 占比拆解analysis=decompose(Attr 含 owner 字段)无法按模块拆解,只能按事件类型/内存池维度看
    泄漏归因(代码位置)call_stack 已配置只能定位到分配行为,无法给出代码位置
    曲线趋势events 含 alloc/free曲线不完整
  3. 数据预处理(一次性):每个数据文件在解读前执行一次格式适配与完整性校验(幂等——已处理过的文件会提示已就绪,不会重复处理):

    a) 格式适配(按需):本 Skill 分析脚本基于 csv(本 Skill 指导采集的产物按 A5 第 10 条应为 csv,无需转换;仅当用户已提供 db 格式时才做 db→csv;需将 csv 导入 MindStudio Insight 可视化时才转 db)。命令见「scripts 使用」格式转换段,双向均流式处理、百万行级可用。⚠️ 转换输出默认在输入文件同目录(如 device_0/dump/),且多卡各 device 的同名 db 可安全逐卡转换;若在 dump 外执行并显式 --output 到同一路径,多卡之间会互相覆盖——转换后核对每个 device_{id}/dump/ 下 CSV 均存在。

    b) 完整性校验与排序:

    # ① 完整性校验:表头、行数、列数一致性、最后一行是否完整、时间戳是否已有序
    python3 scripts/aggregate_dump.py <dump.csv> --check
    
    # ② 按时间戳升序排序并覆写原文件(校验提示"未排序"时执行;已有序时自动跳过)
    python3 scripts/aggregate_dump.py <dump.csv> --sort --overwrite
    

    校验不通过(如最后一行不完整、列数不一致)时,先重采或修复数据,不要带病解读;校验通过且有序后,再进入后续分析步骤。

  4. 优先用脚本做数值计算:涉及聚合、占比、峰值的计算,使用 scripts/aggregate_dump.py 执行(见「scripts 使用」),不要手工估算。

  5. 数据规模评估:先判断事件行数落在哪个档位,再选择可行的分析动作(新旧脚本均流式/增量处理,但部分动作在大数据量下不可行或在输出侧受限):

    规模(事件行数)曲线 / 聚合 / 时刻快照--check--sortcsv↔db 转换直接查看 dump / GUI 导入
    < 10 万行✅✅(流式)✅ 全量排序,内存可接受✅(流式)✅ 正常
    10 万 ~ 100 万行✅(输出侧用 --limit / --bins 控制)✅✅ 全量排序(内存 O(行数),百 MB 级)✅(百万行实测 ~30s / 峰值 ~8MB)⚠️ 导入耗时明显;不要 Read 大文件
    > 100 万行✅(先 --ascii --bins N 看宏观,--limit 采样)✅⚠️ 内存大;mmemosope 产物通常已有序,--check 通过即跳过✅ 可用但耗时长❌ 不可行

    大数据量降维策略(先宏观后微观):

    • 曲线看宏观:--curve --ascii --bins N(分桶绘制)或 --limit N(采样数据点)——--bins 把数据点聚合成 N 个统计桶(每桶含首/末/最小/最大),是天然的数据拟合;再按需对时间窗放大。
    • 峰值/异常段定位后切片:--peak [--key used|device_used|process_used] 自动定位峰值时间戳(直接衔接下一步)→ --at-timestamp <ts>(流式维护活跃块集合,内存 O(活跃块);默认拆驱动层全集(HAL 事件):一级归口表 + 层级分配树,--pool <池> 下钻池内)、--group-by owner --metric peak/total --pool <池>(O(1) 内存,单维度拆解)。
    • 需要 db 时用 convert_dump.py(流式,内存 O(活跃块),不整文件载入)。
    • ⚠️ 禁止动作:直接 Read 打开大 dump 文件、全量 grep 后人工浏览、大数据量导入 MindStudio Insight——一律改为"脚本提取 + TOP/时段归纳"后再解读。

B2 系统性解读三件套

① 整体曲线趋势

目的:判断显存使用整体形态,识别异常增长。

方法:

  1. 用脚本提取显存曲线数据点:

    python3 scripts/aggregate_dump.py <dump.csv> --curve
    

    曲线由事件 Attr 中四个统计键驱动(used 进程内用量 / device_used 整卡用量 / process_used 本进程用量 / total 池预留水位),事件驱动:仅事件时刻有点,两事件之间为阶梯保持。各键口径构成(device_used 与 npu-smi HBM-Usage 同源、used 与 process_used 差值为 HCCP 占用、total 变大 = 池扩容)与 npu-smi 对照方法见 references/msmemscope_data.md §3(统计键口径)/§4(曲线解读)。

  2. 曲线形态识别(对照 references/msmemscope_data.md §4 决策树):

    形态可能含义后续动作
    持续攀升、无回落显存泄漏 / 缓存累积进入「泄漏诊断」
    阶梯上升内存池按需预留(total 同步增长)观察是否超限;评估池预留策略
    平台期稳定正常运行无需处理
    峰值后回落瞬时峰值(如大 batch 中间量)进入「峰值占比」分析

    阶梯上升/平台期的一次性固定大段还需考虑通信内存:HCCL 每通信域默认申请 ~401MB CCL Buffer(in 200MB + out 200MB + winExp 1MB),通信域创建时一次性出现、不随数据量变化;AIV 模式另 +40MB、MC2 场景另 +16MB。当用户需要对 HCCL 通信内存展开分析时,各类通信算子 scratch 大小计算、CCL/AIV/MC2 Buffer 行为与 msmemscope 观测对接详见 references/hccl_memory_detail.md。

  3. 与 npu-smi 对照:若用户环境可用 npu-smi info,将 device_used 曲线与其对照,确认工具数据与整卡实际一致;不一致时说明工具可见范围(host 侧申请)与整卡(含片上/其他进程)的差异。

报告要点:曲线形态结论 + 关键转折点(时间戳、对应事件) + 趋势判断(是否异常)。

② 显存使用大头(模块/组件维度)

目的:回答"显存花在哪了"。

方法:

  1. 确认数据开启过 decompose(Attr 含 owner),否则降级分析(见「B1 数据产物确认」第 2 步)。

  2. 用级联模型拆解(单维度操作):显存拆解是级联的——HAL 事件是驱动层全集(其大小 ≈ 进程驱动显存 process_used,包含 PTA/ATB/MindSpore 框架池向驱动申请的大段,owner=CANN@APP),池事件是同一物理内存的池内子视图,两类数值嵌套、不可相加。正确路径:默认从驱动层全集(HAL)拆出组件(HCCL/APP/GE/RUNTIME…)→ CANN@APP 即框架池段 → 再 --pool PTA 下钻池内用途(weight/optimizer/fsdp2…)。HOST(锁页/主机侧)暂不分析。按场景选池后按 owner 聚合:

    # 驱动层全集拆解(默认;含框架池段,owner=CANN@APP)
    python3 scripts/aggregate_dump.py <dump.csv> --group-by owner --metric peak --pool HAL
    # HAL 之下第二层:框架池内用途拆解
    python3 scripts/aggregate_dump.py <dump.csv> --group-by owner --metric peak --pool PTA
    
  3. 解读 owner 多级分类(@ 分隔,如 PTA@fsdp2@all_gather_output@ops):首段是分配器来源(FRAMEWORK 级)——PTA 池为 PTA,HAL 池为 CANN@<组件>(CANN@HCCL/CANN@APP/CANN@GE/CANN@RUNTIME);丢弃首段后才是该维度的下一级(PTA 池 → weight/optimizer/fsdp2…,HAL 池 → HCCL/APP/GE…)。各段是独立级别槽位(框架@组件@流程@细化),空段跳过,同一维度内深度天然不一致,细分标签见 references/msmemscope_data.md §6.2。

  4. 优先从框架内存池入手:框架内存池是显存分析的重点对象(pytorch 用户优先 PTA),先判断框架池是否异常再联动其他池;内存池语义(HAL 为各框架池总量的父集、池扩容失败触发 OOM)见 references/msmemscope_data.md §5(内存池模型)。

  5. 通信场景(HCCL 集合通信多的训练/推理任务):HAL owner 中出现的一次性固定大段多为 CCL Buffer(默认每通信域 ~401MB,AIV/MC2 场景另加)或算子 scratch——用 --hal-segments 直接列出 HAL 池大段清单(含 alloc_type/page_type,alloc_type=create 即 expandable 生效),按通信类型与运行模式核对应然大小(详见 references/hccl_memory_detail.md)。

  6. 输出大头排名(Top-N,含占比),说明每项的来源与合理性。

需要深入组件/框架行为时按需读取:PTA 池行为 → references/pta_memory_management.md;vLLM-Ascend 显存管理 → references/vllm_ascend_memory_management.md(MindSpore/ATB 独立文件后续补充)。

③ 显存峰值点占比

目的:回答"峰值时刻各模块/流程占比多少"。

方法:

  1. 定位峰值时间点:--peak [--key used|device_used|process_used] [--pool <池>] 自动定位(输出峰值时间戳,可直接衔接 --at-timestamp);或使用 SNAPSHOT 记录的 peak_allocated/peak_reserved 字段。

  2. 默认从驱动层全集拆解(HAL 事件,含框架池段 owner=CANN@APP);按场景下钻——--pool PTA(框架池内用途,weight/optimizer_state/fsdp2…)。命令筛选生命周期包含该时间点的内存块,输出池内一级归口表(丢弃框架段,含各子级)+ 层级分配树(按 组件→流程→细化 下钻,每节点含占用/占比/块数):

    # 驱动层全集拆解(默认;含框架池段;≈ process_used)
    python3 scripts/aggregate_dump.py <dump.csv> --at-timestamp <ns>
    # 显式 HAL / 第二层池内
    python3 scripts/aggregate_dump.py <dump.csv> --at-timestamp <ns> --pool HAL
    python3 scripts/aggregate_dump.py <dump.csv> --at-timestamp <ns> --pool PTA
    

    ⚠️ 级联口径:HAL 是驱动层全集,框架池的物理段已计入 HAL 事件(CANN@APP),池事件是同一物理内存的池内子视图——HAL 与池两类数值嵌套、不可相加,不存在"池并列汇总";HOST 暂不分析。

  3. 峰值成因:结合峰值时间戳前的 OP_LAUNCH/KERNEL_LAUNCH 事件、Call Stack 与 python_trace(若采集)识别关键算子/代码段;结合 SNAPSHOT 字段(allocated/reserved/device_utilization/pt_utilization)补充整卡水位(判定方法与成因分析详见 references/msmemscope_data.md §7)。

B3 典型问题诊断

④ 显存泄漏诊断

入口一:在线泄漏分析(采集时已运行 --analysis=leaks):采集结束工具回显逐卡泄漏汇总(泄漏 Step 数、关联 kernel、地址、泄漏大小)+ 内存波动(单 Step 最小/最大占用比)。第一 Step 波动可忽略(内存尚未稳定),从第二 Step 起分析。

入口二:离线泄漏分析(mstx mark A/B/C + check_leaks):A→B 范围申请、C 点前未释放即判定泄漏;用户未执行时指导执行 msmemscope.check_leaks(input_path=..., mstx_info=..., start_index=0)。

核心原则(幽灵机制):进程退出时未释放的块会被工具补发 shadow FREE,因此 dump 中 MALLOC/FREE 必然配对——"有配对"不是无泄漏的证据;泄漏判定的正确口径是"该 Ptr 的 FREE 是否全部为 shadow:true"(机制与操作见 references/leak_diagnosis_guide.md §1~§2)。

检测方法速览(算法细节、风险分级、shadow 来源判别、常驻内存区分见 references/leak_diagnosis_guide.md §3~§4): 0)脚本先筛候选块(算法 C 的块级筛选自动化)——优先分析长生命周期内存与随进程退出补齐释放(shadow FREE,无真实释放动作) 的块:

python3 scripts/aggregate_dump.py <dump.csv> --leak-candidates [--detail N] [--pool PTA]

输出:候选块汇总(块数/大小/占全部申请量比/含 shadow FREE vs 无任何 FREE 分类)、按 owner 与维度内一级归口(丢弃框架段)聚合、申请时间跨度(早-常驻 vs 晚-新增)、调用栈首帧 TOP、候选块明细(--detail 控制条数,0=不输出)。--pool <池> 按单维度扫描(默认 HAL 驱动层全集;池事件是嵌套子视图,两类不可相加);筛出的候选块再逐一判别 shadow 来源(换栈/退出补齐/真泄漏)与常驻内存;随后按序走算法 A(used 跨周期不回基线,强信号) → B(预留增长,弱信号,须与 A 联动) → C(长生命周期块 shadow 判别) → D(堆栈归因 TOP3)。

原因分析:对照 references/leak_diagnosis_guide.md §5 常见泄漏模式(缓存未清理、梯度/优化器状态累积、KV cache 增长、循环内重复申请、Python 引用残留等),给出"现象特征 → 证据 → 假设 → 验证路径"。

⑤ OOM 诊断

OOM 数据在 dump 的 Event=OOM_DETAIL 中,三类记录(Attr 中 Event Type 区分):

Event Type内容解读要点
OOM_TRIGGER触发操作:func、req_size、flag、ret谁在申请、申请多大触发 OOM
OOM_RECENT_ALLOC最近 K 条未释放记录(pool/ptr/size/timestamp/step/kernel + Call Stack)识别"压死骆驼的最后一根稻草"
OOM_TOP_ALLOC最大 K 条未释放记录OOM 时的大头占用者

诊断步骤:脚本一键汇总 --oom [--detail N](OOM_TRIGGER/TOP_ALLOC/RECENT_ALLOC 三表 + 量化推断提示自动判定)→ ① 看 OOM_TRIGGER(req_size 巨大 = 单次巨量申请;不大 = 总量已耗尽)→ ② 看 OOM_TOP_ALLOC 大头归属(权重/kv_cache/激活/中间量)→ ③ 看 OOM_RECENT_ALLOC 分配序列 → ④ 结合 Call Stack 与 owner 归因到代码位置 → ⑤ 区分框架池扩容失败 OOM(func 指向池扩容路径时,根因是池内占用过高、可回收不足,而非单次大申请)。

字段明细、量化推断规则(req_size ≥80% 剩余空间、同栈重复 ≥3 次、RECENT 累积型判定等)与典型场景示例见 references/oom_diagnosis_guide.md。

⑥ 显存碎片分析

目的:回答"池预留(total)高但实际使用(used)低,是否碎片导致、能否通过配置回收"。

方法概要:

  1. 算碎片率:--fragmentation [--pool <池>] 一键输出池扩容清单(时间戳/前后 total/增量/扩容前 used/total/伴随 HAL 段)+ 碎片率统计(当前/峰值/均值/最差时刻)+ 有效使用率最低 TOP5;或 SNAPSHOT 1 − pt_utilization;峰值时刻与稳定期各算一次;分级 <5% 正常 / 5~15% 偏高 / >15% 严重。
  2. 量化池预留行为:扩容频率按运行时长/Step 数归一化;HAL 段"申请后从未归还"是池缓存正常行为(释放≠归还);扩容前 used/total 为池有效使用率。
  3. 观测盲区:msmemscope 无段级/块级存量视图,逐段碎片率、块状态分布、假性碎片判定需引用 ascend-npu-snapshot-analyzer skill 补采 snapshot;⚠️ 多流场景碎片率高有三种候选解释(真碎片/流池残留/跨流延迟假性碎片),无法区分。

建议速查(配置杠杆详见 references/pta_memory_management.md §4.1 与 §7.3):

  • 碎片严重且频繁扩容 → expandable_segments(与 max_split_size_mb、garbage_collection_threshold 互斥)
  • 碎片集中大块段 → max_split_size_mb;池缓存长期占位、可接受间歇回收 → garbage_collection_threshold 或定期 empty_cache()
  • 多流场景 → 检查流复用设计(每流池 total 只增不减,见 pta_memory_management.md §3.2)

口径明细与观测边界见 references/msmemscope_data.md §9(碎片分析口径)。

  1. 建议(配置杠杆详见 references/pta_memory_management.md §4):
    • 碎片严重且频繁扩容 → expandable_segments(注意与 max_split_size_mb、garbage_collection_threshold 互斥)
    • 碎片集中于大块段 → max_split_size_mb
    • 池缓存长期占位、可接受间歇回收 → garbage_collection_threshold 或定期 empty_cache()
    • 多流场景 → 检查流复用设计(每流池 total 只增不减,见 §3.2 流池残留)

B4 输出报告结构

最终回复按以下结构组织(数据缺失时在对应位置显式说明):

  1. 分析概要:数据来源路径、采集配置(事件/分析功能/调用栈是否开启)、分析范围。
  2. 证据:表格形式呈现关键数据——曲线形态与关键转折点、大头 Top-N 与占比、峰值时刻占比、泄漏/OOM 关键记录(引用具体数值)。
  3. 结论:是否存在问题、问题类型(泄漏/OOM/显存增长/正常)、严重程度。
  4. 建议:针对性优化建议与验证路径(复采验证、修改方向)。
  5. 交付件路径:dump 数据与分析产物路径,方便用户查看。

B5 常见解读误区

误区正确做法
把第一 Step 的内存波动当作泄漏证据第一 Step 内存尚未稳定,从第二 Step 起分析(在线泄漏分析本身即如此)
认为 device_used 等于本进程使用量device_used 是整卡用量(含片上/其他进程);本进程用量看 used/process_used
device_used 为 -1(或键省略)时仍引用该值说明环境不支持整卡用量查询,改用 used/process_used 分析
没开 decompose 却按 owner 拆解无 owner 字段时只能按事件类型/内存池维度分析,明确告知用户信息缺失
用曲线点当轮询采样曲线是事件驱动的(仅 HAL/池事件时刻有点),两事件之间是线性填充/阶梯,不代表中间态采样
把历史显存块计入泄漏start 前的存量显存只参与统计(总量准确),不参与泄漏/拆解分析
证据不足强行下结论列出缺失信息(缺调用栈、缺拆解、缺对比数据),按 Part A 补采对应配置的数据
把"MALLOC/FREE 一一配对"当作无泄漏证据幽灵机制保证必然配对(未释放块在进程退出时被工具补发 shadow FREE)——配对不是无泄漏证据;泄漏判别看该 Ptr 的 FREE 是否全部为 shadow:true、及跨周期增长性
把幽灵释放(attr shadow:true)一概当作未释放内存shadow 有两种来源:非采集期正常释放(真实释放行为)与进程退出时统一释放(未释放内存);前者挂在中间 stop 点之后、后者挂在最后一次 stop/退出时刻,按采集状态与时间戳判别
把常驻内存误判为泄漏常驻内存一般在程序前期申请、总量稳定;泄漏常见周期性增长,按增长性判别(见泄漏诊断)
数值计算手算聚合、占比、峰值计算用 scripts/aggregate_dump.py,保证准确可复现

scripts 使用

scripts/aggregate_dump.py 对 memscope_dump_*.csv 做数据预处理、确定性聚合统计与本地可视化(仅依赖 Python 标准库);scripts/convert_dump.py 做 csv ↔ db 格式转换(与官方 db 格式一致,字段口径详见 references/msmemscope_data.md):

运行前提:仅依赖 Python 3 标准库(3.7+,输出编码自适应)。**Linux 使用 python3,Windows 使用 py -3(或 python)**执行;脚本无平台相关调用,两者输出一致。输出统一为 UTF-8(Windows 控制台为 GBK 时自动替换,不报错)。

# ---- 格式转换(csv ↔ db)----
# 两个方向均流式处理(内存 O(活跃块数),不整文件载入),百万行级可用
# db → csv(供分析脚本使用;默认输出到**输入文件同目录**(如 device_0/dump/),文件名 memscope_dump_{时间戳}.csv;⚠️ 多卡各 device 的同名 db 默认互不覆盖,但显式 --output 到同一路径仍会覆盖,多卡批量转换建议逐卡转换或按卡指定 --output)
python3 scripts/convert_dump.py <dump.db> --to-csv
# csv → db(导入 MindStudio Insight 可视化;默认输出 memscope_dump_{时间戳}.db;建议输入先 --sort 保证时间序)
python3 scripts/convert_dump.py <dump.csv> --to-db
# 旧版工具链表名为 leaks_dump 时用 --table 指定
python3 scripts/convert_dump.py <dump.csv> --to-db --table leaks_dump

# ---- 数据预处理(每个文件一次,幂等)----
# 完整性校验(表头/列数/行关键字段/是否已有序;流式,O(1) 内存)
python3 scripts/aggregate_dump.py <dump.csv> --check
# 按时间戳排序(--overwrite 覆写原文件;已有序时自动跳过;排序需全量载入,大数据量且有序时跳过此步)
python3 scripts/aggregate_dump.py <dump.csv> --sort --overwrite

# ---- 聚合统计与可视化 ----
# 级联单维度拆解:HAL=驱动层全集(含框架池段 CANN@APP,≈process_used);PTA 为第二层池内视图(与 HAL 嵌套不可相加)
python3 scripts/aggregate_dump.py <dump.csv> --group-by owner --metric peak --pool HAL
python3 scripts/aggregate_dump.py <dump.csv> --group-by owner --metric peak --pool PTA
# 未开 decompose 的降级分析:按事件类型(HAL/PTA/...)聚合(仅作层次参考,不并列相加)
python3 scripts/aggregate_dump.py <dump.csv> --group-by event_type --metric peak

# 统计指定时间点(如峰值时刻)活跃块分布:默认拆 HAL 驱动层全集(一级归口表 + 层级分配树,占比默认输出);--pool 下钻池内
python3 scripts/aggregate_dump.py <dump.csv> --at-timestamp <ns>
python3 scripts/aggregate_dump.py <dump.csv> --at-timestamp <ns> --pool PTA

# 扫描泄漏候选块(FREE 全部为 shadow:true 或无任何 FREE 事件的块;默认 HAL 驱动层全集,--pool 指定维度;按 owner/维度内一级归口/申请时间跨度/调用栈聚合,--detail N 控制候选明细条数,0=不输出)
python3 scripts/aggregate_dump.py <dump.csv> --leak-candidates [--detail N] [--pool PTA]

# 输出整卡/进程显存曲线数据点(ts, device_used, used)
python3 scripts/aggregate_dump.py <dump.csv> --curve

# 输出文本化曲线(ASCII,无外部依赖)
python3 scripts/aggregate_dump.py <dump.csv> --curve --ascii

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
2k
Forks
112
Last commit
Sep 2026
Advanced
Item type
skill
Key
memory-analysis
Source
github.com/a5c-ai/babysitter