今天要教大家如何將模型佈署在Triton Server,因為Client的工作DeepStream都有預先寫好的工具,我們就以介紹Server佈署為優先。
先前有提到Triton Server需要一個放置模型的目錄,這個目錄的概念如下
<model-repository-root>/
├── <model-name-1>/
│ ├── config.pbtxt
│ ├── 1/
│ │ └── model (onnx, engine, pt)
│ └── 2/
│ └── model
│
└── <model-name-2>/
├── config.pbtxt
└── 1/
└── model
model-name資料夾就代表一個模型,Client在調用的時候輸入的model name就是指這個。再來1、2、...等流水號就代表模型的版本。Server會根據Client的請求去選擇實際調用的模型檔案。
請參考這份檔案/opt/nvidia/deepstream/deepstream/samples/triton_mode_repo/Secondary_VehicleMake/config.pbtxt
name: "Secondary_VehicleMake"
platform: "tensorrt_plan"
max_batch_size: 16
default_model_filename: "resnet18_vehiclemakenet_pruned.onnx_b16_gpu0_int8.engine"
input [
{
name: "input_1:0"
data_type: TYPE_FP32
format: FORMAT_NCHW
dims: [3, 224, 224]
}
]
output [
{
name: "predictions/Softmax:0"
data_type: TYPE_FP32
dims: [20]
}
]
instance_group [
{
kind: KIND_GPU
count: 1
gpus: 0
}
]
Triton Server可以支援不同的推論框架,所以可以設定你要用的推論框架是哪一個。寫platform或backend都是可以的,我個人比較推薦backend,因為這邊類似ONNX的Execution Provider,在Triton Server的文件中是以backend稱呼這些推論的提供者。因為這個範例設定檔比較舊了,所以會看到這些不太一樣的命名,如果你用backend的話,記得要寫tensorrt,而不是tensorrt_plan。
告訴Server你模型能支援的最大批次數,如果模型可以支援批次推論,那必要條件是tensor的第一個維度是batch_size,沒有商量空間。如果你的模型是後面的維度可以接受batch_size,那請務必設定max_batch_size=0,這樣就會變成顯式(explicit)指定所有維度。
加上這個欄位你才能命名模型檔案,否則Server會找預設的名稱model.<ext>,例如ONNX就是model.onnx,而TensorRT...
model.plan
我也不知道為啥到了這邊變成.plan了,總之如果你習慣用.engine的話,記得要設定default_model_filename哦
這邊需要告訴Server你模型上的每個tensor的資訊,必要的屬性有name、data_type、dims,當max_batch_size > 0時,第一個維度不用設定,只要寫上第2、3、...等後面的維度就好,所以才會看到input_1:0的dims只有寫[3,224,224]。如果你是顯式設定但維度是動態的,那就把對應的維度寫上-1,例如[-1,3,224,224]。
這邊要補充一下DeepStream不友善的一個地方,就是他的元件設計只接受一個input tensor,而且必須要是NCHW或NHWC。如果你有什麼花俏的模型,那麼很抱歉地,nvinferserver是你唯一的選項了,它有提供一些方法載入你寫的shared library去調用模型,我自己有試過NanoSAM這個模型,勉強讓他跑起來但限制也很多,後來放棄DeepStream直接自己寫元件去了。
DeepStream在範例中要使用Triton Server的話得先另外執行腳本把模型佈署到對應的路徑上,所以我們先執行這個腳本
cd /opt/nvidia/deepstream/deepstream/samples
bash prepare_ds_triton_model_repo.sh
完成之後我們可以看一下實際模型佈署的位置
cd /opt/nvidia/deepstream/deepstream/samples
ls -R triton_model_repo/
這個方法會把模型倉庫下的全部模型啟動,如果你模型不多可以直接這樣做
tritonserver --model-repository=triton_model_repo
如果啟動成功的話應該會看到最後的訊息是這樣
I0830 11:15:18.770299 362 grpc_server.cc:2562] "Started GRPCInferenceService at 0.0.0.0:8001"
I0830 11:15:18.770436 362 http_server.cc:4823] "Started HTTPService at 0.0.0.0:8000"
I0830 11:15:18.811702 362 http_server.cc:358] "Started Metrics Service at 0.0.0.0:8002"
稍微往上捲一點可以看到目前就緒的模型有哪些
I0830 11:15:18.716464 362 server.cc:690]
+------------------------+---------+--------+
| Model | Version | Status |
+------------------------+---------+--------+
| Primary_Detector | 1 | READY |
| Secondary_VehicleMake | 1 | READY |
| Secondary_VehicleTypes | 1 | READY |
+------------------------+---------+--------+
這個方法我個人很推薦,當你模型多的時候,有些模型可以特定情況在載入使用,而且Server再啟動當下如果你的部分模型資料夾是空的(例如測試階段),Server會直接啟動失敗。
我們可以用--model-control-mode和--load-model這兩個參數來啟動
tritonserver --model-repository=triton_model_repo --model-control-mode=explicit --load-model=Primary_Detector
這樣的話就只有啟動Primary_Detector這個模型
I0830 11:25:52.512404 448 server.cc:690]
+------------------+---------+--------+
| Model | Version | Status |
+------------------+---------+--------+
| Primary_Detector | 1 | READY |
+------------------+---------+--------+
如果要在Server運行中載入/卸載模型,可以透過發送HTTP請求來實現
curl -X POST http://localhost:8000/v2/repository/models/Secondary_VehicleMake/load
發送之後可以看到Server顯示
[...]
I0830 11:47:44.046772 611 model_lifecycle.cc:849] "successfully loaded 'Secondary_VehicleMake'"
同樣地也可以卸載模型
curl -X POST http://localhost:8000/v2/repository/models/Secondary_VehicleMake/unload
Triton Server的介紹大概就到這裡啦,我認為已經非常夠用了,說真的它的設定方式很豐富,但那必須要去查每個backend的說明文件,而預設的情況就足以應付一般使用。如果你手邊有在使用的模型,不妨也自己佈署一下自己的Triton Server吧,實際操作才會獲益良多。