第十二章 TensorRT 使用

第十二章簡介

本章介紹模型部署的實用工具——TensorRT

TensorRTNvidia公司針對N卡推出的高性能深度學習推理框架,TRT採用c++編寫底層庫,並提供c++/python應用介面,實現了高吞吐、低時延的優點。TRT 應用量化、圖優化、層融合等優化技術,同時利用高度優化的內核找到該模型的最快實現。

TRT涉及的內容非常多,本章將從基礎概念與安裝開始介紹,然後通過一個Resnet的推理來瞭解TRT的工作流程,接著介紹TRT實用工具集trtexecNight system, polygraph,接著介紹基於API的模型搭建方法,最後介紹基於TRT的量化方法及理論原理,還包括PTQQAT的實現,最後通過YOLOv5TRT推理部署來熟悉工程化時,python代碼的編寫。

 

12.1 TensorRT 簡介與安裝

前言

本節將介紹TensorRT的基礎概念,以及在windowslinux下進行安裝及驗證的方法,為後續正式學習TensorRT做好理論和環境的基礎。

TRT簡介

TRTNvidia公司針對N卡推出的高性能深度學習推理框架,TRT採用c++編寫底層庫,並提供c++/python應用介面,實現了高吞吐、低時延的優點。TRT 應用量化、圖優化、層融合等優化技術,同時利用高度優化的內核找到該模型的最快實現。

TRT是官方推理引擎,優化效果自然靠譜,因此使用TRT進行工程化部署已經成為主流方案。

下面介紹TRT工作原理,它與pytorch這樣的訓練框架之間存在什麼差異?為什麼它是彌補pytorch走上高性能工程化必不可少的工具?下面通過一幅圖來說明。

<<AI人工智慧 PyTorch自學>> 第十二章 Tens

TRT主要包含優化器和運行時庫兩部分:

  • optimizer進行模型表示的優化,例如,層融合、圖優化、量化、kernel選擇等操作,目的是為了找到模型在GPU上,運行時最優的表示形式以及方案(kernel選擇),這裡的kernel是具體某個運算元的實現方法,例如卷積的實現就有很多,可以根據實現方式、演算法、資料佈局等進行挑選,優化器會根據網路結構、硬體設定和精度需求等因素,選擇最適合當前場景的 kernel 進行推理計算,以獲得最佳的性能。optimizer是在生產前做準備工作,獲得最優方案,供runtime使用。
  • runtime是運行時庫,可以實現推理引擎創建、推理計算、引擎銷毀等內容,是生產服務中使用的。到這裡,就知道TRT會根據GPU特性、任務特性、用戶自訂操作等,將pytorch模型轉換為TRT 運行時庫能讀取的形式,簡單粗暴理解就是pytorch模型轉為TRT模型。

TRT模型檔(.plan或者.engine)是高度優化的模型表示形式,在真正使用時被Runtime所載入並使用,可以實現高性能推理。

由此可知,TRT可以高性能推理的重要環節是採用優化器優化,那麼優化通常有哪些操作呢?

<<AI人工智慧 PyTorch自學>> 第十二章 Tens

可以通過上圖看到會包括6個主要部分:

  1. Weight & Activation Precision Calibration:權重和啟動精度校準,目的是通過量化模型(float16, int8等)實現高輸送量,以及低存儲。
  2. Layer & Tensor Fusion:層和張量融合,這一步是優化 GPU 記憶體和頻寬的使用,通過將多個節點融合成一個節點,從而減少計算和通信的開銷。例如,卷積、BNReLU融合為一個操作運算元,可以減少資料在 GPU 記憶體中的複製次數,從而提高推理性能。
  3. Kernel Auto-Tuning,內核自動調優,的是根據目標 GPU 平臺的特性和硬體設定,選擇最佳的計算內核和資料佈局方式,以獲得最佳的性能和精度。TensorRT 會根據模型的結構和運行時環境,自動選擇最佳的計算內核和資料佈局方式,從而最大化推理性能。 從這裡表明,優化時的GPU型號要與生產時的GPU型號保持一致,尤其採用.engine來存儲TRT模型時,不同設備之間不能使用。
  4. Dynamic Tensor Memory,動態張量記憶體,可以最小化模型的記憶體佔用,通過動態地分配和釋放張量記憶體,以最大程度地利用有限的 GPU 記憶體資源。
  5. Multi-Stream Execution,多流執行是通過並存執行多個輸入流,提高模型的推理性能。TensorRT 可以將多個輸入流分配到不同的 CUDA 流中,並存執行多個輸入流,從而提高模型的併發性和輸送量。 CUDA流可以理解為
  6. Time Fusion(時間融合) 這一步的主要目的是通過動態生成內核,優化迴圈神經網路(RNN)等模型在多個時間步驟中的計算過程。通過將多個時間步驟的計算合併成一個內核,可以減少資料在 GPU 記憶體中的複製次數,從而提高推理性能。 使用場景:需要優化迴圈神經網路等模型在多個時間步驟中的計算過程,適用於序列模型等有時間序列特徵的深度學習模型。

