当前位置: 首页 > news >正文

从零开始 TensorRT(7)C++ 篇:解析 ONNX

前言

学习资料:
B站视频配套代码 cookbook

示例

参考源码:cookbook → 04-BuildEngineByONNXParser → pyTorch-ONNX-TensorRT

源码

C++ 代码量较多,已上传 GitHub
OpenCV 安装:

apt install libopencv-dev

(1)按 Python 篇中的方式将 RenNet-18 转为 ONNX

python generate_onnx.py

(2)编译运行

mkdir build
cd build
cmake ..
make
cd ../bin./demo
./demo --fp16
./demo --int8

解析

  在 cookbook 中,createCalibrationAndInferenceData.py 将 MNIST 数据存储为 npz 文件,并在 C++ 部分直接读取 Numpy 文件中的数据用于推理和校正,避免了图片解码的相关代码。
  本文示例依然是参考 cookbook,使用 ResNet 进行推理。将读取 Numpy 文件的部分改为读取本地图像,并利用 OpenCV 对图像进行预处理,Int8 模式中的校正器部分代码也有所改动。

(1)预处理

std::vector<float> loadImg(const std::string filename, int width, int height, int channel) {cv::Mat image = cv::imread(filename, cv::IMREAD_COLOR);if (image.empty()) {std::cerr << "Error: Unable to read image file." << std::endl;return std::vector<float>();}cv::cvtColor(image, image, cv::COLOR_BGR2RGB);cv::resize(image, image, cv::Size(width, height));image.convertTo(image, CV_32F, 1.0 / 255.0);cv::Scalar meanData(0.485, 0.456, 0.406);cv::Scalar stdData(0.229, 0.224, 0.225);cv::subtract(image, meanData, image);cv::divide(image, stdData, image);"上面图像读取、resize、归一化、标准化都是调用 OpenCV API 与 Python 代码大同小异""下面是对数组维度进行调整: (h,w,3)->(3,h,w)""这里先把图像拆分成三个通道, 依次将三通道中的数据放到data中""通常会直接对图像数据进行遍历放到data中, 效率应该更高"std::vector<cv::Mat> channels;cv::split(image, channels);std::vector<float> data(channel * height * width);int idx = 0;for (int c = 0; c < channel; ++c) {for (int h = 0; h < height; ++h) {for (int w = 0; w < width; ++w) {data[idx++] = channels[c].at<float>(h, w);}}}return data;
}

(2)校准器

"主要是构造函数和 getBatch 与 cookbook 有所不同"
"先看原版"
"这里与 Python 篇中的校准器有所不同"
"Python: 在所有校准数据中随机抽样 batchsize 个循环校正 nCalibration 次"
"C++: 在所有校准数据中依次获取 batchsize 个, 直到剩余数据不足一个 batch, nCalibration 参数并没有用到"
MyCalibrator::MyCalibrator(const std::string &calibrationDataFile, const int nCalibration, const Dims32 dim, const std::string &cacheFile):nCalibration(nCalibration), dim(dim), cacheFile(cacheFile), iBatch(0)
{cnpy::npz_t    npzFile = cnpy::npz_load(calibrationDataFile);cnpy::NpyArray array   = npzFile[std::string("calibrationData")];pData                  = array.data<float>();if (pData == nullptr){std::cout << "Failed getting calibration data!" << std::endl;return;}"nBatch 代替 nCalibration"nBatch   = array.num_bytes() / bufferSize;  "此处源码明显有误, 应该在 bufferSize 计算之后""nElement 计算数组中元素个数, 即 c*h*w"nElement = 1;for (int i = 0; i < dim.nbDims; ++i){nElement *= dim.d[i];}"bufferSize 为数组空间大小"bufferSize = sizeof(float) * nElement;cudaMalloc((void **)&bufferD, bufferSize);return;
}bool MyCalibrator::getBatch(void *bindings[], char const *names[], int32_t nbBindings) noexcept
{if (iBatch < nBatch){cudaMemcpy(bufferD, &pData[iBatch * nElement], bufferSize, cudaMemcpyHostToDevice);bindings[0] = bufferD;iBatch++;return true;}else{return false;}
}
"本文示例将 calibrationDataDir 文件夹内的图像文件作为校准数据, 代替 cookbook 中的 Numpy 数据"
MyCalibrator::MyCalibrator(const std::string &calibrationDataDir, const int nCalibration, const Dims32 dim, const std::string &cacheFile):nCalibration(nCalibration), dim(dim), cacheFile(cacheFile), iBatch(0) {"range-based loop, 用于遍历容器或其他可迭代对象中元素的循环结构""与 Python 中的循环类似 for entry in os.listdir(dir)""const: 变量只读""auto: 自动推导类型""&: 引用, 避免拷贝""fs::directory_iterator: C++17中<filesystem>提供的功能"for (const auto& entry : fs::directory_iterator(calibrationDataDir)) {if (fs::is_regular_file(entry)) {files.push_back(entry.path().string());}}nBatch = files.size() / dim.d[0];nElement = 1;for (int i = 0; i < dim.nbDims; ++i) {nElement *= dim.d[i];}bufferSize = sizeof(float) * nElement;cudaMalloc((void **)&bufferD, bufferSize);return;
}bool MyCalibrator::getBatch(void* bindings[], char const* names[], int32_t nbBindings) noexcept {if (iBatch < nBatch) {for (int i = 0; i < dim.d[0]; ++i) {"逐个读取图像, 并把数据拷贝到 bufferD 中对应位置"std::vector<float> img = loadImg(files[iBatch*dim.d[0]+i], dim.d[3], dim.d[2], dim.d[1]);cudaMemcpy(&bufferD[i*img.size()], img.data(), img.size()*sizeof(float), cudaMemcpyHostToDevice);}bindings[0] = bufferD;iBatch++;return true;}else {return false;}
}

