選單

深度學習模型大小與模型推理速度的探討

導讀

作者:田子宸,畢業於浙江大學,就職於商湯,文章經過作者同意轉載。

本文將對衡量深度學習模型大小的一些常用指標,如計算量、引數量、訪存量、記憶體佔用等進行探討,分析這些指標對模型部署推理的影響,尤其是計算量與訪存量對模型推理速度的影響,並給出在不同硬體架構下設計網路結構的一些建議。

原文地址:https://zhuanlan。zhihu。com/p/411522457

01

前言

當年頭一次實習做演算法的時候,主管給的第一個任務就是“把一個大的分割模型砍成一個小的”。當時並不理解模型“大”、“小”的真正含義,就簡單的選取計算量作為評價指標,瘋狂砍計算量(backbone 換 MobileNet/ShuffleNet、Conv 換成 DepthWise Conv、以及一些奇奇怪怪的融合結構等等),把模型計算量砍了將近 10 倍,結果一部署發現速度並沒有快多少,反而是把最初的 ResNet 簡單砍掉幾個 block 效果更好。

也是從那時起接觸了訪存量、流水線、RoofLine 模型等概念,對模型推理速度的問題產生了興趣,從此踏上了深度學習推理最佳化的不歸路(劃掉)。

如今做推理最佳化和 HPC 已經有一段時間了,還是偶爾能回想起當年不懂推理時設計的與硬體嚴重不匹配的模型。此外在工作中跟研究員溝通時,也會發現部分研究員對模型大小和模型推理速度的關係不太瞭解,設計出一些很難發揮硬體計算能力的模型結構。因此在這裡對一些用於評價模型大小的指標——計算量、引數量、訪存量、記憶體佔用等指標進行詳細探討,分析這些指標會對模型的部署推理產生何種影響,詳細討論計算量和訪存量對模型推理速度的影響,並給出不同硬體架構下設計高效網路結構的一些建議。

本文不僅僅是為了給出網路的設計建議,更是希望能夠有效傳達效能最佳化的基礎理論知識,以及效能分析的基本思路,幫助各位同學減少網路設計與部署之間的 gap,更高效的完成網路設計與部署工作。非常希望本文能夠對大家的工作有所幫助,也非常歡迎大家在評論區留言探討。

02

常用的模型大小評估指標

目前常用於評價模型大小的指標有:計算量、引數量、訪存量、記憶體佔用等,這些指標從不同維度評價了模型的大小。本節僅作簡單介紹,熟悉的小夥伴可以跳過此節,直接看後面的分析與探討。

1。 計算量

計算量可以說是評價模型大小最常用的指標了,很多論文在跟 baseline 進行比較時,都會把計算量作為重要的比較依據。

計算量是模型所需的計算次數,反映了模型對硬體計算單元的需求。計算量一般用 OPs (Operations) ,即計算次數來表示。由於最常用的資料格式為 float32,因此也常常被寫作 FLOPs (Floating Point Operations),即浮點計算次數。(這裡為了跟傳統習慣保持一致,下文就統一採用 FLOPs 啦)

模型的整體計算量等於模型中每個運算元的計算量之和。而每個運算元的計算量計算方法各不一致。例如對於 Eltwise Sum 來講,兩個大小均為 (N, C, H, W) 的 Tensor 相加,計算量就是 N x C x H x W;而對於卷積來說,計算量公式為(乘加各算一次):

PyTorch 有不少工具可以模型計算量,但需要注意的是這些工具有可能會遺漏一些運算元的計算量,將其計算量算成 0,從而導致統計的計算量跟實際計算量有輕微的偏差,不過大多數情況下這些偏差影響不大。

2。 引數量

早期的論文也很喜歡用引數量來評價模型大小。

引數量是模型中的引數的總和,跟模型在磁碟中所需的空間大小直接相關。對於 CNN 來說引數主要由 Conv/FC 層的 Weight 構成,當然其他的一些運算元也有引數,不過一般忽略不計了。

引數量往往是被算作訪存量的一部分,因此引數量不直接影響模型推理效能。但是引數量一方面會影響記憶體佔用,另一方面也會影響程式初始化的時間。

引數量會直接影響軟體包的大小。當軟體包大小是很重要的指標時,引數量至關重要,例如手機 APP 場景,往往對 APK 包的大小有比較嚴格的限制;此外有些嵌入式裝置的 Flash 空間很小,如果模型磁碟所需空間很大的話,可能會放不下,因此也會對引數量有所要求。

