What is TensorRT
https://editor.csdn.net/md/?articleId=119796453
How Do I Get TensorRT?
2.1安装前的说明
- zip windows安装包暂时不支持Python,将来可能会支持
- 如果你使用Python API请安装PyCUDA,可以参考后文中的PyCUDA的安装
- 目前最新的TensorRT Release为: TensorRT Release 7.x.x–>8.x.x
- CUDA的版本支持9.0, 10.0, 10.2
- 最新的TensorRT支持TensorFlow 1.15.0; Pytorch已经在1.3.0上测试,可能也支持更老的版本
- 最好保证训练的环境和模型转换的环境是一致的比如CUDA和cuDNN的版本一 致性
- 只介绍tar安装包的安装方式和PyCUDA的安装,其他安装方式包括: Debian, RPM,Zip等可参考官方文档
2.2 Tar File Installation
1.安装依赖环境
。CUDA9.0, 10.0, or 10.2
。CuDNN 7.6.5
。Python 2 or Python 3 (Optional)
2.下载TensorRT tar文件
。访问: https //developer nvidia .com/tensorrt
。选择TensorRT版本并下载
3.选择安装的文件夹,所有的安装文件最终都安装在以Tenso:RT-version对应的子文件夹中
4解压tar文件
$ tar xzvf TensorRT-${version}.${os}.${arch}-gnu.${cuda}.${cudnn}.tar.gz
解压后会有lib, include, data, et… 5.添加环境变量
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:TensorRT-${version}/lib
6.安装Python的TensorRT包
$ sudo pip3 install tensorrt-*-cp3x-none-linuxx86_64.whl
7:安装Python UFF包(如果你打算在TensorFlow中使用TensorRT,将TF的模型.pb文件转化成TRT的推理引擎)
$ cd TensorRT-${version}/uff
$ sudo pip3 install uff-0.6.5-py2.py3-none-any.whl
8.安装Python graphsurgeon(通过TRT自定义网络结构)
$ cd TensorRT-${version}/graphsurgeon
$ sudo pip3 install graphsurgeon-0.4.1-py2.py3-none-any.whl
9.验证安装是否成功运行samples/python下的例子(外面的其他例子都是C++写的),看是否安装成功!
$ cd samples/python/end to_end_tensorflow mnist
$ mkdir models
$ python3 models.py
$ cd /home/.../TensorRT-7.0.0.11/data/mnist
$ python3 download_pgms.py
$ python3 sample.py -d /home/.../TensorRT-7.0.0.11/data
执行models.py,训练后会产生models文件夹,生成lenet5.pb 文件 如何手动生成lenet5.uff ?
>>>convert-to-uff ./models/lenet5.pb
UFF Version 0.6.5
=== Automatically deduced input nodes ===
[name: "input_1"
op: "Placeholder"
attr {
key: "dtype"
value {
type: DT_FLOAT
}
}
attr {
key: "shape"
value {
shape {
dim {
size: -1
}
dim {
size: 28
}
dim {
size: 28
}
dim {
size: 1
}
}
}
}
]
=========================================
=== Automatically deduced output nodes ===
[name: "dense_1/Softmax"
op: "Softmax"
input: "dense_1/BiasAdd"
attr {
key: "T"
value {
type: DT_FLOAT
}
}
]
==========================================
Using output node dense_1/Softmax
Converting to UFF graph
DEBUG: convert reshape to flatten node
DEBUG [/home/cv/anaconda3/envs/tensorflow/lib/python3.6/site-packages/uff/converters/tensorflow/converter.py:96] Marking ['dense_1/Softmax'] as outputs
No. nodes: 13
UFF Output written to ./models/lenet5.uff
需要先安装pycuda,见下一步2.3安装PyCUDA,再测试,默认使用data/mnist文件下的lenet5.uff 要想使用自己手动生成的,需要修改sample.py文件中lenet5.uff 路径,改为model/lenet5.uff。再测试一遍。
注意:tensorflow 数据输入格式(NHWC)、tensorrt 数据输入格式(NCHW)
2.3安装PyCUDA
PyCUDA是Python使用NVIDIA CUDA的API,在Python中映射了所有CUDA的API 安装:
$ pip3 install pycuda 或 pip3 install pycuda>=2019. 1.1
文档
https://documen.tician.de/pycuda/driver.html
如果安装失败。请看https://blog.csdn.net/wishchin/article/details/78707014
Working with TensorRT Using the Python API
3.1 Python API vs C++ API
从本质上讲,C ++ API和Python API在支持的需求方面应该完全相同。Python API的主要优点是数据预处理和后处理易于使用,因为可以使用各种库,如NumPy和SciPy。 C ++ API应该用于安全性很重要的情况,例如汽车行业。有关C ++ API的更多信息,请参阅官方文档使用TensorRT的C ++ APl。
- 从模型中创建TensorRT网络定义;
- 调用TensorRT builder以从网络创建优化的运行时引擎;
- 序列化和反序列化引擎,以便在运行时快速重新创建;
- 向引擎填充数据,执行推理。
3.2在python中导入TensorRT
1.导入TensorRT
>>> import tensorrt as trt
2.实现日志记录接口,TensorRT通过该接口报告错误、警告和信息性消息。以下代码显示了如何实现日志记录接口。在这种情况下,我们已经抑制了信息性消息,并仅报告警告和错误。TensorRT Python绑定中包含个简单的记录器。
>>> TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
3.3在Python中创建网络定义
- 使用TensorRT进行推理的第一步是
从训练好的模型创建 TensorRT网络 。实现此目的的最简单方法是使用TensorRT解析器库导入模型 ,支持以下格式的序列化模型: 。Caffe (both BVLC and NVCaffe) 。ONNX 。UFF (used for TensorFlow) - 另一种方法是
使用TensorRT Network API直接定义模型 ,这要求您进行少量API调用以定义网络图中的每个层,并为模型的训练参数实现自己的导入机制 - TensorRT Python API仅适用于x86_ 64平台。有关详细信息,请参阅Deep Learning SDK文档 TensorRT工作流程。
3.3.1使用python API从头定义网络
构建网络时,必须首先定义引擎并为推理创建builder对象 。Python API用于从Network API创建网络和引擎。网络定义参考用于向网络添加各种层。有关使用Python API创建网络和引擎的更多信息,请参阅network_ api _pyt
>>> import tensorrt as trt
以下代码说明了如何使用Input, Convolution, Pooling, FullyConnected, Activation和SoftMax 层创建简单网络。
with trt.Builder(TRT_LOGGER) as builder, builder.create_networkO as network:
input_tensor = network.add_input(name=INPUT NAME, dtype=trt. float32,shape=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)
relu1 = network.add_activation(fc1.get_output(0), trt.ActivationType. RELU)
fc2_w = weights[' fc2.weight' ].numpy()
fc2_b = weights[' fc2.bias' ].numpy()
fc2 = network.add_fully_connected(relul.get_output(0),OUTPUT_SIZE, fc2_w,fc2_b)
fc2.get_output(0).name = OUTPUT_NAME
network.mark_output(fc2.get_output(0))
3.3.2 使用Python中的Parser导入模型
要使用解析器 导入模型,您需要执行以下步骤:
- 创建TensorRT builder和network;
- 为特定格式创建TensorRT解析器Parser;
- 使用解析器解析导入的模型并填充网络。
不同的解析器具有用于标记网络输出的不同机制。具体可参考UFF Parser API ,Caffe Parser API, and ONNX Parser API ,这里我们只介绍UFF Parser,并且将在Section 4的例子中介绍Darknet版本的YOL0 v3以及TensorFlow版本的ResNet50如何通过UFF Parser API进行加速推断
3.3.3使用Python接口导入Tensorflow模型
以下步骤说明了如何使用UFFParser 和Python API直接导入TensorFlow模型。此示例可以在/tensorrt / samples / python/ end_ to_ end_ tensorflow_ mnist目录中找到。有关更多信息,请参阅end. to_end_tensorflow_mnist Python示例(我们同时使用该示例验证TensorRT的安装)。
1、导入TensorRT
>>> import tensorrt as trt
2、创建冻结的TensorFlow模型 3、使用UFF转换器 将冻结的Tensorflow模型pb文件 转换为UFF文件
>>> convert-to-uff frozen_inference_graph.pb
4、定义路径。更改以下路径以反映Samples中包含的模型的位置
>>> model_file = '/data/mnist/mnist.uff'
5、创建builder, network和parser:
with builder = trt.Builder(TRT_LOGGER) as builder, builder.create_network() as network, trt.UffParser() as parser:
parser.register_input("Placeholder", (1, 28, 28))
parser.register_output("fc2/Relu")
parser.parse(model_file, network)
注意:这里使用的是trt.UffParser() ,导入Caffe,ONNX,Pytorch框架的模型类似:trt.CaffeParser() ,trt.OnnxParser() ,可参考官网介绍
3.4使用Python接创建引擎
- builder的一 个功能是搜索其CUDA内核目录以获得最快的可用实现,因此必须使用相同的GPU来构建优化引擎将运行的GPU
- builder具有许多 属性,可以设置这些属性以控制网络应运行的精度,以及自动调整参数,例如TensorRT在确定哪个最快时(多次迭代导致更长的运行时间)应该为每个内核计时多少次同时对噪声的敏感性较低)。还可以查询builder以找出硬件本身支持的混合精度类型。
- 两个特别重要的属性是最大batch大小和最大workspace大小
。最大batch大小指定TensorRT将优化的批量大小。在运行时,可以选择较小的批量大小; 。层算法通常需要临时工作空间。此参数限制网络中任何层可以使用的最大大小。如果提供的scratch不足,则TensorRT可能无法找到给定层的实现; - 有关使用Python构建引擎的更多信息,请参阅introduction orySamples示例
1.使用builder对象创建引擎:
builder.max_batch_size = max_batch_size
builder.max_workspace_size = 1 << 20
with trt.Builder(TRT_LOGGER) as builder:
with builder.build_cuda_engine(network) as engine:
在构建弓|擎时,TensorRT会复制权重 2.进行推理
3.5在Python中序列化引擎
序列化时,将引擎转换为一种格式,以便以后存储和使用以进行推理。要用于推理,只需反序列化引擎即可。序列化和反列化是可选的。由于从网络定义创建引擎可能非常耗时,因此每次应用程序重新运行时都可以通过序列化一次并 在推理时对其进行反序列化来避免重建弓|擎。因此,在构建引擎之后,用户通常希望将其序列化以供以后使用。可以序列化引擎,也可以直接使用引擎进行推理。在将模型用于推理之前,序列化和反序列化是一个可选步骤-如果需要,可以直接使用引擎对象进行推理。序列化弓|擎不能跨平台或TensorRT版本移植。弓|擎特定于它们构建的精确GPU模型(包括平台和TensorRT版本)。
1.序列化模型为modelstream :
serialized_engine = engine.serialize()
2.反序列化模型流以执行推理。反序列化需要创建运行时对象:
with trt.Runtime(TRT_LOGGER) as runtime:
engine = runtime.deserialize_cuda_engine(serialized_engine)
也可以将序列化引擎保存到文件中,并从文件中读回: 1.序列化引擎并写入文件:
with open ("sample.engine", "wb" ) as f:
f.write(engine.serialize())
2.从文件读取引擎并反序列化:
with open("sample.engine","rb") as f, trt.Runtime(TRT_LOGGER) as runtime:
engine = runtime.deserialize_cuda_engine(f.read())
3.6使用Python接口执行推理
以下步骤说明了如何在Python中执行推理,现在已拥有引擎。
1、为输入和输出分配-些主机和设备缓冲区 :
h_input = cuda.pagelocked_empty(engine.get_binding_shape(0).volume(), dtype=np.float32)
h_output = cuda.pagelocked_empty(engine.get_binding_shape(1).volume(), dtype= np.float32)
d_input = cuda.mem_alloc(h_input.nbytes)
d_output = cuda.mem_alloc(h_output.nbytes)
stream = cuda.Stream()
2.创建一些空间来存储中间激活值。 由于引擎保持网络定义和训练的参数,因此需要额外的空间。它们保存在执行上下文中:
with engine.create_execution_context() as context:
cuda.memcpy_htod_async(d_input, h_input, stream)
context.execute_async(bindings=[int(d_input), int(d_output)], stream_handle=stream.handle)
cuda.memcpy_dtoh_async(h_output, d_output, stream)
stream.synchronize()
return h_output
弓|擎可以具有多个执行上下文,允许一组权重用于多个重叠推理任务。例如,可以使用一个弓I擎和每个流中各一个上下文在并行CUDA流中处理图像。每个上下文将在与引擎相同的GPU上创建。
YOLOv3 with TensorRT
4.1为什么选择YOLOv3测试
- 传统的特征提取,two-stage, one-stage, anchor free,基于NAS的网络搜索(EfficientDet)
- YOLOv3在业界应用较多(很好的权衡了速度和精度)
- YOLO系列的改进模型较多YOLO-tiny, YOLO-SPP ,Gaussian-YOLO,GloU-YOLO,D/CIoU-YOLO, etc.
4.2 Darknet,TensorFlow,TensorRT的PK
- DarkNet: Darknet版本的YOLOv3
- TensorFlow: Darknet版本转化为TensorFlow版本基于TensorFlow测试
- TensorRT: 基于UFFParser(TensorRT并不支持所有的TensorFlow API)
- TensorRT: Darknet转化为ONNX基于ONNXParser,但是仍然只是加速了卷积不部分
- TensorFlow 1.9.0 + TensorRT 4(基于TensorFlow集成的TensorRT可以加速)
ResNet-50 with TensorRT
见https://www.bilibili.com/video/BV1r7411n7gQ?p=2
|