天天看點

卷積神經網絡性能優化

作者:資料派THU

作者丨黎明灰燼

來源|https://zhuanlan.zhihu.com/p/80361782

引言

卷積(Convolution)是神經網絡的核心計算之一,它在計算機視覺方面的突破性進展引領了深度學習的熱潮。卷積的變種豐富,計算複雜,神經網絡運作時大部分時間都耗費在計算卷積,網絡模型的發展在不斷增加網絡的深度,是以優化卷積計算就顯得尤為重要。

随着技術的發展,研究人員提出了多種優化算法,包括 Im2col、Winograd 等等。本文首先定義卷積神經網絡的概念,繼而簡要介紹幾種常見的優化方法,并讨論作者在該領域的一些經驗。

  • 大部分時間都耗費在計算卷積連結:
  • https://arxiv.org/abs/1807.11164
  • Im2col 連結:
  • https://www.mathworks.com/help/images/ref/im2col.html
  • Winograd 連結:
  • https://www.intel.ai/winograd/#gs.avmb0n

卷積神經網絡的概念

卷積神經網絡(Convolution Neural Networks, CNN)的概念拓展自信号處理領域的卷積。信号處理的卷積定義為

卷積神經網絡性能優化

(1)

由于對稱性

卷積神經網絡性能優化

卷積計算在直覺上不易了解,其可視化後如圖一所示。圖中紅色滑塊在移動過程中與藍色方塊的積繪制成的三角圖案即為卷積結果 (∗)() 在各點上的取值。

卷積神經網絡性能優化

圖一:信号進行中的卷積

  • 信号進行中的卷積連結:
  • https://jackwish.net/convolution-neural-networks-optimization.html

公式1的離散形式為 :

卷積神經網絡性能優化

(2)

将該卷積拓展到二維空間即可得到神經網絡中的卷積,可簡寫為:

卷積神經網絡性能優化

(3)

其中 為卷積輸出, 為卷積輸入, 為卷積核。該計算的動态可視化可以參考 conv_arithmetic,這裡不再介紹。

  • conv_arithmetic 連結:
  • https://github.com/vdumoulin/conv_arithmetic

當應用到計算機視覺中處理圖檔時,圖檔的通道(Channel)可以對二維卷積簡單堆疊,即:

卷積神經網絡性能優化

(4)

其中 c 是輸入的通道。這便是在三維張量中應用二維卷積的計算。

很多時候,公式描述顯得不是很直覺,圖二是堆疊的二維卷積的可視化。其中,與輸入、輸出、卷積核相關的标記帶有字首 I、O、K。此外,本文圖例對輸出、輸入、卷積核三者的着色一般為:橙色、黃色、綠色。

卷積神經網絡性能優化

圖二:卷積計算定義

當中張量的記憶體布局為 NHWC 時,卷積計算相應的僞代碼如下。其中外三層循環周遊輸出 C 的每個資料點,對于每個輸出資料都需要經由内三層循環累加求和得到(點積)。

for (int oh = 0; oh < OH; oh++) {


for (int ow = 0; ow < OW; ow++) {


    for (int oc = 0; oc < OC; oc++) {


      C[oh][ow][oc] = 0;


      for (int kh = 0; kh < KH, kh++){


        for (int kw = 0; kw < KW, kw++){


          for (int ic = 0; ic < IC, ic++){


            C[oh][ow][oc] += A[oh+kh][ow+kw][ic] * B[kh][kw][ic];


          }


        }


      }


    }


  }


}
           

和矩陣乘的優化方法類似,我們也可針對該計算進行向量化、并行化、循環展開的基本的優化操作。卷積的問題在于其 和 一般不超過 5 ,這不容易向量化,而計算特征又有輸入在空間次元存在資料複用。該計算的複雜性導緻産生了幾種優化方法,下面我們介紹幾種。

  • 和矩陣乘的優化方法連結:
  • https://jackwish.net/gemm-optimization.html

Im2col 優化算法

