1. TensorRT 란?
2. TensorRT 설치하기
3. 여러 프레임워크에서 TensorRT 사용하기
1. TensorRT 란?
TensorRT는 학습된 딥러닝 모델을 최적화하여 NVIDIA GPU 상에서의 추론 속도를 수배 ~ 수십배 까지 향상시켜 딥러닝 서비스를 개선하는데 도움을 줄 수 있는 모델 최적화 엔진이다. 흔히들 우리가 접하는 Caffe, Pytorch, TensorFlow, PaddlePaddle 등의 딥러닝 프레임워크를 통해 짜여진 딥러닝 모델을 TensorRT를 통해 모델을 최적화하여 TESLA T4 , JETSON TX2, TESLA V100 등의 NVIDIA GPU 플랫폼에 아름답게 싣는 것이다.
또한, TensorRT는 NVIDIA GPU 연산에 적합한 최적화 기법들을 이용하여 모델을 최적화하는 Optimizer 와 다양한 GPU에서 모델 연산을 수행하는 Runtime Engine 을 포함한다. TensorRT는 대부분의 딥러닝 프레임워크에서 학습된 모델을 지원하며, 최적의 딥러닝 모델 가속화를 지원한다.
TensorRT의 장점은 C++ 및 Python 을 API 레벨에서 지원하고 있기 때문에 GPU 프로그래밍인 CUDA 지식이 별로 없어도 딥러닝 분야의 개발자들이 쉽게 사용할 수 있다. 또한 GPU가 지원하는 활용 가능한 최적의 연산 자원을 자동으로 사용할 수 있도록 Runtime binary 를 빌드해주기 때문에 Latency 및 Throughput 을 쉽게 향상시킬 수 있고, 이를 통해 딥러닝 응용프로그램 및 서비스의 효율적인 실행이 가능하다. 또한 흔히들 알고있는 Convolution Layer, ReLU 등의 Layer 뿐 만 아니라 다양한 Layer 및 연산에 대하여 Customization 할 수 있는 방법론을 제공(다소 어려운 감이 있지만 ...)하여 개발자들이 유연하게 TensorRT를 활용할 수 있도록 하고 있다.
TensorRT는 NVIDIA 플랫폼에서 최적의 추론 성능을 낼 수 있도록 Network compression, Network optimization, GPU 최적화 기술들을 딥러닝 모델에 자동 적용해준다. 딥러닝 가속화 기법들은 다음과 같다.
- Quantization & Precision Calibration (양자화 및 정밀도 캘리브레이션)
딥러닝의 학습 및 추론에서 정밀도(Precision)를 낮추는 일은 거의 일반적인 방법이 되었다. 낮은 정밀도를 가지는 신경망일수록 데이터의 크기 및 가중치들의 bit 수가 작기 때문에 더 빠르고 효율적인 연산이 가능하다. 이를 위한 양자화 기법중 TensorRT는 Symmetric Linear Quantization 을 사용하고 있으며, 이를 통하여 딥러닝 프레임워크의 일반적인 FP32의 데이터를 FP16 및 INT8 의 데이터 타입으로 정밀도를 낮출 수 있다.
일반적으로 FP16 의 데이터 타입으로 정밀도를 낮추는 것은 모델 정확도에 큰 영향을 주지는 않지만, INT8의 데이터 타입으로 정밀도를 낮추는 것은 모델 정확도에 영향을 주기 때문에 추가적으로 캘리브레이션 작업이 필요하다. 이를 위해 TensorRT 에서는 EntropyCalibrator, EntropyCalibrator2, MinMaxCalibrator 를 지원하고 있으며, 이를 활용하여 양자화 시 가중치 및 intermediate tensor 들의 정보의 손실을 최소화 할 수 있다.
- Graph Optimization (그래프 최적화)
일반적으로 그래프 최적화는 딥러닝 신경망에서 사용되는 Primitive 연산 형태, Compound 연산 형태의 그래프 노드들을 각 플랫폼에 최적화된 코드들로 구성하기 위하여 사용된다. TensorRT 에서는 이를 기반으로 Layer Fusion 방식과 Tensor Fusion 방식을 동시에 적용하고 있다. Layer Fusion은 Vertical Layer Fusion, Horizontal Layer Fusion이 적용되고,또한 Tensor Fusion이 적용되어 모델 그래프를 단순화 시켜주어 모델의 Layer 수가 크게 감소하게 된다. 실제로 TensorRT를 사용하여 ResNet, MobileNet 과 같은 백본 신경망들을 최적화 하면 기존 노드 수가 몇 십배 까지 줄어드는 효과를 보았었다.
- Kernel Auto-tuning (커널 자동 튜닝)
TensorRT 는 NVIDIA의 다양한 플랫폼 및 아키텍쳐에 맞는 Runtime 생성을 도와준다. 각 제품들은 CUDA engine 의 갯수, 아키텍쳐, 메모리 그리고 Serialized engine 포함 여부에 따라 최적화 된 커널이 다르기 때문에 이를 TensorRT Runtime engine build 시 선택적으로 수행하여 최적의 engine binary 생성을 돕게된다.
- Dynamic Tensor Memory & Multi-stream execution (동적 텐서 메모리 및 멀티 스트림 실행)
그 외에도 메모리 관리를 통하여 footprint 를 줄여 재사용 할 수 있도록 도와주는 Dynamic tensor memory 기능이 존재하며, CUDA Stream 기술을 이용하여 multiple input stream 의 스케쥴링을 통해 병렬 효율을 그대화 할 수 있는 Multi-stream execution 기능도 존재한다.
이러한 가속화 기술들을 이용하여 TensorRT는 "속도 향상" 이라는 결과를 얻을 수 있게 된다. 기본적으로 ResNet50 기준으로 볼 때 동일한 GPU 에서 TensorRT 를 사용하는 것만으로도 대략 8배 이상의 성능 향상 효과가 있다고 한다. 필자도 실제로 모델을 최적화 시켰을 때 Pytorch 나 TensorFlow 모델의 추론 속도에 비해 TensorRT Engine 화 하였을 때의 모델 추론 속도가 적게는 5배에서 많게는 10배 까지 속도 향상 결과를 맛봤다. 모델 백본에 따라 성능 차이는 있겠지만 딥러닝 서비스를 배포하기 위해 속도 측면에서 TensorRT가 핵심적인 역할을 수행할 수 있었다.
2. TensorRT 설치하기
TensorRT 는 필자의 오래전 경험에 의하면 Anaconda 에서는 실행하기 힘들다. Anaconda 와 같은 가상환경을 사용할 경우 TensorRT 가 설치된 곳을 제어할 수 없기 때문에 Anaconda 에서 TensorRT 의 실행은 지양한다.
보통 Nvidia Docker 에서 TensorRT Container 를 사용하거나, 그냥 쌩 로컬 환경에 TensorRT를 설치하는 것을 추천한다. 설치법은 이미 많은 분들이 포스팅 했을 거라고 생각한다... 하지만 간략히 써보도록 하겠다. 어렵진 않다. 도커를 사용한다면 문제 없겠지만, 로컬환경에 설치할 때 제일 중요한 건 환경 셋팅 인 듯 하다. 주요 포스팅은 다음을 참고하길 바란다. 아래 2.1 절과 2.2 에서는 간략히만 설명한다.
- (Linux) Docker Container 를 이용한 TensorRT 설치하기
- (Linux) 로컬 환경에 TensorRT 설치하기
- (Windows) 로컬환경에 TensorRT 설치하기
2.1 NVIDIA Docker 이용하여 TensorRT 설치하기
사실 이게 제일 깔끔한 방법이다. 자신의 CUDA 환경을 확인하여 적절한 컨테이너를 선정하여 설치하기 바란다.
NVIDIA Docker 가 우선적으로 설치되어야한다.
TensorRT Container Release Notes :
https://docs.nvidia.com/deeplearning/sdk/tensorrt-container-release-notes/running.html
* nvidia-docker 명령어 중 --rm 이라는 명령어는 도커 컨테이너를 종료하게 되면 생성한 컨테이너도 삭제되므로 주의
2.2 로컬환경에 TensorRT 설치하기
Linux 환경에서 TensorRT 7.0.0 (.tar)기준 설치 방법은 다음과 같다.
Requirements
- PyCUDA 설치
pip install 'pycuda>=2019.1.1'
* TensorRT 예제 실행 도중 PyCUDA 관련 에러가 날 경우, pip uninstall pycuda 를 통해 삭제하고 위와 같이 다시 다운할 것
- CUDA 9.0 / 10.0 / 10.2
- cuDNN 7.6.5
- TensorFlow 1.14.0 (이 버전으로 예제 코드가 테스트 되었다고 한다.)
- Pytorch 1.3.0 (1.2.0 도 가능)
2.2.1 TensorRT 7.0.0 다운로드 (.tar) :
https://developer.nvidia.com/tensorrt
2.2.2 압축풀기
tar xzvf TensorRT-7.x.x.x ~~~
2.2.3 환경 변수 추가
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<다운로드경로/TensorRT_폴더이름/lib>
2.2.4 python 패키지 설치 (python2.x 이면 pip2 ~ python3.x 이면 pip3 ~)
cd TensorRT-${version}/python
sudo pip2 install tensorrt-*-cp27-none-linux_x86_64.whl
sudo pip3 install tensorrt-*-cp3x-none-linux_x86_64.whl
2.2.5 UFF 패키지 설치 (python2.x 이면 pip2 ~ python3.x 이면 pip3 ~)
cd TensorRT-${version}/uff
sudo pip2 install uff-0.6.5-py2.py3-none-any.whl
sudo pip3 install uff-0.6.5-py2.py3-none-any.whl
아래와 같이 입력했을 때 경로가 뜨면 성공
which convert-to-uff
2.2.6 graphsurgeon 패키지 설치 (python2.x 이면 pip2 ~ python3.x 이면 pip3 ~)
cd TensorRT-${version}/graphsurgeon
sudo pip2 install graphsurgeon-0.4.1-py2.py3-none-any.whl
sudo pip3 install graphsurgeon-0.4.1-py2.py3-none-any.whl
3. 여러 프레임워크에서 TensorRT 사용하기
TensorRT는 Keras 모델을 이용하여 TensorFlow pb 를 만들고 Freeze 시켜 TensorRT 엔진을 생성할 수도 있고, TensorFlow 모델을 이용하여 Freeze 된 pb 파일을 만든 뒤 uff parser 를 통해 TensorRT 엔진을 생성할 수 도 있고, Caffe 모델을 이용하여 TensorRT 엔진을 만들 수도 있고, Pytorch 모델을 Onnx 모델로 만든 뒤 TensorRT 엔진을 생성할 수도 있다. 이렇듯 다양한 여러 프레임워크에서 TensorRT 를 이용하여 최적화가 가능하다. 본 포스팅에서는 TensorFlow 를 이용한 TensorRT, Pytorch 를 이용한 TensorRT 만을 다룬다.
- TensorFlow 를 이용한 TensorRT 사용하기
TensorRT 자체를 이용하여 엔진을 만들 수도 있지만 TensorFlow 1.7 버전 부터 포함된 TensorRT(TF-TRT)를 사용하여 엔진을 만들 수도 있다. 이 때 모델을 최적화 할 때 지원하지 않는 레이어가 있다면 TensorRT 에서는 에러를 내뿜고 더이상 최적화를 진행하지 않지만, TensorFlow에 내장된 TF-TRT 는 지원되지 않는 레이어가 있다 한들, 그를 무시하고 나머지를 최적화 시켜버리기 때문에 TensorRT 효과를 제대로 누릴 수 없다는 점이 있다. (TensorFlow 1.14 기준! / 2.0 버전은 바뀌었을지도 모른다는 생각이...) 그래서 본 포스팅에서는 TF-TRT 는 다루지 않는다.
1. ckpt + pbtxt 를 이용한 pb 파일 생성하기
def main():
freeze_graph.freeze_graph('/graph.pbtxt', "", False,
'/checkpoint.ckpt', 'output_node_name',
"save/restore_all", "save/Const",
'frozen.pb', True, "")
print('done.')
if __name__ == '__main__':
main()
TensorFlow 모델을 TensorRT Engine 화 하기 위해서는 ckpt + pbtxt 의 조합을 통해 freeze 된 pb 파일을 생성할 수 있다. 이 때 ckpt 는 학습이 완료된 가중치여야 하며, pbtxt 는 pb 를 읽을 수 있는 이진파일을 뜻한다. 이밖에도 학습된 pb 를 TensorFlow 에 내장되어있는 freeze_graph 를 이용하여 frozen pb 를 생성할 수도 있다.
또한 output_node_name 을 적어주는 것이 중요하다. 자신이 만든 모델이라면 output name 을 지정하여 모델을 생성 할 수 있지만, 타인이 만든 모델이라면 output name 이 지정되어있지 않을 수도 있어서 output shape 을 보고 추론하거나, graph viewer 를 보고 일일이 추론해야하기 때문에 어려움이 존재한다. 어디서부터 어디까지 freeze 할 것 인지가 관건이기 때문에 output node 를 찾는 것은 중요하다.
* graph viewer 는 TensorBoard 또는 netron 을 추천한다. https://lutzroeder.github.io/netron/
2. uff parser 를 이용하여 TensorRT Engine 을 생성할 수 있도록 uff 파일 만들기
TensorRT 설치 할 때 같이 설치했던 convert-to-uff 패키지를 이용하여 uff 파일을 만들 수 있다.
정상적으로 output node 를 인식하여 freeze 된 pb 파일을 만들었으며, 모두 TensorRT 7.0 버전에서 지원되는 레이어만을 그래프가 포함하고 있다면 문제없이 uff 파일이 생성될 것이다.
convert-to-uff frozen_inference_graph.pb
변환 이전에 인식된 노드를 확인하고 싶다면 아래와 같이 입력
convert-to-uff frozen_inference_graph.pb -l
3. uff 파일을 TensorRT engine 파일로 변환
model_file = "frozen.uff"
with trt.Builder(TRT_LOGGER) as builder, builder.create_network() as network, trt.UffParser() as parser:
parser.register_input("input", (B, H, W, C))
parser.register_output("output")
parser.parse(model_file, network)
4. engine build (Python or C++)
https://docs.nvidia.com/deeplearning/sdk/tensorrt-developer-guide/index.html#python_topics
- Pytorch 모델을 Onnx로 변환하고 TensorRT 사용하기
Pytorch 프레임워크를 통하여 학습된 모델을 Onnx로 변환하고, Onnx 모델을 TensorRT Engine 으로 변환하는 방법에 대해 다룬다. Onnx 를 통해 TensorRT Engine 으로 변환할 수도 있지만 바로 Torch to TensorRT 로도 갈 수 있다. 아래 링크를 참고하길 바란다.
https://github.com/NVIDIA-AI-IOT/torch2trt
1. Onnx 생성하기
Onnx 모델을 생성할 때는 Pytorch 모델에 입력되는 input shape 과 동일해야한다. shape 만 맞춰준다면 어떠한 랜덤 값이 들어가도 무방하다. torch.onnx.export 시 중요한 것은 파이토치 모델, 입력 값 만 있으면 Onnx 모델을 만들 수 있다. torch.onnx.export 함수는 기본적으로 scripting 이 아닌 tracing 을 사용하기 때문에 example input 을 넣어주어야 한다.
때에 따라 필요한 옵션을 추가하여 Onnx 모델을 생성 할 수 있다. 이 때 verbose=False 라는 옵션을 추가하면, 어떤 노드들이 Onnx 모델을 위해 인식되었는지 로그를 띄울 수 있다.
import io
import numpy as np
from torch import nn
import torch.utils.model_zoo as model_zoo
import torch.onnx
import torch.nn as nn
import torch.nn.init as init
batch_size = 1
model.load_state_dict(torch.load(PATH))
torch_model.eval()
x = torch.randn(batch_size, 1, 224, 224, requires_grad=True)
torch_out = torch_model(x)
torch.onnx.export(torch_model, # 실행될 모델
x, # 모델 입력값 (튜플 또는 여러 입력값들도 가능)
"super_resolution.onnx", # 모델 저장 경로 (파일 또는 파일과 유사한 객체 모두 가능)
export_params=True, # 모델 파일 안에 학습된 모델 가중치를 저장할지의 여부
opset_version=10, # 모델을 변환할 때 사용할 ONNX 버전
do_constant_folding=True, # 최적하시 상수폴딩을 사용할지의 여부
input_names = ['input'], # 모델의 입력값을 가리키는 이름
output_names = ['output'], # 모델의 출력값을 가리키는 이름
dynamic_axes={'input' : {0 : 'batch_size'}, # 가변적인 길이를 가진 차원
'output' : {0 : 'batch_size'}})
2. Onnx 를 이용하여 TensorRT Engine 생성하기
TensorRT Sample 에 포함된 onnx_to_tensorrt.py 예제이다. 이보다 확실한 코드는 못봤다. build_engine 함수에서 내뿜는 engine 을 리턴받아 engine 을 build 하기만 하면 된다.
def get_engine(onnx_file_path, engine_file_path=""):
def build_engine():
with trt.Builder(TRT_LOGGER) as builder, builder.create_network() as network, trt.OnnxParser(network, TRT_LOGGER) as parser:
builder.max_workspace_size = 1 << 30 # 1GB
builder.max_batch_size = 1
if not os.path.exists(onnx_file_path):
print('ONNX file {} not found, please run yolov3_to_onnx.py first to generate it.'.format(onnx_file_path))
exit(0)
print('Loading ONNX file from path {}...'.format(onnx_file_path))
with open(onnx_file_path, 'rb') as model:
print('Beginning ONNX file parsing')
parser.parse(model.read())
print('Completed parsing of ONNX file')
print('Building an engine from file {}; this may take a while...'.format(onnx_file_path))
engine = builder.build_cuda_engine(network)
print("Completed creating Engine")
with open(engine_file_path, "wb") as f:
f.write(engine.serialize())
return engine
if os.path.exists(engine_file_path):
# If a serialized engine exists, use it instead of building an engine.
print("Reading engine from file {}".format(engine_file_path))
with open(engine_file_path, "rb") as f, trt.Runtime(TRT_LOGGER) as runtime:
return runtime.deserialize_cuda_engine(f.read())
else:
return build_engine()
* 혹시라도 잘못된 정보나 고칠 사항이 있다면 언제든지 댓글 부탁드립니다.
참고자료 1 : https://blogs.nvidia.co.kr/2020/02/19/nvidia-tensor-rt/
참고자료 2 : https://hiseon.me/data-analytics/tensorflow/tensorflow-tensorrt/
참고자료 3 : https://gusrb.tistory.com/21
참고자료 4 : https://docs.nvidia.com/deeplearning/sdk/tensorrt-developer-guide/index.html#python_topics
참고자료 5 : https://tutorials.pytorch.kr/advanced/super_resolution_with_onnxruntime.html
참고자료 6 : https://gaussian37.github.io/dl-pytorch-deploy/
참고자료 7 : https://yunmorning.tistory.com/17
참고자료 8 : https://medium.com/@fanzongshaoxing/accelerate-pytorch-model-with-tensorrt-via-onnx-d5b5164b369
'AI Development > TensorRT' 카테고리의 다른 글
[TensorRT] TensorRT 및 Tensor Core에서 NCHW vs NHWC 형식의 성능 차이 (1) | 2020.04.29 |
---|---|
[TensorRT] 지원되는 연산자 목록 (2020.04.29 기준) (0) | 2020.04.29 |
[TensorRT] AttributeError: 'NoneType' object has no attribute 'serialize' (2) | 2020.03.12 |
[TensorRT] Windows + TensorRT 설치하기 (4) | 2019.11.11 |
[TensorRT] Yolo v3 to onnx (2) | 2019.10.08 |