Back to Mnn

步骤 2:分析瓶颈与制定方案

skills/arm-cpu-optimize/step2-analyze.md

3.5.03.7 KB
Original Source

步骤 2:分析瓶颈与制定方案

目标:分析算子的计算特性和瓶颈,制定具体的优化策略。

前置条件:步骤 1 已通过(基线数据已获取)。

复杂度:中(纯分析,不需要编译运行)


2.1 分析计算特性

计算访存比分析

计算量 (FLOPs): ____
访存量 (Bytes): ____
计算访存比 (FLOPs/Byte): ____

判断: ☐ 计算密集(比值高,如 MatMul)
      ☐ 访存密集(比值低,如 element-wise)
      ☐ 混合型

典型参考

  • MatMul [M, K] x [K, N]:计算 2MKN FLOPs,访存 (MK + KN + MN) * bytes
  • Softmax:计算 ~5N FLOPs(exp + sum + div),访存 ~2N * bytes
  • ReLU:计算 N FLOPs,访存 2N * bytes

当前实现分析

阅读当前所要优化的算子的代码,回答:

1. 当前是否使用多线程?________________________________
2. 数据排布是否 Pack 友好?____________________________
3. 是否有不必要的数据拷贝/转换?______________________
4. 循环是否可以向量化?______________________________
5. 是否有跨 cache line 的访存?_______________________

2.2 确定优化方向

根据计算特性选择优化方向:

计算密集型算子(如 MatMul, Conv)

优先顺序:

  1. 数据排布优化:Pack 为 SIMD 友好的格式(eP × lP × hP)
  2. SIMD 指令:使用 NEON/FP16/SDOT/I8MM
  3. 分块 Tiling:适配 L1/L2 Cache 大小
  4. 多线程:按 M 维度或 H 维度划分

访存密集型算子(如 Softmax, LayerNorm)

优先顺序:

  1. 减少访存:合并多个 pass 为一个
  2. SIMD 向量化:一次处理 4/8 个元素
  3. 多线程:注意避免 false sharing
  4. 预取指令__builtin_prefetch

2.3 制定具体方案

markdown
## 优化方案

### 目标
将 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 |

2.4 理解 MNN 的 Pack 参数

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 参数:

指令集ePlPhP主 Kernel 大小
FP32 NEON124812×8 Tile
FP16248824×8 Tile
SDOT INT8124812×8 Tile
I8MM INT8128812×8 Tile
SME2 FP32取决于 SVL取决于 SVL取决于 SVL可变 Tile

查看实际值:调用 gcore->MNNGetMatMulPackMode(&eP, &lP, &hP) 获取当前运行时的 Pack 参数。


步骤 2 测试标准

通过标准

  • 计算特性分析完成(计算密集 / 访存密集)
  • 优化方案文档已编写
  • 方案中明确了要优化的指令集版本
  • 方案中有预期提升的估算

下一步

步骤 2 通过后,进入 step3-cpp-opt.md(步骤 3:C++ 优化)。