NVIDIA TensorRT | NVIDIA Developerhttps://developer.nvidia.cn/zh-cn/tensorrtTensorRT详细入门指北,如果你还不了解TensorRT,过来看看吧! - 知乎好久不见各位!想我不? 经历了五一还有点后遗症,感觉还没有休息够,时间过得太快了啊啊啊。 希望大家也能及时调整工作状态,搞起来搞起来! 为了更方便地搞起来,早点进入状态。老潘为大家准备了TensorRT入门指…https://zhuanlan.zhihu.com/p/371239130如何使用TensorRT对训练好的PyTorch模型进行加速? - 知乎一.简介 TensorRT是Nvidia公司出的能加速模型推理的框架,其实就是让你训练的模型在测试阶段的速度加快,比如你的模型测试一张图片的速度是50ms,那么用tensorRT加速的话,可能只需要10ms。当然具体能加速多少也不…https://zhuanlan.zhihu.com/p/88318324较为详细的记录总结TensorRT的python接口的使用,环境配置,模型转换和静态动态模型推理_CaiDou的博客-CSDN博客_接口动态模型先来一段摘抄自网上的TensorRT介绍:TensorRT是英伟达针对自家平台做的加速包,TensorRT主要做了这么两件事情,来提升模型的运行速度。TensorRT支持INT8和FP16的计算。深度学习网络在训练时,通常使用 32 位或 16 位数据。TensorRT则在网络的推理时选用不这么高的精度,达到加速推断的目的。TensorRT对于网络结构进行了重构,把一些能够合并的运算合并在了一起,针对GPU的特性做了优化。现在大多数深度学习框架是没有针对GPU做过性能优化的,而英伟达,GPU的生https://blog.csdn.net/qq_36276587/article/details/113175314使用Python部署TensorRT_wq_0708的博客-CSDN博客_python安装 tensorrt windowsTensorRT构建enginePython API 与 C++ API1. 将TensorRT导入 Python程序2. 在Python中创建网络定义2.1. 使用Python API从头开始创建网络定义关于这个任务2.2. 在 Python 中使用解析器导入模型2.3. 使用Python从Caffe导入关于这个任务程序2.4. 使用 Python从TensorFlow导入关于这个任务程序2.5. 使用 Python从ONNX导入关于这个任务程序2.6. 从PyTorch和其他框架导入关于这个任务3. 用https://blog.csdn.net/wq_0708/article/details/121266031TensorRT7.0版本在Linux环境安装,以及安装python API接口,测试TensorRT中的测试用例_星空-CSDN博客#1 TensorRT 介绍##1.1. 认识TensorRTTensorRT是NVIDIA开发的高性能的深度学习推理SDK,它包括深度学习推理优化器和运行时的低延时和数据高吞吐量。TensorRT是有助于在NVIDIA图像处理单元(GPU)的高性能推理的C++库,旨在与TensorFlow、Caffe、Pytorch、MXNet等训练框架形成互补方式工作,从而使预训练的模型快速的在GPU上进行工作,生成结果。TensorRT是基于NVIDIA的并行编程模型CUDA构建的,TensorRT为深度学https://blog.csdn.net/weixin_41010198/article/details/107604593
Sample Support Guide :: NVIDIA Deep Learning TensorRT DocumentationThis Samples Support Guide provides an overview of all the supported TensorRT 8.2.0 Early Access (EA) samples included on GitHub and in the product package. The TensorRT samples specifically help in areas such as recommenders, machine comprehension, character recognition, image classification, and object detection.https://docs.nvidia.com/deeplearning/tensorrt/sample-support-guide/index.html#python_samples_sectionGetting Started with TensorRT — NVIDIA TensorRT Standard Python API Documentation 8.2.0 documentationhttps://docs.nvidia.com/deeplearning/tensorrt/api/python_api/gettingStarted.html
https://github.com/onnx/onnx-tensorrt/blob/master/docs/operators.mdhttps://github.com/onnx/onnx-tensorrt/blob/master/docs/operators.mdTensorRT/samples/python at master · NVIDIA/TensorRT · GitHubTensorRT is a C++ library for high performance inference on NVIDIA GPUs and deep learning accelerators. - TensorRT/samples/python at master · NVIDIA/TensorRThttps://github.com/NVIDIA/TensorRT/tree/master/samples/pythonGitHub - NVIDIA/Torch-TensorRT: PyTorch/TorchScript compiler for NVIDIA GPUs using TensorRTPyTorch/TorchScript compiler for NVIDIA GPUs using TensorRT - GitHub - NVIDIA/Torch-TensorRT: PyTorch/TorchScript compiler for NVIDIA GPUs using TensorRThttps://github.com/NVIDIA/Torch-TensorRTTensorRT是可以在NVIDIA各种GPU硬件平台下运行的一个C++推理框架,是半开源的。
1.tensorrt的版本信息
gtx 1080,centos:7.3,python:3.6.5,cudnn:7.6.1,cuda:9.0.176,torch:1.5.1+cu92,torchvision:0.6.1+cu92,onnx:1.8.1,onnx-simplifer:0.3.4,onnxoptimizer:0.2.5,tensorrt:7.0.0.11,pycuda:2019.1
tensorrt英伟达官方下载时能看到依赖的cuda版本,目前tensor7.0.0.11还支持cuda9.0,并且tensorrt 7.0还支持动态输入,但是在使用tensorrt时先安装pycuda,通常我们使用的都是tensorrt的python接口。在mmclas中可以onnx2tensorrt转成trt,再用test.py中的TensorRTClassifier跑前向,不过在test中的前向是通过dataloader的batch形式提供的,我跑的resnet的模型,如果转成onnx,用的是动态输入,即在bs,w和h三个维度都制定dynamic_export,onnxruntime可以正常推理,但是转成trt时,trt推理会出现问题,wh方向的动态不支持gap,但是使用onnx的静态输出,转成trt,trt推理时没问题的,在onnx2trt时,trt构建器那部分是自动默认的动态转换。
2.onnx的动态输入和tensorrt的动态输入
onnx若为动态输入,则tensorrt为动态输入,动态输入有两个维度,一个是batch维度,一个w和h维度,对onnx而言,若dynamic_export为False,则为静态输入,静态输入的bs可以大于1,但是w和h是固定的,但是bs在推理时和转onnx的bs是一致的,不一致在onnxruntime时会直接报错,
3.tensorrt capacity
tensorrt的c++和python接口几乎具有相同的功能,线下测试时也发现单纯就推理模块而言,速度也几乎一致,很推荐python接口。
tensorrt分为两个阶段,第一阶段需要离线的转成tensorrt的模型,针对目标gpu进行优化,第二阶段使用优化的模型来进行推理。
把模型转到tensort最常见的途径是使用onnx,并使用onnx parser来对网络进行定义,但是也可以使用tensorrt逐步构建定义层和接口,按照网络模型自己搭建也行,但是要把权重文件导到模型中。
调用推理时,必须在适当的位置设置输入和输出缓冲区,涉及到数据在cpu和gpu上的传输,一般预处理是在cpu上还是在gpu上做,也对速度有很大的影响。一般像是归一化等操作。
tensorrt有plugins接口允许应用提供tensort本身不支持的运算符的实现,tensorrt创建和注册的插件PluginRegistry在转换网络时由onnx parser获取。
tensorrt支持fp32,fp16,int8,bool和int32数据类型。当tensorrt选择cuda内核在网络中实现浮点算子时,默认是fp32,可以对整个网络做精度指定,也可以只对网络一部分对高精度指定。tensorrt支持浮点量化,其中浮点值被线性压缩并四舍五入为8位整数。
在优化网络是,tensorrt在内部执行转换(whc格式转换)以使用尽可能快的cuda内核,tensorrt根据定义时的输入尺寸,batch size, image size,可以将构建器配置为允许在运行时调整输入维度,需要指定每个输入的最小,最大尺寸,以及该范围的最优尺寸。tensorrt为每个配置文件创建一个优化引擎,选择适用于最小和最大范围内的所有尺寸且对于最优尺寸最快的cuda内核。
4.python api
以tensorrt的onnx_resnet50.py为例,这是个固定尺寸输入的例子:
import os
# This sample uses an ONNX ResNet50 Model to create a TensorRT Inference Engine
import random
import sys
import numpy as np
# This import causes pycuda to automatically manage CUDA context creation and cleanup.
import pycuda.autoinit
import tensorrt as trt
from PIL import Image
sys.path.insert(1, os.path.join(sys.path[0], ".."))
import common
class ModelData(object):
MODEL_PATH = "ResNet50.onnx"
INPUT_SHAPE = (3, 224, 224)
# We can convert TensorRT data types to numpy types with trt.nptype()
DTYPE = trt.float32
# You can set the logger severity higher to suppress messages (or lower to display more messages).
# 首先创建一个记录器,python接口绑定一个简单的记录器,它记录所有warning的消息到标准输出
TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
# The Onnx path is used for Onnx models.
def build_engine_onnx(model_file):
# 创建一个构建器
builder = trt.Builder(TRT_LOGGER)
# 创建构建器后,优化模型的第一步是创建网络定义,EXPLICIT_BATCH是为了使用onnx parser导入模型
network = builder.create_network(common.EXPLICIT_BATCH)
# 需要从onnxparser填充网络定义,创建一个onnx parser来填充网络
parser = trt.OnnxParser(network, TRT_LOGGER)
# Load the Onnx model and parse it in order to populate the TensorRT network.
# 读取模型文件并处理错误
with open(model_file, 'rb') as model:
if not parser.parse(model.read()):
print ('ERROR: Failed to parse the ONNX file.')
for error in range(parser.num_errors):
print (parser.get_error(error))
return None
# 创建构建配置,指定tensorrt应该如何优化
config = builder.create_builder_config()
# config这个接口有很多属性,你可以设置这些属性来控制tensorrt如何优化,一个重要的属性是
# 最大空间大小,max_workspace_size.层实现通常需要一个临时工作空间,并且此参数限制了网络
# 中任何层可以使用的最大大小,如果提供的工作空间不足,tensorrt可能无找到层的实现
config.max_workspace_size = common.GiB(1)
return builder.build_engine(network, config)
def load_normalized_test_case(test_image, pagelocked_buffer):
# Converts the input image to a CHW Numpy array
def normalize_image(image):
# Resize, antialias and transpose the image to CHW.
c, h, w = ModelData.INPUT_SHAPE
image_arr = np.asarray(image.resize((w, h), Image.ANTIALIAS)).transpose([2, 0, 1]).astype(trt.nptype(ModelData.DTYPE)).ravel()
# This particular ResNet50 model requires some preprocessing, specifically, mean normalization.
return (image_arr / 255.0 - 0.45) / 0.225
# Normalize the image and copy to pagelocked memory.
np.copyto(pagelocked_buffer, normalize_image(Image.open(test_image)))
return test_image
# This function is generalized for multiple inputs/outputs for full dimension networks.
# inputs and outputs are expected to be lists of HostDeviceMem objects.
def do_inference_v2(context, bindings, inputs, outputs, stream):
# Transfer input data to the GPU.
# 要执行推理时,必须为输入输出船体tensorrt缓冲区,为每个输入输出设置gpu缓冲区
[cuda.memcpy_htod_async(inp.device, inp.host, stream) for inp in inputs]
# Run inference.
# 开始推理
context.execute_async_v2(bindings=bindings, stream_handle=stream.handle)
# Transfer predictions back from the GPU.
#
[cuda.memcpy_dtoh_async(out.host, out.device, stream) for out in outputs]
# Synchronize the stream
# 去诶定内核完成后,使用标准的cuda同步机制
stream.synchronize()
# Return only the host outputs.
return [out.host for out in outputs]
def main():
# Set the data path to the directory that contains the trained models and test images for inference.
_, data_files = common.find_sample_data(description="Runs a ResNet50 network with a TensorRT inference engine.", subfolder="resnet50", find_files=["binoculars.jpeg", "reflex_camera.jpeg", "tabby_tiger_cat.jpg", ModelData.MODEL_PATH, "class_labels.txt"])
# Get test images, models and labels.
test_images = data_files[0:3]
onnx_model_file, labels_file = data_files[3:]
labels = open(labels_file, 'r').read().split('\n')
# Build a TensorRT engine.
engine = build_engine_onnx(onnx_model_file)
# Inference is the same regardless of which parser is used to build the engine, since the model architecture is the same.
# Allocate buffers and create a CUDA stream.
inputs, outputs, bindings, stream = common.allocate_buffers(engine)
# Contexts are used to perform inference.
# 引擎拥有优化的模型,但是执行推理需要额外的中间激活状态,通过执行上下文界面,
# 一个引擎可以有多个执行上下文,允许一组权重用于多个重叠的推理任务。
context = engine.create_execution_context()
# Load a normalized test case into the host input page-locked buffer.
test_image = random.choice(test_images)
test_case = load_normalized_test_case(test_image, inputs[0].host)
# Run the engine. The output will be a 1D tensor of length 1000, where each value represents the
# probability that the image corresponds to that label
trt_outputs = common.do_inference_v2(context, bindings=bindings, inputs=inputs, outputs=outputs, stream=stream)
# We use the highest probability as our prediction. Its index corresponds to the predicted label.
pred = labels[np.argmax(trt_outputs[0])]
if "_".join(pred.split()) in os.path.splitext(os.path.basename(test_case))[0]:
print("Correctly recognized " + test_case + " as " + pred)
else:
print("Incorrectly recognized " + test_case + " as " + pred)
if __name__ == '__main__':
main()
整个python接口的api,有在python中创建网络定义,使用onnx parser导入模型,最后构建引擎,因为直接使用onnx做输入文件,onnx转成tensorrt可以反序列化进行保存和读取,保存格式可以为.trt,但是通常我们先用onnx转成trt,再用tensorrt进行推理,最后是执行推理。
5.tensorrt是如何工作的?
通过builder创建的engine,一旦engine创建之后,则可以销毁builder,network,parser,build config,不影响engine的使用。
在创建tensorrt的接口,例如builder,runtime,必须要提供logger的继承。
tensorrt使用大量设备内存,即gpu可以直接访问的内存,而不是cpu的主机内存。构建阶段:tensorrt为timming layer实现分层设备内存,一些实现可能会消耗大量临时内存,尤其是使用大张量的情况,可以通过builder的maxworkspace来控制,默认是0,以便构建器不使用任何的临时空间。如果构建器发现由于空间不足而无法运行适合内核时,会发出一条logging信息来指示。但是即便空间较小,也需要为输入输出和权重创建buffer,tensorrt对操作系统为返回内部分配不是稳健的,有可能因为内存不足,kill掉tensorrt。在构建阶段,主机cpu内存中至少有两个权重的副本,来自原始网络的权重以及在构建引擎时作为引擎一部分包含的权重,此外,当tensorrt组合权重时(conv和bn的组合),将额外创建临时权重张量。运行阶段:tensorrt使用相对较少的主机cpu内存,但是使用大量的设备显存。引擎在反序列化时分配设备显存来存储模型权重,tensorrt加载模型时,由于序列化引擎几乎都是权重,因此它的大小非常接近权重所需的设备内存量。因此看trt的大小几乎等于加载时所需的模型显存。默认情况下,tensorrt直接从cuda分配设备显存。tensorrt的依赖项cudnn和cublas会占用大量的设备显存。
一般来说,tensorrt的对象不是线程安全的。
tensorrt builder使用timming去找到最快的cuda内核去实现给定的运算符,但是timming内核会受到噪声影响,比如gpu上运行的其他程序,gpu clock速度的波动等,因此在构建器的连续运行中,可能不会选择相同的实现。不过可以通过AlgorithmSelector接口轻质构建器为给顶层选择特定实现。
6. Advanced topics
为了减少构建时间,tensorrt创建了一个层时序缓存,以在构建器阶段保存层分析信息,它包括信息特定于目标构建器设备,cuda和tensorrt版本以及可以更改层实现的builderconfig参数。如果有其他层具有相同的输入输出张量和层参数,则tensorrt构建器会跳过分析并重复层的缓存结果,如何为查询到,则构建器会对改图层计时并更新缓存。其实在onnx时做onnx-simplifer,如果是想转到tensorrt中运行的话,意义不大,因为tensorrt在有了trt之后,是有自己的一套优化逻辑的,trt只是有onnx转过来的格式。
除了使用使用解析器,还可以通过网络定义api将网络直接定义到tensorrt中,每层权重已在主机内存中准备好在网络创建期间传递给tensorrt。下面是利用pytorch编码的模型后,用原生的state_dict,用tensorrt的api进行模型,把state_dict进行权重赋值。
# This file contains functions for training a PyTorch MNIST Model
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.autograd import Variable
import numpy as np
import os
from random import randint
# Network
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(1, 20, kernel_size=5)
self.conv2 = nn.Conv2d(20, 50, kernel_size=5)
self.fc1 = nn.Linear(800, 500)
self.fc2 = nn.Linear(500, 10)
def forward(self, x):
x = F.max_pool2d(self.conv1(x), kernel_size=2, stride=2)
x = F.max_pool2d(self.conv2(x), kernel_size=2, stride=2)
x = x.view(-1, 800)
x = F.relu(self.fc1(x))
x = self.fc2(x)
return F.log_softmax(x, dim=1)
class MnistModel(object):
def __init__(self):
self.batch_size = 64
self.test_batch_size = 100
self.learning_rate = 0.0025
self.sgd_momentum = 0.9
self.log_interval = 100
# Fetch MNIST data set.
self.train_loader = torch.utils.data.DataLoader(
datasets.MNIST('/tmp/mnist/data', train=True, download=True, transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=self.batch_size,
shuffle=True,
num_workers=1,
timeout=600)
self.test_loader = torch.utils.data.DataLoader(
datasets.MNIST('/tmp/mnist/data', train=False, transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])),
batch_size=self.test_batch_size,
shuffle=True,
num_workers=1,
timeout=600)
self.network = Net()
# Train the network for one or more epochs, validating after each epoch.
def learn(self, num_epochs=2):
# Train the network for a single epoch
def train(epoch):
self.network.train()
optimizer = optim.SGD(self.network.parameters(), lr=self.learning_rate, momentum=self.sgd_momentum)
for batch, (data, target) in enumerate(self.train_loader):
data, target = Variable(data), Variable(target)
optimizer.zero_grad()
output = self.network(data)
loss = F.nll_loss(output, target)
loss.backward()
optimizer.step()
if batch % self.log_interval == 0:
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(epoch, batch * len(data), len(self.train_loader.dataset), 100. * batch / len(self.train_loader), loss.data.item()))
# Test the network
def test(epoch):
self.network.eval()
test_loss = 0
correct = 0
for data, target in self.test_loader:
with torch.no_grad():
data, target = Variable(data), Variable(target)
output = self.network(data)
test_loss += F.nll_loss(output, target).data.item()
pred = output.data.max(1)[1]
correct += pred.eq(target.data).cpu().sum()
test_loss /= len(self.test_loader)
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(test_loss, correct, len(self.test_loader.dataset), 100. * correct / len(self.test_loader.dataset)))
for e in range(num_epochs):
train(e + 1)
test(e + 1)
def get_weights(self):
return self.network.state_dict()
def get_random_testcase(self):
data, target = next(iter(self.test_loader))
case_num = randint(0, len(data) - 1)
test_case = data.numpy()[case_num].ravel().astype(np.float32)
test_name = target.numpy()[case_num]
return test_case, test_name
import os
import sys
# This sample uses an MNIST PyTorch model to create a TensorRT Inference Engine
import model
import numpy as np
import pycuda.autoinit
import tensorrt as trt
sys.path.insert(1, os.path.join(sys.path[0], ".."))
import common
# You can set the logger severity higher to suppress messages (or lower to display more messages).
# 创建记录器
TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
# 保存一些关于模型的元数据
class ModelData(object):
INPUT_NAME = "data"
INPUT_SHAPE = (1, 1, 28, 28)
OUTPUT_NAME = "prob"
OUTPUT_SIZE = 10
DTYPE = trt.float32
def populate_network(network, weights):
# Configure the network layers based on the weights provided.
# 为网络创建输入张量,指定张量的名称、数据类型和尺寸
input_tensor = network.add_input(name=ModelData.INPUT_NAME, dtype=ModelData.DTYPE, shape=ModelData.INPUT_SHAPE)
# 添加一个卷积层,指定输入、输出图的数量,核尺寸,权重,尺寸和步长
conv1_w = weights['conv1.weight'].numpy()
conv1_b = weights['conv1.bias'].numpy()
conv1 = network.add_convolution(input=input_tensor, num_output_maps=20, kernel_shape=(5, 5), kernel=conv1_w, bias=conv1_b)
conv1.stride = (1, 1)
# 添加一个池化层,指定输入(前一个卷积层的输出),池化类型,窗口大小和步长
pool1 = network.add_pooling(input=conv1.get_output(0), type=trt.PoolingType.MAX, window_size=(2, 2))
pool1.stride = (2, 2)
# 添加下一对卷积核池化层
conv2_w = weights['conv2.weight'].numpy()
conv2_b = weights['conv2.bias'].numpy()
conv2 = network.add_convolution(pool1.get_output(0), 50, (5, 5), conv2_w, conv2_b)
conv2.stride = (1, 1)
pool2 = network.add_pooling(conv2.get_output(0), trt.PoolingType.MAX, (2, 2))
pool2.stride = (2, 2)
# 添加一个全连接层,指定输入、输出数量、内核和偏置权重
fc1_w = weights['fc1.weight'].numpy()
fc1_b = weights['fc1.bias'].numpy()
fc1 = network.add_fully_connected(input=pool2.get_output(0), num_outputs=500, kernel=fc1_w, bias=fc1_b)
# 添加relu激活层
relu1 = network.add_activation(input=fc1.get_output(0), type=trt.ActivationType.RELU)
# 添加最后的全连接层,并将该层的输出标记为整个网络的输出
fc2_w = weights['fc2.weight'].numpy()
fc2_b = weights['fc2.bias'].numpy()
fc2 = network.add_fully_connected(relu1.get_output(0), ModelData.OUTPUT_SIZE, fc2_w, fc2_b)
fc2.get_output(0).name = ModelData.OUTPUT_NAME
network.mark_output(tensor=fc2.get_output(0))
def build_engine(weights):
# For more information on TRT basics, refer to the introductory samples.
# 创建构建器和网络,config配置
builder = trt.Builder(TRT_LOGGER)
network = builder.create_network(common.EXPLICIT_BATCH)
config = builder.create_builder_config()
runtime = trt.Runtime(TRT_LOGGER)
config.max_workspace_size = common.GiB(1)
# Populate the network using weights from the PyTorch model.
# 利用tensorrt的api进行网络的构建,不使用onnx解析
populate_network(network, weights)
# Build and return an engine.
# 对模型利用config进行序列化
plan = builder.build_serialized_network(network, config)
return runtime.deserialize_cuda_engine(plan)
# Loads a random test case from pytorch's DataLoader
def load_random_test_case(model, pagelocked_buffer):
# Select an image at random to be the test case.
img, expected_output = model.get_random_testcase()
# Copy to the pagelocked input buffer
np.copyto(pagelocked_buffer, img)
return expected_output
def main():
common.add_help(description="Runs an MNIST network using a PyTorch model")
# Train the PyTorch model
# 定义一个pytorch模型并训练
mnist_model = model.MnistModel()
mnist_model.learn()
# 权重是从pytorch模型中导入的,导入的是很原始的state_dict,不是onnx
weights = mnist_model.get_weights()
# Do inference with TensorRT.
# 构建引擎
engine = build_engine(weights)
# Build an engine, allocate buffers and create a stream.
# For more information on buffer allocation, refer to the introductory samples.
inputs, outputs, bindings, stream = common.allocate_buffers(engine)
context = engine.create_execution_context()
case_num = load_random_test_case(mnist_model, pagelocked_buffer=inputs[0].host)
# For more information on performing inference, refer to the introductory samples.
# The common.do_inference function will return a list of outputs - we only have one in this case.
[output] = common.do_inference_v2(context, bindings=bindings, inputs=inputs, outputs=outputs, stream=stream)
pred = np.argmax(output)
print("Test Case: " + str(case_num))
print("Prediction: " + str(pred))
if __name__ == '__main__':
main()
tensorrt默认是32位精度,但是能用16位浮点和8位整数,使用较低的精度可以实现较少的内存并实现更快的计算。
explicit vs implicit batch,隐式batch推理是在tensorrt7.0之前的版本中使用的,每个张量都有一个隐式批处理维度,其实就是batch,w和h的batch维度,所有其他维度必须具有恒定长度,虽然现在已经弃用了,但是仍然会向后兼容,在显式批处理模式下,所有的维度都是显式并且是动态的,他们的长度可以在执行时改变,动态尺寸都仅在此模式下使用,onnx parser也需要它。例如,考虑处理一个NCWH格式的具有3个通道大小为HW的N个图像,在运行时,输入张量的维度为[N,3,H,W],在显式批模式下,网络指定为[N,3,H,W],在隐式批模式下,网络仅指定[3,H,W],批次维度N是隐式的,在此模式下,无法在网络中指定N维度,和N维度有关的操作都无法做。我理解就是onnx解析器中的bs是固定的,如果dynamic_export中没有指定,到tensorrt中的bs其实就是指定的,不过在7.0以后的版本也不考虑bs这个了,都是动态的需要指定的。
7.working with dymamic shapes
1.网络定义不得具有隐式批次维度:
create_network(1 <<
int(tensorrt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
2.通过使用指定输入张量的每个运行维度-1,作为维度的占位符。
3.在构建时指定一个或多个优化配置文件,为具有运行时维度的输入指定允许的维度范围,以及自动调整期将优化的维度。
4.使用引擎:
4.1 从引擎中创建执行上下文,与没有动态尺寸的情况相同。
4.2 指定步骤3中涵盖输入维度的优化配置文件之一。
4.3 指定执行上下文的输入维度,这是输入维度后,可以获得tensorrt针对给定输入维度计算出的输出维度。