TensorRT介绍

2023-05-16

TensorRT

文章目录

  • TensorRT
    • 训练和推理的区别
    • TensorRT
      • TensorRT 优化和性能
      • TensorRT 工作原理
      • Python API
        • Importing TensorRT Into Python
        • Creating A Network Definition In Python
        • Building An Engine In Python
        • Serializing A Model In Python
        • Performing Inference In Python
        • examples
      • Working With Mixed Precision Using The Python API
      • 其他
    • 参考

训练和推理的区别

训练vs推理

  • 训练(Traning)过程是网络不断对训练数据集进行学习的过程。训练包括前向传递和后向传播两个阶段,前向传递用于预测标签,然后再通过预测标签与真实标签之间的误差进行后向传播不断修改网络的权重(weights)。在训练的过程中,网络的权重是不断变化的。
  • 推理(Inference)的目的是输出预测标签,仅仅包含前向传递阶段,而且网络的权重是不变的。简言之,推理阶段就是利用训练好的网络进行预测。

TensorRT

TensorRT是nvidia家的一款高性能深度学习推理SDK。此SDK包含深度学习推理优化器和运行环境,可为深度学习推理应用提供低延迟和高吞吐量。在推理过程中,基于TensorRT的应用程序比仅仅使用CPU作为平台的应用程序要快40倍。

TensorRT 优化和性能

TensorRT

  • 权重与激活精度校准:在保证准确率的情况下,通过将模型量化到INT8来更大限度地提高吞吐量
  • 层与张量结合:通过结合内核中的节点,优化使用GPU内存和带宽
  • 内核自动调整:基于目标GPU平台,选择最优数据层和算法
  • 动态张量显存:最小化内存占用并且有效地重新使用张量内存
  • 多数据流执行:并行处理多个输入流的扩展设计

TensorRT 工作原理

TensorRT包含两个阶段:编译build和部署deploy。

  • 编译阶段对网络配置进行优化,并生成一个plan文件,用于通过深度神经网络计算前向传递。plan文件是一个优化的目标代码,可以序列化并且可存储在内存和硬盘中。
    编译阶段
  • 部署阶段通常采用长时间运行的服务或者用户应用程序的形式。它们接收批量输入数据,通过执行plan文件在输入数据上进行推理,并且返回批量的输出数据(分类、目标检测等)

部署阶段
为了优化你的推理模型,TensorRT将接受你的网络定义,执行优化,包括特定平台优化,并且生成一个推理引擎(inference engine)。这个过程被视作编译阶段(build phase)。编译计算可能耗费相当多的时间,尤其是在嵌入式平台中运行时。因此,一个典型的应用将会构建一个引擎,然后将其序列化为一个plan 文件,以供后续使用。(生成的plan文件并不能够跨平台/TensorRT版本移植)

编译阶段在图层中执行如下优化:

  • 消除输出未被使用的层
  • 消除等价于no-op的运算
  • 卷积层,偏差和ReLu操作的融合
  • 聚合具有足够相似参数和相同目标张量的操作(例如,Googlenet v5 inception 模型的1*1卷积)
  • 通过直接将层输出定向到正确最终目的来合并concatenation 层

网络优化

Python API

C++ API和Python API在支持开发者的需求方面非常接近。在任何性能是关键的场景中,和在安全性非常重要的情况下,C++应该被使用。Python API 的主要优点是可以使用Python的各种库文件对数据预处理和后处理。

将一个训练好的模型部署到TensorRT上的流程为:

  1. 从模型创建一个TensorRT网络定义
  2. 调用TensorRT生成器从网络创建一个优化的运行引擎
  3. 序列化和反序列化引,以便于运行时快速重新创建
  4. 向引擎提供数据以执行推断

Importing TensorRT Into Python

# 导入TensorRT
import tensorrt as trt
# 日志接口,TensorRT通过该接口报告错误、警告和信息性消息
TRT_LOGGER = trt.Logger(trt.Logger.WARNING)

Creating A Network Definition In Python

使用解析器(parser)导入一个模型,需要执行以下步骤:

  • 创建TensorRT builder 和 network
  • 为特定的格式创建TensorRT 解析器
  • 使用解析器解析导入的模型并填充模型
import tensorrt as trt

# 以CaffeParse为例
datatype = trt.float32  # 定义数据类型
# 定义配置文件和参数模型路径
deploy_file = 'data/mnist/mnist.prototxt'
model_file = 'data/mnist/mnist.caffemodel'
# 创建builder, network 和 parser
with trt.Builder(TRT_LOGGER) as builder, builder.create_network() as network, trt.CaffeParser() as parser:
    model_tensors = parser.parse(deploy=deploy_file, model=model_file, network=network, dtype=datatype)

注: builder必须在network之前创建。不同的解析器有不同的机制标记网络输出。