除了在設計模型時減少引數量外,還可以透過壓縮模型的方式降低軟體包大小。例如 Caffe 和 ONNX 採用的 Protobuf 就會對模型進行高效的編碼壓縮。不過壓縮模型會帶來解壓縮開銷,會一定程度增加程式初始化的時間。

3。 訪存量

訪存量往往是最容易忽視的評價指標,但其實是現在的計算架構中對效能影響極大的指標。

訪存量是指模型計算時所需訪問儲存單元的位元組大小,反映了模型對儲存單元頻寬的需求。訪存量一般用 Bytes(或者 KB/MB/GB)來表示,即模型計算到底需要存/取多少 Bytes 的資料。

和計算量一樣,模型整體訪存量等於模型各個運算元的訪存量之和。對於 Eltwise Sum 來講,兩個大小均為 (N, C, H, W) 的 Tensor 相加,訪存量是 (2 + 1) x N x C x H x W x sizeof(data_type),其中 2 代表讀兩個 Tensor,1 代表寫一個 Tensor;而對於卷積來說,訪存量公式為:

訪存量對模型的推理速度至關重要,設計模型時需要予以關注。

4。 記憶體佔用

記憶體佔用是指模型執行時,所佔用的記憶體/視訊記憶體大小。一般有工程意義的是最大記憶體佔用,當然有的場景下會使用平均記憶體佔用。這裡要注意的是,記憶體佔用 ≠ 訪存量。

記憶體佔用在論文裡不常用,主要原因是其大小除了受模型本身影響外,還受軟體實現的影響。例如有的框架為了保證推理速度,會將模型中每一個 Tensor 所需的記憶體都提前分配好,因此記憶體佔用為網路所有 Tensor 大小的總和;但更多的框架會提供 lite 記憶體模式,即動態為 Tensor 分配記憶體,以最大程度節省記憶體佔用(當然可能會犧牲一部分效能)。

和引數量一樣,記憶體佔用不會直接影響推理速度,往往算作訪存量的一部分。但在同一平臺上有多個任務併發的環境下,如推理伺服器、車載平臺、手機 APP,往往要求記憶體佔用可控。可控一方面是指記憶體/視訊記憶體佔用量,如果佔用太多,其他任務就無法在平臺上執行;另一方面是指記憶體/視訊記憶體的佔用量不會大幅波動,影響其他任務的可用性。

5。 小結

計算量、引數量、訪存量、記憶體佔用從不同維度定義了模型的大小,應根據不同的場合選用合適的指標進行評價。

模型推理速度不單單受模型計算量的影響,也與訪存量和一些其他因素息息相關。下文將詳細討論影響模型推理速度的因素。

03

計算量越小,模型推理就越快嗎

答案是否定的。

實際上計算量和實際的推理速度之間沒有直接的因果關係。計算量僅能作為模型推理速度的一個參考依據。

模型在特定硬體上的推理速度,除了受計算量影響外,還會受訪存量、硬體特性、軟體實現、系統環境等諸多因素影響,呈現出複雜的特性。因此,在手頭有硬體且測試方便的情況下,實測是最準確的效能評估方式。

在設計網路結構時,如果有實測的條件,建議在模型迭代早期對效能也進行測試。一些 NAS 的方法也會對搜尋出來的網路結構進行測速,或者乾脆對硬體速度進行了建模,也作為初期搜尋的重要引數。這種方法設計出來的網路在後期部署時,會極大減少因效能問題迭代最佳化的時間和人力開銷。

這裡我將討論影響模型在硬體上推理速度的一些因素,一方面希望可以幫助手動/自動設計網路結構的同學更快的設計更高效的網路結構,另一方面希望當模型部署時效能出現問題時能夠為大家提供分析原因的思路。

這一問題我將從如下 3 個點進行討論:

計算密度與 RoofLine 模型

計算密集型運算元與訪存密集型運算元

推理時間

1。 計算密度與 RoofLine 模型

計算密度是指一個程式在單位訪存量下所需的計算量,單位是 FLOPs/Byte。其計算公式很簡單,很多教材、資料裡也稱之為計算訪存比,用於反映一個程式相對於訪存來說計算的密集程度:

RoofLine 模型是一個用於評估程式在硬體上能達到的效能上界的模型,可用下圖表示:

