ONNX 介紹及TensorRT部署

ONNX簡介

Open Neural Network Exchange(ONNX,開放神經網絡交換)格式,是一個用於表示深度學習模型的標準,可以使模型在不一樣框架之間進行轉移。html

 

python

ONNX是一種針對機器學習所設計的開放式的文件格式,用於存儲訓練好的模型。它使得不一樣的人工智能框架(如Pytorch, MXNet)能夠採用相同格式存儲模型數據並交互。 ONNX的規範及代碼主要由微軟,亞馬遜 ,Facebook 和 IBM 等公司共同開發,以開放源代碼的方式託管在Github上。目前官方支持加載ONNX模型並進行推理的深度學習框架有: Caffe2, PyTorch, MXNet,ML.NET,TensorRT 和 Microsoft CNTK,而且 TensorFlow 也非官方的支持ONNX。---維基百科linux



咱們可能會在某一任務中將Pytorch或者TensorFlow模型轉化爲ONNX模型(ONNX模型通常用於中間部署階段),而後再拿轉化後的ONNX模型進而轉化爲咱們使用不一樣框架部署須要的類型。

算法

典型的幾個線路:性能優化

Pytorch -> ONNX -> TensorRT網絡

Pytorch -> ONNX -> TVM數據結構

TF – onnx – ncnn框架

等等,ONNX至關於一個翻譯的做用,這也是爲何ONNX叫作Open Neural Network Exchange。機器學習

 

Pytorch模型定義和模型權重暫時不支持打包在一塊兒,這在推理時候須要先用模型定義代碼構建模型,再加載模型權重,比較麻煩。藉助於onnx格式轉換能夠把模型打包一塊兒,在ONNX Runtime中運行推理,ONNX Runtime 是針對 ONNX 模型的以性能爲中心的引擎,可大大提高模型的性能。另外,onnx模型支持在不一樣框架之間轉換,也支持tensorRT加速分佈式

 

舉例

 

假如咱們利用Pytorch訓練好一個模型,而後咱們將其保存爲.pt文件:

好比就叫作model.pt,這個咱們應該很熟悉吧,二進制的模型權重文件,咱們能夠讀取這個文件,至關於預加載了權重信息。

ONNX呢,利用Pytorch咱們能夠將model.pt轉化爲model.onnx格式的權重,在這裏onnx充當一個後綴名稱,model.onnx就表明ONNX格式的權重文件,這個權重文件不只包含了權重值,也包含了神經網絡的網絡流動信息以及每一層網絡的輸入輸出信息和一些其餘的輔助信息。

簡單拿netron這個工具來可視化(讀取ONNX文件)一下:

 

 


 

如圖,ONNX中的一些信息都被可視化展現了出來,例如文件格式ONNX v3,該文件的導出方pytorch 0.4等等,這些信息都保存在ONNX格式的文件中。


 

假設一個場景:如今某組織由於主要開發用TensorFlow爲基礎的框架,如今有一個深度算法,須要將其部署在移動設備上,以觀測變現。傳統地咱們須要用caffe2從新將模型寫好,而後再訓練參數;試想下這將是一個多麼耗時耗力的過程。

此時,ONNX便應運而生,Caffe2,PyTorch,Microsoft Cognitive Toolkit,Apache MXNet等主流框架都對ONNX有着不一樣程度的支持。這就便於了咱們的算法及模型在不一樣的框架之間的遷移。


 

ONNX

開放式神經網絡交換(ONNX)是邁向開放式生態系統的第一步,它使AI開發人員可以隨着項目的發展選擇合適的工具。 ONNX爲AI模型提供開源格式。 它定義了可擴展的計算圖模型,以及內置運算符和標準數據類型的定義。 最初的ONNX專一於推理(評估)所需的功能。 ONNX解釋計算圖的可移植,它使用graph的序列化格式。 它不必定是框架選擇在內部使用和操做計算的形式。 例如,若是在優化過程當中操做更有效,則實現能夠在存儲器中以不一樣方式表示模型。

