【TensorRT】c++使用面向对象来封装tensorRT推理代码的指针释放问题

这篇具有很好参考价值的文章主要介绍了【TensorRT】c++使用面向对象来封装tensorRT推理代码的指针释放问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、🍎代码框架🍎

初始化模型

std::shared_ptr<nvinfer1::IExecutionContext> Instance::Init_Instance(const char* model_path, const string class_name_path)
{
    //注册防止反序列化报错
    nvinfer1::ILogger* gLogger = NULL;
    initLibNvInferPlugins(gLogger, "");

    TRTLogger logger;
    ifstream fs(model_path, std::ios::binary);
    std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(fs), {});
    fs.close();
    std::shared_ptr<nvinfer1::IRuntime> runtime = make_nvshared(nvinfer1::createInferRuntime(logger));
    //nvinfer1::IRuntime *runtime = nvinfer1::createInferRuntime(logger);

    _engine = make_nvshared(runtime->deserializeCudaEngine((void*)buffer.data(), buffer.size()));
    //_engine = runtime->deserializeCudaEngine((void*)buffer.data(), buffer.size());

    Malloc_data();
    class_names = get_name(class_name_path);

    //初始化cuda流,不需要了,在类中已经作为成员变量初始化了
    //cudaStream_t stream = nullptr;
    checkRuntime(cudaStreamCreate(&stream));
    //创建执行的上下文
    auto execution_context = make_nvshared(_engine->createExecutionContext());
    return execution_context;
}

这里可以看到我用了智能指针来分别定义_engine, _runtime, _context。并且我在头文件中定义了一个类来封装我的推理代码,包括初始化模型的步骤:


类封装

class Instance {
public:
    Instance(float scale_):scale(scale_)
    {
        cout << "调用了构造函数" << endl;
    }
    ~Instance() {
        cout << "调用了析构函数" << endl;
    };
    float scale;
    std::shared_ptr < nvinfer1::IExecutionContext > _context = nullptr;
    //nvinfer1::IExecutionContext* _context = nullptr;

    vector<string> class_names;
    string total_output;

	std::shared_ptr<nvinfer1::IExecutionContext> Init_Instance(const char* model_path, const string class_name_path);
    //nvinfer1::IExecutionContext* Init_Instance(const char* model_path, const string class_name_path);

	void Run_Instance(cv::Mat input);
    void check_ptr();
    void Free_Memory();
    vector<string> get_name(string class_name_path);
    void destory_engine();

private:

    void Malloc_data();
    cv::cuda::GpuMat ProcessImage(cv::cuda::GpuMat pre_input);
    void PostcessImage(cv::Mat nums, cv::Mat boxes, cv::Mat scores, cv::Mat classes, cv::Mat masks);
    //void Init_parameters();

    int INPUT_SIZE = 1344;
    int MIN_SIZE = 800;
    int MAX_SIZE = 1333;
    int MASK_SIZE = 28;
    float CONFIDENCE = 0;
    float MASK_THRESHOLD = 0.5;
    int input_numel = 1;
    int output_nums_numel = 1;
    int output_boxes_numel = 1;
    int output_scores_numel = 1;
    int output_classes_numel = 1;
    int output_masks_numel = 1;
    cv::Mat INPUT;

    cudaStream_t stream = nullptr;
    std::shared_ptr<nvinfer1::ICudaEngine> _engine = nullptr;
    std::shared_ptr<nvinfer1::IRuntime> _runtime = nullptr;
    //nvinfer1::ICudaEngine* _engine = nullptr;
    //nvinfer1::IRuntime* _runtime = nullptr;

  
    //初始化输入和输出指针
    //static float* input_host_data = nullptr;
    float* input_device_data = nullptr;
    Output_ptr output_host = { nullptr, nullptr, nullptr, nullptr, nullptr };
    Output_ptr output_device = { nullptr, nullptr, nullptr, nullptr, nullptr };
};

在这里可以看到,我已经将_engine, _runtime, _context都定义在了类的成员变量当中,并且都用的智能指针shared_ptr的方式。(并且我也在类中封装了Malloc_data()和Free_malloc()函数,作用分别是为tensorRT推理时在host和device上为输入输出的指针分配存储空间,和在执行推理完毕后,将host和device上分配的指针指向的内存空间手动释放掉)。


主函数
第一次封装是将我的推理代码封装在类中,为了方便c#软件调用部署导出的dll,我们将进行二次封装,因此主函数的接口使用的是二次封装的:

#include "port.h"

