ops-tune-workbench-plugin 0.0.0-stage → 0.0.1-beta.1

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,476 @@
1
+ # Scalar 高性能编码原则
2
+
3
+ 本文给出 9 条编写 Scalar 高性能算子的编码原则。每条原则的格式统一为:
4
+
5
+ - **原理**:为什么这样写会让 Scalar 流水跑得更快
6
+ - **识别要点**:在已有代码中识别该反模式的关键信号
7
+ - **反例 / 正例**:可直接对照的代码模板(非真实算子代码,用于模式识别)
8
+
9
+ > 所有原则的共同目标:**帮助编译器更好地进行寄存器分配、别名分析和常量传播,从而减少 Load/Store 指令**。
10
+
11
+ ---
12
+
13
+ ## P1 结构体内慎用数组
14
+
15
+ ### 原理
16
+
17
+ 结构体内的数组成员,如果通过**动态下标**(运行时变量)访问,会让编译器的**别名分析(Alias Analysis)**失败:编译器无法确定下标的具体值,必须考虑最坏情况——下标可能经过计算后恰好指向结构体中的其他成员。为了保证正确性,编译器会**放弃对整个结构体所有成员的常量传播**,改为从内存重新读取。该污染会沿继承/包含关系向上传播。
18
+
19
+ ### 识别要点
20
+
21
+ - 类/结构体中同时存在数组成员和需要常量优化的其他成员
22
+ - 通过运行时变量(如 ping-pong 索引、循环变量)下标访问数组成员
23
+ - profiling 中观察到「常量参数本应折叠却仍走 Load」的现象
24
+
25
+ ### 反例
26
+
27
+ ```cpp
28
+ class Block {
29
+ event_t eventIds_[2] = {EVENT_ID0, EVENT_ID1}; // 数组成员
30
+ event_t eventIdsM_[2] = {EVENT_ID2, EVENT_ID3};
31
+ uint16_t pingPongId_ = 0; // 运行时下标
32
+ uint32_t tileM_; // 同结构体内其他成员被一起污染
33
+ };
34
+
35
+ void Block::Step() {
36
+ SetFlag<HardEvent::V_MTE2>(eventIds_[pingPongId_]); // 动态下标
37
+ pingPongId_ ^= 1;
38
+ // 即使 tileM_ 在编译期可推断为常量,也会被保守地走 Load
39
+ }
40
+ ```
41
+
42
+ ### 正例
43
+
44
+ ```cpp
45
+ class Block {
46
+ event_t eventId_ = EVENT_ID0; // 拆为独立标量
47
+ event_t eventIdM_ = EVENT_ID2;
48
+ uint16_t pingPongId_ = 0;
49
+ uint32_t tileM_;
50
+ };
51
+
52
+ void Block::Step() {
53
+ SetFlag<HardEvent::V_MTE2>(eventId_);
54
+ eventId_ = (eventId_ == EVENT_ID0) ? EVENT_ID1 : EVENT_ID0;
55
+ eventIdM_ = (eventIdM_ == EVENT_ID2) ? EVENT_ID3 : EVENT_ID2;
56
+ pingPongId_ ^= 1;
57
+ }
58
+ ```
59
+
60
+ ---
61
+
62
+ ## P2 循环主尾块分离
63
+
64
+ ### 原理
65
+
66
+ 热路径循环(如 Cube 类算子的 K-Reduce 循环)若在单一 `for` 内通过 `if` 处理首块、周期性事件、尾块,则**每轮迭代都执行 3 次分支判断**。Scalar 的分支预测器较简单,对"大多数迭代为 false 但偶尔为 true"的模式预测效果差;热路径中每次预测失败的代价被放大。
67
+
68
+ ### 识别要点
69
+
70
+ - 热路径循环内出现 `if (k == 0)`、`if (k == maxK - 1)`、`if (k % N == 0)` 等模式
71
+ - 循环次数大(数十~数百),且循环体含 MTE2 周期性 load 或首尾特殊处理
72
+
73
+ ### 反例
74
+
75
+ ```cpp
76
+ for (uint64_t k = 0; k < maxK; ++k) {
77
+ if (k == 0) { SetInitialParams(); }
78
+ if (k % loadStride == 0) { MTE2_LoadAL1(); }
79
+ if (k == maxK - 1) { SetFinalParams(); }
80
+ UpdateParams(k);
81
+ Compute();
82
+ }
83
+ ```
84
+
85
+ ### 正例
86
+
87
+ ```cpp
88
+ // Prologue:处理首块
89
+ SetInitialParams();
90
+ UpdateParams(0);
91
+ Compute();
92
+
93
+ // Hot Loop:零分支,仅纯计算与参数更新,周期事件被外层包住
94
+ uint64_t k = 1;
95
+ uint64_t segmentEnd = loadStride;
96
+ while (k < maxK - 1) {
97
+ if unlikely(k == segmentEnd) {
98
+ MTE2_LoadAL1();
99
+ segmentEnd += loadStride;
100
+ }
101
+ uint64_t end = (segmentEnd < maxK - 1) ? segmentEnd : maxK - 1;
102
+ for (; k < end; ++k) { // 内层 for 内零分支
103
+ UpdateParams(k);
104
+ Compute();
105
+ }
106
+ }
107
+
108
+ // Epilogue:处理尾块
109
+ UpdateParams(maxK - 1);
110
+ SetFinalParams();
111
+ Compute();
112
+ ```
113
+
114
+ > 适用边界:循环次数 < 5 次时,三段式带来的代码膨胀可能触发 I-Cache miss,需权衡。
115
+
116
+ ---
117
+
118
+ ## P3 显式编写循环代码
119
+
120
+ ### 原理
121
+
122
+ `for` 循环的回跳走**专用循环硬件**,不经过分支预测器,不会发生 flush;同时编译器对显式循环更容易做循环展开、循环无关变量外提等优化。
123
+ 反之,通过 `while(Iterate())` 状态机隐式实现多维嵌套循环时,每次 Tile 切换都会触发大量进位判断(一次切换可能引发 3–5 次连续 mispredict);状态机函数为处理各维度 Tail 与边界,代码体积通常很大(数百行),容易触发 I-Cache miss。
124
+
125
+ ### 识别要点
126
+
127
+ - 看到 `while(Iterate(self))`、`while(self->Next())` 等隐式状态机驱动循环
128
+ - `Iterate` / `Next` 函数内部级联多个 `if (counter == limit) { counter = 0; ...higher_dim++ }` 进位判断
129
+ - 函数体长(>200 行)、内部存在多层嵌套 `if` 处理维度切换
130
+
131
+ ### 反例
132
+
133
+ ```cpp
134
+ while (IterateMFirstMMode(self)) { // 隐式状态机
135
+ LoadAL1(self);
136
+ IterateK(self);
137
+ FreeTensor();
138
+ }
139
+
140
+ // IterateMFirstMMode 内部:
141
+ template <class Intf>
142
+ inline bool IterateMFirstMMode(Intf* self) {
143
+ if (IterateL0MFirstMMode(self)) return true;
144
+ self->ctx.mAL1Iter++;
145
+ if (self->ctx.mAL1Iter != self->ctx.loopM) { CalcMVar(self); return true; }
146
+ self->ctx.mAL1Iter = 0;
147
+ self->ctx.batchIter++;
148
+ if (self->ctx.batchIter != self->ctx.loopBatch) return true;
149
+ self->ctx.batchIter = 0;
150
+ // ... 多层级联 ...
151
+ return false;
152
+ }
153
+ ```
154
+
155
+ ### 正例
156
+
157
+ ```cpp
158
+ for (uint64_t nBL1 = 0; nBL1 < self->ctx.loopN; ++nBL1) {
159
+ for (uint64_t batch = 0; batch < self->ctx.loopBatch; ++batch) {
160
+ for (uint64_t mAL1 = 0; mAL1 < self->ctx.loopM; ++mAL1) {
161
+ self->ctx.nBL1Iter = nBL1;
162
+ self->ctx.batchIter = batch;
163
+ self->ctx.mAL1Iter = mAL1;
164
+ CalcMVar(self);
165
+
166
+ for (uint64_t nL0 = 0; nL0 < self->ctx.l12l0LoopN; ++nL0) {
167
+ for (uint64_t mL0 = 0; mL0 < self->ctx.l12l0LoopM; ++mL0) {
168
+ // L0 层计算
169
+ }
170
+ }
171
+ }
172
+ }
173
+ }
174
+ ```
175
+
176
+ ---
177
+
178
+ ## P4 尽量使用局部变量
179
+
180
+ ### 原理
181
+
182
+ 局部变量与成员变量在编译器优化层面有三方面本质差异:
183
+
184
+ 1. **寄存器分配**:未取地址的局部变量可能从不进入内存;成员变量必须通过 `this`+offset 访问,每次读写至少一次内存访问。
185
+ 2. **别名分析**:未取地址的局部变量,编译器知道无其它指针能指向它,可大胆做寄存器复用;成员变量则因可能的指针别名,每次读取都可能需要重新 Load。
186
+ 3. **跨函数调用**:未取地址的局部变量可跨函数调用保持在寄存器中;成员变量被外部函数调用后须重新从内存加载。
187
+
188
+ ### 识别要点
189
+
190
+ - 类中存在仅在单个函数(或少数内联函数)中频繁访问的成员变量
191
+ - 该成员变量在 kernel 生命周期内的值实际上不需要跨函数共享
192
+ - 含 `this->xxx` 的热路径表达式特别多
193
+
194
+ ### 反例
195
+
196
+ ```cpp
197
+ template <typename T>
198
+ class FlashAttentionKernel {
199
+ protected:
200
+ ConstParam constParam_; // 类成员
201
+ public:
202
+ inline void Init() {
203
+ for (int i = 0; i < constParam_.iters; ++i) { // 每轮 Load constParam_
204
+ DoStep(constParam_.scale); // this->constParam_.scale
205
+ }
206
+ }
207
+ };
208
+ ```
209
+
210
+ ### 正例
211
+
212
+ ```cpp
213
+ template <typename T>
214
+ class FlashAttentionKernel {
215
+ public:
216
+ inline void Init() {
217
+ ConstParam constParam; // 局部变量,可全程驻留寄存器
218
+ // ... 初始化 constParam ...
219
+ for (int i = 0; i < constParam.iters; ++i) {
220
+ DoStep(constParam.scale); // 无 this 间接、无别名顾虑
221
+ }
222
+ }
223
+ };
224
+ ```
225
+
226
+ ---
227
+
228
+ ## P5 变量定义贴近使用位置
229
+
230
+ ### 原理
231
+
232
+ 编译器把变量映射到寄存器。变量的**活跃范围(Live Range)**——从定义到最后一次使用的代码范围——越长,该变量占用寄存器的时间越长。长活跃范围会挤压其他变量的寄存器空间,迫使编译器进行 Spill。贴近使用位置定义则可能让变量直接使用临时寄存器、甚至被优化掉。
233
+
234
+ ### 识别要点
235
+
236
+ - 函数顶部集中定义大量局部变量
237
+ - 某个变量被定义后,跨越了大段(数十行以上)无关代码后才被使用
238
+ - 函数中段有大量函数调用或重计算(寄存器压力大)
239
+
240
+ ### 反例
241
+
242
+ ```cpp
243
+ void Foo() {
244
+ int a = 1; // 活跃范围横跨整个函数
245
+ int b = 2;
246
+ int c = 3;
247
+
248
+ DoHeavyWork(); // a/b/c 与重计算的临时值争寄存器
249
+ CallSubKernel();
250
+ DoMoreWork();
251
+
252
+ Print(a, b, c); // 真正使用在末尾
253
+ }
254
+ ```
255
+
256
+ ### 正例
257
+
258
+ ```cpp
259
+ void Foo() {
260
+ DoHeavyWork();
261
+ CallSubKernel();
262
+ DoMoreWork();
263
+
264
+ int a = 1; // 紧邻使用,活跃范围极短
265
+ int b = 2;
266
+ int c = 3;
267
+ Print(a, b, c);
268
+ }
269
+ ```
270
+
271
+ ---
272
+
273
+ ## P6 避免多级指针解引用
274
+
275
+ ### 原理
276
+
277
+ 多级指针带来三方面问题:
278
+
279
+ 1. **访存延迟串行累加**:每一级解引用本质上是一条 Load 指令,且这些 Load 之间存在数据依赖(前一条 Load 的结果是下一条 Load 的地址)。
280
+ 2. **破坏数据局部性**:多级指针的各级地址可能散落在堆内存不同位置,每级解引用都可能触发 D-Cache miss。
281
+ 3. **编译器优化困难**:指针别名问题让编译器不确定指针的某一级内容是否会被其他写操作修改,每次解引用都必须从内存重新加载。
282
+
283
+ ### 识别要点
284
+
285
+ - 类成员是指针类型,且通过该指针访问被指对象的成员
286
+ - 形如 `obj_->member->field` 或 `tiling_->params->Kb` 的访问链
287
+ - tiling/config 类参数通过指针长期持有
288
+
289
+ ### 反例
290
+
291
+ ```cpp
292
+ class Block {
293
+ const TCubeTiling* tiling_; // 指针类型成员
294
+ public:
295
+ bool IsTail(int kInner) {
296
+ return kInner + stepK_ >= tiling_->Kb; // 2 次 Load:先 Load tiling_,再 Load tiling_->Kb
297
+ }
298
+ };
299
+ ```
300
+
301
+ ### 正例
302
+
303
+ ```cpp
304
+ class Block {
305
+ AscendC::Shape<int64_t, int64_t, int64_t> problemShape_; // 值类型聚合体 (M, N, K)
306
+ public:
307
+ bool IsTail(int kInner) {
308
+ return kInner + stepK_ >= Get<MNK_K>(problemShape_); // 1 次 Load
309
+ }
310
+ };
311
+ ```
312
+
313
+ ---
314
+
315
+ ## P7 避免使用超大结构体
316
+
317
+ ### 原理
318
+
319
+ 1. **缓存局部性差**:D-Cache cacheline 大小为 64 字节。结构体过大时,访问不同成员可能落在不同 cacheline 上,导致 D-Cache miss 增多。建议结构体 ≤ 64B(1 个 cacheline),最大不超过 128B。
320
+ 2. **寄存器溢出**:编译器无法将超大结构体完全放入寄存器,必须分配到栈内存上,每次访问成员都生成 Load/Store 指令。
321
+ 3. **指针传递引入别名**:为避免拷贝开销,大结构体常通过指针传递,但这引入别名问题——编译器无法确定两个指针是否指向同一内存,无法激进优化。
322
+
323
+ ### 识别要点
324
+
325
+ - 单个 struct/class 的成员超过 10 个、估算尺寸 > 64B
326
+ - "上帝结构体":把不同计算阶段(L1/L0/事件/调试)的所有字段堆在同一个对象里
327
+ - 接口签名出现 `void f(BigParam* a, BigParam* b, ...)`(多个同类型指针,别名风险)
328
+
329
+ ### 反例
330
+
331
+ ```cpp
332
+ struct GodParams { // ~200B,跨多个 cacheline
333
+ // L1 阶段
334
+ uint64_t l1A, l1B, l1ScaleA, l1ScaleB;
335
+ // L0 阶段
336
+ uint64_t l0A, l0B, l0C;
337
+ // 事件
338
+ event_t evV2MTE2, evV2MTE3, evMTE1_M, evM_FIX;
339
+ // tiling、调试标志
340
+ TilingParams tiling;
341
+ uint32_t debugFlags;
342
+ // ...
343
+ };
344
+
345
+ void Compute(GodParams* a, GodParams* b) {
346
+ a->l1A = ...;
347
+ b->l1A = ...; // 若 a == b,前一条赋值被覆盖
348
+ int x = a->l1A; // 编译器必须重新 Load
349
+ int y = a->l0C; // 与 l1A 在不同 cacheline
350
+ }
351
+ ```
352
+
353
+ ### 正例
354
+
355
+ ```cpp
356
+ struct L1Stage { uint64_t a, b, scaleA, scaleB; }; // 32B
357
+ struct L0Stage { uint64_t a, b, c; }; // 24B
358
+ struct EventIds { event_t v2mte2, v2mte3, mte1_m, m_fix; }; // ≤ 32B
359
+
360
+ void Compute(L1Stage l1, L0Stage l0) { // 按值传递,无别名
361
+ l1.a = ...;
362
+ l0.c = ...;
363
+ }
364
+ ```
365
+
366
+ ---
367
+
368
+ ## P8 用 constexpr / 模板参数承载编译期常量
369
+
370
+ ### 原理
371
+
372
+ `const` 修饰的成员变量、或在构造函数中赋值的运行时常量,对编译器来说**仍是 runtime 值**——必须通过 Load 读取,且无法参与常量折叠(Constant Folding)和循环展开(Loop Unrolling)。
373
+ 改为 `constexpr` 或模板非类型参数后,该值在编译期就嵌入到生成代码中,进而能链式触发 P1 类常量传播优化(编译器一旦确认某个值为常量,就更愿意把相关变量也保持在寄存器中)。
374
+
375
+ ### 识别要点
376
+
377
+ - 类中含 `const` 成员变量、值在构造时确定但程序生命周期内不变
378
+ - 在 host 侧本就以模板/编译期方式生成的 tiling 参数,却被以 runtime 入参方式传入 kernel
379
+ - 形如 `for (int i = 0; i < kernel.tileM_; ++i)` 的循环,循环上限本应在编译期可知
380
+
381
+ ### 反例
382
+
383
+ ```cpp
384
+ class Kernel {
385
+ const uint32_t tileM_; // const 成员,对编译器仍是 runtime Load
386
+ const uint32_t tileK_;
387
+ public:
388
+ Kernel(uint32_t m, uint32_t k) : tileM_(m), tileK_(k) {}
389
+ void Run() {
390
+ for (uint32_t i = 0; i < tileM_; ++i) { // 无法展开
391
+ for (uint32_t j = 0; j < tileK_; ++j) {
392
+ Compute(i, j);
393
+ }
394
+ }
395
+ }
396
+ };
397
+ ```
398
+
399
+ ### 正例
400
+
401
+ ```cpp
402
+ // 方案 A:模板非类型参数——值在类型中固化
403
+ template <uint32_t TILE_M, uint32_t TILE_K>
404
+ class Kernel {
405
+ public:
406
+ void Run() {
407
+ for (uint32_t i = 0; i < TILE_M; ++i) { // 可被完全展开
408
+ for (uint32_t j = 0; j < TILE_K; ++j) {
409
+ Compute(i, j);
410
+ }
411
+ }
412
+ }
413
+ };
414
+
415
+ // 方案 B:constexpr static——全局编译期常量
416
+ class Kernel {
417
+ static constexpr uint32_t TILE_M = 128;
418
+ static constexpr uint32_t TILE_K = 64;
419
+ public:
420
+ void Run() {
421
+ for (uint32_t i = 0; i < TILE_M; ++i) {
422
+ for (uint32_t j = 0; j < TILE_K; ++j) {
423
+ Compute(i, j);
424
+ }
425
+ }
426
+ }
427
+ };
428
+ ```
429
+
430
+ ---
431
+
432
+ ## P9 Hot Loop 内不构造对象、不取地址
433
+
434
+ ### 原理
435
+
436
+ 1. **构造/析构展开后是大量 Store**:在热循环内构造对象,每轮迭代都会展开为对成员的逐项初始化 Store;带析构语义的对象还会在迭代末尾插入清理代码。
437
+ 2. **取地址迫使编译器 Spill**:对局部变量取地址(`&x`)意味着该地址可能传递到外部代码,编译器必须保守地假设变量在调用之后可能被修改,因此必须把变量放到栈上(Spill),不能保持在寄存器中。
438
+ 3. **取地址也阻碍别名分析**:被取地址的变量与其他指针之间无法证明非别名,污染周围代码的优化。
439
+
440
+ ### 识别要点
441
+
442
+ - 热循环内出现非平凡类型(如 `LocalTensor`、临时聚合体)的就地构造
443
+ - 循环内出现 `Api(&x)` 形式调用,且 `x` 本可按值传递
444
+ - 循环内对中间变量频繁取地址传给辅助函数
445
+
446
+ ### 反例
447
+
448
+ ```cpp
449
+ // 反例 #1:循环内构造 LocalTensor,每轮触发多个成员的初始化 Store
450
+ for (int i = 0; i < N; ++i) {
451
+ LocalTensor<half> tmp = buf.Get<half>(); // 每轮重新构造
452
+ Compute(tmp, i);
453
+ }
454
+
455
+ // 反例 #2:循环内对局部变量取地址,强制 Spill 到栈
456
+ for (int i = 0; i < N; ++i) {
457
+ uint32_t idx = i * 2;
458
+ LegacyApi(&idx); // &idx 触发 Spill,idx 无法驻留寄存器
459
+ }
460
+ ```
461
+
462
+ ### 正例
463
+
464
+ ```cpp
465
+ // 正例 #1:构造外提,循环内仅复用
466
+ LocalTensor<half> tmp = buf.Get<half>();
467
+ for (int i = 0; i < N; ++i) {
468
+ Compute(tmp, i);
469
+ }
470
+
471
+ // 正例 #2:能按值传递就按值传递;必须传地址时,把变量提升为循环不变量
472
+ for (int i = 0; i < N; ++i) {
473
+ uint32_t idx = i * 2;
474
+ NewApi(idx); // 按值传,idx 全程在寄存器
475
+ }
476
+ ```
@@ -0,0 +1,163 @@
1
+ # Conv 算子 Scalar 优化
2
+
3
+ Conv 类算子的 Scalar 优化围绕一个核心思路:**利用场景特化,将运行时可变量尽可能转化为编译期常量**,从而减少 Scalar 侧的地址计算与分支判断,降低 Load/Store 指令占比。
4
+
5
+ ---
6
+
7
+ ## 1. 固定循环轴与泛化范围
8
+
9
+ ### 原理
10
+
11
+ 通用 Conv 实现需要考虑任意 N/H/W/C/K 组合,循环轴排列、tiling 粒度、weight 加载策略都做成参数化的,这导致 Scalar 在每个循环层级都要做动态地址计算和分支。而 **depthwise** 和 **小 case** 场景下,输入规模受限,循环轴是固定的,比如上面2种场景下weight 在单核内是全载(fullload)的 —— 此时可以去除不必要的循环轴,降低scalar开销。
12
+
13
+ > **小 case** 定义:FMAP 和 Weight 能在一轮搬运中全载到 L1 的场景。此时不再需要逐 tile 切分 weight/fmap,循环轴可大幅精简。
14
+
15
+ ### Depthwise 场景的循环轴
16
+
17
+ ```
18
+ for group in [0, groupOpt): // 组间循环(AIV/AIC 交替)
19
+ for batch in [0, batchCount): // batch 循环
20
+ for m_AL1 in [0, actualM): // 输出空间 M 维(ho×wo),按 AL1 tile 切
21
+ for k in [0, kTotal): // 输入通道 K 维(K = cin/groups × kh × kw)
22
+ ```
23
+
24
+ Weight 全载:每组 weight 的完整 `[cout/groups, cin/groups, kh, kw]` 在 `SetupGroup` 阶段一次性加载到 L1(B1 buffer),整个 group 内的 batch 迭代和 M 迭代复用它。
25
+
26
+ ### 小 case 场景的循环轴
27
+
28
+ ```
29
+ for m in [0, actualM): // 输出空间 M 维
30
+ for k in [0, kTotal): // 输入通道 K 维(K = cin × kh × kw)
31
+ ```
32
+
33
+ Weight 全载:`LoadWeightL1()` 在 Process 开头一次性将本 core 的 `[singleCoreCo, kTotal]` weight 加载到 L1,之后 M-loop 和 K-loop 中不再搬运 weight。
34
+
35
+ ### 为什么省 Scalar
36
+
37
+ 去除无效的循环轴后:代码段长度减少(少一层循环 = 少一套地址计算逻辑),运行过程中的变量减少(循环变量、临时偏移量不再需要),运行时额外计算减少(不再需要每层循环的动态乘加来推导地址)。指令数显著下降。
38
+
39
+ ---
40
+
41
+ ## 2. 去除 Queue / TBuffer / Tpipe,改用 SetFlag/WaitFlag + LocalTensor
42
+
43
+ ### 原理
44
+
45
+ Queue / TBuffer / Tpipe 是 Ascend C 的**高级抽象**,它们在底层展开为大量 Scalar 指令:队列状态查询、缓冲区索引更新、自动同步插入。在 hot loop 中使用这些抽象,Scalar 需要:
46
+ - 维护 Queue 的读/写指针和状态字
47
+ - 为 TBuffer 做地址重映射
48
+ - 在 Tpipe 的各阶段之间插入隐式同步
49
+
50
+ 当场景足够简单(固定循环轴、全载 weight)时,可以直接用底层原语替代:
51
+
52
+ ### 替代对照
53
+
54
+ ```
55
+ Queue → SetFlag / WaitFlag(显式硬件事件同步)
56
+ TBuffer → LocalTensor(直接指定 TPposition + 偏移,手动管理缓冲区)
57
+ Tpipe → 不需要(Queue 和 TBuffer 都去掉了,Tpipe 只剩空壳)
58
+ ```
59
+
60
+ ### 简要代码模式
61
+
62
+ **同步:Queue → SetFlag/WaitFlag**
63
+
64
+ ```
65
+ // 原模式(Queue)
66
+ // EnQue<MTE1_M>(queue, ...);
67
+
68
+ // 新模式(显式事件同步)
69
+ uint16_t pingPong = 0;
70
+ SetFlag<HardEvent::M_MTE1>(static_cast<event_t>(pingPong)); // 生产者信号
71
+ WaitFlag<HardEvent::MTE1_M>(static_cast<event_t>(pingPong)); // 消费者等待
72
+ SetFlag<HardEvent::MTE1_M>(static_cast<event_t>(pingPong)); // 消费者完成信号
73
+ pingPong ^= 1;
74
+ ```
75
+
76
+ **缓冲区:TBuffer → LocalTensor**
77
+
78
+ ```
79
+ // 原模式(TBuffer)
80
+ // TBuffer al0Buf = pipe.GetBuffer<A2>();
81
+
82
+ // 新模式(直接指定位置和大小)
83
+ constexpr uint32_t L0A_HALF = 32768;
84
+ LocalTensor<half> al0(TPosition::A2, pingPong * L0A_HALF, L0A_HALF / sizeof(half));
85
+ ```
86
+
87
+ ### 优化效果示意
88
+
89
+ ```
90
+ 优化前(Queue + TBuffer + Tpipe):
91
+ 每条 Load/Copy 指令前 Scalar 需要:
92
+ - 查询 queue 状态(Load)
93
+ - 计算 buffer offset(ALU + Load)
94
+ - 更新 buffer 索引(Store)
95
+ → 典型 Scalar Load/Store 占比 > 30%
96
+
97
+ 优化后(SetFlag/WaitFlag + LocalTensor):
98
+ 每条 Load/Copy 指令前 Scalar 仅需要:
99
+ - WaitFlag(硬件信号量,无 Scalar 开销)
100
+ - offset 来自编译期常量(常量折叠,0 指令)
101
+ → Scalar Load/Store 占比可降到 < 15%
102
+ ```
103
+
104
+ ---
105
+
106
+ ## 3. TilingData 常量化
107
+
108
+ ### 原理
109
+
110
+ 在**图静态**场景(编译期已知所有维度参数),将 TilingData 声明为 `constexpr`,编译器会对所有 `.convRunInfo.xxx` 和 `.convApiTiling.xxx` 的访问做**常量传播 + 常量折叠**。这意味着:
111
+
112
+ - `ri.kh * ri.kw`、`GCeilDiv(kTotal_, K0_VAL)` 等表达式在编译期算出结果
113
+ - `Load3DBitModeParam` 的 config0/config1 字段直接嵌入立即数
114
+ - 不再产生运行时从内存 Load TilingData 的 Scalar 指令
115
+
116
+ ### 声明方式
117
+
118
+ ```cpp
119
+ // 编译期常量 TilingData(图静态场景)
120
+ constexpr Conv2DTilingData kTiling = {
121
+ .convRunInfo = { /* 所有字段编译期已知 */ },
122
+ .convApiTiling = { /* ... */ },
123
+ };
124
+ ```
125
+
126
+ kernel 内部通过 `Tiling()` 访问(指针指向 `&kTiling`),编译器看到 `constexpr` 后会将所有成员访问折叠。
127
+
128
+ ### 适用条件
129
+
130
+ | 场景 | TilingData 来源 | 可否常量 |
131
+ |------|----------------|---------|
132
+ | 直接调用(demo/验证) | 编译期常量 | 可 `constexpr` |
133
+ | ops-nn 集成(框架下沉) | Host 侧运行时计算,通过 workspace 传入 | 不可 |
134
+
135
+ 图静态场景常量化后,TilingData 相关的 Scalar Load 指令从 **数十条 → 0**。
136
+
137
+ ---
138
+
139
+ ## 三者叠加效果
140
+
141
+ ```
142
+ ┌─────────────────────────────┐
143
+ │ 固定循环轴(场景特化) │
144
+ │ 消除分支 + 动态地址计算 │
145
+ └──────────────┬──────────────┘
146
+ │
147
+ ┌──────────────▼──────────────┐
148
+ │ 去除 Queue/TBuffer/Tpipe │
149
+ │ 消除队列维护 + 缓冲区映射 │
150
+ └──────────────┬──────────────┘
151
+ │
152
+ ┌──────────────▼──────────────┐
153
+ │ TilingData constexpr │
154
+ │ 常量传播 → 消除参数 Load │
155
+ └──────────────┬──────────────┘
156
+ │
157
+ ┌──────────────▼──────────────┐
158
+ │ Scalar Load/Store 占比 │
159
+ │ 从 90%+ → 10% 以内 │
160
+ └─────────────────────────────┘
161
+ ```
162
+
163
+ 三者是**递进关系**:固定循环轴是前提(场景特化让循环结构可写死),再去掉高级抽象(Queue/TBuffer/Tpipe 没有存在的必要),最后常量化 TilingData(把仅存的参数 Load 也消除)。单独做一项收效有限,三者叠加才能把 Scalar 开销压到最低。
@@ -0,0 +1,30 @@
1
+ # Scalar 性能优化策略索引
2
+
3
+ Scalar 单元负责标量计算、地址计算、指令参数构造与指令分发。当它本身成为瓶颈、无法及时把指令发到 Cube / Vector / MTE 的 Issue 队列时,其他流水线会出现 bubble,整个算子被拖慢。这种现象称为 **ScalarBound**。
4
+
5
+ Scalar 优化的核心结论:**主因不是 Scalar 计算指令多,而是 Load/Store 指令多**(典型占比超过 30%),其根源是编译器寄存器 Spill。因此本类目下所有原则的共同目标是:**帮助编译器更好地完成寄存器分配、别名分析和常量传播,从而减少 Load/Store**。
6
+
7
+ ## 9 条编码原则速查
8
+
9
+ | 编号 | 原则 | 一句话核心 |
10
+ |------|------|-----------|
11
+ | [P1](coding_principles.md#p1-结构体内慎用数组) | 结构体内慎用数组 | 动态下标的结构体数组会让编译器放弃整个结构体的常量传播 |
12
+ | [P2](coding_principles.md#p2-循环主尾块分离) | 循环主尾块分离 | Prologue / Hot Loop(零分支)/ Epilogue 三段式,避免热路径每轮 3 次分支判断 |
13
+ | [P3](coding_principles.md#p3-显式编写循环代码) | 显式编写循环代码 | 用嵌套 `for` 替代隐式状态机;`for` 的回跳走专用硬件,不进分支预测 |
14
+ | [P4](coding_principles.md#p4-尽量使用局部变量) | 尽量使用局部变量 | 成员变量受别名分析压制;跨函数调用后必须从内存重新 Load |
15
+ | [P5](coding_principles.md#p5-变量定义贴近使用位置) | 变量定义贴近使用位置 | 缩短活跃范围 = 缩短寄存器占用 = 降低 Spill 概率 |
16
+ | [P6](coding_principles.md#p6-避免多级指针解引用) | 避免多级指针解引用 | 每级解引用都是带依赖的 Load,用值类型聚合体替代 |
17
+ | [P7](coding_principles.md#p7-避免使用超大结构体) | 避免使用超大结构体 | > 64B 跨 cacheline;超寄存器容量必 Spill;指针传递引入别名 |
18
+ | [P8](coding_principles.md#p8-用-constexpr--模板参数承载编译期常量) | 用 `constexpr` / 模板参数承载编译期常量 | `const` 成员对编译器仍是 runtime Load;进入常量折叠才能链式带动 P1 类优化 |
19
+ | [P9](coding_principles.md#p9-hot-loop-内不构造对象不取地址) | Hot Loop 内不构造对象、不取地址 | 构造/析构展开后是大量初始化 Store;取地址会让编译器假设变量可被外部修改、强制 Spill |
20
+
21
+ ## 与其他算子族优化的协同
22
+
23
+ Scalar 优化与算子族优化**正交**:算子族优化决定"做什么计算和搬运",Scalar 优化决定"这些指令能不能被及时分发出去"。两者都要做,但顺序上以算子族优化(tiling / MTE 策略)为先。
24
+
25
+ 各算子族在通用 9 条原则之上还有场景特化的 Scalar 优化策略:
26
+
27
+ | 算子族 | 场景 | 核心思路 | 指南 |
28
+ |--------|------|---------|------|
29
+ | Conv | Depthwise、小 case(FMAP/Weight 全载 L1) | 固定循环轴 + 去除高层抽象 + TilingData 常量化 | [Conv Scalar 优化指南](conv_scalar.md) |
30
+ | FA | — | 📋 规划中 | — |