mcpField
A
ascend-profiling-anomaly

ascend-profiling-anomaly

github.com/ascend开发52152 次安装25 周前更新
代码仓库

关于 ascend-profiling-anomaly

用于分析 Ascend NPU 性能分析数据的技能,面向性能工程师。它通过设备空闲间隙检测、结构分解和模型架构分析,分别呈现异常证据与可能归因,并生成独立的架构报告。

主要功能

  1. 01分解步骤、结构、区块与算子
  2. 02合并设备区间并检测空闲间隙
  3. 03结合主机事件标注潜在归因
  4. 04汇总异常标签与周期性指标
  5. 05生成独立的架构分析报告

适用场景

  1. 01定位训练或推理步骤中的设备空闲时间
  2. 02检查层边界及结构内部的间隙
  3. 03依据主机事件评估同步或通信风险

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ascend/agent-skills --skill ascend-profiling-anomaly

安装后在 Claude Code 中输入/ascend-profiling-anomaly确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
architecture_report_template.md
kernel_data_guide.md
rulebook.md
schema.json
scripts/
reference_host_gap_branch.py

详细介绍

Ascend Profiling 异常发现技能

用途

通过三个并行流水线分析 Ascend NPU 的 Profiling 数据:

  1. 结构分解:step → structure(层)→ block / side → op → PMU 判定 — 回答时间花在哪里。
  2. 异常发现:step → 设备忙碌区间并集 → 空泡检测 → 异常标签 → 软归因 — 回答哪些情况看起来不自然,隐藏问题可能在哪里。
  3. 模型架构分析:FIA 时间线 → pass 边界 → 层分类 → 每层子结构 → 通信流水线 → 架构摘要 — 回答这是什么模型,以及各组件如何执行。生成单独的 Markdown 报告文件。

核心理念是关注点分离:“存在异常”是基于设备时间区间得出的硬事实;“异常为何存在”是软归因,可能需要额外证据。即使 Profiling 配置较弱(无调用栈、无形状信息、主机事件稀疏),该技能仍必须可靠地发现设备空闲空泡和风险标签。

参考文件 — 何时阅读

开始分析前请先阅读以下文件:

文件阅读时机内容
references/kernel_data_guide.md始终阅读 — 首先阅读kernel_details.csv、op_summary、trace_view.json 的原始数据列模式;step → structure → block/side → op 层级;如何在各层级解析、筛选和分配 kernel;多流处理;各层级的耗时聚合
references/rulebook.md始终阅读异常阈值、标记规则、判定表、软归因规则、AICPU 分类、等待锚点规则
references/architecture_report_template.md始终阅读 — 生成架构报告前阅读独立 Markdown 架构报告的完整模板:必需章节、格式规则、层分类分析技术、通信重叠测量、每层耗时分解
references/schema.json生成结构化 JSON 输出时anomaly_discovery 输出对象的完整 JSON 模式
scripts/reference_host_gap_branch.py编写分析脚本时区间合并、空泡指标、软归因、等待锚点评分的 Python 参考实现

流水线概览

完整状态机:

INGEST → INVENTORY → FACT_EXTRACTION → CANDIDATE_STEP_DETECTION →
STEP_GROUPING → MACRO_STEP_RESOLUTION → SEGMENTATION →
CLOCK_ACCOUNTING → ANOMALY_DISCOVERY → PERF_JUDGEMENT →
RECOMMENDATION → RENDER → DONE
                                        ↘
                          ARCHITECTURE_ANALYSIS → ARCH_REPORT_RENDER → ARCH_REPORT_SAVE

ANOMALY_DISCOVERY 位于 CLOCK_ACCOUNTING 之后、PERF_JUDGEMENT 之前。它接收已分段的 step 和 structure,并在其基础上运行空泡检测流水线。

ARCHITECTURE_ANALYSIS 与 PERF_JUDGEMENT 并行运行,使用来自 CLOCK_ACCOUNTING 的相同分段数据以及 FIA 时间线分析。它会生成单独的 Markdown 报告文件,并将其保存在 Profiling 数据旁。


数据层级:Step → Structure → Block/Side → Op

理解原始 kernel 数据如何映射到各个层级至关重要。完整列模式和解析细节请阅读 references/kernel_data_guide.md。以下是概念概览:

第 0 层:原始 Kernel

kernel_details.csv 中的每一行表示一次设备 kernel 执行 — 一次 AI Core 任务、AI CPU 任务或 HCCL 通信任务调用。关键字段:Name、Task Type、Start Time(us)、Duration(us)、Wait Time(us)、Accelerator Core、Stream ID、Input Shapes、Output Shapes。