深度學習模型大小與模型推理速度的探討

RoofLine 模型

用公式描述:

當程式的計算密度I較小時,程式訪存多而計算少,效能受記憶體頻寬限制,稱為訪存密集型程式,即圖中橙色區域。在此區域的程式效能上界=計算密度×記憶體頻寬,表現為圖中的斜線,其中斜率為記憶體頻寬的大小。計算密度越大,程式所能達到的速度上界越高,但使用的記憶體頻寬始終為最大值。

反之如果計算密度I較大,程式效能受硬體最大計算峰值(下文簡稱為算力)限制,稱為計算密集型程式,即圖中藍色區域。此時效能上界=硬體算力,表現為圖中的橫線。此時計算速度不受計算密度影響,但計算密度越大,所需記憶體頻寬就越少。

在兩條線的交點處,計算速度和記憶體頻寬同時到達最大值。

深度學習模型大小與模型推理速度的探討

在不同裝置上,同一個程式的性質可能發生變化

在不同裝置上,同一個程式的性質可能發生變化。例如上圖中的程式2,在算力稍弱的裝置2上屬於計算密集型程式,而在算力較強的裝置1上就屬於訪存密集型程式了(感謝評論區指正)。如果想要充分發揮裝置1的效能,應當適當加大程式的計算密度(比如到程式3的位置)。

2。 計算密集型運算元與訪存密集型運算元

網路中的運算元可以根據計算密度進行分類。一般來講,Conv、FC、Deconv 運算元屬於計算密集型運算元;ReLU、EltWise Add、Concat 等屬於訪存密集型運算元。

同一個運算元也會因引數的不同而導致計算密度變化,甚至改變性質,比如在其他引數不變的前提下,增大 Conv 的 group,或者減小 Conv 的 input channel 都會減小計算密度。

舉個栗子,對於不同引數的卷積,計算密度如下:

可以看到,不同引數下卷積運算元的計算密度有很大的差異。第 4 個運算元 Depthwise Conv 計算密度僅有 2。346,在當下的很多裝置上都屬於訪存密集型運算元。

運算元的計算密度越大,約有可能提升硬體的計算效率,充分發揮硬體效能。我們以一個 Intel X86 伺服器平臺為例(10980 XE)。該平臺 CPU 頻率為 4。5 GHz,我們以 16 核為例,其理論 FP32 算力為 4。608 TFLOPs/s,記憶體頻寬理論值為 96 GB/s。在此平臺上的 RoofLine 模型為:

深度學習模型大小與模型推理速度的探討

Intel 10980 XE 16 核 RoofLine 模型,以及各個運算元的計算密度與效能

該平臺“拐點”的計算密度為 48,計算較為密集的 OP1 和 OP2 處在計算密集區,能夠達到平臺的算力峰值;而 OP3 和 OP4 處在訪存密集區,受記憶體頻寬限制不能到達算力峰值,尤其是 OP4,由於計算訪存比過低,計算效率僅有可憐的 4。9%,計算效率並不高。

3。 推理時間

這裡涉及到一個 gap,很多部署的同學們更喜歡談“計算效率”,而實際上演算法同學真正關心的點是“推理時間”,導致兩者在對接的時候經常會出現一些 misleading。因此我這裡單獨開一節來探討一下“推理時間”的評估方法。

其實也很簡單,按照 RoofLine 模型,我們很容易就能得到運算元實際的執行時間:

這是一個分段函式,拆開來可得:

一句話總結:對於訪存密集型運算元,推理時間跟訪存量呈線性關係,而對於計算密集型運算元,推理時間跟計算量呈線性關係。

講到這裡,我們就能初步回答本章一開始的問題了:按照 RoofLine 模型,在計算密集區,計算量越小,確實推理時間越小。但是在訪存密集區,計算量與推理時間沒關係,真正起作用的是訪存量,訪存量越小,推理的時間才越快。在全域性上,計算量和推理時間並非具有線性關係。

上一節中,OP4 雖然計算效率很低,但由於訪存量也很低,因此其實推理速度還是快於其他幾個 OP 的。但是我們可以觀察到,其計算量雖然只有 OP1 的 1/130,但是推理時間僅降低到了 1/6,兩者並非是線性關係(也是當年我把模型減到 1/10 計算量,但其實沒快多少的原因)。

