RowMajor MatMul optimization
backend | armv7-a | armv8-a | cuda | vulkan | x86 |
---|---|---|---|---|---|
support | ✔️ | ✔️ | ✔️ | ✔️ | ✅ |
- 准备 armv7/aarch64 linux 开发环境,树莓派/rk3399/aws arm server 都可以。
- clone 代码后,修改
makefile
的OLD
和NEW
。首次运行需要改成同一个代码版本,例如
OLD := MMult_4x4_8
NEW := MMult_4x4_8
- 默认情况下
ARCH := native
。直接编译运行即可
$ cd armv8 && make run
- gflops 结果在对应
.m
文件,用plot.py
可绘制相关折线图。
此项目基于 blis-lab 文档和项目实现,与原作区别在于:
- 原作为列主序
x86 SSE
代码。考虑到移动端卷积优化一般使用arm
架构芯片,本项目是基于arm64
版行主序gemm
优化; - 原作没有做 k 维拆解,也没有太细致的分块,离 CPU 极限差距不小。本项目目前最新的
MMult_4x4_17.c
最高可达 9.9gflops,相当于 CPU 峰值的 70%; - 本项目没有处理边界问题,只考虑 MNK 均为 4 的倍数的情况;
sub_kernel
也只写了最简单的一种汇编。实用需要简单调整一下; - 绘图方面扔掉了冗长的
octave
(arm linux 配置一次环境太麻烦),改用python plot
。
ARM 系列优化中文教程在
- 知乎 GEMM 入门
- 知乎 GEMM caching (最后一节增加了理论支撑哦)
- ARMv7 4x4kernel 懒人优化小实践
自 知乎 GEMM 入门 发布后,有不少同学问如何写一个 int8 gemm。俺写好了~~~
chgemm 是个可用的 int8 gemm 库。相对于本教程中的代码,区别在于:
- 处理了边界问题,不像教程里只考虑尺寸为 4 的倍数的情况;
- int8 最高达到了 18.6 gflops(相对 fp32 理论极限只有14.3,gemmlowp大约 12-14gflops);
- 基于对称量化原理,输入数值范围必须在 [-127, +127],不能出现 -128;
chgemm 已合入ncnn INT8 卷积实现。
- 需自行安装 cuda 驱动和 OpenBLAS 做 baseline
- 首次运行需要
makefile
里改成同一个代码版本,例如
OLD := MMult_cuda_5
NEW := MMult_cuda_5
$ cd cuda
$ make
$ ./test_MMult.x
...
- 如果想用
plot.py
绘制折线图,用make run
生成运行结果
$ python3 plot.py output_MMult_cuBLAS_1.m output_MMult_cuda_12.m
build 依赖 kompute 这层 API 包装,见 vulkan build 文档