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,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ops-family
|
|
3
|
+
description: 算子族实践库与模板代码货架。按算子族(matmul/mc2/reduce/elementwise/broadcast/conversion/sort/scalar/simt…)组织的实现范式、A/B 双型文档与可拷贝代码模板(.h/.cpp/.template)。实施环节的模板优先纪律(直接拷贝 + 最小适配 + 编译修复顺序)在本 SKILL 落地。触发:查算子族优化参考实现、查模板代码、实施方案落地时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 算子族实践库(family)
|
|
7
|
+
|
|
8
|
+
> 职责:机制确定后「怎么写」的货架。查到模板**必须直接拷贝**,禁止参考重写——这是
|
|
9
|
+
> 知识层与编排层的双重契约(verdict→mechanism 路由到此,模板路径进候选方案卡)。
|
|
10
|
+
|
|
11
|
+
## 算子族分类表
|
|
12
|
+
|
|
13
|
+
模板数 = `references/<族>/` 下 .h/.cpp/.template 实测计数(冒烟静态断言防漂移);
|
|
14
|
+
状态 = ✅ 实质内容 / 🟡 骨架(索引层)/ ❌ 占位。
|
|
15
|
+
|
|
16
|
+
| 族 | 典型算子 | 架构 | 模板数 | 状态 | 文档 |
|
|
17
|
+
|----|---------|------|-------|------|------|
|
|
18
|
+
| matmul | MatMul/BatchMatMul/MXFP4/A16W16 | DAV_3510 | 1 | ✅(Blaze 基础模板 ×1,经 480-case 穿刺验证) | `references/matmul/guide.md`(六策略互斥判定树)+ `references/matmul/templates/` |
|
|
19
|
+
| mc2 | matmul_all_reduce/allgather_matmul/alltoall_matmul | DAV_3510 | 0 | ✅ 设计参考(无货架代码) | `references/mc2/guide.md`(3 策略) |
|
|
20
|
+
| reduce | ReduceSum/Softmax/LayerNorm/RMSNorm | DAV_3510 | 10 | ✅(Softmax 模板 ×8 + kernel_utils + tiling) | `references/reduce/guide.md` |
|
|
21
|
+
| elementwise | Sin/Cos/Abs/Exp | DAV_3510 | 5 | ✅(add_custom 可裁剪工程模板:kernel .asc/.h + host .asc + torch 扩展 ×2,经真机验证的可裁剪工程模板;scripts/ 验证脚本不计模板数) | `references/elementwise/guide.md` + `references/elementwise/templates/`(usage_guide + add_custom) |
|
|
22
|
+
| broadcast | 含广播轴 Add/Mul/Sub | DAV_3510 | 5 | ✅(code/ 可裁剪源码) | B 型选型(OneDim 快路径 + NDDMA/DataCopyPad/UB 三实现) |
|
|
23
|
+
| conversion | Transpose/Concat/Split | DAV_3510 | 11 | ✅(transpose 模板 + tiling_data) | `references/conversion/`(12 篇 transpose) |
|
|
24
|
+
| sort | TopK/KthValue/Sort/ArgSort | A2+A5 | 0 | 🟡 设计参考(M-way 归并三 Pattern 路由 + Pattern C 四阶段架构已蒸馏;radix 路线 radix_sort.md;无货架代码) | `references/sort/guide.md`(Pattern 决策树)+ `references/sort/radix_sort.md` |
|
|
25
|
+
| scalar | ScalarBound 算子 | A2+A5 | 0 | ✅(设计原则 + conv 实践,无模板) | `references/scalar/guide.md` |
|
|
26
|
+
| simt | 条件分支/离散索引 | DAV_3510 | 0 | 🟡 设计参考(VF 三件套范式 + 共享内存/多核同步 + verdict 映射已蒸馏;无货架代码) | `references/simt/guide.md`(编程范式)+ `references/simt/optimization-guide.md` |
|
|
27
|
+
| fa | FlashAttention 类 | DAV_3510 | 0 | 🟡 设计参考(方法论已蒸馏:三通道 Roofline + mix kernel 设计 + 不变量 I1-I5;无货架代码,实战案例仍走降级策略) | `references/fa/guide.md`(判定映射 + 区制路由)+ `references/fa/fa_roofline_design.md` + `references/fa/fa_mixed_kernel_design.md` |
|
|
28
|
+
| convolution / nn / random | — | — | 0 | ❌ 规划中(M2+) | — |
|
|
29
|
+
|
|
30
|
+
未收录族返回「该算子族优化知识暂未收录」并**计数上报**(知识缺口感知回路的输入,
|
|
31
|
+
落盘 `references/knowledge_gaps.json`)。融合算子拆解为基元族分别查询
|
|
32
|
+
(AddRelu = broadcast + elementwise)。
|
|
33
|
+
|
|
34
|
+
## 模板代码查找链路
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
本 SKILL.md 分类表
|
|
38
|
+
→ references/<family>/guide.md(族指南)
|
|
39
|
+
→ 模板表选方案(适用条件列)
|
|
40
|
+
→ references/<family>/templates/<模板名>.md(说明文档)
|
|
41
|
+
→ 同名 .h / .cpp / .template(代码骨架,以此为实施基线)
|
|
42
|
+
|
|
43
|
+
跨族公共设施:references/common/(计时 harness 货架——
|
|
44
|
+
timing_harness/ 两模板 + index.md,snapshot kernel_avg_us 的第一生产者,
|
|
45
|
+
见 P0-2;搬运/尾块/UB 常驻设计参考)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 脚本
|
|
49
|
+
|
|
50
|
+
| 脚本 | 职责 |
|
|
51
|
+
|------|------|
|
|
52
|
+
| `scripts/family_asset_audit.py` | 族表模板数静态断言(防 SKILL.md 数据漂移,CI 门禁) |
|
|
53
|
+
| `scripts/tiling_candidates.py` | Tiling 候选生成器·四族(elementwise/reduction/broadcast/conversion):shape/dtype + soc-spec 容量约束 → 候选参数表(block_dim/tile),逐候选附容量占用计算过程 + 剪枝记录——机制卡「禁止经验值交付」的执行载体(P0-5;L2_UNDERUTILIZATION 命中后调用的首选工具) |
|
|
54
|
+
|
|
55
|
+
## 模板优先纪律(T1-T5,编排层同款)
|
|
56
|
+
|
|
57
|
+
1. 查到模板(.h/.cpp/.template)→ **直接拷贝到项目 `op_kernel/`**(保留 dav310 等子目录
|
|
58
|
+
结构),仅做最小适配;`.template` 先按 usage_guide 转同名 .h/.cpp。
|
|
59
|
+
2. 模板内 MicroAPI VF 计算(RegTensor/MaskReg/LoadAsFp32/StoreFromFp32)**原样保留**,
|
|
60
|
+
禁止降级为高层 API。
|
|
61
|
+
3. MicroAPI 编译报错修复顺序:①命名空间别名(`namespace MicroAPI = Reg;`)→ ②API 签名
|
|
62
|
+
适配(对照 CANN 实际头文件)→ ③include 路径 → ④全部无效才降级**对应分支**,
|
|
63
|
+
并在结果中列出尝试过的修复与失败原因。
|
|
64
|
+
4. 实施方返回「模板使用情况」:哪些直接拷贝、哪些降级、降级原因与尝试记录。
|
|
65
|
+
|
|
66
|
+
## 文档结构(A/B 双型)
|
|
67
|
+
|
|
68
|
+
- **A 型 单实现调参**(如 matmul pingpong/swat):优化目标(量化收益)→ 架构概览 →
|
|
69
|
+
关键参数 → 核心循环(改造前后对照含事件同步)→ 关键修改点表。
|
|
70
|
+
- **B 型 多实现选型**(如 broadcast):总览速查 + **选型决策树**(决定性能的核心)+
|
|
71
|
+
每实现一份分册 + code/ 可裁剪源码。选 B 时收益 = 选对实现避免劣化,必须给选型依据。
|
|
72
|
+
|
|
73
|
+
## 扩展新族
|
|
74
|
+
|
|
75
|
+
1. 建 `references/<family>/`;2. 判 A/B 型按对应结构写;3. 更新本表;4. 族 guide 内
|
|
76
|
+
模板与判定的 mechanism_refs 对齐(新增机制卡时反向引用)。
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# 进阶:通用切分(任意 ubSplitAxis / 大 shape / 尾块非对齐)
|
|
2
|
+
|
|
3
|
+
> 主文档:[broadcast_design.md](broadcast_design.md) | 参考代码:[`code/broadcast_tiling_common.h`](code/broadcast_tiling_common.h)(`ComputeTiling`)
|
|
4
|
+
>
|
|
5
|
+
> 入门样例([broadcast_add](code/broadcast_add_tiling.cpp))已切换到本文的通用切分。本文解释为什么不能写死 `ubSplitAxis=0`,以及通用切分的完整公式——这是把指导用到真实大 shape(如 cann-bench case 4 int32 8192×8192、case 10 fp16 363×367×373)的关键。
|
|
6
|
+
|
|
7
|
+
## 1. 为什么不能写死 ubSplitAxis=0
|
|
8
|
+
|
|
9
|
+
写死「尾轴整条进 UB、沿 0 轴切」只在 `尾轴元素数 ≤ elemNum` 时成立。真实 case 的尾轴常远超 UB:
|
|
10
|
+
|
|
11
|
+
| 场景 | 问题 |
|
|
12
|
+
|------|------|
|
|
13
|
+
| 尾轴 rowLen > elemNum(如 8192 fp32) | 一整行放不进 UB,必须**切到尾轴内部** |
|
|
14
|
+
| 大 shape 无广播(BRC_NONE) | 同样会尾轴超 UB,需与广播输入一样的多轴切分 |
|
|
15
|
+
| 高维 shape | 切分轴可能落在中间某轴,`dimProductBeforeUbInner` 不再等于 `ubOuter` |
|
|
16
|
+
|
|
17
|
+
## 2. 通用切分算法(`ComputeTiling`)
|
|
18
|
+
|
|
19
|
+
切分对象是**输出 shape**。从尾轴向外累乘,找能塞进 UB 的最内切分轴;若连尾轴一行都放不下,则切尾轴本身。
|
|
20
|
+
|
|
21
|
+
```cpp
|
|
22
|
+
// 1) 选切分轴:从尾轴向外,尽量把内层整轴塞进 UB
|
|
23
|
+
int splitAxis = 0; int64_t innerBelow = 1; // innerBelow = ∏ outputDims[splitAxis+1 .. rank-1]
|
|
24
|
+
for (int ax = rank - 1; ax >= 0; ax--) {
|
|
25
|
+
if (innerBelow * outputDims[ax] > elemNum) { splitAxis = ax; break; }
|
|
26
|
+
innerBelow *= outputDims[ax]; splitAxis = ax;
|
|
27
|
+
}
|
|
28
|
+
// 2) 切分大小
|
|
29
|
+
if (innerBelow > elemNum) { // 连一行都放不下 → 切尾轴本身
|
|
30
|
+
ubSplitAxis = rank - 1; innerBelow = 1; ubFormer = elemNum; // 每块 elemNum 个元素
|
|
31
|
+
} else {
|
|
32
|
+
ubSplitAxis = splitAxis; ubFormer = elemNum / innerBelow; // 一次放几行
|
|
33
|
+
}
|
|
34
|
+
ubFormer = clamp(ubFormer, 1, outputDims[ubSplitAxis]);
|
|
35
|
+
ubOuter = ceil(outputDims[ubSplitAxis] / ubFormer);
|
|
36
|
+
ubTail = outputDims[ubSplitAxis] - (ubOuter - 1) * ubFormer;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 关键:`dimProductBeforeUbInner` 通用公式
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
dimProductBeforeUbInner = (∏ outputDims[0 .. ubSplitAxis-1]) × ubOuter // = UB tile 总数
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- `ubSplitAxis = 0`:∏(空)=1 → 退化为 `ubOuter`(即入门样例的特例)。
|
|
46
|
+
- `ubSplitAxis = rank-1`(切尾轴):`∏ outputDims[0..rank-2] × ubOuter`。
|
|
47
|
+
|
|
48
|
+
这个值喂给 `GetAxesIndices`/`GetGmOffset`,**ubSplitAxis≠0 时必须用通用公式**,否则下标还原全错。完整实现见 `ComputeTiling`。
|
|
49
|
+
|
|
50
|
+
### 多核
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
totalTiles = dimProductBeforeUbInner;
|
|
54
|
+
blockFormer = ceil(totalTiles / coreNum); // 先按核数算每核最多几个 tile
|
|
55
|
+
blockNum = ceil(totalTiles / blockFormer); // 再回收用不上的核
|
|
56
|
+
blockTail = totalTiles - (blockNum-1)*blockFormer; // ∈[1, blockFormer]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
> 顺序很关键:若先 `blockNum=min(coreNum,totalTiles)` 再 `blockFormer=ceil(totalTiles/blockNum)`,会出现 `blockTail<0`(如 totalTiles=100、coreNum=64 → blockFormer=2、blockTail=-26),非尾核处理越界 tile。必须先定 blockFormer 再回收核。
|
|
60
|
+
|
|
61
|
+
## 3. 尾块非 32B 对齐
|
|
62
|
+
|
|
63
|
+
`ubTail = splitDim - (ubOuter-1)*ubFormer` 往往**不是 alignEle 的倍数**(如质数 shape、大 shape 展平)。处理方式:
|
|
64
|
+
|
|
65
|
+
- **搬运**:`DataCopyPad` 的 `blockLen` 以**字节**计,内部自动 pad 到 32B;非对齐尾块**直接传真实长度即可**,无需手动 mask/padding(`DataCopyPadCompact` 已如此)。
|
|
66
|
+
- **计算**:`Add`/`Broadcast` 等矢量指令的 `count` 传真实元素数,AscendC 处理非对齐尾数;不要按对齐数多算,否则踩到相邻 tile。
|
|
67
|
+
- **输出**:`DataCopyPad` 写回同样传真实 `tile` 字节,不会越界写。
|
|
68
|
+
|
|
69
|
+
> 即:连续布局下尾块非对齐**全部由 DataCopyPad 兜底**,开发者不需要额外分支。仅当用 `DataCopy`(非 Pad)搬非对齐数据时才需自己 padding。
|
|
70
|
+
|
|
71
|
+
## 4. 大 shape 无广播(BRC_NONE)
|
|
72
|
+
|
|
73
|
+
无广播的大 shape(cann-bench case 4/5/6)和广播输入**共用同一套切分**:`ComputeTiling` 只看输出 shape,与是否广播无关。BRC_NONE 输入在 kernel 走 `CopyInPlain`,其 `len = rows * inputStrides[ubSplitAxis]`,因 stride 与输出一致即为 `tile`,天然支持尾轴被切。所以"无广播但 shape 很大"无需特殊处理——切分通用化后自动覆盖。
|
|
74
|
+
|
|
75
|
+
## 5. NDDMA 在 ubSplitAxis≠0 的参数装配
|
|
76
|
+
|
|
77
|
+
`MakeNddmaParams` / `BroadcastNddma` 已按 `ubSplitAxis` 参数化,`ubSplitSize` 语义是「**切分轴方向本 tile 的元素/行数**」:
|
|
78
|
+
|
|
79
|
+
- `ubSplitAxis = 0`:`ubSplitSize = rows`(行数)。
|
|
80
|
+
- `ubSplitAxis = rank-1`(切尾轴):`ubSplitSize = ubFormer`(尾轴一段的元素数),`axisInsideUb = NDDMA_DIM-1`,只填切分轴一维 + 高位补 1。
|
|
81
|
+
|
|
82
|
+
`axisInsideUb = NDDMA_DIM - (shapeLen - ubSplitAxis)`:rank 越大、切分轴越靠外,需补的 size=1 高位轴越少。**前置条件 `rank = shapeLen - ubSplitAxis ≤ NDDMA_DIM(5)`**;超过时 Host 选型回退 ③(`PickBroadcastMode`),官方 atvoss 则走 with-loop NDDMA(本样例未实现)。
|
|
83
|
+
|
|
84
|
+
## 6. cann-bench case 对照
|
|
85
|
+
|
|
86
|
+
| case | shape / dtype | 切分结果(ComputeTiling) |
|
|
87
|
+
|------|--------------|------------------------|
|
|
88
|
+
| 4 | int32 8192×8192 | 尾轴 8192 > elemNum → 切尾轴(ubSplitAxis=1),ubFormer=elemNum;无广播走 BRC_NONE |
|
|
89
|
+
| 7/8/9 | 质数非对齐 shape | ubTail 非对齐 → DataCopyPad 自动兜底 |
|
|
90
|
+
| 10 | fp16 363×367×373 | 尾轴 373 若 ≤ elemNum 则切中间轴(ubSplitAxis=1),dimProductBeforeUbInner=363×ubOuter |
|
|
91
|
+
|
|
92
|
+
> 这些 case 现在都能由通用切分覆盖;写死 ubSplitAxis=0 的旧样例会在 case 4/10 上因「一行放不进 UB」失败。
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# AscendC Broadcast 性能优化与实现选型指导(总览)
|
|
2
|
+
|
|
3
|
+
> 广播算子的性能关键在于**按场景选对实现**(前置 OneDim 快路径 + tile 内 NDDMA / DataCopyPad / UB 三类)——选错直接慢甚至 nan,选对才快。本文即该选型的最佳实践。
|
|
4
|
+
|
|
5
|
+
> 纯 **AscendC API** 指导,不依赖任何模板调度框架。提炼自 atvoss broadcast 的设计经验,只保留两块可直接迁移的内容:**Tiling 选型/切分逻辑** 与 **OneDim 快路径 + 三类 Kernel 广播写法**。
|
|
6
|
+
> 适用:DAV_3510(A5 / Ascend950,C310)。广播 = 某输入在某些轴上 shape=1 / stride=0,需铺开到输出 shape。
|
|
7
|
+
|
|
8
|
+
## 文档结构
|
|
9
|
+
|
|
10
|
+
| 文件 | 内容 |
|
|
11
|
+
|------|------|
|
|
12
|
+
| **broadcast_design.md**(本文) | 总览、实现速查、Tiling 选型与切分逻辑、决策树、约束 |
|
|
13
|
+
| [onedim_design.md](onedim_design.md) | 实现④ OneDim 合轴塌一维快路径(标量广播)★前置优先 |
|
|
14
|
+
| [nddma_design.md](nddma_design.md) | 实现① NDDMA 搬入即广播 |
|
|
15
|
+
| [datacopypad_design.md](datacopypad_design.md) | 实现② DataCopyPad 紧凑搬入 + 复用 |
|
|
16
|
+
| [ub_broadcast_design.md](ub_broadcast_design.md) | 实现③ UB 内 Broadcast 指令 |
|
|
17
|
+
| [advanced_tiling.md](advanced_tiling.md) | 进阶:通用切分(任意 ubSplitAxis / 大 shape / 尾块非对齐 / cann-bench case) |
|
|
18
|
+
| [code/broadcast_tiling_common.h](code/broadcast_tiling_common.h) | 常量 / TilingData / `ComputeTiling` / 切分 helper / 四类广播原语(含 OneDim) |
|
|
19
|
+
| [code/broadcast_add_tiling.cpp](code/broadcast_add_tiling.cpp) | 端到端样例(①②③ 多维选型):Host(选型 + 切分) |
|
|
20
|
+
| [code/broadcast_add_kernel.cpp](code/broadcast_add_kernel.cpp) | 端到端样例(①②③ 多维选型):Kernel + 算子入口 |
|
|
21
|
+
| [code/onedim_add_tiling.cpp](code/onedim_add_tiling.cpp) | 端到端样例(④ OneDim 标量广播):Host(`TryOneDim` + 极简切分) |
|
|
22
|
+
| [code/onedim_add_kernel.cpp](code/onedim_add_kernel.cpp) | 端到端样例(④ OneDim 标量广播):Kernel + 算子入口 |
|
|
23
|
+
|
|
24
|
+
## 0. 实现速查(一个前置快路径 + tile 内三类)
|
|
25
|
+
|
|
26
|
+
| # | 实现 | 广播在哪发生 | 核心 AscendC API | 占用单元 | 典型适用 |
|
|
27
|
+
|---|------|------------|-----------------|---------|---------|
|
|
28
|
+
| ④ | [**OneDim 合轴塌一维**](onedim_design.md) ★前置 | 标量首块 Duplicate / 满输入直搬 | `Duplicate(ub,scalar,len)` + `DataCopyPad` | Vector(标量铺) / MTE2 | **合轴后塌一维**:每输入要么满 shape 要么纯标量(标量广播、同 shape elementwise) |
|
|
29
|
+
| ① | [**NDDMA 搬入即广播**](nddma_design.md) | GM→UB 搬运中 | `DataCopy<T,DIM,cfg>(ub,gm,MultiCopyParams)`,广播轴 `loopSrcStride=0` | MTE2(DMA),不占 Vector | 大 dtype(FP32/INT32)等、或 B8/B16 尾轴非对齐;**切分轴本身是广播轴** |
|
|
30
|
+
| ② | [**DataCopyPad(外层广播,offset 寻址)**](datacopypad_design.md) | 不在搬运中,靠 GM offset(外层广播轴 stride=0) | `DataCopyPad(ub,gm,ext,pad)` 每轮搬一段连续数据 | MTE2,不占 Vector | 广播轴**全在切分轴之上(外层)**、切分轴连续 |
|
|
31
|
+
| ③ | [**UB 内 Broadcast 指令**](ub_broadcast_design.md) | UB 内 | `Broadcast<T,R>(dst,src,dstShape,srcShape,&tiling)` | Vector | **前提广播轴在 tile 内(brcInTile)**;且:尾轴对齐且 dtype∈{INT8,UINT8,FP16,BF16,INT16,UINT16},或非尾轴广播且尾轴≥dcache/2(~4096B),或广播中间计算结果 |
|
|
32
|
+
|
|
33
|
+
**判断口诀(按优先级)**:**先试 ④**——合轴后能塌一维(每个输入要么满 shape、要么纯标量)就走 OneDim(标量首块 Duplicate、tiling 退化 1D、固定成本最低),命中即用。塌不成一维(部分轴广播,如 `[M,1]/[1,N]`)才进 ①②③:先看广播轴在不在 UB tile 内。**全在 tile 外(外层循环轴)→ 一律 ②**(offset 寻址每轮连续搬;UB 指令和 NDDMA 都展不了外层轴)。在 tile 内才在 ③/① 间选:尾轴对齐的小字节类型(B8/B16)或尾轴非广播的 BigNLast → ③(Vector 吞吐高),其余 → ①(DMA 不占 Vector)。
|
|
34
|
+
|
|
35
|
+
## 1. Tiling 逻辑(Host)
|
|
36
|
+
|
|
37
|
+
### 1.1 统一的切分模型
|
|
38
|
+
|
|
39
|
+
无论哪类实现,切分都是两层(与普通 elementwise 一致),对象始终是**输出 shape**:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
多核切分:blockNum 个核,每核处理 blockFormer 个「UB 外循环单元」,尾核 blockTail
|
|
43
|
+
UB 切分:选 ubSplitAxis 轴,每次处理 ubFormer 行(尾块 ubTail),共 ubOuter 次外循环
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
TilingData 字段见 [`code/broadcast_tiling_common.h`](code/broadcast_tiling_common.h) 的 `BroadcastTilingData`,可直接照搬。关键字段:`inputStrides`(广播轴=0)、`outputDims/Strides`、`ubSplitAxis/ubFormer/ubOuter`、`blockNum/blockFormer`、`dimProductBeforeUbInner`(UB tile 总数)、`elemNum`。
|
|
47
|
+
|
|
48
|
+
> **`ubSplitAxis` 不要写死成 0**。尾轴常超 UB 容量(如 8192 fp32),必须按输出 shape 动态选切分轴、必要时切到尾轴内部。通用选轴 + 完整公式(含 `dimProductBeforeUbInner` 通用式、大 shape、尾块非对齐)见 [advanced_tiling.md](advanced_tiling.md) 与 `ComputeTiling`。下文 §1.2–1.4 给要点。
|
|
49
|
+
|
|
50
|
+
### 1.2 广播轴识别
|
|
51
|
+
|
|
52
|
+
**广播轴 = 该输入 `inputStrides[i][axis]==0` 且 `outputStrides[axis]!=0`。** 这是所有判断的基础(不是只看 dim==1)。**必须扫描所有轴**得到三个标志,不能只取第一个广播轴(否则同时有外层广播轴和 tile 内广播轴时会误判):
|
|
53
|
+
|
|
54
|
+
```cpp
|
|
55
|
+
bool anyBrc = false, brcInTile = false, nonLastBrc = false, lastAxisBrc = false;
|
|
56
|
+
for (int j = 0; j < shapeLen; j++) {
|
|
57
|
+
if (inputStrides[i][j] == 0 && outputStrides[j] != 0) {
|
|
58
|
+
anyBrc = true;
|
|
59
|
+
if (j >= ubSplitAxis) brcInTile = true; // 广播轴落在 UB tile 内(含尾轴)
|
|
60
|
+
if (j < shapeLen - 1) nonLastBrc = true; // 存在非尾轴广播
|
|
61
|
+
else lastAxisBrc = true; // 尾轴本身是广播轴
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 1.3 三类选型决策(每个广播输入独立判断)
|
|
67
|
+
|
|
68
|
+
> **前置:先试 OneDim(④)。** 进入下面的逐输入 `PickBroadcastMode` 之前,先 `TryOneDim`——若合轴后塌成一维(每个输入要么满 shape 要么纯标量),整算子走 OneDim 快路径(`ComputeOneDimTiling` + 标量 `Duplicate`),不再做三类切分。详见 [onedim_design.md](onedim_design.md)。塌不成一维(部分轴广播)才执行下面的三类选型。
|
|
69
|
+
|
|
70
|
+
```cpp
|
|
71
|
+
int PickBroadcastMode(int i) { // 承接 §1.2 扫描得到的 anyBrc/brcInTile/nonLastBrc/lastAxisBrc
|
|
72
|
+
if (!anyBrc) return 0; // 非广播输入,普通 CopyIn
|
|
73
|
+
if (!brcInTile) return 2; // ★广播轴严格在外层 → ② DataCopyPad(offset 寻址;切分轴非广播,len 公式成立)
|
|
74
|
+
|
|
75
|
+
// ★「在 tile 内」≠「UB 能展开」:切分轴广播但 ubFormer==1 时 tile 内仅 1 行(dShape==sShape),
|
|
76
|
+
// UB Broadcast 退化空广播 → nan。只有存在真正可展开维(dst>src)才可选 ③,否则走 ① NDDMA。
|
|
77
|
+
bool inTileExpandable = false;
|
|
78
|
+
for (int j = ubSplitAxis+1; j < shapeLen; j++)
|
|
79
|
+
if (inputStrides[i][j]==0 && outputDims[j]>1) inTileExpandable = true; // 切分轴以下广播
|
|
80
|
+
if (inputStrides[i][ubSplitAxis]==0 && outputDims[ubSplitAxis]>1 && ubFormer>1)
|
|
81
|
+
inTileExpandable = true; // 切分轴广播且多行
|
|
82
|
+
|
|
83
|
+
int64_t lastDim = outputDims[shapeLen - 1], dt = sizeof(T_i), alignEle = 32 / dt;
|
|
84
|
+
static const set<DataType> kUb = {DT_INT8,DT_UINT8,DT_FLOAT16,DT_BF16,DT_INT16,DT_UINT16};
|
|
85
|
+
if (inTileExpandable) {
|
|
86
|
+
if (lastDim % alignEle == 0 && kUb.count(dtype_i)) return 3; // ①尾轴对齐+B8/B16 → ③
|
|
87
|
+
if (nonLastBrc && !lastAxisBrc && lastDim*dt >= GetNddmaDcacheSize()/2) return 3; // ②BigNLast → ③
|
|
88
|
+
}
|
|
89
|
+
if (shapeLen - ubSplitAxis > NDDMA_DIM) return 3; // rank>5 without-loop NDDMA 装不下 → ③(含退化守卫兜底)
|
|
90
|
+
return 1; // 其余 tile 内广播 → ① NDDMA
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`brcMode` 逐输入写进 TilingData / tilingKey,kernel 据此分发。完整实现见 [`code/broadcast_add_tiling.cpp`](code/broadcast_add_tiling.cpp)。两道关键门控(cann-bench Maximum case 18 实测):
|
|
95
|
+
1. **`!brcInTile`(广播轴严格在外层)→ 一律 ②**:UB/NDDMA 只在 tile 内展开,外层轴只能靠 offset 寻址。
|
|
96
|
+
2. **`brcInTile` 但无可展开维(切分轴广播且 `ubFormer==1`)且 `rank≤5` → ① NDDMA**:此时 UB Broadcast 会 `dShape==sShape` 空广播出 nan;NDDMA 在 `ubFormer==1` 下搬 inner 连续数据、外层靠 offset 广播仍正确。(`rank>5` 时 without-loop NDDMA 装不下 → 仍走 ③,由 kernel `UbBroadcast` 退化守卫拷贝兜底。)kernel `UbBroadcast` 的退化守卫(无可展开维则拷贝)对两种情形都做双保险。
|
|
97
|
+
|
|
98
|
+
### 1.4 切分大小与选轴(`ComputeTiling`)
|
|
99
|
+
|
|
100
|
+
```cpp
|
|
101
|
+
elemNum = AlignDown( ubSize / (aliveBufferNum * maxDtypeBytes * DB_LOOP), alignEle );
|
|
102
|
+
// 从尾轴向外累乘选切分轴:能整轴塞进 elemNum 就继续向外;放不下则切该轴;
|
|
103
|
+
// 连尾轴一行都放不下 → 切尾轴本身(ubFormer = elemNum)
|
|
104
|
+
// ubFormer/ubOuter/ubTail 沿 ubSplitAxis 算;ubTail 可非对齐(DataCopyPad 兜底)
|
|
105
|
+
dimProductBeforeUbInner = (∏ outputDims[0 .. ubSplitAxis-1]) × ubOuter // UB tile 总数,通用公式
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
完整实现 `ComputeTiling` 见 [`code/broadcast_tiling_common.h`](code/broadcast_tiling_common.h),推导与 cann-bench case 对照见 [advanced_tiling.md](advanced_tiling.md)。
|
|
109
|
+
|
|
110
|
+
`aliveBufferNum`:③ 需额外一块放广播前的紧凑源(src+dst 两块),①② 直接铺到目标块(一块)——选 ③ 的输入要把这块计入预算。
|
|
111
|
+
|
|
112
|
+
## 2. 各实现
|
|
113
|
+
|
|
114
|
+
各实现的适用、Kernel 写法、注意见分册:[④ OneDim(前置)](onedim_design.md)、[① NDDMA](nddma_design.md)、[② DataCopyPad](datacopypad_design.md)、[③ UB Broadcast](ub_broadcast_design.md)。原语统一在 [`code/broadcast_tiling_common.h`](code/broadcast_tiling_common.h):① ② ③ 为 `BroadcastNddma` / `DataCopyPadCompact` / `UbBroadcast`(通用切分 `ComputeTiling`,helper `GetAxesIndices`/`UpdateAxesIndices`/`GetGmOffset`/`FillUbShape`/`UbSrcLen`);④ 为 `TryOneDim` / `ComputeOneDimTiling` / `OneDimCalcCore` / `OneDimLoadInput`。
|
|
115
|
+
|
|
116
|
+
端到端串接见样例 [Host](code/broadcast_add_tiling.cpp) + [Kernel](code/broadcast_add_kernel.cpp)。
|
|
117
|
+
|
|
118
|
+
## 3. 选型决策树
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
★ 前置:合轴后塌成一维吗?(每个输入要么满 shape、要么纯标量 → TryOneDim)
|
|
122
|
+
├─ 是 → ④ OneDim 快路径(标量首块 Duplicate、满输入直搬;tiling 退化 1D) ——命中即用,整算子走此路
|
|
123
|
+
└─ 否(部分轴广播,如 [M,1]/[1,N])↓ 进入逐输入三类选型
|
|
124
|
+
|
|
125
|
+
该输入是广播输入吗?(存在 stride==0 轴) ——按从上到下的优先级匹配
|
|
126
|
+
├─ 否 → 普通 DataCopyPad 搬入(brcMode=0)
|
|
127
|
+
└─ 是:
|
|
128
|
+
├─ 广播轴严格在外层(brcInTile=false) → ② DataCopyPad ★必须先判!外层轴只能 offset 寻址
|
|
129
|
+
└─ 广播轴在 UB tile 内(brcInTile=true):
|
|
130
|
+
├─ rank=(shapeLen-ubSplitAxis) > 5 → ③(without-loop NDDMA 装不下;UB 退化守卫兜底无可展开维的情形)
|
|
131
|
+
├─ 有可展开维(inTileExpandable:切分轴以下广播,或切分轴广播且 ubFormer>1):
|
|
132
|
+
│ ├─ 尾轴对齐 且 dtype∈{INT8,UINT8,FP16,BF16,INT16,UINT16} → ③ UB-BRC
|
|
133
|
+
│ ├─ 尾轴非广播 且 存在非尾轴广播 且 尾轴字节 ≥ dcache/2(~4096B) → ③ UB-BRC (BigNLast)
|
|
134
|
+
│ └─ 其余 → ① NDDMA
|
|
135
|
+
└─ 无可展开维(切分轴广播且 ubFormer==1,tile 内仅 1 行) → ① NDDMA ★走 ③ 会 dShape==sShape 空广播出 nan
|
|
136
|
+
注:实际代码 rank>5 在 ①② 之后判(可展开时①②仍优先),但对"无可展开维"分支也生效——见 broadcast_add_tiling.cpp。
|
|
137
|
+
官方 atvoss rank>5 走 with-loop NDDMA(SCH_MODE_NDDMA_WITH_LOOP_CACHE_BRC),本样例未实现故回退 ③。
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## 4. 自检清单
|
|
141
|
+
|
|
142
|
+
- [ ] ④ OneDim 前置:`TryOneDim` 命中(每输入满 shape 或纯标量)即走快路径,标量走单块 `TBuf` 首块 `Duplicate`、不进双缓冲队列;`ComputeOneDimTiling` 只给 `dimLen/tileNum/blockNum`,切分由 kernel `OneDimCalcCore` 运行期推
|
|
143
|
+
- [ ] 广播轴判定基于 `inputStrides[i][axis]==0 && outputStrides[axis]!=0`,不是只看 dim==1
|
|
144
|
+
- [ ] `brcMode` 逐输入计算并写入 TilingData/tilingKey,kernel 分支与之一一对应
|
|
145
|
+
- [ ] ① NDDMA:广播轴 `loopSrcStride=0`、非广播轴填真实 stride;维数 ≤ 5(否则套循环)
|
|
146
|
+
- [ ] ② DataCopyPad:广播靠 `GetGmOffset`(外层广播轴 stride=0),每轮连续搬即可;复用为可选优化且判据用 offset 比较(非切分轴 stride,后者是死路径)
|
|
147
|
+
- [ ] 切分:用 `ComputeTiling` 动态选 ubSplitAxis,`dimProductBeforeUbInner=∏outputDims[0..split-1]×ubOuter`;尾轴超 UB 时切到尾轴;尾块非对齐由 DataCopyPad 兜底
|
|
148
|
+
- [ ] ③ UB-BRC:`elemNum` 预算多留一块紧凑源;rank 静态(≤4)可走编译期 `Broadcast<T,R>`;尾块修正 shape 首轴
|
|
149
|
+
- [ ] DoubleBuffer:`elemNum` 已按 `aliveBufferNum * dtypeBytes * 2` 反推
|
|
150
|
+
- [ ] 精度:与 naive 全展开实现对比,FP32 < 1e-5、FP16 < 1e-3
|
|
151
|
+
|
|
152
|
+
## 5. 约束与适用范围
|
|
153
|
+
|
|
154
|
+
- 平台:DAV_3510(C310)。`MultiCopy`/NDDMA 多维 DMA 与 `Broadcast` 指令均为该架构 AscendC API。
|
|
155
|
+
- 维度上限:建议 `BROADCAST_MAX_DIMS = 8`;单次 NDDMA `NDDMA_DIM = 5`。
|
|
156
|
+
- `BLOCK_LENGTH = 32`(字节),对齐元素数 = `32 / sizeof(dtype)`。
|
|
157
|
+
- 只覆盖**连续布局**广播;转置/非连续布局需搬运前做 layout 处理,不在本文范围。
|
|
158
|
+
- ④ OneDim 是**整算子级**的前置分流(合轴塌一维则全算子走它);①②③ 是塌不成一维时**逐输入混用**(不同输入走不同 brcMode),均由 tiling 决定。
|
|
159
|
+
- 对标 atvoss 连续布局四个调度模式:① ↔ NDDMA without/with-loop(schMode 1/2)、③ ↔ UB_BROADCAST(101~109)、④ ↔ ONE_DIM_ADVANCE/ONE_DIM(202/201);非连续布局族(transpose 等)不在本文范围。
|
|
160
|
+
- 代码为**范式级**:`AlignDown/CeilDiv/GET_TILING_DATA/DTYPE_X` 等按工程宏/惯例占位,落地需接 op proto / REGISTER / tiling 注册 / 对齐校验等工程件。
|
|
@@ -0,0 +1,126 @@
|
|
|
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
|
+
* \file broadcast_add_kernel.cpp
|
|
13
|
+
* \brief 端到端样例(Kernel 侧):z = x + y,演示「§7 helper 还原下标 → 逐输入按 brcMode 走三类写法」。
|
|
14
|
+
* 范式级代码:GET_TILING_DATA / DTYPE_X 等按工程宏占位。
|
|
15
|
+
*/
|
|
16
|
+
#include "broadcast_tiling_common.h"
|
|
17
|
+
|
|
18
|
+
namespace BrcDemo {
|
|
19
|
+
|
|
20
|
+
template <typename T>
|
|
21
|
+
class BroadcastAdd {
|
|
22
|
+
public:
|
|
23
|
+
static constexpr int IN_NUM = 2;
|
|
24
|
+
using TD = BroadcastTilingData<IN_NUM>;
|
|
25
|
+
|
|
26
|
+
__aicore__ inline void Init(GM_ADDR x, GM_ADDR y, GM_ADDR z, const TD& t)
|
|
27
|
+
{
|
|
28
|
+
td_ = t;
|
|
29
|
+
xGm_.SetGlobalBuffer((__gm__ T*)x);
|
|
30
|
+
yGm_.SetGlobalBuffer((__gm__ T*)y);
|
|
31
|
+
zGm_.SetGlobalBuffer((__gm__ T*)z);
|
|
32
|
+
pipe_.InitBuffer(qx_, 2, td_.elemNum * sizeof(T));
|
|
33
|
+
pipe_.InitBuffer(qy_, 2, td_.elemNum * sizeof(T));
|
|
34
|
+
pipe_.InitBuffer(qz_, 2, td_.elemNum * sizeof(T));
|
|
35
|
+
pipe_.InitBuffer(bufSrc_, td_.elemNum * sizeof(T)); // ③ 用:广播前紧凑源
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
__aicore__ inline void Process()
|
|
39
|
+
{
|
|
40
|
+
int64_t loops = (GetBlockIdx() == td_.blockNum - 1) ? td_.blockTail : td_.blockFormer;
|
|
41
|
+
int64_t axes[BROADCAST_MAX_DIMS] = {0};
|
|
42
|
+
GetAxesIndices(
|
|
43
|
+
axes, td_.blockFormer * GetBlockIdx(), td_.outputDims, td_.ubSplitAxis, td_.dimProductBeforeUbInner);
|
|
44
|
+
for (int64_t loop = 0; loop < loops; loop++) {
|
|
45
|
+
if (loop != 0)
|
|
46
|
+
UpdateAxesIndices(axes, td_.outputDims, td_.ubSplitAxis, td_.ubOuter);
|
|
47
|
+
int64_t rows = (axes[td_.ubSplitAxis] == td_.ubOuter - 1) ? td_.ubTail : td_.ubFormer;
|
|
48
|
+
int64_t tile = rows * td_.outputStrides[td_.ubSplitAxis]; // 本 tile 元素数
|
|
49
|
+
|
|
50
|
+
// --- x:普通搬入 ---
|
|
51
|
+
LocalTensor<T> xl = qx_.template AllocTensor<T>();
|
|
52
|
+
CopyInPlain(xGm_, xl, 0, axes, rows);
|
|
53
|
+
qx_.EnQue(xl);
|
|
54
|
+
// --- y:按 brcMode 走三类之一 ---
|
|
55
|
+
LocalTensor<T> yl = qy_.template AllocTensor<T>();
|
|
56
|
+
LoadBroadcastInput(yl, 1, axes, rows, tile);
|
|
57
|
+
qy_.EnQue(yl);
|
|
58
|
+
// --- 计算 + 输出 ---
|
|
59
|
+
LocalTensor<T> xv = qx_.template DeQue<T>();
|
|
60
|
+
LocalTensor<T> yv = qy_.template DeQue<T>();
|
|
61
|
+
LocalTensor<T> zv = qz_.template AllocTensor<T>();
|
|
62
|
+
AscendC::Add(zv, xv, yv, tile);
|
|
63
|
+
qz_.EnQue(zv);
|
|
64
|
+
qx_.FreeTensor(xv);
|
|
65
|
+
qy_.FreeTensor(yv);
|
|
66
|
+
LocalTensor<T> zo = qz_.template DeQue<T>();
|
|
67
|
+
int64_t zoff = GetGmOffset(axes, td_.outputStrides, td_.ubSplitAxis, td_.ubFormer);
|
|
68
|
+
AscendC::DataCopyExtParams ext{1, (uint32_t)(tile * sizeof(T)), 0, 0, 0};
|
|
69
|
+
AscendC::DataCopyPad(zGm_[zoff], zo, ext);
|
|
70
|
+
qz_.FreeTensor(zo);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private:
|
|
75
|
+
__aicore__ inline void CopyInPlain(
|
|
76
|
+
const GlobalTensor<T>& gm, const LocalTensor<T>& ub, int i, const int64_t (&axes)[BROADCAST_MAX_DIMS],
|
|
77
|
+
int64_t rows)
|
|
78
|
+
{
|
|
79
|
+
int64_t off = GetGmOffset(axes, td_.inputStrides[i], td_.ubSplitAxis, td_.ubFormer);
|
|
80
|
+
int64_t len = rows * td_.inputStrides[i][td_.ubSplitAxis];
|
|
81
|
+
DataCopyPadCompact(gm[off], ub, len);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// 三类广播分发
|
|
85
|
+
__aicore__ inline void LoadBroadcastInput(
|
|
86
|
+
const LocalTensor<T>& dst, int i, const int64_t (&axes)[BROADCAST_MAX_DIMS], int64_t rows, int64_t tile)
|
|
87
|
+
{
|
|
88
|
+
int64_t off = GetGmOffset(axes, td_.inputStrides[i], td_.ubSplitAxis, td_.ubFormer);
|
|
89
|
+
if (td_.brcMode[i] == BRC_NONE) { // 非广播输入:普通紧凑搬入
|
|
90
|
+
int64_t len = rows * td_.inputStrides[i][td_.ubSplitAxis];
|
|
91
|
+
DataCopyPadCompact(yGm_[off], dst, len);
|
|
92
|
+
} else if (td_.brcMode[i] == BRC_NDDMA) { // ①
|
|
93
|
+
BroadcastNddma(
|
|
94
|
+
yGm_[off], dst, td_.outputDims, td_.outputStrides, td_.inputStrides[i], td_.shapeLen, td_.ubSplitAxis,
|
|
95
|
+
rows);
|
|
96
|
+
} else if (td_.brcMode[i] == BRC_DATACOPYPAD) { // ②:广播轴全在外层
|
|
97
|
+
// 广播由 GetGmOffset 的 stride=0 寻址实现:外层广播轴推进时 off 不变 → 取到同一段 GM。
|
|
98
|
+
// 每轮搬运(正确且安全);可选复用见 datacopypad_design.md(本样例未启用)。
|
|
99
|
+
int64_t len = rows * td_.inputStrides[i][td_.ubSplitAxis]; // 切分轴非广播,len=tile
|
|
100
|
+
DataCopyPadCompact(yGm_[off], dst, len);
|
|
101
|
+
} else { // ③ BRC_UB
|
|
102
|
+
LocalTensor<T> src = bufSrc_.template Get<T>();
|
|
103
|
+
int64_t srcLen = UbSrcLen(td_.inputStrides[i], td_.inputDims[i], td_.ubSplitAxis, td_.shapeLen, rows);
|
|
104
|
+
DataCopyPadCompact(yGm_[off], src, srcLen);
|
|
105
|
+
UbBroadcast(dst, src, td_.outputDims, td_.inputDims[i], td_.ubSplitAxis, td_.shapeLen, rows);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
TPipe pipe_;
|
|
110
|
+
TQue<TPosition::VECIN, 2> qx_, qy_;
|
|
111
|
+
TQue<TPosition::VECOUT, 2> qz_;
|
|
112
|
+
TBuf<TPosition::VECCALC> bufSrc_;
|
|
113
|
+
GlobalTensor<T> xGm_, yGm_, zGm_;
|
|
114
|
+
TD td_;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
} // namespace BrcDemo
|
|
118
|
+
|
|
119
|
+
// 算子入口
|
|
120
|
+
extern "C" __global__ __aicore__ void broadcast_add(GM_ADDR x, GM_ADDR y, GM_ADDR z, GM_ADDR workspace, GM_ADDR tiling)
|
|
121
|
+
{
|
|
122
|
+
GET_TILING_DATA(td, tiling); // 解析 BroadcastTilingData<2>
|
|
123
|
+
BrcDemo::BroadcastAdd<DTYPE_X> op;
|
|
124
|
+
op.Init(x, y, z, td);
|
|
125
|
+
op.Process();
|
|
126
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
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
|
+
* \file broadcast_add_tiling.cpp
|
|
13
|
+
* \brief 端到端样例(Host 侧):z = x + y,演示「识别广播轴 → 两层切分 → 逐输入选 brcMode」。
|
|
14
|
+
* 范式级代码:AlignDown/CeilDiv/平台查询等按工程惯例占位,落地需接 op proto / tiling 注册。
|
|
15
|
+
* 输出 [M, N];x 满 shape;y = [1,N](外层广播)或 [M,1](尾轴广播)。
|
|
16
|
+
*/
|
|
17
|
+
#include <set>
|
|
18
|
+
#include <algorithm>
|
|
19
|
+
#include "broadcast_tiling_common.h"
|
|
20
|
+
|
|
21
|
+
namespace BrcDemo {
|
|
22
|
+
|
|
23
|
+
constexpr int IN_NUM = 2; // x, y
|
|
24
|
+
using TD = BroadcastTilingData<IN_NUM>;
|
|
25
|
+
|
|
26
|
+
// 广播轴扫描结果:把 PickBroadcastMode 里「扫描所有轴得到的布尔标志」聚合成小结构体,
|
|
27
|
+
// 便于主函数据此选型,同时降低主函数圈复杂度(选型语义不变)。
|
|
28
|
+
struct BrcAxisFlags {
|
|
29
|
+
bool anyBrc; // 存在任意广播轴
|
|
30
|
+
bool brcInTile; // 广播轴落在 UB tile 内(含尾轴)
|
|
31
|
+
bool nonLastBrc; // 存在非尾轴广播
|
|
32
|
+
bool lastAxisBrc; // 尾轴本身是广播轴
|
|
33
|
+
bool inTileExpandable; // tile 内存在真正可展开维(dst>src)
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// 扫描所有轴,判定各广播标志(与原 PickBroadcastMode 内联逻辑逐条等价)。
|
|
37
|
+
static BrcAxisFlags AnalyzeBroadcastAxes(const TD& td, int i)
|
|
38
|
+
{
|
|
39
|
+
BrcAxisFlags f{false, false, false, false, false};
|
|
40
|
+
for (int64_t j = 0; j < td.shapeLen; j++) {
|
|
41
|
+
if (td.inputStrides[i][j] == 0 && td.outputStrides[j] != 0) {
|
|
42
|
+
f.anyBrc = true;
|
|
43
|
+
if (j >= td.ubSplitAxis)
|
|
44
|
+
f.brcInTile = true; // 广播轴落在 UB tile 内(含尾轴)
|
|
45
|
+
if (j < td.shapeLen - 1)
|
|
46
|
+
f.nonLastBrc = true; // 存在非尾轴广播
|
|
47
|
+
else
|
|
48
|
+
f.lastAxisBrc = true; // 尾轴本身是广播轴
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// 「在 tile 内」不等于「UB 能展开」:切分轴是广播轴且 ubFormer==1 时 tile 内仅 1 行(dShape==sShape)。
|
|
52
|
+
for (int64_t j = td.ubSplitAxis + 1; j < td.shapeLen; j++) // 切分轴以下某轴广播
|
|
53
|
+
if (td.inputStrides[i][j] == 0 && td.outputDims[j] > 1)
|
|
54
|
+
f.inTileExpandable = true;
|
|
55
|
+
if (td.inputStrides[i][td.ubSplitAxis] == 0 && td.outputDims[td.ubSplitAxis] > 1 && td.ubFormer > 1)
|
|
56
|
+
f.inTileExpandable = true; // 切分轴广播且 tile 内多行
|
|
57
|
+
return f;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// dtype 是否属于 UB Broadcast 集合(B8/B16)。
|
|
61
|
+
static bool IsUbBroadcastDtype(ge::DataType dtype)
|
|
62
|
+
{
|
|
63
|
+
static const std::set<ge::DataType> kUb = {ge::DT_INT8, ge::DT_UINT8, ge::DT_FLOAT16,
|
|
64
|
+
ge::DT_BF16, ge::DT_INT16, ge::DT_UINT16};
|
|
65
|
+
return kUb.count(dtype) != 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 三类选型(见 broadcast_design.md §1.3)。须扫描所有轴,区分「tile 内是否有广播轴」与
|
|
69
|
+
// 「是否所有广播轴都在切分轴之上」,不能只看第一个广播轴。dcache 阈值用平台查询,源码注释约 4096B。
|
|
70
|
+
static int PickBroadcastMode(const TD& td, int i, int dtSize, ge::DataType dtype, int64_t nddmaDcache)
|
|
71
|
+
{
|
|
72
|
+
BrcAxisFlags f = AnalyzeBroadcastAxes(td, i);
|
|
73
|
+
if (!f.anyBrc)
|
|
74
|
+
return BRC_NONE;
|
|
75
|
+
|
|
76
|
+
// ★ 广播轴全在外层(tile 外,严格 < ubSplitAxis)→ ② DataCopyPad(外层广播靠 GetGmOffset 的
|
|
77
|
+
// stride=0 寻址;此时切分轴非广播,len=rows*stride 成立)。必须先判,否则 ②的 len 公式会错。
|
|
78
|
+
if (!f.brcInTile)
|
|
79
|
+
return BRC_DATACOPYPAD;
|
|
80
|
+
|
|
81
|
+
// 广播轴在 tile 内(≥ubSplitAxis)。但「在 tile 内」不等于「UB 能展开」:
|
|
82
|
+
// 切分轴是广播轴且 ubFormer==1 时,tile 内该轴只有 1 行(dShape==sShape),UB Broadcast 退化成
|
|
83
|
+
// 空广播会出 nan。只有存在真正可展开维(dst>src)时才可选 ③,否则走 ① NDDMA(ubFormer==1 下
|
|
84
|
+
// NDDMA 搬 inner 连续数据 + 外层靠 offset 广播,仍正确)。
|
|
85
|
+
int64_t lastDim = td.outputDims[td.shapeLen - 1];
|
|
86
|
+
int64_t dtBytes = (dtSize > 0) ? dtSize : 1; // 钳制除数,保证静态可证 >=1(G.EXP.22-CPP)
|
|
87
|
+
int64_t alignEle = BLOCK_LENGTH / dtBytes;
|
|
88
|
+
|
|
89
|
+
if (f.inTileExpandable) { // 仅有可展开维才考虑 ③
|
|
90
|
+
if (lastDim % alignEle == 0 && IsUbBroadcastDtype(dtype))
|
|
91
|
+
return BRC_UB; // ①尾轴对齐+B8/B16
|
|
92
|
+
if (f.nonLastBrc && !f.lastAxisBrc && lastDim * dtBytes >= nddmaDcache / 2)
|
|
93
|
+
return BRC_UB; // ②BigNLast
|
|
94
|
+
}
|
|
95
|
+
// rank>5:without-loop NDDMA 装配不下(>NDDMA_DIM 维),本样例未实现 with-loop → 一律退 UB
|
|
96
|
+
// (含 !inTileExpandable:UB 的退化守卫会在无可展开维时拷贝兜底,不会空广播)。
|
|
97
|
+
if (td.shapeLen - td.ubSplitAxis > NDDMA_DIM)
|
|
98
|
+
return BRC_UB;
|
|
99
|
+
return BRC_NDDMA; // 其余 tile 内广播 → ① NDDMA
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 简化的切分入口(省略 context 取值/校验)
|
|
103
|
+
ge::graphStatus AddBrcTiling(
|
|
104
|
+
TD& td, int64_t M, int64_t N, const int64_t yShape[2], int dtSize, ge::DataType dtype, int64_t coreNum,
|
|
105
|
+
int64_t ubSize, int64_t nddmaDcache)
|
|
106
|
+
{
|
|
107
|
+
// ---- 1. shape / stride(输出连续;广播轴 stride=0)----
|
|
108
|
+
td.shapeLen = 2;
|
|
109
|
+
td.outputDims[0] = M;
|
|
110
|
+
td.outputDims[1] = N;
|
|
111
|
+
td.outputStrides[0] = N;
|
|
112
|
+
td.outputStrides[1] = 1;
|
|
113
|
+
// x:满 shape
|
|
114
|
+
td.inputDims[0][0] = M;
|
|
115
|
+
td.inputDims[0][1] = N;
|
|
116
|
+
td.inputStrides[0][0] = N;
|
|
117
|
+
td.inputStrides[0][1] = 1;
|
|
118
|
+
// y 紧凑存储:[1,N] → dims{1,N} stride{0,1}(外层广播);[M,1] → dims{M,1} stride{1,0}(尾轴广播)
|
|
119
|
+
bool yBrcOuter = (yShape[0] == 1);
|
|
120
|
+
td.inputDims[1][0] = yBrcOuter ? 1 : M;
|
|
121
|
+
td.inputDims[1][1] = yBrcOuter ? N : 1;
|
|
122
|
+
td.inputStrides[1][0] = yBrcOuter ? 0 : 1; // [M,1] 行 stride=1(每行 1 个元素),不是 N
|
|
123
|
+
td.inputStrides[1][1] = yBrcOuter ? 1 : 0;
|
|
124
|
+
|
|
125
|
+
// ---- 2. 通用两层切分:自动选 ubSplitAxis,支持尾轴超 UB / 大 shape(见 advanced_tiling.md)----
|
|
126
|
+
// buffer 槽位:x/y/z 各双缓冲(3×2=6) + ③紧凑源单块(1) = 7;这里 4×2=8 取保守上界
|
|
127
|
+
int64_t aliveBuf = 4;
|
|
128
|
+
ComputeTiling(
|
|
129
|
+
td, dtSize, coreNum, ubSize, aliveBuf); // 算 ubSplitAxis/ubFormer/ubOuter/ubTail/
|
|
130
|
+
// dimProductBeforeUbInner/blockNum 等(见 broadcast_tiling_common.h)
|
|
131
|
+
|
|
132
|
+
// ---- 3. 逐输入选 brcMode(依赖上一步算出的 ubSplitAxis)----
|
|
133
|
+
for (int i = 0; i < IN_NUM; i++)
|
|
134
|
+
td.brcMode[i] = PickBroadcastMode(td, i, dtSize, dtype, nddmaDcache);
|
|
135
|
+
// x 满 shape → BRC_NONE。y 的归属由 PickBroadcastMode 按优先级 + 实际 ubSplitAxis 决定:
|
|
136
|
+
// 尾轴对齐且 B8/B16 → BRC_UB;否则看广播轴相对 ubSplitAxis 的位置:
|
|
137
|
+
// 在 tile 内(含切分轴/尾轴) → BRC_NDDMA;全在外层 → BRC_DATACOPYPAD。
|
|
138
|
+
// 注意 ubSplitAxis 现由 ComputeTiling 动态选定(大 N 会切到尾轴),不再恒为 0。
|
|
139
|
+
|
|
140
|
+
// context_->SetBlockDim(td.blockNum); // 落地时设置
|
|
141
|
+
return ge::GRAPH_SUCCESS;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
} // namespace BrcDemo
|