Tensor-8.6.1官方课程学习笔记

教程

官方教程

官方文档

cookbook

TensorRT简介

1.用于高效实现已训练好的深度学习模型的推理过程的SDK

2.内含推理优化器和运行时环境

3.使DL模型能以更高吞吐量和更低的延迟运行

构建期:推理优化器

1.模型解析 / 搭建

2.计算图优化:横向融合和纵向融合

3.节点消除:去掉无用层

4.多精度支持

5.优选kernel / format:针对硬件选择最优实现

6.导入plugin:实现自定义操作

7.显存优化:显存池

运行期:运行时环境

1.运行时环境:对象生命期管理,内存显存管理,异常处理

2.序列化、反序列化:保存、加载engine

基本流程

构建期

前期准备:Logger、Builder、Config、Profile

创建network

生成序列化网络

运行期

建立Engine 和 Context

Buffer相关准备

执行推理

善后工作

获取网络

1.使用框架自带TRT接口

2.使用Parser从onnx文件导入

3.使用TensorRT原生API搭建网络

​ 1)使用TensorFlow / pyTorch创建并训练一个网络

​ 2)提取网络权重

​ 3)TensorRT中逐层重建该网络并加载权重

​ 4)生成推理引擎

​ 5)加载推理引擎并推理

API

Logger:日志记录器

loggre = trt.Logger(trt.Logger.VERBOSE)

Builder:引擎构建器

builder = trt.Builder(logger)

builder.create_network()					# 创建TensorRT网络对象				
builder.create_optimization_profile()		# 创建用于Dynamic Shape输入的配置器

BuilderConfig: 网络属性选项

config = builder.create_builder_config()

config.config_set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 << 30)		# 指定构建起显存
config.flag = 								# 设置标志位开关
config.int8_calibrator = 					# 指定INT8-PTQ的校正器
config.add_optimization_profile()			# 添加用于Dynamic Shaped输入的配置器
...

Network:网络具体构造

network = builder.create_network(<int(tensorrt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))

network.add_input()		# 标记网络输入
network.mark_output()	# 标记网络输出

network.name / network.num_layers / network.num_inputs / network.num_outputs

Profile: 指定输入张量大小范围

profile = builder.create_optimization_profile()

profile.set_shape(tensorName,minShape,commonShape,maxShape)  	# 给定输入张量的最小、最常见、最大尺寸
config.add_optimization_profile(profile) 						# 将设置的profile传递给config以创建网络

Layer / Tensor: 网络层 和 张量

# Layer
layer.name / layer.type / layer.precision / layer.get_output()
# Tensor
tensor.name / tensor.shape / tensor.dtype

Engine: 计算引擎

serializedNetwork = builder.build_serialized_network(network,config)
engine = trt.Runtime(logger).deserialize_cuda_engine(serializedNetwork)

engine.num_io_tensors	# 获取engine绑定的输入输出张量总数
engine.num_layre		# 获取engine总蹭树
Engine.get tensor_name(i)						# 第i个张量的名字
engine.get_tensor_dtype(iTensorName[i])			# 第i个张量的数据类型,传入张量名字而非索引
engine.get tensor shape(iTensorName[i])			# 第i个张量的张量形状,Dynamic Shape模式下结果可能含-1
engine.engine.get tensor mode(iTensorName[i])	# 第i个张量属于是输入还是输出张量

Context: 推理进程

context = engine.create_execution_context()

context.set input shape(iTensorName[i],shapeofInputTensor) 	# 设定第i个张量的形状(Dynamic Shape模式中使用)
context.get_tensor_shape(iTensorName[i])					# 获取第i个张量的形状
context.set_tensor_address(iTensorName[i],address)			# 设定输入输出张量的指针
context.execute_async_v3(srteam)							# Explicit batch模式的异步执行

自定义扩展

Plugin: 插件

功能:
    以.so的形式插入到网络中实现某些算子
    实现TensorRT不原生支持的层或结构
    替换性能不足的层或结构
    手动合并TensorRT没有自动融合的层或结构
限制条件:
	自己实现CUDA C++kernel,为结果精度和性能负责
    Plugin与其他Layer.之间无法fusing
    可能在Plugin节点前后插入reformatting节点,增加开销
    为了支持FP16模式,Plugin要允许float16的输入输出张量类型,并实现float16的CUDA C++kernel
    为了支持lnt8模式下的calibration过程,Plugin需要实现FP32的支持,否则要手工指定所有输入输出张量的dynamic_rang
    Int8模式下,Plugin内部张量的dynamic range也要手工指定
实现步骤:
	继承IPluginV2DynamicExt类实现一个Plugin类
    继承IPluginCreator类实现一个PluginCreator类
    实现用于计算的CUDA C++ kernel
    将Plugin编译为.so保存
    加载编译好的.so
    在Plugin Registry里找到需要的Plugin
    通过Plugin Creator构造需要的Plugin
    将Plugin插入网络中(搭建网络情景)
    Parser自动识别(通过Parser加载模型场景)
