| name | performance-health-score |
| description | 为一次性能 profiling 数据计算 0-100 的性能健康度评分 (PHS, Performance Health Score) 与等级 (S/A/B+/B/C/D),作为报告"结论速览"首行的仪表盘指标。复合公式涵盖计算利用率、通信效率、调度效率、内存带宽利用率四个子项;按工作负载场景(大模型多卡训练 / 单卡训练或推理 / 单算子调优 / 集群慢卡)自动切换权重;子项缺数据时按比例归一化剩余权重。另含一个独立诊断指标"显存容量利用率(HBM 占用率,从 memory_record.csv / npu_module_mem.csv / NPU_MEM 表提取,不计入 PHS)",用于回答显存占用 / OOM 风险类问题。 |
| metadata | {"type":"skill"} |
performance-health-score — 性能健康度评分
本 skill 给 AI 阅读。每份性能 Profiling 报告与算子调优报告的"第 1 章 结论速览"必须先调用本 skill,按下方公式打分,并把分数 + 等级 + 分项写入报告首行(用于后续仪表盘展示)。
触发条件
profiling-workflow/SKILL.md 规则 1 第 1 章"结论速览"已强制每份性能/算子报告必须含 PHS 行。Hermes / Icarus 工作流均适用。
不适用:Accuracy(精度)报告。
公式
PHS = w_compute × 计算利用率
+ w_comm × 通信效率
+ w_sched × 调度效率
+ w_mem × 内存带宽利用率
- 四个子项各自归一化为 0-100
- 权重按"场景权重表"选择
- 任一子项数据缺失(采集不完整、单卡无通信、推理无 step 概念等)时记为
N/A,剩余子项权重按比例放大归一化,避免把"未采集"误判为"不健康"
子项算法
1. 计算利用率
| 场景 | 算法 | 数据来源 |
|---|
| 大模型训练(有可计算的 FLOPs) | MFU = 实际 FLOPs/s ÷ 芯片峰值 FLOPs/s × 100 | 调用 op-mfu-calculator skill |
| 算子调优 / 无 FLOPs 模型 | AI Core 占用率 = AI Core busy time ÷ 总采集时间 × 100 | PipeUtilization.csv、kernel_details.csv |
| 推理服务化 | 同上,必要时按 batch 加权 | kernel_details.csv |
芯片峰值 FLOPs 参考:
| 芯片 | FP16 (TFLOPs) | BF16 (TFLOPs) | FP32 (TFLOPs) |
|---|
| Ascend 910B | 376 | 376 | 75 |
| Ascend 910C | 数据采集时按手册更新 | | |
2. 通信效率
通信效率 = Σ (各链路实测带宽 × 该链路传输总字节数) ÷ Σ (该链路理论带宽 × 该链路传输总字节数) × 100
- 按 transport type 分类:LOCAL / HCCS / PCIE / RDMA
- 理论带宽参考(按手册或
hccn_tool 实测):
- HCCS(节点内):~30 GB/s
- RDMA(节点间):~25 GB/s
- PCIE Gen4 x16:~32 GB/s
- 数据来源:
communication.json、communication_matrix.json、slow_link.csv
- 单卡场景:本项记
N/A,权重按比例归一化到其他三项
3. 调度效率
调度效率 = (1 - (Free time + Wait time + Idle time) ÷ 单步总时间) × 100
- 数据来源:
step_trace_time.csv、analysis.db.StepTraceTime
- 多卡场景:先各 Rank 计算后取均值
- 推理无 step 概念:用
(1 - Host bubble ratio) × 100 代替,数据来自 cann_api_sum 中相邻 launch 间隙
4. 内存带宽利用率
内存带宽利用率 = HBM 实测平均读写带宽 ÷ HBM 峰值带宽 × 100
- HBM 峰值参考:
- Ascend 910B:1.6 TB/s(HBM2e)
- Ascend 910C:按手册
- 数据来源:算子调优场景用
Memory.csv;训练场景用 ascend_pytorch_profiler_*.db 的 memory 表
注意区分两个"内存利用率":本子项是带宽利用率(实测读写带宽 ÷ HBM 峰值带宽,反映访存压力)。它与下面的显存容量利用率(占了多少 GB ÷ 单卡 HBM 总容量)是不同维度,别混用。PHS 评分用的是本子项(带宽)。
补充指标:显存容量利用率(HBM 占用率 — 诊断用,不计入 PHS)
回答"显存利用率""HBM 占了多少""会不会 OOM/还能加多大 batch"这类问题时报此指标。它是独立诊断项,不进入 PHS 加权公式(PHS 内存子项仍只用带宽利用率,避免双重计入)。
前提与目录名 / 采集等级无关(落盘目录叫 level2、prof_out 等都行),只要采集时开了 profile_memory=true(落盘里有 memory_record.csv 即满足)。
显存容量利用率 = 显存占用峰值 (GB) ÷ 单卡 HBM 总容量 (GB) × 100
- 显存占用峰值数据来源(落盘 CSV,取
Total Reserved(MB) 时间序列最大值):
memory_record.csv:整进程视角,Component=APP 行的 Total Reserved(MB) 峰值(最贴近"这张卡占了多少显存");同表还有 Total Allocated(MB)(实际分配)/Total Active(MB)(活跃张量),可一并报;
npu_module_mem.csv:按组件(SLOG/KERNEL/...)拆分的 Reserved,用于定位占用大头;
operator_memory.csv:逐算子申请/释放与生命周期,用于排查显存峰值是哪些算子/激活贡献的;
- DB 口径:
ascend_pytorch_profiler_*.db 的 NPU_MEM(hbm/ddr 字节)、NPU_MODULE_MEM(totalReserved)、NPU_OP_MEM(totalAllocate/totalReserve)。
- 单卡 HBM 总容量:随芯片型号(如 910B 常见 32GB / 64GB),从
NPU_INFO 表确认型号后定;落盘缺型号时按候选容量给区间并注明"待确认型号",不要猜单值。
- 判读:
- Reserved ≫ Allocated(碎片/预留过多)→ 关注
PYTORCH_NPU_ALLOC_CONF=expandable_segments:True 等分配器配置;
- 容量利用率低但带宽利用率高 → 访存瓶颈而非容量瓶颈,优化方向在带宽/算子而非省显存;
- 容量利用率高(如 >90%)→ OOM 风险,建议 recompute / 调小 micro-batch / 切分并行度。
- 多卡:逐 rank 取峰值后报 max 与分布;PP/DP 不同 stage 的显存通常不均衡,按 rank 分别给。
场景权重表
按本次分析的工作负载类型选择一行:
| 场景 | 计算 | 通信 | 调度 | 内存 | 集群均衡度 |
|---|
| 大模型多卡训练(默认) | 0.40 | 0.30 | 0.20 | 0.10 | — |
| 单卡训练 / 推理 | 0.50 | N/A | 0.30 | 0.20 | — |
| 单算子调优 | 0.50 | N/A | 0.20 | 0.30 | — |
| 集群慢卡场景 | 0.20 | 0.30 | 0.30 | 0.10 | 0.10 |
集群均衡度(仅"集群慢卡场景"启用):
集群均衡度 = (1 - (max Rank step time - min Rank step time) ÷ mean Rank step time) × 100
数据来源:cluster_time_summary 输出。
权重归一化(N/A 处理)
若某子项为 N/A:
归一化权重 = 原权重 ÷ (1 - N/A 子项权重之和)
例:单卡推理场景,通信 N/A,则其他三项权重变为:
- 计算 0.50 ÷ (1 - 0) = 0.50(不变,因为单卡场景权重表里通信本就是 N/A)
- 调度 0.30 ÷ 1 = 0.30
- 内存 0.20 ÷ 1 = 0.20
若多卡训练中通信数据采集失败:
- 计算 0.40 ÷ (1 - 0.30) = 0.57
- 调度 0.20 ÷ 0.70 = 0.29
- 内存 0.10 ÷ 0.70 = 0.14
等级映射
| 分数区间 | 等级 | 释义 |
|---|
| 90 ≤ PHS ≤ 100 | S | 接近理论极限,无明显优化空间 |
| 75 ≤ PHS < 90 | A | 优秀,仅有零碎优化点 |
| 60 ≤ PHS < 75 | B+ | 良好,存在可观优化空间 |
| 45 ≤ PHS < 60 | B | 中等,建议系统性优化 |
| 30 ≤ PHS < 45 | C | 较差,存在显著瓶颈 |
| 0 ≤ PHS < 30 | D | 严重瓶颈,必须优先处理 |
输出格式(写入报告第 1 章首行)
固定格式,不要自由发挥。PHS 当前值与优化后预估值写在同一行,用 → 分隔:
- **性能健康度**:<分数> / 100 (<等级>) → 优化后预估 **<预估分数> / 100 (<预估等级>)** — 计算 <X>% · 通信 <Y>% · 调度 <Z>% · 内存 <W>%
集群慢卡场景额外追加均衡度子项:
- **性能健康度**:<分数> / 100 (<等级>) → 优化后预估 **<预估分数> / 100 (<预估等级>)** — 计算 <X>% · 通信 <Y>% · 调度 <Z>% · 内存 <W>% · 均衡 <V>%
任一子项 N/A 时直接写 N/A,禁止写 0:
- **性能健康度**:72 / 100 (B+) → 优化后预估 **85 / 100 (A)** — 计算 78% · 通信 N/A · 调度 85% · 内存 60%
优化后预估值的计算方式:根据行动清单中 P0/P1 项的"预期收益",反向估算各子项优化后数值,再代回 PHS 公式得到预估分和等级。若 P0/P1 无量化收益(全为高/中/低定性),则用保守估算(低=+3%、中=+7%、高=+12% 每子项)并在第 5 章注明。
收益上限行
第 1 章"收益上限"行只保留时间/利用率收益,不再重复 PHS 数字(PHS 已在首行展示):
- **收益上限**:行动清单 P0/P1 全部落地后节省 ~17% 单步耗时(约 210 ms)
计算流程(AI 执行步骤)
按以下顺序逐步执行,不要跳步:
- 识别场景:读取数据目录结构与 profiler 元数据,对照"场景权重表"4 类选一类
- 采集 4 个子项数值:按"子项算法"小节逐项采集,缺数据则记 N/A
- 权重归一化:若有 N/A 项,按"权重归一化"小节重新分配
- 加权求和:得到 0-100 整数分(四舍五入)
- 查等级表:得到 S/A/B+/B/C/D
- 估算优化后 PHS:根据行动清单中 P0/P1 项的"预期收益",反向估算优化后各子项数值,再代回公式,得到预估分和等级
- 写入报告:按"输出格式"将当前 PHS +
→ 优化后预估 写入第 1 章首行;"收益上限"行只写时间/利用率收益,不重复 PHS 数字
边界与错误处理
| 情形 | 处理方式 |
|---|
| 4 个子项全部 N/A | 不要输出 PHS 行,在第 1 章首行写"性能健康度:数据不足无法计算(详见第 5 章数据与方法)" |
数据完整性校验失败(mindstudio_profiler_data_check 报告失败) | 同上,不强行打分 |
| 子项数值 > 100(如理论带宽参考值偏低导致) | 截断到 100,并在第 5 章附录注明"<子项> 实测超出参考理论值,已截断" |
| 用户明确指定权重 | 听从用户;并在第 5 章附录注明"已采用用户自定义权重 <数值>" |