在高性能领域,对于矩阵乘(GEMM)的优化是一个非常重要的课题。GEMM可以非常广泛地应用于航空航天、流体力学等科学计算领域,这也是之前HPC的主要应用场景。后来深度学习开展地如火如荼,由于对高算力的需要,也成为HPC的主要应用场景之一。这些年涌现了一系列的深度学习模型。模型里面最耗时的东西,包括卷积、全连接层、attention,都可以转换成GEMM操作。所以说,GEMM优化的重要性,怎么突出都不过分。
目前网上能找到的针对GEMM优化的资料主要有这么几个方面: 一、论文,目前针对GPU进行GEMM优化的论文非常多,这里主要推荐Understanding the GPU Microarchitecture和Fast implementation of dgemm on fermi gpu以及 Dissecting the NVIDIA Volta GPU Architecture via Microbenchmarking。这几篇论文在业界都比较有影响力,就是代码开源方面做的不算太好。二、官方博客,主要是CUTLASS和NervanaSystems-SGEMM优化。还有前段时间旷视发的文章CUDA矩阵乘法优化,写的都很详细。三、github的一些demo,代码量不大,看起来比较舒服。我是看了这两个,
demo1代码写的好理解一些,但是优化工作没做完全,没有做到prefetch。demo2是效果很好,11个优化技巧,不断逼近cublas。但是代码真的看起来比较难受,最重要的很多参数写死了,不好去调。
总而言之,目前列举的上述资料存在着这么两个问题:一、文档方面,读起来还是比较费劲,对于小白来说,还是不够简单不够傻,看起来太累了;二、代码方面,要么是没公开代码,要么是代码太多了,看不下去;还有的就是代码可读性很强,但是优化工作还不是特别深,或者就是代码优化做的很好,但是可读性差了。方方面面总是有点欠缺,所以希望能够写一篇尽可能地在文档上简单明了,在代码上详细且可读性好的文章。当然,这是一个逐步迭代的过程,所以这篇文章也会持续进行更新哈。
本篇文章主要是采纳了cutlass的行文思路,主要介绍GEMM中的数据分块和如何在多级存储进行数据搬运。这也是HPC优化的核心思想,怎么样让数据放在更近的存储上来掩盖计算的延时,从而减少存储墙的影响。文章分为四个方面进行叙述,首先介绍在global memory层面如何进行分块以及数据搬运,随后介绍在shared memory层面如何进行分块以及数据搬运,而后介绍在register层面如何进行分块以及避免bank冲突,最后介绍如何进行prefetch以更好地掩盖访存时延。
从global memory到shared memory