Building An Engine In Python

builde的功能之一是通过搜索CUDA内核目录以获得可用的最快实现,因此有必要使用相同的GPU进行构建,就像优化引擎将在其上运行一样。

IBuilderConfig有很多属性,你可以设置这些属性来控制网络运行的精度,以及自动调整参数等等。其中一个特别重要的属性是 maximum workspace size

# 使用build对象建造engine
with trt.Builder(TRT_LOGGER) as builder, builder.create_builder_config() as config:
    # 当构建一个优化引擎时,这决定了builder可用的内存量,通常应当设置为尽可能高
    config.max_workspace_size = 1 << 20 
    with builder.build_engine(network, config) as engine:

Serializing A Model In Python

序列化,意味着将engine转化为一种可以存储的格式并且在以后可以进行推理。用于推理使用时,只需要简单地反序列化engine。序列化和反序列化都是可选的。由于从网络定义中创建一个engine是非常耗时的,通常序列化一次并且在推理时反序列化即可。因此,在构建engine之后,用户通常希望序列化它以供以后使用。

# 序列化模型到modelstream
serialized_engine = engine.serialize()
# 反序列化modelstream用于推理。反序列化需要创建runtime对象。
with trt.Runtime(TRT_LOGGER) as runtime:    
    engine = runtime.deserialize_cuda_engine(serialized_engine)

# 序列化engine并且写入一个file中
with open(“sample.engine”, “wb”) as f:
		f.write(engine.serialize())
		
# 从文件中读取engine并且反序列化
with open(“sample.engine”, “rb”) as f, trt.Runtime(TRT_LOGGER) as runtime:
		engine = runtime.deserialize_cuda_engine(f.read())

Performing Inference In Python

# engine有一个输入binding_index=0和一个输出binding_index=1
h_input = cuda.pagelocked_empty(trt.volume(context.get_binding_shape(0)), dtype=np.float32)
h_output = cuda.pagelocked_empty(trt.volume(context.get_binding_shape(1)), dtype=np.float32)
# 为输入和输出分配内存
d_input = cuda.mem_alloc(h_input.nbytes)
d_output = cuda.mem_alloc(h_output.nbytes)
# 创建一个流在其中复制输入/输出并且运行推理
stream = cuda.Stream()

#创建一些空间来存储中间激活值。由于引擎包含网络定义和训练参数,因此需要额外的空间。它们被保存在执行上下文中。
with engine.create_execution_context() as context:
    # 将输入数据转换到GPU上
	cuda.memcpy_htod_async(d_input, h_input, stream)
	# 运行推理
	context.execute_async_v2(bindings=[int(d_input), int(d_output)], stream_handle=stream.handle)
	# 从GPU上传输预测值
	cuda.memcpy_dtoh_async(h_output, d_output, stream)
	# 同步流
	stream.synchronize()
# 返回主机输出
return h_output

examples

import pycuda.driver as cuda
import pycuda.autoinit
import tensorrt as trt
import common
   
TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
  
# 分配主机和设备缓冲区,创建流
def allocate_buffers(engine):
    h_input = cuda.pagelocked_empty(trt.volume(context.get_binding_shape(0)), dtype=np.float32)
    h_output = cuda.pagelocked_empty(trt.volume(context.get_binding_shape(1)), dtype=np.float32)
    d_input = cuda.mem_alloc(h_input.nbytes)
    d_output = cuda.mem_alloc(h_output.nbytes)
    stream = cuda.Stream()
    return h_input, h_output, d_input, d_output, stream
    
def do_inference(context, h_input, h_output, d_input, d_output, stream):
    cuda.memcpy_htod_async(d_input, h_input, stream)
	context.execute_async_v2(bindings=[int(d_input), int(d_output)], stream_handle=stream.handle)
	cuda.memcpy_dtoh_async(h_output, d_output, stream)
	stream.synchronize()

def build_engine_caffe(model_file, deploy_file):
    with trt.Builder(TRT_LOGGER) as builder, builder.create_network() as network, trt.CaffeParser() as parser:
        builder.max_workspace_size = common.GiB(1)
        model_tensors = parser.parse(deploy=deploy_file, model=model_file, network=network, dtype=trt.float32)
        network.mark_output(model_tensors.find(ModelData.OUPUT_NAME))
        return builder.build_cuda_engine(network)

def Load_normalized_test_case(test_image, pakelocked_buffer):
    # 将输入图像转化为一个CHW numpy数组

def main():
    caffe_model_file, caffe_deploy_file
    with build_engine_caffe(caffe_model_file, caffe_deploy_file) as engine:
        h_input, h_output, d_input, d_output, stream = allocate_buffers(engine)
        with engine.create_execution_context() as context:
            test_image
            Load_normalized_test_case(test_image, h_input)
            do_inference(context, h_input, h_output, d_input, d_output, stream)

