乗算の数を減らすために最適化されたアルゴリズム (Gauss、Strassen、Winograd)

目次

ガウスアルゴリズム

ストラッセンアルゴリズム

Winograd アルゴリズム

つる 1D

2D つる


        ハードウェア設計では、ロジック リソースの使用と組み合わせロジックの遅延の点で、乗算は加算よりもはるかに高くなりますハードウェアの観点からは、乗算をシフトと加算に変換する傾向があり、たとえば、8 の乗算は 3 ビットの左シフトに変換できます。A*15 は (A<<4) - A に変換でき、乗算は他の演算に変換して、リソースの消費と組み合わせロジックの遅延を削減できます。

        しかし、乗算値が固定値でない場合、ハードウェア上で乗算をシフトや加算に変換することが困難な場合があり、乗算が避けられない場合には、いかに乗算回数を減らすかが非常に重要となります。


ガウスアルゴリズム

ガウスアルゴリズムの最適乗算

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

(a+bi)*(c+di) を計算する場合、必要な乗算の合計数は 4 回の乗算と 3 回の加算です。

ガウス アルゴリズムを使用して最適化:

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

        ガウス アルゴリズムによって最適化された後、実数部は本物、虚数部は になります想像全体の計算量は当初の乗算4回+加算3回から乗算3回+加算5回となり、乗算回数が減りました。


ストラッセンアルゴリズム

        上記の行列の乗算では、合計 8 回の乗算 + 4 回の加算が使用されます。

Strassen アルゴリズムは Gauss アルゴリズムに非常に似ており、最適化方法は次のとおりです。

                        \\P_1=a(fh)、\ P_2=(a+b)h、\ P_3=(c+d)e\ P_4=d(ge) \\P_5=(a+d)(e+h)、 \ P_6=(bd)(g+h)、\ P_7=(ac)(e+f)

                        結果: 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}   

        2X2 行列乗算に適用された Strassen アルゴリズムは、8 乗算 + 4 加算を7 乗算 + 18 加算に変換できます。       

        行列 B が重み行列などの定数の場合。その後、Strassen アルゴリズムは8 回の乗算 + 4 回の加算を7 回の乗算 + 13 回の加算に変換し、乗算の数を減らすことができます

        Strassen アルゴリズムは、乗算の数を減らすことで、行列乗算の複雑さを Θ(N 3 )からΘ(N 2.807 )に軽減します 。計算数を減らすと、より多くのメモリが必要になります。


Winograd アルゴリズム

        Winograd は、短い畳み込みを計算するための高速アルゴリズムです。

        1 次元の畳み込み演算は F( m,r )として定義されm出力サイズrフィルター サイズとすると、入力信号の長さは m+r−1 となります。  

        畳み込み演算は、対応する位置を乗算してからそれらを合計することです。入力信号の各位置は少なくとも 1 つの乗算に参加する必要があるため、乗算の数は少なくとも記録される入力信号の長さと同じになります。として:

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

        行と列でそれぞれ 1 次元の畳み込み演算を実行して 2 次元の畳み込みを取得します。これは 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)。

つる 1D

        入力信号はd = [d_0\ d_1\ d_2\ d_3 ]^T, 畳み込みカーネルはg =[g_0\ g_1\ g_2]^T, 入力は 1*4 行列, 畳み込みカーネルは 1*3 行列です. 2 つの畳み込み結果は 2 つの値を取得します. 上記の畳み込みプロセスは次のように書くことができます次の行列乗算                            形式​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​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{b行列}

        一般的な行列の乗算であれば、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 回のシフトが必要です。コンボリューション カーネル フィルターg_iが定数の場合、たとえばフィルターが固定重み行列である場合、Winograd の計算には4 回の乗算 + 8回の加算が必要です。

        便宜上、Winograd 1D は次のように表現できます。

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

        ここで\odot、 はドット積、つまりビットの乗算です。B^Tこれはサイズ の入力変換行列(m+r-1)\times(m+r-1)、 G はサイズ(m+r-1)\times rr のフィルター変換行列、A^Tおよびサイズ の出力変換行列ですm\回(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 }

        gConvolution kernel: g=\begin{bmatrix} g_0&g_1 &g_2 \end{bmatrix}^T; dInput signal: d=\begin{bmatrix} d_0 &d_1 &d_2 &d_3 \end{bmatrix}^T、これらの行列を Y 方程式に組み込むと、上記の F(2,3) と同じ結果を導き出すことができます。

2D つる

        Winograd 1D 式によれば、次のように簡略化できます。

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

        2次元のコンボリューションの場合、右図に示すように、3*3のコンボリューションカーネルを使用して4*4の領域をコンボリューションし、合計4回のコンボリューションを実行します。 9*1 行列、4*4 領域はコンボリューション カーネルとの乗算方法に従って 4*9 行列に拡張され、4*9 領域拡張行列と 9*1 コンボリューション カーネルの積は展開行列は依然として畳み込み結果と等しくなります。

         上記の方法での最適化により、2D 畳み込みを 1D 乗算に変換することができたので、Winograd 1D の簡略化公式を使用して畳み込み乗算を最適化できます。

        各部分行列の繰り返し要素の位置は 1 次元の場合と同じであり、繰り返し部分行列も 1 次元の場合と同じです

 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{b行列}

        Order 、つまりwindow の0 番目の行要素は、 1st 2nd 、 3rd row;を意味するため、次の結果を推測できます。D_0=[k_0,k_1,k_2,k_3]^TD_1、D_2、D_3W_0=[w_0,w_1,w_2]^T

 簡単に言うと、1D Winograd は 2D Winograd にネストされています。

        上記の乗算では、直接畳み込みは 36 回の乗算 (4*9) を実行しますが、Winograd アルゴリズムを使用すると、乗算の回数を 2.25 分の 16 回に減らすことができ、最適化された畳み込みに大きな影響を与えます。アルゴリズム。

おすすめ

転載: blog.csdn.net/qq_57502075/article/details/127906455