ONNX是一個開放式規範,由如下組件組成:

可擴展計算圖模型的定義
標準數據類型的定義
內置運算符的定義


 

Protobuf

ONNX既然是一個文件格式,那麼咱們就須要一些規則去讀取它,或者寫入它,ONNX採用的是protobuf這個序列化數據結構協議去存儲神經網絡權重信息。

Protobuf是個什麼東西,若是你們使用過caffe或者caffe2,那麼想必可能對Protobuf比較熟悉,由於caffe的模型採用的存儲數據結構協議也是Protobuf。

這裏簡單介紹一些protobuf吧,Protobuf是一種平臺無關、語言無關、可擴展且輕便高效的序列化數據結構的協議,能夠用於網絡通訊和數據存儲。咱們能夠經過protobuf本身設計一種數據結構的協議,而後使用各類語言去讀取或者寫入,一般咱們採用的語言就是C++。

關於這個有一篇文章比較好地對此進行了介紹:https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/index.html這裏就不進行詳細的介紹了。

 

爲何要用onnx

如今你們都喜歡用pytorch訓練模型,而pytorch訓練的模型轉成pth,用C++推理也很難達到真正的加速效果,由於本質上最耗時的網絡前向推理部分並無太多的加速。而且採用libtorch C++推理pytorch並非一件簡單的事情,除非你的模型能夠被trace。

在這種狀況之下,引入onnx更合理,從目前整個DL生態來看,onnx具備如下好處:

  • 它的模型格式比基於layer的老一代框架更加細粒度;

  • 它擁有統一化的定義,而且基於任何框架均可以推理他;

  • 它能夠實現不一樣框架之間的互相轉化。

咱們今天要作的事情,就是在上面的onnx模型的基礎上,採用TensorRT來進行推理。先作一個簡單的速度對比:

框架

語言

耗時(s)

fps

Pytorch

python

0.012+0.022

29

ONNXRuntime

python

0.008+0.022

34

TensorRT

C++

0.004+0.001

250



 

真正落地的算法部署,毫無疑問,假如你的targetGPU,採用ONNX+TensorRT應該是目前最成熟、最優化的方案。假如你的target是一些嵌入式芯片,那麼採用MNN也是能夠經過onnx輕鬆實現CPU嵌入式端快速推理的。

既然ONNX和TensorRT這麼好,爲何都不用呢?爲何都還在用Python寫難看的推理的代碼呢?緣由也很簡單:

  • 入門太難,C++通常人玩不來;

  • 既要懂模型的每一層輸入輸出,又要懂TensorRT的API,至少要很熟悉。

 

TensorRT

通常的深度學習項目,訓練時爲了加快速度,會使用多GPU分佈式訓練。但在部署推理時,爲了下降成本,每每使用單個GPU機器甚至嵌入式平臺(好比 NVIDIA Jetson)進行部署,部署端也要有與訓練時相同的深度學習環境,如caffe,TensorFlow等。因爲訓練的網絡模型可能會很大(好比,inception,resnet等),參數不少,並且部署端的機器性能存在差別,就會致使推理速度慢,延遲高。這對於那些高實時性的應用場合是致命的,好比自動駕駛要求實時目標檢測,目標追蹤等。因此爲了提升部署推理的速度,出現了不少輕量級神經網絡,好比squeezenet,mobilenet,shufflenet等。基本作法都是基於現有的經典模型提出一種新的模型結構,而後用這些改造過的模型從新訓練,再從新部署。

TensorRT是一個高性能的深度學習推理(Inference)優化器,能夠爲深度學習應用提供低延遲、高吞吐率的部署推理。TensorRT可用於對超大規模數據中心、嵌入式平臺或自動駕駛平臺進行推理加速。TensorRT現已能支持TensorFlow、Caffe、Mxnet、Pytorch等幾乎全部的深度學習框架,將TensorRT和NVIDIA的GPU結合起來,能在幾乎全部的框架中進行快速和高效的部署推理。