再舉兩個例子強化一下,首先看這兩個卷積,他們的計算量差不多,但是因為都在訪存密集區,OP3 的訪存量遠低於 OP5,其推理也更快:

下面這個栗子更明顯,OP5 和 OP6 的區別僅僅是一個是 DepthWise Conv,一個是普通 Conv,其他引數沒有變化。按照我們之前的直觀感受,Conv 換成 DepthWise Conv 應該會更快,但實際上兩者的推理時間是差不多的(這組引數也是當年我用過的【手動捂臉):

4. 小結

從上面的討論中我們可以看出:計算量並不能單獨用來評估模型的推理時間,還必須結合硬體特性(算力&頻寬),以及訪存量來進行綜合評估。並非是計算量越低模型推理越快。在評價模型大小時,也建議加上訪存量作為重要的評價指標。

需要強調的一點是,不同的硬體平臺峰值算力和記憶體頻寬不同,導致同一個模型在平臺 1 上可能是計算密集的,在平臺 2 上可能就變成了訪存密集的。例如上文提到的 Intel X86 平臺,“拐點”值為 48,而 NVIDIA V100“拐點”值為 173。6,上文舉的例子在 V100 平臺上僅有 OP2 落在了計算密集區,剩下的全部是訪存密集的。因此,同樣的模型在不同平臺上性質可能會發生改變,需要具體情況具體分析。

我們很難給出一個通用性的結論,究其原因是 RoofLine 模型本身是一個非線性模型。這裡必須要強調一點的是,除了峰值算力和記憶體頻寬之外,還有硬體限制、系統環境、軟體實現等諸多因素會影響程式的實際效能,使得其非線性特性更加嚴重。因此 RoofLine 模型僅僅只能提供一個性能上界的評估方式,並不代表能夠達到的實際效能。實際效能最準確的測量方式只有真機實測。

RoofLine 模型更重要的是提供了一種分析效能的思想,即計算密集型程式更多的受限於硬體算力,而訪存密集型程式更多的受限於硬體記憶體頻寬。在理解這一點的基礎上設計網路結構,並分析網路的效能,將更有理論參考。不會再對”計算量減半,為啥推理時間沒變“這種問題抱有疑問了(說的就是我【流淚)

下文將對 RoofLine 模型的一些限制進行討論,分析哪些因素將以何種方式影響程式,使得其到達不了 RoofLine 模型估計的效能上界。

(下文要開始難度升級了,建議沒看懂 RoofLine 模型的同學們再把這一章看一遍,不然後面會看的有點懵)

04

影響模型推理效能的其他因素

RoofLine 模型可以用來評估程式的效能上界,但是實際能達到的效能還會受到硬體限制、系統環境、軟體實現等諸多因素的影響,距離效能上界有一定距離。本章將對這些影響因素進行分析。

1。 硬體限制對效能上界的影響

前面 RoofLine 模型使用的峰值算力及記憶體頻寬,是根據紙面資料計算得到的,是理論上的最大值。但在實際情況下,硬體會因為種種原因,無法達到這個理論值。因此建議大家對硬體進行micro-benchmark,以獲取硬體的真實效能上限。

以上文的 Intel X86 CPU 為例,我們之前計算的 avx512 理論算力為 4。608 TFLOPs/s,但這個數值的前提是頻率能維持在 4。5 GHz。然而實際上在使用 16 核跑 avx512 指令時,CPU 頻率會下降到約 2。9 GHz,此時理論算力僅剩下 2。96 TFLOPs/s,而實測值僅有 2。86 TFLOPs/s。

除了頻率之外,有些晶片可能會因為一些設計上或實現上的原因,導致在實際使用時達不到理論峰值。比如一些低端晶片不支援多發射、不支援亂序執行、採用了阻塞式 Cache 等等,一些晶片甚至會有一些效能 bug,導致在實際使用時幾乎到達不了理論峰值(這裡我個人傾向於把這些原因歸結為硬體限制帶來的損失)。

記憶體同理,該平臺理論頻寬為 96GB/s,但實測下來最高讀頻寬僅有 74 GB/s,僅能到達理論頻寬的 77%。

我們可以得到修正後的 RoofLine 模型,圖中藍色填充部分反映了因實際算力和記憶體頻寬達到不了理論值而造成的損失:

深度學習模型大小與模型推理速度的探討

