Skip to content

Commit 45232ba

Browse files
committed
Replace C++ API by Python API for TensorRT
1 parent 4895eff commit 45232ba

File tree

6 files changed

+154
-395
lines changed

6 files changed

+154
-395
lines changed

PyTorch-ONNX-TensorRT/CMakeLists.txt

Lines changed: 0 additions & 16 deletions
This file was deleted.

PyTorch-ONNX-TensorRT/FindTensorRT.cmake

Lines changed: 0 additions & 87 deletions
This file was deleted.

PyTorch-ONNX-TensorRT/README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
# How to convert a model from PyTorch to TensorRT and speed up inference
22
The blog post is here: https://www.learnopencv.com/how-to-convert-a-model-from-pytorch-to-tensorrt-and-speed-up-inference/
33

4-
To run Python part:
4+
To run PyTorch part:
55
```shell script
66
python3 -m pip install -r requirements.txt
77
python3 pytorch_model.py
88
```
99

10-
To run C++ part:
11-
```shell script
12-
mkdir build
13-
cd build
14-
cmake -DOpenCV_DIR=[path-to-opencv-build] -DTensorRT_DIR=[path-to-tensorrt] ..
15-
make -j8
16-
trt_sample[.exe] resnet50.onnx turkish_coffee.jpg
17-
```
10+
To run TensorRT part:
11+
1. Download and install NVIDIA CUDA 10.0 or later following by official instruction: [link](https://developer.nvidia.com/cuda-10.0-download-archive)
12+
2. Download and extract CuDNN library for your CUDA version (login required): [link](https://developer.nvidia.com/rdp/cudnn-download)
13+
3. Download and extract NVIDIA TensorRT library for your CUDA version (login required):
14+
[link](https://developer.nvidia.com/nvidia-tensorrt-6x-download).
15+
The minimum required version is 6.0.1.5.
16+
Please follow the [Installation Guide](https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html) for your system and don't forget to install Python's part
17+
4. Add the absolute path to CUDA, TensorRT, CuDNN libs to the environment variable ```PATH``` or ```LD_LIBRARY_PATH```
18+
5. Install [PyCUDA](https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html#installing-pycuda)
1819

1920
# AI Courses by OpenCV
2021

Lines changed: 68 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,79 @@
11
import cv2
22
import onnx
33
import torch
4-
from albumentations import (
5-
Compose,
6-
Resize,
7-
)
4+
from albumentations import (Compose,Resize,)
85
from albumentations.augmentations.transforms import Normalize
96
from albumentations.pytorch.transforms import ToTensor
107
from torchvision import models
118

12-
# load pre-trained model ------------------------------------------------------
13-
model = models.resnet50(pretrained=True)
149

15-
# preprocessing stage ---------------------------------------------------------
16-
# transformations for the input data
17-
transforms = Compose(
18-
[
10+
def preprocess_image(img_path):
11+
# transformations for the input data
12+
transforms = Compose([
1913
Resize(224, 224, interpolation=cv2.INTER_NEAREST),
2014
Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
2115
ToTensor(),
22-
],
23-
)
24-
25-
# read input image
26-
input_img = cv2.imread("turkish_coffee.jpg")
27-
# do transformations
28-
input_data = transforms(image=input_img)["image"]
29-
# prepare batch
30-
batch_data = torch.unsqueeze(input_data, 0).cuda()
31-
32-
# inference stage -------------------------------------------------------------
33-
model.eval()
34-
model.cuda()
35-
output_data = model(batch_data)
36-
37-
# post-processing stage -------------------------------------------------------
38-
# get class names
39-
with open("imagenet_classes.txt") as f:
40-
classes = [line.strip() for line in f.readlines()]
41-
# calculate human-readable value by softmax
42-
confidences = torch.nn.functional.softmax(output_data, dim=1)[0] * 100
43-
# find top predicted classes
44-
_, indices = torch.sort(output_data, descending=True)
45-
i = 0
46-
# print the top classes predicted by the model
47-
while confidences[indices[0][i]] > 0.5:
48-
class_idx = indices[0][i]
49-
print(
50-
"class:",
51-
classes[class_idx],
52-
", confidence:",
53-
confidences[class_idx].item(),
54-
"%, index:",
55-
class_idx.item(),
56-
)
57-
i += 1
58-
59-
# convert to ONNX -------------------------------------------------------------
60-
onnx_filename = "resnet50.onnx"
61-
torch.onnx.export(
62-
model,
63-
batch_data,
64-
onnx_filename,
65-
input_names=["input"],
66-
output_names=["output"],
67-
export_params=True,
68-
)
69-
70-
onnx_model = onnx.load(onnx_filename)
71-
# check that the model converted fine
72-
onnx.checker.check_model(onnx_model)
73-
74-
print("Model was successfully converted to ONNX format.")
75-
print("It was saved to", onnx_filename)
16+
])
17+
18+
# read input image
19+
input_img = cv2.imread(img_path)
20+
# do transformations
21+
input_data = transforms(image=input_img)["image"]
22+
# prepare batch
23+
batch_data = torch.unsqueeze(input_data, 0)
24+
25+
return batch_data
26+
27+
28+
def postprocess(output_data):
29+
# get class names
30+
with open("imagenet_classes.txt") as f:
31+
classes = [line.strip() for line in f.readlines()]
32+
# calculate human-readable value by softmax
33+
confidences = torch.nn.functional.softmax(output_data, dim=1)[0] * 100
34+
# find top predicted classes
35+
_, indices = torch.sort(output_data, descending=True)
36+
i = 0
37+
# print the top classes predicted by the model
38+
while confidences[indices[0][i]] > 0.5:
39+
class_idx = indices[0][i]
40+
print(
41+
"class:",
42+
classes[class_idx],
43+
", confidence:",
44+
confidences[class_idx].item(),
45+
"%, index:",
46+
class_idx.item(),
47+
)
48+
i += 1
49+
50+
51+
def main():
52+
# load pre-trained model -------------------------------------------------------------------------------------------
53+
model = models.resnet50(pretrained=True)
54+
55+
# preprocessing stage ----------------------------------------------------------------------------------------------
56+
input = preprocess_image("turkish_coffee.jpg").cuda()
57+
58+
# inference stage --------------------------------------------------------------------------------------------------
59+
model.eval()
60+
model.cuda()
61+
output = model(input)
62+
63+
# post-processing stage --------------------------------------------------------------------------------------------
64+
postprocess(output)
65+
66+
# convert to ONNX --------------------------------------------------------------------------------------------------
67+
ONNX_FILE_PATH = "resnet50.onnx"
68+
torch.onnx.export(model, input, ONNX_FILE_PATH, input_names=["input"], output_names=["output"], export_params=True)
69+
70+
onnx_model = onnx.load(ONNX_FILE_PATH)
71+
# check that the model converted fine
72+
onnx.checker.check_model(onnx_model)
73+
74+
print("Model was successfully converted to ONNX format.")
75+
print("It was saved to", ONNX_FILE_PATH)
76+
77+
78+
if __name__ == '__main__':
79+
main()
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from pytorch_model import preprocess_image, postprocess
2+
import torch
3+
import pycuda.driver as cuda
4+
import pycuda.autoinit
5+
import numpy as np
6+
import tensorrt as trt
7+
8+
9+
ONNX_FILE_PATH = "resnet50.onnx"
10+
# logger to capture errors, warnings, and other information during the build and inference phases
11+
TRT_LOGGER = trt.Logger()
12+
13+
14+
def build_engine(onnx_file_path):
15+
# initialize TensorRT engine and parse ONNX model
16+
builder = trt.Builder(TRT_LOGGER)
17+
network = builder.create_network()
18+
parser = trt.OnnxParser(network, TRT_LOGGER)
19+
20+
# allow TensorRT to use up to 1GB of GPU memory for tactic selection
21+
builder.max_workspace_size = 1 << 30
22+
# we have only one image in batch
23+
builder.max_batch_size = 1
24+
# use FP16 mode if possible
25+
if builder.platform_has_fast_fp16:
26+
builder.fp16_mode = True
27+
28+
# parse ONNX
29+
with open(onnx_file_path, 'rb') as model:
30+
print('Beginning ONNX file parsing')
31+
parser.parse(model.read())
32+
print('Completed parsing of ONNX file')
33+
34+
# generate TensorRT engine optimized for the target platform
35+
print('Building an engine...')
36+
engine = builder.build_cuda_engine(network)
37+
context = engine.create_execution_context()
38+
print("Completed creating Engine")
39+
return engine, context
40+
41+
42+
def main():
43+
# initialize TensorRT engine and parse ONNX model
44+
engine, context = build_engine(ONNX_FILE_PATH)
45+
# get sizes of input and output and allocate memory required for input data and for output data
46+
for binding in engine:
47+
if engine.binding_is_input(binding): # we expect only one input
48+
input_shape = engine.get_binding_shape(binding)
49+
input_size = trt.volume(input_shape) * engine.max_batch_size * np.dtype(np.float32).itemsize # in bytes
50+
device_input = cuda.mem_alloc(input_size)
51+
else: # and one output
52+
output_shape = engine.get_binding_shape(binding)
53+
# create page-locked memory buffers (i.e. won't be swapped to disk)
54+
host_output = cuda.pagelocked_empty(trt.volume(output_shape) * engine.max_batch_size, dtype=np.float32)
55+
device_output = cuda.mem_alloc(host_output.nbytes)
56+
57+
# Create a stream in which to copy inputs/outputs and run inference.
58+
stream = cuda.Stream()
59+
60+
61+
# preprocess input data
62+
host_input = np.array(preprocess_image("turkish_coffee.jpg").numpy(), dtype=np.float32, order='C')
63+
cuda.memcpy_htod_async(device_input, host_input, stream)
64+
65+
# run inference
66+
context.execute_async(bindings=[int(device_input), int(device_output)], stream_handle=stream.handle)
67+
cuda.memcpy_dtoh_async(host_output, device_output, stream)
68+
stream.synchronize()
69+
70+
# postprocess results
71+
output_data = torch.Tensor(host_output).reshape(engine.max_batch_size, output_shape[0])
72+
postprocess(output_data)
73+
74+
75+
if __name__ == '__main__':
76+
main()

0 commit comments

Comments
 (0)