GitHub - NVIDIA/TensorRT: TensorRT is a C++ library for high performance inference on NVIDIA GPUs and deep learning accelerators.TensorRT is a C++ library for high performance inference on NVIDIA GPUs and deep learning accelerators. - GitHub - NVIDIA/TensorRT: TensorRT is a C++ library for high performance inference on NVIDIA GPUs and deep learning accelerators.https://github.com/NVIDIA/TensorRT使用 TensorRT 加速深度学习推理 - NVIDIA 技术博客想要更多吗?查看 DLI 实践培训课程: 用 TensorRT 优化和部署 TensorFlow 模型 这是的更新版本 如何用…https://developer.nvidia.com/zh-cn/blog/speeding-up-deep-learning-inference-using-tensorrt/
tensorflow-tensorrt - Databrickshttps://docs.microsoft.com/zh-cn/azure/databricks/_static/notebooks/deep-learning/tensorflow-tensorrt.html
7.TensorRT中文版开发教程-----TensorRT中的INT8量化详解_扫地的小何尚的博客-CSDN博客7. 如何使用TensorRT中的INT8点击此处加入NVIDIA开发者计划7.1. Introduction to QuantizationTensorRT 支持使用 8 位整数来表示量化的浮点值。量化方案是对称均匀量化 - 量化值以有符号 INT8 表示,从量化到非量化值的转换只是一个乘法。在相反的方向上,量化使用倒数尺度,然后是舍入和钳位。要启用任何量化操作,必须在构建器配置中设置 INT8 标志。7.1.1. Quantization Workflows创建量化网络有两种工作流程:训https://blog.csdn.net/kunhe0512/article/details/124506907
基于 TensorRT 实现 Bert 预训练模型推理加速(超详细-附核心代码-避坑指南) - 知乎更新日志: 2022.01.14:八-1,导出ONNX文件,输出设置动态尺寸,增加FP16精度加速数据一、前言本文主要基于 TensorRT 实现 Bert 预训练模型的推理加速,完成这篇笔记的内容,你可以了解以下知识点: 使用 NVIDIA …https://zhuanlan.zhihu.com/p/446477075
【理论知识】实际部署中tensorrt的简单理解_qqsuiying的博客-CSDN博客_tensorrt部署因为各种项目的原因,其实已经用过一段时间tensorrt了,但是一直没仔细梳理过理论知识了,在b站刷到官方教程,写个博客梳理一下tensorrt基础知识和开发流程。(写到一半莫名其妙后半部分被csdn吞了,草稿找不到了,以后还是本地写了)tensorrt简介tensorrt是NV官方的深度学习部署工具➢ 用于高效实现已训练好的深度学习模型的推理过程的 SDK ➢ 内含推理优化器和运行时环境 ➢ 使 DL 模型能以更高吞吐量和更低的延迟运行 ➢ 有 C++ 和 python 的 API,完全等价可以混用tenhttps://blog.csdn.net/qqsuiying/article/details/125272916
TensorRT8.2最新版入门教程 - 知乎废话不多说,下面进入正题。最近搞了几周TensorRT感知模型部署,查阅了很多资料,发现之前的博客要么是版本太老,不适用新版本,要么是案例代码不全(如老潘),不利于初学者入门。遂花时间重新走了一遍安装流程,并…https://zhuanlan.zhihu.com/p/467401558
什么是TensorRT - 知乎Tensor是一个有助于在NVIDIA图形处理单元(GPU)上高性能推理c++库。它旨在与TesnsorFlow、Caffe、Pytorch以及MXNet等训练框架以互补的方式进行工作,专门致力于在GPU上快速有效地进行网络推理。 如今现有的一些训…https://zhuanlan.zhihu.com/p/356072366
TensorRT概览_人工智能曾小健的博客-CSDN博客_tensorrt使用cpuTensorRT能加速模型吗?能!根据官方文档,使用TensorRT,在CPU或者GPU模式下其可提供10X乃至100X的加速。本人的实际经验中,TensorRT提供了20X的加速。TensorRT为什么能提升模型的运行速度?TensorRT是英伟达针对自家平台做的加速包,TensorRT主要做了这么两件事情,来提升模型的运行速度。TensorRT支持INT8和FP16的计算。深度学习网络在训练时,通常使用 32 位或 16 位数据。TensorRT则在网络的推理时选用不这么高的精度,达到加https://blog.csdn.net/sinat_37574187/article/details/119801045
https://www.jianshu.com/p/b7404294041ehttps://www.jianshu.com/p/b7404294041e
========================================================================
因为各种项目的原因,其实已经用过一段时间tensorrt了,但是一直没仔细梳理过理论知识了,在b站刷到官方教程,写个博客梳理一下tensorrt基础知识和开发流程。
(写到一半莫名其妙后半部分被csdn吞了,草稿找不到了,以后还是本地写了)
tensorrt简介
tensorrt是NV官方的深度学习部署工具
➢ 用于高效实现已训练好的深度学习模型的推理过程的 SDK ➢ 内含推理优化器和运行时环境 ➢ 使 DL 模型能以更高吞吐量和更低的延迟运行 ➢ 有 C++ 和 python 的 API,完全等价可以混用
tensorrt主要进行以下工作
➢ 构建期(推理优化器) ➢ 模型解析 / 建立 加载 Onnx 等其他格式的模型 / 使用原生 API 搭建模型 ➢ 计算图优化 横向层融合(Conv),纵向层融合(Conv+add+ReLU), …… ➢ 节点消除 去除无用层,节点变换(Pad, Slice, Concat, Shuffle), …… ➢ 多精度支持 FP32 / FP16 / INT8 / TF32(可能插入 reformat 节点) ➢ 优选 kernel / format 硬件有关优化 ➢ 导入 plugin 实现自定义操作 ➢ 显存优化 显存池复用 ➢ 运行期(运行时环境) ➢ 运行时环境 对象生命期管理,内存显存管理,异常处理 ➢ 序列化反序列化 推理引擎保存为文件或从文件中加载
2.tensorrt的部署简要流程
搭建tensorrt的基本流程
➢ 基本流程 ➢ 构建期 ➢ 建立 Builder(引擎构建器) ➢ 创建 Network(计算图内容) ➢ 生成 SerializedNetwork(网络的 TRT 内部表示) ➢ 运行期 ➢ 建立 Engine 和 Context ➢ Buffer 相关准备(Host 端 + Device 端 + 拷贝操作) ➢ 执行推理(Execute)
示例代码在官方github的01-SimpleDemo/TensorRT8中的 TRT8-cudart.py 或 TRT8.cpp(python 和 C++ 等价版本)
官方github上的代码更新过,和教程不完全相同,但思路完全一样。
构建期:
logger = trt.Logger(trt.Logger.ERROR) # 指定 Logger,可用等级:VERBOSE,INFO,WARNING,ERRROR,INTERNAL_ERROR
if os.path.isfile(trtFile): # 如果有 .plan 文件则直接读取
with open(trtFile, 'rb') as f:
engineString = f.read()
if engineString == None:
print("Failed getting serialized engine!")
return
print("Succeeded getting serialized engine!")
else: # 没有 .plan 文件,从头开始创建
builder = trt.Builder(logger) # 网络元信息,Builder/Network/BuilderConfig/Profile 相关
network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
profile = builder.create_optimization_profile()
config = builder.create_builder_config()
config.max_workspace_size = 1 << 30
inputTensor = network.add_input('inputT0', trt.DataType.FLOAT, [-1, -1, -1]) # 指定输入张量
profile.set_shape(inputTensor.name, [1, 1, 1], [3, 4, 5], [6, 8, 10]) # 指定输入张量 Dynamic Shape 范围
config.add_optimization_profile(profile)
identityLayer = network.add_identity(inputTensor) # 恒等变换
network.mark_output(identityLayer.get_output(0)) # 标记输出张量
engineString = builder.build_serialized_network(network, config) # 生成序列化网络
if engineString == None:
print("Failed getting serialized engine!")
return
print("Succeeded getting serialized engine!")
with open(trtFile, 'wb') as f: # 将序列化网络保存为 .plan 文件
f.write(engineString)
print("Succeeded saving .plan file!")
运行期:
```engine = trt.Runtime(logger).deserialize_cuda_engine(engineString) # 使用 Runtime 来创建 engine
if engine == None:
print("Failed building engine!")
return
print("Succeeded building engine!")
context = engine.create_execution_context() # 创建 context(相当于 GPU 进程)
context.set_binding_shape(0, [3, 4, 5]) # Dynamic Shape 模式需要绑定真实数据形状
nInput = np.sum([engine.binding_is_input(i) for i in range(engine.num_bindings)]) # 获取 engine 绑定信息
nOutput = engine.num_bindings - nInput
for i in range(nInput):
print("Bind[%2d]:i[%2d]->" % (i, i), engine.get_binding_dtype(i), engine.get_binding_shape(i), context.get_binding_shape(i), engine.get_binding_name(i))
for i in range(nInput,nInput+nOutput):
print("Bind[%2d]:o[%2d]->" % (i, i - nInput), engine.get_binding_dtype(i), engine.get_binding_shape(i), context.get_binding_shape(i), engine.get_binding_name(i))
data = np.arange(3 * 4 * 5, dtype=np.float32).reshape(3, 4, 5) # 准备数据和 Host/Device 端内存
bufferH = []
bufferH.append(np.ascontiguousarray(data.reshape(-1)))
for i in range(nInput, nInput + nOutput):
bufferH.append(np.empty(context.get_binding_shape(i), dtype=trt.nptype(engine.get_binding_dtype(i))))
bufferD = []
for i in range(nInput + nOutput):
bufferD.append(cudart.cudaMalloc(bufferH[i].nbytes)[1])
for i in range(nInput): # 首先将 Host 数据拷贝到 Device 端
cudart.cudaMemcpy(bufferD[i], bufferH[i].ctypes.data, bufferH[i].nbytes, cudart.cudaMemcpyKind.cudaMemcpyHostToDevice)
context.execute_v2(bufferD) # 运行推理计算
for i in range(nInput, nInput + nOutput): # 将结果从 Device 端拷回 Host 端
cudart.cudaMemcpy(bufferH[i].ctypes.data, bufferD[i], bufferH[i].nbytes, cudart.cudaMemcpyKind.cudaMemcpyDeviceToHost)
for i in range(nInput + nOutput):
print(engine.get_binding_name(i))
print(bufferH[i].reshape(context.get_binding_shape(i)))
for b in bufferD: # 释放 Device 端内存
cudart.cudaFree(b)
tensorrt搭建与开发方式 官方列出了三种方案
➢ 使用框架自带 TRT 接口(TF-TRT, Torch-TensorRT) ➢ 简单灵活,部署仍在原框架中,无需书写 Plugin
➢ 使用 Parser(TF/Torch/… → ONNX[1] → TensorRT) ➢ 流程成熟, ONNX 通用性好,方便网络调整,兼顾效率性能
➢ 使用 Parser(TF/Torch/… → ONNX[1] → TensorRT) ➢ 流程成熟, ONNX 通用性好,方便网络调整,兼顾效率性能
三种方案各有优劣
我自己做过的以及网上开源的项目中,更过是采用第二种方式,第一种方案也有,第三种则见得少一些(毕竟我也是刚开始接触tensorrt)
github中也给出了使用API搭建MNIST手写识别模型的示例
不过pytorch和paddle的demo都是TODO待更新,目前只有TensorFlow的
代码基本流程如下: ➢ TensorFlow 中创建并训练一个网络 ➢ 提取网络权重,保存为 para.npz ➢ TensorRT 中重建该网络并加载 para.npz 中的权重 ➢ 生成推理引擎 ➢ 用引擎做实际推理
tensorrt运行期
engine是trt中的计算引擎,有点类似于cpu计算中的线程,算是基本计算单元。
➢生成 TRT 内部表示 ➢ serializedNetwork = builder. build_serialized_network(network, config) ➢生成 Engine ➢ engine = trt.Runtime(logger).deserialize_cuda_engine( serializedNetwork ) ➢创建 Context ➢ context = engine.create_execution_context() ➢绑定输入输出(Dynamic Shape 模式必须) ➢ context.set_binding_shape(0,[1,1,28,28]) ➢准备 Buffer ➢ inputHost = np.ascontiguousarray(inputData.reshape(-1)) ➢ outputHost = np.empty(context.get_binding_shape(1), trt.nptype(engine.get_binding_dtype(1))) ➢ inputDevice = cudart.cudaMalloc(inputHost.nbytes)[1] ➢ outputDevice = cudart.cudaMalloc(outputHost.nbytes)[1] ➢执行计算 ➢ cudart.cudaMemcpy(inputDevice, inputHost.ctypes.data, inputHost.nbytes, cudart.cudaMemcpyKind.cudaMemcpyHostToDevice) ➢ context.execute_v2([int(inputDevice), int(outputDevice)]) ➢ cudart.cudaMemcpy(outputHost.ctypes.data, outputDevice, outputHost.nbytes, cudart.cudaMemcpyKind.cudaMemcpyDeviceToHost)
这里补了一点 CUDA异构计算的知识
➢CUDA 异构计算 ➢ 同时准备 CPU 端内存和 GPU端显存 ➢ 开始计算前把数据从内存拷贝到显存中 ➢ 计算过程的输入输出数据均在 GPU端读写 ➢ 计算完成后要把结果拷贝会内存才能使用
在运行过程中就需要涉及到内存和显存的数据拷贝
➢Buffer ➢ 内存和显存的申请 ➢ inputHost = np.ascontiguousarray(inputData.reshape(-1)) ➢ outputHost = np.empty(context.get_binding_shape(1), trt.nptype(engine.get_binding_dtype(1))) ➢ inputDevice = cudart.cudaMalloc(inputHost.nbytes)[1] ➢ outputDevice = cudart.cudaMalloc(outputHost.nbytes)[1]
➢ 内存和显存之间的拷贝 ➢ cudart.cudaMemcpy(inputDevice, inputHost.ctypes.data, inputHost.nbytes, cudart.cudaMemcpyKind.cudaMemcpyHostToDevice) ➢ cudart.cudaMemcpy(outputHost.ctypes.data, outputDevice, outputHost.nbytes, cudart.cudaMemcpyKind.cudaMemcpyDeviceToHost)
➢ 推理完成后释放显存 ➢ cudart.cudaFree(inputDevice) ➢ cudart.cudaFree(outputDevice)
1
1
开发者辅助工具
➢trtexec TensorRT 命令行工具,主要的 End2End 性能测试工具 ➢Netron 网络可视化 ➢onnx-graphsurgeon onnx 计算图编辑 ➢polygraphy 结果验证与定位,图优化 ➢Nsight Systems 性能分析
等用熟了之后看看能不能单独写个博客
主要参考自nvidia官方给出的教程,教程是基于8.2.3版本的TensorRT。
trt-samples-for-hackathon-cn/cookbook at master · NVIDIA/trt-samples-for-hackathon-cn · GitHub
在b站官方还有个简单的讲解视频,不过个人觉得ppt比讲解本身重要一点。
以及
(7条消息) TensorRT 之入门篇点PY的博客-CSDN博客tensorrt教程