CANN oam-tools 性能剖析转 UI 报告:Breakdown Schema v2 到 UI JSON 的字段级 Schema 映射详解

发布时间:2026/9/18 4:22:52
CANN oam-tools 性能剖析转 UI 报告:Breakdown Schema v2 到 UI JSON 的字段级 Schema 映射详解 CANN oam-tools 性能剖析转 UI 报告Breakdown Schema v2 到 UI JSON 的字段级 Schema 映射详解【免费下载链接】oam-tools本项目为开发者提供故障定位工具包含故障信息收集软硬件信息展示AI core error报错分析等能力提升故障问题定位效率文档可在昇腾社区搜索“故障处理简介”选择社区版。项目地址: https://gitcode.com/cann/oam-tools本文以 oam-tools 仓库中cann-perf-breakdown工作流的第二阶段adapt-breakdown-to-ui-json参考文档 schema-mapping_en.md 为主体完整讲解模型性能剖析结果breakdown v2 的analysis_config.json如何映射为 UI 报告运行时消费的四种后端 JSON 事实分析配置、性能数据、归一化时间线与模型架构图。该映射以 Qwen-7B 的一对真实产物breakdown 侧analysis_config.json与报告侧qwen7b_analysis_config.json为验证基准。读完后你将掌握顶层键的逐字段映射规则、结构节点的形态转换、指标作用域metric scope语义、AI Core 计数器指标的处理方式、MoE 专家清单expert inventory的可测性边界以及 validate_conversion.py 强制执行的跨文件不变量。一、映射的上下文这个 Skill 解决什么问题整个转换链路位于三段式 Skill 之间SKILL.md 给出了明确的职责边界perf-breakdown-skill → THIS SKILL → generate-ui-json-report analysis_config.json 4 UI facts report/ runtime HTML kernel rows (representative) model source输入是一个已通过全部硬门槛validation、critique、score 均passed的 schema v2 breakdown 包输出是报告运行时读取的四个事实文件——prefix_analysis_config.json、prefix_perf_data.json、prefix_timeline.json与outputs/model_architecture_graph.json。映射文档的字段规则正是这四份产物之间的契约任何字段命名或标识规则identity rule的改动都必须先对照该文档。二、顶层键映射breakdown v2 → UI analysis config映射文档的第一张表定义了顶层键的逐一对应关系是转换的骨架breakdown v2UI analysis config说明schema_version: 2schema_version: 2.1-ui两套体系的版本号刻度不同不能直接拷贝数字model_namemodel_name原样透传—model_id由转换方选定必须与 perf 数据、时间线三方一致—report_id由转换方选定必须与 perf 数据、时间线三方一致—id_namespace形如model/model-id每个node_id都从它派生representative_steprepresentative_step原样透传architecturearchitecture整体透传包括source_of_truth和factstrace_scopetrace_scope透传绝不把unknown强化为已确认范围stagesdictstagesdict按节点逐个重塑见下文节点形态structures.grouplayer_structure.key折叠后的重复组runtime_auxiliarylistruntime_auxiliarylist按节点逐个重塑—source_only_structurelist捕获从未观察到的节点excluded_profiler_ops—不是 UI 的 owner/fact留在 breakdown 中但计入核算覆盖unmapped_ops—必须为空否则根本不允许转换migration—若存在且标记legacy_unverified拒绝转换model_flowmodel_flow可选的旧版线性流dataflowdataflow显式的跨结构图取代model_flow—structure_provenance/capture_provenance结构与运行数据来源不同时必填architecture和trace_scope之所以原样透传是因为它们已经是经过校验的架构事实重新推导只会丢弃 breakdown 中沉淀的 AST 证据。从源码看build_node_index.py 按声明顺序遍历stages、structures.group.children与runtime_auxiliary并拒绝两类畸形节点同时声明children与op_indices的节点会把自己的 kernel 直接计一次又通过后代计一次以及两个结构节点碰撞到同一node_id。三、节点形态Node Shape从结构节点到 UI 节点一个 breakdown 结构节点长这样以 Qwen-7B 的 SwiGLU gate 投影为例{ name: w1, semantic: SwiGLU gate projection, code_ref: modeling_qwen.py:561-571, op_indices: [31], kernels: [{index: 31, name: MatMulV2, duration_us: 99.5, input_shapes: 1,1,4096;11008,4096, output_shapes: 1,1,11008, shape_raw: ...}] }映射为 UI 分析节点后{ node_id: model/qwen-7b/decoder_layers/mlp/w1, semantic_key: w1, node_kind: op, metric_scope: all_observed_instances, name: w1, semantic: SwiGLU gate projection, code_ref: modeling_qwen.py:561-571, instance_indices: [0, 1, ..., 31], mapped_kernels: 32, children: [] }关键转换规则name同时写入semantic_key和nameop_indices/kernels被丢弃它们塌缩为一个计数字段mapped_kernels并流向性能数据与时间线。逐 kernel 的行数据不属于分析配置node_kind取值有children的容器是module叶子是op运行时项是runtime_auxiliaryinstance_indices每步只执行一次的节点为[]重复组下的节点列出全部观察到的实例下标如 32 层的全部 32 个下标children按声明顺序递归——顺序本身是一项语义声明激活流的先后次序。四、指标作用域Metric ScopeScope含义典型来源aggregate对后代求和带children的容器all_observed_instances叶子在每次调用中重复出现重复组下的叶子single_instance每步执行一次的叶子stages下的叶子sampled_window_context采样的设备上下文不是计算运行时采样器窗口一个重要推论作用域重叠的aggregate节点不能机械相加来得到时间占比UI 的占比是从total_time_us推导的。校验器侧对应一条硬检查validate_conversion.py 中metric_scope为sampled_window_context的记录若time_us非 null 即判定失败——因为采样窗口的挂钟时间不是计算时间若保留数值会让一个 0% 时间占比的节点在按 duration 排序时胜出、赢得默认选中导致 Inspector 打开后是空白的文档实测案例四个 10 ms 窗口合计 39.88 ms 挂钟压过 19.65 ms 的 decoder 聚合节点。五、性能记录Performance Record每个携带指标的节点一条记录与分析节点用同一个node_id对齐。所有键必须出现即使值为 null——键缺失与 null 是两种不同的声明null 表示捕获没测到缺失意味着流水线忘了问。完整键集合node_id module metric_scope time_us time_pct nops hbm_mb gflops mfu_bf16_pct mfu_int8_pct aicore_time_us aiv_time_us aicore_time_pct mac_ratio mte2_ratio mte1_ratio scalar_ratio fixpipe_ratio vec_ratio aiv_mte2_ratio cube_utilization_pct aic_total_cycles aiv_total_cycles aicore_cycle_time_us aiv_cycle_time_us counter_coverage op_ratio instance_indices code_ref kernel_scope_note其中hbm_mb是逻辑 shape × dtype 字节数的对比估算绝不是实测流量、容量或采样 HBM 时间线当节点跨多次调用聚合时必须在kernel_scope_note中说明。校验器对键集的落实分为两档validate_conversion.py#L31-L46REQUIRED_METRIC_KEYStime_us、time_pct、nops、hbm_mb、mfu_int8_pct、mfu_bf16_pct、metric_scope、op_ratio、aicore_time_us、mac_ratio、mte2_ratio无条件要求COUNTER_METRIC_KEYSaiv_time_us、aicore_time_pct、cube_utilization_pct、aic_total_cycles、aicore_cycle_time_us、counter_coverage只在文件带计数器形态时要求。判定标记是counter_coverage这一哨兵键——以它存在与否区分新发射器产物与旧产物避免对历史产物误报回归。5.1 AI Core 计数器指标这些指标来自kernel_details.csv的aic_*/aiv_*列由 attribute_kernels.py 带到每一条已归因行上。源码中 COUNTER_FIELDS 常量逐项列出了被携带的字段aic_mac_ratio、aic_mte1_ratio、aic_mte2_ratio、aiv_vec_ratio、aiv_mte2_ratio、cube_utilization_pct、block_dim、mix_block_dim等与映射文档的键集合一一对应。三条容易踩坑的规则均有源码注释佐证数据来源是raw_ops_details.json而非raw_ops.json。后者只有身份与时间前者才有计数器。load_counters 的 docstring 直接指出教训读错文件曾导致每个节点的计数器指标全部输出 null而数据就在磁盘上。文件缺失时返回空映射——无计数器的捕获仍能正常归因只是这些指标报 unavailable保留aic_/aiv_前缀不带前缀的mac_ratio会被误读为也覆盖了向量核而 AIV 流水线有自己独立的一组比例字段比例字段是时间加权的。mac_ratio与mte2_ratio的对比就是计算受限 vs 访存受限的读法MAC 高说明 cube 在算MTE2 高说明在等加载。加权方式按各计数器自身描述的时间而不是简单平均——否则一个 2 µs 的 Cast 会与一个 84 µs 的 MlaPrologV3 同权。counter_coverage报告该节点有多少 kernel 携带了计数器。没有它一个只由 50 个 kernel 中的 1 个算出的比例会被误读为全节点比例。5.2 MoE 专家清单Expert Inventorymodel-id_expert_inventory.json为每个已声明的专家各一条DeepSeek 3.2257 条。它不是逐专家的性能分解而是一份捕获能说什么、不能说什么的声明书。字段结构declared routed / shared / total / experts_per_token / source_refs expert_parallelism moe_ep_size local_routed_experts residency_evidence ep_rank resident_expert_indices identity_note measurability separable_per_expert reason what_would_be_needed counts declared_total resident_on_profiled_rank individually_measured fused_measured residency_unresolved remote_ep_shard fused_group_nodes node_id time_us nops covers_experts experts[] expert_id expert_index kind data_state local_slot resident_on_profiled_rank measured_by_node_id time_us reasondata_state只有四种取值语义必须精确区分build_expert_inventory.py 的模块 docstring 明确列出这两条不可混淆的理由measured拥有自己的 kernel共享专家——在每个 rank 上复制、未融合是唯一可以有真实time_us的状态fused_measured位于某个被测量的 group kernel 内但该 kernel 一次性覆盖全部驻留专家任何数字都不是这个专家独有的remote_ep_shard在另一个 EP rank 上执行时间是未知不是零residency_unresolved驻留数量已知全局身份未知。两条独立的事实链在源码中可验证专家并行度moe_ep_size来自GroupedMatmul输入中堆叠专家权重的首维。observed_local_experts 在 kernel 的input_shapes中找 rank ≥ 3 的第一个输入兼容[E, K, N]与 W8A8 分形量化布局[E, K1, N1, k0, n0]。已声明总数只能来自 manifest facts 及其 source refs——绝不能从 kernel shape 读因为 shape 只显示一个 rank 的切片否则会把模型按 EP 因子低报。当多个 GroupedMatmul kernel 报告不同的首维时脚本报告层不共享同一 EP 拓扑而非自行调和kernel 融合驻留专家以单个GroupedMatmul运行profiler 只报一个 duration。按 token 份额拆分会产出硬件从未测量过的逐专家数字——build_expert_inventory.py#L194 中非 shared 专家的time_us固定为None并有 validator 检查强制拒绝非measured专家携带逐专家时间。5.3 设备时钟与核数除数顶层字段aicore_freq_mhz加上第一阶段 device_freq.py 产出的完整device_profile块。两个独立来源declaredtrace_view.json中的AI Core Freq计数器事件。通常整个捕获只有两个采样点所以它是铭牌值不是频率曲线derived逐 kernel 的cycles / time / cores稠密且所有 cycle 派生指标都依赖它。两者不一致时 derived 胜出cross_check.agreement把失配暴露出来而不是取平均抹掉。核数除子是全部技巧所在。aic_total_cycles汇总了 kernel 占用的所有核心所以单独用cycles / time得到的是核数 × 时钟——在 24 核的 kernel 上会读出约 44 GHz 的荒谬值。AIV 计数器在MIX_AICkernel 上必须用Mix Block Dim而非Block Dim向量阶段运行在不同数量的核心上用错字段恰好报告 2 倍于真值的时钟DS3.2 捕获上漏除核数会放大 22 倍。一致性校验是这条链路最便宜也最有力的检查aicore_cycle_time_us与aicore_time_us是同一物理量经不同路径得到的结果两者一致就同时证明了时钟和除子都对。validate_conversion.py#L261-L278 以 1% 容差强制执行——对计数器舍入足够宽松对除子错成核数倍偏差 100%则绝无放行可能。此外校验器还检查aicore_freq_mhz与device_profile内值一致、aicore_freq_basis属于derived/declared/unavailable之一、cross_check.agreement不得为mismatchL244-L259。无计数器捕获不是错误时钟置 null所有派生字段置 nullUI 报 unavailable。绝不代入假设频率——那会静默地把整套 cycle 指标整体重标。计数器求和有意包含duplicate_of行与 duration 求和相反。原因是双重上报的集合通信中COMMUNICATION 主行不携带计数器AIV 行携带全部计数器跳过 duplicate 等于丢弃实测的向量工作量DS3.2 捕获中占该 step AIV 时间的 6.9%而不是去重。对应地validate_conversion.py#L299-L315 断言每一对 duplicate 中至多一行携带计数器防止未来 profiler 双行都填计数器时静默双计。六、时间线事件Timeline Event每个已归因 kernel 一条另加每个运行时/采样窗口一条字段集合event_id op_index name op_type device_id stream_id accelerator_core start_time_us ts_us duration_us end_us wait_time_us owner_node_id instance_index structure_instance_node_id submodule mapping_status trace_join_statusowner_node_id必须能解析到分析节点——校验器同时检查所有事件有 owner与所有非空 owner 可解析两条instance_index承载重复组的层下标structure_instance_node_id在代表节点被折叠时标识具体实例——UI 需要它来计算单实例核心指标而不是把 32 层全部求和submodule保存结构叶子名当捕获自身的分段标签与之不同时原标签保留在capture_submodule。采样窗口节点取time_us: null挂钟跨度单独放在sampled_window_span_us字段理由见前文作用域一节。七、图model_architecture_graph.v1model_architecture_graph.v1契约要求非空roots、显式edges、一个section/source_architecture根以及一个独立的section/runtime_auxiliary根运行时辅助必须与模型数据流分开。边只能从声明推导绝不推断三类来源激活边来自容器内children的顺序残差/跳过边来自structures.group.branches例如{name: attention_residual, inputs: [block_input, attn.c_proj], output: residual_attn, source_ref: modeling_qwen.py:623-624}每个声明的inputs/output对生成一条独立边带稳定 id、semanticEdgeType: residual、张量元数据与 provenance。即使折叠投影让多条边落到相同的可见端点每条边身份也必须保留——绝不允许仅按投影后的source-target去重跨结构边来自顶层dataflow.edges把每个端点的structure加可选source_port/target_port解析为图节点 id。若某条branches声明引用了结构中未定义的输入这是 breakdown 的缺陷——应当报告而不是悄悄丢边。每个条目的状态字段dataState取mapped/source_only/runtimeorigin取source/hybrid/syntheticmapped 条目携带backendNodeId与mappingKind。Source-only 条目保持selectable: true并带sourceRefs绝不携带backendNodeId、不得继承性能热图。校验器对应两条检查所有backendNodeId必须解析到分析节点dangling 报出dataState source_only的条目不得带backendNodeIdvalidate_conversion.py#L228-L236。八、Source-only 节点键名就是陷阱source_only_structure的条目以structure_node_id为键绝不能写成node_id。原因是 UI 运行时通过扫描node_id来构建后端节点索引——用错键等于把一个无指标节点注入该索引直接导致后端计数检查失败。校验器专门设有两条防线source-only entries use structure_node_id, not node_id与no source-only node carries metricsvalidate_conversion.py#L121-L137。条目形态{structure_node_id: model/qwen-7b/stages/embedding/position_range, name: position_range, code_ref: modeling_qwen.py:802-808, data_state: source_only, reason: Position arange runs once outside the representative decode step, so no Range kernel falls inside this capture window.}reason必须是具体的捕获事实。Not found 不是理由——SKILL.md 也强调发射器自动生成的 no kernel attributed 只描述了症状必须替换为真实原因如上面的位置 arange 在代表 decode step 之外执行因此该捕获窗口内不存在 Range kernel。九、跨文件不变量Cross-file Invariants交棒给报告 Skill 之前validate_conversion.py 按以下清单逐条验证任何一条失败都会点名具体节点model_id、report_id、representative_step在三份 JSON 中完全一致校验器对三值集合判等分析侧与性能侧的node_id集合对每个携带指标的节点一一对应且各无重复时间线每个非空owner_node_id都能解析到分析节点且每个事件都有 ownerkernel 数量守恒叶子sum(mapped_kernels) 已归因 kernel 数 时间线计算事件数attributed excluded unattributed raw kernel 总数且核算覆盖率必须恰为 100%任何source_only_structure条目不出现在性能数据中图的每个backendNodeId解析到分析节点每条图边都携带张量元数据与 provenancethin edge 报出计数器一致性时钟存在时time_us与cycle_time_us双路结果 1% 内一致duplicate 对至多一行携带计数器sampled_window_context节点time_us为 null。这些检查在合成数据上有对应的测试保障测试夹具见 tests/fixtures/synthetic含analysis_config_v2.json与raw_ops.json的最小合成 breakdown各行为测试位于 tests 下的test_readiness.py、test_handoff_compatibility.py、test_ui_report_handoff.py等。十、实操路径一键转换与失败处理映射文档描述的字段契约由五步流水线落地均取自 SKILL.mdcheck_breakdown_ready.py --breakdown dir --out readiness.json——确认 breakdown 可转换各状态文件passed、schema v2、unmapped_ops为空、无legacy_unverified迁移build_node_index.py --breakdown dir --namespace model/model-id --rename-group StructureKeynode-name --out node_index.json——生成节点索引。重复组在 breakdown 里按源类命名QWenBlock、在报告里按角色寻址decoder_layers时必须显式用--rename-group声明改名绝不从类名启发式推导角色名attribute_kernels.py --breakdown dir --nodes node_index.json --split-rules rules.json --out kernel_attribution.json——按三级证据归因叶子自身op_indices→trace_instances[].op_range的范围算术 → 显式分裂规则全程禁止叶子标签相似性匹配emit_ui_facts.py ... --model-id id --report-id id --peak-bf16-tflops v --dtype-bytes v --out out-dir——写出三份事实文件核算覆盖率低于 100% 时拒绝运行validate_conversion.py --out out-dir --attribution kernel_attribution.json——跑完上文第九节的不变量清单然后交棒给 UI Skill 自己的validate-architecture-graph.mjs做最终权威校验。一次性路径由 run_pipeline.py 提供python run_pipeline.py --breakdown dir从就绪门槛启动、写出ui-report-handoff.json、执行报告生成器最终返回pending_manual_validation。失败处理原则同样写死在契约里kernel 数量不匹配时不得重分配余量要找到断言错误的 run、打印其 op type 与 shape、对照模型源码节点不在索引中时修复命名空间派生绝不把两个不同结构节点合并成一个 id时间线 owner 解析不到时给显式的 runtime_auxiliary 节点不做 phase 级兜底。报告结果时要给出零余量核算例如1218 total 1217 attributed 1 excluded 0 unattributed让分段可审计校验器硬编码了别家模型节点名而失败时如实说明是哪条断言、为什么而不是改节点名去迎合它。小结这份 schema 映射的核心思想可以概括为三点标识一致性id_namespace派生所有node_id三份文件共享model_id/report_id/representative_step、证据优先边与归因只来自声明绝不推断、绝不按相似度匹配、诚实的不可用null 与缺失键严格区分未测到的指标报 unavailable 而非代入假设值。字段表、不变量清单与 validate_conversion.py 的逐条实现共同构成了一道可审计的交棒门槛使 breakdown 侧的性能事实能够无损、无虚构地进入 UI 报告运行时。【免费下载链接】oam-tools本项目为开发者提供故障定位工具包含故障信息收集软硬件信息展示AI core error报错分析等能力提升故障问题定位效率文档可在昇腾社区搜索“故障处理简介”选择社区版。项目地址: https://gitcode.com/cann/oam-tools创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考