Working With Mixed Precision Using The Python API

import tensorrt as trt


# 使用python设置层精度 Layer Precision
# 用precision指定层精度
layer.precision = trt.int8
# 设置输出张量数据类型与层实现一致
layer.set_output_type(out_tensor_index, trt.int8)
# builder强制准寻设置的精度
builder.strict_type_constraints = true


# 使用Python使得推理以FP16精度运行
builder.fp16_mode = True
# 通过设置builder标志强制16-bit精度
builder.strict_type_constraints = True


# 通过设置builder标志运行INT8精度模式
builder.int8_mode = True

# 使用Python设置每一层的动态范围
# 为了能够以INT8精度执行推理,必须为每一网络张量设置动态范围。可以使用各种方法导出动态范围值,包括量化感知训练或者仅仅简单地记录上一个训练epoch期间每个张量的最小和最大值
layer = network[layer_index]
tensor = layer.get_output(output_index)
tensor.dynamic_range = (min_float, max_float)
# 同样需要为网络输入设置动态范围
input_tensor = network.get_input(input_index)
input_tensor.dynamic_range = (min_float, max_float)

# INT8校准
# 和测试/验证文件相似,使用输入文件集合作为一个矫正文件数据集。确保校准文件能够代表整个推断数据文件。为了使得TensorRT能够使用校准文件,需要创建batchstream对象。一个bacthstream对象通常被用来配置校准器。
NUM_IMAGES_PER_BATCH = 5
batchstream = ImageBatchStream(NUM_IMAGES_PER_BATCH, calibration_files)
# 用输入节点名称和batch stream创建一个Int8_calibrator对象
Int8_calibrator = EntropyCalibrator(["input_node_name"], batchstream)
# 设置INT8模式和INT校准
config.set_flag(trt.BuilderFlag.INT8)
config.int8_calibrator = Int8_calibrator


# 使用Python API创建一个明确的精度网络,需要将EXPLICIT_PRECISION标志传送给builder
network_creation_flag = 1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_PRECISION)
self.network = self.builder.create_network(network_creation_flag)

其他

TensorRT 允许开发者可以import、calibrate、generate和deploy优化网络。网络可以直接从Caffe框架中imported,或者通过UFF/ONNX格式从其他框架中imported;网络也可以通过直接设置参数和权重实例化各层以编程地方式创建。

TensorRT为所有支持平台提供了C++实现,以及在x86、aarch64和ppc64le平台上提供Python支持。


终于恰饭了,感谢金主深蓝学院,如果您想系统性学习TensorRT,可访问深度神经网络加速cudnn和TensorRT课程。

参考

[1]. What’s the Difference Between Deep Learning Training and Inference?
[2]. TensorRT(1)-介绍-使用-安装
[3]. TensorRT Homepages
[4]. TensorRT Developer Guide

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TensorRT介绍 的相关文章