作為早期的深度學習架構,Caffe 中卷積的實作采用的是基于 im2col 的方法,至今仍是卷積重要的優化方法之一。

Im2col 是計算機視覺領域中将圖檔轉換成矩陣的矩陣列(column)的計算過程。從上一節的介紹中可以看到,二維卷積的計算比較複雜不易優化,是以在深度學習架構發展的早期,Caffe 使用 Im2col 方法将三維張量轉換為二維矩陣,進而充分利用已經優化好的 GEMM 庫來為各個平台加速卷積計算。最後,再将矩陣乘得到的二維矩陣結果使用 Col2im 将轉換為三維矩陣輸出。

  • Caffe 連結:
  • http://caffe.berkeleyvision.org/
  • Caffe 使用 Im2col 方法将三維張量轉換為二維矩陣連結:
  • https://github.com/Yangqing/caffe/wiki/Convolution-in-Caffe:-a-memo

算法過程

除非特别說明,本文預設采用的記憶體布局形式為 NHWC 。其他的記憶體布局和具體的轉換後的矩陣形狀或許略有差異,但不影響算法本身的描述。

卷積神經網絡性能優化

圖三:Im2col 算法計算卷積的過程

圖三是使用 Im2col 算法計算卷積的過程示例,具體的過程包括(簡單起見忽略 Padding 的情況,即認為 =,=:

  1. 将輸入由 ×× 根據卷積的計算特性展開成 (×)×(××) 形狀的二維矩陣。顯然,轉換後使用的記憶體空間相比原始輸入多約 ∗−1 倍。
  2. 權重的形狀一般為 ××× 四維張量,可以将其直接作為形狀為 ()×(××)) 的二維矩陣處理。
  3. 對于準備好的兩個二維矩陣,将 (××) 作為累加求和的次元,運作矩陣乘可以得到輸出矩陣 (×)×()。這一過程可以直接使用各種優化過的 BLAS(Basic Linear Algebra Subprograms)庫來完成。
  4. 輸出矩陣 (×)×() 在記憶體布局視角即為預期的輸出張量 ×× 。

Im2col 計算卷積使用 GEMM 的代價是額外的記憶體開銷。這是因為原始卷積計算中,卷積核在輸入上滑動以計算輸出時,相鄰的輸出計算在空間上複用了一定的輸入輸出。而用 Im2col 将三維張量展開成二維矩陣時,這些原本可以複用的資料平坦地分布到矩陣中,将輸入資料複制了 ∗−1 份。

當卷積核尺寸 × 是 1×1 時,上述步驟中的 和 可以消去,即輸入轉換後形狀為 (×)×(),卷積核形狀為 ()×(),卷積計算退化為矩陣乘。注意觀察,對于這種情況,Im2col 過程實際上并沒有改變輸入的形狀,是以矩陣乘操作可以直接在原始輸入上運作,進而省去記憶體組織的過程(即上述步驟中的 1、2、4 步)。

記憶體布局與卷積性能

神經網絡中卷積的記憶體布局主要有 NCHW 和 NHWC 兩種,不同的記憶體布局會影響計算運作時通路存儲器的模式,特别是在運作矩陣乘時。本小節分析采用 Im2col 優化算法時計算性能性能和記憶體布局的關系。

  • 特别是在運作矩陣乘時連結:

在完成 Im2col 轉換後,得到用于運作矩陣乘的輸入矩陣和卷積核矩陣。對計算過程施加矩陣計算中常用的資料劃分、向量化等優化方法(相關定義請參考通用矩陣乘(GEMM)優化算法)。下面着重分析在這種場景下,不同記憶體布局對性能的影響。

  • 通用矩陣乘(GEMM)優化算法連結:

首先考慮 NCHW 記憶體布局,将 NCHW 記憶體布局的卷積對應到矩陣乘 = 時, 是卷積核(filter), 是輸入(input),各個矩陣的次元如圖四所示。圖中的 ,, 用于标記矩陣乘,即

卷積神經網絡性能優化

,同時标記出它們和卷積計算中各個次元的關系。

卷積神經網絡性能優化

