Triton Inference Server에서 TensorRT Engine Inference

soooooooooo·2021년 5월 26일
4

TensorRT

목록 보기
1/1
post-thumbnail

Triton Inference Server GitHub: https://github.com/triton-inference-server/server

Triton Inference Server?

Triton Inference Server(이하 TRTIS)는 모델을 넣어주면 추론 서버를 만들어주는 Nvidia 에서 제공해주는 SDK입니다. 모델은 Pytorch, Tensorflow, onnx, TensorRT 등등 이 지원되며, TensorRT 엔진에서 가장 뛰어난 효과를 보장합니다.

왜 TRTIS를 사용할까요? 간단합니다. 간편하고 빠르기 때문입니다. Python이나 C++으로 TensorRT 엔진을 사용하여서 추론 작업을 하는 것은 Pytorch나 Tensorflow 에서 추론을 하는 것보다 성능이 좋지만, 더 low 적인 작업이 많아서 추론 코드를 작성하기에 조금 어렵습니다. 그러나 TRTIS를 사용하면 기본적인 config 설정과 모델만 있으면 서버 방식으로 배포하여 접근도 쉽고, 클라이언트 코드의 재작성이 불필요 해집니다. 게다가 추론도 Multi GPU Inference를 하려면 프로세스를 여러개 돌려야 하기 때문에 프로세스 관리가 까다로운데, TRTIS는 GPU 설정만 해주면 스스로 Multi GPU Inference를 해주어서, 추론 코드를 작성하는 시간을 아낄 수 있습니다. 그리고, 한 GPU에 모델을 여러개 올려서 배포하고, 모델마다 버전을 관리 할 수 있어서, 모델 관리에 용이합니다. 또, TRTIS는 C++ 기반으로 만들어져 있어서, 일반적으로 Python에서 TensorRT 엔진을 돌려서 추론하는 것보다 빠릅니다.

아래 내용은 EDSR 모델()을 이용해서 Super Resolution 추론 서버를 제작하는 과정입니다. 서버는 A100 서버를 기준으로 작성하였고, 같이 첨부되어있는 EDSR 모델도 A100에서 TensorRT 엔진을 만들었습니다. A100이 아닌 다른 Nvidia GPU에서 작업을 하면 작동이 안 되거나 성능이 저하 될 수 있습니다.

같이 첨부된 onnx 모델이나, 자신이 가지고 있는 개인 Pytorch 모델 및 onnx 모델을 TensorRT 엔진으로 변환하여 사용하고 싶으시면, (#document 미완성)에 들어가셔서 참고하시기 바랍니다.

TRTIS Docker Image 설치하기

TRTIS는 직접 빌드 하거나 도커 이미지로 실행시키는 방법이 있는데, 일반적으로 Docker 컨테이너로 사용하는게 제일 쉽고 관리가 간편합니다.

이 커맨드를 이용하여 pull 합니다.

$ sudo docker pull nvcr.io/nvidia/tritonserver:21.04-py3

<xx.yy>는 https://ngc.nvidia.com/catalog/containers/nvidia:tritonserver 에 들어가시어 원하는 버전을 입력해서 컨테이너를 불러옵니다. Tags 탭에 들어가시면 무슨 컨테이너가 있는지 확인할 수 있습니다. 이 글을 작성할 당시는 21.04가 가장 최신이였으므로, 이 글에서는 21.04로 사용하겠습니다.

P.S ) 주의할 점은 TensorRT 엔진을 사용할려면 TensorRT와 TRTIS와 버전이 매칭되어야 하는데, https://ngc.nvidia.com/catalog/containers/nvidia:tensorrt 에 접속하시어, 아래에 있는 커맨드로 TensorRT 컨테이너를 pull 하여 이 컨테이너에서 TensorRT 엔진을 만들어서 서버에 가져와야 합니다.

$ sudo docker pull nvcr.io/nvidia/tensorrt:21.04-py3

TRTIS 도커 이미지를 가져왔으면 docker run 하기 전 TRTIS에 모델을 설정 해 줍시다.

모델 저장소 설정하기

일반적으로 추론을 하기 위해선 미리 학습된 모델이 필요합니다. TRTIS도 미리 모델을 설정해줘서 관리 및 실행을 할 수 있습니다.

TRTIS는 정해진 모델 폴더 양식이 따로 있습니다. 모델의 저장소는 아래와 같은 레이아웃 형태를 지켜야합니다. 후에, 로컬 서버에 모델과 레이아웃을 지켜준 폴더를 만들어주면, 도커로 run 할 때 docker의 -v 옵션을 통해서 컨테이너와 연결을 시켜 줍니다.

<model-repository-path>/
	<model-name>/
		[config.pbtxt]
		[<output-labels-file> ...]
		<version>/
			<model-definition-file>
		<version>/
			<model-definition-file>
		...
	<model-name>/
		[config.pbtxt]
		[<output-labels-file> ...]
		<version>/
			<model-definition-file>
		<version>/
			<model-definition-file>
	 	...
	...

예를 들어,

