神经网络的全链接层计算过程可以看成两个矩阵相乘,如下图所示,一个MxN的矩阵乘以一个NxP的矩阵,得到一个MxP的矩阵,进行乘法的次数为:
(N)*(M*P)
加法次数为:
(N-1)*M*P
所以,矩阵乘法总的计算量为(N)*(M*P)+(N-1)*M*P = (2N-1)*M*P
每计算出一个结果,需要对一个N维向量作内积,内积需要进行N次乘法和N-1次加法(第一次计算不需要作加法,或者看成+0,就不需要-1了),计算一个结果的计算次数为2N-1.
比如,就拿3*3的矩阵乘法为例:
计算如下:
所以,它的计算量为:
乘法次数:3*3*3=27次.
加法次数: 2*3*3 =18次.
算在一起浮点操作为27+18=45次.
用公式计算(2N-1)*M*P=5*3*3=45次,互相印证符合。
当然,如果将MAC计算初始值看成0,则初始情况下实际上做了一个+0的加法操作,每个结果元素进行的加法次数也可以认为是N次而非N-1次,这样相当于增加了M*P个加法(每个结果元素1个+0操作),因为你可以认为一开始进行了加0操作。这样的化公式就更加简介,直接就是2N*M*P就,N*M*P个乘法和N*M*P个加法,乘法和加法次数各占一半,每次乘法对应一次加法,正好可以由一个MAC单元去执行。
这样,矩阵乘法总的计算次数就变成了2N*M*P。
计算/访存比
所以,对于一个M*K*N的矩阵乘加运算(MxK与KxN的矩阵相乘,再与MxN的矩阵相加),它的计算访存比为:
分子表示计算量,前面已经推导过了,分母中mxk表示读取第一个矩阵的读次数,相应的kxn是第二个矩阵的读次数,因为第三个矩阵既是操作数,又是结果,所以需要读写两次,为 2xmxn。
如果对于方阵,K=N=M,此时计算/访存比可以简单表示为:
说明矩阵规模越大,计算/访存比会越高,利用大矩阵配合有效分块算法,会获得较大的计算密度。
根据上面的公式也可以看出,对于标量运算来说,计算密度为1/2,是小于矩阵运算的。
矩阵乘法的计算模式
矩阵乘法的计算模式相对固定,面向神经网络的专用加速器多遵循两种计算模式:
1.模式一,矩阵乘法被看作若干对向量进行逐元素对应相乘,得到新的向量后在进行向量内相加归约加合得到最终结果。结果矩阵为mxn时,会有mxn个向量进行该操作。这种模式对应向量乘法单元和加法树单元的结构:
下面是一个加法树乘法器的verilog实现:
module multi_add_tree(a,b,clk,out);
output [15:0] out;
input [7:0] a,b;
input clk;
wire [15:0] out;
wire [15:0] out1,c1;
wire [13:0] out2;
wire [11:0] out3,c2;
wire [9:0] out4;
reg [14:0] temp0;
reg [13:0] temp1;
reg [12:0] temp2;
reg [11:0] temp3;
reg [10:0] temp4;
reg [9:0] temp5;
reg [8:0] temp6;
reg [7:0] temp7;
// 8*1乘法器
function [7:0] mut8_1;
input [7:0] operand;
input sel;
begin
mut8_1 = sel ? operand : 8'b0000_0000;
end
endfunction
//操作数b各位与操作数a相乘
always @(posedge clk)
begin
temp7 = mut8_1(a,b[0]);
temp6 = (mut8_1(a,b[1]))<<1;
temp5 = (mut8_1(a,b[2]))<<2;
temp4 = (mut8_1(a,b[3]))<<3;
temp3 = (mut8_1(a,b[4]))<<4;
temp2 = (mut8_1(a,b[5]))<<5;
temp1 = (mut8_1(a,b[6]))<<6;
temp0 = (mut8_1(a,b[7]))<<7;
end
//加法树运算
assign out1 = temp0 + temp1;
assign out2 = temp2 + temp3;
assign out3 = temp4 + temp5;
assign out4 = temp6 + temp7;
assign c1 = out1 + out2;
assign c2 = out3 + out4;
assign out = c1 + c2;
endmodule
仿真计算2x100=0xc8=200:
2.模式2,把矩阵相乘分解至以标量为单位,每次操作都是三个标量(axb+c)间的乘加运算,这种模式对应乘加单元组成的脉动阵列结构。
两种方法的差别在于各自的数据流调度方式,即数据存储和复用上的差异,nvidia tensor core则遵循了矩阵乘法的计算模式,结合寄存器的读取共享,尽可能地优化数据的复用。
两个矩阵相乘的几何结构
稀疏化操作原理
若矩阵中数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。定义非零元素的总数比上矩阵所有元素的总数为矩阵的稠密度。
对于AXB=C的形式来说,A的行中对应为0的项,对应B中列的项即便不为0,对最终的结果也起不到任何作用。
A100中的稀疏结构符合一些前置约定,是通过新的2:4稀疏矩阵定义来实现的,该定义允许在每个四项向量中有两个非零值。支持行上2:4的结构化稀疏性,如上图所示。由于矩阵的结构定义良好,它可以有效地压缩,并将内存存储和带宽减少近2倍。
参考文档
数字电路基础知识——组合逻辑电路之乘法器的设计(一)—— 并行、移位相加、加法树、查找表乘法器_乘法器电路图-CSDN博客