TensorRT 是一個C++庫,從 TensorRT 3 開始提供C++ API和Python API,主要用來針對 NVIDIA GPU進行 高性能推理(Inference)加速。如今最新版TensorRT是4.0版本。

TensorRT 以前稱爲GIE。

深度學習

  • 訓練
  • 部署

 

訓練(training)和 推理(inference)的區別:

  • 訓練(training)包含了前向傳播和後向傳播兩個階段,針對的是訓練集。訓練時經過偏差反向傳播來不斷修改網絡權值(weights)。
  • 推理(inference)只包含前向傳播一個階段,針對的是除了訓練集以外的新數據。能夠是測試集,但不徹底是,更多的是整個數據集以外的數據。其實就是針對新數據進行預測,預測時,速度是一個很重要的因素。

日常自學深度學習的時候關注的更可能是訓練的部分,即獲得一個模型.而實際工做很大一塊的工做內容集中於如何將模型部署到具體的芯片上.你本身寫的模型效果是很難優於成熟的知名的模型的.
以無人駕駛爲例,拍攝到圖片後,芯片上的加載的模型要可以識別出圖片裏是什麼.對自動駕駛這種場景而言,對實時性地要求是很是高的.試想,從圖片輸入到模型,到模型識別出圖片中前方有我的花了1分鐘,你正以100km/h行駛,後果天然是災難性的.
這就引出了推理引擎.model裏的信息其實就是一些權重矩陣信息而已.輸入圖片數據後,進行一大堆的矩陣運算,獲得最終圖片的分類.推理引擎乾的事情就是優化矩陣運算,縮短運算時間.

 

而tensorRT 則是對訓練好的模型進行優化。 tensorRT就只是推理優化器。當你的網絡訓練完以後,能夠將訓練模型文件直接丟進tensorRT中,而再也不須要依賴深度學習框架(Caffe,TensorFlow等),以下:

能夠認爲tensorRT是一個只有前向傳播的深度學習框架,這個框架能夠將 Caffe,TensorFlow的網絡模型解析,而後與tensorRT中對應的層進行一一映射,把其餘框架的模型統一所有 轉換到tensorRT中,而後在tensorRT中能夠針對NVIDIA自家GPU實施優化策略,並進行部署加速。

TensorRT的核心就是一個深度學習的高性能C++的推理庫, 基本適配主流的訓練框架,如Tensorflow, Caffe, Pytorch, MXNet。

若是想了解更多關於tensorrt的介紹,可參考官網介紹

詳細介紹參見這裏

 

安裝流程:

1.系統環境:cuda10.2 + cudnn7.6.5 ,Nvidia驅動安裝版本爲440.33,具體參見這裏

2.須要的cuDNN的版本,須要時自行下載

3.TensorRT安裝及配置步驟:

tar -zxvf TensorRT-7.0.0.11.Ubuntu-16.04.x86_64-gnu.cuda-10.2.cudnn7.6.tar.gz 
 
#解壓獲得TensorRT-7.0.0.11的文件夾,將裏邊的lib絕對路徑添加到環境變量中
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/gavin/mysoft/TensorRT-7.0.0.11/lib
 
#安裝TensorRT
cd TensorRT-7.0.0.11/python
#if python2
sudo pip2 install tensorrt-5.1.5.0-py2.py3-none-any.whl
#if python3
sudo pip3 install tensorrt-7.0.0.11-cp35-none-linux_x86_64.whl
 
#安裝UFF
cd TensorRT-7.0.0.11/uff
#if python2
sudo pip2 install uff-0.6.5-py2.py3-none-any.whl
#if python3
sudo pip3 install uff-0.6.5-py2.py3-none-any.whl
 