test_models/        <아무렇게나 지어주면 >
	EDSR/             <자기가 지정해주고 싶은 모델명>
		config.pbtxt		<무조건  이름을 지켜야함>
		1/              <version 아무렇게나 지어주면 >
			model.plan		<TensorRT의 확장자명은 plan, onnx는 onnx.. 이름은 무조건 model로 고정시켜야 >
		2/
			model.plan
		...
	...

모델 저장소 안에는 여러 모델 이름 폴더들이 있고 그 안에는 각 모델의 정보가 담긴 config.pbtxt 파일과 그 아래에는 그 모델의 버전 폴더가 있고 각 버전안에는 모델이 들어가 있습니다. 로컬 서버에 첨부된 test_models 폴더를 넣어줍니다.

config.pbtxt는 모델의 초기 설정과 같은 config 파일이고, 인풋 사이즈와 아웃풋 사이즈를 정해주고 이 모델이 TensorRT인지 Pytorch인지 Tensorflow인지 알려주면서, 배치사이즈 최대 크기는 몇으로 둬야 할지 등등 미리 정해줍니다.

참고로, 후에 docker run 할때 명령어 중 --strict-model-config=false 옵션을 사용하면, ONNX나 TensorFlow 모델에선 따로 config.pbtxt 파일을 제공할 필요가 없습니다. 여기선 TensorRT이므로 설정을 해주어야 합니다.

아래는 EDSR 모델 TensorRT의 config.pbtxt 파일 입니다.

platform: "tensorrt_plan"
max_batch_size: 1
input [
  {
    name: "input"
    data_type: TYPE_FP32
    dims: [ 3, 540, 960 ]
  }
]
output [
  {
    name: "output"
    data_type: TYPE_FP32
    dims: [ 3, 1080, 1920 ]
  }
]
dynamic_batching { }

name은 Pytorch에서 onnx를 만들때 넣은 input 이름을 넣어주면 되고 output도 마찬가지로 onnx 만들때의 output 이름을 넣어주면 됩니다. 데이터 타입은 TensorRT의 Input, Output의 데이터 타입을 넣어주면 되고, dims는 onnx를 만들때 shape를 넣어주면 됩니다. 같이 첨부된 EDSR 모델은 이미지 input이 960x540이고 output이 1920x1080이므로 dims를 위와 같이 작성하였습니다.

보다 자세한 model config 설정은 https://github.com/triton-inference-server/server/blob/master/docs/model_configuration.md 참고하시기 바랍니다.

dynamic_batching은 작업이 여러개 들어오면 동적으로 배치를 할당하여 더 빠르게 추론을 하는 것인데, max_batch_size가 1이면 이점을 가져갈순 없지만, max_batch_size가 2 이상일때 이점을 가져갈 수 있습니다. max_batch_size가 1이여도 오류가 따로 생기진 않으니 넣어줍시다.

보다 자세한 최적화 내용은 https://github.com/triton-inference-server/server/blob/master/docs/optimization.md 참고하시기 바랍니다. 자세한 모델 저장소 구조 설명은 https://github.com/triton-inference-server/server/blob/master/docs/model_repository.md 참고하시기 바랍니다.

TRTIS 서버 가동하기

모델 저장소 설정을 완료 하였으면, 이제 TRTIS를 가동해봅시다.

$ docker run --gpus=1 --rm -p 8000:8000 -p 8001:8001 -p 8002:8002 -v /blar_blar/test_models:/models nvcr.io/nvidia/tritonserver:21.04-py3 tritonserver --model-repository=/models

-v 옵션에서 자신의 모델 저장소를 컨테이너와 연결시켜서 트리톤 서버 옵션에 모델 저장소의 위치를 설정합니다. 같이 첨부되어 있는 test_models 폴더를 타겟으로 합니다.

-v ~/blar_blar/test_models:/models --model-repository=/models

위에는 --gpus=1로 설정되어있지만 --gpus=all 이나, --gpus=2나 --gpus="device=0,1,2,3" 등등을 사용해서 추가 작업 없이 Multi Gpu Inference를 사용할 수 있습니다. 여기서는 gpu를 한개만 사용해보겠습니다.

TRTIS 서버가 성공적으로 작동하면, 아래와 같이 마지막 세줄에는 이 문구가 나옵니다.

I0508 06:34:23.773345 1 grpc_server.cc:4028] Started GRPCInferenceService at 0.0.0.0:8001
I0508 06:34:23.773639 1 http_server.cc:2761] Started HTTPService at 0.0.0.0:8000
I0508 06:34:23.815116 1 http_server.cc:2780] Started Metrics Service at 0.0.0.0:8002

종료는 ctrl + c를 통해서 종료할 수 있습니다. nvidia-smi로 확인하면, 첫 번째 gpu에 모델이 올라간 모습을 확인 할수 있습니다.

[pjs102793@localhost ~]$ nvidia-smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 450.80.02    Driver Version: 450.80.02    CUDA Version: 11.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  A100-SXM4-40GB      On   | 00000000:07:00.0 Off |                    0 |
| N/A   31C    P0    58W / 400W |   2048MiB / 40537MiB |      0%      Default |
|                               |                      |             Disabled |
+-------------------------------+----------------------+----------------------+
...
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A     10451      C   tritonserver                     2045MiB |
+-----------------------------------------------------------------------------+

