五. TensorRT API的基本使用-TensorRT-network-structure

目录

    • 前言
    • 0. 简述
    • 1. 案例运行
    • 2. 代码分析
      • 2.1 main.cpp
      • 2.2 model.cpp
    • 总结
    • 下载链接
    • 参考

前言

自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》,链接。记录下个人学习笔记,仅供自己参考

本次课程我们来学习课程第五章—TensorRT API 的基本使用,一起来学习打印网络模型结构

课程大纲可以看下面的思维导图

在这里插入图片描述

0. 简述

本小节目标:学习如何打印优化前后网络模型结构

今天我们来讲第五章节第四小节—5.4-print-structure 这个案例,来看下经过 TensorRT 优化前后网络的结构有什么样的变化

下面我们开始本次课程的学习🤗

1. 案例运行

在正式开始课程之前,博主先带大家跑通 5.4-print-structure 这个小节的案例🤗

源代码获取地址:https://github.com/kalfazed/tensorrt_starter.git

首先大家需要把 tensorrt_starter 这个项目给 clone 下来,指令如下:

git clone https://github.com/kalfazed/tensorrt_starter.git

也可手动点击下载,点击右上角的 Code 按键,将代码下载下来。至此整个项目就已经准备好了。也可以点击 here 下载博主准备好的源代码(注意代码下载于 2024/7/14 日,若有改动请参考最新

整个项目后续需要使用的软件主要有 CUDA、cuDNN、TensorRT、OpenCV,大家可以参考 Ubuntu20.04软件安装大全 进行相应软件的安装,博主这里不再赘述

假设你的项目、环境准备完成,下面我们来一起运行 5.4 小节案例代码

开始之前我们需要创建几个文件夹,在 tensorrt_starter/chapter5-tensorrt-api-basics/5.4-print-structure 小节中创建一个 models 文件夹,接着在 models 文件夹下创建 onnx 和 engine 文件夹,总共三个文件夹需要创建

创建完后 5.4 小节整个目录结构如下:

在这里插入图片描述

接着我们需要执行 python 文件创建一个 ONNX 模型,先进入到 5.4 小节中:

cd tensorrt_starter/chapter5-tensorrt-api-basics/5.4-print-structure

执行如下指令:

python src/python/generate_onnx.py

Note:大家需要准备一个虚拟环境,安装好 torch、onnx、onnxsim 等第三方库

输出如下:

在这里插入图片描述

生成好的 onnx 模型文件保存在 models/onnx 文件夹下,大家可以查看

接着我们需要利用 ONNX 生成对应的 engine,在此之前我们需要修改下整体的 Makefile.config,指定一些库的路径:

# tensorrt_starter/config/Makefile.config
# CUDA_VER                    :=  11
CUDA_VER                    :=  11.6# opencv和TensorRT的安装目录
OPENCV_INSTALL_DIR          :=  /usr/local/include/opencv4
# TENSORRT_INSTALL_DIR        :=  /mnt/packages/TensorRT-8.4.1.5
TENSORRT_INSTALL_DIR        :=  /home/jarvis/lean/TensorRT-8.6.1.6

Note:大家查看自己的 CUDA 是多少版本,修改为对应版本即可,另外 OpenCV 和 TensorRT 修改为你自己安装的路径即可

然后我们还要简单修改下源码,在 src/cpp/main.cpp 中默认打印的 ONNX 是 vgg16.onnx,我们修改为 sample.onnx,修改如下所示:

# src/cpp/main.cpp
int main(int argc, char const *argv[])
{Model model("models/onnx/sample.onnx");// Model model("models/onnx/resnet50.onnx");// Model model("models/onnx/vgg16.onnx");...
}

接着我们就可以来执行编译,指令如下:

make -j64

输出如下:

在这里插入图片描述

接着执行:

./trt-infer

输出如下:

在这里插入图片描述

我们这里读取一个模型,然后将模型优化前后信息都打印出来了,我们的模型是使用的上节课的 onnx,就是一个 Linear 层

Note:博主这里也准备了 resnet50 和 vgg16 的 ONNX 模型,大家可以点击 here 下载,然后运行代码看下 resnet50 和 vgg16 在 TensorRT 优化前后有什么区别

如果大家能够看到上述输出结果,那就说明本小节案例已经跑通,下面我们就来看看具体的代码实现

2. 代码分析

2.1 main.cpp

我们先从 main.cpp 看起:

#include <iostream>
#include <memory>#include "utils.hpp"
#include "model.hpp"using namespace std;int main(int argc, char const *argv[])
{Model model("models/onnx/sample.onnx");// Model model("models/onnx/resnet50.onnx");// Model model("models/onnx/vgg16.onnx");if(!model.build()){LOGE("fail in building model");return 0;}// if(!model.infer()){//     LOGE("fail in infering model");//     return 0;// }return 0;
}

与之前 build 的案例一样,这里只提供 build 的接口,然后在 build 函数中我们对模型的结构进行打印,除了 sample.onnx 外这边还有 resnet50.onnx 和 vgg16.onnx,大家可以都测试下

博主这边还测试了 resnet50.onnx 经过 tensorRT 优化前后的网络结构打印:

在这里插入图片描述

resnet50.onnx优化前

在这里插入图片描述

resnet50.onnx优化后

可以看到优化前有 126 层,都是 conv+relu,每一层的输入输出维度以及精度都有打印;优化后只有 79 层,可以看懂 tensorRT 做了很多层融合,比如 conv+relu 融合,conv+add+relu 融合等等

我们再看下 vgg16.onnx:

在这里插入图片描述

vgg16.onnx优化前

在这里插入图片描述

vgg16.onnx优化后

可以看到 vgg16 优化前有 49 个 layer,基本上就是 conv+relu+maxpool 的组合,优化后只有 25 层,tensorRT 做了一些层融合操作

2.2 model.cpp

相比于之前的 build 案例代码,它新增了如下代码:

bool Model::build(){...// 把优化前和优化后的各个层的信息打印出来LOG("Before TensorRT optimization");print_network(*network, false);LOG("");LOG("After TensorRT optimization");print_network(*network, true);return true;
};

那它通过调用 print_network 函数打印网络结构信息,其中该函数接受两个参数传递,一个是 network,一个是 bool 变量,用来指定打印优化前还是优化后的网络结构

我们重点来看下该函数的实现:

int inputCount = network.getNbInputs();
int outputCount = network.getNbOutputs();
string layer_info;for (int i = 0; i < inputCount; i++) {auto input = network.getInput(i);LOG("Input info: %s:%s", input->getName(), printTensorShape(input).c_str());
}for (int i = 0; i < outputCount; i++) {auto output = network.getOutput(i);LOG("Output info: %s:%s", output->getName(), printTensorShape(output).c_str());
}

首先我们通过 network 获取模型输入和输出的数量,接着对于每个 input 和 output,我们都把它的 name 和 shape 给打印出来。network 的 getInputgetOutput 方法返回的是一个 ITensor* 类型的变量,从 ITensor 中我们可以获取它的 dimension、name、type 等信息

其中的 printTensorShape 函数的内容如下:

string printTensorShape(nvinfer1::ITensor* tensor){string str;str += "[";auto dims = tensor->getDimensions();for (int j = 0; j < dims.nbDims; j++) {str += to_string(dims.d[j]);if (j != dims.nbDims - 1) {str += " x ";}}str += "]";return str;
}

通过 getDimensions 获取 ITensor 的维度信息,之后遍历 nbDims 将每个维度的信息给打印出来就行

OK,我们接着往下看:

int layerCount = optimized ? mEngine->getNbLayers() : network.getNbLayers();
LOG("network has %d layers", layerCount);

通过 optimized 变量我们选择不同的 API 接口获取 layer 总数量,如果 optimized 为 true 那么我们从 mEngine 中去拿 layer 总层数,如果 optimized 为 false,那么我们从 network 中去拿 layer 总层数,接着将网络总层数打印出来

其中的 IEngine 我们可以认为它是已经用 tensorR 优化好的模型,而 INetwork 我们可以认为它是还没有用 tensorRT 优化,刚刚通过 parser 给 parse 出来的模型

我们下面看优化前后模型结构如何打印:

if (!optimized) {for (int i = 0; i < layerCount; i++) {char layer_info[1000];auto layer   = network.getLayer(i);auto input   = layer->getInput(0);int n = 0;if (input == nullptr){continue;}auto output  = layer->getOutput(0);LOG("layer_info: %-40s:%-25s->%-25s[%s]", layer->getName(),printTensorShape(input).c_str(),printTensorShape(output).c_str(),getPrecision(layer->getPrecision()).c_str());}
}

如果打印没有被优化的模型结构,则先遍历 layerCount,然后通过 getLayer 方法拿到层信息,接着通过 layer 的 getInput 和 getOutput 方法拿到对应层的输入输出,接着把层的 name、input shape、output shape、precision 给打印出来

我们再来看优化后:

auto inspector = make_unique<nvinfer1::IEngineInspector>(mEngine->createEngineInspector());
for (int i = 0; i < layerCount; i++) {string info = inspector->getLayerInformation(i, nvinfer1::LayerInformationFormat::kONELINE);info = info.substr(0, info.size() - 1);LOG("layer_info: %s", info.c_str());
}

这里我们通过 createEngineInspector 创建了一个 inspector 来查看 engine 内部信息,接着通过 inspector 的 getLayerInformation 获取每一层的信息,它直接返回的就是一个字符串。它有两个参数,第一个参数代表获取的是第几个 layer,第二个参数代表想获取的 layer info 的格式,可以有 JSON、ONELINE 格式

OK,这就是 print network structure 的全部内容,内容不多,比较简单

总结

本次课程我们主要学习了如何打印 tensorRT 优化前后的网络结构,可以方便我们对比 tensorRT 都做了哪些优化,优化前我们主要是通过 INetwork 获取 layer 信息,优化后我们主要是 ICudaEngine 获取 layer 信息,此外一些类的定义包括 ITensor、ILayer、INetwork、ICudaEngine、IExecutionContext、IBuilder 等等大家可以看下官方文档理解其含义

OK,以上就是 5.4 小节案例的全部内容了,下节我们来学习 5.5 小节来利用 C++ API 手动搭建网络模型,敬请期待😄

下载链接

  • tensorrt_starter源码
  • 5.4-TensorRT-network-structure案例文件

参考

  • Ubuntu20.04软件安装大全
  • https://github.com/kalfazed/tensorrt_starter.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/49810.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redisson分布式锁使用详解

引言 日常开发中&#xff0c;难免遇到一些并发的场景&#xff0c;为了保证接口执行的一致性&#xff0c;通常采用加锁的方式&#xff0c;因为服务是分布式部署模式&#xff0c;本地锁Reentrantlock和Synchnorized这些就先放到一边了&#xff0c;Redis的setnx锁存在无法抱保证原…

九-2、Rocky Linux软件包管理与安装 学习笔记

1. DNF的rocky linux管理 DNF: Dandified YUM,基于RPM的Linux软件包管理器&#xff0c;是YUM的下一代版本。 Dnf命令和yum命令兼容&#xff0c;依然使用yum仓库。 dnf module在软件安装上更方便&#xff0c;可以通过dnf module install 在安装软件时指定安装的版本&#xff0…

QT开发(QT的基本概述和环境的安装)

QT的概述 一.QT的介绍背景1.1 什么是QT1.2QT的发展史1.3 Qt支持的平台1.4QT版本1.5QT的优点1.6QT的应用场景 二.搭建QT开发环境2.1 QT的开发工具的下载2.2 QT环境变量配置 三.QT的三种基类四.QT Hello World程序4.1使用按钮实现4.1.1 代码方式实现4.1.2 可视化操作实现 一.QT的…

【C#】在一个给定的宽、高范围内,获取到该多边形内部的所有坐标集合?

问题点 使用C#语言在一个给定的宽、高范围内&#xff0c;获取到该多边形内部的所有坐标集合&#xff1f; 这个多边形可能存在交叉及互相重叠部分 图像的宽、高可以定义为&#xff1a;2000*2000 多边形坐标集合&#xff1a;Point[] polygon_points new Point[] { new Point…

如何在vscode中对在服务器上多卡运行的bash脚本进行debug?

问题描述 使用vscode可以很方便地添加断点&#xff0c;进行代码调试。 在使用服务器时&#xff0c;我们的python代码通常是通过bash脚本来执行的&#xff0c;那么如何进行debug呢&#xff1f; 待运行的bash 脚本示例 前半段定义了一些参数&#xff0c;后半段是执行python代码…

数据结构的概念和术语

目录 一.前言 二.数据结构的基本概念 三.数据结构的术语 一.前言 数据结构是一门研究非数值计算的程序设计中计算机的操作对象以及它们之间的关系和操作的学科。数据结构的基本数据结构包括两部分&#xff0c;线性结构跟非线性结构。 二.数据结构的基本概念 数据结构主要包括…

压测实操--kafka broker压测方案

作者&#xff1a;九月 环境信息&#xff1a; 操作系统centos7.9&#xff0c;kafka版本为hdp集群中的2.0版本。 kafka broker参数 num.replica.fetchers&#xff1a;副本抓取的相应参数&#xff0c;如果发生ISR频繁进出的情况或follower无法追上leader的情况则适当增加该值&…

CTF ssrf 基础入门

0x01 引言 我发现我其实并不是很明白这个东西&#xff0c;有些微妙&#xff0c;而且记忆中也就记得Gopherus这个工具了&#xff0c;所以重新学习了一下&#xff0c;顺便记录一下吧 0x02 辨别 我们拿到一个题目&#xff0c;他的名字可能就是题目类型&#xff0c;但是也有可能…

【使用 Pytest 记录日志文件并确保测试用例正常执行】

1. 更新测试脚本 首先&#xff0c;确保你的测试脚本 wifi_test.py 配置了日志记录&#xff0c;并包含所有测试用例&#xff1a; import subprocess import time import logging import pytest import sys# 配置日志记录 logging.basicConfig(filenamewifi_test.log, levellog…

vue侦听器(Watch)精彩案例剖析一

目录 watch介绍 监视普通数据类型 监视对象类型 watch介绍 在 Vue 中,watch主要用于监视数据的变化,并执行相应操作。一旦被监视的属性发生变化,回调函数将自动被触发。当在 Vue 中使用watch来响应数据变化时,首先要清楚,watch本质上是一个对象,且必须以对象的…

HDShredder 7 企业版案例分享: 依照国际权威标准,安全清除企业数据

HDShredder 7 企业版用户案例 天津鸿萌科贸发展有限公司是德国 Miray 公司 HDShredder 数据清除软件的授权代理商。近日&#xff0c;上海某网络科技有限公司采购 HDShredder 7 企业版x4&#xff0c;为公司数据存储资产的安全清除工作流程配备高效的执行工具。HDShredder 7 企业…

划分型dp,CF 1935C - Messenger in MAC

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1935C - Messenger in MAC 二、解题报告 1、思路分析 比较简单的思路是反悔贪心&#xff0c;这里不展开说了&#xff0c;来说一下dp的做法 由于式子里面带绝对值&#xff0c;很烦&#xff0c;我们将pair按…

Bootstrap实现dialog上一步下一步多个弹窗交互

Bootstrap实现dialog上一步下一步多个弹窗交互 版本介绍&#xff1a; Bootstrap v3.3.7jQuery v3.5.1 一、功能介绍 重新设置bootstrap主题色内容区以card形式展示&#xff0c;纯js实现分页功能共两步骤&#xff0c;第一步选择模板&#xff0c;第二步进行其他操作步骤一内的按…

特征工程在机器学习中的重要性

特征工程在机器学习中的重要性 特征工程在机器学习中占据着至关重要的地位&#xff0c;它是连接原始数据与机器学习模型之间的桥梁。通过特征工程&#xff0c;我们可以将原始数据转换为机器学习算法能够有效利用的形式&#xff0c;从而提高模型的性能和准确性。以下是特征工程…

JAVA毕业设计153—基于Java+Springboot+小程序的校园维修管理系统小程序(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringboot小程序的校园维修管理系统小程序(源代码数据库)153 一、系统介绍 本项目分为用户、维修员、管理员三种角色 1、用户&#xff1a; 注册、登录、报修申报、报修…

师资培训丨AIGC 技术与大模型应用开发实战线下广州班莅临泰迪智能科技参观调研

7月23日&#xff0c;2024年第二期全国数字人才技能提升师资培训班——AIGC 技术与大模型应用开发实战线下广州班莅临广东泰迪智能科技股份有限公司产教融合实训基地参观调研&#xff0c;来自全国各地三十多名高校教师参与本次活动。泰迪智能科技董事长张良均、校企合作经理吴桂…

【Gin】架构的精妙编织:Gin框架中组合模式的革新实践与技术深度解析(上)

【Gin】架构的精妙编织&#xff1a;Gin框架中组合模式的革新实践与技术深度解析(上) 大家好 我是寸铁&#x1f44a; 【Gin】架构的精妙编织&#xff1a;Gin框架中组合模式的革新实践与技术深度解析(上)✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言 本次文章分为上下两部分…

【区块链+绿色低碳】基于区块链的企业碳管理平台 | FISCO BCOS应用案例

在当今全球气候变化和环境问题日益严重的背景下&#xff0c;碳减排已成为全球共同面临的重要任务。作为能源消耗大户&#xff0c; 现代企业必须认识到碳减排的重要性&#xff0c;并采取有效措施实现碳减排。通过完善碳资产管理&#xff0c;企业可以清晰地了解 自身的碳排放情况…

矩估计与最大似然估计的通俗理解

点估计与区间估计 矩估计与最大似然估计都属于点估计&#xff0c;也就是估计出来的结果是一个具体的值。对比区间估计&#xff0c;通过样本得出的估计值是一个范围区间。例如估计一个人的年龄&#xff0c;点估计就是最终直接估计年龄为50岁&#xff0c;而区间估计是最终估计的…

hicp学习 VRRP选举过程、MSTP+VRRP混合组网

VRRP 的选举规则 1、先比优先级&#xff0c;越大越优先&#xff0c;默认优先级是100.范围 0-255&#xff0c;可配置的范围是1-254。0和255这两个优先级是保留的不配置 0&#xff1a;用来告诉 Backup 立即成为 Master。一般是 Master 设备主动退出 VRRP 组&#xff08;人为删除…