交互;
	构建期:
        TensorRT向Plugin传输参数和权重
        Plugin向TensorRT报告其输入输出张量信息,包括数量、形状(Shape)、数据类型(DataType)和数据排布(Layout)组合
        Plugin向TensorRT报告其需要的workspace大小
        TensorRT尝试各种允许的组合,选择性能最佳的输入输出组合(可能在Plugin前后插入reformat节点)
        Plugin不参与层fusing
	运行期
		TensorRT为Plugin提供输入输出张量的地址,workspace的地址,以及所在的stream
插件类型:
	IPluginV2				# 支持单一input / output格式
    IPluginV2Ext			# 支持单一input格式和混合output格式
    IPluginV2IOExt			# 支持混合input / output格式,Implicit Batch模式
    IPluginV2 DynamicExt	# 支持混合input / output格式,Dynamic Shape模式

关键特性

Explicit batch

可应用Dynamic Shape模型。

适用于输入张量形状在推理时才决定网络

除了Batch维,其他维度也可以推理时才决定

需要Optimazation Profile帮助网络优化

需用context.set_input_shape绑定实际输入数据形状

FP16

config.flags = 1 << int(trt.BuilderFlag.FP16)

需要更长的构建时间,需要插入Reformat节点

部分层可能出现精度下降导致误差,使用polygraphy等工具,可以强制该层使用FP32进行计算

config.set_flag(trt.BuilderFlag.OBEY_PRECISION_CONSTRAINTS)
layer.precision = trt.float32

Int8模式——PTQ

不需要对网络模型做出改变,只需要一个校准集

1. 需要有校准集(输入范例数据)
2. 自己实现calibrator(如右图)
3. config.set_flag(trt.BuilderFlag.INT8)
4. config.int8_calibrator

Int8模式——QAT

训练时修改网络

1. config.set_flag(trt.BuilderFlag.INT8)
2. 在pyTorch网络中插入Quantize/Dequantize层

内存管理

CUDA异构计算
	1. 同时准备CPU端内存和GPU端显存
	2. 开始计算前把数据从内存拷贝到显存中
	3. 计算过程的输入输出数据均在GPU端读写
	4. 计算完成后要把结果拷贝会内存才能使用
	5. 内存释放

可以将cuda对于显存的优化应用于到tensorrt中。

一些技巧

1. 如果不用Int8模式,onnx parser的代a码几乎是通用的
	可以用trtexec,基本等价于脚本中的APl

2. 遇到TensorRT不支持的节点
    1. 修改源模型
    2. 修改Onnx计算图
    3. TensorRT中实现Plugin
    4. 修改Parser: 修改TRT源码并重新编译TRT

TensorRT环境

CUDA + Cudnn + TensorRT:
	注意版本对应关系
使用NVIDIA-optimized Docker
	安装步骤:https:/docs.nvidia.com/datacenter/cloud-native,/container--toolkit/install--guide.html#docker
	镜像列表:https:/docs.nvidia.com/deeplearning/frameworks/,support-matrix/index.html
	推荐镜像:nvcr.io/nvidia/pytorch:23.03-py3 (pyTorch1.14+TRT8.5.2),nvcr.io/nvidia/pytorch:23.04-py3 (pyTorch2.0 + TRT8.6.1)

python库
	nvidia-pyindex,cuda-python (python>3.7),pycuda,onnx,onnx-surgeon,onnxruntime-gpu,opencv-python,polygraphy

开发辅助工具

trtexec:模型转换、推理工具

位于tensor-xx/bin/trtexec,docker中位于: /opt/tensorrt/bin/

# 功能
由onnx文件生成TensorRT引擎并序列化为Plan文件
查看onnx文件或Plan文件的网络逐层信息
模型性能测试:测试TensorRT基于随机输入或给定输入下的性能
# 示例
# 使用onnx构建引擎并推理
trtexec
    --onnx=model.onnx				\
    --minShapes=x:0:1x1x28x28		\
    --optShapes=x:0:4x1x28x28		\
    --maxShapes=x:0:16x1x28x28		\
    --workspace=1024				\
    --saveEngine=model-FP32.plan	\
    --shapes=x:0:4x1x28x28			\	
    --verbose
# 使用onnx构建引擎并推理,使用fp16模式
trtexec
    --onnx=model.onnx				\
    --minShapes=x:0:1x1x28x28		\
    --optShapes=x:0:4x1x28x28		\
    --maxShapes=x:0:16x1x28x28		\
    --workspace=1024				\
    --saveEngine=model-FP32.plan	\
    --shapes=x:0:4x1x28x28			\	
    --verbose						\
    --fp16
# 读取引擎并推理
trtexec 							\
	--loagEngine=./moder-Fp32.plan	\
	--shapes=x:0:4x1x28x28			\
	--verbose

Netron: 网络模型可视化工具

