已合并
feat(matmul_story): add one-click run script with auto target recommendation #100
yangyang016创建于 3月23日
feat(matmul_story): add one-click run script with auto target recommendation #100
已合并
yangyang016创建于 3月23日
7 个文件变更+379-21
@@ -37,6 +37,8 @@ set(RECIPE_VARIANTS quant_matmul_mxfp4)
37foreach(variant IN LISTS RECIPE_VARIANTS)37foreach(variant IN LISTS RECIPE_VARIANTS)
38 install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples/${variant}/scripts/38 install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/examples/${variant}/scripts/
39 DESTINATION ${MATMUL_INSTALL_PREFIX}/matmul_recipes/${variant}39 DESTINATION ${MATMUL_INSTALL_PREFIX}/matmul_recipes/${variant}
40- FILES_MATCHING PATTERN "*.py"40+ FILES_MATCHING
41+ PATTERN "*.py"
42+ PATTERN "*.sh"
41 )43 )
42endforeach()44endforeach()
@@ -67,9 +67,39 @@ NPU ARCH 3510
67 67 
68两个可执行文件在运行结束后都会自动调用 `verify_result.py`,将 NPU 输出与 CPU golden 进行一致性校验。68两个可执行文件在运行结束后都会自动调用 `verify_result.py`,将 NPU 输出与 CPU golden 进行一致性校验。
69 69 
70-## 构建与运行70+## 一键运行(推荐)
71 71 
72-仓库根目录下完成编译和安装后进入当前样例目录:72+仓库提供 `run.sh`(位于 `matmul_recipes/examples/quant_matmul_mxfp4/scripts/`)可一键串联 **构建 → 数据生成 → 算子执行 → 结果校验** 全流程。
73+推荐先进入样例目录再执行,命令更短:
74+ 
75+```bash
76+cd Samples/2_Performance/matmul_story/matmul_recipes/examples/quant_matmul_mxfp4
77+ 
78+# 自动构建 + 自动推荐最优算法 + 运行
79+bash scripts/run.sh 16 2048 16384
80+ 
81+# 指定目标可执行文件,跳过重新构建
82+bash scripts/run.sh \
83+ --target quant_matmul_mxfp4_a_full_load --skip-build 16 2048 16384
84+ 
85+# 查看完整帮助
86+bash scripts/run.sh --help
87+```
88+ 
89+### run.sh 参数说明
90+ 
91+| 参数 | 说明 |
92+|------|------|
93+| `m k n` | 矩阵维度(必填)。`k` 须为偶数。 |
94+| `--target <name>` | 指定要运行的可执行文件名。省略时自动调用推荐脚本选择最优目标。 |
林鹏翔4月2日

需要验证不带target的效果

likedislike
95+| `--skip-build` | 跳过构建/安装阶段,复用已有 `build_out`。 |
林鹏翔4月2日

需要确认没有build的时候,设置这个命令的效果

