减少乘法次数的优化算法(Gauss、Strassen、Winograd)

目录

Gauss算法

Strassen算法

Winograd算法

Winograd 1D

Winograd 2D


        在硬件设计中,乘法无论是在逻辑资源的使用上还是组合逻辑的延时上都要比加法高很多。从硬件方面考虑,我们都更倾向于将乘法转换成移位和加法,譬如乘以8,可以转换为左移3位。A*15可以转换为(A<<4) - A,将乘法转换为其他的运算以减少资源消耗和组合逻辑延时。

        但有时候乘以的数值不是定值的时候,我们在硬件上就很难将乘法转化为移位和加法,那么在乘法无法避免的时候,如何减少乘法的次数就显得至关重要。


Gauss算法

Gauss算法优化乘法

                                  (a+bi)*(c+di) = (ac -bd) + (bc + ad )i

计算(a+bi)*(c+di) 时,总共涉及到的乘法次数为四次乘法和三次加法。

使用gauss算法优化:

                                                      \begin{c} \\k_{1} = c * (a+b) \\ k_{2} = a*(d-c) \\k_{3} =b*(c+d)\\ \\Real_{1} = k_{1}-k_{3} \\Imaginary_2 = k_1+ k_2 \end{c}

        经过Gauss算法优化之后,实部为Real,虚部为Imaginar。整个计算量从原来的4次乘法+3次加法,变到了3次乘法+5次加法,减少了乘法次数。


Strassen算法

        上面的矩阵乘法,总共用到了8次乘法+4次加法。

Strassen算法和Gauss算法很相似,优化的方法如下:

                        \\P_1=a(f-h),\ P_2=(a+b)h,\ P_3=(c+d)e\ P_4=d(g-e) \\P_5=(a+d)(e+h),\ P_6=(b-d)(g+h),\ P_7=(a-c)(e+f)

                        results: AB=\begin{bmatrix} P_5+P_4-P_2+P_6&P_1+P_2 \\ P_3+P_4&P_1+P_5-P_3-P_7 \end{bmatrix}   

        Strassen算法应用在2X2的矩阵乘法可以将8次乘法+4次加法,转换为7次乘法 + 18次加法。       

        如果矩阵B是常数,譬如权重矩阵。那么Strassen算法可以将8次乘法+4次加法,转换为7次乘法 + 13次加法,减少了乘法次数

        Strassen算法通过减少乘法数,把矩阵乘法的复杂度从 Θ(N3) 减少到 Θ(N2.807),减少了计算次数的代价就是需要更多的内存。


Winograd算法

        Winograd是一种计算短卷积的快速算法。

        一维卷积运算定义为F(m,r)mOutput SizerFilter Size,则输入信号的长度为m+r−1:  

        卷积运算是对应位置相乘然后求和,输入信号每个位置至少要参与1次乘法,所以乘法数量最少与输入信号长度相同,记为:

                                                     \\u(F(m,r)) = m + r-1

        在行列上分别进行一维卷积运算,可得到二维卷积,记为F(m×n,r×s),输出为m×n,卷积核为r×s,则输入信号为(m+r−1)(n+s−1),乘法数量至少为μ(F(m×n,r×s))=μ(F(m,r))μ(F(n,s))=(m+r−1)(n+s−1)。

Winograd 1D

        输入信号为d = [d_0\ d_1\ d_2\ d_3 ]^T,卷积核为g =[g_0\ g_1\ g_2]^T,输入为1*4矩阵,卷积核为1*3矩阵,两者卷积结果会得到两个值,可以把上述卷积过程写为如下矩阵乘法形式                            ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​            ​​​​​​​F(2,3)=\begin{bmatrix} d_0 &d_1 &d_2 \\ d_1&d_2 &d_3 \end{bmatrix} \begin{bmatrix} g_0\\g_1 \\ g_2 \end{bmatrix}=\begin{bmatrix} r_0\\r_1 \end{bmatrix}

        如果是一般的矩阵乘法,则需要进行6次乘法和4次加法,过程如下:

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​            \\r_0=(d_0*g_0)+(d_1*g_1)+(d_2*g_2)\\ r_1 =(d_1*g_0)+(d_2*g_1)+(d_3*g_2)

        WInograd 算法是面向卷积的运算而不是普通的矩阵相乘:

        ​​​​​​​        ​​​​​​​        ​​​​​​​            F(2,3)=\begin{bmatrix} d_0 &d_1 &d_2 \\ d_1&d_2 &d_3 \end{bmatrix} \begin{bmatrix} g_0\\g_1 \\ g_2 \end{bmatrix}=\begin{bmatrix} m_1+m_2+m_3 \\ m_2-m_3-m_4 \end{bmatrix}

        其中:

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​    \\m_1=(d_0-d_2)g_0\ \ \ \ \ m_2=(d_1+d_2)\frac{g_2+g_1+g_2}{2}\\ m_4=(d_1-d_3)g_2\ \ \ \ \ m_3=(d_2-d_1)\frac{g_0-g_1+g_2}{2}

        Winograd的计算需要进行4次乘法+12次加法+2次移位。如果卷积核filter的g_i为常数,例如filter为固定权重矩阵,则Winograd的计算需要进行4次乘法+8次加

        为了方便,Winograd 1D可以表示为:

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​            Y=A^T [(Gg)\odot (B^T d)]

        其中\odot为点积,即对位相乘。B^T为Input transform矩阵,尺寸为(m+r-1)\times(m+r-1)​​​​​​​,G为Filter transform矩阵,尺寸为(m+r-1)\times rr,A^T为output transform矩阵,尺寸为m\times(m+r-1)

            B^T=\begin{bmatrix} 1&0 &-1 &0 \\ 0&1 &1 &0 \\ 0& -1 & 1 &0 \\ 0& 1 &0 &-1 \end{bmatrix} ,\ G=\begin{bmatrix} 1& 0 &0 \\ \frac{1}{2}& \frac{1}{2}& \frac{1}{2} \\ \frac{1}{2}& -\frac{1}{2}& \frac{1}{2} \\ 0 & 0 & 1 \end{bmatrix}, \ A^T=\begin{bmatrix} 1 &1 & 1 & 0\\ 0& 1& -1& -1 \end{bmatrix}

        g卷积核:g=\begin{bmatrix} g_0&g_1 &g_2 \end{bmatrix}^T; d输入信号:d=\begin{bmatrix} d_0 &d_1 &d_2 &d_3 \end{bmatrix}^T,将这些矩阵带入到Y等式中,就能推出和上面F(2,3)一样的结果。

