skills/arm-cpu-optimize/SKILL.md
触发条件:用户请求优化 ARM CPU 上的 MNN 算子、低 bit GEMM/GEMV kernel、NEON/SDOT/I8MM/SME2 实现,或要求 review ARM 汇编/dispatch/pack 性能问题。
边界:不要读取、修改或依赖
schema/private/和source/internal/。
.S。MNNPackedMatMul、MNNComputeMatMulForE_1、MNNScaleAndAddBias、MNNSoftmax、MNNNorm、pack/unpack 等已有高性能函数。只有现有函数无法覆盖热点时才新增 Vec4/intrinsic/asm。MNNGetGemmUnit、kernel 注册、mixed/online reorder 选择必须同步更新。开始前先写清楚这次优化覆盖哪些组合:
| 维度 | 需要确认 |
|---|---|
| 算子/入口 | 哪个 executor、CoreFunctions 指针、asm symbol |
| 数据类型 | FP32、FP16、INT8、w2/w3/w4、per-channel/per-block |
| shape 热点 | E=1 decode、E>1 prefill、block size 32/64、OC split、tail |
| ISA | NEON、SDOT、I8MM、SME2,以及 runtime disable flag |
| 后处理 | bias、scale、zero point、fp32 min/max、add-dst、ReLU/ReLU6 |
| 验收 | op test、模型 prompt、roofline 或 speed test |
tId>0 的 OC chunk。在正式写汇编前,用 C++ 写一个“寄存器级”的模拟实现:
std::array/局部数组模拟 v0..v31 的 lane,而不是依赖编译器自动向量化。sdot/smmla 的输入排列、每 4 byte dot 的分组、w2/w3 bit-plane unpack、sign/zero point 处理。写 asm 前先列一张寄存器表:
| 寄存器 | 用途 | live 范围 | 可否复用 | 风险 |
|---|---|---|---|---|
x* | 指针、loop counter、stride、metadata | 哪个 loop/分支 | 是否跨 call/branch | 指针恢复、tail |
v* | accumulator、input、unpack tmp、scale、min/max | unpack、compute、postprocess | 是否可被 clobber | ReLU/minmax、add-dst |
特别注意:
x19-x28、d8-d15 的 callee-saved 规则。fp32minmax != nullptr 分支都不会覆盖它。ld1r {.2d} 替代 ld1 {.8b} + mov d[1]、消除不必要的 pointer restore。新增或替换 kernel 时同时检查:
CoreFunctions/arm init 中的函数指针注册。MNNGetGemmUnit、UNIT/SRC_UNIT/DST_XUNIT、weight reorder、online reorder 是否和 kernel 期望一致。最少验证:
cmake --build build -j 8
cd build
./run_test.out op/lowMemory/blockConv 0 1 4
./run_test.out op/lowMemory/HybridConv 0 1 4
./run_test.out op/lowMemory/blockConv 0 1 4 # 在 SDOT 目标设备/构建配置上复跑
./run_test.out op/lowMemory/HybridConv 0 1 4 # 在 SDOT 目标设备/构建配置上复跑
LLM 低 bit kernel 额外验证:
./llm_demo /path/to/w3/config.json prompt.txt 64 1
./llm_demo /path/to/w3/config.json prompt.txt 64 1 # 在 SDOT 目标设备/构建配置上复跑
./llm_demo /path/to/w2/config.json prompt.txt 64 1
./llm_demo /path/to/w2/config.json prompt.txt 64 1 # 在 SDOT 目标设备/构建配置上复跑
说明:
64 1 代表短 decode 且关闭 thinking 的 sanity 方式,具体参数以当前 llm_demo 为准。性能验证:
./run_test.out speed/GemvBW 0 2
记录 us/iter、W MiB、bytes/elem、eff GB/s、%peak、GFLOPS。w2/w3 的 eff BW 低时,优先检查 unpack 指令/字节比和 issue 压力,而不是直接假设 memory bandwidth 不足。
| 函数 | 优先用途 | 注意点 |
|---|---|---|
gcore->MNNPackedMatMul | 大规模 GEMM | Pack 开销要能摊薄 |
gcore->MNNPackedMatMulRemain | GEMM tail | 和主 kernel layout 一致 |
gcore->MNNComputeMatMulForE_1 | E=1 GEMV/decode | LLM decode 优先看这里 |
gcore->MNNComputeMatMulForH_1 | H=1 VecMat | 确认矩阵方向 |
gcore->MNNScaleAndAddBias / MNNScaleAndAddBiasScalar | scale+bias | 检查 in-place |
MNNSoftmax | softmax | 确认 axis/layout |
MNNNorm | LayerNorm/RMSNorm | 确认 mean/rms 语义 |
MNNExp / MNNSiLu | 激活 | 部分函数不支持 in-place |
gcore->MNNPackCUnit / MNNUnpackCUnit | NC4/NC8 重排 | pack size 由 runtime 决定 |
gcore->MNNPackC4ForMatMul_A / MNNPackForMatMul_B | MatMul pack | 和 kernel pack mode 配套 |
MNN_CONCURRENCY_BEGIN/END | 多线程 | 注意 per-thread pointer 偏移 |
| 陷阱 | 规避方式 |
|---|---|
| op 单测通过但 LLM 输出乱码 | 增加 E=1、block64、fp32 min/max、multi-block、模型 prompt 验证 |
| w3 i8mm 错但 sdot 对 | 分开在 I8MM 和 SDOT 路径定位,不要混合定位 |
| min/max 被 unpack scratch 覆盖 | postprocess 前重新检查 live range,必要时延迟加载 min/max |
| 低 bit OC 分线程错位 | pointer 偏移用真实 packed cell stride,测试 mSplitByOc=true 和 tId>0 |
| SME2 pack/kernel 不匹配 | packer、kernel 注册、unit 参数同时改,同时测 fallback |
| w2 偶发复读误判为 kernel bug | 用 greedy/no-thinking、FP16 对照、短 prompt 做区分 |
| 只堆 unroll 性能反降 | 先看寄存器压力、unpack issue、load/store、branch 和 postprocess |
| 小 shape 调用重型函数变慢 | 小规模保留朴素/Vec4 路径,大规模才用 pack+matmul |
| 文件 | 用途 |
|---|---|
source/backend/cpu/compute/CommonOptFunction.h | CoreFunctions 定义和函数签名 |
source/backend/cpu/CPUAttention.cpp | MatMul/Softmax/Norm/多线程复用参考 |
source/backend/cpu/compute/DenseConvolutionTiledExecutor.cpp | pack、tiling、线程拆分参考 |
source/backend/cpu/arm/arm64/MNNPackedMatMul.S | AArch64 asm 风格参考 |
source/backend/cpu/arm/arm64/MNNPackedMatMul_int8.S | SDOT/int8 matmul 参考 |
test/speed/MatMulSpeed.cpp | speed test 组织方式参考 |
skills/arm-cpu-optimize/step0-decompose.md:计算拆解和 CoreFunctions 映射。skills/arm-cpu-optimize/step1-benchmark.md:建立 baseline 和 speed test。skills/arm-cpu-optimize/step2-analyze.md:瓶颈分析和方案选择。skills/arm-cpu-optimize/step3-cpp-opt.md:C++ 层函数复用、多线程、内存池。skills/arm-cpu-optimize/step4-asm.md:C++ oracle/SIMD 模拟/寄存器规划/asm 实现。skills/arm-cpu-optimize/step5-integrate.md:集成、回归和性能报告。