iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0

原本這部分是打算跟著昨天的nvinfer一起介紹的,但寫完文章發現內容實在太多了,於是決定單獨拆成一天來跟大家介紹囉。

TensorRT的CLI工具trtexec

前面我們在運行範例的時候都是透過nvinfer去建立TensorRT模型,但其實也可以使用trtexec預先編譯好TensorRT模型讓nvinfer直接使用,這有什麼好處呢?

首先,你的串流可以立即啟動,隨著模型的參數量跟複雜度增加,編譯時間成長幅度也是相當驚人,以我自身的經歷有遇過大批次數模型要編譯30分鐘以上的,就像你看影片不會接受30分鐘後才開始播放這種事,對吧?

其次,當你是第一次由ONNX編譯,偶爾會跳出一些警告,甚至編譯失敗。遇到這種情況時,trtexec提供更完整的日誌(log)且具備分級[I]、[W]、[E]、[V],分別代表INFO、WARNING、ERROR、VERBOSE(預設關閉),讓開發者可以更進一步的排查編譯過程的問題。另外這個工具提供更多的編譯參數讓開發者可以進一步優化編譯結果,不必自己調用TensorRT的API。

如何使用

先直接上範例,就比照前面示範的串流程式做相同的編譯操作。設定檔請參考/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-test1/dstest1_pgie_config.txt

export ONNX_FILE="/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx"
export ENGINE_FILE="/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx_b1_gpu0_fp16.engine"

trtexec \
    --onnx=${ONNX_FILE} \
    --saveEngine=${ENGINE_FILE} \
    --minShapes=input_1:0:1x3x544x960 \
    --optShapes=input_1:0:1x3x544x960 \
    --maxShapes=input_1:0:1x3x544x960 \
    --fp16

執行指令後就會開始編譯,我們先看幾個重要資訊

[08/24/2026-16:13:47] [I] TensorRT version: 10.16.0
[08/24/2026-16:13:47] [I] Loading standard plugins
[08/24/2026-16:13:47] [I] [TRT] [MemUsageChange] Init CUDA: CPU +1, GPU +0, now: CPU 33, GPU 997 (MiB)
[08/24/2026-16:13:47] [I] Start parsing network model.
[08/24/2026-16:13:47] [I] [TRT] ----------------------------------------------------------------
[08/24/2026-16:13:47] [I] [TRT] Input filename:   /opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx
[08/24/2026-16:13:47] [I] [TRT] ONNX IR version:  0.0.7
[08/24/2026-16:13:47] [I] [TRT] Opset version:    12
[08/24/2026-16:13:47] [I] [TRT] Producer name:    tf2onnx
[08/24/2026-16:13:47] [I] [TRT] Producer version: 1.9.2
[08/24/2026-16:13:47] [I] [TRT] Domain:
[08/24/2026-16:13:47] [I] [TRT] Model version:    0
[08/24/2026-16:13:47] [I] [TRT] Doc string:
[08/24/2026-16:13:47] [I] [TRT] ----------------------------------------------------------------
[08/24/2026-16:13:47] [I] Finished parsing network model. Parse time: 0.0124231
[08/24/2026-16:13:47] [I] Set shape of input tensor input_1:0 for optimization profile 0 to: MIN=1x3x544x960 OPT=1x3x544x960 MAX=1x3x544x960
  • TensorRT version

    「非常」重要,版本不對,Engine報廢,一定要記得讓你編譯使用的TensorRT版本跟Runtime使用的版本一致。某些新增或棄用功能也是跟版本直接相關,要仔細比對。

  • Input filename

    用來檢查編譯的檔案是否正確

  • Opset version

    算子集版本。TensorRT每個版本會有它可以支援的最高Opset版本,也有機會透過升級Opset版本得到性能提升。

  • 模型輸入

    [08/24/2026-16:13:47] [I] Set shape of input tensor input_1:0 for optimization profile 0 to: MIN=1x3x544x960 OPT=1x3x544x960 MAX=1x3x544x960
    

    這個是TensorRT模型可以支援的輸入大小,分為MINOPTMAX三個部分。MIN就是可以請求的最小輸入維度,MAX是最大。OPT是範圍之間的維度,通常以你最常使用的批次大小為標準,它的原理是在編譯中用你指定的輸入維度反覆運算去找出最佳的優化路徑,所以維度越大就要優化越久。

完成之後會看到一筆漂亮的數據

[08/24/2026-16:14:18] [I] === Performance summary ===
[08/24/2026-16:14:18] [I] Throughput: 561.345 qps