PSCUDA流的理解

CUDA流是CUDA程式設計中用於平行計算的一種抽象概念,是一組在GPU上並存執行的操作序列。CUDA流用於管理和調度GPU上的計算資源。每個CUDA流都有自己的計算資源,包括寄存器、共用記憶體、全域記憶體等,這些資源是獨立的,不同流之間不會相互干擾。在執行CUDA程式時,GPU上的計算資源被分割成了若干個流,每個流可以獨立地執行一組操作序列。CUDA流可以看作是一條命令流水線,其中的每個操作都是在GPU上並存執行的。

可以將CUDA流看作是一個GPU上的工廠生產線,流中的每個操作就像是生產線上的一個工人,每個工人都有自己的工作任務,按照一定的順序進行工作。這樣,GPU上的計算資源就可以同時處理多個任務,從而實現平行計算。

為什麼叫流(stream),是可以將其理解為資料的流動。在CUDA程式設計中,資料可以從CPUGPU,也可以從GPUGPU,甚至可以在GPU內部進行資料流程動。通過合理地利用CUDA流,可以將資料的流動和計算的流程進行有效地整合和優化,以獲得更高的性能和效率。

Windows安裝

接下來進行TRT的安裝,將分windowslinux下,所有安裝步驟參照官方文檔進行:https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html

建議採用docker鏡像安裝使用,可避免很多不必要的坑,若不採用docker的話,建議嚴格按照官方文檔步驟進行。

額外需要注意的是cudacudnn版本要與TRT版本匹配,同時主要環境變數的設置,中間可能會存在各種報錯,請自行網上搜索解決方案。

TensorRT可以通過多種方法安裝,例如Debian or RPM packages, a Python wheel file, a tar file, or a zip file.

在這裡先介紹Windows的安裝,採用zip檔的形式。

第一步:在官網下載zip文件,TensorRT-8.6.0.12.Windows10.x86_64.cuda-11.8.zip

