Resnet C ++ 部署 tensort 部署(四)
Resnet C ++ 部署 pytorch功能测试(一)
Resnet C ++ 部署 模型训练(二)
Resnet C ++ 部署 模型测试&转 onnx(三)
Resnet C ++ 部署 tensort 部署(四)
之后,开始onnx 转trt 部署测试
1 代码
这是核心代码,改一下main 函数里面的参数,推理函数里面的参数即可运行
#include "NvInfer.h"
#include "cuda_runtime_api.h"
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <vector>
#include <chrono>
#include <cmath>
#include <cassert>
#include<Windows.h>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
// onnx转换头文件
#include "NvOnnxParser.h"
#include"read_config.hpp"
#include"labels.hpp"
#include "NvInferPlugin.h"
using namespace nvonnxparser;using namespace std;#define CHECK(status) \do\{\auto ret = (status);\if (ret != 0)\{\std::cerr << "Cuda failure: " << ret << std::endl;\abort();\}\} while (0)// stuff we know about the network and the input/output blobs
static const int INPUT_H = 224;
static const int INPUT_W = 224;
static const int OUTPUT_SIZE = 2;const char* INPUT_BLOB_NAME = "images";
const char* OUTPUT_BLOB_NAME = "prob";
void* global_buffers[2];using namespace nvinfer1;//static Logger gLogger;//构建Logger
class Logger : public ILogger
{void log(Severity severity, const char* msg) noexcept override{// suppress info-level messagesif (severity <= Severity::kWARNING)std::cout << msg << std::endl;}
} gLogger;// Creat the engine using only the API and not any parser.
ICudaEngine* createEngine(unsigned int maxBatchSize, IBuilder* builder, IBuilderConfig* config,string onnx_name)
{int dir_l = 0;int dir_r = onnx_name.rfind(".");string enginePath;onnx_name = onnx_name.substr(dir_l, dir_r)+".onnx";std::cout << "onnx_name:" << onnx_name << std::endl;const char* onnx_path = onnx_name.c_str();INetworkDefinition* network = builder->createNetworkV2(1U); //此处重点1U为OU就有问题IParser* parser = createParser(*network, gLogger);parser->parseFromFile(onnx_path, static_cast<int32_t>(ILogger::Severity::kWARNING));for (int32_t i = 0; i < parser->getNbErrors(); ++i) { std::cout << parser->getError(i)->desc() << std::endl; }std::cout << "successfully load the onnx model" << std::endl;// Build enginebuilder->setMaxBatchSize(maxBatchSize);builder->setMaxBatchSize(maxBatchSize);config->setMaxWorkspaceSize(1 << 20);config->setFlag(nvinfer1::BuilderFlag::kFP16); // 设置精度计算//config->setFlag(nvinfer1::BuilderFlag::kINT8);ICudaEngine* engine = builder->buildEngineWithConfig(*network, *config);std::cout << "successfully create engine " << std::endl;//销毁network->destroy();parser->destroy();return engine;
}void APIToModel(unsigned int maxBatchSize, IHostMemory** modelStream, string trt_name)
{// Create builderIBuilder* builder = createInferBuilder(gLogger);IBuilderConfig* config = builder->createBuilderConfig();std::cout << "trt_name:" << trt_name << std::endl;// Create model to populate the network, then set the outputs and create an engineICudaEngine* engine = createEngine(maxBatchSize, builder, config, trt_name);assert(engine != nullptr);// Serialize the engine(*modelStream) = engine->serialize();// Close everything downengine->destroy();builder->destroy();config->destroy();
}void do_Initial(int batchSize)
{//void* buffers[2];//buffers[0] = global_buffers[0];//buffers[1] = global_buffers[1];// Pointers to input and output device buffers to pass to engine.// Engine requires exactly IEngine::getNbBindings() number of buffers.// float* m_bindings[2];// In order to bind the buffers, we need to know the names of the input and output tensors.// Note that indices are guaranteed to be less than IEngine::getNbBindings()const int inputIndex = 0; //inputIndex = 0const int outputIndex = 1;//outputIndex = 1// Create GPU buffers on deviceCHECK(cudaMalloc(&global_buffers[inputIndex], batchSize * 3 * INPUT_H * INPUT_W * sizeof(float)));CHECK(cudaMalloc(&global_buffers[outputIndex], batchSize * OUTPUT_SIZE * sizeof(float)));// Release stream and buffers
}
void do_Inference(IExecutionContext *context_,float* input, float* output, int batchSize,cudaStream_t &stream)
{const int inputIndex = 0; //inputIndex = 0const int outputIndex = 1;//outputIndex = 1//void* buffers[2];//buffers[0] = global_buffers[0];//buffers[1] = global_buffers[1]; Create GPU buffers on device//CHECK(cudaMalloc(&buffers[inputIndex], batchSize * 3 * INPUT_H * INPUT_W * sizeof(float)));//CHECK(cudaMalloc(&buffers[outputIndex], batchSize * OUTPUT_SIZE * sizeof(float)));// Create streamCHECK(cudaStreamCreate(&stream));// DMA input batch data to device, infer on the batch asynchronously, and DMA output back to hostCHECK(cudaMemcpyAsync(global_buffers[inputIndex], input, batchSize * 3 * INPUT_H * INPUT_W * sizeof(float), cudaMemcpyHostToDevice, stream));context_->enqueueV2(global_buffers, stream, nullptr);//Changed by xfx20241202CHECK(cudaMemcpyAsync(output, global_buffers[outputIndex], batchSize * OUTPUT_SIZE * sizeof(float), cudaMemcpyDeviceToHost, stream));cudaStreamSynchronize(stream);
}void do_uninitial(cudaStream_t &stream, void* buffers[2])
{cudaStreamDestroy(stream);CHECK(cudaFree(buffers[0]));CHECK(cudaFree(buffers[1]));
}//加工图片变成拥有batch的输入, tensorrt输入需要的格式,为一个维度
void ProcessImage(vector<cv::Mat> images, float input_data[],const int batch_tem) {//只处理一张图片,总之结果为一维[batch*3*INPUT_W*INPUT_H]//以下代码为投机取巧了std::vector<cv::Mat> InputImage;if(images.size() != batch_tem){std::cout << "image batch is unequal to batch_tem" << std::endl;exit(-1);}for (int i = 0; i < batch_tem; ++i){cv::resize(images[i], images[i], cv::Size(INPUT_W, INPUT_H), 0, 0, cv::INTER_LINEAR);InputImage.push_back(images[i]);} int ImgCount = InputImage.size();//std::cout <<"ImgCount:" << ImgCount << std::endl;//float input_data[BatchSize * 3 * INPUT_H * INPUT_W];for (int b = 0; b < ImgCount; b++) {cv::Mat img = InputImage.at(b);int w = img.cols;int h = img.rows;int i = 0;for (int row = 0; row < h; ++row) {uchar* uc_pixel = img.data + row * img.step;for (int col = 0; col < INPUT_W; ++col) {input_data[b * 3 * INPUT_H * INPUT_W + i] = (float)uc_pixel[2] / 255.0;input_data[b * 3 * INPUT_H * INPUT_W + i + INPUT_H * INPUT_W] = (float)uc_pixel[1] / 255.0;input_data[b * 3 * INPUT_H * INPUT_W + i + 2 * INPUT_H * INPUT_W] = (float)uc_pixel[0] / 255.0;uc_pixel += 3;++i;}}}}int get_trtengine(string trt_name) {int dir_l = 0;int dir_r = trt_name.rfind(".");trt_name = trt_name.substr(dir_l, dir_r) + ".engine";IHostMemory* modelStream{ nullptr };APIToModel(100, &modelStream, trt_name);assert(modelStream != nullptr);std::ofstream p(trt_name, std::ios::binary);if (!p){std::cerr << "could not open plan output file" << std::endl;return -1;}p.write(reinterpret_cast<const char*>(modelStream->data()), modelStream->size());modelStream->destroy();return 0;}int infer(string trt_name, const int batch_tem_, int loop_time_) {int batch_tem = batch_tem_;int loop_time = loop_time_;int dir_l = 0;int dir_r = trt_name.rfind(".");trt_name = trt_name.substr(dir_l, dir_r) + ".engine";//加载engine引擎char* trtModelStream{ nullptr };size_t size{ 0 };std::ifstream file(trt_name, std::ios::binary);if (file.good()) {file.seekg(0, file.end);size = file.tellg();file.seekg(0, file.beg);trtModelStream = new char[size];assert(trtModelStream);file.read(trtModelStream, size);file.close();}//反序列为engine,创建contextIRuntime* runtime = createInferRuntime(gLogger);assert(runtime != nullptr);ICudaEngine* engine = runtime->deserializeCudaEngine(trtModelStream, size, nullptr);int32_t inputD = 0;// engine->getBindingDimensions(inputD).d[0]//auto engine->getBindingDimensions;assert(engine != nullptr);IExecutionContext* context = engine->createExecutionContext();assert(context != nullptr);delete[] trtModelStream;//*********************推理*********************//// 循环推理float time_read_img = 0.0;float time_infer = 0.0;float *prob = new float[batch_tem*OUTPUT_SIZE];float *data = new float[batch_tem * 3 * INPUT_H * INPUT_W];do_Initial(batch_tem);cudaStream_t stream;for (int loop = 0; loop < loop_time; loop++){// 处理图片为固定输出auto start = std::chrono::system_clock::now(); //时间函数 std::string path2 = "./data/cat.png";vector<cv::Mat> images;cv::Mat img2 = cv::imread(path2);//images.push_back(img);for (int i = images.size(); i < batch_tem; ++i){images.push_back(img2);}//--ProcessImage(images, data, batch_tem);auto end = std::chrono::system_clock::now();time_read_img = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() + time_read_img; start = std::chrono::system_clock::now(); //时间函数for (int i = 0; i < 1; ++i){do_Inference(context, data, prob, batch_tem, stream);}end = std::chrono::system_clock::now();time_infer = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() + time_infer;//std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;//输出后处理//std::cout <<"prob="<<prob << std::endl;ImageNetLabels labels;for (int batch = 0; batch < batch_tem; ++batch){float cls_float = prob[0];int cls_id = 0;for (int i = (0+batch)* OUTPUT_SIZE; i < (1+batch)*OUTPUT_SIZE; i++){if (cls_float < prob[i]){cls_float = prob[i];cls_id = i;}printf("ID %d %f: %s\n", i% OUTPUT_SIZE, prob[i],labels.imagenet_labelstring(i%1000).c_str());}//printf("LOOP_time:%d batch: %d result %d \n", loop,batch, cls_id % 100);printf("Batch:%d ClassId:%d Class name:%s \n", batch, cls_id%OUTPUT_SIZE, labels.imagenet_labelstring(cls_id % 1000).c_str());}}do_uninitial(stream, global_buffers);std::cout << "C++ engine" << "mean read img time = " << time_read_img / loop_time << "ms\t" << "mean infer img time =" << time_infer / loop_time << "ms" << std::endl;// Destroy the enginecontext->destroy();engine->destroy();runtime->destroy();return 0;
}int main(int argc, char** argv)
{bool didInitPlugins = initLibNvInferPlugins(nullptr, "");string init_config_path = "./config/config.yaml";InitParameter m_init_para=yaml_read(init_config_path);std::cout <<"batch size:" << m_init_para.batch_size << std::endl;std::cout << "loop time:" << m_init_para.batch_size << std::endl;std::cout << "deylay time:" << m_init_para.delay_time << std::endl;std::cout << "model path:" << m_init_para.model_path << std::endl;std::cout << "mode:" << m_init_para.mode<<std::endl;// string mode = argv[1];string mode = m_init_para.mode; //适用windows编译,固定指定参数//if (std::string(argv[1]) == "-s") {if (mode == "-s") {std::cout << "m_init_para.model_path:" << m_init_para.model_path << std::endl;get_trtengine(m_init_para.model_path);}//else if (std::string(argv[1]) == "-d") {else if (mode == "-d") {infer(m_init_para.model_path, m_init_para.batch_size, m_init_para.loop_time);}else {return -1;}return 0;
}
2 精度比较
| 图片 | .pt | .onnx | .trt |
|---|---|---|---|
| cat | [1.0000e+00, 1.4013e-45] | [1.0000e+00, 1.4013e-45] | [0.999920,0.000080] |
3 结论
可以看出 onnx 模型精度损失很小 .trt 精度损失较大
相关文章:
Resnet C ++ 部署 tensort 部署(四)
Resnet C 部署 pytorch功能测试(一) Resnet C 部署 模型训练(二) Resnet C 部署 模型测试&转 onnx(三) Resnet C 部署 tensort 部署(四) 之后,开始onnx 转trt 部…...
《Java核心技术I》对并发散列映射的批操作
对并发散列映射的批操作 Java API提供了批处理,计时其他线程处理映射,这些操作也能安全的执行。 3种不同操作: search(搜索),为每个键或值应用一个函数,直到函数生成一个非null的结果,然后搜索终止&…...
记录一次使用git无权限的问题排查
正常的配置了公私钥之后,在gitlab中也存储了配对的公钥,但当使用git clone 时,总是报无权限 由于在这台机器中添加了多个公私钥,有点复杂,我们可以使用命令 ssh -vvvT 调试一下 ssh -vvvT yourGitlabAddr...
appium学习之二:adb命令
1、查看设备 adb devices 2、连接 adb connect IP:端口 3、安装 adb install xxx.apk 4、卸载 adb uninstall 【包名】 5、把对应目录下的1.txt文件传到手机sdcard下 adb push 1.txt /sdcard 6、进入对应的设备里 adb shell 7、切入sdcard目录 cd /sdcard 8、ls 查…...
Linux Vi/Vim使用 ⑥
掌握 CentOS 7 下的 Vi/Vim 编辑器:从安装到精通 在 CentOS 7 系统的日常运维、编程开发以及各类文本处理场景中,Vi/Vim 编辑器都是不可或缺的得力工具。它以轻量、高效、功能强大著称,虽然初次上手有一定学习门槛,但掌握之后便能…...
JCR一区牛顿-拉夫逊优化算法+分解对比!VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测
JCR一区牛顿-拉夫逊优化算法分解对比!VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测 目录 JCR一区牛顿-拉夫逊优化算法分解对比!VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.中科院…...
easyExcel实现表头批注
背景: 网上大部分都不能直接使用,为此总结一个方便入手且可用的工具,用自定义注解实现 依赖包: <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>…...
Pytest测试用例使用小结
基础使用 Pytest 测试用例实现代码 import pytest from server.service import Servicepytest.fixture def service():return Service(logger)class TestService:classmethoddef setup_class(cls):"""初始化设置一次:return:"""logger.info(&q…...
LeetCode题练习与总结:132 模式--456
一、题目描述 给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[i] < nums[k] < nums[j] 。 如果 nums 中存在 132 模式的子序列 &a…...
IdentityServer4框架、ASP.NET core Identity
OAuth2.0 IdentityServer4 官网 中文官网 ASP.NET Core Identity提供了一个用来管理和存储用户账户的框架. IdentityServer4是基于ASP.NET Core实现的认证和授权框架,是对OpenID Connect和OAuth 2.0协议的实现。 IdentityServer是一个中间件,它可以添加符合OpenID…...
【分子材料发现】——GAP:催化过程中吸附构型的多模态语言和图学习(数据集处理详解)(二)
Multimodal Language and Graph Learning of Adsorption Configuration in Catalysis https://arxiv.org/abs/2401.07408Paper Data: https://doi.org/10.6084/m9.figshare.27208356.v2 1 Dataset CatBERTa训练的文本字符串输入来源于Open Catalyst 2020 (OC20…...
SpringBoot开发过程中经常遇到问题解决方案分享
目录 1. Spring Boot应用启动缓慢 2. 数据库连接池配置问题 3. Spring Boot应用无法连接外部服务 4. 配置文件读取不生效 5. Spring Boot应用的日志输出不完整 6. Spring Boot中的Transactional事务管理问题 1. Spring Boot应用启动缓慢 问题原因: Spring Boo…...
AR眼镜_消费级工业AR智能眼镜主板硬件解决方案
AR眼镜的研发是一项复杂的软硬件集成工程,它需要在摄影、音频、交互和连接等多个方面提供卓越的基础体验,因此产品的每个细节都显得尤为重要。 在设计AR眼镜时,重量、体积和散热性能都是必须认真考量的关键因素。在芯片平台的选择上ÿ…...
Springboot 核心注解
Spring Boot 是一个基于 Spring 框架的扩展,旨在简化新 Spring 应用的初始搭建以及开发过程。它通过自动配置和约定优于配置的原则,减少了开发者的工作量。Spring Boot 提供了一组核心注解和 Starter 依赖管理工具来帮助开发者快速启动项目。 1. Spring…...
Nacos集群搭建【Oracle作外部数据源】
一、知识点分析 1.Nocas是什么? Nacos是一个动态服务发现、配置管理和服务管理平台。 1.1定义与背景: Nacos,全称为Dynamic Naming and Configuration Service,是由阿里巴巴开源的云原生应用配套工具。它旨在简化微服务架…...
云轴科技ZStack出席中国电信国际EMCP平台香港发布会,持续推动海外合作
近日,以“云聚未来 翼起新篇”为主题的中国电信国际多云服务一站式平台(E-surfing Managed Cloud Platform,简称EMCP平台)新闻发布会在香港成功举办,标志着中国电信国际在云计算服务领域取得了又一重大进展。云轴科技…...
爬虫自动化之drissionpage+SwitchyOmega实现随时切换代理ip
本文介绍了如何使用DrizzlePage进行爬虫自动化,并重点讲解了首次启动时设置代理IP以及通过SwitchyOmega插件实现随时切换代理IP的方法。 安装一次,后面调用就不会再去安装了 下载地址:https://github.com/FelisCatus/SwitchyOmega/releases 这两个文件随便那个都可以,下载…...
docker安装kettle(PDI)并实现web访问
我是MAC电脑M1版本,希望把软件交给docker进行管理,最近公司同事都通过kettle来实现外部数据对接,所以我本地也有安装kettle需求,在网上找到了这个解决方案操作很简单,但出现了无法访问的情况。我的排查方式是ÿ…...
[软件工程]十.可靠性工程(reliable engineering)
1.什么是可靠性工程 我们希望软件在给定的时间内,运行的时候不会崩溃或者发生失效,同时能保护我们的数据和个人信息。我们要能够信任我们所使用的软件,这意味着软件必须是可靠的。可靠性(reliability):系统…...
【Makefile】编译日志之输出重定向符号 >
用法1 make all >& compilelog.txt make all > compilelog.txt这两个编译命令在功能上有一些细微的区别,主要在于标准输出和标准错误的处理方式。 make all >& compilelog.txt 这个命令会将标准输出(stdout)和标准错误&a…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
