2020/10/02 此版維護期限已到期,未來將不再更新,請轉至最新版

前言

本章為提供給還在使用舊版的人參考,關於此套件的詳細說明也可都在最新版中查看。


Server

系統環境

  • OS:Ubuntu 18.04
  • GPU Driver:450.51.05
  • Docker:19.03.5
  • Docker Image:nvcr.io/nvidia/tritonserver:20.07-v1-py3

安裝步驟

安裝 Docker

本篇是將系統架設在 Docker 上,可以參考此文章 將 Docker 環境建立起來。

下載映像檔

1
sudo docker pull nvcr.io/nvidia/tritonserver:20.07-v1-py3

運行步驟

模型轉換

系統支援的模型如下,如訓練時所使用的框架非下述所示,則需進行轉換。

  • Tensorflow (graphdef, savedmodel)
  • TensorRT (plan)
  • ONNX (onnx)
  • PyTorch (pt)
  • Caffe2 (netdef)

為了增加系統效能,建議模型都要過 TensorRT 編譯。

建立模型庫

模型庫中保存著多個模型包。
每個模型包皆由版本及設定檔所組成,版本建議以自然數依序命名 (Ex. 1,2,3…)。

建立模型庫範例如下圖所示:
以此範例來說
模型庫為 model-repository
模型庫中共存放了4個模型包 (mnistTensorrt, mnist-tftrt, tensorflowGraphdef, tensorflowSavedmodel)
其中以 mnist-tftrt 模型包為例,mnist-tftrt 為此模型的命名,資料夾中存放了版本 1 的模型及設定檔。

編輯設定檔

每個模型包皆須有設定檔,系統會根據設定檔來運行模型,最基本的設定檔由 5 大元素組成:模型名稱、模型框架、最大批次大小、輸入及輸出層的資訊、GPU 實例資訊。

更詳盡的參數說明可以參考官方文件

編輯設定檔範例如下圖所示:

設定檔中的模型名稱需與資料夾的模型名稱一致。

最大批次大小為推論批次設定的最大值,不一定是實際推論批次大小。

運行伺服器端

在運行前需指定此服務要跑幾個 GPU、走哪些 Port 以及模型庫的路徑。

1
2
3
4
sudo docker run -d --gpus <GPU Number> --name <Conatainer Name> --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 -p <Host Port>:8000 -p <Host Port>:8001 -p <Host Port>:8002 -v <Model Repository Path>:/models nvcr.io/nvidia/tritonserver:20.07-v1-py3 tritonserver --model-store=/models

# Example
sudo docker run -d --gpus all --name Triton_Server --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 -p 8000:8000 -p 8001:8001 -p 8002:8002 -v /home/user/Documents/model-repository:/models nvcr.io/nvidia/tritonserver:20.07-v1-py3 tritonserver --model-store=/models

Port 8000 為 HTTP 協定通道
Port 8001 為 GRPC 協定通道

檢查系統狀態

檢查系統是否正常的運行中:

1
curl -v localhost:8000/api/status

Triton 提供 Prometheus Metrics,內容主要為 GPU 狀態和請求統計資訊等:

1
curl -v http://localhost:8002/metrics

Client

系統環境

  • OS:Ubuntu 18.04
  • Docker:19.03.5
  • Docker Image:nvcr.io/nvidia/tritonserver:20.07-v1-py3-clientsdk

安裝步驟

安裝 Docker

本篇是將系統架設在 Docker 上,可以參考此文章 將 Docker 環境建立起來。

下載映像檔

1
sudo docker pull nvcr.io/nvidia/tritonserver:20.07-v1-py3-clientsdk

運行步驟

串接設備

目前主流要推論的資料為數據、影像、聲音以及文字,在跟 Server 端溝通之前,Client 端需先跟各設備進行串接。

如影像型推論,就需跟攝影機、機台、儲存設備、呈現平台…等串接。

撰寫程式碼

Client 端程式碼撰寫主要分成三大部分,依序為

  • 前處理
    此部分主要處裡的事項為資訊進模型前的所有處理,如影像解碼、維度轉換、訊號處理等等。
  • Client-Server 溝通
    指定將推論的模型資訊,透過 HTTP 或 GRPC 跟 Server 溝通。
    詳細的函數說明可以參考官方文件官方範例
  • 後處理
    此部分主要處裡的事項為接到 Server 回傳來推論結果後的所有處理,如儲存檔案、訊息整理、結果呈現等等。

前後處理會因不同的應用實例有所差異,此部分不是本章的重點。
本章將會著重在說明 Triton Client-Server 基本的溝通函數,其他更深入的函數將在日後介紹。

運行客戶端

在運行前需確認 Server 的 IP、走的協定 (HTTP or GRPC) 以及讀取儲存資料的位置。

1
2
3
4
sudo docker run -d --name <Container Name> -v <Data Path>:/data nvcr.io/nvidia/tritonserver:20.07-v1-py3-clientsdk bash -c '<Client Code>'

# Example
sudo docker run -d --name Triton_Client -v /home/user/Documents/data:/data nvcr.io/nvidia/tritonserver:20.07-v1-py3-clientsdk bash -c 'python /data/client.py'