第 1 层:Step

一个 step 表示一次训练/推理迭代。Step 由 trace_view.json 中的 ProfilerStep#N 用户标注或 Iteration#N 标记识别。每个 step 定义一个服务窗口 [S_i, S_{i+1})。所有开始时间落在此窗口内的 kernel 都属于 step i。

在 step 层级,计算:

  • 总服务时间、设备忙碌区间并集、供给不足比例
  • 启动前间隙、尾部间隙、内部空泡
  • 每个 step 的异常标签和软根因标签
Level 2:结构(层)

在一个步骤内,内核会形成重复的结构,通常对应模型层(例如 Transformer 块、注意力层、MLP 块)。分段通过以下方式识别这些结构:

  1. 内核时间线中重复的名称模式序列
  2. 内核组之间显著的时间间隔
  3. 标记层边界的用户注释(如果存在)

每个结构都包含步骤窗口内一段连续的内核。

在结构级别,计算:

  • 结构墙钟时间,即结构跨度内设备忙碌时间的并集
  • 结构时间占步骤总时间的比例
  • 每个结构的气泡指标(气泡是在此结构内,还是位于结构之间?)
Level 3:块 / 辅助操作

在每个结构内,内核分为:

  • 块(主要计算路径):构成此层前向或反向传播过程的主导 AI Core 内核链。这些内核在主计算流上执行。
  • 辅助操作(辅助运算):其他所有内容,包括小型逐元素运算、通信(HCCL)、AI CPU 回退运算、内存复制和同步事件。这些操作可能在单独的流上执行。

在块 / 辅助操作级别,同时维护四种计时视角:

  • wall_ms — 从第一个内核开始到最后一个内核结束的墙钟时间
  • busy_union_ms — 合并后的设备忙碌时间(计入多流重叠)
  • kernel_sum_ms — 所有内核持续时间的算术总和(忽略重叠)
  • total_cost_ms — 所有内核的 duration + wait 总和

仅依据一个指标得出的结论并不完整。块的 kernel_sum 较高而 wall 较低,意味着流并行度较高。辅助操作的 total_cost 较高而 duration 较低,则意味着存在 wait-anchor 虚假热点风险。

Level 4:算子(单个算子)

最细粒度。每个算子可能产生一个或多个设备内核。算子级分析包括:

  • 按总成本排名的顶级算子与按内核持续时间排名的顶级算子(这两种排名往往不同)
  • Wait-anchor 检测:wait_ratio > 0.95 且 duration 极短、但 total_cost 较高的算子
  • AICPU 分类:根据 masked_ratio 对运行在 AI CPU 而非 AI Core 上的算子进行分类
  • 小算子的初步判断:判断单个小算子究竟是真正的低效之处,还是噪声

异常发现流程(详细说明)

Phase 1:BUILD_DEVICE_INTERVALS

对于每个步骤,收集 kernel_details.csv 中所有设备内核区间:

device_intervals = []
for each kernel row where Start_Time_us is within step window:
    s = max(step_start_us, row.Start_Time_us)
    e = min(step_end_us, row.Start_Time_us + row.Duration_us)
    if e > s:
        device_intervals.append(Interval(s, e))

关键规则:

  • 将内核区间裁剪到步骤窗口边界内
  • 在进行区间统计之前应用通信去重规则(参见 references/kernel_data_guide.md 中关于通信去重的章节)
  • 纳入 AI_CORE、AI_CPU 和 HCCL 任务——这些都计为“设备忙碌”
  • 存在多个流时,将所有流的区间收集到同一集合中
Phase 2:MERGE_INTERVALS

按开始时间对区间排序,并合并重叠区间:

merged = merge(device_intervals)  # see scripts/reference_host_gap_branch.py
busy_union = sum of merged segment durations

由此得到合并后的忙碌时间段,所有气泡指标均据此计算。

Phase 3:GAP_CLASSIFICATION

根据合并后的时间段,计算每个步骤的指标:

  • service_ms = 步骤窗口时长
  • device_busy_union_ms = 合并后时间段的持续时间总和
  • underfeed_ms = service − busy_union
  • underfeed_ratio = underfeed / service
  • prelaunch_gap_ms = start(first_merged_segment) − step_start
  • tail_gap_ms = step_end − end(last_merged_segment)
  • internal_bubble_total_ms = 相邻合并时间段之间的间隔总和
  • largest_internal_bubble_ms = 相邻合并时间段之间的最大间隔
  • bubble_count = 时间段之间的间隔数量
Phase 4:HOST_EVIDENCE_COLLECTION