Winograd 2D

        根据Winograd 1D公式,可以如下化简:

        ​​​​​​​        ​​​​​​​        ​​​​​​​          Y=A^T [(Gg)\odot (B^T d)]=A^T [(GgG^T)\odot (B^T dB)]A

        对于二维卷积,如右图所示,用一个3*3的卷积核对4*4的区域进行卷积,总共会卷积四次,我们将3*3的卷积核拉长成一个9*1的矩阵,4*4的区域按照和卷积核的乘法方式,扩展为一个4*9的矩阵,这样这个4*9的区域扩展矩阵和9*1的卷积核扩展矩阵的乘积还是等于卷积结果:

         通过上面这种方式优化,我们就成功的将2D的卷积,转化为了1D的乘法,就可以使用我们前面Winograd 1D的化简公式来优化卷积乘法。

        每个子矩阵中重复元素的位置与一维时相同,同时重复的子矩阵也和一维时相同

 我们就可以把Winograd 1D的乘法模块复用到2D中:

        ​​​​​​​        ​​​​​​​        ​​​​​​​            F(2,3)=\begin{bmatrix} d_0 &d_1 &d_2 \\ d_1&d_2 &d_3 \end{bmatrix} \begin{bmatrix} g_0\\g_1 \\ g_2 \end{bmatrix}=\begin{bmatrix} r_0\\r_1 \end{bmatrix}

        令D_0=[k_0,k_1,k_2,k_3]^T,即窗口中的第0行元素,D_1,D_2,D_3表示第12、3行;W_0=[w_0,w_1,w_2]^T,因此我们可以推导出如下结果:

 简单来说,1D Winograd被嵌套成了2D Winograd

        对于如上的乘法,直接卷积将会进行36次乘法(4*9),采用Winograd算法,可以将乘法的数目减少到16次,减少了2.25倍,对优化卷积算法效果显著。

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
本文是采用MATLAB仿真计算平台对人口预测的应用问题所进行的一些研究,其研究工作基础与研究背景源自本人承担的2010年浙江省教育厅科研课题项目《基于MATLAB仿真预测模型及犯罪数量实测研究》的前期工作、2009年浙江警官职业学院科研课题项目《基于MATLAB曲线拟合分析研究》与《基于MATLAB人口预测分析研究》以及多年来从事《数学实验》的教学工作。相关的研究成果已发表于吉林师范大学学报(自然科学版,2010年5月)及微计算机信息学报(2010年8月)本论文的研究成果主要包括:采用MATLAB软件仿真实测出近期人口预测模型: 以MATLAB仿真计算平台,以中国1990-2008年历年人口统计资料为数据环境,仿真实测出了适于近期人口预测的简洁高效的多项式模型与傅立叶级数模型。依照预测时间的不同,从多个角度探讨了近期预测模型的准确度,进而得到了具有较高准确度的近期人口预测模型。改进了传统LOGISTIC人口预测模型的相关参数:以往传统的中远期人口预测模型多引自于荷兰学者Verhaus提出的LOGISTIC模型,其数理上的人口总量并非一个无限增长的数学过程,内含的人口阻滞作用将使人口达到饱和而最终趋于常量,但人口预测的准确度取决于如何选取模型及待定参数。 为解决这个问题,本文采用MATLAB仿真计算平台进行了实测分析与研究,对LOGISTIC人口预测模型进行了泛化式改进,www.bolelib.com/post/29.html获得了与其它文献不同的人口环境容纳量。由本文完成的MATLAB仿真实验表明,改进后的LOGISTIC人口预测模型准确度明显提高,预测的平均相对误差由4.485%降低为0.606%,对LOGISTIC模型预测值再次修正后,预测的最大相对误差由1.30%降低为0.38%,其精度较好满足中远期人口预测的要求。 依所建立的LESLIE模型编程实测而获取了人口结构的重要数据:以66岁及以上为老年人口这个新的界定标准,得出了50年间各年龄段的人口数量,并进一步修正了LESLIE模型的预测误差,提高了近期人口预测的准确度。本文编程实测所获取的人口结构数据表明,未来50年中国人口扶养比攀升加快,仅基于2001年8.11%的中国人口扶养比进行预测,中国人口扶养比在2042年将增至32.06%,可能提前显现发达国家的人口结构,将给人均资源匮乏的中国社会造成沉重的负担。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃葱的酸菜鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值