#安裝graphsurgeon
cd TensorRT-7.0.0.11/graphsurgeon
#if python2
sudo pip2 install graphsurgeon-0.4.1-py2.py3-none-any.whl
#if python3
sudo pip3 install graphsurgeon-0.4.1-py2.py3-none-any.whl

我的配置部分截圖

 

測試:

python
import tensorflow
import tensorrt
import uff

不報錯就對了。

 

下載相應版本的cuDNN

cuda卸載:

到CUDA9.0的目錄下,找到卸載的文件

/usr/local/cuda-9.0/bin

sudo /usr/local/cuda-9.0/bin/uninstall_cuda_9.0.pl

這個過程須要一分鐘左右,

sudo rm -rf /usr/local/cuda-9.0/

 

卸載cuDNN

打開終端,輸入

sudo rm -rf /usr/local/cuda/lib64/libcudnn

sudo rm -rf /usr/local/cuda/include/cudnn.h

 

 

關係

  • onnx能夠認爲是一個文件協議(表示機器學習模型的開放標準), 許多框架(包括 TensorFlow、PyTorch、SciKit-Learn、Keras、Chainer、MXNet 和 MATLAB)中的模型均可以導出或轉換爲標準 ONNX 格式。 模型採用 ONNX 格式後,可在各類平臺和設備上運行。能夠支持不一樣平臺的CPU,GPU推理
  • tensortRT 是一個推理優化器,是一個C++庫

目前pytorch比較成熟的方式:①trace 模型,而後 libtorch 前向 ② pytorch模型轉到onnx模型,而後使用tensorrt部署;第二種部署方式更加有效率

 

TensorRT 爲何能讓模型加速跑?

模型加速愈來愈成爲深度學習工程中的剛需了,最近的CVPR和ICLR會議中,模型的壓縮和剪枝是受到的關注愈來愈多。畢竟工程上,算法工程師的深度學習模型是要在嵌入式平臺跑起來,投入應用的。在模型的推理(inference)過程當中,計算速度是很重要的。好比自動駕駛,若是使用一個經典的深度學習模型,很容易就跑到200毫秒的延時,那麼這意味着,在實際駕駛過程當中,你的車一秒鐘只能看到5張圖像,這固然是很危險的一件事。因此,對於實時響應比較高的任務,模型的加速時頗有必要的一件事情了。

若是你使用英偉達的產品,好比PX2,那麼在平臺上部署模型投入應用,不少時候就須要用到專門的模型加速工具 —— TensorRT。

TensorRT下的模型是在作什麼?

TensorRT只負責模型的推理(inference)過程,通常不用TensorRT來訓練模型的哈。

TensorRT能加速模型嗎?

能!根據官方文檔,使用TensorRT,在CPU或者GPU模式下其可提供10X乃至100X的加速。本人的實際經驗中,TensorRT提供了20X的加速。

TensorRT爲何能提高模型的運行速度?

TensorRT是英偉達針對自家平臺作的加速包,TensorRT主要作了這麼兩件事情,來提高模型的運行速度。

  1. TensorRT支持INT8和FP16的計算。深度學習網絡在訓練時,一般使用 32 位或 16 位數據。TensorRT則在網絡的推理時選用不了這麼高的精度,達到加速推斷的目的。
  2. TensorRT對於網絡結構進行了重構,把一些可以合併的運算合併在了一塊兒,針對GPU的特性作了優化。如今大多數深度學習框架是沒有針對GPU作過性能優化的,而英偉達,GPU的生產者和搬運工,天然就推出了針對本身GPU的加速工具TensorRT。一個深度學習模型,在沒有優化的狀況下,好比一個卷積層、一個偏置層和一個reload層,這三層是須要調用三次cuDNN對應的API,但實際上這三層的實現徹底是能夠合併到一塊兒的,TensorRT會對一些能夠合併網絡進行合併。咱們經過一個典型的inception block來看一看這樣的合併運算。

 

參考文獻:

1.TensorRT安裝及使用

2.tensorRT 7.0安裝配置

相關文章
相關標籤/搜索