Onnx-graphsurgeon: Onnx文件修改工具

onnx原生的api也能对onnx做一些修改

功能:
	修改计算图:图属性 / 节点 / 张量 / 节点和张量的连接 / 权重
	修改子图:添加 / 删除 / 替换 / 隔离
	优化计算图:常量折叠 / 拓扑排序 / 去除无用层
	功能和API上有别于onnx库
	
下载和参考文档:
    pip install nvidia-pyindex onnx-graphsurgeon
    https://github.com/NVIDIA/TensorRT/tree/master/tools/onnx-graphsurgeon/examples
    https://docs.nvidia.com/deeplearning/tensorrt/onnx-graphsurgeon/docs/index.html

Polygraphy: 深度学习模型调试器

功能:
	使用多种后端运行推理计算,包括TensorRT,onnxruntime,TensorFlow
	比较不同后端的逐层计算结果
	由模型文件生成TensorRT引擎并序列化为.plan
	查看模型网络的逐层信息
	修改Onnx模型,如提取子图,计算图化简
	分析Onnx转TensorRT失败原因,将原计算图中可以/不可以转TensorRT的子图分割保存
	隔离TensorRT中的错误tactic
下载和参考文档:
    pip install polygraphy
    https://docs.nvidia.com/deeplearning/tensorrt/polygraphy/docs/index.html
	https:/www.nvidia.com/en-us/on-demand,/session/,gtcspring.21-s31695/(onnx-graphsurgeon和polygraphy的-个视频教程)

分为不同的模式,用以实现不同的功能

nsight systems: 性能调试器

随cuda安装。/usr/local/cuda/bin/nsys 和 /usr/local/cuda/bin/nsys-ui

用于替代就工具nvprof 和 nvvp

1. 使用nsys profile xxx, 获得.qbrep 或 .qdrep-nsys 文件
2. 打开nsys-ui,将上述文件拖入即可观察timeline

只计量运行阶段,而不分析构建期
构建期肘打开profiling以便获得关于Layer的更多信息
	builder_config.profilling_verbosity trt.ProfilingVerbosity.DETAILED
可以搭配trtexec使用:nsys profile-o myProfile trtexec-loadEngine:=mode.plan -=-warmUp=0 --duration
也可以配合自己的script使用:nsys profile-o myProfile python myScript.py

高级话题

Optimization Profile

功能:
	缩小每个Profile范围,方便TensorRT自动优化
	推理时,根据数据形状选择相应Profile
	注意输入输出数据的绑定位置
间接作用:
	多Context的基础工作
	增加显存占用、引擎尺寸和.plan尺寸

Cuda event、cuda stream

与pinned-memory

使用Context进行多线程调用

contextList [engine.create_execution_context()for index in range(nContext)]

Cuda Graph

优点:
    降低CPU Launch cost
    CUDA工作流优化
    缓解大量kernel调用时的Launch Bound
要点:
	Graph 定义,Graph实例化,Graph 执行
	Dynamic Shape模式中,实际数据形状发生改变时(调用context..set binding_shape)
	要先跑一遍context..execute再重新捕获Graph,最后再实例化和执行Graph

Timing Cache

节约engine的构建时间

优点:
	优化单次引擎构建时间(模型内多个同参数的算子)
    优化多次引擎构建时间(debug、参数更新后重新构建)
    尤化同环境下多个引擎构建时间(跨builder可用)
    用于反复生成一模一样的引擎
要点:
    类似引擎序列化反序列化,将Timing Cache保存出来下次用
    类似.plan,不可跨平台和开发环境使用

Algorithm Selector

为某一层的实现选择对应的算法

要点:
    自己实现一个MyAlgorithmSelector类
    关键是实现两个成员函数
        一个用来挑选特定层的算法
        一个用来报告所有层的挑选结果
    构建网络时交给BuilderConfig
实际工作流程:
    先通过polygraphy等工具发现某层的个Tactic
    构造Algorithm Selector屏蔽掉盖层的该tactic
    构建引擎

Refit

更新权重,而不重新构建engine

优点:
	节约反复构建引擎的时间
	强化学习必备
要点:
    BuilderConfig中设置相应Flag
    在构建好engine的基础上更新权重
    更新某层权重后,邻近层可能他需要更新(尽管其值可能不变),如Convolution层中的kernel和bias
    注意权重的排布方式
    Dynamic Shape模式暂不支持

Tactic Source

要点:
	BuilderConfig中设置相应Flag
    可以开启或关闭cuBLAS、cuBLASLt、.cuDNN
优点:
    节约部分内存、显存,减少构建时间
缺点:
    不能使用某些优化,可能导致性能下降
    可能导致构建失败
    后续版本中,TensorRT将彻底断开对外部Library依赖

版本兼容

config.set flag(trt.BuilderFlag.VERSION COMPATIBLE)
runtime.engine_host_code_allowed True
前向后向均可
可能会有少许性能损失
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值