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.
Files changed (183) hide show
  1. package/NOTICE.md +14 -0
  2. package/README.md +39 -2
  3. package/cordis.patch.yml +20 -0
  4. package/lib/client.js +4253 -0
  5. package/lib/host.js +2518 -0
  6. package/package.json +53 -4
  7. package/skills/tool-ops-tune/INSTALL.md +52 -0
  8. package/skills/tool-ops-tune/README.md +167 -0
  9. package/skills/tool-ops-tune/SKILL.md +93 -0
  10. package/skills/tool-ops-tune/agent/AGENTS.md +195 -0
  11. package/skills/tool-ops-tune/agent/agents/perf-implementer.md +68 -0
  12. package/skills/tool-ops-tune/agent/agents/perf-reviewer.md +86 -0
  13. package/skills/tool-ops-tune/agent/workflows/task-prompts.md +362 -0
  14. package/skills/tool-ops-tune/agent/workflows/troubleshooting.md +43 -0
  15. package/skills/tool-ops-tune/docs/figures/opstune-architecture.png +0 -0
  16. package/skills/tool-ops-tune/docs/figures/opstune-architecture.svg +253 -0
  17. package/skills/tool-ops-tune/docs/ops-tune-design.md +404 -0
  18. package/skills/tool-ops-tune/docs//347/224/250/344/276/213/346/236/204/345/273/272.md +714 -0
  19. package/skills/tool-ops-tune/docs//347/237/245/350/257/206/345/272/223/350/247/204/350/214/203.md +103 -0
  20. package/skills/tool-ops-tune/evals/evals.json +242 -0
  21. package/skills/tool-ops-tune/ops-collect/SKILL.md +146 -0
  22. package/skills/tool-ops-tune/ops-collect/references/tool-routing.md +86 -0
  23. package/skills/tool-ops-tune/ops-collect/scripts/collect_board.sh +444 -0
  24. package/skills/tool-ops-tune/ops-collect/scripts/collect_cases.py +368 -0
  25. package/skills/tool-ops-tune/ops-collect/scripts/collect_sim.sh +134 -0
  26. package/skills/tool-ops-tune/ops-collect/scripts/csv_to_db.py +314 -0
  27. package/skills/tool-ops-tune/ops-collect/scripts/db_bench.py +545 -0
  28. package/skills/tool-ops-tune/ops-collect/scripts/facts_bridge.py +1063 -0
  29. package/skills/tool-ops-tune/ops-collect/scripts/isolation_test.py +454 -0
  30. package/skills/tool-ops-tune/ops-collect/scripts/jsonl_to_cases.py +163 -0
  31. package/skills/tool-ops-tune/ops-family/SKILL.md +76 -0
  32. package/skills/tool-ops-tune/ops-family/references/broadcast/advanced_tiling.md +92 -0
  33. package/skills/tool-ops-tune/ops-family/references/broadcast/broadcast_design.md +160 -0
  34. package/skills/tool-ops-tune/ops-family/references/broadcast/code/broadcast_add_kernel.cpp +126 -0
  35. package/skills/tool-ops-tune/ops-family/references/broadcast/code/broadcast_add_tiling.cpp +144 -0
  36. package/skills/tool-ops-tune/ops-family/references/broadcast/code/broadcast_tiling_common.h +401 -0
  37. package/skills/tool-ops-tune/ops-family/references/broadcast/code/onedim_add_kernel.cpp +107 -0
  38. package/skills/tool-ops-tune/ops-family/references/broadcast/code/onedim_add_tiling.cpp +64 -0
  39. package/skills/tool-ops-tune/ops-family/references/broadcast/datacopypad_design.md +46 -0
  40. package/skills/tool-ops-tune/ops-family/references/broadcast/guide.md +14 -0
  41. package/skills/tool-ops-tune/ops-family/references/broadcast/nddma_design.md +53 -0
  42. package/skills/tool-ops-tune/ops-family/references/broadcast/onedim_design.md +114 -0
  43. package/skills/tool-ops-tune/ops-family/references/broadcast/ub_broadcast_design.md +67 -0
  44. package/skills/tool-ops-tune/ops-family/references/common/datacopy_optimization_design.md +351 -0
  45. package/skills/tool-ops-tune/ops-family/references/common/index.md +9 -0
  46. package/skills/tool-ops-tune/ops-family/references/common/tail_block_design.md +268 -0
  47. package/skills/tool-ops-tune/ops-family/references/common/timing_harness/index.md +38 -0
  48. package/skills/tool-ops-tune/ops-family/references/common/timing_harness/timing_harness_aclrt_event.cpp +199 -0
  49. package/skills/tool-ops-tune/ops-family/references/common/timing_harness/timing_harness_torch_event.py +130 -0
  50. package/skills/tool-ops-tune/ops-family/references/common/ub_resident_design.md +342 -0
  51. package/skills/tool-ops-tune/ops-family/references/conversion/guide.md +69 -0
  52. package/skills/tool-ops-tune/ops-family/references/conversion/index.md +4 -0
  53. package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_base.template +81 -0
  54. package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_big_dim.template +217 -0
  55. package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_cut_one_axis.template +336 -0
  56. package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_cut_two_axis.template +781 -0
  57. package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_n_last.template +340 -0
  58. package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_small_shape.template +321 -0
  59. package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_tensor_move.template +102 -0
  60. package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_transdata_5hd.template +480 -0
  61. package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_transdata_5hd_021axis.template +533 -0
  62. package/skills/tool-ops-tune/ops-family/references/conversion/templates/dav3510/transpose_with_gather.template +688 -0
  63. package/skills/tool-ops-tune/ops-family/references/conversion/templates/transpose_tiling_data.template +192 -0
  64. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_big_dim.md +220 -0
  65. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_cut_one_axis.md +175 -0
  66. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_cut_two_axis.md +177 -0
  67. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_fusion_design.md +398 -0
  68. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_gather.md +191 -0
  69. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_n_last.md +276 -0
  70. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_small_shape.md +315 -0
  71. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_tensor_move.md +203 -0
  72. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_tiling_data.md +176 -0
  73. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_vconv_021.md +206 -0
  74. package/skills/tool-ops-tune/ops-family/references/conversion/transpose_vconv_5hd.md +179 -0
  75. package/skills/tool-ops-tune/ops-family/references/elementwise/double_buffer_design.md +288 -0
  76. package/skills/tool-ops-tune/ops-family/references/elementwise/guide.md +46 -0
  77. package/skills/tool-ops-tune/ops-family/references/elementwise/index.md +10 -0
  78. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/CMakeLists.txt +131 -0
  79. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/README.md +55 -0
  80. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_extension/add_custom_torch.cpp +80 -0
  81. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_extension/ops.h +23 -0
  82. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_extension/register.cpp +30 -0
  83. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_host/add_custom.asc +149 -0
  84. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_host/data_utils.h +97 -0
  85. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_kernel/add_custom_kernel.asc +136 -0
  86. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/op_kernel/add_custom_tiling.h +31 -0
  87. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/run.sh +86 -0
  88. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/scripts/gen_data.py +70 -0
  89. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/scripts/golden.py +34 -0
  90. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/scripts/test_torch.py +99 -0
  91. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/add_custom/scripts/verify_result.py +56 -0
  92. package/skills/tool-ops-tune/ops-family/references/elementwise/templates/usage_guide.md +61 -0
  93. package/skills/tool-ops-tune/ops-family/references/elementwise/vector_efficiency_design.md +203 -0
  94. package/skills/tool-ops-tune/ops-family/references/fa/fa_mixed_kernel_design.md +174 -0
  95. package/skills/tool-ops-tune/ops-family/references/fa/fa_roofline_design.md +141 -0
  96. package/skills/tool-ops-tune/ops-family/references/fa/guide.md +87 -0
  97. package/skills/tool-ops-tune/ops-family/references/knowledge_gaps.json +56 -0
  98. package/skills/tool-ops-tune/ops-family/references/matmul/best-practices-guide.md +14 -0
  99. package/skills/tool-ops-tune/ops-family/references/matmul/fullload_design.md +344 -0
  100. package/skills/tool-ops-tune/ops-family/references/matmul/guide.md +52 -0
  101. package/skills/tool-ops-tune/ops-family/references/matmul/mte2_preload_design.md +320 -0
  102. package/skills/tool-ops-tune/ops-family/references/matmul/pingpong_design.md +254 -0
  103. package/skills/tool-ops-tune/ops-family/references/matmul/scale_coalescing_design.md +282 -0
  104. package/skills/tool-ops-tune/ops-family/references/matmul/streamk_design.md +374 -0
  105. package/skills/tool-ops-tune/ops-family/references/matmul/swat_design.md +423 -0
  106. package/skills/tool-ops-tune/ops-family/references/matmul/templates/matmul_basic_blaze.template +165 -0
  107. package/skills/tool-ops-tune/ops-family/references/matmul/templates/usage_guide.md +29 -0
  108. package/skills/tool-ops-tune/ops-family/references/mc2/best-practices-guide.md +43 -0
  109. package/skills/tool-ops-tune/ops-family/references/mc2/guide.md +42 -0
  110. package/skills/tool-ops-tune/ops-family/references/mc2/local_matmul_design.md +130 -0
  111. package/skills/tool-ops-tune/ops-family/references/mc2/pipeline_balancing_design.md +502 -0
  112. package/skills/tool-ops-tune/ops-family/references/reduce/guide.md +178 -0
  113. package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/kernel_utils.template +75 -0
  114. package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ar_full_load.template +429 -0
  115. package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ar_recompute.template +485 -0
  116. package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ar_small_r.template +348 -0
  117. package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ara_full_load.template +574 -0
  118. package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ara_online.template +324 -0
  119. package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_ara_recompute.template +436 -0
  120. package/skills/tool-ops-tune/ops-family/references/reduce/templates/dav310/softmax_v2_base.template +950 -0
  121. package/skills/tool-ops-tune/ops-family/references/reduce/templates/fused_attention_online_softmax_design.md +428 -0
  122. package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ar_full_load.md +137 -0
  123. package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ar_recompute.md +135 -0
  124. package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ar_small_r.md +122 -0
  125. package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ara_full_load.md +144 -0
  126. package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ara_online.md +185 -0
  127. package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_ara_recompute.md +163 -0
  128. package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_tiling.template +460 -0
  129. package/skills/tool-ops-tune/ops-family/references/reduce/templates/softmax_v2_tiling_data.template +278 -0
  130. package/skills/tool-ops-tune/ops-family/references/reduce/templates/state_resident_design.md +337 -0
  131. package/skills/tool-ops-tune/ops-family/references/reduce/templates/usage_guide.md +253 -0
  132. package/skills/tool-ops-tune/ops-family/references/scalar/coding_principles.md +476 -0
  133. package/skills/tool-ops-tune/ops-family/references/scalar/conv_scalar.md +163 -0
  134. package/skills/tool-ops-tune/ops-family/references/scalar/guide.md +30 -0
  135. package/skills/tool-ops-tune/ops-family/references/simt/guide.md +91 -0
  136. package/skills/tool-ops-tune/ops-family/references/simt/optimization-guide.md +110 -0
  137. package/skills/tool-ops-tune/ops-family/references/sort/guide.md +83 -0
  138. package/skills/tool-ops-tune/ops-family/references/sort/radix_sort.md +354 -0
  139. package/skills/tool-ops-tune/ops-family/scripts/family_asset_audit.py +68 -0
  140. package/skills/tool-ops-tune/ops-family/scripts/tiling_candidates.py +419 -0
  141. package/skills/tool-ops-tune/ops-mechanism/SKILL.md +23 -0
  142. package/skills/tool-ops-tune/ops-mechanism/cases/ascendc/case_groupedmatmul_pipeline.md +23 -0
  143. package/skills/tool-ops-tune/ops-mechanism/cases/ascendc/case_triton_atomic_revert.md +19 -0
  144. package/skills/tool-ops-tune/ops-mechanism/cases/mc2/case_mc2_fusion.md +19 -0
  145. package/skills/tool-ops-tune/ops-mechanism/references/optimize/api-usage.md +70 -0
  146. package/skills/tool-ops-tune/ops-mechanism/references/optimize/ascendc-regbase-vf.md +45 -0
  147. package/skills/tool-ops-tune/ops-mechanism/references/optimize/ascendc-tiling.md +51 -0
  148. package/skills/tool-ops-tune/ops-mechanism/references/optimize/data-copy.md +67 -0
  149. package/skills/tool-ops-tune/ops-mechanism/references/optimize/index.md +45 -0
  150. package/skills/tool-ops-tune/ops-mechanism/references/optimize/mc2-balancing.md +77 -0
  151. package/skills/tool-ops-tune/ops-mechanism/references/optimize/mc2.md +103 -0
  152. package/skills/tool-ops-tune/ops-mechanism/references/optimize/memory-hierarchy.md +40 -0
  153. package/skills/tool-ops-tune/ops-mechanism/references/optimize/pipeline.md +95 -0
  154. package/skills/tool-ops-tune/ops-mechanism/scripts/case_backfill.py +170 -0
  155. package/skills/tool-ops-tune/ops-mechanism/scripts/log_gap.py +145 -0
  156. package/skills/tool-ops-tune/ops-mechanism/scripts/mc2_search.py +367 -0
  157. package/skills/tool-ops-tune/ops-report/SKILL.md +77 -0
  158. package/skills/tool-ops-tune/ops-verdict/evals/run_evals.py +837 -0
  159. package/skills/tool-ops-tune/ops-verdict/evals/smoke/install-hooks.sh +65 -0
  160. package/skills/tool-ops-tune/ops-verdict/evals/smoke/run_smoke.sh +405 -0
  161. package/skills/tool-ops-tune/ops-verdict/fixtures/core_tail_a5.csv +25 -0
  162. package/skills/tool-ops-tune/ops-verdict/fixtures/few_cores_a5.csv +5 -0
  163. package/skills/tool-ops-tune/ops-verdict/fixtures/mte2_bound_a2.csv +17 -0
  164. package/skills/tool-ops-tune/ops-verdict/fixtures/multi_kernel_mix_a5.csv +7 -0
  165. package/skills/tool-ops-tune/ops-verdict/fixtures/no_bound_a5.csv +9 -0
  166. package/skills/tool-ops-tune/ops-verdict/fixtures/serial_no_overlap_a2.csv +9 -0
  167. package/skills/tool-ops-tune/ops-verdict/fixtures/vec_bound_a5.csv +9 -0
  168. package/skills/tool-ops-tune/ops-verdict/references/io-contracts.md +94 -0
  169. package/skills/tool-ops-tune/ops-verdict/references/rule-schema.md +130 -0
  170. package/skills/tool-ops-tune/ops-verdict/references/scope-schema.md +61 -0
  171. package/skills/tool-ops-tune/ops-verdict/references/soc-spec.yaml +140 -0
  172. package/skills/tool-ops-tune/ops-verdict/rules/L0-instruction.yaml +67 -0
  173. package/skills/tool-ops-tune/ops-verdict/rules/L1-single-core.yaml +316 -0
  174. package/skills/tool-ops-tune/ops-verdict/rules/L2-inter-core.yaml +173 -0
  175. package/skills/tool-ops-tune/ops-verdict/rules/L3-inter-card.yaml +156 -0
  176. package/skills/tool-ops-tune/ops-verdict/scripts/batch_pipeline.py +444 -0
  177. package/skills/tool-ops-tune/ops-verdict/scripts/calibrate.py +249 -0
  178. package/skills/tool-ops-tune/ops-verdict/scripts/delta_compare.py +244 -0
  179. package/skills/tool-ops-tune/ops-verdict/scripts/render_html.py +274 -0
  180. package/skills/tool-ops-tune/ops-verdict/scripts/snapshot.py +200 -0
  181. package/skills/tool-ops-tune/ops-verdict/scripts/trace_bubble.py +331 -0
  182. package/skills/tool-ops-tune/ops-verdict/scripts/verdict.py +1072 -0
  183. package/skills/tool-ops-tune/scripts/diff_audit.py +281 -0