TRTIS 서버 성능 체크 및 TRTIS 클라이언트 설치 및 사용

TRTIS를 서버를 실행했으면 TRTIS 클라이언트를 통해서 추론을 해봅시다.

TRTIS 클라이언트도 따로 아래의 명령어로 TRTIS 클라이언트 도커 이미지를 pull 하고 컨테이너에 들어갑니다.

$ sudo docker pull nvcr.io/nvidia/tritonserver:21.04-py3-sdk
$ sudo docker run --rm -it --net=host nvcr.io/nvidia/tritonserver:21.04-py3-sdk

성공적으로 attach 하면 이 명령어를 통해서 성능을 확인해봅니다.

$ perf_analyzer -m EDSR -u localhost:8001 -i grpc --concurrency-range 1:8 -f result.csv

-m 옵션은 서버의 모델명을 적어줍니다. test_models 하위에 있는 폴더 이름을 의미합니다. -u 는 서버의 IP를 정하고 포트번호를 정해줍니다. http는 8000번 gRPC는 8001 번으로 설정하였고, 여기서는 8001번인 gRPC 프로토콜을 이용해서 접속하겠습니다. -i 는 defaults는 http고 gRPC 통신을 사용하기 위해 grpc를 넣어주었습니다. --concureency-range는 말 그대로 동시 접속을 의미하고 1:8은 동시접속 1~8까지 테스팅을 하겠다는 의미입니다. -f 옵션은 성능 분석 결과를 csv로 저장하는 옵션입니다. 보다 자세한 옵션은 -h 옵션을 통해 확인하시기 바랍니다.

참고로 --streaming 옵션도 있는데 gRPC 환경에서만 이 옵션을 사용할 수 있고, 거의 모든 상황에서 streaming 옵션이 더 좋은 성능을 제공하기 때문에, --streaming 옵션을 사용하시는게 좋습니다. 여기서는 streaming 옵션을 사용하지 않겠습니다.

작동을 마치게 되면 마지막에 result가 나옵니다. 아래에

Concurrency: 1, throughput: 18.2 infer/sec, latency 55233 usec
Concurrency: 2, throughput: 35 infer/sec, latency 56711 usec
Concurrency: 3, throughput: 52.8 infer/sec, latency 56981 usec
Concurrency: 4, throughput: 49.8 infer/sec, latency 80075 usec
Concurrency: 5, throughput: 55.4 infer/sec, latency 90266 usec
Concurrency: 6, throughput: 59.6 infer/sec, latency 101349 usec
Concurrency: 7, throughput: 56.2 infer/sec, latency 124410 usec
Concurrency: 8, throughput: 55.6 infer/sec, latency 143304 usec

EDSR 모델은 동시 접속이 6일때 가장 좋은 frame을 보여주었습니다. 그 이상은 오히려 추론 성능이 좋아지지 않고 latency만 증가하고 있습니다.

frame을 중요시하면 동시접속 6이 효율적이고 latency를 중요시하면 동시접속 3이 효율적인 것을 확인 할 수 있습니다.

이처럼 성능 분석기로 자신의 상황에 맞게 효율이 좋은 상황을 테스팅해 볼 수 있습니다.

이제 TRTIS 클라이언트로 이미지를 넣고 EDSR 모델에 통과 시켜 봅시다. 첨부된 edsr_image_client.py 를 실행합니다.

root@localhost:/workspace/junseo# python edsr_image_client.py -m EDSR -u localhost:8001 -i grpc --streaming images
Request 1, batch size 1
Request 2, batch size 1
Request 3, batch size 1
Done!

이 코드는 전체적으로 성능 분석기와 옵션이 거의 유사합니다. 맨 마지막에는 단일 이미지나, 이미지들이 들어있는 폴더를 지정해 줄 수 있습니다. images 폴더 내에는 3장의 이미지가 있고 실행하면 <model_name>_sr 폴더가 생기고 그 안에 <image_file_name>_sr 파일들이 생성됩니다.

이미지는 960x540 크기인 이미지만 넣을수 있습니다. output은 scale에 따라 다르고, 이 모델은 scale이 2이므로 output 크기는 1920x1080 크기로 생성이 됩니다.

마무리

여기까지 TensorRT EDSR 모델이 담긴 TRTIS 서버를 구동하여 이미지를 추론하였습니다. TRTIS Github Document에 설명이 자세하게 되어있어서 모르는 점은 https://github.com/triton-inference-server/server 에 참고하셔서 확인하거나, 궁금한 점이나 이 문서에 잘못된 정보가 있으면, bpjs102793@gmail.com 에 메일로 보내주세요. 참고하여 적극적으로 반영하겠습니다. 감사합니다.

3개의 댓글

comment-user-thumbnail
2021년 5월 26일

잘 읽고 갑니다. 어려우니 천천히 읽어야겠네요

답글 달기
comment-user-thumbnail
2021년 7월 7일

세미나 기대하겠습니다 👍

답글 달기
comment-user-thumbnail
2021년 8월 2일

잘 보고 갑니다. ^^

답글 달기