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,170 @@
|
|
|
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
|
+
"""case_backfill.py — E 级案例回灌草稿生成(REVIEW2 G9 / 反馈 P1-2 ②)
|
|
13
|
+
|
|
14
|
+
设计对齐:
|
|
15
|
+
- io-contracts.md 已冻结 case_candidate.json 契约(opstune.case-candidate/1.0,
|
|
16
|
+
Step 5 产出,「经评审后入库」),但案例卡的入库一直是人工从 JSON 誊写
|
|
17
|
+
Markdown——格式漂移、警示列漏写、证据等级漏标都是人工誊写的常态错误。
|
|
18
|
+
- 本脚本把候选 JSON 转成 ops-mechanism/cases/ 案例卡 Markdown **草稿**:
|
|
19
|
+
固定字段全带上 + E 级标注 + 警示列模板 + 「评审后入库」水印——仍是草稿,
|
|
20
|
+
评审与合入是人工动作(与 calibrate.py 同款纪律:脚本不替代评审)。
|
|
21
|
+
|
|
22
|
+
用法:
|
|
23
|
+
python3 case_backfill.py --input tuning_artifacts/gelu/case_candidate.json \
|
|
24
|
+
--cases-dir ../cases -o cases/ascendc/case_gelu_ub_fusion.draft.md
|
|
25
|
+
# 多条目输入(数组形态)也支持:逐条产出 draft
|
|
26
|
+
|
|
27
|
+
输出草稿字段(对齐 ops-mechanism SKILL.md 案例卡 schema):
|
|
28
|
+
算子类别 / DSL / 类型(PR|非PR) / 来源可信度(E 级) / 来源链接 + 验证日期 /
|
|
29
|
+
瓶颈证据 / 优化机制 / 原文性能数字 / 适用范围与警示
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from __future__ import annotations
|
|
33
|
+
|
|
34
|
+
import argparse
|
|
35
|
+
import datetime
|
|
36
|
+
import json
|
|
37
|
+
import sys
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def as_candidates(data) -> list[dict]:
|
|
42
|
+
"""单条目 dict 或 entries 数组都接受。"""
|
|
43
|
+
if isinstance(data, list):
|
|
44
|
+
return data
|
|
45
|
+
if isinstance(data, dict):
|
|
46
|
+
if "entries" in data and isinstance(data["entries"], list):
|
|
47
|
+
return data["entries"]
|
|
48
|
+
return [data]
|
|
49
|
+
return []
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def scene_fp_text(fp: dict) -> str:
|
|
53
|
+
if not isinstance(fp, dict):
|
|
54
|
+
return str(fp)
|
|
55
|
+
keys = ("soc", "shape", "dtype", "format", "cann_version", "timing_method")
|
|
56
|
+
return " / ".join(f"{k}={fp[k]}" for k in keys if fp.get(k) is not None) or str(fp)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def draft_md(c: dict, idx: int) -> str:
|
|
60
|
+
fp = c.get("scene_fingerprint", {})
|
|
61
|
+
measured = c.get("speedup_measured")
|
|
62
|
+
est = c.get("speedup_est")
|
|
63
|
+
est_text = (
|
|
64
|
+
f"[{est[0]}, {est[1]}]"
|
|
65
|
+
if isinstance(est, (list, tuple)) and len(est) == 2
|
|
66
|
+
else str(est)
|
|
67
|
+
)
|
|
68
|
+
rollback = c.get("rollback_happened")
|
|
69
|
+
lines = [
|
|
70
|
+
f"# 案例卡(草稿 {idx}):{c.get('operator', '?')} — {c.get('mechanism', '?')}",
|
|
71
|
+
"",
|
|
72
|
+
"> ⚠️ **E 级回灌草稿——评审后入库**:本文件由 case_backfill.py 从 case_candidate.json",
|
|
73
|
+
"> 自动生成,字段按 ops-mechanism SKILL.md 案例卡 schema 组装;警示列与适用边界",
|
|
74
|
+
"> 为模板占位,评审时必须补全/核实后才可摘掉草稿水印。",
|
|
75
|
+
"",
|
|
76
|
+
"| 字段 | 值 |",
|
|
77
|
+
"|------|-----|",
|
|
78
|
+
f"| 算子类别 | {c.get('operator', '?')}({c.get('dsl', 'Ascend C')}) |",
|
|
79
|
+
"| 类型 | 非 PR(Agent 实测回流) |",
|
|
80
|
+
"| 来源可信度 | **E 级**(本工作流 verdict→机制→实测闭环;speedup 只绑定当时口径指纹,不外推) |",
|
|
81
|
+
f"| 来源链接 + 验证日期 | case_candidate.json @ {c.get('generated_at', '?')};"
|
|
82
|
+
f"生成于 {datetime.date.today().isoformat()} |",
|
|
83
|
+
f"| 瓶颈证据 | rule_id `{c.get('bound_rule', '?')}`(verdict 命中,"
|
|
84
|
+
f"口径指纹:{scene_fp_text(fp)}) |",
|
|
85
|
+
f"| 优化机制 | {c.get('mechanism', '?')} |",
|
|
86
|
+
f"| 原文性能数字 | speedup **{measured if measured is not None else '—'}**(实测,"
|
|
87
|
+
f"KEEP 轮;预估区间 {est_text}) |",
|
|
88
|
+
f"| 回滚 | {'**发生过**(见 notes)' if rollback else '无'} |",
|
|
89
|
+
"",
|
|
90
|
+
"## 适用范围与警示(评审时补全,占位模板)",
|
|
91
|
+
"",
|
|
92
|
+
"- [ ] 口径边界:上述 speedup 仅在「{soc} / {shape} / {dtype} / CANN {cann_version}」"
|
|
93
|
+
"下成立,**禁止外推**到其他 shape/dtype/soc;".format(
|
|
94
|
+
soc=fp.get("soc", "?"),
|
|
95
|
+
shape=fp.get("shape", "?"),
|
|
96
|
+
dtype=fp.get("dtype", "?"),
|
|
97
|
+
cann_version=fp.get("cann_version", "?"),
|
|
98
|
+
),
|
|
99
|
+
"- [ ] 触发条件:命中 {rule} 时的哪个反证/severity 档位下适用本机制;".format(
|
|
100
|
+
rule=c.get("bound_rule", "?")
|
|
101
|
+
),
|
|
102
|
+
"- [ ] 反例边界:何种场景该机制会劣化(回滚轮次的 notes 是线索);",
|
|
103
|
+
f"- [ ] 原始备注:{c.get('notes', '(无)')}",
|
|
104
|
+
"",
|
|
105
|
+
"## 入库前检查单(ops-mechanism SKILL.md 检索规则)",
|
|
106
|
+
"",
|
|
107
|
+
"- [ ] 警示列已补全(反例与收益案例同等收录,警示列必填)",
|
|
108
|
+
"- [ ] 验证日期已核对",
|
|
109
|
+
"- [ ] 与既有同型案例(≤3)合并或分立已决策",
|
|
110
|
+
"- [ ] 摘除本草稿头部「草稿」水印",
|
|
111
|
+
]
|
|
112
|
+
return "\n".join(lines) + "\n"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def main() -> int:
|
|
116
|
+
ap = argparse.ArgumentParser(
|
|
117
|
+
description="case_candidate.json → E 级案例卡草稿(回灌 27-1 的半自动段)"
|
|
118
|
+
)
|
|
119
|
+
ap.add_argument(
|
|
120
|
+
"--input", required=True, help="case_candidate.json(单条目或 entries 数组)"
|
|
121
|
+
)
|
|
122
|
+
ap.add_argument(
|
|
123
|
+
"--cases-dir",
|
|
124
|
+
default=None,
|
|
125
|
+
help="ops-mechanism/cases/ 目录(提示用;草稿默认不入库,评审后人工移入)",
|
|
126
|
+
)
|
|
127
|
+
ap.add_argument(
|
|
128
|
+
"-o",
|
|
129
|
+
"--output",
|
|
130
|
+
required=True,
|
|
131
|
+
help="草稿输出路径(多条目时为前缀,逐条 .draft-N.md)",
|
|
132
|
+
)
|
|
133
|
+
args = ap.parse_args()
|
|
134
|
+
|
|
135
|
+
data = json.loads(Path(args.input).read_text(encoding="utf-8"))
|
|
136
|
+
cands = as_candidates(data)
|
|
137
|
+
if not cands:
|
|
138
|
+
print("ERROR: 输入无有效条目", file=sys.stderr)
|
|
139
|
+
return 1
|
|
140
|
+
schema = data.get("schema") if isinstance(data, dict) else None
|
|
141
|
+
if schema and schema != "opstune.case-candidate/1.0":
|
|
142
|
+
print(
|
|
143
|
+
f"WARN: schema {schema} != opstune.case-candidate/1.0,仍按字段尽力解析",
|
|
144
|
+
file=sys.stderr,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
out = Path(args.output)
|
|
148
|
+
written = []
|
|
149
|
+
if len(cands) == 1:
|
|
150
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
151
|
+
out.write_text(draft_md(cands[0], 1), encoding="utf-8")
|
|
152
|
+
written.append(out)
|
|
153
|
+
else:
|
|
154
|
+
for i, c in enumerate(cands, 1):
|
|
155
|
+
p = out.parent / f"{out.stem}.draft-{i}.md"
|
|
156
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
157
|
+
p.write_text(draft_md(c, i), encoding="utf-8")
|
|
158
|
+
written.append(p)
|
|
159
|
+
|
|
160
|
+
for p in written:
|
|
161
|
+
print(f"draft → {p}")
|
|
162
|
+
print(
|
|
163
|
+
"下一步:人工评审(检查单在草稿尾部)→ 补全警示列 → 移入 cases/ 并摘水印"
|
|
164
|
+
+ (f"(目标目录参考:{args.cases_dir})" if args.cases_dir else "")
|
|
165
|
+
)
|
|
166
|
+
return 0
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if __name__ == "__main__":
|
|
170
|
+
sys.exit(main())
|
|
@@ -0,0 +1,145 @@
|
|
|
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
|
+
"""log_gap.py — ops-family 知识缺口计数写入(REVIEW2 G9 / 反馈 P1-2 ③,提前骑行项)
|
|
13
|
+
|
|
14
|
+
设计对齐:
|
|
15
|
+
- ops-family SKILL.md 承诺「未收录族返回并**计数上报**(知识缺口感知回路的输入,
|
|
16
|
+
落盘 references/knowledge_gaps.json)」——此前该文件六条缺口 count 全 0,
|
|
17
|
+
无任何脚本写入:计数是纸面承诺(反馈 §4:「log_gap.py 提前——0.5 人日,
|
|
18
|
+
让 knowledge_gaps 计数从 M1 起开始积累,否则 P1-7 的季度排产承诺持续空转」)。
|
|
19
|
+
- 本脚本就是写入载体:路由时发现族未收录 / 族内文档为骨架 → 本条命令落一条
|
|
20
|
+
gap 记录(count+1 / first_seen 登记 / note 追加),季度排产(27-4)读它。
|
|
21
|
+
|
|
22
|
+
用法:
|
|
23
|
+
python3 log_gap.py --family fa --kind family_missing [--note "本次场景:FA 混合绑核"]
|
|
24
|
+
python3 log_gap.py --list
|
|
25
|
+
|
|
26
|
+
gap 条目语义(与 knowledge_gaps.json 现有 schema 一致):
|
|
27
|
+
family 算子族名(fa/elementwise/sort/simt/matmul/mc2/...)
|
|
28
|
+
kind family_missing | guide_missing | guide_skeleton | no_shelf_code
|
|
29
|
+
(未知 kind 允许写入——新类型由使用者定义,list 输出如实呈现)
|
|
30
|
+
count 命中次数(排产权重)
|
|
31
|
+
first_seen 首次命中日期
|
|
32
|
+
last_seen 最近命中日期(本脚本新增字段;旧条目首次追加时补写)
|
|
33
|
+
notes[] 每次命中的场景备注(增量追加,不覆盖)
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
import argparse
|
|
39
|
+
import datetime
|
|
40
|
+
import json
|
|
41
|
+
import sys
|
|
42
|
+
from pathlib import Path
|
|
43
|
+
|
|
44
|
+
# knowledge_gaps.json 归 ops-family(族表 SKILL.md 承诺的落盘位置);脚本放
|
|
45
|
+
# ops-mechanism/scripts 是因为「路由时发现未收录」发生在机制路由阶段(Step 3
|
|
46
|
+
# 查模板路径),ops-mechanism 是调用方。parents[2] = 套件根(tool-ops-tune/)。
|
|
47
|
+
GAPS_PATH = (
|
|
48
|
+
Path(__file__).resolve().parents[2]
|
|
49
|
+
/ "ops-family"
|
|
50
|
+
/ "references"
|
|
51
|
+
/ "knowledge_gaps.json"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
KNOWN_KINDS = ("family_missing", "guide_missing", "guide_skeleton", "no_shelf_code")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def load_gaps() -> dict:
|
|
58
|
+
if not GAPS_PATH.exists():
|
|
59
|
+
return {
|
|
60
|
+
"schema": "opstune.knowledge-gaps/1.0",
|
|
61
|
+
"description": "ops-family 知识缺口计数落盘",
|
|
62
|
+
"gaps": [],
|
|
63
|
+
}
|
|
64
|
+
return json.loads(GAPS_PATH.read_text(encoding="utf-8"))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def save_gaps(gaps: dict) -> None:
|
|
68
|
+
GAPS_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
69
|
+
GAPS_PATH.write_text(
|
|
70
|
+
json.dumps(gaps, ensure_ascii=False, indent=2) + "\n", encoding="utf-8"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def main() -> int:
|
|
75
|
+
ap = argparse.ArgumentParser(
|
|
76
|
+
description="知识缺口计数写入(知识缺口感知回路 27-4 的输入)"
|
|
77
|
+
)
|
|
78
|
+
ap.add_argument("--family", help="算子族名(如 fa / elementwise)")
|
|
79
|
+
ap.add_argument(
|
|
80
|
+
"--kind",
|
|
81
|
+
help="缺口类型(family_missing/guide_missing/guide_skeleton/no_shelf_code,"
|
|
82
|
+
"或自定义新类型)",
|
|
83
|
+
)
|
|
84
|
+
ap.add_argument("--note", default=None, help="本次命中场景备注(追加进 notes)")
|
|
85
|
+
ap.add_argument("--list", action="store_true", help="列出全部缺口与计数")
|
|
86
|
+
args = ap.parse_args()
|
|
87
|
+
|
|
88
|
+
gaps = load_gaps()
|
|
89
|
+
|
|
90
|
+
if args.list or (not args.family and not args.kind):
|
|
91
|
+
if not gaps.get("gaps"):
|
|
92
|
+
print("(无缺口记录)")
|
|
93
|
+
return 0
|
|
94
|
+
print(f"{'family':<14} {'kind':<16} {'count':>5} first_seen last_seen")
|
|
95
|
+
for g in sorted(gaps["gaps"], key=lambda g: -g.get("count", 0)):
|
|
96
|
+
print(
|
|
97
|
+
f"{g['family']:<14} {g['kind']:<16} {g.get('count', 0):>5}"
|
|
98
|
+
f" {g.get('first_seen', '-'):<11} {g.get('last_seen', '-'):<10}"
|
|
99
|
+
)
|
|
100
|
+
return 0
|
|
101
|
+
|
|
102
|
+
if not args.family or not args.kind:
|
|
103
|
+
print("ERROR: 需要 --family 与 --kind(或 --list)", file=sys.stderr)
|
|
104
|
+
return 1
|
|
105
|
+
if args.kind not in KNOWN_KINDS:
|
|
106
|
+
# 不拒绝:新类型是正常演进,但 stderr 提示核对(防拼写错误把计数写进错误桶)
|
|
107
|
+
print(
|
|
108
|
+
f"WARN: kind {args.kind!r} 不在已知四类 {KNOWN_KINDS}——若是新类型忽略本提示;"
|
|
109
|
+
f"若是笔误请改正后重跑(写错桶会稀释排产信号)",
|
|
110
|
+
file=sys.stderr,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
today = datetime.date.today().isoformat()
|
|
114
|
+
entry = next(
|
|
115
|
+
(
|
|
116
|
+
g
|
|
117
|
+
for g in gaps["gaps"]
|
|
118
|
+
if g["family"] == args.family and g["kind"] == args.kind
|
|
119
|
+
),
|
|
120
|
+
None,
|
|
121
|
+
)
|
|
122
|
+
if entry is None:
|
|
123
|
+
entry = {
|
|
124
|
+
"family": args.family,
|
|
125
|
+
"kind": args.kind,
|
|
126
|
+
"note": "",
|
|
127
|
+
"first_seen": today,
|
|
128
|
+
"count": 0,
|
|
129
|
+
"notes": [],
|
|
130
|
+
}
|
|
131
|
+
gaps["gaps"].append(entry)
|
|
132
|
+
print(f"[new] {args.family}/{args.kind} 条目登记")
|
|
133
|
+
else:
|
|
134
|
+
print(f"[hit] {args.family}/{args.kind}")
|
|
135
|
+
entry["count"] = entry.get("count", 0) + 1
|
|
136
|
+
entry["last_seen"] = today
|
|
137
|
+
if args.note:
|
|
138
|
+
entry.setdefault("notes", []).append(f"{today} {args.note}")
|
|
139
|
+
save_gaps(gaps)
|
|
140
|
+
print(f"count={entry['count']} → {GAPS_PATH}")
|
|
141
|
+
return 0
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
sys.exit(main())
|
|
@@ -0,0 +1,367 @@
|
|
|
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
|
+
"""mc2_search.py — MC² 配平系统搜索器(REVIEW2 G6-M2 / 反馈 P1-4)
|
|
13
|
+
|
|
14
|
+
设计对齐:
|
|
15
|
+
- mc2-balancing.md 机制卡写明「统一搜索算法(禁止经验值交付)」:四剪枝 +
|
|
16
|
+
Top-N 输出——此前只有 markdown 描述,全仓无执行载体(REVIEW2 G6 定性)。
|
|
17
|
+
- 本脚本是执行载体:输入 TilingData + R(隔离测试产出)→ 长短块排布候选
|
|
18
|
+
搜索 → 四剪枝 → Top-N 候选 + 剪枝记录(配平方案卡必须附本输出)。
|
|
19
|
+
|
|
20
|
+
搜索空间(机制卡原文语义):
|
|
21
|
+
长块 M ∈ 候选集(baseM 合法对齐粒度的倍数序列)
|
|
22
|
+
短块 M = 长块 M / ρ(对齐修正),ρ = max(R, 1/R)(长块与短块 M 之比)
|
|
23
|
+
块数切分:长块数 + 短块数在总 M(矩阵行数)预算内排布
|
|
24
|
+
|
|
25
|
+
四剪枝(可行性,机制卡编号):
|
|
26
|
+
① 核利用率:usedCoreNum × 块数覆盖不下降(候选的覆盖块数 ≥ 当前方案的)
|
|
27
|
+
② L1/L0 容量:baseM/baseN/baseK 组合不超片上预算(soc-spec.yaml 容量表)
|
|
28
|
+
③ 膨胀下界:计算膨胀 + 通信膨胀估算不超过收益(短块填充带来的冗余开销)
|
|
29
|
+
④ 对齐约束:M/N/K 对齐要求(512B 地址对齐 → 分形对齐 16/32 粒度)
|
|
30
|
+
|
|
31
|
+
输出(opstune.mc2-search/1.0):
|
|
32
|
+
candidates[]:Top-N(--top,默认 5)——每候选带 block 布局、容量占用计算
|
|
33
|
+
过程、剪枝检查通过记录
|
|
34
|
+
pruned[]:被剪枝候选 + 剪枝原因(可审计证据:剪枝记录本身是证据)
|
|
35
|
+
meta:R / ρ / 搜索空间统计 / soc 容量参数溯源
|
|
36
|
+
|
|
37
|
+
用法:
|
|
38
|
+
python3 mc2_search.py --m 4096 --base-n 256 --base-k 256 --used-core-num 16 \
|
|
39
|
+
--r-value 2.4 --soc a5 [-o candidates.json]
|
|
40
|
+
# R 来自 isolation_test.py 的 r_value;TilingData 来自 host 侧打印(机制卡 MC-1)
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
from __future__ import annotations
|
|
44
|
+
|
|
45
|
+
import argparse
|
|
46
|
+
import datetime
|
|
47
|
+
import json
|
|
48
|
+
import sys
|
|
49
|
+
from pathlib import Path
|
|
50
|
+
|
|
51
|
+
SCHEMA = "opstune.mc2-search/1.0"
|
|
52
|
+
SOC_SPEC_FILE = "soc-spec" + ".yaml" # 判定引擎同源峰值标尺
|
|
53
|
+
DEFAULT_SOC_SPEC = (
|
|
54
|
+
Path(__file__).resolve().parents[2] / "ops-verdict" / "references" / SOC_SPEC_FILE
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# 对齐粒度(机制卡剪枝④:分形对齐 16 / 512B 地址对齐折算元素粒度)
|
|
58
|
+
FRACTAL_ALIGN = 16 # M/N/K 分形对齐粒度(Cube MAC 16×16×16)
|
|
59
|
+
ELEM_ALIGN_512B = { # 512B 地址对齐折算的最小元素数(dtype 元素大小 → 元素数)
|
|
60
|
+
"fp16": 256,
|
|
61
|
+
"bf16": 256,
|
|
62
|
+
"fp32": 128,
|
|
63
|
+
"int8": 512,
|
|
64
|
+
}
|
|
65
|
+
# 512B 对齐是搬运效率推荐态而非硬约束(DataCopyPad 场景允许非 512B 对齐;
|
|
66
|
+
# 分形对齐 16 才是 Cube 的硬约束)——剪枝④按此分两级:分形不齐 → 剪枝;
|
|
67
|
+
# 512B 不齐 → 记录 warn 不剪枝(候选照常输出,标注 warn_align_512b)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def load_soc_caps(soc: str, soc_spec_path: Path) -> dict:
|
|
71
|
+
"""从 soc-spec.yaml 取容量约束(剪枝②的真源,不硬编码)。"""
|
|
72
|
+
import yaml
|
|
73
|
+
|
|
74
|
+
spec = yaml.safe_load(Path(soc_spec_path).read_text(encoding="utf-8"))
|
|
75
|
+
block = spec.get("socs", {}).get(soc)
|
|
76
|
+
if not block:
|
|
77
|
+
raise SystemExit(f"ERROR: soc-spec 无 {soc} 条目({soc_spec_path})")
|
|
78
|
+
buf = block.get("buffer", {})
|
|
79
|
+
ref = block.get("reference", {})
|
|
80
|
+
return {
|
|
81
|
+
"l1_kb": buf.get("l1_kb"),
|
|
82
|
+
"l0a_kb": buf.get("l0a_kb"),
|
|
83
|
+
"l0b_kb": buf.get("l0b_kb"),
|
|
84
|
+
"l0c_kb": buf.get("l0c_kb"),
|
|
85
|
+
"ub_kb": buf.get("ub_kb"),
|
|
86
|
+
"core_num": ref.get("ai_core_cnt", {}).get("value"),
|
|
87
|
+
"source": f"soc-spec:{soc}",
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def align_up(v: int, grain: int) -> int:
|
|
92
|
+
return ((v + grain - 1) // grain) * grain
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def long_block_candidates(
|
|
96
|
+
m: int, base_m_min: int, base_m_max: int, dtype: str, step_grain: int
|
|
97
|
+
) -> list[int]:
|
|
98
|
+
"""长块 M 候选集:[base_m_min, min(base_m_max, m)] 内按 step_grain 步进的
|
|
99
|
+
对齐值 + m 本身(整除免短块收尾)。"""
|
|
100
|
+
align = max(FRACTAL_ALIGN, ELEM_ALIGN_512B.get(dtype, FRACTAL_ALIGN))
|
|
101
|
+
hi = min(base_m_max, align_up(m, align))
|
|
102
|
+
cands = set()
|
|
103
|
+
v = align_up(base_m_min, align)
|
|
104
|
+
while v <= hi:
|
|
105
|
+
cands.add(v)
|
|
106
|
+
v = align_up(v + step_grain, align)
|
|
107
|
+
cands.add(hi)
|
|
108
|
+
return sorted(cands)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def prune(candidate: dict, ctx: dict) -> tuple[list[str], list[str]]:
|
|
112
|
+
"""四剪枝:返回 (剪枝原因, 警告) 两列表(原因空 = 通过全部剪枝)。"""
|
|
113
|
+
reasons, warns = [], []
|
|
114
|
+
# ④ 对齐约束:分形对齐 16 是 Cube 硬约束(剪枝);512B 对齐是搬运推荐态(警告)
|
|
115
|
+
for k in ("long_m", "short_m"):
|
|
116
|
+
if candidate[k] % FRACTAL_ALIGN != 0:
|
|
117
|
+
reasons.append(f"④ {k}={candidate[k]} 不满足分形对齐 {FRACTAL_ALIGN}")
|
|
118
|
+
if candidate["long_m"] % ctx["elem_align_512b"] != 0:
|
|
119
|
+
warns.append(
|
|
120
|
+
f"长块 M={candidate['long_m']} 非 512B 对齐粒度"
|
|
121
|
+
f"({ctx['elem_align_512b']} 元素)——搬运效率推荐态,DataCopyPad 场景可接受"
|
|
122
|
+
)
|
|
123
|
+
if candidate["short_m"] % ctx["elem_align_512b"] != 0:
|
|
124
|
+
warns.append(
|
|
125
|
+
f"短块 M={candidate['short_m']} 非 512B 对齐粒度——同上,记录不剪枝"
|
|
126
|
+
)
|
|
127
|
+
if ctx["base_n"] % FRACTAL_ALIGN != 0 or ctx["base_k"] % FRACTAL_ALIGN != 0:
|
|
128
|
+
reasons.append("④ baseN/baseK 未分形对齐(输入参数问题)")
|
|
129
|
+
|
|
130
|
+
# ② L1/L0 容量:A/B tile + 双 buffer 不超预算(元素 × dtype 字节 × buffer 份数)
|
|
131
|
+
elem_bytes = ctx["elem_bytes"]
|
|
132
|
+
buf_num = ctx.get("l1_buffer_num", 2)
|
|
133
|
+
a_kb = candidate["long_m"] * ctx["base_k"] * elem_bytes / 1024
|
|
134
|
+
b_kb = ctx["base_n"] * ctx["base_k"] * elem_bytes / 1024
|
|
135
|
+
l1_use_kb = (a_kb + b_kb) * buf_num
|
|
136
|
+
if l1_use_kb > ctx["l1_kb"]:
|
|
137
|
+
reasons.append(
|
|
138
|
+
f"② L1 超预算:({a_kb:.0f}+{b_kb:.0f})×{buf_num} = {l1_use_kb:.0f}KB"
|
|
139
|
+
f" > {ctx['l1_kb']}KB"
|
|
140
|
+
)
|
|
141
|
+
l0a_use_kb = candidate["long_m"] * ctx["base_k"] * elem_bytes / 1024
|
|
142
|
+
l0b_use_kb = ctx["base_n"] * ctx["base_k"] * elem_bytes / 1024
|
|
143
|
+
if l0a_use_kb > ctx["l0a_kb"]:
|
|
144
|
+
reasons.append(f"② L0A 超预算:{l0a_use_kb:.0f}KB > {ctx['l0a_kb']}KB")
|
|
145
|
+
if l0b_use_kb > ctx["l0b_kb"]:
|
|
146
|
+
reasons.append(f"② L0B 超预算:{l0b_use_kb:.0f}KB > {ctx['l0b_kb']}KB")
|
|
147
|
+
l0c_use_kb = candidate["long_m"] * ctx["base_n"] * elem_bytes / 1024
|
|
148
|
+
if l0c_use_kb > ctx["l0c_kb"]:
|
|
149
|
+
reasons.append(f"② L0C 超预算:{l0c_use_kb:.0f}KB > {ctx['l0c_kb']}KB")
|
|
150
|
+
|
|
151
|
+
# ① 核利用率:候选覆盖块数(长+短块要占满核)不下降
|
|
152
|
+
if candidate["blocks_total"] < ctx["current_blocks"]:
|
|
153
|
+
reasons.append(
|
|
154
|
+
f"① 核覆盖下降:候选块数 {candidate['blocks_total']}"
|
|
155
|
+
f" < 当前 {ctx['current_blocks']}"
|
|
156
|
+
)
|
|
157
|
+
if candidate["blocks_total"] < ctx["used_core_num"]:
|
|
158
|
+
reasons.append(
|
|
159
|
+
f"① 块数 < usedCoreNum({candidate['blocks_total']}"
|
|
160
|
+
f" < {ctx['used_core_num']}):有空闲核"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# ③ 膨胀下界:短块膨胀(补齐对齐引入的冗余计算)+ 排布浪费 ≤ 掩盖收益
|
|
164
|
+
# 收益上界(机制卡:配平收益 ≤ min 侧掩盖,估为 (ρ-1)/ρ × T_max 占比)
|
|
165
|
+
# 膨胀 = 冗余元素 / 总元素;排布浪费 = 尾部空隙 / 总 M
|
|
166
|
+
inflate_pct = candidate.get("inflation_pct", 0.0) + candidate.get(
|
|
167
|
+
"tail_waste_pct", 0.0
|
|
168
|
+
)
|
|
169
|
+
if inflate_pct > ctx["max_inflation_pct"]:
|
|
170
|
+
reasons.append(
|
|
171
|
+
f"③ 膨胀 {inflate_pct:.1f}% > 上限 {ctx['max_inflation_pct']}%"
|
|
172
|
+
f"(对齐冗余 {candidate.get('inflation_pct', 0):.1f}% + "
|
|
173
|
+
f"尾部浪费 {candidate.get('tail_waste_pct', 0):.1f}%)"
|
|
174
|
+
)
|
|
175
|
+
return reasons, warns
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def build_candidate(long_m: int, rho: float, m: int, ctx: dict) -> dict:
|
|
179
|
+
# 短块 M = 长块 M / ρ(对齐修正向上)
|
|
180
|
+
short_m = align_up(max(1, round(long_m / rho)), FRACTAL_ALIGN)
|
|
181
|
+
# 排布:R>1(计算慢)→ 长块主导;R<1(通信慢)→ 短块多塞间隙。
|
|
182
|
+
# 简化排布(机制卡「实际排布按 Top-N 实测修正」):长块铺满为主,
|
|
183
|
+
# 末段用短块收尾降低尾部浪费。
|
|
184
|
+
long_blocks = m // long_m
|
|
185
|
+
remain = m - long_blocks * long_m
|
|
186
|
+
short_blocks = 0
|
|
187
|
+
if remain > 0:
|
|
188
|
+
if remain % short_m == 0 and remain // short_m > 0:
|
|
189
|
+
short_blocks = remain // short_m
|
|
190
|
+
else:
|
|
191
|
+
# 短块收不齐:短块数 = ceil,末块对齐膨胀记入 inflation
|
|
192
|
+
short_blocks = -(-remain // short_m)
|
|
193
|
+
blocks_total = long_blocks + short_blocks
|
|
194
|
+
covered = long_blocks * long_m + abs(short_blocks) * short_m
|
|
195
|
+
inflation_pct = max(0.0, (covered - m) / m * 100) if m > 0 else 0.0
|
|
196
|
+
tail_waste_pct = max(0.0, (covered - m) / m * 100) if m > 0 else 0.0
|
|
197
|
+
return {
|
|
198
|
+
"variant": f"long{long_m}_short{short_m}",
|
|
199
|
+
"long_m": long_m,
|
|
200
|
+
"short_m": short_m,
|
|
201
|
+
"rho": round(rho, 3),
|
|
202
|
+
"long_blocks": long_blocks,
|
|
203
|
+
"short_blocks": short_blocks,
|
|
204
|
+
"blocks_total": blocks_total,
|
|
205
|
+
"inflation_pct": round(inflation_pct, 2),
|
|
206
|
+
"tail_waste_pct": round(tail_waste_pct, 2),
|
|
207
|
+
"capacity_kb": {
|
|
208
|
+
"l1": round(
|
|
209
|
+
(long_m + ctx["base_n"])
|
|
210
|
+
* ctx["base_k"]
|
|
211
|
+
* ctx["elem_bytes"]
|
|
212
|
+
* ctx.get("l1_buffer_num", 2)
|
|
213
|
+
/ 1024,
|
|
214
|
+
1,
|
|
215
|
+
),
|
|
216
|
+
"l0a": round(long_m * ctx["base_k"] * ctx["elem_bytes"] / 1024, 1),
|
|
217
|
+
"l0b": round(ctx["base_n"] * ctx["base_k"] * ctx["elem_bytes"] / 1024, 1),
|
|
218
|
+
"l0c": round(long_m * ctx["base_n"] * ctx["elem_bytes"] / 1024, 1),
|
|
219
|
+
},
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def main() -> int:
|
|
224
|
+
ap = argparse.ArgumentParser(
|
|
225
|
+
description="MC² 配平系统搜索器(四剪枝 + Top-N,禁经验值交付)"
|
|
226
|
+
)
|
|
227
|
+
ap.add_argument("--m", type=int, required=True, help="矩阵 M(总行数,TilingData)")
|
|
228
|
+
ap.add_argument("--base-n", type=int, required=True, help="baseN(TilingData)")
|
|
229
|
+
ap.add_argument("--base-k", type=int, required=True, help="baseK(TilingData)")
|
|
230
|
+
ap.add_argument(
|
|
231
|
+
"--used-core-num",
|
|
232
|
+
type=int,
|
|
233
|
+
required=True,
|
|
234
|
+
help="usedCoreNum(TilingData;机制卡 MC-1 硬约束)",
|
|
235
|
+
)
|
|
236
|
+
ap.add_argument(
|
|
237
|
+
"--r-value",
|
|
238
|
+
type=float,
|
|
239
|
+
required=True,
|
|
240
|
+
help="隔离测试 R = T_compute/T_comm(isolation_test.py 的 r_value)",
|
|
241
|
+
)
|
|
242
|
+
ap.add_argument("--soc", default="a5", help="a2/a3/a5(容量约束读 soc-spec)")
|
|
243
|
+
ap.add_argument("--dtype", default="fp16", choices=["fp16", "bf16", "fp32", "int8"])
|
|
244
|
+
ap.add_argument("--base-m-min", type=int, default=64, help="长块 M 搜索下界")
|
|
245
|
+
ap.add_argument("--base-m-max", type=int, default=512, help="长块 M 搜索上界")
|
|
246
|
+
ap.add_argument("--step", type=int, default=32, help="搜索步进(粒度)")
|
|
247
|
+
ap.add_argument(
|
|
248
|
+
"--l1-buffer-num", type=int, default=2, help="L1 buffer 份数(pingpong=2)"
|
|
249
|
+
)
|
|
250
|
+
ap.add_argument(
|
|
251
|
+
"--max-inflation-pct",
|
|
252
|
+
type=float,
|
|
253
|
+
default=15.0,
|
|
254
|
+
help="剪枝③膨胀上限 %%(默认 15,🟡 工程初值)",
|
|
255
|
+
)
|
|
256
|
+
ap.add_argument(
|
|
257
|
+
"--current-blocks",
|
|
258
|
+
type=int,
|
|
259
|
+
default=None,
|
|
260
|
+
help="当前方案块数(剪枝①基准;缺省取 used-core-num)",
|
|
261
|
+
)
|
|
262
|
+
ap.add_argument("--top", type=int, default=5, help="Top-N 输出")
|
|
263
|
+
ap.add_argument("--soc-spec", default=str(DEFAULT_SOC_SPEC))
|
|
264
|
+
ap.add_argument("-o", "--output", default=None, help="candidates.json 输出")
|
|
265
|
+
args = ap.parse_args()
|
|
266
|
+
|
|
267
|
+
caps = load_soc_caps(args.soc, Path(args.soc_spec))
|
|
268
|
+
rho = max(args.r_value, 1.0 / args.r_value) if args.r_value > 0 else 1.0
|
|
269
|
+
ctx = {
|
|
270
|
+
"base_n": args.base_n,
|
|
271
|
+
"base_k": args.base_k,
|
|
272
|
+
"used_core_num": args.used_core_num,
|
|
273
|
+
"current_blocks": args.current_blocks
|
|
274
|
+
if args.current_blocks is not None
|
|
275
|
+
else args.used_core_num,
|
|
276
|
+
"elem_bytes": {"fp16": 2, "bf16": 2, "fp32": 4, "int8": 1}[args.dtype],
|
|
277
|
+
"elem_align": max(FRACTAL_ALIGN, ELEM_ALIGN_512B[args.dtype]),
|
|
278
|
+
"elem_align_512b": ELEM_ALIGN_512B[args.dtype],
|
|
279
|
+
"l1_kb": caps["l1_kb"],
|
|
280
|
+
"l0a_kb": caps["l0a_kb"],
|
|
281
|
+
"l0b_kb": caps["l0b_kb"],
|
|
282
|
+
"l0c_kb": caps["l0c_kb"],
|
|
283
|
+
"l1_buffer_num": args.l1_buffer_num,
|
|
284
|
+
"max_inflation_pct": args.max_inflation_pct,
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
# 搜索 + 剪枝
|
|
288
|
+
candidates, pruned = [], []
|
|
289
|
+
space = long_block_candidates(
|
|
290
|
+
args.m, args.base_m_min, args.base_m_max, args.dtype, args.step
|
|
291
|
+
)
|
|
292
|
+
for lm in space:
|
|
293
|
+
c = build_candidate(lm, rho, args.m, ctx)
|
|
294
|
+
reasons, warns = prune(c, ctx)
|
|
295
|
+
if warns:
|
|
296
|
+
c["warn_align_512b"] = warns
|
|
297
|
+
if reasons:
|
|
298
|
+
pruned.append({"variant": c["variant"], "reasons": reasons})
|
|
299
|
+
else:
|
|
300
|
+
candidates.append(c)
|
|
301
|
+
|
|
302
|
+
# 排序取 Top-N:块数多(核覆盖好)优先,其次膨胀小(机制卡:估算 ≠ 实测,
|
|
303
|
+
# Top-N 供逐个实测——排序只是实测顺序,不是最终结论)
|
|
304
|
+
candidates.sort(
|
|
305
|
+
key=lambda c: (-c["blocks_total"], c["inflation_pct"] + c["tail_waste_pct"])
|
|
306
|
+
)
|
|
307
|
+
top = candidates[: args.top]
|
|
308
|
+
|
|
309
|
+
result = {
|
|
310
|
+
"schema": SCHEMA,
|
|
311
|
+
"generated_at": datetime.datetime.now().isoformat(timespec="seconds"),
|
|
312
|
+
"soc": args.soc,
|
|
313
|
+
"soc_caps": {
|
|
314
|
+
k: caps[k] for k in ("l1_kb", "l0a_kb", "l0b_kb", "l0c_kb", "core_num")
|
|
315
|
+
},
|
|
316
|
+
"soc_caps_source": caps["source"],
|
|
317
|
+
"input": {
|
|
318
|
+
"m": args.m,
|
|
319
|
+
"base_n": args.base_n,
|
|
320
|
+
"base_k": args.base_k,
|
|
321
|
+
"used_core_num": args.used_core_num,
|
|
322
|
+
"r_value": args.r_value,
|
|
323
|
+
"dtype": args.dtype,
|
|
324
|
+
"rho": round(rho, 3),
|
|
325
|
+
},
|
|
326
|
+
"search_space": {
|
|
327
|
+
"long_m_range": [min(space), max(space)] if space else [],
|
|
328
|
+
"n_explored": len(space),
|
|
329
|
+
},
|
|
330
|
+
"candidates": top,
|
|
331
|
+
"pruned": pruned,
|
|
332
|
+
"notes": [
|
|
333
|
+
"排序 = 实测顺序(块数优先、膨胀次之),不是最终结论——每候选须逐个实测"
|
|
334
|
+
"(tileCnt 扫描、跨 rank max 口径)后择优(mc2-balancing.md)",
|
|
335
|
+
f"剪枝③膨胀上限 {args.max_inflation_pct}% 为 🟡 工程初值,实测校准后回写",
|
|
336
|
+
],
|
|
337
|
+
"next": "逐候选实测同口径(msprof task-based、同 warmup/loops、跨 rank max),"
|
|
338
|
+
"delta_compare 出三段结论;配平方案卡必须附本输出(含剪枝记录)",
|
|
339
|
+
}
|
|
340
|
+
if args.output:
|
|
341
|
+
out = Path(args.output)
|
|
342
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
343
|
+
out.write_text(
|
|
344
|
+
json.dumps(result, indent=2, ensure_ascii=False) + "\n", encoding="utf-8"
|
|
345
|
+
)
|
|
346
|
+
print(f"→ {out}")
|
|
347
|
+
print(
|
|
348
|
+
f"MC² 配平搜索:R={args.r_value} ρ={rho:.2f} → 探索 {len(space)} / "
|
|
349
|
+
f"通过 {len(candidates)} / 剪枝 {len(pruned)},Top-{len(top)}:"
|
|
350
|
+
)
|
|
351
|
+
for c in top:
|
|
352
|
+
print(
|
|
353
|
+
f" {c['variant']}: 长块×{c['long_blocks']} + 短块×{c['short_blocks']}"
|
|
354
|
+
f" = {c['blocks_total']} 块,膨胀 {c['inflation_pct'] + c['tail_waste_pct']:.1f}%,"
|
|
355
|
+
f"L1 {c['capacity_kb']['l1']}KB"
|
|
356
|
+
)
|
|
357
|
+
if not top:
|
|
358
|
+
print(
|
|
359
|
+
" (无候选通过四剪枝——检查 TilingData/R 输入或放宽 --max-inflation-pct)",
|
|
360
|
+
file=sys.stderr,
|
|
361
|
+
)
|
|
362
|
+
return 1
|
|
363
|
+
return 0
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
if __name__ == "__main__":
|
|
367
|
+
sys.exit(main())
|