第二步:把zip解壓到CUDA同級目錄(位置無所謂,建議與CUDA放在一起,例如C:\Program Files\NVIDIA GPU Computing Toolkit\TensorRT-8.6.0.12),將TensorRT-8.6.0.12\lib下檔複製到CUDA安裝目錄/bin下麵(C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.3\bin

第三步:安裝python whl,在TensorRT-8.6.0.12\python下找到對應版本的whl,主要是看python版本。然後安裝以下三個庫

python.exe -m pip install tensorrt-*-cp3x-none-win_amd64.whl

python.exe -m pip install tensorrt_lean-*-cp3x-none-win_amd64.whl

python.exe -m pip install tensorrt_dispatch-*-cp3x-none-win_amd64.whl

Copy

第四步:pytorchTensorFlow需要額外安裝3python

python3 -m pip install graphsurgeon\graphsurgeon-0.4.6-py2.py3-none-any.whl

python3 -m pip install uff\uff-0.6.9-py2.py3-none-any.whl

python3 -m pip install onnx_graphsurgeon\onnx_graphsurgeon-0.3.12-py2.py3-none-any.whl

Copy

第五步:建議安裝 cuda-python & pycuda

根據官方安裝文檔指引:https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html

如果需要使用python-api,則需要安裝cuda-python,安裝方法:https://nvidia.github.io/cuda-python/install.html

pip install pycuda

pip install cuda-python

Copy

安裝pycuda可能會遇到:提示缺少 c++構建工具

error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/

Copy

參考微軟的回答:https://learn.microsoft.com/en-us/answers/questions/136595/error-microsoft-visual-c-14-0-or-greater-is-requir

下載一個vs_BuildTools.exe,然後安裝生成工具即可。

Windows TRT驗證

trtexec 運行模型

trtexectensorrt自帶的命令列工具,可以進行TRT模型生成,以及推理耗時評估。

windows下,首先需要將trtexec.exe所在資料夾添加到系統環境變數,這樣在cmd中,trtexec指令才會被識別到。

接著打開cmd,運行以下命令,將onnx檔轉換為tensorrtengine檔,並且自動進行推理耗時評估。

其中,onnx檔可從chatper-11資料夾下獲取。

trtexec --onnx=resnet50_bs_1.onnx --saveEngine=resnet50_bs_1.engine

Copy

經過30s左右詳細日誌輸出,最底部有推理性能日誌:

[06/13/2023-14:56:23] [I] === Performance summary ===

[06/13/2023-14:56:23] [I] Throughput: 503.749 qps

[06/13/2023-14:56:23] [I] Latency: min = 1.89886 ms, max = 2.85559 ms, mean = 1.92952 ms, median = 1.92126 ms, percentile(90%) = 1.93677 ms, percentile(95%) = 1.95227 ms, percentile(99%) = 2.20648 ms

[06/13/2023-14:56:23] [I] Enqueue Time: min = 0.288818 ms, max = 1.23926 ms, mean = 0.570478 ms, median = 0.669189 ms, percentile(90%) = 0.782898 ms, percentile(95%) = 0.83667 ms, percentile(99%) = 1.03223 ms

[06/13/2023-14:56:23] [I] H2D Latency: min = 0.0751953 ms, max = 0.138062 ms, mean = 0.0788889 ms, median = 0.0770264 ms, percentile(90%) = 0.0814819 ms, percentile(95%) = 0.0932617 ms, percentile(99%) = 0.111938 ms

[06/13/2023-14:56:23] [I] GPU Compute Time: min = 1.81738 ms, max = 2.7533 ms, mean = 1.8471 ms, median = 1.84009 ms, percentile(90%) = 1.85034 ms, percentile(95%) = 1.8606 ms, percentile(99%) = 2.11353 ms

[06/13/2023-14:56:23] [I] D2H Latency: min = 0.00317383 ms, max = 0.0183716 ms, mean = 0.0035316 ms, median = 0.00341797 ms, percentile(90%) = 0.00390625 ms, percentile(95%) = 0.00390625 ms, percentile(99%) = 0.00415039 ms

[06/13/2023-14:56:23] [I] Total Host Walltime: 3.00348 s

[06/13/2023-14:56:23] [I] Total GPU Compute Time: 2.79466 s

[06/13/2023-14:56:23] [W] * GPU compute time is unstable, with coefficient of variance = 3.29947%.

[06/13/2023-14:56:23] [W]   If not already in use, locking GPU clock frequency or adding --useSpinWait may improve the stability.

[06/13/2023-14:56:23] [I] Explanations of the performance metrics are printed in the verbose logs.

[06/13/2023-14:56:23] [I]

&&&& PASSED TensorRT.trtexec [TensorRT v8600] # trtexec --onnx=resnet50_bs_1.onnx --saveEngine=resnet50_bs_1.engine

Copy

可看到,基於TRT引擎的resnet50batchsize=1的模型,在推理效率上,輸送量為503,平均時延為1.92ms

可以對比onnxruntime的輸送量,提高了86%的吞吐(11.2小節做了評估,bs=1時,輸送量為270),時延減少了48%3.7 --> 1.92 ms

為了進一步對比,還可以執行batchsize=128時的resnet50,觀察輸送量與時延情況,具體如下表所示:

trtexec --onnx=resnet50_bs_128.onnx --saveEngine=resnet50_bs_128.engine

Copy

[06/13/2023-15:05:08] [I] === Performance summary ===

[06/13/2023-15:05:08] [I] Throughput: 9.05117 qps

[06/13/2023-15:05:08] [I] Latency: min = 109.778 ms, max = 111.595 ms, mean = 110.354 ms, median = 110.348 ms, percentile(90%) = 110.654 ms, percentile(95%) = 110.674 ms, percentile(99%) = 111.595 ms

[06/13/2023-15:05:08] [I] Enqueue Time: min = 0.542603 ms, max = 1.39661 ms, mean = 0.860929 ms, median = 0.815994 ms, percentile(90%) = 1.23169 ms, percentile(95%) = 1.28577 ms, percentile(99%) = 1.39661 ms

[06/13/2023-15:05:08] [I] H2D Latency: min = 9.49048 ms, max = 10.332 ms, mean = 9.63266 ms, median = 9.57568 ms, percentile(90%) = 9.7522 ms, percentile(95%) = 10.2017 ms, percentile(99%) = 10.332 ms

[06/13/2023-15:05:08] [I] GPU Compute Time: min = 100.16 ms, max = 101.197 ms, mean = 100.652 ms, median = 100.593 ms, percentile(90%) = 101.011 ms, percentile(95%) = 101.036 ms, percentile(99%) = 101.197 ms

[06/13/2023-15:05:08] [I] D2H Latency: min = 0.064209 ms, max = 0.114136 ms, mean = 0.0695243 ms, median = 0.0656738 ms, percentile(90%) = 0.083374 ms, percentile(95%) = 0.0861816 ms, percentile(99%) = 0.114136 ms

[06/13/2023-15:05:08] [I] Total Host Walltime: 3.204 s

[06/13/2023-15:05:08] [I] Total GPU Compute Time: 2.9189 s

[06/13/2023-15:05:08] [I] Explanations of the performance metrics are printed in the verbose logs.

[06/13/2023-15:05:08] [I]

&&&& PASSED TensorRT.trtexec [TensorRT v8600] # trtexec --onnx=resnet50_bs_128.onnx --saveEngine=resnet50_bs_128.engine

Copy

onnxTRT的輸送量、時延對比如下表所示,可以看到輸送量有30-80%的提升,時延有20-50%左右的降低。

 

輸送量

輸送量

時延

時延

 

onnxruntime

trt

onnxruntime

trt

bs = 1

270

503(↑86%

3.7

1.9(49%)

bs = 128

852

1158(↑36%

150.3

110(27%)

日誌資訊中有很多意義內容,包括:

  • Throughput:模型的推理輸送量,以每秒推理數量(QPS)為單位。
  • Latency:模型一次推理的延遲時間統計資訊,包括最小值、最大值、平均值、中位數和百分位數(90%95%99%)。
  • Enqueue Time:將資料傳輸到GPU的時間統計資訊,
  • H2D Latency:將主機資料傳輸到GPU的延遲時間統計資訊,
  • GPU Compute Time:模型在GPU上運行的計算時間統計資訊
  • D2H Latency:從GPU將資料傳輸回主機的延遲時間統計資訊
  • Total Host Walltime:模型推理的總時間,包括傳輸資料、計算和傳輸資料回主機的時間。
  • Total GPU Compute Time:模型在GPU上的總計算時間。

Bug記錄

安裝TRT時,切記關注自己的cuda版本,要找到適配你cuda版本的TRT版本!

由於剛更換電腦,cuda安裝了最新的v12.4 一開始想安裝TRT v8.6.1,發現報錯:

[03/27/2024-22:34:24] [I] Loading standard plugins

[03/27/2024-22:34:24] [E] Uncaught exception detected: Unable to open library: nvinfer_plugin.dll

&&&& FAILED TensorRT.trtexec [TensorRT v8601] # trtexec --onnx=resnet50_bs_1.onnx --saveEngine=resnet50_bs_1.engine --tacticSources=-CUDNN

Copy

根本原因是 cuda-v12.4需要更高的TRT版本,最終安裝的是TensorRT-10.0.0.6

Linux 安裝

linux的安裝有多種途徑,如果有docker環境,強烈建議使用docker拉取官方鏡像,直接可以使用。

如果不用docker,可以採用debubuntu)、tarlinux都可以)、rpmRedhat/Centos),筆者在centosubuntu上嘗試過以上三種方法,由於伺服器環境不純淨,導致各種問題裝上。因此建議大家有docker就用docker,沒有docker的話可完全參照官方文檔的步驟就可以了。