对于每个气泡窗口(合并片段之间的间隙,或启动前/末尾间隙),在 trace_view.json 中扫描相同时间范围内的主机事件:

要收集的主机事件类别:

  • cpu_op / python_function / user_annotation — 一般主机活动
  • AscendCL@* — ACL 运行时事件
  • HostToDevice / torch_to_npu / aclrtMemcpy* / aclrtSynchronize* — 同步/拷贝标记
  • c10d / Hccl / hcom / StreamWaitEvent / Notify_Wait — 通信标记

计算重叠比:

  • host_visible_coverage_ratio = 任意主机事件覆盖的气泡比例
  • sync_marker_overlap_ratio = 同步/拷贝标记覆盖的比例
  • comm_marker_overlap_ratio = 通信标记覆盖的比例
Phase 5:SOFT_ATTRIBUTION

根据重叠比,为每个显著气泡分配概率级别的标签:

条件标签
sync_overlap ≥ 0.20possible_sync_or_h2d
comm_overlap ≥ 0.20possible_comm_wait
host_coverage < 0.05possible_untraced_host_blocking
host_coverage ≥ 0.10,但同步/通信并非主要因素possible_host_launch_lag
host_parallelism < 1.2,且以上情况均不适用possible_python_serialization_or_lock
均不适用insufficient_evidence

可以同时存在多个标签。这些标签明确不代表唯一的根因。

Phase 6:ANOMALY_TAGGING

根据 references/rulebook.md 决策表应用异常标签。核心标签:

气泡严重程度:DEVICE_IDLE_GAP_HEAVY、PRELAUNCH_GAP_HEAVY、TAIL_GAP_HEAVY、INTERNAL_BUBBLE_HEAVY

风险标签:HOST_ORIGINATED_RISK、COMM_SYNC_RISK、WAIT_POLLUTION_RISK、WAIT_ANCHOR_FALSE_HOTSPOT、AICPU_EXPOSED_RISK、UNTRACED_HOST_BLOCKING_RISK、PARTIAL_CAPTURE_BOUNDARY、VARIABLE_SHAPE_SAME_TEMPLATE

Phase 7:WAIT_ANCHOR_SCAN

在算子层级扫描虚假热点:

wait_ratio = wait_us / (duration_us + wait_us)
if wait_ratio > 0.95 and duration_us < 10.0 and total_cost_rank <= 10:
    tag WAIT_ANCHOR_FALSE_HOTSPOT

这些算子会吸收空闲等待时间,因此看起来耗时较长,但其内核执行时间可以忽略不计。请在根因排序中降低它们的优先级。

Phase 8:GROUP_AGGREGATION

按 step_group_id 汇总步骤级指标:

  • 为每个气泡指标计算平均值、中位数、P90、P95
  • 如果组内 ≥60% 的步骤满足 bubble_count > 0,则 recurring_bubble_pattern = true
  • dominant_idle_pattern = 占比最高的类型:prelaunch / internal_bubble / tail
Phase 9:PRODUCE_OUTPUT

将异常结果与结构拆分结果合并。报告必须包含:

隐藏问题发现部分
  • 主要步骤/组的气泡指标(service、busy_union、underfeed_ratio)
  • 原始内核证据表:对于每个排名靠前的气泡窗口,列出间隙前后紧邻的内核及其名称、任务类型、耗时和流,以便专家在时间线上定位准确位置
  • 前 5 个气泡窗口的时间戳、范围和主机证据
  • 步骤组中的气泡周期性统计
  • 主机证据覆盖情况评估
  • 带证据链的软根因标签
  • 后续采样建议
气泡优先摘要(固定的 5 个问题模板)
  1. 是否存在显著的设备空闲气泡?
  2. 它们主要集中在哪种步骤类型/组?
  3. 它们主要属于启动前/末尾/内部/步骤间气泡中的哪种?
  4. 是否存在显著的主机来源风险?
  5. 证据是否足以确定根因?如果不足,请明确说明。
结构级气泡深入分析

对于主要步骤,按结构拆分气泡贡献:

  • 哪些结构包含最大的内部气泡?
  • 气泡集中在结构边界(层与层之间),还是结构内部?
  • 对于存在大气泡的结构,其周边内核的名称和任务类型是什么?

模型架构分析流程(单独的 Markdown 报告)

此流程会生成一份独立的 Markdown 报告文件,记录根据性能分析数据逆向还原的模型架构。完整模板、格式规则和分析技术请参阅 references/architecture_report_template.md。

报告将保存为 model_architecture_report_<profiling_dir_name>.md,位于性能分析目录或输出目录中。

