文章目录
本项目记录了在riscv平台上优化SGEMM(单精度浮点通用矩阵乘法)的过程。代码仓库位于https://github.com/Zhao-Dongyu/sgemm_riscv
通用矩阵乘(General Matrix Multiplication
,简称gemm
)是深度学习框架的核心计算单元之一,广泛用于Convolution
、Full connection
、Matmul
等算子实现。
我是在 全志 Nezha D1 开发板上进行的实验与探索,version 0 - version 5
是使用的 C 语言,version 6 - version 9
则部分使用了汇编,涉及到 RISC-V V
扩展指令。
注意:不同于其他的某些gemm优化工程,在本工程中,全部使用 行主序 的矩阵。因为我喜欢 行主序!
预备知识
RISC-V 是一种开放标准指令集架构 (ISA),通过开放协作开启处理器创新的新时代。
GEMM 通用矩阵乘法,基本线性代数子程序之一。
FLOPS每秒浮点运算次数,亦称每秒峰值速度,(英语:Floating-point operations per second
;缩写:FLOPS
),即每秒所执行的浮点运算次数。一个 GFLOPS(gigaFLOPS)
等于每秒十亿(10^9)次的浮点运算;
矩阵乘的计算量是 2 * M * N * K
,计算量除以耗时即为当前gemm版本的gflops。
- 乘以 2 是因为每次操作包含一次乘法和一次加法
准备工作
相关代码位于 ./prepare/
。
测试交叉编译
我使用的 全志 Nezha D1 开发板,在这里下载的交叉编译链接。
详细教程见readme
内存带宽测试
分别通过以下几个小工程对开发板内存带宽进行测试
roofline模型
Roofline 提出了使用 Operational Intensity
(计算强度)进行定量分析的方法,并给出了模型在计算平台上所能达到理论计算性能上限公式。
D1
的算力可达4 GFlops(@1GHz)
- Memory :
2.727 GB/s
(DDR3 792 MHz)。- 虽然我测出来最高是
2.592 GB/s
,可能哪里出了问题? - 商汤还是要相信一下的,暂时以他的为准吧
- 虽然我测出来最高是
sgemm优化
相关代码位于 ./sgemm/
。
使用说明
以 step0
为例,你需要先编辑 Makefile ,配置自己的交叉编译链。
$ cd sgemm/step0/
$ make
$ adb push test_bl_sgemm_step0.x ./.
$ adb shell './test_bl_sgemm_step0.x'
Version 0: naive版本
这个版本思路在我看来是最直观的,毕竟我当时就是这么学习、理解和计算矩阵乘法的:
A 的一行乘以 B 的一列得到 C 的一个元素。
<img src=https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fgithub.com%2FZhao-Dongyu%2Fsgemm_riscv%2Fblob%2Fmain%2Fpics%2Fstep0.gif&pos_id=img-FG36OOPj-1708998491920) width=70% />
优快云平台限制图片在5MB以内,所以计算过程的动图无法上传。如有需求可以去https://github.com/Zhao-Dongyu/sgemm_riscv/wiki查看
for ( i = 0; i < m; i ++ ) {
// Start 2-th loop
for ( j = 0; j < n; j ++ ) {
// Start 1-nd loop
for ( p = 0; p < k; p ++ ) {
// Start 0-st loop
C( i, j ) += A( i, p ) * B( p, j );
} // End 0-th loop
} // End 1-st loop
} // End 2-nd loop
我认为version 0
非常契合的解释了 C m