onnx转换TensorRT的步骤

A. 解析onnx

已有的trt不适配,需要将onnx转为trt

  1. parse onnx
  2. serialize trt
  3. 保存trt文件

注意:如果不使用Int8模式,onnx的parser代码几乎通用

概览

构建阶段

  1. 建立logger(日志)
  2. 建立builder(网络元数据)
  3. 创建network(计算图)(API独需)
  4. 生成序列化的网络(网络的trt内部表示)

运行阶段

  1. 建立engine(可执行代码)
  2. 创建context(gpu进程)
  3. buffer准备(host+device)
  4. 拷贝host to device
  5. 执行推理execute
  6. 拷贝device to host
  7. 善后

A.1 构建阶段

1. 创建logger

记录器

getTRTLogger();

2. 创建builder

模型搭建的入口,网络的trt内部表示和引擎都是builder的成员方法生成的

builder.create_optimization_profile():创建用于dynamic shape输入的配置器

createInferBuilder()

builder.create_network():创建tensorrt网络对象

createNetworkV2()

在builderconfig下面进行细节设置


另外builder需要创建optimazation profile

在给定输入张量的最小最常见最大尺寸后,将设置的profile传给config

auto profile = builder->createOptimizationProfile();
profile->setDimensions();
config->addOptimizationProfile(profile);

3. 设置builder config

进行设置网络属性

config=builder.create_builder_config()

auto config = std::unique_ptr<nvinfer1::IBuilderConfig, samplesCommon::InferDeleter>(builder->createBuilderConfig());
  1. 指定构建期可用显存

  2. 设置标志位开关

  3. 指定校正器

  4. 添加用于dynamic shape输入的配置器

    config->addOptimizationProfile(profile);//添加用于dynamic shape输入的配置器
    config->setFlag();

4. 搭建network

创建network(计算图)是API独需的因为其他两种方法使用parser从onnx导入,不用一层层添加

network=builder.create_network()

在onnx-parser中一旦模型parser解析完成,network就自动填好了,成为了serialized network

onnx-parser解析

createParser(*network, sample::gLogger.getTRTLogger();
​
parser->parseFromFile(modelFile.c_str(), static_cast<int>(sample::gLogger.getReportableSeverity()));

A.2 运行阶段 runtime

5. 生成TRT内部表示-serialized network

build_serialized_network(network,config)

6. 生成engine

推理引擎,可执行的代码段

生成engine:

m_engine = std::unique_ptr<nvinfer1::ICudaEngine, samplesCommon::InferDeleter>(builder->buildEngineWithConfig(*network, *config), samplesCommon::InferDeleter());

7. 创建context

context即GPU进程

创建context:

python:engine.create_execution_context()

 m_context = std::unique_ptr<nvinfer1::IExecutionContext, samplesCommon::InferDeleter>(m_engine->createExecutionContext(), samplesCommon::InferDeleter());

绑定输入输出

仅dynamic shape需要

8. 准备buffer

  1. 内存和显存的分别申请
  2. 拷贝
  3. 释放

python:cudart.cudaMalloc(inputHost.nbytes)[1]

课程第四部分会对buffer部分的优化做介绍

9. 执行计算-execute

拷贝到cuda buffer上执行再拷贝回host,这一步一般是B.解析trt中做,但是读取onnx后也可以做

10. 序列化引擎

engine->serialize()

11. 导出trt

特殊情况

遇到tensorrt不支持的onnx模型节点

  1. 修改源模型
  2. 修改onnx计算图,onnx-surgeon
  3. tensorrt中实现plugin
  4. 修改parser:修改源码,重新编译trt,因为tensorrt部分开源

B. 解析trt

已有trt,直接导入然后使用

parse TRT后得到engine和context

1. 创建logger

getTRTLogger()

2. 创建cudaruntime

createInferRuntime()

3. 解析/反序列化trt文件,生成引擎

runtime->deserializeCudaEngine()

4. 创建context

engine->createExecutionContext()

5. 使用

相关推荐
陌小呆^O^5 分钟前
Cmakelist.txt之win-c-udp-server
c语言·开发语言·udp
C++忠实粉丝5 分钟前
计算机网络socket编程(3)_UDP网络编程实现简单聊天室
linux·网络·c++·网络协议·计算机网络·udp
lindsayshuo6 分钟前
jetson orin系列开发版安装cuda的gpu版本的opencv
人工智能·opencv
向阳逐梦7 分钟前
ROS机器视觉入门:从基础到人脸识别与目标检测
人工智能·目标检测·计算机视觉
Gu Gu Study12 分钟前
枚举与lambda表达式,枚举实现单例模式为什么是安全的,lambda表达式与函数式接口的小九九~
java·开发语言
时光の尘26 分钟前
C语言菜鸟入门·关键字·float以及double的用法
运维·服务器·c语言·开发语言·stm32·单片机·c
我们的五年31 分钟前
【Linux课程学习】:进程描述---PCB(Process Control Block)
linux·运维·c++
陈鋆32 分钟前
智慧城市初探与解决方案
人工智能·智慧城市
qdprobot32 分钟前
ESP32桌面天气摆件加文心一言AI大模型对话Mixly图形化编程STEAM创客教育
网络·人工智能·百度·文心一言·arduino
QQ395753323733 分钟前
金融量化交易模型的突破与前景分析
人工智能·金融