何时生成架构报告

始终生成。 每次性能分析都必须在输出异常发现结果的同时生成此报告。架构报告提供了必要的背景信息,有助于理解异常发现结果。

架构分析阶段
阶段 A1:FIA_TIMELINE_ANALYSIS

使用 FusedInferAttentionScore(FIA)调用作为主要结构标记:

  1. 从 kernel_details.csv 中提取所有 FIA 内核(名称中包含 FusedInferAttentionScore)
  2. 按 Start Time(us) 排序
  3. 将每个 FIA 分类为 prefill(持续时间 > 10ms)或 decode(持续时间 < 1ms)
  4. 确定 pass 数量:num_passes = total_FIA / FIA_per_pass
  5. 根据 prefill 和 decode FIA 簇之间的时间戳间隔,识别阶段转换
阶段 A2:PASS_BOUNDARY_DETECTION

对每个前向 pass,确定:

  • FIA 索引范围(例如 #0–#94)
  • 时间跨度(绝对时间戳)
  • 从第一个内核到最后一个内核的墙钟时间
  • 平均 prefill FIA 持续时间
  • 内核总数

应记录跨 pass 的差异(FIA 持续时间、墙钟时间);这些差异可能揭示 KV 缓存增长或内存压力的影响。

阶段 A3:LAYER_CLASSIFICATION

对每一层(由相邻的 FIA 调用界定),提取内核序列并进行分类:

分类内核层类型
没有 MoE 标记(无 MoeGatingTopK、无 DFC、无 GroupedMatmul)Dense
存在 DispatchFFNCombineMoE+DFC
存在 GroupedMatmul 和 alltoallv(无 DFC)MoE+GMM
存在采样操作(ArgMax、rejection_*)包含 decode/采样逻辑

构建汇总表:层类型 | 层范围 | 数量 | 特征

阶段 A4:CROSS_VERIFICATION

统计每个 pass 中的关键操作数,并验证其与层分类相符:

  • FIA 数量应等于层数
  • DispatchFFNCombine 数量应与 MoE+DFC 层数相符
  • GroupedMatmul 数量应与 MoE+GMM 层数加 decode 层数相符
  • MoeGatingTopK 数量应与所有 MoE 层(DFC + GMM + decode)相符

差异表明分类可能有误;请在继续之前解决这些问题。

阶段 A5:PER_LAYER_SUBSTRUCTURE

对每种不同的层类型,分析内核执行序列:

  1. 按功能角色对内核分组(attention、projection、TP 通信、MoE 路由、专家分发、专家 FFN、MoE 后归一化、下一层准备、EP 通信、采样)
  2. 测量每个功能组的墙钟时间
  3. 确定每个组运行所在的流
  4. 计算时间分解:组件 | 墙钟时间 | 占层的比例
  5. 记录该层类型特有的异常(第 0 层的预热开销、转换层中的额外内核、应在 AI_CORE 上运行的 AICPU 操作)

以带时间标注和流标签的内核序列树形式呈现。确切的树形表示格式请参阅模板。

阶段 A6:DECODE_ANALYSIS

Decode 层需要单独分析,因为其成本分布有本质区别:

  • FIA 持续时间大幅下降(prefill 28ms → decode 0.2ms)
  • 通信(尤其是 EP 的 all-to-all)通常占主导
  • 专家计算从融合形式(DFC)转为显式形式(GroupedMatmul)

生成主要成本表,并解释其成本分布为何不同于 prefill。

阶段 A7:COMMUNICATION_PIPELINE

记录多流重叠策略:

  1. 说明每个流的用途(主计算、AI_CPU 通信、HCCL、alltoall)
  2. 测量各流之间的重叠比例
  3. 绘制 ASCII 流水线图,展示通信如何隐藏在计算之后
  4. 计算总通信量中被隐藏(重叠)的比例
  5. 解释 kernel_sum >> wall 的关系
阶段 A8:ARCH_REPORT_RENDER

按照 references/architecture_report_template.md 中的模板,将所有发现整理成 Markdown 报告。必须包含以下 10 个部分:

  1. 配置上下文
  2. 模型架构判定(证据链表)
  3. 前向传播边界(逐次传递表)
  4. 层分类(类型表)
  5. 交叉验证表
  6. 逐层子结构(核函数序列树 + 每种层类型的计时明细)
  7. 解码阶段分析(主要开销 + 预填充与解码对比)
  8. 通信流水线结构(流表 + ASCII 流水线图)
  9. 层间差异(对比表)
  10. 模型架构摘要(ASCII 模型图 + 执行时间线)
阶段 A9:ARCH_REPORT_SAVE

将报告保存为 model_architecture_report_<profiling_dir_name>.md。告知用户文件所在位置。


关键约束

  • **绝不能因根本原因不明确而跳过异常发现。**气泡事实是确定性结论;根因标签是非确定性结论。两者都必须始终报告。
  • 未检查等待锚点风险前,绝不能将高等待、短时长的操作称为真正的热点。
  • 即使整体步骤受设备限制,也绝不能忽略局部气泡。
  • 绝不能只使用一种计时指标——始终在块/侧级别进行双时钟核算(wall_ms + busy_union_ms + kernel_sum_ms + total_cost_ms)。
  • 主机端证据稀少时,始终输出 insufficient_evidence 或 possible_untraced_host_blocking——绝不能默默省略异常部分。
  • 始终提供已报告气泡附近的原始核函数上下文——每个气泡间隙前后的核函数名称、任务类型、时长和流 ID。
  • 使用分层确定性措辞:事实使用陈述句;根因使用 possible / probable / insufficient evidence。
  • 始终将模型架构 Markdown 报告单独生成为一个文件——绝不能只将其合并到异常输出中。
  • **绝不能跳过逐层子结构分析。**每种不同的层类型都必须有自己的核函数序列树、计时明细和流注释。
  • 架构报告中始终包含证据链表——读者必须能看到如何根据原始 FIA 数据确定层数和传递结构。
  • 定稿架构报告前始终进行交叉验证,核对操作数量与层分类是否一致。必须解决差异,或明确注明。

优雅降级

缺失数据影响操作
record_shapes=false无法检测形状变化气泡检测继续;跳过 VARIABLE_SHAPE_SAME_TEMPLATE 标签
with_stack=false软归因的具体程度降低降低置信度;不影响气泡检测
主机事件稀疏无法缩小根因类别范围UNTRACED_HOST_BLOCKING_RISK,requires_host_followup=true
捕获边界截断边缘间隙可能是伪影在边界相邻间隙上标记 PARTIAL_CAPTURE_BOUNDARY
没有 communication.json无法评估通信等待跳过通信重叠分析,并在证据缺口中说明。架构报告省略通信流水线带宽统计,但仍记录流的角色
没有步骤标记无法定义步骤窗口回退到将全局捕获范围作为单个伪步骤
仅有 op_summary(没有 kernel_details)粒度较粗改用算子级区间;在局限性中说明。架构报告使用算子计数进行层分类,但无法生成逐层内核序列树
未检测到 FIA 内核无法通过 FIA 确定层边界架构报告回退到其他结构标记(例如重复的内核模式、通信边界)。说明层数的置信度降低
捕获了单次前向传播无法交叉验证各次传播的一致性架构报告记录单次传播;说明无法分析不同传播之间的变化
未检测到解码 FIA仅捕获推理或预填充架构报告省略解码阶段分析部分;说明捕获范围的局限性

输出约定摘要

每次分析必须生成两项输出:

1. 异常发现输出

顶层对象 anomaly_discovery,包含:enabled、dominant_group_id、global_device_gap_analysis、step_group_anomalies、bubble_windows、wait_anchor_ops、soft_root_cause_summary、requires_host_followup、confidence。

每个步骤结果必须包含气泡指标、异常标签和软根因标签。

完整的 JSON 架构请参阅 references/schema.json。

2. 模型架构报告(Markdown 文件)

生成独立的 Markdown 文件,并保存为 model_architecture_report_<profiling_dir_name>.md,其中包含架构模板要求的全部 10 个章节。完整规范请参阅 references/architecture_report_template.md。

报告至少必须包含:

  • 用于证明层数和传播结构的证据链
  • 包含所有不同层类型的层分类表
  • 每种层类型的逐层内核序列树及计时细分
  • 包含流重叠示意图的通信流水线结构
  • 模型架构 ASCII 摘要图和逐次传播执行时间线

架构报告是理解模型结构的主要交付物。它必须独立完整,读者无需参考异常输出即可了解模型的完整执行过程。

建议

每条建议必须包含 scope(global/step_group/structure/side/op)、followup_required、evidence_gap 和 priority(P0–P3)。

常见后续处理模式:

  • 气泡多且缺少堆栈 → 使用 with_stack=true 重新分析
  • 缺少形状信息且分组不稳定 → 设置 record_shapes=true
  • 主机风险高且证据不足 → 进行主机侧采样 / 查看线程视图
  • 等待污染严重 → 检查通信和同步路径
  • 结构间气泡较大 → 检查主机侧层调度延迟

评论

支持 Markdown