安裝前準備-系統版本查看

Linux系統下,注意系統的發行版本本是什麼,LinuxUbuntuCentos/RedHat有著不同的安裝包,這裡需要一開始查看自己系統版本。

cat /etc/*-release

Copy

同時查看cuda版本以及cudnn版本

nvcc -V

# cudnn 8.0以前版本查看

cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2

# cudnn 8.0以後版本查看

cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2

Copy

這裡安裝的是ubuntu18.04, cuda11.6, cudnn8.9.2

通過docker安裝

https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tensorrt

https://docs.nvidia.com/deeplearning/tensorrt/container-release-notes/index.html

https://catalog.ngc.nvidia.com/orgs/nvidia/containers/pytorch/tags(pytorch + trt的容器)

有了docker可以直接拉取鏡像,在環境中使用對應的TRT

第一步:拉取鏡像

docker pull nvcr.io/nvidia/tensorrt:23.04-py3

Copy

TRT的版本可以通過文檔查找

23.04-py3表示20234月發佈的鏡像,該鏡像環境是:

  • Ubuntu 20.04
  • Python3.8
  • NVIDIA CUDA® 12.1.0
  • NVIDIA cuBLAS 12.1.3
  • NVIDIA cuDNN 8.9.0
  • NVIDIA NCCL 2.17.1

第二步:啟動鏡像

docker run -it -d --name trt  --gpus all -v /home/docker_volume:/mnt nvcr.io/nvidia/tensorrt:23.04-py3 /bin/bash

Copy

第三步:進入容器,查看trt版本

docker exec -it trt /bin/bash

dpkg -l | grep TensorRT

Copy

得到如下顯示,表明安裝成功,可以嘗試使用trtexecpython進行TRT模型推理。

root@c3d8bfb1d917:/opt/tensorrt/bin# dpkg -l | grep TensorRT

ii  libnvinfer-bin                  8.5.1-1+cuda11.8                  amd64        TensorRT binaries

ii  libnvinfer-dev                  8.5.1-1+cuda11.8                  amd64        TensorRT development libraries and headers

ii  libnvinfer-plugin-dev           8.5.1-1+cuda11.8                  amd64        TensorRT plugin libraries and headers

ii  libnvinfer-plugin8              8.5.1-1+cuda11.8                  amd64        TensorRT plugin library

ii  libnvinfer8                     8.5.1-1+cuda11.8                  amd64        TensorRT runtime libraries

ii  libnvonnxparsers-dev            8.5.1-1+cuda11.8                  amd64        TensorRT ONNX libraries

ii  libnvonnxparsers8               8.5.1-1+cuda11.8                  amd64        TensorRT ONNX libraries

ii  libnvparsers-dev                8.5.1-1+cuda11.8                  amd64        TensorRT parsers libraries

ii  libnvparsers8                   8.5.1-1+cuda11.8                  amd64        TensorRT parsers libraries

ii  tensorrt-dev                    8.5.1.7-1+cuda11.8                amd64        Meta package for TensorRT development libraries

Copy

第四步:驗證TRT

基於trtexec 運行模型。首先,編譯trtexec

cd /workspace/tensorrt/samples/trtexec

make

Copy

然後,添加環境變數:

export PATH=$PATH:/path/to/trtexec

 

export PATH=$PATH:/workspace/tensorrt/samples/trtexec

Copy

最後,將resnet50_bs_1.onnx檔放到伺服器,執行命令:

trtexec --onnx=resnet50_bs_1.onnx --saveEngine=resnet50_bs_1.engine

Copy

最後得到如下輸出:

[06/14/2023-07:18:37] [I] === Performance summary ===

[06/14/2023-07:18:37] [I] Throughput: 443.756 qps

[06/14/2023-07:18:37] [I] Latency: min = 2.27521 ms, max = 2.51807 ms, mean = 2.30483 ms, median = 2.3042 ms, percentile(90%) = 2.32056 ms, percentile(95%) = 2.32422 ms, percentile(99%) = 2.33069 ms

[06/14/2023-07:18:37] [I] Enqueue Time: min = 0.792969 ms, max = 1.42358 ms, mean = 0.966213 ms, median = 0.89917 ms, percentile(90%) = 1.28101 ms, percentile(95%) = 1.29688 ms, percentile(99%) = 1.34668 ms

[06/14/2023-07:18:37] [I] H2D Latency: min = 0.0510864 ms, max = 0.09021 ms, mean = 0.0603899 ms, median = 0.0601807 ms, percentile(90%) = 0.0654297 ms, percentile(95%) = 0.06604 ms, percentile(99%) = 0.0751953 ms

[06/14/2023-07:18:37] [I] GPU Compute Time: min = 2.22003 ms, max = 2.45557 ms, mean = 2.24015 ms, median = 2.24048 ms, percentile(90%) = 2.25073 ms, percentile(95%) = 2.25391 ms, percentile(99%) = 2.26099 ms

[06/14/2023-07:18:37] [I] D2H Latency: min = 0.00244141 ms, max = 0.0136719 ms, mean = 0.00428888 ms, median = 0.00305176 ms, percentile(90%) = 0.0114746 ms, percentile(95%) = 0.0126953 ms, percentile(99%) = 0.0133057 ms

[06/14/2023-07:18:37] [I] Total Host Walltime: 3.00616 s

[06/14/2023-07:18:37] [I] Total GPU Compute Time: 2.98836 s

[06/14/2023-07:18:37] [I] Explanations of the performance metrics are printed in the verbose logs.

[06/14/2023-07:18:37] [I]

&&&& PASSED TensorRT.trtexec [TensorRT v8601] # trtexec --onnx=resnet50_bs_1.onnx --saveEngine=resnet50_bs_1.engine

Copy

通過Deb包安裝

Deb參考官網吧,這裡安裝最後失敗了,所以推薦大家用docker安裝,下面是作為記錄。

第一步:在官網下載deb包。並安裝

sudo dpkg -i nv-tensorrt-local-repo-${os}-${tag}_1.0-1_amd64.deb

sudo cp /var/nv-tensorrt-local-repo-${os}-${tag}/*-keyring.gpg /usr/share/keyrings/

sudo apt-get update

Copy

第二步:安裝 tensorrt

需要等待3-5分鐘。

sudo apt-get install tensorrt

Copy

第三步:安裝其它工具

sudo apt-get install python3-libnvinfer-lean

sudo apt-get install python3-libnvinfer-dispatch

python3 -m pip install numpy

sudo apt-get install python3-libnvinfer-dev

python3 -m pip install numpy onnx

sudo apt-get install onnx-graphsurgeon

Copy

第四步:驗證安裝

安裝好後,可到/usr/src/tensorrt 查看安裝目錄。

dpkg-query -W tensorrt

Copy

第五步:編譯trtexec

cd /usr/src/tensorrt/samples/trtexec

make

Copy

根據官方文檔只需要make就可以獲得trtexec,但是我的伺服器的配置出了些問題,make時出現如下報錯:

/usr/local/cuda/include/cuda_runtime_api.h:4219:65: error: 'cudaLaunchConfig_t' does not name a type; did you mean 'cudaFunction_t'?

 extern __host__ cudaError_t CUDARTAPI cudaLaunchKernelExC(const cudaLaunchConfig_t *config, const void *func, void **args);

Copy

多種嘗試未解決,後續將採用docker鏡像來使用TRT,這裡暫時放棄。

小結

本小節介紹了TensorRT的基礎概念,知道了TRT中需要做優化和推理兩個主要內容,其中的優化可以在API中或者是trtexec中進行,推理則提供了pythonc++兩種介面。在安裝上,介紹了windows下和linux下的安裝及驗證,可以看到在吞吐和時延上,TRTONNX都有優勢。

下一小節將詳細介紹TRT的工作流程。

 

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 HCHUNGW 的頭像
    HCHUNGW

    HCHUNGW的部落格

    HCHUNGW 發表在 痞客邦 留言(0) 人氣()