skills/arm-cpu-optimize/step2-analyze.md
目标:分析算子的计算特性和瓶颈,制定具体的优化策略。
前置条件:步骤 1 已通过(基线数据已获取)。
复杂度:中(纯分析,不需要编译运行)
计算量 (FLOPs): ____
访存量 (Bytes): ____
计算访存比 (FLOPs/Byte): ____
判断: ☐ 计算密集(比值高,如 MatMul)
☐ 访存密集(比值低,如 element-wise)
☐ 混合型
典型参考:
[M, K] x [K, N]:计算 2MKN FLOPs,访存 (MK + KN + MN) * bytes阅读当前所要优化的算子的代码,回答:
1. 当前是否使用多线程?________________________________
2. 数据排布是否 Pack 友好?____________________________
3. 是否有不必要的数据拷贝/转换?______________________
4. 循环是否可以向量化?______________________________
5. 是否有跨 cache line 的访存?_______________________
根据计算特性选择优化方向:
优先顺序:
优先顺序:
__builtin_prefetch## 优化方案
### 目标
将 Xxx 算子在 ARM64 上的性能从 xx GFLOPS 提升到 xx GFLOPS
### 方案
1. C++ 层:
- [ ] 添加多线程支持(按 xxx 维度划分)
- [ ] 优化数据排布(Pack 为 NC4HW4 / eP×lP)
- [ ] 减少不必要的内存分配
2. 汇编层:
- [ ] FP32 NEON:实现 xxx 的核心内循环
- [ ] FP16:利用 ARMv8.2 FP16 指令,Pack8
- [ ] SDOT/I8MM:INT8 量化版本(如需要)
- [ ] SME2:利用矩阵扩展(如平台支持)
3. 大小核调度:
- [ ] 大核使用 FP16 + I8MM
- [ ] 小核使用 FP32 NEON
### 预期提升
| 指令集 | 预期 GFLOPS | 预期提升 |
|--------|------------|---------|
| C++ 多线程 | xx | ~Nx |
| FP32 NEON | xx | ~Nx |
| FP16 | xx | ~2x over FP32 |
| SDOT | xx | ~Nx |
MNN 的矩阵乘核心函数使用 eP, lP, hP 三个参数来描述分块策略:
A 矩阵 [M, K] → Pack 为 [M/eP, K/lP, eP, lP]
B 矩阵 [K, N] → Pack 为 [N/hP, K/lP, lP, hP]
C 矩阵 [M, N] → Pack 为 [N/hP, M, hP]
不同指令集的 Pack 参数:
| 指令集 | eP | lP | hP | 主 Kernel 大小 |
|---|---|---|---|---|
| FP32 NEON | 12 | 4 | 8 | 12×8 Tile |
| FP16 | 24 | 8 | 8 | 24×8 Tile |
| SDOT INT8 | 12 | 4 | 8 | 12×8 Tile |
| I8MM INT8 | 12 | 8 | 8 | 12×8 Tile |
| SME2 FP32 | 取决于 SVL | 取决于 SVL | 取决于 SVL | 可变 Tile |
查看实际值:调用
gcore->MNNGetMatMulPackMode(&eP, &lP, &hP)获取当前运行时的 Pack 参数。
步骤 2 通过后,进入 step3-cpp-opt.md(步骤 3:C++ 优化)。