- read

神經網路的推理速度是由什麼決定的?

Rice Yang 46

圖片來源:Time Travel Wallpapers — Top Free Time Travel Backgrounds — Time Travel Hd Wallpaper | Neat

深度學習使用了更深層的神經網路,擁有更多的參數,讓深度學習具備了優於傳統機器學習的學習表徵能力。與此同時,過多的參數與計算量也讓深度學習模型也很難在一般的機器上 real-time 執行。

從大約 2015 年開始,研究人員透過軟體、硬體、演算法等,透過不同的方式加速深度學習的推理時間;但是在探討加速方法之前,我們得先知道影響深度學習模型的推理時計算速度的關鍵因素有哪些。

這篇文章列舉了一些影響神經網路推理速度的指標,並且逐個介紹其如何影響神經網路的推理速度:

  • FLOPs
  • MACs
  • Floating-Point Precision 浮點數精度
  • Quantization 量化
  • Inference SDK
  • Process Unit 計算單元

FLOPs — 最直接的指標

FLOPs (Floating Point Operations),直譯就是浮點數的計算次數,是最直接用來評量深度學習速度的指標。一個簡單的概念是:如果一個演算法所需要的浮點數計算次數越多,那麼這個演算法所需要的時間越長。

值得注意的是,FLOPs 並不等於模型參數量。FLOPs 表示的是模型的計算成本,而模型參數量只能表示模型的大小與頻寬,不能直接反映模型的推理時間。

雖然說 FLOPs 只計算浮點數,但是通常神經網路的計算都是浮點數的,所以實際上我們在計算深度學習的 FLOPs 的時候並特別不會去確認數字的類型。對一個神經網路而言,總共的 FLOPs 就是所有子 OP (Operations) 的 FLOPs 加總。

舉例來說,Convolution OP 的 FLOPs 計算方式如下:

其中 Ci 表示輸入的 Channel 數量,Co 表示輸出的 Channel 數量,H, W 表示輸出的 Feature Map 的高, 寬,而 K 表示 Convolution Kernel 的大小

下圖的用動畫的例子來說明的話,上述公式可以展開成 (2 x 1 x 3 x 3–1) x 3 x 3 x 1 = 17 x 9 = 153,也就是 FLOPs=153。後面的 9 對應著動畫的 9 次卷積移動,而前面的 17 則是每格輸出數字需要的乘法與加法次數。

卷積操作的動畫示意圖。來源:A Comprehensive Guide to Convolutional Neural Networks — the ELI5 way

值得注意的是,無論原輸入與卷積核的數字是不是 0,在計算 FLOPs 的時候都需要納入計算。如果要將原輸入與卷積核的數字 0 剔除計算,則需要特殊的硬體支援。

MACs

MACs (Memory Access Costs) ,有時候也會寫成 Memory Access,指的是記憶體的存取次數。通常 MACs 是與 FLOPs 成正比的,但是在根據網路結構的不同,MACs 可能會在 FLOPs 不變的情況下增加,導致模型的推理時間變長。

在經典輕量化網路之一 SufficientNet V2 的論文中,作者對 MACs 做了一次詳盡的分析,發現一些常見的降低 FLOPs 的卷積設計,例如 Element-wise Convolution, Group Convolution,反而會使 MACs 增加。同時,在同樣的卷積設計下,輸入與輸出 Channels 相同時的 MACs 會最低,速度也會提升。

同樣的模型,在不同的晶片上會有不同的耗時比例。作者認為這是由於不同晶片對 MACs 的 IO 成本不同所導致的。來源:EfficientNet V2 論文

MACs 會導致運行速度增加的原因,是由於電腦的 IO 處理都是需要時間的。要進行一次的卷積計算,就勢必得把輸入與卷積核中的數字都從各自的記憶體中取出來,計算完後再寫到輸出的記憶體內。在一般的程式設計準則中,需要儘量減少 IO 操作例如 memory copy 也是基於一樣的道理,因為 IO 成本其實不低且通常難以察覺。

Floating Point Precision 浮點數精度

由於神經網路中的計算都是基於浮點數,因此使用精度越高的浮點數就可能造成越大的耗時。這篇文章列出了各種浮點數類型,並且用圖片的方式表示各種浮點數類型中每個 bit 的用途:

將浮點數轉變為整數的過程示意圖。來源:Inside Quantization Aware Training

量化訓練 Quantization Aware Training

