以往我分析了一些AI加速器的设计,包括TPU,FSD,华为达芬奇等,无一例外都是从已经给出的设计出发,去分析其优缺点和应用范围。在以前的文章中,关于这些设计是如何完成的,其背后是否有必定设计原则和理念的内容均没有进行探讨。而这两点,实则是设计一个优秀的,可持续迭代的加速器的基础。本文将从矩阵加速器出发,经过一些简化的模型,给出简单的设计框架。缓存
通常来讲,矩阵乘法加速器中须要加速的计算可表示为架构
\[ C = A\times B + C \]框架
其中\(A\in R^{m\times k}\), \(B\in R^{k\times n}\), \(C\in R^{m\times n}\) 。优化
矩阵乘法加速器,通常至少包括计算单元,缓存(SRAM等构成)和内存(譬如DDR等)。其中缓存的读写速率较高,能够和计算单元的运算速度相匹配,但容量较小;内存的容量相对缓存较大,但读写速率较低。spa
和通常的处理器相比,特定的加速器能够设计数量巨大的计算单元(譬如Google TPU V1设计了65536个乘法器);可是DDR的带宽的提高倒是有限的。所以,设计目标之一在于优化数据访问,下降DDR的读写带宽。架构设计
假设加速器的总缓存大小为\(M\), 在一次计算过程当中,用于存储矩阵\(A,B,C\)的缓存空间大小分别为\(M_A,M_B,M_C\)。设计
矩阵乘法加速器的设计目的通常是为了加速大规模的矩阵乘法计算,为了简化分析过程,假设矩阵\(A,B,C\)的大小\(S_A,S_B,S_C\)均远大于\(M\),即计算过程当中每次只能在缓存中存放一部分数据,完成子矩阵\(A_{sub},B_{sub},C_{sub}\)的计算。显然,存放在缓存中的数据都会参与运算,否在有冗余数据浪费存储和带宽。所以\(A_{sub},B_{sub},C_{sub}\)应可以完成一组矩阵计算,即内存
\[A_{sub}\in R^{p\times s},B_{sub}\in R^{s\times q},C_{sub}\in R^{p\times q}\]ci
据此,为了完成矩阵计算,从DDR到SRAM的总数据读写为class
\[D_{size} = n/q \times S_A + m/p \times S_B + 2\times S_C\]
据此能够给出优化目标为
\[ \mathbf{min} : mnk/q + mnk/p +2mn \\ \mathbf{sub.to }: p\times s + s\times q + p\times q \leqslant M\\ p>0,s>0,q>0 \]
简化为
\[ \mathbf{min} : 1/q + 1/p \\ \mathbf{sub.to }: p\times s + s\times q + p\times q \leqslant M\\ p>0,s>0,q>0 \]
求解得当\(s=1\),\(p=q=\sqrt{M+1}-1\)时获得最优解。即若要设计一个带宽优化的乘法器,应该尽量的将缓存用于存储\(C_{sub}\),每次计算的子矩阵为
\[C_{sub}^{p\times q} += A_{sub}^{p\times 1} + B_{sub}^{1\times q} \]
Telsa的FSD的设计和上述讨论结果是一致的(只不过FSD的SRAM对应了上述的DDR,Register对应了上述的SRAM),FSD计算过程当中\(A_{sub}\in R^{96\times 1},B_{sub}\in R^{96\times 96},C_{sub}\in R^{96\times 96}\)。对应的FSD的设计其实是以下降SRAM-Register之间的读写为目的进行优化的。
依据第二节的结果,每次计算的子矩阵为
\[C_{sub}^{p\times q} += A_{sub}^{p\times 1} + B_{sub}^{1\times q} \]
整个计算过程当中,其并行度最高为\({p\times q}\)(即每一个周期完成\({p\times q}\)个乘法)。而为了完成一次计算,须要从缓存里读取\(p+q+q\times q\)个数据送入到计算阵列中。所以一次读/写的数据位宽宽度极高,随着并行度的增加,数据位宽线性增加。
数据位宽的问题主要存在\(C_{sub}\)上。为了解决这一问题,Telsa FSD采用了移位的方式,在计算完成后,将计算结果依次写回到SRAM中。
若是设计目的在于计算阵列和缓存之间的优化,参考第二节的设计思路,在必定并行度上,但愿尽量下降缓存的读写带宽,优化目标能够表示为
\[ \mathbf{min}:x\times y+y\times z+x\times z \\ \mathbf{sub.to }:x\times y\times z=P \\ x>0,y>0,z>0 \]
其中\(P\)表明计算阵列的并行度,求解得当\(x=y=z=\sqrt[3]{P}\)时,此时设计的计算阵列对缓存的访问能够尽量的低。
华为的达芬奇架构中计算阵列的设计和上述讨论是一致的,达芬奇中的CUBE Core是一个\(16\times16\times16\)的MAC阵列(以Davinci Max为例),能够完成
\[C_{sub}^{16\times 16} += A_{sub}^{16\times 16} + B_{sub}^{16\times 16} \]
的矩阵计算。
上述的全部讨论都基于一个最简单的硬件模型,从两个角度分别求解了理论上最优的设计应该是怎么样的。
实际状况每每会复杂不少,硬件架构方面就会复杂不少。同时优化的目标每每有多个,而优化的限制条件也会有不少。
可是在我看来,只有采用这样的设计方法,即将问题建模,求解,才能造就一个好的设计。也只有采用这样的设计方法,才能再已有的基础上,进一步增长优化目标和优化条件,进一步的优化架构设计。