likedislike
yangyang016
4月2日 评论:
yangyang016
4月3日 评论:
96+| `-h, --help` | 显示帮助信息。 |
97+ 
98+如需查看完整算法推荐排名(含耗时表格),请在安装目录下直接运行 `quant_matmul_mxfp4_algorithm_recommend.py`(见下文「手动构建与运行」)。
99+ 
100+## 手动构建与运行
101+ 
102+如需手动控制各步骤,可在仓库根目录下完成编译和安装后,进入当前样例目录:
73 103 
74```bash104```bash
75cmake -S . -B build105cmake -S . -B build
@@ -101,3 +131,15 @@ python3 gen_data.py 16 2048 16384
101```bash131```bash
102python3 quant_matmul_mxfp4_algorithm_recommend.py 16 2048 16384132python3 quant_matmul_mxfp4_algorithm_recommend.py 16 2048 16384
103```133```
134+ 
135+下图为推荐脚本输出的**结构示意**(数值为虚构,仅说明版式):
136+ 
137+```text
138+[Profile Breakdown]
139++--------------------------------+----------+---------+----------+---------+---------+------------+--------------+
140+| candidate |kernel(us)| mac(us) |scalar(us)| mte1(us)| mte2(us)|fixpipe(us) |icache_miss(%)|
141++================================+==========+=========+==========+=========+=========+============+==============+
142+| quant_matmul_mxfp4_swat | 12.345| 1.234 | 0.567| 0.123 | 0.456 | 0.789 | 0.100 |
143+| quant_matmul_mxfp4_a_full_load | 15.678| 2.100 | 0.800| 0.200 | 0.300 | 0.500 | 0.250 |
144++--------------------------------+----------+---------+----------+---------+---------+------------+--------------+
145+```
@@ -16,7 +16,7 @@ import sys
16import tempfile16import tempfile
17from dataclasses import dataclass17from dataclasses import dataclass
18from pathlib import Path18from pathlib import Path
19-from typing import List, Optional19+from typing import List, Optional, Tuple
20 20 
21 21 
22MSPROF_OUTPUT_DIR_NAME = "msprof_recommend"22MSPROF_OUTPUT_DIR_NAME = "msprof_recommend"
@@ -73,11 +73,13 @@ class CandidateResult:
73 73 
74 74 
75def print_usage(program_name: str) -> None:75def print_usage(program_name: str) -> None:
76- print(f"Usage: {program_name} m k n")76+ print(f"Usage: {program_name} m k n [--print-target]")
77 print("Args:")77 print("Args:")
78 print(" m: row of matrix A")78 print(" m: row of matrix A")
79 print(" k: shared dimension of A and B")79 print(" k: shared dimension of A and B")
80 print(" n: col of matrix B")80 print(" n: col of matrix B")
81+ print("Options:")
82+ print(" --print-target: print only the recommended executable name")
81 print(f"Example: {program_name} 1024 4096 2048")83 print(f"Example: {program_name} 1024 4096 2048")
82 84 
83 85 
@@ -90,19 +92,37 @@ def parse_positive_uint64(arg: str, name: str) -> int:
90 return value92 return value
91 93 
92 94 
93-def parse_arguments(argv: List[str]) -> tuple[int, int, int]:95+def parse_arguments(argv: List[str]) -> Tuple[int, int, int, bool]:
94 if len(argv) >= 2 and argv[1] in ("-h", "--help"):96 if len(argv) >= 2 and argv[1] in ("-h", "--help"):
95 print_usage(Path(argv[0]).name)97 print_usage(Path(argv[0]).name)
96 raise SystemExit(0)98 raise SystemExit(0)
97- if len(argv) != 4:99+ 
100+ print_target_only = False
101+ positional: List[str] = []
102+ for arg in argv[1:]:
103+ if arg == "--print-target":
104+ print_target_only = True
105+ continue
106+ if arg.startswith("-"):
107+ raise ValueError(f"Unknown option: {arg}")
108+ positional.append(arg)
109+ 
110+ if len(positional) != 3:
98 raise ValueError("Expected exactly 3 arguments: m k n")111 raise ValueError("Expected exactly 3 arguments: m k n")
99 112 
100- m = parse_positive_uint64(argv[1], "m")113+ m = parse_positive_uint64(positional[0], "m")
101- k = parse_positive_uint64(argv[2], "k")114+ k = parse_positive_uint64(positional[1], "k")
102- n = parse_positive_uint64(argv[3], "n")115+ n = parse_positive_uint64(positional[2], "n")
103 if k % 2 != 0:116 if k % 2 != 0:
104 raise ValueError("k must be an even number")117 raise ValueError("k must be an even number")
105- return m, k, n118+ return m, k, n, print_target_only
119+ 
120+ 
121+def get_ranked_results(results: List[CandidateResult]) -> List[CandidateResult]:
122+ return sorted(
123+ [item for item in results if item.succeeded],
124+ key=lambda item: item.kernel_time_us if item.kernel_time_us is not None else float("inf"),
125+ )
106 126 
107 127 
108def resolve_executable(script_dir: Path, executable_name: str) -> Path:128def resolve_executable(script_dir: Path, executable_name: str) -> Path:
@@ -391,7 +411,7 @@ def print_ranking(results: List[CandidateResult]) -> None:
391 411 
392def main(argv: List[str]) -> int:412def main(argv: List[str]) -> int:
393 try:413 try:
394- m, k, n = parse_arguments(argv)414+ m, k, n, print_target_only = parse_arguments(argv)
395 except ValueError as error:415 except ValueError as error:
396 print(f"ERROR: {error}")416 print(f"ERROR: {error}")
397 print_usage(Path(argv[0]).name)417 print_usage(Path(argv[0]).name)
@@ -418,8 +438,16 @@ def main(argv: List[str]) -> int:
418 candidate_result = run_candidate(script_dir, candidate, m, k, n)438 candidate_result = run_candidate(script_dir, candidate, m, k, n)
419 results.append(candidate_result)439 results.append(candidate_result)
420 440 
441+ ranked_results = get_ranked_results(results)
442+ if print_target_only:
443+ if not ranked_results:
444+ print("ERROR: No compatible algorithm found for the current shape.")
445+ return 1
446+ print(ranked_results[0].label)
447+ return 0
448+ 
421 print_ranking(results)449 print_ranking(results)
422- return 0 if any(result.succeeded for result in results) else 1450+ return 0 if ranked_results else 1
423 finally:451 finally:
424 cleanup_msprof_output_dir(msprof_output_dir)452 cleanup_msprof_output_dir(msprof_output_dir)
425 453 
@@ -0,0 +1,125 @@
1+# ----------------------------------------------------------------------------------------------------------
2+# Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+# CANN Open Software License Agreement Version 2.0 (the "License").
5+# Please refer to the License for details. You may not use this file except in compliance with the License.
6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+# See LICENSE in the root of the software repository for the full text of the License.
9+# ----------------------------------------------------------------------------------------------------------
10+ 
11+set -euo pipefail
12+ 
13+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14+ 
15+find_repo_root() {
16+ local dir="$SCRIPT_DIR"
17+ while [[ "$dir" != "/" ]]; do
18+ if [[ -f "$dir/.ci/build.sh" ]]; then
19+ echo "$dir"
20+ return 0
21+ fi
22+ dir="$(dirname "$dir")"
23+ done
24+ return 1
25+}
26+ 
27+REPO_ROOT="$(find_repo_root || true)"
28+if [[ -z "$REPO_ROOT" ]]; then
29+ echo "ERROR: cannot locate repo root containing .ci/build.sh"
30+ exit 1
31+fi
32+ 
33+INSTALL_DIR="${REPO_ROOT}/build_out/2_Performance/matmul_story/matmul_recipes/quant_matmul_mxfp4"
34+TARGET=""
35+SKIP_BUILD=false
36+M=""
37+K=""
38+N=""
39+ 
40+usage() {
41+ cat <<'EOF'
42+Usage: bash run.sh [OPTIONS] m k n
43+ 
44+Options:
45+ --target <name> Specify executable name to run.
46+ --skip-build Skip build/install stage.
47+ -h, --help Show this help.
48+ 
49+When --target is omitted, run.sh auto-selects target via:
50+ python3 quant_matmul_mxfp4_algorithm_recommend.py --print-target m k n
51+EOF
52+}
53+ 
54+while [[ $# -gt 0 ]]; do
55+ case "$1" in
56+ --target)
57+ [[ -z "${2:-}" ]] && { echo "ERROR: --target needs a value"; exit 1; }
58+ TARGET="$2"
59+ shift 2
60+ ;;
61+ --skip-build)
62+ SKIP_BUILD=true
63+ shift
64+ ;;
65+ -h|--help)
66+ usage
67+ exit 0
68+ ;;
69+ -*)
70+ echo "ERROR: unknown option: $1"
71+ usage
72+ exit 1
73+ ;;
74+ *)
75+ if [[ -z "$M" ]]; then
76+ M="$1"
77+ elif [[ -z "$K" ]]; then
78+ K="$1"
79+ elif [[ -z "$N" ]]; then
80+ N="$1"
81+ else
82+ echo "ERROR: unexpected argument: $1"
83+ usage
84+ exit 1
85+ fi
86+ shift
87+ ;;
88+ esac
89+done
90+ 
91+if [[ -z "$M" || -z "$K" || -z "$N" ]]; then
92+ echo "ERROR: m k n are required"
93+ usage
94+ exit 1
95+fi
96+ 
97+if [[ "$SKIP_BUILD" != true ]]; then
98+ bash "${REPO_ROOT}/.ci/build.sh"
99+fi
100+ 
101+if [[ ! -d "$INSTALL_DIR" ]]; then
102+ echo "ERROR: install dir not found: $INSTALL_DIR"
103+ echo "Hint: remove --skip-build for full build/install."
104+ exit 1
105+fi
106+ 
107+cd "$INSTALL_DIR"
108+ 
109+python3 gen_data.py "$M" "$K" "$N"
110+ 
111+if [[ -z "$TARGET" ]]; then
112+ TARGET="$(python3 quant_matmul_mxfp4_algorithm_recommend.py --print-target "$M" "$K" "$N")"
113+fi
114+ 
115+if [[ -z "$TARGET" ]]; then
116+ echo "ERROR: failed to select a target executable"
117+ exit 1
118+fi
119+ 
120+if [[ ! -x "./$TARGET" ]]; then
121+ echo "ERROR: executable not found: $INSTALL_DIR/$TARGET"
122+ exit 1
123+fi
124+ 
125+"./$TARGET" "$M" "$K" "$N"
@@ -20,5 +20,7 @@ add_subdirectory(7_fullload)
20 20 
21install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts/21install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts/
22 DESTINATION ${MATMUL_INSTALL_PREFIX}/matmul_tutorials22 DESTINATION ${MATMUL_INSTALL_PREFIX}/matmul_tutorials
23- FILES_MATCHING PATTERN "*.py"23+ FILES_MATCHING
24+ PATTERN "*.py"
25+ PATTERN "*.sh"
24)26)
@@ -24,9 +24,39 @@
24- `matmul_tutorial_mxfp4_memery_access_coalescing`(Step 6)24- `matmul_tutorial_mxfp4_memery_access_coalescing`(Step 6)
25- `matmul_tutorial_mxfp4_a_fullload`(Step 7)25- `matmul_tutorial_mxfp4_a_fullload`(Step 7)
26 26 
27-## 构建与运行27+## 一键运行(推荐)
28 28 
29-仓库根目录执行编译安装,并进入教安装目录:29+仓库提供 `scripts/run.sh`,可一键串联 **构建 → 数据生成 → 算子执行 → 结果校验** 全流
30+建议先进入 `matmul_tutorials/` 目录再执行:
31+ 
32+```bash
33+cd Samples/2_Performance/matmul_story/matmul_tutorials
34+ 
35+# 指定 Step 运行
36+bash scripts/run.sh --target matmul_tutorial_mxfp4_swat 256 256 256
37+ 
38+# 自动构建 + 未指定 target 时运行 Step 0(matmul_tutorial_mxfp4_base)
39+bash scripts/run.sh 256 256 256
Y
Yyangyang0164月2日

确认下target是否需要传

likedislike
40+ 
41+# 跳过构建阶段
42+bash scripts/run.sh --target matmul_tutorial_mxfp4_swat_balance --skip-build 256 256 256
43+ 
44+# 查看完整帮助
45+bash scripts/run.sh --help
46+```
47+ 
48+### run.sh 参数说明
49+ 
50+| 参数 | 说明 |
51+|------|------|
52+| `m k n` | 矩阵维度(必填)。`k` 须为偶数。 |
53+| `--target <name>` | 指定要运行的教程可执行文件名;省略时默认 Step 0(`matmul_tutorial_mxfp4_base`) |
54+| `--skip-build` | 跳过构建/安装阶段,复用已有 `build_out`。 |
55+| `-h, --help` | 显示帮助信息。 |
56+ 
57+## 手动构建与运行
58+ 
59+如需手动控制各步骤,在仓库根目录执行编译安装,并进入教程安装目录:
30 60 
31```bash61```bash
32cmake -S . -B build62cmake -S . -B build
@@ -43,13 +73,8 @@ python3 gen_data.py 256 256 256
43 73 
44# 2) 运行某个 Step(示例:Step 2)74# 2) 运行某个 Step(示例:Step 2)
45./matmul_tutorial_mxfp4_swat 256 256 25675./matmul_tutorial_mxfp4_swat 256 256 256
46- 
47-# 3) 结果校验(若可执行文件未自动校验,可手动执行)
48-python3 verify_result.py 256 256
49```76```
50 77 
51-> 调用约定:教程程序以自身所在目录作为工作目录,读写 `./input` 和 `./output`,并在该目录下调用 `verify_result.py`。
52- 
53## 相关文档78## 相关文档
54 79 
55- 顶层说明:[`../README.md`](../README.md)80- 顶层说明:[`../README.md`](../README.md)
@@ -0,0 +1,134 @@
1+# ----------------------------------------------------------------------------------------------------------
2+# Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+# CANN Open Software License Agreement Version 2.0 (the "License").
5+# Please refer to the License for details. You may not use this file except in compliance with the License.
6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+# See LICENSE in the root of the software repository for the full text of the License.
9+# ----------------------------------------------------------------------------------------------------------
10+ 
11+ 
12+set -euo pipefail
13+ 
14+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15+find_repo_root() {
16+ local dir="$SCRIPT_DIR"
17+ while [[ "$dir" != "/" ]]; do
18+ if [[ -f "$dir/.ci/build.sh" ]]; then
19+ echo "$dir"
20+ return 0
21+ fi
22+ dir="$(dirname "$dir")"
23+ done
24+ return 1
25+}
26+REPO_ROOT="$(find_repo_root || true)"
27+if [[ -z "$REPO_ROOT" ]]; then
28+ echo "ERROR: cannot locate repo root containing .ci/build.sh"
29+ exit 1
30+fi
31+INSTALL_DIR="${REPO_ROOT}/build_out/2_Performance/matmul_story/matmul_tutorials"
32+DEFAULT_TUTORIAL_TARGET="matmul_tutorial_mxfp4_base"
33+ 
34+TARGET=""
35+SKIP_BUILD=false
36+M=""
37+K=""
38+N=""
39+ 
40+usage() {
41+ cat <<'EOF'
42+Usage: bash run.sh [OPTIONS] m k n
43+ 
44+One-stop script: build, generate data, run, and verify a matmul tutorial step.
45+ 
46+Positional arguments:
47+ m Row count of matrix A
48+ k Shared dimension of A and B (must be even)
49+ n Column count of matrix B
50+ 
51+Options:
52+ --target <name> Tutorial executable to run (e.g. matmul_tutorial_mxfp4_swat).
53+ When omitted, defaults to Step 0: matmul_tutorial_mxfp4_base.
54+ --skip-build Skip the build/install phase (reuse existing build_out).
55+ -h, --help Show this help message and exit.
56+ 
57+Available tutorial executables (Step 0 – Step 7):
58+ matmul_tutorial_mxfp4_base (Step 0)
59+ matmul_tutorial_mxfp4_pingpong (Step 1)
60+ matmul_tutorial_mxfp4_swat (Step 2)
61+ matmul_tutorial_mxfp4_swat_balance (Step 3)
62+ matmul_tutorial_mxfp4_swat_unitflag (Step 4)
63+ matmul_tutorial_mxfp4_half1l1_ping_halfl1_pong (Step 5)
64+ matmul_tutorial_mxfp4_memery_access_coalescing (Step 6)
65+ matmul_tutorial_mxfp4_a_fullload (Step 7)
66+ 
67+Examples:
68+ # Run with explicit target
69+ bash scripts/run.sh --target matmul_tutorial_mxfp4_swat 256 256 256
70+ 
71+ # Default Step 0 + skip rebuild
72+ bash scripts/run.sh --skip-build 256 256 256
73+ 
74+EOF
75+}
76+ 
77+while [[ $# -gt 0 ]]; do
78+ case "$1" in
79+ --target)
80+ [[ -z "${2:-}" ]] && { echo "ERROR: --target requires a value"; usage; exit 1; }
81+ TARGET="$2"; shift 2 ;;
82+ --skip-build)
83+ SKIP_BUILD=true; shift ;;
84+ -h|--help)
85+ usage; exit 0 ;;
86+ -*)
87+ echo "ERROR: unknown option: $1"; usage; exit 1 ;;
88+ *)
89+ if [[ -z "$M" ]]; then M="$1"
90+ elif [[ -z "$K" ]]; then K="$1"
91+ elif [[ -z "$N" ]]; then N="$1"
92+ else echo "ERROR: unexpected argument: $1"; usage; exit 1
93+ fi
94+ shift ;;
95+ esac
96+done
97+ 
98+if [[ -z "$M" || -z "$K" || -z "$N" ]]; then
99+ echo "ERROR: m, k, n are required."
100+ usage
101+ exit 1
102+fi
103+ 
104+# ── 1. Build ────────────────────────────────────────────────────────────────
105+if [[ "$SKIP_BUILD" != true ]]; then
106+ echo "=== Building project (via .ci/build.sh) ==="
107+ bash "${REPO_ROOT}/.ci/build.sh"
108+fi
109+ 
110+if [[ ! -d "$INSTALL_DIR" ]]; then
111+ echo "ERROR: Install directory not found: $INSTALL_DIR"
112+ echo " Run without --skip-build to perform a full build first."
113+ exit 1
114+fi
115+cd "$INSTALL_DIR"
116+ 
117+# ── 2. Generate test data ──────────────────────────────────────────────────
118+echo "=== Generating test data (m=$M k=$K n=$N) ==="
119+python3 gen_data.py "$M" "$K" "$N"
120+ 
121+# ── 3. Determine target executable ─────────────────────────────────────────
122+if [[ -z "$TARGET" ]]; then
123+ TARGET="${DEFAULT_TUTORIAL_TARGET}"
124+ echo " Using default Step 0 target: $TARGET"
125+fi
126+ 
127+if [[ ! -x "./$TARGET" ]]; then
128+ echo "ERROR: Executable not found or not executable: $INSTALL_DIR/$TARGET"
129+ exit 1
130+fi
131+ 
132+# ── 4. Run ──────────────────────────────────────────────────────────────────
133+echo "=== Running ./$TARGET $M $K $N ==="
134+"./$TARGET" "$M" "$K" "$N"