量化訓練是在模型的訓練階段就把模型類型轉換為整數型。通常的量化訓練包含 3 個步驟:

  1. 使用一般的浮點數模型訓練。
  2. 統計浮點數輸出的值域邊界,把網路權重轉換為整數與一組 scaling、bias,並持續訓練權重、scaling、bias。
  3. 保存模型,紀錄學習的權重、scaling、bias。

目前 TensorFlow 對量化訓練的支援程度遠比 PyTorch 好,詳細範例可以參考 TensorFlow 的官方教學:

Quantization aware training in Keras example

Welcome to an end-to-end example for quantization aware training. For an introduction to what quantization aware…

www.tensorflow.org

TensorRT 的網路加速示意圖。來源:NVIDIA TensorRT
  1. Reduce Mixed Precision:透過混合精度,將模型轉換為更低的浮點精度或是整數量化,在計算損失最小的情況下增加推理速度。
  2. Tayer/Tensor Fusion:融合相鄰的線型計算來減少推理時間,包含垂直融合與水平融合。比如前後 Conv/BN 層是可以完全融合成一個 Conv 表示的,屬於垂直融合;而多分支的 Conv 分支也可以融合為一個 Conv 層,屬於水平融合。Layer/Tensor Fusion 直接降低了模型的 FLOPs,達到加速作用。
  3. Kernel Auto-Tuning:相同的卷積運算在底層可能有不同的實作方式。SDK 會根據部署機器的不同,選擇最好的卷積計算實作。
  4. Dynamic Tensor Memory:透過動態的記憶體管理機制,降低記憶體的獲取、釋放、搬運次數,達成加速的效果。
  5. Multi-Stream Execution:利用平行計算降低運行時間。
  6. Time Fusion:針對 RNN 類的時序網路做的特殊加速。

Process Unit 計算單元

不同的計算單元會有不同的加速指令集與硬體實作,因此將模型部署在不同的計算單元上,推理的速度也會不一樣。除了深度學習最常用到的 GPU 之外,也有很多為了深度學習提出的專門晶片,例如 Google 推出的 TPU,以及各家晶片廠為移動設備設計的 NPU。另外,為了程式與模型的通用型,也有不少消費級的 APP 會把模型部署在 CPU。

GPU

GPU 本來是為了電腦繪圖設計的芯片,其特性是核心數非常多,因此可以利用來做大量的平行計算。早期只有 CUDA 的時代,GPU 就有被用來做科學計算的用途;在深度學習框架普世之後,GPU 在 AI 的地位也越來越穩固,是目前學術界最通用的部屬方式。

TPU

TPU,Tensor Process Unit,是 Google 為了深度學習專門推出的計算晶片,在產業界用的較多。通常是配備給雲端 Server,用來加速機器學習的訓練、推理。

NPU

NPU,Neural Process Unit,一般是指終端設備使用的深度學習專用晶片。不同廠家的 NPU,對浮點精度、量化類型、卷積類型的支援程度也不一樣。值得注意的是,很多廠商並不會用 NPU 這個名字,例如聯發科的 MT8175 中用的名字是 AI Accelerator

CPU

CPU 是最通用的計算單元,因此將深度學習部署在 CPU 上也是最通用的部屬方式。值得注意的是,在相同的 CPU 計算主頻率下,不同的 CPU 架構以及指令集也會導致不同的推理時間,例如 RISC-V。

目前硬體加速也是深度學習的一個研究方向之一。例如今年 Facebook 提出了新的論文 ELMA,可以使用新的硬件架構,在維持模型浮點精度不變的情況下加速深度學習的推理時間,效果甚至可以超越 8 bits 量化。

Making floating point math highly efficient for AI hardware

In recent years, compute-intensive artificial intelligence tasks have prompted creation of a wide variety of custom…

engineering.fb.com

結論

雖然我們在研讀深度學習論文時,大部分的網路架構只會列出參數量與FLOPs,作為網路 runtime 的速度指標。但是實際上神經網路的計算速度遠遠不是這兩個參數可以定義的。

在實際情況下,我們需要針對不同的部屬環境去設計不同的網路。例如對於部署在 server 端的模型,我們可以使用 Float32、中等 FLOPs 的模型設計,結合 TensorRT 的部屬方式;但是對於部署在 ARM 芯片的模型,我們可能需要 8-bits 量化、低 FLOPs、低 MACs 的模型設計,並且搭配 TFLite 達到最佳的加速效果。