随机推荐

  • 虚拟机linux装无线网卡驱动,linux无线网卡驱动安装

    环境 在笔记本里的虚拟机10 0版本 xff0c centos 6 5 无线网卡fast fw300um 第一步要查看芯片 lsusb 当你得到芯片之后接下来查看内核 xff0c 如果内核已经有芯片模块就不用再装了 xff0c 如果不支持的
  • 使用Altium Designer 20绘制双层板以及四层板

    直接入正题 1 按照正常的绘制双层板的方式新建工程文件 xff0c 加入原理图和PCB文件 xff08 如果会绘制双层板请直接看第二步 xff09 xff08 1 xff09 新建工程文件 xff08 2 xff09 选择工程类型 xff0
  • 1.1 Ubuntu18.04 ROS tcp/ip Server通信实现

    Ubuntu18 04 ROS tcp ip Server通信实现 此小节介绍tcp ip Server收发数据 xff0c 并将截取到底信息通过话题方式发布出去 下一节介绍Ubuntu18 04 ROS tcp ip client通信实现
  • 1.2 Ubuntu18.04 ROS tcp/ip Client通信实现

    Ubuntu18 04 ROS tcp ip Client通信实现 此小节介绍tcp ip Client收发数据 xff0c 测试平台为为Ubuntu18 04 与Windows系统上的网络调试助手进行通信测试 xff0c 调试助手采用的有
  • 使用Gazebo对PX4飞控进行SITL仿真

    在仿真之前 xff0c 首先需要搞清楚每个模块所代表的含义 xff0c 在这个操作中扮演什么角色 Gazebo xff1a 可以理解成对我们实际飞行物理环境的一个仿真 QGC xff1a 地面站 xff0c 不用多说 Firmware xf
  • GitLab统计代码量

    gitlab官方文档 xff1a https docs gitlab com ee api index html 1 生成密钥 登录gitlab xff0c 编辑个人资料 xff0c 设置访问令牌 2 获取当前用户所有可见的项目 接口地址
  • 【树莓派】(2)网络连接、IP设置、屏幕大小设置、VNC安装与配置

    目录 1 网络连接 1 1有线网连接 SSH协议 1 2 无线网连接 VNC 方法1 xff1a 不能联网 方法2 xff1a 能联网 2 VNC安装与配置 3 IP WiFi配置 4 屏幕大小 屏幕黑屏时间设置 1 网络连接 分为有屏幕和
  • Linux服务配置 配置VNC远程桌面

    一 VNC简介 VNC Virtual Network Console 是虚拟网络控制台的缩写 它 是一款优秀的远程控制工具软件 xff0c 由著名的 AT amp T 的欧洲研究实验室开发的 VNC 是在基于 UNIX 和 Linux 操
  • 异常检测 and 自编码器(2)

    文章目录 前言一 自编码器用于异常检测的网址推荐1 自编码器AutoEncoder解决异常检测问题2 基于自编码器的时间序列异常检测算法3 深度学习实现自编码器Autoencoder神经网络异常检测心电图ECG时间序列 总结 前言 上篇文章
  • python树莓派3控制蜂鸣器_树莓派3 modelB型 连接HC-SR501人体红外感应模块和蜂鸣器模块...

    连接前准备 树莓派3 modelB型一个 HC SR501传感器一只 低电平蜂鸣器模块 有源 即接上电就会响 xff0c 低电平触发 母对母杜邦线三根 实物图如下 xff1a 博主连接的不是特别美观 两个传感器的连接图分别如下 HC SR5
  • git submodule 使用教程

    1 submoude 介绍 xff08 1 xff09 项目很大参与开发人员多的时候 xff0c 需要将各个模块文件进行抽离单独管理 xff08 2 xff09 使用git submodule来对项目文件做成模块抽离 xff0c 抽离出来的
  • 为什么笔记本电脑电源适配器基本是19V供电

    为什笔记本电源适配器供电一般不是20V xff0c 不是25V xff0c 偏偏是19V呢 xff0c 我们从硬件角度聊聊这个问题 首先一个大背景是 xff0c 笔记本电池基本都是锂电池为主 xff0c 在设计上 xff0c 一般会使用多枚
  • 基于国产飞腾、Intel X86等CPU主板设计与调试入门指导

    知识就像货币 xff0c 流动才有意义 一 前言 因为我是做硬件的 xff0c 想用这样一篇文章介绍一下我们常见的电脑主板 xff0c 或者说电路板卡 xff0c 是怎么设计出来的 仅以技术之所学 xff0c 得此文章 xff0c 若有表达
  • 两台电脑直接使用一根网线传输文件

    教程 目录 xff1a https blog csdn net dkbnull article details 87933584 有时候我们需要在两台电脑之间传输几十G的大文件 xff0c 或者置换新电脑时复制文件到新电脑 xff0c 而我
  • keil5(ARM)的下载和安装教程

    Keil 5的下载与安装 下载和安装教程均在以下百度网盘链接中 链接 xff1a 百度网盘 请输入提取码 https pan baidu com s 11N8EwQRBT 5AzXmW7y1X6A 提取码 xff1a efv3
  • git 远程分支与本地分支

    前言 远程仓库上只有 1 个 master 分支 复制远程仓库的地址 3 克隆远程仓库到本地 一 注意 xff1a 本地的 head 和 master 文件都存在 xff0c 但是 remote 的 master 信息是保存在文件 git
  • ARM 自己动手安装交叉编译工具链

    一 Windows中装软件的特点 Windows中装软件使用安装包 xff0c 安装包解压后有2种情况 xff1a 一种是一个安装文件 xff08 exe msi xff09 xff0c 双击进行安装 xff0c 下一步直到安装完毕 安装完
  • ARM X210开发板的软开关按键问题

    一 X210 开发板的软启动电路详解 x210bv3 pdf 1 210 供电需要的电压比较稳定 xff0c 而外部适配器的输出电压不一定那么稳定 xff0c 因此板载了一个文稳压器件 MP1482 这个稳压芯片的作用就是外部适配器电压在一
  • pyqt5 编写串口通讯上位机_如何使用Python开发串口通讯上位机(二)

    黑色的dos窗口对于大部分来说 xff0c 页面极为不友好 xff0c 且操作不方便 xff0c 因此本篇主要讲讲如何结合QtDesigner创建一个UI并初步与串口Api链接 1 QtDesigner进行上位机页面设计 Python下的软
  • TensorRT介绍

    TensorRT 文章目录 TensorRT训练和推理的区别TensorRTTensorRT 优化和性能TensorRT 工作原理Python APIImporting TensorRT Into PythonCreating A Netw