@@ -0,0 +1,368 @@
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
+ """collect_cases.py — 逐 case 采集编排 + 标杆双路径(REVIEW2 G1+G5 / 整改 P0-1)
13
+
14
+ 设计对齐:
15
+ - A1 全量 case 铁律(>20 取前 20 逐 case 覆盖)此前靠主 agent 手工串
16
+ 20×N 次 collect_board.sh 再手拼 perf CSV——三类高频错误(漏 case 违 A1、
17
+ 口径漂移触发 delta_compare exit 2 后双侧重采、目录混乱)全在这一步。
18
+ - baseline_kind=system 此前只是 snapshot 的一个字段,无采集编排——「比标杆
19
+ 快多少」(用户终极问题)不可答。
20
+ - 本脚本把两者合一:输入 cases.csv + exe,逐 case × 逐 variant(内建
21
+ {custom, system} 双路径)调 collect_board.sh,产出 batch_pipeline.py
22
+ 直接可吃的 perf_data.csv + 逐 case manifest 归档。
23
+
24
+ 用法:
25
+ # 单算子(自前后对比):
26
+ python3 collect_cases.py --cases cases.csv --exe ./build/gelu_demo \\
27
+ --mode quick --output ./collect_out
28
+
29
+ # 标杆双路径(cases.csv 扩展列 ref_impl = 标杆可执行/描述):
30
+ python3 collect_cases.py --cases cases.csv --exe ./build/gelu_demo \\
31
+ --ref-exe "python3 ref/gelu_ref.py" --mode quick --output ./collect_out
32
+
33
+ # 定向补采(只重采指定 case):
34
+ python3 collect_cases.py --cases cases.csv --exe ./build/gelu_demo \\
35
+ --mode quick --output ./collect_out --cases-subset c03,c07
36
+
37
+ 产物布局({output}/{case_id}/{variant}/ 每目录一份 collection_manifest):
38
+ collect_out/
39
+ perf_data.csv ← batch_pipeline --perf 直接输入
40
+ collect_summary.json ← 逐 case × variant 状态(伪 Green 防护)
41
+ c01/custom/collection_manifest.json
42
+ c01/system/collection_manifest.json
43
+ ...
44
+
45
+ 纪律继承:
46
+ - case 间串行、同卡同口径(device 由 collect_board.sh pick_device 统一选择
47
+ 并注入 ASCEND_RT_VISIBLE_DEVICES);
48
+ - 已有 manifest 的目录跳过(防重采闸门同款——补采用 --cases-subset 指定);
49
+ - 采集失败不静默:逐条记入 collect_summary.json 的 failed 列表。
50
+ """
51
+
52
+ from __future__ import annotations
53
+
54
+ import argparse
55
+ import csv
56
+ import json
57
+ import subprocess
58
+ import sys
59
+ import time
60
+ from pathlib import Path
61
+
62
+ SCHEMA = "opstune.collect-cases/1.0"
63
+ HERE = Path(__file__).resolve().parent
64
+ COLLECT_BOARD = HERE / "collect_board.sh"
65
+
66
+
67
+ def load_cases(path: str) -> list[dict]:
68
+ with open(path, encoding="utf-8-sig") as f:
69
+ rows = list(csv.DictReader(f))
70
+ for r in rows:
71
+ if not r.get("case_id") or not r.get("shape") or not r.get("dtype"):
72
+ raise SystemExit(f"ERROR: cases.csv 行缺必需列(case_id/shape/dtype): {r}")
73
+ return rows
74
+
75
+
76
+ def run_collect(
77
+ exe: str,
78
+ args_str: str,
79
+ mode: str,
80
+ out_dir: Path,
81
+ timeout: int,
82
+ kernel_name: str | None,
83
+ ) -> dict:
84
+ """调 collect_board.sh 一次;返回 {status, manifest, task_duration_us}。"""
85
+ cmd = [
86
+ "bash",
87
+ str(COLLECT_BOARD),
88
+ "--exe",
89
+ exe,
90
+ "--mode",
91
+ mode,
92
+ "--output",
93
+ str(out_dir),
94
+ "--timeout",
95
+ str(timeout),
96
+ ]
97
+ if args_str:
98
+ cmd += ["--args", args_str]
99
+ if kernel_name:
100
+ cmd += ["--kernel-name", kernel_name]
101
+ proc = subprocess.run(cmd, capture_output=True, text=True)
102
+ manifest_path = out_dir / "collection_manifest.json"
103
+ manifest = None
104
+ if manifest_path.exists():
105
+ manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
106
+ if proc.returncode != 0:
107
+ return {
108
+ "status": "failed",
109
+ "rc": proc.returncode,
110
+ "stderr": proc.stderr[-400:],
111
+ "manifest": manifest,
112
+ }
113
+ if manifest is None:
114
+ return {
115
+ "status": "failed",
116
+ "rc": proc.returncode,
117
+ "stderr": "collect_board 退出 0 但无 manifest",
118
+ "manifest": None,
119
+ }
120
+ blocks_ok = all(b.get("status") == "ok" for b in manifest.get("blocks", []))
121
+ return {
122
+ "status": "ok" if blocks_ok else "partial",
123
+ "rc": 0,
124
+ "stderr": "",
125
+ "manifest": manifest,
126
+ }
127
+
128
+
129
+ def task_duration_of(manifest: dict | None, out_dir: Path) -> float | None:
130
+ """从采集产物提取 Task Duration 均值(quick/standard 模式的 op_summary)。"""
131
+ if manifest is None:
132
+ return None
133
+ # 快路径:timing 模式 result.json(P0-2 产物)
134
+ timing_json = out_dir / "result.json"
135
+ if timing_json.exists():
136
+ try:
137
+ t = json.loads(timing_json.read_text(encoding="utf-8"))
138
+ if t.get("kernel_avg_us") is not None:
139
+ return float(t["kernel_avg_us"])
140
+ except (json.JSONDecodeError, ValueError):
141
+ pass
142
+ # op_summary 路径:全部 op_summary Task Duration 均值(单 kernel 语义)
143
+ vals: list[float] = []
144
+ for p in sorted(out_dir.rglob("op_summary_*.csv")):
145
+ with open(p, encoding="utf-8-sig", errors="replace") as f:
146
+ for row in csv.DictReader(f):
147
+ v = row.get("Task Duration(us)") or row.get("Task Duration")
148
+ if v:
149
+ try:
150
+ vals.append(float(str(v).strip()))
151
+ except ValueError:
152
+ pass
153
+ return (sum(vals) / len(vals)) if vals else None
154
+
155
+
156
+ def main() -> int:
157
+ ap = argparse.ArgumentParser(
158
+ description="逐 case 采集编排 + 标杆双路径(A1 铁律工具化)"
159
+ )
160
+ ap.add_argument(
161
+ "--cases",
162
+ required=True,
163
+ help="cases.csv(case_id/shape/dtype/attrs[/ref_impl])",
164
+ )
165
+ ap.add_argument("--exe", required=True, help="被测可执行文件(custom 路径)")
166
+ ap.add_argument(
167
+ "--exe-args",
168
+ default="",
169
+ help="exe 追加参数模板({shape} {dtype} {attrs} 占位符逐 case 替换)",
170
+ )
171
+ ap.add_argument(
172
+ "--ref-exe",
173
+ default=None,
174
+ help="标杆路径/命令(system 路径;缺省无标杆,仅 custom 单路径)",
175
+ )
176
+ ap.add_argument(
177
+ "--ref-exe-args", default=None, help="标杆参数模板(缺省同 --exe-args)"
178
+ )
179
+ ap.add_argument(
180
+ "--mode",
181
+ default="quick",
182
+ choices=["quick", "standard", "timing"],
183
+ help="采集模式:quick=时间复核 / standard=7 组指标(判定输入)/ timing=event harness",
184
+ )
185
+ ap.add_argument("-o", "--output", required=True, help="采集根目录")
186
+ ap.add_argument("--timeout", type=int, default=1800)
187
+ ap.add_argument(
188
+ "--kernel-name", default=None, help="多 kernel 程序过滤(透传 collect_board)"
189
+ )
190
+ ap.add_argument(
191
+ "--max-cases",
192
+ type=int,
193
+ default=20,
194
+ help="case 截断上限(A1 铁律 >20 取前 20;0 = 不截断)",
195
+ )
196
+ ap.add_argument(
197
+ "--cases-subset",
198
+ default="",
199
+ help="定向补采:逗号分隔 case_id 列表(只采这些 case)",
200
+ )
201
+ args = ap.parse_args()
202
+
203
+ cases = load_cases(args.cases)
204
+ # 定向补采先于截断过滤:subset 指定的 case 必须全量可见(否则 >max-cases
205
+ # 工程的定向补采会误报「无匹配」或漏采——检视 #8 修复)
206
+ if args.cases_subset:
207
+ wanted = {c.strip() for c in args.cases_subset.split(",") if c.strip()}
208
+ cases = [c for c in cases if c["case_id"] in wanted]
209
+ if not cases:
210
+ print(
211
+ f"ERROR: --cases-subset 无匹配 case({sorted(wanted)})",
212
+ file=sys.stderr,
213
+ )
214
+ return 1
215
+ elif args.max_cases and len(cases) > args.max_cases:
216
+ cases = cases[: args.max_cases]
217
+ print(
218
+ f"WARN: cases 截断为前 {args.max_cases}(A1 铁律,报告必须告知用户)",
219
+ file=sys.stderr,
220
+ )
221
+
222
+ variants = [("custom", args.exe, args.exe_args)]
223
+ if args.ref_exe:
224
+ variants.append(
225
+ (
226
+ "system",
227
+ args.ref_exe,
228
+ args.ref_exe_args if args.ref_exe_args is not None else args.exe_args,
229
+ )
230
+ )
231
+
232
+ out_root = Path(args.output)
233
+ out_root.mkdir(parents=True, exist_ok=True)
234
+
235
+ # ---- 逐 case × 逐 variant 串行采集(同卡同口径;已有 manifest 跳过)----
236
+ perf_rows: list[dict] = []
237
+ status_rows: list[dict] = []
238
+ t0 = time.time()
239
+ for case in cases:
240
+ cid = case["case_id"]
241
+ tpl_vars = {
242
+ "shape": case["shape"],
243
+ "dtype": case["dtype"],
244
+ "attrs": case.get("attrs", ""),
245
+ "case_id": cid,
246
+ }
247
+ for vname, exe, args_tpl in variants:
248
+ if (
249
+ vname == "system"
250
+ and not case.get("ref_impl", "").strip()
251
+ and args_tpl == ""
252
+ ):
253
+ # cases.csv 无 ref_impl 列且未给参数模板:标杆跑与 custom 相同命令无意义
254
+ if not case.get("ref_impl"):
255
+ status_rows.append(
256
+ {
257
+ "case_id": cid,
258
+ "variant": vname,
259
+ "status": "skipped",
260
+ "reason": "cases.csv 无 ref_impl(该 case 无标杆定义)",
261
+ }
262
+ )
263
+ continue
264
+ vdir = out_root / cid / vname
265
+ if (vdir / "collection_manifest.json").exists():
266
+ # 复用分支读取已有 manifest(传 None 会被 task_duration_of 短路
267
+ # 恒返 None → 已采 case 从对比矩阵消失——检视 #11 修复)
268
+ dur = task_duration_of(
269
+ json.loads(
270
+ (vdir / "collection_manifest.json").read_text(encoding="utf-8")
271
+ ),
272
+ vdir,
273
+ )
274
+ perf_rows.append(
275
+ {
276
+ "case_id": cid,
277
+ "variant": vname,
278
+ "kernel_avg_us": dur if dur else "",
279
+ "precision": "",
280
+ }
281
+ )
282
+ status_rows.append(
283
+ {
284
+ "case_id": cid,
285
+ "variant": vname,
286
+ "status": "reused",
287
+ "reason": "已有 manifest(防重采闸门),直接复用",
288
+ }
289
+ )
290
+ continue
291
+ exe_args = args_tpl.format(**tpl_vars) if args_tpl else ""
292
+ res = run_collect(
293
+ exe, exe_args, args.mode, vdir, args.timeout, args.kernel_name
294
+ )
295
+ dur = task_duration_of(res.get("manifest"), vdir)
296
+ perf_rows.append(
297
+ {
298
+ "case_id": cid,
299
+ "variant": vname,
300
+ "kernel_avg_us": dur if dur is not None else "",
301
+ "precision": "",
302
+ }
303
+ )
304
+ status_rows.append(
305
+ {
306
+ "case_id": cid,
307
+ "variant": vname,
308
+ "status": res["status"],
309
+ "reason": res.get("stderr", "")[:200]
310
+ if res["status"] != "ok"
311
+ else "",
312
+ }
313
+ )
314
+ mark = res["status"].upper()
315
+ print(
316
+ f" [{mark:>7}] {cid}/{vname}"
317
+ f"{' task_duration=%.1fus' % dur if dur else ''}"
318
+ )
319
+
320
+ # ---- perf_data.csv(batch_pipeline --perf 直接输入格式)----
321
+ perf_path = out_root / "perf_data.csv"
322
+ with open(perf_path, "w", encoding="utf-8", newline="") as f:
323
+ w = csv.DictWriter(
324
+ f, fieldnames=["case_id", "variant", "kernel_avg_us", "precision"]
325
+ )
326
+ w.writeheader()
327
+ for r in perf_rows:
328
+ w.writerow(
329
+ {**r, "precision": r["precision"] or "pass"}
330
+ ) # 精度列由 Phase 4 实施后填真值
331
+
332
+ # ---- collect_summary.json(伪 Green 防护:failed/partial 如实呈现)----
333
+ failed = [s for s in status_rows if s["status"] in ("failed", "partial")]
334
+ summary = {
335
+ "schema": SCHEMA,
336
+ "cases": len(cases),
337
+ "variants": [v for v, _, _ in variants],
338
+ "mode": args.mode,
339
+ "elapsed_s": round(time.time() - t0, 1),
340
+ "ok": len([s for s in status_rows if s["status"] in ("ok", "reused")]),
341
+ "failed_or_partial": failed,
342
+ "rows": status_rows,
343
+ "next": (
344
+ f"python3 ../ops-verdict/scripts/batch_pipeline.py "
345
+ f"--from-collect {out_root} ...(直连模式,无需手拼 CSV)"
346
+ ),
347
+ }
348
+ (out_root / "collect_summary.json").write_text(
349
+ json.dumps(summary, indent=2, ensure_ascii=False) + "\n", encoding="utf-8"
350
+ )
351
+
352
+ print(
353
+ f"perf_data.csv → {perf_path}({len(perf_rows)} 行 = {len(cases)} case × {len(variants)} variant)"
354
+ )
355
+ if failed:
356
+ print(
357
+ f"⚠ {len(failed)} 项 failed/partial(详见 collect_summary.json)——伪 Green 防护:不得从清单抹掉",
358
+ file=sys.stderr,
359
+ )
360
+ print(
361
+ f"下一步:batch_pipeline.py --from-collect {out_root} --baseline-variant "
362
+ f"{'system' if len(variants) > 1 else 'custom'} ..."
363
+ )
364
+ return 1 if any(s["status"] == "failed" for s in status_rows) else 0
365
+
366
+
367
+ if __name__ == "__main__":
368
+ sys.exit(main())
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env bash
2
+ # -----------------------------------------------------------------------------------------------------------
3
+ # Copyright (c) 2026 Huawei Technologies Co., Ltd.
4
+ # This program is free software, you can redistribute it and/or modify it under the terms and conditions of
5
+ # CANN Open Software License Agreement Version 2.0 (the "License").
6
+ # Please refer to the License for details. You may not use this file except in compliance with the License.
7
+ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
8
+ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
9
+ # See LICENSE in the root of the software repository for the full text of the License.
10
+ # -----------------------------------------------------------------------------------------------------------
11
+ # collect_sim.sh — 仿真路径采集编排(REVIEW2 G7 / 反馈 P1-1①)
12
+ #
13
+ # 设计对齐:
14
+ # - tool-routing 决策树④「无卡 / 指令级下钻 → cannsim(仅 A5 单卡 AI Core)」
15
+ # 此前只有决策树一行文字,全仓无 cannsim 编排脚本——mode=sim /
16
+ # timing_method=sim 空转(REVIEW2 G7 定性)。
17
+ # - 本脚本补编排:cannsim record(精度+性能仿真)→ report(trace 生成)→
18
+ # 归档进 collection_manifest(mode=sim 块),下游 trace_bubble.py /
19
+ # verdict.py 消费同一条链。
20
+ #
21
+ # 用法:
22
+ # bash collect_sim.sh --exe ./build/demo --args "8448 4096 4096" \
23
+ # --soc-version Ascend950 --output ./prof/sim_base
24
+ # 可选:--timeout <秒>(默认 1800);--cores <0 | 0-2 | all>(report 核范围,默认 0)
25
+ #
26
+ # 产物布局(归档进 manifest,与上板采集同构):
27
+ # {output}/cannsim_<timestamp>_<app>/ cannsim 原始输出(cannsim.log 等)
28
+ # {output}/report/ cannsim report 输出(trace_core*.json)
29
+ # {output}/collection_manifest.json mode=sim 的采集块真源
30
+ #
31
+ # 门禁(先探测再选命令,与 collect_board.sh 同款纪律):
32
+ # cannsim 不可用 → 明确报错(不静默降级);--soc-version 必填(仿真目标芯片)。
33
+
34
+ set -euo pipefail
35
+
36
+ EXE=""
37
+ EXE_ARGS=""
38
+ SOC_VERSION=""
39
+ OUTPUT="./prof/sim_run"
40
+ CORES="0"
41
+ TIMEOUT=1800
42
+
43
+ usage() {
44
+ sed -n '2,22p' "$0"; exit 1
45
+ }
46
+
47
+ while [[ $# -gt 0 ]]; do
48
+ case "$1" in
49
+ --exe) EXE="$2"; shift 2 ;;
50
+ --args) EXE_ARGS="$2"; shift 2 ;;
51
+ --soc-version) SOC_VERSION="$2"; shift 2 ;;
52
+ --output) OUTPUT="$2"; shift 2 ;;
53
+ --cores) CORES="$2"; shift 2 ;;
54
+ --timeout) TIMEOUT="$2"; shift 2 ;;
55
+ -h|--help) usage ;;
56
+ *) echo "unknown arg: $1" >&2; usage ;;
57
+ esac
58
+ done
59
+
60
+ [[ -x "$EXE" || -f "$EXE" ]] || { echo "ERROR: --exe 不存在或不可执行: $EXE" >&2; exit 1; }
61
+ [[ -n "$SOC_VERSION" ]] || { echo "ERROR: --soc-version 必填(仿真目标芯片,如 Ascend950)" >&2; exit 1; }
62
+
63
+ # ---- 工具探测(cannsim 是 python 入口,PATH 或 CANN python 路径均可)----
64
+ CANNBIN=""
65
+ if command -v cannsim >/dev/null 2>&1; then
66
+ CANNBIN="cannsim"
67
+ elif [[ -n "${ASCEND_HOME_PATH:-}" && -x "${ASCEND_HOME_PATH}/bin/cannsim" ]]; then
68
+ CANNBIN="${ASCEND_HOME_PATH}/bin/cannsim"
69
+ else
70
+ echo "ERROR: cannsim 不可用。检查 CANN 安装(simulation 组件)与 source set_env.sh。" >&2
71
+ echo " cannsim 仅 A5 单卡 AI Core 仿真;MC²/HCCL 不支持(tool-routing 决策树④)。" >&2
72
+ exit 1
73
+ fi
74
+ echo "[probe] cannsim: $CANNBIN"
75
+
76
+ mkdir -p "$OUTPUT"
77
+ MANIFEST="$OUTPUT/collection_manifest.json"
78
+ if [[ -f "$MANIFEST" ]]; then
79
+ echo "ERROR: $MANIFEST 已存在 —— 该目录只允许解析,禁止重复采集(与上板同款闸门)。" >&2
80
+ exit 2
81
+ fi
82
+
83
+ BLOCKS=()
84
+ record_block() { # name status path note
85
+ BLOCKS+=("$(python3 -c 'import json,sys; print(json.dumps({"name": sys.argv[1], "status": sys.argv[2], "path": sys.argv[3], "note": sys.argv[4]}, ensure_ascii=False))' "$1" "$2" "$3" "$4")")
86
+ }
87
+
88
+ # ---- cannsim record(精度+性能仿真,-g 顺带生成 report)----
89
+ echo "[sim] cannsim record(soc=$SOC_VERSION)…"
90
+ if timeout "$TIMEOUT" "$CANNBIN" record "$EXE" -s "$SOC_VERSION" -o "$OUTPUT" -g \
91
+ ${EXE_ARGS:+-u "$EXE_ARGS"} > "$OUTPUT/cannsim_record.log" 2>&1; then
92
+ # cannsim 输出目录形态:{output}/cannsim_<timestamp>_<appname>/
93
+ # 只匹配目录(-d 投影;cannsim_record.log 同样命中 cannsim_* 通配且 mtime
94
+ # 更晚,会把 head -1 顶成日志文件——检视 #15 修复)
95
+ SIM_DIR=$(find "$OUTPUT" -maxdepth 1 -type d -name 'cannsim_*' 2>/dev/null \
96
+ | sort -r | head -1 || true)
97
+ if [[ -n "${SIM_DIR:-}" && -d "$SIM_DIR/report" ]]; then
98
+ record_block "cannsim_record" ok "$SIM_DIR" "soc=$SOC_VERSION args=${EXE_ARGS:-<none>}"
99
+ record_block "cannsim_report" ok "$SIM_DIR/report" "trace_core*.json(Chrome Trace Format)"
100
+ else
101
+ record_block "cannsim_record" partial "$OUTPUT" \
102
+ "record 退出 0 但未发现 cannsim_*/report 目录(检查 cannsim_record.log)"
103
+ fi
104
+ else
105
+ rc=$?
106
+ record_block "cannsim_record" failed "$OUTPUT" \
107
+ "cannsim record 退出非 0(rc=$rc),日志: $OUTPUT/cannsim_record.log"
108
+ fi
109
+
110
+ # ---- manifest 落盘(mode=sim;与上板同构,下游 facts_bridge/verdict 同链消费)----
111
+ BLOCKS_JSON=$(printf '\x1f%s' "${BLOCKS[@]:-}")
112
+ BLOCKS_JSON=${BLOCKS_JSON:1}
113
+ python3 - "$MANIFEST" "$EXE" "$EXE_ARGS" "$SOC_VERSION" "$CORES" "$BLOCKS_JSON" <<'PYEOF'
114
+ import json, sys, datetime
115
+ manifest = {
116
+ "schema": "opstune.collection/1.0",
117
+ "generated_at": datetime.datetime.now().isoformat(timespec="seconds"),
118
+ "mode": "sim",
119
+ "exe": sys.argv[2],
120
+ "args": sys.argv[3],
121
+ "soc_version": sys.argv[4],
122
+ "report_cores": sys.argv[5],
123
+ "blocks": [json.loads(b) for b in sys.argv[6].split("\x1f")] if sys.argv[6] else [],
124
+ }
125
+ with open(sys.argv[1], "w", encoding="utf-8") as f:
126
+ json.dump(manifest, f, ensure_ascii=False, indent=2)
127
+ f.write("\n")
128
+ PYEOF
129
+
130
+ echo "[done] manifest → $MANIFEST"
131
+ echo "下一步:"
132
+ echo " 1. 空泡/重叠度分析:python3 ../ops-verdict/scripts/trace_bubble.py --trace <report>/trace_core0.json"
133
+ echo " 2. 仿真口径快照:snapshot.py --mode sim --timing-method sim"
134
+ echo " 3. 注意:sim 数字与上板数字禁止混比(snapshot HARD 口径;timing_method=sim 专用)"