【TensorRT 10 C++ inference example】最新版本TensorRT c++ api的推理部署教程
TensorRT是英伟达推出的部署框架,我的工作经常需要封装我的AI算法和模型给到桌面软件使用,那么tensorRT对我来说就是不二之选。TensorRT和cuda深度绑定,在c++版本的推理教程中需要使用cuda进行数据的显存绑定,由于10之前的写法比较固定,我自己基于tensorRT和cuda写了一套部署框架,将模型转换和核心推理部分都封装了起来。
但是最近在一个新项目上,我把cuda升级到了12.4,随着的tensorRT也用上了最新的10.11版本,然后我发现原来的代码报错了,仔细检查发现tensorRT10修改了很多原来的api,我在网上查询了一些方案,大部分都没有解决或者不是很清楚,还有些文章需要付费所以也看不了。后来我发现英伟达自己在tensorRT项目中给了很多sample,但是这些sample有点臃肿,所以在这里我分享一下我的方案。
【关于如何生成trt的引擎文件我这里就不写了,tensorRT10和之前的版本在这里区别不大,而且tensorRT都会给一个转换的可执行文件。所以我直接从模型推理开始。】
首先,我将回顾一个tensorRT的推理流程,然后会将一些最新版本和之前版本的区别,最后会给上最新版本推理的示例代码。
TensorRT首先需要初始化模型引擎和执行会话,这个新旧版本都一样,这里放一下我的代码:
// 核心头文件
#include <NvOnnxParser.h>
#include <NvInfer.h>
#include <cuda_runtime_api.h>
// 首先定义cuda stream
cudaStream_t stream;
// 初始化变量
nvinfer1::IRuntime* model_runtime{ nullptr };
nvinfer1::ICudaEngine* model_engine{ nullptr };
nvinfer1::IExecutionContext* model_context{ nullptr };
// 模型路径
const char* modelFile = deployModel.modelPath.c_str();
// 加载模型
model_runtime = nvinfer1::createInferRuntime(gLogger);
std::ifstream fin(modelFile, std::ios::binary);
std::string modelData = "";
while (fin.peek() != EOF) { // 使用fin.peek()防止文件读取时无限循环
std::stringstream buffer;
buffer << fin.rdbuf();
modelData.append(buffer.str());
}
fin.close();
model_engine = model_runtime->deserializeCudaEngine(modelData.data(), modelData.size());
model_context = model_engine->createExecutionContext();
完成模型的初始化后,接下来我们需要进行数据缓冲的创建,即预先创建好输入输出的数据缓冲,我一般会把每个模型的输入输出的大小写到配置文件里,这样这里就可以直接创建,也可以通过model_engine->getTensorShape(name)进行获取,怎么写都可以,重要的要确定好输入输出的index和shape。
// buffers,这里是一个指针数组,设计多少都可以,一般的模型只有一个输入一个输出的话,设置为2也可以,这里我设置100只是习惯
void* model_buffers[100];
// 计算输入shape,这里的inputShape是[640, 640, 3],inputIndex是0
int tmpInputSize = 1;
for (int j = 0; j < inputShape.size(); j++) {
tmpInputSize *= inputShape[j];
}
// 这是使用cuda申请对于大小的显存,并和缓存指针绑定
CUDA_CHECK(cudaMalloc(&model_buffers[inputIndex], tmpInputSize * sizeof(float)));
// 同样的操作对output也进行一遍
int tmpOutputSize = 1;
for (int j = 0; j < outputShape.size(); j++) {
tmpOutputSize *= outputShape[j];
}
CUDA_CHECK(cudaMalloc(&model_buffers[outputIndex], tmpOutputSize * sizeof(float)));
我习惯提前做好这些,这些在新旧版本上都是一致的没有区别,接下来就是模型推理部分了,也是有区别的地方。旧版本使用enqueue、enqueueV2进行推理,而新api是enqueueV3这里的差异导致我研究了半天。
首先看一下旧版本的推理方式,以enqueueV2为例:
// 分配cuda stream
CUDA_CHECK(cudaStreamCreate(&stream));
// 这里是将真正的输入数据移动到刚刚绑定申请完显存的缓存地址上,inputData就是真正的输入数据
CUDA_CHECK(cudaMemcpyAsync(model_buffers[inputIndex], inputData, inputSize * sizeof(float), cudaMemcpyHostToDevice, stream));
// 接下来就是推理部分
model_context->enqueueV2(model_buffers, stream, nullptr);
// 完成推理将缓存地址中输出数据移动出来
float* outputData = new float[outputSize];
CUDA_CHECK(cudaMemcpyAsync(outputData, model_buffers[outputIndex], outputSize * sizeof(float), cudaMemcpyDeviceToHost, stream));
// 同步stream
CUDA_CHECK(cudaStreamSynchronize(stream));
这里我们可以看到enqueueV2接受了model_buffers作为输入,但是enqueueV3就完全不一样了,他的参数只有一个stream,我看到这个api的时候都懵了,输入怎么办?输出怎么办?于是我看了官方的example,又看了几个教程,才终于搞明白,tensorRT10新增了一个输入输出注册的环节,需要先将buffer地址注册,然后再推理,等于将原来的一步拆分了两步,说实话真的有点脱裤子放屁,没活硬整了。好吧,看一下代码吧。
// 前面都是一样的
CUDA_CHECK(cudaStreamCreate(&stream));
CUDA_CHECK(cudaMemcpyAsync(model_buffers[inputIndex], inputData, inputSize * sizeof(float), cudaMemcpyHostToDevice, stream));
// 这里开始,需要进行输入输出的地址注册
model_context->setInputTensorAddress(model_engine->getIOTensorName(inputIndex), model_buffers[inputIndex]);
model_context->setOutputTensorAddress(model_engine->getIOTensorName(outputIndex), model_buffers[outputIndex]);
// 接下来就是推理部分,这里不需要放缓存了
model_context->enqueueV3(stream);
// 完成推理将缓存地址中输出数据移动出来,后面也是和旧版本一样了
float* outputData = new float[outputSize];
CUDA_CHECK(cudaMemcpyAsync(outputData, model_buffers[outputIndex], outputSize * sizeof(float), cudaMemcpyDeviceToHost, stream));
// 同步stream
CUDA_CHECK(cudaStreamSynchronize(stream));
搞清楚后,其实挺让人无语的,我想看看源码,可惜老黄并没有公开,github上的也只有头文件和sample,但是感觉这个地址注册可能就是脱裤子放屁了一下,但是这样变动sample里又写的很复杂,真的很让人无语。
好啦,以上就是本次分享的全部,欢迎大家评论区交流!
【TensorRT 10 C++ inference example】最新版本TensorRT c++ api的推理部署教程的更多相关文章
- Windows 10的最新版1803版本ISO下载
Windows 10推出已经有几年时间了,笔者一直在用这个新版本.据说Windows 10以后只会推出新的更新,而不会有新的操作系统推出,所以Windows 10的更新就显得重要了.这次给大家推荐一个 ...
- Ubuntu18.04 LTS 安装部署golang最新版本1.10
1 步骤 //1 直接安装golang-go 目前最新版本是1.10 sudo apt-get install golang-go //2 向/etc/profile追加以下代码 sudo vim / ...
- 用 Love2D 实现法线贴图的例程(到最新版本 0.10.1)
用 Love2D 实现法线贴图的例程(到最新版本 0.10.1) 概述 一般来说, 复杂的光照模型会被用在 3D 游戏中, 以产生逼真的效果, 不过也有些开发者研究出一些代码可以在 2D 游戏中使用这 ...
- 性能工具 stream 最新版本5.10 The STREAM benchmark
官网下载最新性能工具 stream 最新版本5.10 https://github.com/jeffhammond/STREAM 官网下载最新性能工具 stream 最新版本5.10 http:/ ...
- centos7 升级内核到最新版本
centos7 从问世以来,官网提供的镜像始终是3.10 版本,该版本最大的一个问题是对硬件驱动(尤其是无线网卡)的支持不是很好,本人亲测>5种机型,无线网卡均无法正常使用,如果是非主流机型,手 ...
- MPlayer-2016 最新版本
MPlayer 和 FFmpeg 最新版本 运行 Install.cmd 添加右键播放功能 mplayer\outformat.conf 配置视频分割命令参数 ; 往前0.05秒 大概10多个帧 ' ...
- 如何安装最新版本的memcached
转载自孟叔的博客: https://learndevops.cn/index.php/2016/06/10/how-to-install-the-latest-version-of-memcache ...
- ubuntu安装最新版本的node.js
下面的方法适用于最新版本的Ubuntu.Ubuntu 12.04 LTS.Ubuntu 12.10.Ubuntu 13.04等版本.它可以帮助开发者在Ubuntu上安装Node.js,无需从头编译安装 ...
- 【转】Win7环境下VS2010配置Cocos2d-x-2.1.4最新版本的开发环境(亲测)
http://blog.csdn.net/ccf19881030/article/details/9204801 很久以前使用博客园博主子龙山人的一篇博文<Cocos2d-x win7+vs20 ...
- Linux(Fedora)下NodeJs升级最新版本(制定版本)
Linux(Fedora)下NodeJs升级最新版本(制定版本) 首先安装n模块: npm install -g n 升级node.js到最新稳定版 n stable 升级node.js到制定版本 n ...
随机推荐
- FishSpeech应用篇——专属朗读人
背景 FishSpeech部署教程参见:使用FishSpeech进行语音合成推理 - 天命小猪 - 博客园 部署好之后,就能够基于推理来定制自己专属朗读人.编程能力强的小伙伴可以结合AI定制一个自己的 ...
- Deepseek学习随笔(13)--- 清华大学发布第5弹:DeepSeek与AI幻觉(附网盘链接)
人工智能技术的飞速发展为我们带来了前所未有的便利,但同时也伴随着一个不容忽视的问题--AI幻觉.清华大学发布的<DeepSeek与AI幻觉>详细探讨了AI幻觉的成因.评测方法以及应对策略, ...
- FastAPI极速入门:15分钟搭建你的首个智能API(附自动文档生成)🚀
title: FastAPI极速入门:15分钟搭建你的首个智能API(附自动文档生成) date: 2025/3/1 updated: 2025/3/1 author: cmdragon excerp ...
- C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
前言 C#/.NET/.NET Core技术前沿周刊,你的每周技术指南针!记录.追踪C#/.NET/.NET Core领域.生态的每周最新.最实用.最有价值的技术文章.社区动态.优质项目和学习资源等. ...
- webpack 科学修改 node_modules 某个包的部分文件为本地文件
需求总是千变万化,npm 不是万能的,node_modules 里面的文件也是需要维护的. 如果 npm install 安装了某个包,然而这个包里面部分文件不支持你的需求,这时候怎么办? 比如:ht ...
- Vue3+TS项目无法识别自动导入提示
遇到问题 在写 Vue3 + TS 项目的时候,经常遇到写完一个新方法后,在组件使用的时候无法自动识别. 解决方案 Volar: Restart Vue Server 重新启动 Vue 服务
- vue强制刷新页面
方法一 this.$router.go(0) // 会出现一段空白页,用户体验不好 方法二 在 app.vue 中定义 reload() 方法 <template> <div id= ...
- linux安装protoc
protobuf 是做什么的? 专业的解答: Protocol Buffers 是一种轻便高效的结构化数据存储格式,可用于结构化数据串行化,很适合做数据存储或 RPC 数据交换格式.它可用于通讯协议. ...
- 因为Apifox不支持离线,我果断选择了Apipost!
要说国内最有名的两款API开发工具不是Apipost就是Apifox,因为曾经遭遇到一件事,导致我坚定的选择了Apipost. 有一年春节我攒了足够的年假,提前开开心心的过年回家,路上我的领导给我打电 ...
- oracle的IP访问列表
Windows版本Oracle 19c. 在sqlnet.ora中添加下面语句 tcp.validnode_checking=yes tcp.invited_nodes=(127.0.0.1,132. ...