圖四:NCHW 記憶體布局卷積轉換成的矩陣乘

對該矩陣施行劃分後,我們詳細分析局部性的表現,并标記在圖四中。其中 Inside 表示 4×4 小塊矩陣乘内部的局部性,Outside 表示在削減次元方向小塊之間的局部性。

  • 對輸出而言,小塊内訪存局部性較差,這是因為每次向量化加載會加載四個元素,每次加載都會發生緩存缺失(Cache miss)。外部表現取決于全局計算方向——行優先則局部性較好,列優先則較差。輸出的行為不是這裡的讨論終點,畢竟它沒有訪存複用。
  • 對卷積核而言,小塊内訪存局部性較差,這和輸出類似。當小塊加載發生緩存缺失時,處理器會一次性加載一個緩存行(Cache line),這使得後續的若幹個小塊訪存都能緩存命中(Cache hit),直到該緩存行全部命中後進入下一個緩存行的範圍。是以小塊外部局部性較好。
  • 對輸入而言,小塊内訪存局部性表現同樣不好。然而不同于卷積核,小塊中因緩存缺失加載到緩存中的緩存行資料隻會被使用一次,因為這種記憶體布局中下一個小塊的位址範圍一般超出了一個緩存行。是以輸入的幾乎每次記憶體加載都會發生高速緩存缺失——Cache 沒有起到加速的作用,每次訪存都需要到記憶體取資料。

是以,用 Im2col 處理卷積計算時,NCHW 布局對記憶體很不友好。

圖五是與之相對的 NHWC 記憶體布局的示例。值得注意的是,NHWC 和 NCHW 中 、 矩陣所代表的張量發生了調換——=×(調換一下隻是不想多畫一張圖)。具體的拆分方式仍然一樣,也正是上一小節中描述的步驟所建構的矩陣。

卷積神經網絡性能優化

圖五:NHWC 記憶體布局卷積轉換成的矩陣乘

類似地,分析三個張量的訪存表現可知:

  • 對輸出而言,NHWC 和 NCHW 表現一樣。
  • 對輸入而言,小方塊的内部局部性表現不是很好,因為幾次向量加載都會發生緩存不命中;而外部局部性表現則較好,因為在削減次元滑動使用的記憶體是連續的。這種表現和 NCHW 中卷積核的表現一樣,整體來看都是對高速緩存比較友好的記憶體布局。
  • 對卷積核而言,NHWC 的情況和 NCHW 中輸入的情況類似,小塊内和小塊外的局部性都較差。