int main()
{
	cv::String folder = ;
	std::vector<cv::String> paths;
	cv::glob(folder, paths);
	const char* model_path = ;
	const string class_path = ;
	Init_model(model_path, class_path);
	for (int i = 0; i < paths.size(); i++)
	{
		char* y_output = NULL;
		cv::Mat input = cv::imread(paths[i]);
		cv::Mat bgr[3];
		cv::split(input, bgr);
		uchar* b_ptr = bgr[0].data;
		uchar* g_ptr = bgr[1].data;
		uchar* r_ptr = bgr[2].data;
		auto time_start = std::chrono::system_clock::now();
		Run_model(b_ptr, g_ptr, r_ptr, 800, 800, 3, y_output);
		auto time_end = std::chrono::system_clock::now();
		std::chrono::duration<double> diff = time_end - time_start;
		cout << y_output;
		cout << "deep learning cost time : " << diff.count() * 1000 << "ms" << endl << endl;
	}
	Free_memory();
	check_Ptr();
	destory_trt();
	system("pause");
	return 0;
}

可以看到在上述代码经过一个for循环遍历完所有要检测的图像之后,在循环外部,程序即将结束之前,我们调用了Free_memory()来手动释放host和device指针指向的内存以及释放推理时创建的cuda流,并且通过Check_ptr()方法来判断指针是否被释放完成。最后我们通过destory_trt()接口来释放推理时创建的_engine, _runtime, _context。最后跑出的推理结果十分正确,代码跑的也很流畅没有bug,并且通过一个写了一个while死循环来跑也没有发现内存泄露。到这里我以为我已经大功告成了。


二、💡问题以及分析💡

【TensorRT】c++使用面向对象来封装tensorRT推理代码的指针释放问题,推理平台|TensorRT,c++,开发语言,CUDA
这是终端跑出来的结果,可以看到执行完了Free_memory()并且通过check_ptr()方法,我们可以判断指针已经释放完毕了。但是当我们经过system(“pause”)继续往下执行推出程序时,问题就来了:
【TensorRT】c++使用面向对象来封装tensorRT推理代码的指针释放问题,推理平台|TensorRT,c++,开发语言,CUDA
是NvInferRuntime.h所报出的问题,显示我们可管理的指针将被执行两次释放,说人话就是我们的指针已经释放完了,但是现在又要执行那个指针的释放,电脑也不知道咋办了,只能抛出错误。于是乎,我便开始从头开始查询我的代码,看看到底哪里多释放了一次,后来突然发现,由于我使用了智能指针,智能指针在其完成调用之后,根据引用计数可以自动释放,而我的这些_engine, _context, _runtime,也都已经在类的成员变量中定义过了,在类中如果不是new出来的内存,其他的都会随着程序的执行结束而自动销毁(new出来的内存需要手动delete)。到这里我才恍然大悟,既然我用类来封装代码了,因此也不需要通过智能指针的方式来定义推理的变量了,因此我将这三个智能指针换成了普通指针,最后运行,没有问题!
【TensorRT】c++使用面向对象来封装tensorRT推理代码的指针释放问题,推理平台|TensorRT,c++,开发语言,CUDA文章来源地址https://www.toymoban.com/news/detail-802182.html

