天天看點

深度學習模型部署簡要介紹

一、模型部署簡介

近幾年來,随着算力的不斷提升和資料的不斷增長,深度學習算法有了長足的發展。深度學習算法也越來越多的應用在各個領域中,比如圖像處理在安防領域和自動駕駛領域的應用,再比如語音處理和自然語言處理,以及各種各樣的推薦算法。如何讓深度學習算法在不同的平台上跑的更快,這是深度學習模型部署所要研究的問題。

目前主流的深度學習部署平台包含GPU、CPU、ARM。模型部署架構則有英偉達推出的TensorRT,谷歌的Tensorflow和用于ARM平台的tflite,開源的caffe,百度的飛漿,騰訊的NCNN。其中基于GPU和CUDA的TensorRT在伺服器,高性能計算,自動駕駛等領域有廣泛的應用。

深度學習模型部署簡要介紹
深度學習模型部署簡要介紹

二、使用TensorRT進行推理

1、建構TensorRT Engine​

使用TensorRT進行推理,共分為兩個階段。

  • 第一個階段主要是建構TensorRT引擎。目前的主流方式是從onnx轉換為TensorRT的引擎。而從各種訓練架構都有非常豐富的工具,可以将訓練後的模型轉換到onnx。
深度學習模型部署簡要介紹
深度學習模型部署簡要介紹

2、運作TensorRT引擎

  • 第二階段主要是運作TensorRT的引擎。ICudaEngine接口持有優化後的引擎,如果要進行推理,還要從ICudaEngine建立IExecutionContext,進而使用IExecutionContext::execute或者IExecutionContext::enqueue函數進行推理。

3、使用混合精度

TensorRT預設使用float32來進行推理,同時也支援fp16和int8的推理。使用fp16進行推理,可以得到幾乎和float32相同精度的結果,但是計算量會比float32少的多,和float32推理的差別僅僅在于多設定一個flag。而使用int8進行推理,則需要首先對模型進行量化,得到每一層的動态範圍,以便于在運作時進行設定。

深度學習模型部署簡要介紹

4、動态尺寸

TensorRT還支援動态尺寸。動态尺寸是指在建構引擎時不指定全部的輸入尺寸,而是以-1作為占位符,等到運作時再設定具體的尺寸。這種情況下一般需要在建構時,添加優化配置檔案。

深度學習模型部署簡要介紹

三、TensorRT的優化

1、性能度量工具​

在優化代碼之前,首先必須要對代碼進行度量。最簡單直接的度量方法是使用c++标準庫的chrono中的API來測量兩個時間點的內插補點。但是TensorRT代碼多數為并行代碼,是以在CUDA中引入了CUDA Event的概念,可以更友善地對并行代碼進行計時。另外還有一些官方的工具,比如trtexec和nvprof,都可以對TensorRT進行剖析。

深度學習模型部署簡要介紹

2、TensorRT優化方法

主要優化方法包含使用batch和stream。batch是指将多個尺寸相同資料組合在一起,送入網絡中進行推理。這樣比每次隻處理一個資料要快的多。使用stream則可以增加更多的并行性。stream也可以和線程一起使用。

深度學習模型部署簡要介紹

四、TensorRT自定義層

TensorRT并不支援所有的深度學習算子。有些算子,還需要我們自己去實作。TensorRT提供了layer plugin接口,我們隻需要繼承該接口,并實作其中相應的函數即可。

一般建議自定義層的第一步是首先使用CUDA實作自定義層的主要功能,然後再将其和layer plugin的接口進行組合。

五、CUDA程式設計

為了進一步加速深度學習運作時間,我們一般也會将深度學習模型的前處理和後處理放在GPU上來做。是以我們還需要更深入的學習如何用CUDA C進行程式設計。

為了友善編寫在GPU上運作的代碼,英偉達推出了CUDA程式設計模型,擴充了原始C++。CUDA程式設計模型主要有兩個部分,一個是如何組織線程層次結構,更好地利用GPU的并行性,一個是如何通路裝置記憶體。

1、線程層次結構

CUDA C++對C++進行了擴充,允許程式員定義C++函數,稱為CUDA kernel。kernel是用__global__聲明指定的,在給定的核心調用中,執行該核心的CUDA線程數量是用新的<<...>>執行配置文法指定的。多個線程組成線程塊,而多個線程塊進一步組成線程網格。一個塊内的線程可以通過一些共享記憶體來共享資料,并通過同步它們的執行來協調記憶體通路。

深度學習模型部署簡要介紹

2、記憶體層次結構

裝置記憶體可以分為全局記憶體,共享記憶體,常量記憶體和紋理記憶體。每個線程都有私有的本地記憶體。每個線程塊都有共享記憶體,對該塊的所有線程都是可見的,并且與該塊具有相同的生命周期。所有線程都可以通路相同的全局記憶體。

全局、常量和紋理記憶體空間針對不同的記憶體使用情況進行了優化。紋理記憶體還為一些特定的資料格式提供了不同的尋址模式,以及資料過濾

深度學習模型部署簡要介紹

3、CUDA程式設計優化

1)記憶體優化

一般來說GPU上的計算比CPU快的多,但是将原本CPU代碼移植到GPU之後,不僅僅要對比代碼的執行速度,還要考慮記憶體傳輸的問題。畢竟在GPU運算之前,需要将主機記憶體中的資料傳輸到裝置記憶體,這通常是比較耗時的。

優化傳輸速度的一種方法是使用頁面鎖定記憶體。鎖頁記憶體由cudaMallocHost申請,由cudaFreeHost釋放,它既可以被CPU代碼通路,也可以被GPU代碼通路。

另外一種方法是重疊資料傳輸和kernel執行。cudaMemcpyAsync可以進行異步資料傳輸,而在調用kernel時可以使用指定的CUDA stream進行調用。如下圖所示,實作同一功能的代碼執行順序不一樣時可能産生完全不同的并行效果。

深度學習模型部署簡要介紹

2)執行配置優化

繼續閱讀