一个奇怪的 Bug

  在 int8 模式下,最初设置校正时 BatchSize 为1 calibrationBatchSize {1};,常见输入 BatchSize 为 4 profile->setDimensions(inputTensor->getName(), OptProfileSelector::kOPT, Dims32 {4, {4, nChannel, nHeight, nWidth}}); 时出现如下报错

Succeeded parsing .onnx file!
Failed finding cache file!
ERROR: 1: [calibrator.cpp::add::793] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
ERROR: 1: [executionContext.cpp::commonEmitDebugTensor::1855] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
ERROR: 1: [resizingAllocator.cpp::deallocate::105] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
...
ERROR: 1: [resizingAllocator.cpp::deallocate::105] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
ERROR: 3: [engine.cpp::~Engine::298] Error Code 3: API Usage Error (Parameter check failed at: runtime/api/engine.cpp::~Engine::298, condition: mExecutionContextCounter.use_count() == 1. Destroying an engine object before destroying the IExecutionContext objects it created leads to undefined behavior.
)
ERROR: 1: [cudaDriverHelpers.cpp::operator()::94] Error Code 1: Cuda Driver (an illegal memory access was encountered)
ERROR: 1: [cudaResources.cpp::~ScopedCudaStream::47] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
ERROR: 2: [calibrator.cpp::calibrateEngine::1181] Error Code 2: Internal Error (Assertion context->executeV2(&bindings[0]) failed. )
Failed building serialized engine!

  但是反复检查代码感觉没有非法的内存访问,偶然对常用输入的 BatchSize 修改后发现代码能跑通,便做了如下测试。按理来说 optBatchSize 和校正时的 BatchSize 没什么关系,多半是 TensorRT 内部的 Bug。

optBatchSizecalibrationBatchSizerun
51×
2×
3×
4
41×
2×
3×
4
31
2
3
4

相关文章:

从零开始 TensorRT(7)C++ 篇:解析 ONNX

前言 学习资料&#xff1a; B站视频配套代码 cookbook 示例 参考源码&#xff1a;cookbook → 04-BuildEngineByONNXParser → pyTorch-ONNX-TensorRT 源码 C 代码量较多&#xff0c;已上传 GitHub OpenCV 安装&#xff1a; apt install libopencv-dev&#xff08;1&…...

k8s集群的CA证书过期处理

文章目录 制作延期的CA证书获取CA全名准备签发申请配置生成新CA验证并替换CA 更新master组件的CA配置kube-apiserverkube-controller-managerkube-schedulerkube-admin检查证书过期时间 更新ServiceAccount secret更新node组件配置的CA更新kubelet连接配置签发kubelet自动申请的…...

linuxOPS基础_linux系统注意事项

Linux严格区分大小写 Linux 和Windows不同&#xff0c;Linux严格区分大小写的&#xff0c;包括文件名和目录名、命令、命令选项、配置文件设置选项等。 例如&#xff0c;Win7 系统桌面上有文件夹叫做Test&#xff0c;当我们在桌面上再新建一个名为 test 的文件夹时&#xff0c…...

《探索虚拟与现实的边界:VR与AR谁更能引领未来?》

引言 在当今数字时代,虚拟现实(VR)和增强现实(AR)技术正以惊人的速度发展,并逐渐渗透到我们的日常生活中。它们正在重新定义人与技术、人与环境之间的关系,同时也为各行各业带来了全新的可能性。然而,究竟是VR还是AR更有潜力改变未来?本文将围绕这一问题展开深入探讨。…...

C++ 获取上一级文件夹路径

我们可能会经常遇到文件所在文件夹路径的问题&#xff0c;虽然各大平台也有提供方便快捷的API来实现&#xff0c;但是如果脱离平台本身&#xff0c;或者想实现跨平台的话&#xff0c;可以考虑用纯C的代码来实现这一需求 示例代码 #include <string> #include <ios…...

Apache Pulsar的分布式集群模式构建

1. 准备环境 6台带jdk8的Linux服务器&#xff08;CentOS7为例&#xff09; ip分别为&#xff1a; 主机名IP地址zookeeper1192.168.8.101zookeeper2192.168.8.102zookeeper3192.168.8.103pulsar1192.168.8.108pulsar2192.168.8.109pulsar3192.168.8.110 2. 下载Pulsar最新安…...