範例

接下來將以大家耳熟能詳的 MNIST 所訓練出的模型當作範例,由於訓練模型不是本篇的重點,可以直接下載訓練好的模型進行後續的練習。

Server

訓練模型

此部分以 MNIST 資料集和簡單的 CNN 模型當作範例。
撰寫框架為 Kears,來源為官方範本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import tensorflow.compat.v2 as tf
import tensorflow_datasets as tfds

tfds.disable_progress_bar()
tf.enable_v2_behavior()


(ds_train, ds_test), ds_info = tfds.load(
'mnist',
split=['train', 'test'],
shuffle_files=True,
as_supervised=True,
with_info=True,
)

def normalize_img(image, label):
"""Normalizes images: `uint8` -> `float32`."""
return tf.cast(image, tf.float32) / 255., label

ds_train = ds_train.map(
normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_train = ds_train.cache()
ds_train = ds_train.shuffle(ds_info.splits['train'].num_examples)
ds_train = ds_train.batch(128)
ds_train = ds_train.prefetch(tf.data.experimental.AUTOTUNE)


ds_test = ds_test.map(
normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
ds_test = ds_test.batch(128)
ds_test = ds_test.cache()
ds_test = ds_test.prefetch(tf.data.experimental.AUTOTUNE)


model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28, 1)),
tf.keras.layers.Dense(128,activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(
loss='sparse_categorical_crossentropy',
optimizer=tf.keras.optimizers.Adam(0.001),
metrics=['accuracy'],
)

model.fit(
ds_train,
epochs=6,
validation_data=ds_test,
)

## 模型儲存
model.save('mnist')

模型轉換

由於儲存的模型已是 SavedModel 格式,所以此步只需用 TensorRT 編譯優化即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from tensorflow.python.compiler.tensorrt import trt_convert as trt
import tensorflow as tf

conversion_params = trt.DEFAULT_TRT_CONVERSION_PARAMS
conversion_params = conversion_params._replace(max_workspace_size_bytes=(1<<32))
conversion_params = conversion_params._replace(precision_mode="FP16")
conversion_params = conversion_params._replace(maximum_cached_engines=128)
conversion_params = conversion_params._replace(use_calibration=False)
conversion_params = conversion_params._replace(max_batch_size=32)
converter = trt.TrtGraphConverterV2(input_saved_model_dir='mnist', conversion_params=conversion_params)
converter.convert()

def input_fn():
for _ in range(100):
yield [tf.random.normal((32, 28, 28, 1))]
converter.build(input_fn)
converter.save('model.savedmodel')

建立模型庫

以上面的模型為例,建立出的模型庫如下圖所示。

編輯設定檔

以下的參數為必要欄位,其他深入或客製化的參數,可以參考官網文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
name: "mnist"
platform: "tensorflow_savedmodel"
max_batch_size: 32
input [
{
name: "flatten_input"
data_type: TYPE_FP32
format: FORMAT_NHWC
dims: [28, 28, 1]
}
]
output [
{
name: "dense_1"
data_type: TYPE_FP32
dims: [10]
}
]
instance_group [
{
kind: KIND_GPU
count: 2
}
]

運行伺服器端

1
sudo docker run -d --gpus all --name Triton_Server --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 -p 8000:8000 -p 8001:8001 -p 8002:8002 -v /home/user/Documents/model-repository:/models nvcr.io/nvidia/tritonserver:20.06-py3 tritonserver --model-store=/models

運行伺服器端後,成功的畫面如下所示。

Cleint

串接設備

由於沒有實際的設備可以串接,此部分直接取用 MNIST 測試資料集中一張影像當作範例,最後將接到的推論結果直接顯示在螢幕上。

MNIST 測試資料如下圖所示。

撰寫程式碼

client.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from PIL import Image
import numpy as np
import tritongrpcclient
from tritonclientutils import triton_to_np_dtype

## 前處理
img = Image.open('test.jpg').convert('L')
img = img.resize((28, 28))
imgArr = np.asarray(img)/255
imgArr = np.expand_dims(imgArr[:, :, np.newaxis], 0)
imgArr= imgArr.astype(triton_to_np_dtype('FP32'))

## Client-Server 溝通
protocol = ProtocolType.from_str("gRPC")
ctx = InferContext(url='localhost:8001', protocol, 'mnist', 1, 2)
responses = []
responses.append(ctx.run(
{"flatten_input":[imgArr]},
{"dense_1":InferContext.ResultFormat.RAW}))

## 後處理
print (np.argmax(responses[0].as_numpy('dense_1')[0]))

運行客戶端

將客戶端環境運行起來後,執行上部撰寫好的程式碼,即可進行推論。

1
sudo docker run -it --rm --name Triton_Client -v /home/user/data:/data nvcr.io/nvidia/tritonserver:20.07-v1-py3-clientsdk bash -c 'python /data/client.py'

最後 MNIST 推論結果如下圖所示,可以發現有成功的預測出數字。


參考資料

  1. Triton Inference Server Docs

  2. Triton Inference Server Github