Skip to content

bigwater/how-to-optimize-gemm

 
 

Repository files navigation

how-to-optimize-gemm

RowMajor MatMul optimization

backend armv7-a armv8-a cuda vulkan x86
support ✔️ ✔️ ✔️ ✔️

一、ARM Cortex-A

编译和运行

  1. 准备 armv7/aarch64 linux 开发环境,树莓派/rk3399/aws arm server 都可以。
  2. clone 代码后,修改makefileOLDNEW。首次运行需要改成同一个代码版本,例如
OLD    := MMult_4x4_8
NEW   := MMult_4x4_8
  1. 默认情况下ARCH := native。直接编译运行即可
$ cd armv8 && make run
  1. gflops 结果在对应.m 文件,用plot.py可绘制相关折线图。

fp32 GEMM

此项目基于 blis-lab 文档和项目实现,与原作区别在于:

  1. 原作为列主序x86 SSE代码。考虑到移动端卷积优化一般使用arm架构芯片,本项目是基于arm64行主序gemm优化;
  2. 原作没有做 k 维拆解,也没有太细致的分块,离 CPU 极限差距不小。本项目目前最新的MMult_4x4_17.c最高可达 9.9gflops,相当于 CPU 峰值的 70%;
  3. 本项目没有处理边界问题,只考虑 MNK 均为 4 的倍数的情况;sub_kernel也只写了最简单的一种汇编。实用需要简单调整一下;
  4. 绘图方面扔掉了冗长的 octave(arm linux 配置一次环境太麻烦),改用 python plot

ARM 系列优化中文教程在

  1. 知乎 GEMM 入门
  2. 知乎 GEMM caching (最后一节增加了理论支撑哦)
  3. ARMv7 4x4kernel 懒人优化小实践

二、int8 GEMM

知乎 GEMM 入门 发布后,有不少同学问如何写一个 int8 gemm。俺写好了~~~

chgemm 是个可用的 int8 gemm 库。相对于本教程中的代码,区别在于:

  1. 处理了边界问题,不像教程里只考虑尺寸为 4 的倍数的情况;
  2. int8 最高达到了 18.6 gflops(相对 fp32 理论极限只有14.3,gemmlowp大约 12-14gflops);
  3. 基于对称量化原理,输入数值范围必须在 [-127, +127],不能出现 -128;

chgemm 已合入ncnn INT8 卷积实现。

三、CUDA

  1. 需自行安装 cuda 驱动和 OpenBLAS 做 baseline
  2. 首次运行需要 makefile 里改成同一个代码版本,例如
OLD    := MMult_cuda_5
NEW   := MMult_cuda_5
$ cd cuda
$ make
$ ./test_MMult.x
... 
  1. 如果想用plot.py绘制折线图,用 make run 生成运行结果
$ python3 plot.py output_MMult_cuBLAS_1.m output_MMult_cuda_12.m
  1. 知乎 cuda 入门的正确姿势:how-to-optimize-gemm

四、Vulkan

build 依赖 kompute 这层 API 包装,见 vulkan build 文档

知乎 如何火急火燎地上手 Vulkan

Releases

No releases published

Packages

No packages published

Languages

  • C++ 88.1%
  • C 10.7%
  • Cuda 0.6%
  • Mathematica 0.2%
  • Objective-C 0.2%
  • Makefile 0.1%
  • Other 0.1%