兩種記憶體布局中的卷積核緩存表現并不是問題,因為卷積核在運作期間保持不變,可以在模型加載階段轉換卷積核的記憶體布局,使其在小塊外的記憶體對緩存友好(例如将 (××)×() 的布局轉換為 ()×(×× )。這裡值得說明的是一般架構或引擎的運作都至少可分為兩個階段:準備階段和運作階段。一些模型的預處理工作可以放在準備階段完成,例如重新排布卷積核的記憶體布局這種在運作階段保持不變的資料。

是以,當使用 Im2col 方法計算時,整體的訪存表現取決于輸入的情況,即 NHWC 的記憶體布局要比 NCHW 記憶體布局更加友好。我們在實踐過程中的一個實驗表明,對于一個 1×1 卷積核的卷積,當采用類似的優化方法時,從 NCHW 轉換為 NHWC 可以将高速緩存缺失率從約 50% 降低到 2% 左右。這種程度的提高可以大幅改進軟體的運作性能(這裡特指不使用特别設計過的矩陣乘優化方法)。

空間組合優化算法

Im2col 是一種比較樸素的卷積優化算法,在沒有精心處理的情況下會帶來較大的記憶體開銷。空間組合(Spatial pack)是一種類似矩陣乘中重組記憶體的優化算法。

  • 矩陣乘中重組記憶體連結:
  • https://github.com/flame/how-to-optimize-gemm/wiki#packing-into-contiguous-memory
卷積神經網絡性能優化

圖六:空間組合優化算法對計算的劃分

空間組合優化算法是一種基于分治法(Divide and Conquer)的方法——它基于空間特性将卷積計算劃分為若幹份,分别處理。圖六所示是在空間上将輸出、輸入劃分為四份。

劃分後,一個大的卷積計算被拆分為若幹個小的卷積計算。雖然在劃分的過程中計算總量不變,但計算小矩陣時訪存局部性更好,可以借由計算機存儲層次結構獲得性能提升。這通過圖七中的步驟來完成。該步驟和上節中 Im2col 重組記憶體的過程類似:

  1. 在 H 和 W 次元劃分,将形狀為 ××× 的輸入張量拆分為 ℎ∗ 個(兩個方向分别拆分 ℎ 和 次)形狀為 ×/ℎ×/× 的張量,分别将這些小的張量組織為連續記憶體;
  2. 将得到的 ℎ∗ 個輸入張量分别和卷積核做二維卷積操作,即可得到 ℎ∗ 個形狀為 ×/ℎ×/× 的輸出張量;
  3. 将這些輸出張量重組記憶體布局得到最終形狀為 ××× 的輸出。
卷積神經網絡性能優化

圖七:空間組合計算的步驟

值得注意的是,友善起見,上文的描述中忽略了 Padding 的問題。實際在步驟 1 中将輸入張量劃分為若幹個小張量時,除了将劃分的小塊中原始資料拷貝外,還需要将相鄰的小張量的邊界資料拷貝。具體而言,如圖八所示,空間拆分得到的小張量的形狀實際上是:

×(/ℎ+2(−1))×(/+(−1))×.(5)

這裡的 2(−1) 和 2(−1) 遵循 Padding 規則。規則為

卷積神經網絡性能優化

時,它們可以忽略;規則為 SAME 時,位于源張量邊界的一邊 Padding 補

卷積神經網絡性能優化

,不在源張量邊界的 Padding 則使用鄰居張量的值。隻要考慮一下卷積的計算原理,這是顯而易見的。

卷積神經網絡性能優化

圖八:空間組合算法的劃分細節

上面的三個示例圖都是拆分為 4 份的情況,實際應用中可以拆為很多份。例如可以拆成小張量邊長為 4 或者 8 ,進而友善編譯器向量化計算操作。随着拆分出的張量越小,其局部性也越高,負面作用是消耗的額外記憶體也越多。這些額外記憶體是由于 Padding 引入的。當拆分為 ℎ∗h∗w份時,拆分後 Padding 消耗的記憶體為:

卷積神經網絡性能優化

可以看到,随着拆分的粒度越小,額外消耗的記憶體越大。值得注意的是,當拆分到最細粒度時,即将在形狀為 ××× 的輸出的空間上拆分∗ 份時,空間組合退化為 Im2col 方法。此時在一個元素上的卷積即為矩陣乘計算一個輸出元素時的點積。

隻做空間劃分時,劃分與卷積核無關。而如果在輸出的通道次元劃分,卷積核也可做相應的拆分。通道次元的劃分相當于固定空間劃分後簡單的堆疊,不會對影響記憶體消耗,但會影響局部性。對于不同規模的卷積,尋找合适的劃分方法不是一件容易的事情。正如計算機領域的許多問題一樣,該問題也是可以自動化的,例如 AutoTVM 可以在這種情況下尋找較優的劃分方法。

AutoTVM 連結:

https://arxiv.org/abs/1805.08166

Winograd 優化算法

前兩節介紹的兩種算法,Im2col 在将三維張量組織成矩陣後調用 GEMM 計算庫,這些計算庫很大程度上使用一些基于訪存局部性的優化;空間組合優化則本身就是利用局部性優化的方法。本小節介紹的 Winograd 優化算法則是矩陣乘優化方法中 Coppersmith–Winograd 算法的一種應用,是基于算法分析的方法。

這部分公式過多,排版不便,有興趣的話可以參考原文或其他相關文獻。

參考原文連結:

間接卷積優化算法

Marat Dukhan 在 QNNPACK(Quantized Neural Network PACKage)中推出了間接卷積算法(The Indirect Convolution Algorithm),似乎到目前為止(2019 年中)依然是所有已公開方法中最快的。最近作者發表了相關的文章來介紹其中的主要思想。

雖然該算法在 QNNPACK 中的實作主要用于量化神經網絡(業界的其他量化優化方案都比較傳統 TensorFlow Lite 使用 Im2col 優化算法、騰訊出品的 NCNN使用 Winograd 優化算法;OpenAI 出品的 Tengine 使用 Im2col 優化算法),但其是一種同樣的優化算法設計。

本文寫作時設計文章尚未公開,而了解該算法設計很多細節内容,最好能結合代碼了解。我的 QNNPACK fork 包含一個 explained 分支,其中對增加了對部分代碼的注釋,可作參考。

QNNPACK 連結:

https://github.com/pytorch/QNNPACK

TensorFlow Lite 使用 Im2col 優化算法連結:

https://github.com/tensorflow/tensorflow/blob/v2.0.0-beta1/tensorflow/lite/kernels/internal/optimized/integer_ops/conv.h

NCNN使用 Winograd 優化算法連結:

https://github.com/Tencent/ncnn/blob/20190611/src/layer/arm/convolution_3x3_int8.h

Tengine 使用 Im2col 優化算法連結:

https://github.com/OAID/Tengine/blob/v1.3.2/executor/operator/arm64/conv/conv_2d_fast.cpp

我的 QNNPACK fork 連結:

https://github.com/jackwish/qnnpack

計算工作流

間接卷積算法的有效工作以來一個關鍵的前提——網絡連續運作時,輸入張量的記憶體位址保持不變。這一特性其實比較容易滿足,即使位址真的需要變化,也可以将其拷貝到固定的記憶體區域中。

卷積神經網絡性能優化

圖九:間接卷積算法工作流

圖九是間接卷積算法工作流的詳細過程。最左側部分表示多個輸入使用相同的輸入緩沖區(Input Buffer)。間接卷積算法會在該輸入緩沖區基礎上建構如圖十的「間接緩沖區」(Indirect Buffer),而間接緩沖區是間接卷積算法的核心。如圖中右側,在網絡運作時,每次計算出 × 規模的輸出,其中 為将 × 視作一維後的向量化規模。一般 × 為 4×4、8×8 或 4×8 。在計算 × 規模大小的輸出時,經由間接緩沖區取出對應使用的輸入,并取出權重,計算出結果。計算過程等價于計算 × 和 × 矩陣乘。

在實作中,軟體的執行過程分為兩部分:

  1. 準備階段:加載模型,配置輸入緩沖區;重排權重,使其記憶體布局适用于後續計算;
  2. 運作階段:對于每個輸入,運作 ⌈∗/⌉∗⌈/⌉次核心循環,每次使用 GEMM 方法計算出 × 大小的輸出。
卷積神經網絡性能優化

圖十:間接緩沖區

如相關章節的讨論,Im2col 優化算法存在兩個問題,第一是占用大量的額外記憶體,第二是需要對輸入進行額外的資料拷貝。這兩點如何才能解決呢?間接卷積算法給出的答案是間接緩沖區(Indirect Buffer),如圖十右半所示。

圖十是正常的 Im2col 優化算法和間接卷積優化算法的對比。正如相關小節介紹的那樣,Im2col 優化算法首先将輸入拷貝到一個矩陣中,如圖十中 Input 的相關箭頭,然後執行矩陣乘操作。間接卷積優化算法使用的間接緩沖區中存儲的其實是指向輸入的指針(這也是間接卷積優化算法要求輸入記憶體位址固定的原因),在運作時根據這些指針即可模拟出類似于 Im2col 的矩陣計算過程。

間接緩沖區布局

間接緩沖區可以了解為是一組卷積核大小的緩沖區,共有 × 個,每個緩沖區大小為 ×——每個緩沖區對應着某個輸出要使用的輸入的位址。每計算一個空間位置的輸出,使用一個間接緩沖區;空間位置相同而通道不同的輸出使用相同的間接緩沖區,緩沖區中的每個指針用于索引輸入中 個元素。在計算時,随着輸出的移動,選用不同的間接緩沖區,即可得到相應的輸入位址。無需再根據輸出目标的坐标計算要使用的輸入的位址,這等同于預先計算位址。

圖十一繪制了當 × 為 4 、 和 均為 3 時,間接緩沖區的實際使用方法與計算過程。圖中命名為局部間接緩沖區意指目前考慮的是計算 × 時核心計算的過程。

當計算 × 大小的輸出時,使用的輸入為卷積核在對應輸入位置上滑動 步所覆寫的趨于,即規模 ()×(+2(−1))× 的輸入。在間接卷積算法中,這些輸入記憶體由 M個間接緩沖區中的指針索引,共有 ×× 個。圖十一中辨別出了輸入空間位置左上角輸入和相應的輸入緩沖區的對應關系。可以看到,這裡的 A、B、C、D 四個輸入緩沖區,相鄰的兩個緩沖區所指向的位址區域有 (−)/ ,這裡即為 2/3 ,各個緩沖區中指針的坐标也已标明。

卷積神經網絡性能優化

圖十一:間接緩沖區詳解

圖中将平面緩沖區繪制成三維形式(增加 IC 次元),意在說明間接緩沖區的每個指針可索引 IC 個輸入元素,而每個間接緩沖區索引的内容即為與權重對應的輸入記憶體區域。

進一步地,左上角的輸入緩沖區排列方式并不是最終的排布方法,實際上這些指針會被處理成圖十一中部間接緩沖區的形式。将左上每個緩沖區中的指針打散,即可得到 × 指針,将 A、B、C、D 四個緩沖區的不同空間位置的指針收集到一起,即可得到圖中上部分的緩沖區排列方式 ××。可以看到, A、B、C、D 四個緩沖區内部相同空間位置的指針被組織到了一起。圖中中上部分是可視化的效果,中下部分則是間接緩沖區的真正組織方式。圖中褐色和深黃色的着色對應着相同的輸入記憶體或指針。值得注意的是,圖例中 Stride 為 1,當 Stride 不為 1 時,重新組織後 A、B、C、D 相同空間的坐标(對應于在輸入的坐标)不一定是連續的,相鄰的空間位置橫向坐标相差 大小。

使用間接緩沖區計算

我們已經知道了間接緩沖區的組織形式,以及其指針對應于輸入記憶體的位址趨于,現在來研究在計算過程中如何使用這些緩沖區。

和上一小節一樣,本小節的讨論大體都在計算 × 規模的輸出,而這些輸出要使用 個 × 大小的輸入,其中有資料重用。現在回顧一下 Im2col 的算法(如圖十一中下左部分),當向量化運作計算時,對于 × 的矩陣乘計算,每次取出 × 規模的輸入和 × 規模的權重,對該塊運作矩陣乘即可得到相應的部分和結果。其中 是向量化計算在 K次元上的步進因子。

而卷積之是以可以使用 Im2col 優化算法,本質原因在于其拆解後忽略記憶體複用後的計算過程等價于矩陣乘。而間接緩沖區使得可以通過指針模拟出對輸入的訪存。在實際運作計算 × 輸出的計算核(micro kernel)時,會有 個指針掃描輸入。個指針每次從圖十一中下部分的間接緩沖區結構中取出 個位址,即對應于輸入 × 的記憶體,如圖中右上角的布局。在這裡的步進中,仍是以 × 形式運作,其中 在 次元上運動。當這部分輸入掃描完畢後,這 個指針從間接緩沖區中取出相應的指針,繼續下一次對 × 輸入記憶體的周遊,每次計算出 1/(∗) 的輸出部分和。當這個過程運作 × 次後,即得到了 × 的輸出。圖十一右下角的僞代碼對應了這一過程。由于間接緩沖區已經被組織成了特定的形狀,是以每次更新 個指針時,隻需要從間接緩沖區指針(圖中僞代碼裡的 p_indirect_buffer)中擷取。

這個過程的邏輯不易了解,這裡再做一點補充說明。當上述的 個指針不斷運動掃描記憶體時,實際上是在掃描三維輸入 Im2col 之後的矩陣。而輸入緩沖區的特定是它将對二維矩陣的掃描轉化為了對三維張量的掃描。對輸入的掃描過程即是對圖十一中上部分可視化的輸入的掃描,聯系左上和左下對應的輸入關系,不難發現它每次掃描輸入中 × 塊記憶體。值得注意的是,這裡的 × 由 個 1× 張量組成,它們之間 次元的間距為 。

這樣一來,隻要運作該計算核心 ⌈∗/⌉∗⌈/⌉ 次,即可得到全部輸出。

間接卷積優化算法解決了卷積計算的三個問題,第一是空間向量化問題,第二是位址計算複雜問題,第三是記憶體拷貝問題。一般計算卷積時都需要對輸入補零(對于 × 不是 1×1 的情況),這個過程傳統的方法都會發生記憶體拷貝。而間接卷積優化算法中的間接緩沖區可以通過間接指針巧妙地解決這一問題。在構造間接緩沖區時額外建立一塊 1× 的記憶體緩沖區,其中填入零值,對于空間中需要補零的位置,将相應的間接指針指向該緩沖區,那麼後續計算時即相當于已經補零。例如圖十一中 A 的左上角對應于輸入空間位置 (0,0) 的,當需要補零時該位置一定要為零值,此時隻要修改間接緩沖區的位址即可。

讨論、總結與展望

至此,本文探讨了一些已經發表或開源的卷積神經網絡的優化方法。這些優化方法或多或少地推動了深度學習技術在雲端或移動端的應用,幫助了我們的日常生活。例如,最近上海人民乃至全中國人們頭疼的垃圾分類問題,也可以利用深度學習方法來幫助人們了解如何分類。

  • 利用深度學習方法來幫助人們了解如何分類連結:
  • https://news.mydrivers.com/1/633/633858.htm

從本文的集中優化方法中可以看到,卷積神經網絡的優化算法依然可以囊括在基于算法分析的方法和基于軟體優化的方法。實際上,在現代計算機系統中,基于軟體優化的方法,特别是基于計算機存儲層次結構的優化顯得更為重要,因為其方法更容易挖掘和應用。另一方面也是因為現代計算機新增的專用指令已經可以抹除不同計算的耗時差異。在這種場景下,基于算法分析的方法要和基于軟體優化的方法結合或許能取得更優的優化效果。

最後,本文讨論的優化方法都是通用的方法,而随着神經網絡處理器(如寒武紀 MLU、Google TPU)的發展,以及其他通用計算處理器的拓展(如點積相關的指令:Nvidia GPU DP4A、Intel AVX-512 VNNI、ARM SDOT/UDOT ),深度學習的優化或許還值得繼續投入資源。

寒武紀 MLU 連結:

https://www.jiqizhixin.com/articles/2019-06-20-12

Nvidia GPU DP4A 連結:

https://devblogs.nvidia.com/mixed-precision-programming-cuda-8/

Intel AVX-512 VNN 連結:

本文寫作過程中參考了以下(包括但不限于)資料:

QNNPACK

( 連結:https://github.com/pytorch/QNNPACK )

Convolution in Caffe

( 連結:https://github.com/Yangqing/caffe/wiki/Convolution-in-Caffe:-a-memo )

TensorFlow

Wikipedia

Fast Algorithms for Convolutional Neural Networks

( 連結:https://github.com/Tencent/ncnn )

NCNN

( 連結:https://github.com/OAID/Tengine )

Tengine

( 連結:https://jackwish.net/neural-network-quantization-introduction-chn.html )

神經網絡量化簡介

通用矩陣乘(GEMM)優化算法

( 連結:https://jackwish.net/gemm-optimization.html )

The Indirect Convolution Algorithm

繼續閱讀