第三百八十六回

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了Snackbar Widget相关的内容,本章回中将介绍TimePickerDialog Widget.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在这里说的TimePickerDialog是一种弹出窗口&#xff0c;只不过窗口的内容固定显示…...

Java中介者模式剖析及使用场景

中介者模式 一、介绍二、智能家居系统项目实现三、总结1.优点2.缺点3.使用经验4.Spring框架类似使用思想 一、介绍 介者模式是一种行为型设计模式&#xff0c;它允许对象之间通过一个中介者对象进行通信&#xff0c;而不是直接相互引用。将多对多的关系转化为一对多的关系&…...

ElevenLabs用AI为Sora文生视频模型配音 ,景联文科技提供高质量真人音频数据集助力生成逼真音效

随着Open AI公司推出的Sora文生视频模型惊艳亮相互联网&#xff0c;AI语音克隆创企ElevenLabs又为Sora的演示视频生成了配音&#xff0c;所有的音效均由AI创造&#xff0c;与视频内容完美融合。 ElevenLabs的语音克隆技术能够从一分钟的音频样本中创建逼真的声音。为了实现这一…...

Go语言基础

Go的数据类型定义 //运行第一个程序package main func main(){print("Hello World") }在GO语言中&#xff0c;一个程序只能有一个main包&#xff0c;对应只能有一个main方法&#xff0c;若无法满足这个条件&#xff0c;编译时将会报错。注释方式与PHP相同 import的使…...

IOS覆盖率报告info文件解读

一&#xff0c;IOS覆盖率报告的生成 在做前端精准测试的时候&#xff0c;对于iOS端&#xff0c;通常会做如下操作&#xff1a; &#xff08;1&#xff09;合并覆盖率数据 如下操作&#xff1a; xcrun llvm-profdata merge coverage_file1657885040728.profraw coverage_fil…...

爬虫实战——scrapy框架爬取多张图片

scrapy框架的基本使用&#xff0c;请参考我的另一篇文章&#xff1a;scrapy框架的基本使用 起始爬取的网页如下&#xff1a; 点击每张图片&#xff0c;可以进入图片的详情页&#xff0c;如下&#xff1a; 代码实现&#xff1a; 项目文件结构如下 img_download.py文件代码 im…...

LLVM TableGen 系统学习笔记

Basic TableGen 系统可以帮助记录领域特定的信息。它也可以认为是一种小型的编译系统。 TableGen 责负分析文件&#xff0c; 分析结果交给领域特定的后端进行处理。 重要的概念 records 一个 record 有一个独立的名称&#xff0c;一系列值和一系列父类。 它保存了特定领域…...

基于stm32的流水灯设计

1基于stm32的流水灯设计[proteus仿真] 速度检测系统这个题目算是课程设计和毕业设计中常见的题目了&#xff0c;本期是一个基于51单片机的自行车测速系统设计 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】&#xff0c;赞赏任意文章 2&#xffe5;&#xff0c…...

kotlin图片合成和压缩

kotlin图片合成和压缩 之前的方法是继承AsyncTask 在doInBackground 里面去做压缩的操作&#xff0c;然后用 publishProgress 切到主线程里面更新 新方法是在协程里的去做 class ImageService {private fun getSumWidths(bitmaps: ArrayList<Bitmap>): Int {var sumWid…...

Java学习笔记004——接口概念理解及意义

一个类中有抽象方法&#xff0c;则必须声明为abstract&#xff08;做为抽象类&#xff09;&#xff0c;抽象类不能实例化。子类继承抽象类&#xff0c;必须对所有的抽象方法重写&#xff0c;否则依然有抽象方法&#xff0c;还是抽象的&#xff0c;无法实例化。故抽象类常做为基…...

MT笔试题

前言 某团硬件工程师的笔试题&#xff0c;个人感觉题目的价值还是很高的&#xff0c;分为选择题和编程题&#xff0c;选择题考的是嵌入式基础知识&#xff0c;编程题是两道算法题&#xff0c;一道为简单难度&#xff0c;一道为中等难度 目录 前言选择题编程题 选择题 C语言中变…...

50道SQL面试题

50道SQL面试题 有需要互关的小伙伴,关注一下,有关必回关,争取今年认证早日拿到博客专家 环境 -- ---------------------------- -- Table structure for teacher -- ---------------------------- DROP TABLE IF EXISTS teacher; CREATE TABLE teacher (t_id varchar(20) …...

2024蓝桥杯每日一题(双指针)

一、第一题&#xff1a;牛的学术圈 解题思路&#xff1a;双指针贪心 仔细思考可以知道&#xff0c;写一篇综述最多在原来的H指数的基础上1&#xff0c;所以基本方法可以是先求出原始的H指数&#xff0c;然后分类讨论怎么样提升H指数。 【Python程序代码】 n,l map(int,…...

Android 开发过程中常见的内存泄漏场景分析

场景1 Static变量存储上下文环境Context public class ClassName {// 定义1个静态变量private static Context mContext;//... // 引用的是Activity的contextmContext context; // 当Activity需销毁时&#xff0c;由于mContext 静态 & 生命周期 应用程序的生命周期&…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...