trtexec預設會在編譯完成後以OPT維度做推論,單位是qps(Query Per Second),以影像串流而言可以間接當作FPS。

提高batch-size

前面範例是用batch-size=1編譯模型,這邊我們提高到4做一個示範,然後記得要改ENGINE_FILE的路徑哦,不然前面示範的模型就被蓋掉了。

export ONNX_FILE="/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx"
export ENGINE_FILE="/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx_b4_gpu0_fp16.engine"

trtexec \
    --onnx=${ONNX_FILE} \
    --saveEngine=${ENGINE_FILE} \
    --minShapes=input_1:0:1x3x544x960 \
    --optShapes=input_1:0:4x3x544x960 \
    --maxShapes=input_1:0:4x3x544x960 \
    --fp16

編譯結果如下

[08/24/2026-16:16:06] [I] Set shape of input tensor input_1:0 for optimization profile 0 to: MIN=1x3x544x960 OPT=4x3x544x960 MAX=4x3x544x960

[...]

[08/24/2026-16:16:51] [I] === Performance summary ===
[08/24/2026-16:16:51] [I] Throughput: 156.494 qps

這個模型就可進行最大批次數是4的推論啦。

精度指定

  • FP16:參考剛才的範例
  • FP32:非常簡單,去掉--fp16
  • BEST:前面介紹nvinfer有提到過,這邊的話要使用--best,或是你可以自己指定--f16加上--int8,不能使用INT8的節點就會退回FP16運算

再溫馨提醒一次,這個功能會在TensorRT 11.x版本正式被移除,到時候要使用NVIDIA Model Optimizer

提高編譯優化等級

這個是nvinfer那邊不能做到的,如果你真的要追求更快的速度,可以加上--builderOptimizationLevel=<n:1~5>這個參數,例如把前面的範例再提高優化等級

export ONNX_FILE="/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx"
export ENGINE_FILE="/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx_b1_gpu0_fp16_opt4.engine"

trtexec \
    --onnx=${ONNX_FILE} \
    --saveEngine=${ENGINE_FILE} \
    --minShapes=input_1:0:1x3x544x960 \
    --optShapes=input_1:0:1x3x544x960 \
    --maxShapes=input_1:0:1x3x544x960 \
    --fp16 \
    --builderOptimizationLevel=4

加上這個編譯條件「通常」可以微幅提升qps,但只要提高一個等級就會大幅提高編譯時間,我個人從經驗來看是不太建議使用。

但是!官方論壇有一個已知的情況必須使用這個編譯參數,就是預設的優化等級找不到任何優化路徑,使得編譯失敗。這時候官方回覆是請你提高一個等級到4(預設是3),讓編譯器有更多優化路徑可以嘗試,通常這麼做就可以成功。

讓我們來看看實測結果吧

[08/24/2026-16:26:43] [I] === Performance summary ===
[08/24/2026-16:26:43] [I] Throughput: 494.923 qps

很遺憾地,結果是開倒車。至於原因非常複雜,取決於你的模型結構可以嘗試什麼優化手段,以及編譯當下嘗試路徑的運算時間,因為編譯器會以當下的運算時間做為選擇路徑的手段。

載入模型推論

除了編譯,剛才也示範了這個工具是有推論功能的,所以我們也可以直接載入預先編譯好的模型並指定維度推論。

export ENGINE_FILE="/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx_b4_gpu0_fp16.engine"

trtexec \
    --loadEngine=${ENGINE_FILE} \
    --shapes=input_1:0:2x3x544x960

可以看到這樣的訊息

[08/24/2026-16:34:20] [I] Using random values for input input_1:0
[08/24/2026-16:34:20] [I] Input binding for input_1:0 with dimensions 2x3x544x960 and type fp32 is created.
[08/24/2026-16:34:20] [I] Output binding for output_cov/Sigmoid:0 with dimensions 2x4x34x60 and type fp32 is created.
[08/24/2026-16:34:20] [I] Output binding for output_bbox/BiasAdd:0 with dimensions 2x16x34x60 and type fp32 is created.
[08/24/2026-16:34:20] [I] Starting inference

你可以測試不同條件下的推論速度去決定最終的應用程式該怎麼設定,通常我們也只看qps,如果你有更多需求可以只輸入trtexec,他會跳出整個CLI的參數說明。

結語

以上的內容就是我在實戰中經常會用到的指令啦,大家可以嘗試不同的組合來玩看看哦。


上一篇
[Day 08] 推論元件nvinfer
下一篇
[Day 10] 讓推論服務化nvinferserver
系列文
深入認識DeepStream,不只是停在執行範例13
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言