到了这里,关于【TensorRT】c++使用面向对象来封装tensorRT推理代码的指针释放问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • yolov7的 TensorRT c++推理,win10, cuda11.4.3 ,cudnn8.2.4.15,tensorrt8.2.1.8。

    yolov7的 TensorRT c++推理,win10, cuda11.4.3 ,cudnn8.2.4.15,tensorrt8.2.1.8。

    yolov7的 tensorrt8 推理, c++ 版本 环境 win10 vs2019 opencv4.5.5 cuda_11.4.3_472.50_win10.exe cudnn-11.4-windows-x64-v8.2.4.15 TensorRT-8.2.1.8.Windows10.x86_64.cuda-11.4.cudnn8.2.zip RTX2060推理yolov7, FP32 耗时 28ms  ,FP16 耗时 8ms,单帧对应总耗时30ms 和 10ms。 推理yolov7-tiny,FP32 耗时 8ms  ,FP16 耗时 2ms。 tensorr

    2024年02月15日
    浏览(9)
  • 【模型部署 01】C++实现GoogLeNet在OpenCV DNN、ONNXRuntime、TensorRT、OpenVINO上的推理部署

    【模型部署 01】C++实现GoogLeNet在OpenCV DNN、ONNXRuntime、TensorRT、OpenVINO上的推理部署

    深度学习领域常用的基于CPU/GPU的推理方式有OpenCV DNN、ONNXRuntime、TensorRT以及OpenVINO。这几种方式的推理过程可以统一用下图来概述。整体可分为模型初始化部分和推理部分,后者包括步骤2-5。 以GoogLeNet模型为例,测得几种推理方式在推理部分的耗时如下: 结论: GPU加速首选

    2024年02月06日
    浏览(14)
  • 【模型部署 01】C++实现分类模型(以GoogLeNet为例)在OpenCV DNN、ONNXRuntime、TensorRT、OpenVINO上的推理部署

    【模型部署 01】C++实现分类模型(以GoogLeNet为例)在OpenCV DNN、ONNXRuntime、TensorRT、OpenVINO上的推理部署

    深度学习领域常用的基于CPU/GPU的推理方式有OpenCV DNN、ONNXRuntime、TensorRT以及OpenVINO。这几种方式的推理过程可以统一用下图来概述。整体可分为模型初始化部分和推理部分,后者包括步骤2-5。 以GoogLeNet模型为例,测得几种推理方式在推理部分的耗时如下: 结论: GPU加速首选

    2024年02月06日
    浏览(13)
  • TensorRT(C++)基础代码解析

    TensorRT(C++)基础代码解析

    TensorRT build engine的过程 创建builder 创建网络定义:builder — network 配置参数:builder — config 生成engine:builder — engine (network, config) 序列化保存:engine — serialize 释放资源:delete 2.1.1 创建builder nvinfer1 是 NVIDIA TensorRT 的 C++ 接口命名空间。构建阶段的最高级别接口是 Builder。Bu

    2024年01月18日
    浏览(11)
  • 【深度学习】SDXL tensorRT 推理,Stable Diffusion 转onnx,转TensorRT

    【深度学习】SDXL tensorRT 推理,Stable Diffusion 转onnx,转TensorRT

    juggernautXL_version6Rundiffusion.safetensors文件是pth pytroch文件,需要先转为diffusers 的文件结构。 FP16在后面不好操作,所以最好先是FP32: 有了diffusers 的文件结构,就可以转onnx文件。 项目:https://huggingface.co/docs/diffusers/optimization/onnx stabilityai/stable-diffusion-xl-1.0-tensorrt 项目:https://hug

    2024年01月19日
    浏览(8)
  • TensorRT 推理 (onnx->engine)

    TensorRT 推理 (onnx->engine)

    测试使用:【Win10+cuda11.0+cudnn8.2.1+TensorRT8.2.5.1】 关于安装 一、模型转换 onnx2trt 方法1:使用wang-xinyu/tensorrtx部署yolov5方法:https://wangsp.blog.csdn.net/article/details/121718501 方法2:使用tensorRT转成engine 方法3:使用C++ onnx_tensorrt将onnx转为trt 的推理engine 参考 【python 方法参考】 方法4:

    2023年04月08日
    浏览(7)
  • TensorRT推理手写数字分类(三)

    TensorRT推理手写数字分类(三)

    (一)使用pytorch搭建模型并训练 (二)将pth格式转为onnx格式 (三)onxx格式转为engine序列化文件并进行推理   上一节我们已经成功搭从pth文件转为onnx格式的文件,并对导出的onnx文件进行了验证,结果并无问题。这一节我们就从这个onnx文件入手,一步一步生成engine文件并

    2024年02月12日
    浏览(10)
  • 【TensorRT】TensorRT C# API 项目更新 (1):支持动态Bath输入模型推理(下篇)

    【TensorRT】TensorRT C# API 项目更新 (1):支持动态Bath输入模型推理(下篇)

    关于该项目的调用方式在上一篇文章中已经进行了详细介绍,具体使用可以参考《最新发布!TensorRT C# API :基于C#与TensorRT部署深度学习模型》,下面结合Yolov8-cls模型详细介绍一下更新的接口使用方法。 4.1 创建并配置C#项目   首先创建一个简单的C#项目,然后添加项目配置

    2024年04月17日
    浏览(8)
  • TensorRT创建Engine并推理engine

    NVIDIA TensorRT是一个高性能的深度学习推理库,专为部署神经网络模型而设计。TensorRT通过优化和高效的内存管理来提高模型的推理速度,从而提高整体应用程序的性能。以下是使用TensorRT创建Engine并进行推理的步骤: 安装TensorRT库: 首先,确保您已经安装了TensorRT库。请访问

    2023年04月14日
    浏览(7)
  • 大语言模型推理提速:TensorRT-LLM 高性能推理实践

    大语言模型推理提速:TensorRT-LLM 高性能推理实践

    作者:顾静 大型语言模型(Large language models,LLM)是基于大量数据进行预训练的超大型深度学习模型。底层转换器是一组神经网络,这些神经网络由具有 self-attention 的编码器和解码器组成。编码器和解码器从一系列文本中提取含义,并理解其中的单词和短语之间的关系。 当前

    2024年01月25日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包