ops-tune-workbench-plugin 0.0.0-stage → 0.0.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE.md +14 -0
- package/README.md +39 -2
- package/cordis.patch.yml +20 -0
- package/lib/client.js +4253 -0
- package/lib/host.js +2518 -0
- package/package.json +53 -4
- package/skills/tool-ops-tune/INSTALL.md +52 -0
- package/skills/tool-ops-tune/README.md +167 -0
- package/skills/tool-ops-tune/SKILL.md +93 -0
- package/skills/tool-ops-tune/agent/AGENTS.md +195 -0
- package/skills/tool-ops-tune/agent/agents/perf-implementer.md +68 -0
- package/skills/tool-ops-tune/agent/agents/perf-reviewer.md +86 -0
- package/skills/tool-ops-tune/agent/workflows/task-prompts.md +362 -0
- package/skills/tool-ops-tune/agent/workflows/troubleshooting.md +43 -0
- package/skills/tool-ops-tune/docs/figures/opstune-architecture.png +0 -0
- package/skills/tool-ops-tune/docs/figures/opstune-architecture.svg +253 -0
- package/skills/tool-ops-tune/docs/ops-tune-design.md +404 -0
- package/skills/tool-ops-tune/docs//347/224/250/344/276/213/346/236/204/345/273/272.md +714 -0
- package/skills/tool-ops-tune/docs//347/237/245/350/257/206/345/272/223/350/247/204/350/214/203.md +103 -0
- package/skills/tool-ops-tune/evals/evals.json +242 -0
- package/skills/tool-ops-tune/ops-collect/SKILL.md +146 -0
- package/skills/tool-ops-tune/ops-collect/references/tool-routing.md +86 -0
- package/skills/tool-ops-tune/ops-collect/scripts/collect_board.sh +444 -0
- package/skills/tool-ops-tune/ops-collect/scripts/collect_cases.py +368 -0
- package/skills/tool-ops-tune/ops-collect/scripts/collect_sim.sh +134 -0
- package/skills/tool-ops-tune/ops-collect/scripts/csv_to_db.py +314 -0
- package/skills/tool-ops-tune/ops-collect/scripts/db_bench.py +545 -0
- package/skills/tool-ops-tune/ops-collect/scripts/facts_bridge.py +1063 -0
- package/skills/tool-ops-tune/ops-collect/scripts/isolation_test.py +454 -0
- package/skills/tool-ops-tune/ops-collect/scripts/jsonl_to_cases.py +163 -0
- package/skills/tool-ops-tune/ops-family/SKILL.md +76 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/advanced_tiling.md +92 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/broadcast_design.md +160 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/code/broadcast_add_kernel.cpp +126 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/code/broadcast_add_tiling.cpp +144 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/code/broadcast_tiling_common.h +401 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/code/onedim_add_kernel.cpp +107 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/code/onedim_add_tiling.cpp +64 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/datacopypad_design.md +46 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/guide.md +14 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/nddma_design.md +53 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/onedim_design.md +114 -0
- package/skills/tool-ops-tune/ops-family/references/broadcast/ub_broadcast_design.md +67 -0
- package/skills/tool-ops-tune/ops-family/references/common/datacopy_optimization_design.md +351 -0
- package/skills/tool-ops-tune/ops-family/references/common/index.md +9 -0
- package/skills/tool-ops-tune/ops-family/references/common/tail_block_design.md +268 -0
- package/skills/tool-ops-tune/ops-family/references/common/timing_harness/index.md +38 -0
- package/skills/tool-ops-tune/ops-family/references/common/timing_harness/timing_harness_aclrt_event.cpp +199 -0
- package/skills/tool-ops-tune/ops-family/references/common/timing_harness/timing_harness_torch_event.py +130 -0
- package/skills/tool-ops-tune/ops-family/references/common/ub_resident_design.md +342 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/guide.md +69 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/index.md +4 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_base.template +81 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_big_dim.template +217 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_cut_one_axis.template +336 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_cut_two_axis.template +781 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_n_last.template +340 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_small_shape.template +321 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_tensor_move.template +102 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_transdata_5hd.template +480 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_transdata_5hd_021axis.template +533 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_with_gather.template +688 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/templates/transpose_tiling_data.template +192 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_big_dim.md +220 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_cut_one_axis.md +175 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_cut_two_axis.md +177 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_fusion_design.md +398 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_gather.md +191 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_n_last.md +276 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_small_shape.md +315 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_tensor_move.md +203 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_tiling_data.md +176 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_vconv_021.md +206 -0
- package/skills/tool-ops-tune/ops-family/references/conversion/transpose_vconv_5hd.md +179 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/double_buffer_design.md +288 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/guide.md +46 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/index.md +10 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/CMakeLists.txt +131 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/README.md +55 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_extension/add_custom_torch.cpp +80 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_extension/ops.h +23 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_extension/register.cpp +30 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_host/add_custom.asc +149 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_host/data_utils.h +97 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_kernel/add_custom_kernel.asc +136 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_kernel/add_custom_tiling.h +31 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/run.sh +86 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/scripts/gen_data.py +70 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/scripts/golden.py +34 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/scripts/test_torch.py +99 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/scripts/verify_result.py +56 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/templates/usage_guide.md +61 -0
- package/skills/tool-ops-tune/ops-family/references/elementwise/vector_efficiency_design.md +203 -0
- package/skills/tool-ops-tune/ops-family/references/fa/fa_mixed_kernel_design.md +174 -0
- package/skills/tool-ops-tune/ops-family/references/fa/fa_roofline_design.md +141 -0
- package/skills/tool-ops-tune/ops-family/references/fa/guide.md +87 -0
- package/skills/tool-ops-tune/ops-family/references/knowledge_gaps.json +56 -0
- package/skills/tool-ops-tune/ops-family/references/matmul/best-practices-guide.md +14 -0
- package/skills/tool-ops-tune/ops-family/references/matmul/fullload_design.md +344 -0
- package/skills/tool-ops-tune/ops-family/references/matmul/guide.md +52 -0
- package/skills/tool-ops-tune/ops-family/references/matmul/mte2_preload_design.md +320 -0
- package/skills/tool-ops-tune/ops-family/references/matmul/pingpong_design.md +254 -0
- package/skills/tool-ops-tune/ops-family/references/matmul/scale_coalescing_design.md +282 -0
- package/skills/tool-ops-tune/ops-family/references/matmul/streamk_design.md +374 -0
- package/skills/tool-ops-tune/ops-family/references/matmul/swat_design.md +423 -0
- package/skills/tool-ops-tune/ops-family/references/matmul/templates/matmul_basic_blaze.template +165 -0
- package/skills/tool-ops-tune/ops-family/references/matmul/templates/usage_guide.md +29 -0
- package/skills/tool-ops-tune/ops-family/references/mc2/best-practices-guide.md +43 -0
- package/skills/tool-ops-tune/ops-family/references/mc2/guide.md +42 -0
- package/skills/tool-ops-tune/ops-family/references/mc2/local_matmul_design.md +130 -0
- package/skills/tool-ops-tune/ops-family/references/mc2/pipeline_balancing_design.md +502 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/guide.md +178 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/kernel_utils.template +75 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ar_full_load.template +429 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ar_recompute.template +485 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ar_small_r.template +348 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ara_full_load.template +574 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ara_online.template +324 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ara_recompute.template +436 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_base.template +950 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/fused_attention_online_softmax_design.md +428 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ar_full_load.md +137 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ar_recompute.md +135 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ar_small_r.md +122 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ara_full_load.md +144 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ara_online.md +185 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ara_recompute.md +163 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_tiling.template +460 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_tiling_data.template +278 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/state_resident_design.md +337 -0
- package/skills/tool-ops-tune/ops-family/references/reduce/templates/usage_guide.md +253 -0
- package/skills/tool-ops-tune/ops-family/references/scalar/coding_principles.md +476 -0
- package/skills/tool-ops-tune/ops-family/references/scalar/conv_scalar.md +163 -0
- package/skills/tool-ops-tune/ops-family/references/scalar/guide.md +30 -0
- package/skills/tool-ops-tune/ops-family/references/simt/guide.md +91 -0
- package/skills/tool-ops-tune/ops-family/references/simt/optimization-guide.md +110 -0
- package/skills/tool-ops-tune/ops-family/references/sort/guide.md +83 -0
- package/skills/tool-ops-tune/ops-family/references/sort/radix_sort.md +354 -0
- package/skills/tool-ops-tune/ops-family/scripts/family_asset_audit.py +68 -0
- package/skills/tool-ops-tune/ops-family/scripts/tiling_candidates.py +419 -0
- package/skills/tool-ops-tune/ops-mechanism/SKILL.md +23 -0
- package/skills/tool-ops-tune/ops-mechanism/cases/ascendc/case_groupedmatmul_pipeline.md +23 -0
- package/skills/tool-ops-tune/ops-mechanism/cases/ascendc/case_triton_atomic_revert.md +19 -0
- package/skills/tool-ops-tune/ops-mechanism/cases/mc2/case_mc2_fusion.md +19 -0
- package/skills/tool-ops-tune/ops-mechanism/references/optimize/api-usage.md +70 -0
- package/skills/tool-ops-tune/ops-mechanism/references/optimize/ascendc-regbase-vf.md +45 -0
- package/skills/tool-ops-tune/ops-mechanism/references/optimize/ascendc-tiling.md +51 -0
- package/skills/tool-ops-tune/ops-mechanism/references/optimize/data-copy.md +67 -0
- package/skills/tool-ops-tune/ops-mechanism/references/optimize/index.md +45 -0
- package/skills/tool-ops-tune/ops-mechanism/references/optimize/mc2-balancing.md +77 -0
- package/skills/tool-ops-tune/ops-mechanism/references/optimize/mc2.md +103 -0
- package/skills/tool-ops-tune/ops-mechanism/references/optimize/memory-hierarchy.md +40 -0
- package/skills/tool-ops-tune/ops-mechanism/references/optimize/pipeline.md +95 -0
- package/skills/tool-ops-tune/ops-mechanism/scripts/case_backfill.py +170 -0
- package/skills/tool-ops-tune/ops-mechanism/scripts/log_gap.py +145 -0
- package/skills/tool-ops-tune/ops-mechanism/scripts/mc2_search.py +367 -0
- package/skills/tool-ops-tune/ops-report/SKILL.md +77 -0
- package/skills/tool-ops-tune/ops-verdict/evals/run_evals.py +837 -0
- package/skills/tool-ops-tune/ops-verdict/evals/smoke/install-hooks.sh +65 -0
- package/skills/tool-ops-tune/ops-verdict/evals/smoke/run_smoke.sh +405 -0
- package/skills/tool-ops-tune/ops-verdict/fixtures/core_tail_a5.csv +25 -0
- package/skills/tool-ops-tune/ops-verdict/fixtures/few_cores_a5.csv +5 -0
- package/skills/tool-ops-tune/ops-verdict/fixtures/mte2_bound_a2.csv +17 -0
- package/skills/tool-ops-tune/ops-verdict/fixtures/multi_kernel_mix_a5.csv +7 -0
- package/skills/tool-ops-tune/ops-verdict/fixtures/no_bound_a5.csv +9 -0
- package/skills/tool-ops-tune/ops-verdict/fixtures/serial_no_overlap_a2.csv +9 -0
- package/skills/tool-ops-tune/ops-verdict/fixtures/vec_bound_a5.csv +9 -0
- package/skills/tool-ops-tune/ops-verdict/references/io-contracts.md +94 -0
- package/skills/tool-ops-tune/ops-verdict/references/rule-schema.md +130 -0
- package/skills/tool-ops-tune/ops-verdict/references/scope-schema.md +61 -0
- package/skills/tool-ops-tune/ops-verdict/references/soc-spec.yaml +140 -0
- package/skills/tool-ops-tune/ops-verdict/rules/L0-instruction.yaml +67 -0
- package/skills/tool-ops-tune/ops-verdict/rules/L1-single-core.yaml +316 -0
- package/skills/tool-ops-tune/ops-verdict/rules/L2-inter-core.yaml +173 -0
- package/skills/tool-ops-tune/ops-verdict/rules/L3-inter-card.yaml +156 -0
- package/skills/tool-ops-tune/ops-verdict/scripts/batch_pipeline.py +444 -0
- package/skills/tool-ops-tune/ops-verdict/scripts/calibrate.py +249 -0
- package/skills/tool-ops-tune/ops-verdict/scripts/delta_compare.py +244 -0
- package/skills/tool-ops-tune/ops-verdict/scripts/render_html.py +274 -0
- package/skills/tool-ops-tune/ops-verdict/scripts/snapshot.py +200 -0
- package/skills/tool-ops-tune/ops-verdict/scripts/trace_bubble.py +331 -0
- package/skills/tool-ops-tune/ops-verdict/scripts/verdict.py +1072 -0
- package/skills/tool-ops-tune/scripts/diff_audit.py +281 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# ----------------------------------------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2026 Huawei Technologies Co., Ltd.
|
|
5
|
+
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
|
|
6
|
+
# CANN Open Software License Agreement Version 2.0 (the "License").
|
|
7
|
+
# Please refer to the License for details. You may not use this file except in compliance with the License.
|
|
8
|
+
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
|
9
|
+
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
|
|
10
|
+
# See LICENSE in the root of the software repository for the full text of the License.
|
|
11
|
+
# ----------------------------------------------------------------------------------------------------------
|
|
12
|
+
"""snapshot.py — 调优结果指纹快照(不可变基线的载体)
|
|
13
|
+
|
|
14
|
+
设计对齐(docs/算子调优AGENT设计文档.md §6 数据契约):
|
|
15
|
+
- 口径指纹思想:性能结论只有在同口径下才可比。
|
|
16
|
+
- HARD_KEYS(环境/口径 12 字段)不一致禁止比较;MECHANISM_KEYS(tiling_key/block_dim)
|
|
17
|
+
是优化本身的变量 → 降级 WARN 并写进报告(对优化本质的建模)。
|
|
18
|
+
- 精度门禁第三道(脚本化):precision != pass → 本快照可保存,但禁止进入性能结论。
|
|
19
|
+
|
|
20
|
+
用法:
|
|
21
|
+
python3 snapshot.py --op gelu --variant baseline --mode board --soc a5 \
|
|
22
|
+
--precision pass --kernel-avg-us 14.1 --timing-method event \
|
|
23
|
+
--baseline-kind self_before_after --cann-version 8.3.0 \
|
|
24
|
+
--device-id 0 --shape 8448x4096 --dtype fp16 --format ND \
|
|
25
|
+
--warmup 5 --repeat 20 -o tuning_artifacts/gelu/baseline/result.json
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
import argparse
|
|
31
|
+
import datetime
|
|
32
|
+
import json
|
|
33
|
+
import subprocess
|
|
34
|
+
import sys
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
|
|
37
|
+
SCHEMA = "opstune.snapshot/1.0"
|
|
38
|
+
|
|
39
|
+
# 口径指纹:delta_compare.py 硬校验字段(不一致 → 拒绝比较)
|
|
40
|
+
HARD_KEYS = (
|
|
41
|
+
"op",
|
|
42
|
+
"soc",
|
|
43
|
+
"mode",
|
|
44
|
+
"timing_method",
|
|
45
|
+
"baseline_kind",
|
|
46
|
+
"cann_version",
|
|
47
|
+
"device_id",
|
|
48
|
+
"shape",
|
|
49
|
+
"dtype",
|
|
50
|
+
"format",
|
|
51
|
+
"warmup",
|
|
52
|
+
"repeat",
|
|
53
|
+
)
|
|
54
|
+
# 机制变量:分核/tiling 类优化本身会改 → 降级 WARN
|
|
55
|
+
MECHANISM_KEYS = ("tiling_key", "block_dim")
|
|
56
|
+
|
|
57
|
+
TIMING_METHODS = ("event", "sim", "msprof", "msprof_task_duration", "profiler_summary")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def env_fingerprint() -> dict:
|
|
61
|
+
"""尽力采集环境指纹;失败字段置 unavailable,不阻断(离线诊断也允许建快照)。"""
|
|
62
|
+
fp = {}
|
|
63
|
+
for key, cmd in {
|
|
64
|
+
"npu_smi": ["npu-smi", "info"],
|
|
65
|
+
"cann_version_info": [
|
|
66
|
+
"bash",
|
|
67
|
+
"-c",
|
|
68
|
+
"cat $ASCEND_HOME_PATH/version.info 2>/dev/null | head -3",
|
|
69
|
+
],
|
|
70
|
+
}.items():
|
|
71
|
+
try:
|
|
72
|
+
fp[key] = (
|
|
73
|
+
subprocess.run(
|
|
74
|
+
cmd, capture_output=True, text=True, timeout=10
|
|
75
|
+
).stdout.strip()[:500]
|
|
76
|
+
or "unavailable"
|
|
77
|
+
)
|
|
78
|
+
except Exception:
|
|
79
|
+
fp[key] = "unavailable"
|
|
80
|
+
return fp
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def main() -> int:
|
|
84
|
+
ap = argparse.ArgumentParser(description="调优结果指纹快照")
|
|
85
|
+
ap.add_argument("--op", required=True)
|
|
86
|
+
ap.add_argument(
|
|
87
|
+
"--variant", required=True, help="baseline / round-01-<mechanism> / optimized"
|
|
88
|
+
)
|
|
89
|
+
ap.add_argument("--mode", default="board", choices=["board", "sim"])
|
|
90
|
+
ap.add_argument("--soc", required=True, help="a2/a3/a5")
|
|
91
|
+
ap.add_argument(
|
|
92
|
+
"--precision",
|
|
93
|
+
required=True,
|
|
94
|
+
choices=["pass", "fail"],
|
|
95
|
+
help="精度门禁结果(工程现有测试口径,禁止自创容差)",
|
|
96
|
+
)
|
|
97
|
+
ap.add_argument("--kernel-avg-us", type=float, default=None)
|
|
98
|
+
ap.add_argument(
|
|
99
|
+
"--kernel-p50-us",
|
|
100
|
+
type=float,
|
|
101
|
+
default=None,
|
|
102
|
+
help="稳态 p50(µs,可选分布字段;供 delta_compare 抖动诊断)",
|
|
103
|
+
)
|
|
104
|
+
ap.add_argument(
|
|
105
|
+
"--kernel-p95-us", type=float, default=None, help="稳态 p95(µs,可选分布字段)"
|
|
106
|
+
)
|
|
107
|
+
ap.add_argument(
|
|
108
|
+
"--kernel-max-us", type=float, default=None, help="稳态 max(µs,可选分布字段)"
|
|
109
|
+
)
|
|
110
|
+
ap.add_argument(
|
|
111
|
+
"--timing-method",
|
|
112
|
+
required=True,
|
|
113
|
+
choices=TIMING_METHODS,
|
|
114
|
+
help="event=host aclrtEvent / sim=cannsim / msprof / msprof_task_duration"
|
|
115
|
+
"=长kernel无event设施时 / profiler_summary",
|
|
116
|
+
)
|
|
117
|
+
ap.add_argument(
|
|
118
|
+
"--baseline-kind", required=True, choices=["system", "self_before_after"]
|
|
119
|
+
)
|
|
120
|
+
ap.add_argument("--cann-version", default="unknown")
|
|
121
|
+
ap.add_argument("--repo-commit", default=None)
|
|
122
|
+
ap.add_argument("--device-id", default=None)
|
|
123
|
+
ap.add_argument("--shape", required=True)
|
|
124
|
+
ap.add_argument("--dtype", required=True)
|
|
125
|
+
ap.add_argument("--format", default="ND")
|
|
126
|
+
ap.add_argument("--tiling-key", default=None)
|
|
127
|
+
ap.add_argument("--block-dim", type=int, default=None)
|
|
128
|
+
ap.add_argument("--warmup", type=int, required=True)
|
|
129
|
+
ap.add_argument("--repeat", type=int, required=True)
|
|
130
|
+
ap.add_argument(
|
|
131
|
+
"--status",
|
|
132
|
+
default="ok",
|
|
133
|
+
choices=["ok", "partial", "dry_run"],
|
|
134
|
+
help="dry_run=未上板仅离线结论;partial=部分 case/指标未采集",
|
|
135
|
+
)
|
|
136
|
+
ap.add_argument(
|
|
137
|
+
"--mismatch", type=int, default=None, help="精度 mismatch 数(误差指纹)"
|
|
138
|
+
)
|
|
139
|
+
ap.add_argument("--max-abs-err", type=float, default=None)
|
|
140
|
+
ap.add_argument("--max-rel-err", type=float, default=None)
|
|
141
|
+
ap.add_argument("--verdict-file", default=None, help="关联 verdict.json 路径")
|
|
142
|
+
ap.add_argument("--extra", default="", help="任意扩展键值 k=v,k=v")
|
|
143
|
+
ap.add_argument(
|
|
144
|
+
"--no-env-probe", action="store_true", help="跳过环境探测(离线/CI)"
|
|
145
|
+
)
|
|
146
|
+
ap.add_argument("-o", "--output", required=True)
|
|
147
|
+
args = ap.parse_args()
|
|
148
|
+
|
|
149
|
+
extra = {}
|
|
150
|
+
if args.extra:
|
|
151
|
+
for kv in args.extra.split(","):
|
|
152
|
+
if "=" in kv:
|
|
153
|
+
k, v = kv.split("=", 1)
|
|
154
|
+
extra[k] = v
|
|
155
|
+
|
|
156
|
+
# 口径指纹(HARD):字段名与 argparse 目标名同名,从契约元组直接构建——
|
|
157
|
+
# 单一真源(新增 HARD 字段只改 HARD_KEYS 元组,不在此重复手写字段名)
|
|
158
|
+
hard_fields = {key: getattr(args, key) for key in HARD_KEYS}
|
|
159
|
+
snap = {
|
|
160
|
+
"schema": SCHEMA,
|
|
161
|
+
"generated_at": datetime.datetime.now().isoformat(timespec="seconds"),
|
|
162
|
+
# 口径指纹(HARD)+ 溯源 commit(非 HARD:仅环境留痕)
|
|
163
|
+
**hard_fields,
|
|
164
|
+
"repo_commit": args.repo_commit,
|
|
165
|
+
# 机制变量(WARN 级)
|
|
166
|
+
"tiling_key": args.tiling_key,
|
|
167
|
+
"block_dim": args.block_dim,
|
|
168
|
+
# 性能与精度
|
|
169
|
+
"variant": args.variant,
|
|
170
|
+
"precision": args.precision,
|
|
171
|
+
"kernel_avg_us": args.kernel_avg_us,
|
|
172
|
+
# 可选分布字段(F20:±5% 噪声带判定的统计基础;MC² 抖动双维纪律的落盘载体)
|
|
173
|
+
"kernel_p50_us": args.kernel_p50_us,
|
|
174
|
+
"kernel_p95_us": args.kernel_p95_us,
|
|
175
|
+
"kernel_max_us": args.kernel_max_us,
|
|
176
|
+
"mismatch": args.mismatch,
|
|
177
|
+
"max_abs_err": args.max_abs_err,
|
|
178
|
+
"max_rel_err": args.max_rel_err,
|
|
179
|
+
"status": args.status,
|
|
180
|
+
"verdict_file": args.verdict_file,
|
|
181
|
+
"env": {} if args.no_env_probe else env_fingerprint(),
|
|
182
|
+
"extra": extra,
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
out = Path(args.output)
|
|
186
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
187
|
+
out.write_text(
|
|
188
|
+
json.dumps(snap, indent=2, ensure_ascii=False) + "\n", encoding="utf-8"
|
|
189
|
+
)
|
|
190
|
+
print(f"snapshot → {out}")
|
|
191
|
+
if args.precision != "pass":
|
|
192
|
+
print(
|
|
193
|
+
"⚠ 精度门禁未通过:本快照禁止用于性能结论(delta_compare 将拒绝生成对比)",
|
|
194
|
+
file=sys.stderr,
|
|
195
|
+
)
|
|
196
|
+
return 0
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
if __name__ == "__main__":
|
|
200
|
+
sys.exit(main())
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# ----------------------------------------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2026 Huawei Technologies Co., Ltd.
|
|
5
|
+
# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
|
|
6
|
+
# CANN Open Software License Agreement Version 2.0 (the "License").
|
|
7
|
+
# Please refer to the License for details. You may not use this file except in compliance with the License.
|
|
8
|
+
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
|
9
|
+
# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
|
|
10
|
+
# See LICENSE in the root of the software repository for the full text of the License.
|
|
11
|
+
# ----------------------------------------------------------------------------------------------------------
|
|
12
|
+
"""trace_bubble.py — cannsim/trace 空泡与重叠度分析(REVIEW2 G7/G8/G13 / 反馈 P1-1②)
|
|
13
|
+
|
|
14
|
+
设计对齐:
|
|
15
|
+
- L1_SERIAL_NO_OVERLAP 的串行指纹此前是派生推断(pipe 求和≈100%),
|
|
16
|
+
L1_LATENCY_SYNC_SUSPECT 置信度 medium、无直接证据(G13);
|
|
17
|
+
- pipeline.md 机制卡承诺「DoubleBuffer 生效 = MTE 与计算重叠比例 >30%
|
|
18
|
+
(部分 10-30%,未生效 <5%)」只有文字,无度量工具(G8);
|
|
19
|
+
- L0_STALL_DOMINANT 的 top_stall_pct 无生产者(G7)。
|
|
20
|
+
- 本脚本从 trace_core*.json(cannsim report 产出的 Chrome Trace Format)直接
|
|
21
|
+
提取:pipe 重叠比例 → overlap_pct、空泡占比 → top_stall_pct,输出 verdict.py
|
|
22
|
+
可直接消费的 --scalar 串——三个缺口一个工具补齐。
|
|
23
|
+
|
|
24
|
+
trace 格式(cannsim report 实测,与 ops-simulator 文档一致):
|
|
25
|
+
Chrome Trace Format:traceEvents[],ph="X" duration 事件(ts/dur,单位 ns),
|
|
26
|
+
metadata 事件(ph="M" name="process_name")携带 pid → pipeline 名映射。
|
|
27
|
+
cannsim 把 VECTOR 细分为 RVECSU/RVECEX/RVECLD/RVECST/RVECLP、FIXPIPE 写作
|
|
28
|
+
FIXP——归并处理(与业界仿真分析实践同款认知,独立实现)。
|
|
29
|
+
|
|
30
|
+
用法:
|
|
31
|
+
python3 trace_bubble.py --trace report/trace_core0.json [--scalar-out scalars.json]
|
|
32
|
+
python3 trace_bubble.py --trace-dir report/ # 多核聚合(逐核 + 汇总)
|
|
33
|
+
输出标量(verdict --scalar 直接消费):
|
|
34
|
+
overlap_pct :主计算 pipe 与 MTE2 的 busy 交集 / 并集(pipeline.md 阈值
|
|
35
|
+
>30% 生效 / 10-30% 部分 / <5% 未生效的直接度量)
|
|
36
|
+
top_stall_pct :主 pipe 空泡中最大单一类别占比(L0_STALL_DOMINANT 消费;
|
|
37
|
+
分类粒度:数据等待 / 同步 / 标量开销 / 结构性,先粗后细)
|
|
38
|
+
bubble_pct :主 pipe 空泡总占比(LATENCY/SYNC 可疑档的直接证据)
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
from __future__ import annotations
|
|
42
|
+
|
|
43
|
+
import argparse
|
|
44
|
+
import datetime
|
|
45
|
+
import json
|
|
46
|
+
import sys
|
|
47
|
+
from pathlib import Path
|
|
48
|
+
|
|
49
|
+
SCHEMA = "opstune.trace-bubble/1.0"
|
|
50
|
+
|
|
51
|
+
# cannsim PID/名称 → 统一 pipe 名(RVECSU 等细分归并 VECTOR;FIXP=FIXPIPE)
|
|
52
|
+
PIPE_ALIASES = {
|
|
53
|
+
"SCALAR": "SCALAR",
|
|
54
|
+
"SCALARLDST": "SCALARLDST",
|
|
55
|
+
"VEC": "VECTOR",
|
|
56
|
+
"VECTOR": "VECTOR",
|
|
57
|
+
"RVECSU": "VECTOR",
|
|
58
|
+
"RVECEX": "VECTOR",
|
|
59
|
+
"RVECLD": "VECTOR",
|
|
60
|
+
"RVECST": "VECTOR",
|
|
61
|
+
"RVECLP": "VECTOR",
|
|
62
|
+
"CUBE": "CUBE",
|
|
63
|
+
"MTE1": "MTE1",
|
|
64
|
+
"MTE2": "MTE2",
|
|
65
|
+
"MTE3": "MTE3",
|
|
66
|
+
"FIXP": "FIXPIPE",
|
|
67
|
+
"FIXPIPE": "FIXPIPE",
|
|
68
|
+
"FLOWCTRL": "FLOWCTRL",
|
|
69
|
+
"FLOWCONTROL": "FLOWCTRL",
|
|
70
|
+
"CACHEMISS": "CACHEMISS",
|
|
71
|
+
"ICACHELOAD": "CACHEMISS",
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
COMPUTE_PIPES = ("VECTOR", "CUBE") # 主计算 pipe(空泡归因对象)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Event:
|
|
78
|
+
__slots__ = ("ts", "end", "pipe")
|
|
79
|
+
|
|
80
|
+
def __init__(self, ts: float, dur: float, pipe: str):
|
|
81
|
+
self.ts = ts
|
|
82
|
+
self.end = ts + dur
|
|
83
|
+
self.pipe = pipe
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def load_events(trace_path: Path) -> tuple[list[Event], dict]:
|
|
87
|
+
"""读 Chrome Trace:duration 事件 + process_name 映射。返回 (events, pid_map)。"""
|
|
88
|
+
data = json.loads(trace_path.read_text(encoding="utf-8"))
|
|
89
|
+
events_raw = data.get("traceEvents", data if isinstance(data, list) else [])
|
|
90
|
+
pid_map: dict[int, str] = {}
|
|
91
|
+
events: list[Event] = []
|
|
92
|
+
for e in events_raw:
|
|
93
|
+
if not isinstance(e, dict):
|
|
94
|
+
continue
|
|
95
|
+
ph = e.get("ph")
|
|
96
|
+
if ph == "M" and e.get("name") == "process_name":
|
|
97
|
+
args = e.get("args", {}) or {}
|
|
98
|
+
name = str(args.get("name", "")).strip()
|
|
99
|
+
pid = e.get("pid")
|
|
100
|
+
if name and pid is not None:
|
|
101
|
+
pid_map[pid] = name
|
|
102
|
+
elif ph == "X":
|
|
103
|
+
pid = e.get("pid")
|
|
104
|
+
raw_name = str(e.get("name", "")).strip()
|
|
105
|
+
pipe = PIPE_ALIASES.get(pid_map.get(pid, ""), None) or PIPE_ALIASES.get(
|
|
106
|
+
raw_name.split("_")[0].upper(), None
|
|
107
|
+
)
|
|
108
|
+
if pipe is None:
|
|
109
|
+
# args 里找(部分 trace 把 pipe 放 args)
|
|
110
|
+
pipe = PIPE_ALIASES.get(
|
|
111
|
+
str((e.get("args") or {}).get("pipe", "")).upper()
|
|
112
|
+
)
|
|
113
|
+
if pipe and isinstance(e.get("dur"), (int, float)):
|
|
114
|
+
events.append(Event(float(e["ts"]), float(e["dur"]), pipe))
|
|
115
|
+
events.sort(key=lambda ev: ev.ts)
|
|
116
|
+
return events, pid_map
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def busy_intervals(events: list[Event], pipe: str) -> list[tuple[float, float]]:
|
|
120
|
+
"""某 pipe 的 busy 区间(合并重叠)。"""
|
|
121
|
+
ivs = sorted((ev.ts, ev.end) for ev in events if ev.pipe == pipe)
|
|
122
|
+
merged: list[tuple[float, float]] = []
|
|
123
|
+
for s, e in ivs:
|
|
124
|
+
if merged and s <= merged[-1][1]:
|
|
125
|
+
merged[-1] = (merged[-1][0], max(merged[-1][1], e))
|
|
126
|
+
else:
|
|
127
|
+
merged.append((s, e))
|
|
128
|
+
return merged
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def total_len(ivs: list[tuple[float, float]]) -> float:
|
|
132
|
+
return sum(e - s for s, e in ivs)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def intersect_len(a: list[tuple[float, float]], b: list[tuple[float, float]]) -> float:
|
|
136
|
+
"""两区间集交集总长(双指针)。"""
|
|
137
|
+
i = j = 0
|
|
138
|
+
total = 0.0
|
|
139
|
+
while i < len(a) and j < len(b):
|
|
140
|
+
s = max(a[i][0], b[j][0])
|
|
141
|
+
e = min(a[i][1], b[j][1])
|
|
142
|
+
if e > s:
|
|
143
|
+
total += e - s
|
|
144
|
+
if a[i][1] < b[j][1]:
|
|
145
|
+
i += 1
|
|
146
|
+
else:
|
|
147
|
+
j += 1
|
|
148
|
+
return total
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def union_len(a: list[tuple[float, float]], b: list[tuple[float, float]]) -> float:
|
|
152
|
+
return total_len(a) + total_len(b) - intersect_len(a, b)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def analyze_core(events: list[Event]) -> dict:
|
|
156
|
+
"""单核分析:主计算 pipe 的 overlap / bubble / 空泡分类。"""
|
|
157
|
+
pipes = {ev.pipe for ev in events}
|
|
158
|
+
main_pipe = next((p for p in COMPUTE_PIPES if p in pipes), None)
|
|
159
|
+
if main_pipe is None:
|
|
160
|
+
return {"error": "无 VECTOR/CUBE 计算事件(trace 只含其它 pipe?)"}
|
|
161
|
+
|
|
162
|
+
main_ivs = busy_intervals(events, main_pipe)
|
|
163
|
+
span = (events[-1].end - events[0].ts) if events else 0.0
|
|
164
|
+
main_busy = total_len(main_ivs)
|
|
165
|
+
bubble_pct = (span - main_busy) / span * 100 if span > 0 else None
|
|
166
|
+
|
|
167
|
+
# overlap:主 pipe vs MTE2(pipeline.md 阈值的直接度量对象)
|
|
168
|
+
mte2_ivs = busy_intervals(events, "MTE2")
|
|
169
|
+
ov_union = union_len(main_ivs, mte2_ivs)
|
|
170
|
+
overlap_pct = (
|
|
171
|
+
intersect_len(main_ivs, mte2_ivs) / ov_union * 100 if ov_union > 0 else None
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# 空泡分类(粗粒度四类,对齐空泡分析体系一级分类):
|
|
175
|
+
# 主 pipe 空泡窗口内看谁 busy → 归因
|
|
176
|
+
def coverage(ivs, s, e) -> float:
|
|
177
|
+
return intersect_len(ivs, [(s, e)]) / (e - s) if e > s else 0.0
|
|
178
|
+
|
|
179
|
+
other_pipes = [
|
|
180
|
+
p
|
|
181
|
+
for p in ("MTE2", "MTE3", "MTE1", "SCALAR", "SCALARLDST", "FIXPIPE")
|
|
182
|
+
if p in pipes
|
|
183
|
+
]
|
|
184
|
+
other_ivs = {p: busy_intervals(events, p) for p in other_pipes}
|
|
185
|
+
# 主 pipe gap 列表
|
|
186
|
+
gaps = []
|
|
187
|
+
for i in range(len(main_ivs) - 1):
|
|
188
|
+
gaps.append((main_ivs[i][1], main_ivs[i + 1][0]))
|
|
189
|
+
# 首尾也算(kernel 边界空泡)
|
|
190
|
+
if main_ivs:
|
|
191
|
+
gaps.append((events[0].ts, main_ivs[0][0]))
|
|
192
|
+
gaps.append((main_ivs[-1][1], events[-1].end))
|
|
193
|
+
cat_busy = {p: 0.0 for p in ("DATA", "SCALAR", "STRUCT", "IDLE")}
|
|
194
|
+
total_gap = 0.0
|
|
195
|
+
for s, e in gaps:
|
|
196
|
+
if e <= s:
|
|
197
|
+
continue
|
|
198
|
+
w = e - s
|
|
199
|
+
total_gap += w
|
|
200
|
+
best, best_cov = None, 0.0
|
|
201
|
+
for p in other_pipes:
|
|
202
|
+
cov = coverage(other_ivs[p], s, e)
|
|
203
|
+
if cov > best_cov:
|
|
204
|
+
best, best_cov = p, cov
|
|
205
|
+
if best in ("MTE2", "MTE3", "MTE1") and best_cov > 0.3:
|
|
206
|
+
cat_busy["DATA"] += w # 数据搬运等待
|
|
207
|
+
elif best in ("SCALAR", "SCALARLDST") and best_cov > 0.3:
|
|
208
|
+
cat_busy["SCALAR"] += w # 标量开销
|
|
209
|
+
elif best is not None and best_cov > 0.3:
|
|
210
|
+
cat_busy["STRUCT"] += w # 结构性/其它 pipe 活跃
|
|
211
|
+
else:
|
|
212
|
+
cat_busy["IDLE"] += w # 全 idle:同步/排空类
|
|
213
|
+
top_stall_pct = (
|
|
214
|
+
max((v / total_gap * 100 for v in cat_busy.values()), default=None)
|
|
215
|
+
if total_gap > 0
|
|
216
|
+
else None
|
|
217
|
+
)
|
|
218
|
+
top_stall_cat = max(cat_busy, key=cat_busy.get) if total_gap > 0 else None
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
"main_pipe": main_pipe,
|
|
222
|
+
"span": round(span, 1),
|
|
223
|
+
"main_busy_pct": round(main_busy / span * 100, 2) if span > 0 else None,
|
|
224
|
+
"bubble_pct": round(bubble_pct, 2) if bubble_pct is not None else None,
|
|
225
|
+
"overlap_pct": round(overlap_pct, 2) if overlap_pct is not None else None,
|
|
226
|
+
"bubble_categories_pct": {
|
|
227
|
+
k: round(v / total_gap * 100, 1) for k, v in cat_busy.items()
|
|
228
|
+
}
|
|
229
|
+
if total_gap > 0
|
|
230
|
+
else {},
|
|
231
|
+
"top_stall_pct": round(top_stall_pct, 1) if top_stall_pct is not None else None,
|
|
232
|
+
"top_stall_category": top_stall_cat,
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def verdict_scalar(core_results: dict[str, dict]) -> dict:
|
|
237
|
+
"""多核汇总 → verdict --scalar(跨核取 max——与木桶口径一致)。"""
|
|
238
|
+
oks = [r for r in core_results.values() if "error" not in r]
|
|
239
|
+
if not oks:
|
|
240
|
+
return {}
|
|
241
|
+
out = {}
|
|
242
|
+
ov = [r["overlap_pct"] for r in oks if r.get("overlap_pct") is not None]
|
|
243
|
+
ts = [r["top_stall_pct"] for r in oks if r.get("top_stall_pct") is not None]
|
|
244
|
+
bb = [r["bubble_pct"] for r in oks if r.get("bubble_pct") is not None]
|
|
245
|
+
if ov:
|
|
246
|
+
out["overlap_pct"] = max(ov)
|
|
247
|
+
if ts:
|
|
248
|
+
out["top_stall_pct"] = max(ts)
|
|
249
|
+
if bb:
|
|
250
|
+
out["bubble_pct"] = max(bb)
|
|
251
|
+
return out
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def main() -> int:
|
|
255
|
+
ap = argparse.ArgumentParser(
|
|
256
|
+
description="trace 空泡与重叠度分析(overlap/top_stall/bubble 标量生产者)"
|
|
257
|
+
)
|
|
258
|
+
ap.add_argument("--trace", default=None, help="单核 trace_core*.json")
|
|
259
|
+
ap.add_argument(
|
|
260
|
+
"--trace-dir", default=None, help="report 目录(全部 trace_core*.json 聚合)"
|
|
261
|
+
)
|
|
262
|
+
ap.add_argument(
|
|
263
|
+
"--scalar-out", default=None, help="scalars.json 输出(verdict --scalar 消费)"
|
|
264
|
+
)
|
|
265
|
+
args = ap.parse_args()
|
|
266
|
+
|
|
267
|
+
traces: list[Path] = []
|
|
268
|
+
if args.trace:
|
|
269
|
+
traces = [Path(args.trace)]
|
|
270
|
+
elif args.trace_dir:
|
|
271
|
+
traces = sorted(Path(args.trace_dir).glob("trace_core*.json"))
|
|
272
|
+
if not traces:
|
|
273
|
+
print(
|
|
274
|
+
"ERROR: 需要 --trace 或 --trace-dir(未发现 trace_core*.json)",
|
|
275
|
+
file=sys.stderr,
|
|
276
|
+
)
|
|
277
|
+
return 1
|
|
278
|
+
|
|
279
|
+
core_results: dict[str, dict] = {}
|
|
280
|
+
for t in traces:
|
|
281
|
+
try:
|
|
282
|
+
events, _ = load_events(t)
|
|
283
|
+
core_results[t.name] = analyze_core(events)
|
|
284
|
+
except (json.JSONDecodeError, OSError) as e:
|
|
285
|
+
core_results[t.name] = {"error": f"读取/解析失败:{e}"}
|
|
286
|
+
|
|
287
|
+
scalars = verdict_scalar(core_results)
|
|
288
|
+
result = {
|
|
289
|
+
"schema": SCHEMA,
|
|
290
|
+
"generated_at": datetime.datetime.now().isoformat(timespec="seconds"),
|
|
291
|
+
"traces": [str(t) for t in traces],
|
|
292
|
+
"per_core": core_results,
|
|
293
|
+
"scalars": scalars,
|
|
294
|
+
"scalar_str": ",".join(f"{k}={v}" for k, v in scalars.items()),
|
|
295
|
+
"interpretation": {
|
|
296
|
+
"overlap_pct": "主计算 pipe × MTE2 busy 交集/并集(pipeline.md:>30% 生效 /"
|
|
297
|
+
" 10-30% 部分 / <5% 未生效)",
|
|
298
|
+
"top_stall_pct": "空泡最大单一类别占比(L0_STALL_DOMINANT 消费;类别"
|
|
299
|
+
" DATA/SCALAR/STRUCT/IDLE)",
|
|
300
|
+
"bubble_pct": "主 pipe 空泡总占比(L1_LATENCY_SYNC_SUSPECT / "
|
|
301
|
+
"L1_SERIAL_NO_OVERLAP 的直接证据)",
|
|
302
|
+
},
|
|
303
|
+
"next": "python3 ../../ops-verdict/scripts/verdict.py --rules <L1/L0 规则包> "
|
|
304
|
+
"--scalar "
|
|
305
|
+
+ ",".join(f"{k}={v}" for k, v in scalars.items())
|
|
306
|
+
+ " -o verdict.json(trace 证据与 CSV 证据互补)",
|
|
307
|
+
}
|
|
308
|
+
if args.scalar_out:
|
|
309
|
+
out = Path(args.scalar_out)
|
|
310
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
311
|
+
out.write_text(
|
|
312
|
+
json.dumps(result, indent=2, ensure_ascii=False) + "\n", encoding="utf-8"
|
|
313
|
+
)
|
|
314
|
+
print(f"→ {out}")
|
|
315
|
+
print(
|
|
316
|
+
f"trace_bubble: {len(traces)} 核 → scalar: {result['scalar_str'] or '(无——检查 trace pipe 映射)'}"
|
|
317
|
+
)
|
|
318
|
+
for name, r in core_results.items():
|
|
319
|
+
if "error" in r:
|
|
320
|
+
print(f" ⚠ {name}: {r['error']}", file=sys.stderr)
|
|
321
|
+
else:
|
|
322
|
+
print(
|
|
323
|
+
f" {name}: main={r['main_pipe']} busy={r['main_busy_pct']}% "
|
|
324
|
+
f"bubble={r['bubble_pct']}% overlap(mte2)={r['overlap_pct']}% "
|
|
325
|
+
f"top_stall={r.get('top_stall_pct')}%({r.get('top_stall_category')})"
|
|
326
|
+
)
|
|
327
|
+
return 0
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
if __name__ == "__main__":
|
|
331
|
+
sys.exit(main())
|