修正了實測峰值算力和記憶體頻寬後的 RoofLine 模型,藍色填充部分為硬體限制帶來的損失

修正後的模型“拐點”發生了變化,因此運算元的性質也會發生變化。建議拿到硬體後對硬體進行 micro-benchmark,這裡推薦兩個測試工具:

一個是高叔叔寫的浮點峰值測試方法的文章,最後有 github 連結,大家可以 clone 下來測試硬體峰值:

https://zhuanlan。zhihu。com/p/28226956

還有一個是 stream 測試工具,可以用於測試記憶體頻寬:

https://www。cs。virginia。edu/stream/

2。 系統環境對效能的影響

除非程式執行在裸機中,否則作業系統一定會對效能上界產生一定影響,比如作業系統在多核間的排程損失、作業系統的記憶體管理帶來的損失、作業系統本身佔用的運算資源等等。

對於一般的深度學習推理任務而言,現代作業系統對效能的影響並不是特別明顯。但是在一些特殊情況下,也會帶來嚴重的效能損失。我這裡將會舉兩個例子:

一個是 Android 系統在大小核上的排程,一旦程式在 CPU 上的佔用率不足(比如是週期工作的任務),則有可能被 Android 排程到小核上,帶來效能損失。

另一個例子是記憶體缺頁。在 Linux 系統上,當向系統申請記憶體頁後,系統只是返回了虛擬頁,等到程式實際使用虛擬頁時,才會透過觸發缺頁異常的方式,進入作業系統核心分配物理頁,這一過程會嚴重降低效能。

好在這些問題可以透過軟體進行一部分彌補,例如排程問題可以使用綁核來解決,缺頁問題可以透過繫結物理頁(需要核心態)或記憶體池來解決。因此作業系統帶來的影響是可控的。

除了作業系統帶來的影響,系統中執行的其他程序也會對當前程序造成影響。比如一個系統中運行了多個深度學習例項,或者系統後臺一些 APP 自啟動了等等。這些程序都會佔用核心算力和記憶體頻寬,造成當前程序效能損失。

這往往會導致在工程測試環境下效能達標的模型,在實際部署時效能下降。因此,必須關注工程測試環境和實際部署系統環境的差異。如有條件,最好在實際部署環境下進行測試。

3。 軟體實現對效能的影響

除了硬體限制和系統環境外,一個任務的軟體實現好壞對效能有著重大的影響。

例如對於同樣的矩陣操作任務,使用 python 寫的多重 for 迴圈,和用 numpy 高度最佳化過的矩陣操作函式,效能可以差出 1~2 個數量級。

對於深度學習模型推理而言,推理框架對模型效能的影響主要體現在:是否充分利用了硬體的流水線資源、是否高效利用了硬體中的快取、是否採用了時間複雜度更低的演算法、是否解決了作業系統帶來的效能損失(如上文的排程問題和記憶體缺頁問題)、是否進行了正確高效的圖最佳化等等。

由於影響因素很多,因此軟體對效能的影響往往呈現出很強的非線性,導致在評估效能時很難給出一些普適性的結論,很多時候只能具體情況具體分析。(有的時候甚至有點玄學【捂臉)

例如同樣計算量的向量四則運算和超越函式,後者往往會慢於前者的原因是很多硬體不支援超越函式的 SIMD 指令;再比如空洞卷積(dilated Conv)效能會弱於普通卷積的原因是前者對訪存的利用不如後者高效等等。

在軟體實現的影響下,RoofLine 模型的上界再次下降,達到圖中的紅線(真實的非線性可能會比我隨手畫的要複雜的多):

深度學習模型大小與模型推理速度的探討

RoofLine 模型各種效能損失示意圖,圖中曲線不代表真實比例

因此,在評估或分析深度學習推理效能時,簡單的計算量/訪存量指標是完全不夠的,只能做個性能上界參考。實際能達到的效能其實還要關注很多很多因素,例如運算元的訪存模式、資料排布、是否能夠進行圖融合、是否有精度可接受的低時間複雜度演算法、演算法並行度是否充足、各種運算的比例等等因素。

這些因素對於演算法同學而言可能過於複雜,並不需要掌握。但如果所在的公司/部門有交流的機會的話,可以跟部署/最佳化的同學針對模型結構和運算元進行探討,以獲取效能最佳化的建議。

這裡可以一些一般性的結論,僅供參考:

對於一些訪存非常密集且訪存 pattern 連續的運算元,如 Concat、Eltwise Sum、ReLU、LeakyReLU、ReflectionPad 等,在 Tensor 資料量很大的情況下,軟體實現的損失會非常小,正常情況下基本都能達到記憶體頻寬實測上限;如果框架採用了融合策略的話,基本可以達到 0 開銷。

對於 Conv/FC/Deconv 等運算元,在計算密度很高的情況下,大多數框架是能夠很接近算力峰值的。但對於計算密度不是特別高的 case,不同框架的表現不一,需要實測才能確定。不過從大趨勢而言,都是計算密度越高,硬體的利用率越高的。

儘量使用常用的運算元引數,例如 Conv 儘量使用 3x3_s1/s2,1x1_s1/s2 等,這些常用引數往往會被特殊最佳化,效能更好。

4。 小結

RoofLine 模型僅能用於估計模型所能達到的效能上界,而實際部署時,還會受硬體限制、系統環境、軟體實現等因素的影響,導致無法達到 RoofLine 模型所定義的效能上界。

此外,由於這些因素往往會導致效能曲線有較強的非線性,理論分析和實測會有一定差距,有時這些因素會嚴重影響效能曲線,甚至會導致運算元的性質發生變化。因此本節討論的內容只是提供一些分析的思路與技巧,實測始終是最準確的效能評估方式。

05

面向推理速度的模型設計建議

前面討論了一大堆,其實最實用的還是“怎麼設計模型能夠達到更快的推理速度”。

在給出我的個人建議之前,首先要先宣告的是:由於不同硬體、不同環境、不同框架的差異會很大,這些建議可能並不是在所有條件下都適用。在設計算法或效能測試遇到疑問時,建議諮詢部署/最佳化的同學。

好了,廢話不多說(其實已經說了很多了),給出我的一些個人建議:

方法論建議:

瞭解目標硬體的峰值算力和記憶體頻寬,最好是實測值,用於指導網路設計和運算元引數選擇。

明確測試環境和實際部署環境的差異,最好能夠在實際部署環境下測試效能,或者在測試環境下模擬實際部署環境。

針對不同的硬體平臺,可以設計不同計算密度的網路,以在各個平臺上充分發揮硬體計算能力(雖然工作量可能會翻好幾倍【捂臉)。

除了使用計算量來表示/對比模型大小外,建議引入訪存量、特定平臺執行時間,來綜合反映模型大小。

實測是最準確的效能評估方式,如果有條件快速實測的話,建議以實測與理論分析相結合的方式設計並迭代網路。

遇到效能問題時,可以逐層 profiling,並與部署/最佳化同學保持緊密溝通,具體問題具體分析(適當瞭解一下計算相關理論的話,可以更高效的溝通)。

網路設計建議:

對於低算力平臺(CPU、低端 GPU 等),模型很容易受限於硬體計算能力,因此可以採用計算量低的網路來降低推理時間。

對於高算力平臺(GPU、DSP 等),一味降低計算量來降低推理時間就並不可取了,往往更需要關注訪存量。單純降低計算量,很容易導致網路落到硬體的訪存密集區,導致推理時間與計算量不成線性關係,反而跟訪存量呈強相關(而這類硬體往往記憶體弱於計算)。相對於低計算密度網路而言,高計算密度網路有可能因為硬體效率更高,耗時不變乃至於更短。

面向推理效能設計網路結構時,儘量採用經典結構,大部分框架會對這類結構進行圖最佳化,能夠有效減少計算量與訪存量。例如 Conv->BN->ReLU 就會融合成一個運算元,但 Conv->ReLU->BN 就無法直接融合 BN 層

運算元的引數儘量使用常用配置,如 Conv 儘量使用 3x3_s1/s2、1x1_s1/s2 等,軟體會對這些特殊引數做特殊最佳化。

CNN 網路 channel 數儘量選擇 4/8/16/32 的冪次,很多框架的很多運算元實現在這樣的 channel 數下效果更好(具體用多少不同平臺不同框架不太一樣)。

框架除了計算耗時外,也處理網路拓撲、記憶體池、執行緒池等開銷,這些開銷跟網路層數成正比。因此相比於“大而淺”的網路,“小而深”的網路這部分開銷更大。一般情況下這部分開銷佔比不大。但在網路運算元非常碎、層數非常多的時候,這部分開銷有可能會影響多執行緒的擴充套件性,乃至於成為不可忽視的耗時因素。

