TensorRT轉換時的靜態模式與動態模式
1. TensorRT的模型轉換
當我們需要利用NVIDIA的硬體進行加速模型的時候,很多時候會選擇將模型轉為TensorRT模型,不同的框架下有各種各樣的轉換方式,如轉為uff然後再轉TensorRT,或者先轉為onnx再轉TensorRT,不過一般都比較繁瑣,並且需要修改推斷程式碼。
自TensorFlow1.7及更高版本開始,TensorFlow與TensorRT模型混合使用變得更加方便,通常不需要改動原來的TensorFlow模型的推斷程式碼就能夠使用TensorRT模型,具體原理可以參考使用TensorRT加速GPU上的TensorFlow推理。
一般來說,需要先把原來的TensorFlow模型轉為TensorRT模型,轉換的核心程式碼如下:
trt_graph = trt.create_inference_graph(graph_def, outputs=output_names, max_batch_size=batch_size, max_workspace_size_bytes=workspace_size, precision_mode=precision_mode)
但是往往在這個過程中,會出現譬如以下的報錯:
TensorRT node TRTEngineOp_0 added for segment 0 consisting of 139 nodes failed: Internal: Input shapes must be fully defined when in static mode. Please try is_dynamic_op=True (shape was [?,?,?,?]). Fallback to TF...
究其原因,是因為在轉換為TensorRT模型的時候,要求輸入是確定的shape,如果不是需要將is_dynamic_op引數設定為True,這樣將轉為動態模式。
2. 靜態模式與動態模式區別
2.1. 靜態模式
轉之前的模型,輸入的維度形狀都是確定的,不可以變。這種情況下,TensorRT已經將engine離線建立了,在載入TensorRT模型的時候,會自動建立engine。
2.2. 動態模式
轉之前的輸入維度是動態的(最經常的情況,就是批次的維度不確定,但是其他維度確定),這個時候,在轉換的時候其實並沒有離線建立engine,但是由於TensorRT在執行的時候又要求所有的維度都是確定的,因此,TensorRT每遇到一個新的形狀的時候,就會建立一個新的engine。在實際的推理中,有時候速度會突然變慢,往往是建立engine造成的。
3. engine的重用機制
上面說到,在動態模式下,遇到新的輸入形狀,TensorRT會新建立一個新engine。但並不是所有情況都會重新建立,TensorRT有其engine重用機制,只要符合下面兩個條件即可:
- 當前engine的batch size大於等於新的input的batch size
- engine的其他維度與新的input的其他維度匹配
舉個例子。我們模型的輸入維度為[?,128,128,3],其中第一個維度為batch size維度。當遇到第一個新input,它的輸入形狀為[10,128,128,3],這個時候,TensorRT會建立一個新的engine(就叫A吧),它輸入的形狀為[10,128,128,3],並將該engine快取。
如果遇到一個新的輸入,如[3,128,128,3],這個時候會先去快取尋找是否有符合的engine,因為batch size比engine A的要小,而且其他維度是一樣的,所以就不再建立新的engine,直接利用A進行推理了。
當然,engine的快取個數是有限的,需要在轉換的時候進行設定(maximum_cached_engines引數 ),一般建議是5.
最後修改完的引數為:
trt_graph = trt.create_inference_graph(graph_def, outputs=output_names, max_batch_size=batch_size, is_dynamic_op=True, max_workspace_size_bytes=workspace_size, maximum_cached_engines=5, precision_mode=precision_mode)
4. 參考
(完)
本文版權歸作者(https://www.cnblogs.com/harrymore/)和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結,如有問題, 可郵件([email protected])諮詢.