一些其他建議:

除了最佳化網路結構、推理框架效能外,還可以考慮透過一些其他工程技巧來提升系統整體的效能。例如:對推理服務流水化,並行資料讀取與計算的過程,掩蓋 IO 延時。

本文介紹了評估模型大小的四個常用指標——計算量、引數量、訪存量、記憶體佔用,從 RoofLine 模型入手詳細討論了影響模型推理速度的影響因素,並給出了面向推理速度的模型設計方法論與建議。

撰寫本文的目的,不僅僅是給演算法同學提供有效的網路設計建議,更多的還是希望能夠傳達效能最佳化的基礎知識與分析思路,減少演算法設計到部署之間的 gap,更快速高效的設計推理友好的網路模型。希望能對大家的工作有所幫助。

由於本人知識水平有限,如有錯誤和不詳盡的地方,望大家不吝指出,非常歡迎大家在評論區留言探討。

追更:

看到評論區有人問有沒有訪存量小的模型結構。一些研究工作,例如 ShuffleNetV2, 已經在設計網路的時候兼顧訪存量了。但據我所知目前還沒有像 DepthWise Conv 一樣經典的節省訪存量的模型結構。

關於這個問題,我個人是這麼看的:

1。 訪存量可以減小,但網路精度很難保證不變,因此需要一系列的研究來探索

2。 一些白給訪存量的技巧可以用上,一些白白浪費訪存量的操作不要搞

3。 低精度/量化有的時候節省訪存量的意義遠大於節省計算量

回顧 Xception/ MobileNet 的研究就可以看出,DWConv 3X3 + Conv 1X1 的結構之所以成為經典結構,一方面是計算量確實減少了,另一方面也是其精度確實沒有太大的損失。計算量可以在設計完網路時就可以算出,但網路精度只有在網路訓練完之後才能評估,需要花費大量的時間與精力反覆探索才能找到這一結構。

一些研究確實開始關注訪存量對推理速度的影響,例如 ShuffleNetV2 在選定 group 的時候就是以訪存量為依據的,但並不是整體的 block 都是圍繞降低訪存量來設計的。由於本人很久沒有關注演算法的研究進展了,據我所知目前是沒有專注於減少放存量的模型結構及研究工作的(如果有的話歡迎在評論區留言)。

我個人認為這可以成為一個很好的研究主題,可以為模型部署帶來很大的幫助。一種方法是可以透過手工設計網路結構,另一種方法是可以將訪存量作為 NAS 的一個引數進行搜尋。前者可解釋性更強一些,後者可能研究起來更容易。但是有一點請務必注意:降低訪存量的最終目的一定是為了減少模型的推理時間。如果模型處在目標裝置的計算密集區,降低訪存量的意義有限。

關於實際工程部署,有一些技巧/注意的點可以保證不浪費訪存量:

1。 channel 數儘量保持在 4/8/16/32 的倍數,不要設計 channel = 23 這種結構。目前大部分推理框架為了加速計算,都會用特殊的資料排布,channel 會向上 pad。比如框架會把 channel pad 到 4 的倍數,那麼 channel = 23 和 24 在訪存量上其實是一致的。

2。 一些非常細碎乃至毫無意義的後處理運算元,例如 Gather、Squeeze、Unsqueeze 等,最好給融合掉。這種現象往往見於 PyTorch 匯出 onnx 的時候,可以嘗試使用 onnxsim 等工具來進行融合,或者手動新增大運算元。

3。 嘗試一些部署無感的技巧,例如蒸餾、RepVGG(感謝

@OLDPAN

)等。

最後想聊一下低精度/量化。對於裝置算力很強但模型很小的情況,低精度/量化我個人認為其降低訪存量的作用要遠大於節省計算量,可以有效加快模型推理速度。但是要注意兩點:一個是框架如果不支援 requant,而是每次計算前都量化一次,計算完之後再反量化,那麼使用低精度/量化反而會增加訪存量,可能造成推理效能的下降;另一個是對於支援混合精度推理的框架,要注意不同精度轉換時是否會有額外的效能開銷。如果有的話,要儘量減少精度的轉換。

END

為方便大家學習交流,我們建了微信交流群,歡迎加我的微信邀請你進群。

微商無關人員,請繞道謝謝合作!

你的每一個“在看”,我都當成了喜歡