TensorRT8——ONNX转trt

TensorRT安装

首先需要确保正确安装CUDA,安装后通过nvcc -V验证是否安装。

下载TensorRT
网址:https://developer.nvidia.com/nvidia-tensorrt-8x-download,下载最新版解压

tar -xzvf TensorRT-8.4.0.6.Linux.x86_64-gnu.cuda-11.6.cudnn8.3.tar.gz

为了节省根目录的内存,TensorRT我放在home下,添加环境变量

sudo vim ~/.bashrc
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/3D/TensorRT-8.4.0.6/lib
source ~/.bashrc

接着,我们通过样例程序判断TRT能否正常工作。我们先是将sampleMNIST源码进行编译,此时会在bin目录生成可执行文件,我们切换过去直接执行。

cd ~/3D/TensorRT-8.4.0.6/samples/sampleMNIST
make
cd ../../bin/
./sample_mnist

在这里插入图片描述
如果输出如下内容,最后显示PASSED,表明样例运行通过。

python支持

在上一部分中,虽然我们已经安装了TensorRT,但是我们的Python环境还不能通过import tensorrt导入,所以需要通过安装对应的.whl来实现。

pip install ../TensorRT-8.4.0.6/python/tensorrt-8.4.0.6-cp37-none-linux_x86_64.whl 

在这里插入图片描述

ONNX部署

TensorRT是nvidia公司针对nvidia显卡训练的模型在特定平台进行加速的推理优化库,是一个c++库,仅支持推理,不支持训练;

进行推理,需要先创建IExecutionContext对象,要创建这个对象,就需要先创建一个ICudaEngine的对象(engine),两种创建engine的方式:

  • 使用模型文件创建engine,并可把创建的engine序列化后存储到硬盘以便后面直接使用;
  • 使用之前已经序列化存储的engine,这种方式比较高效些,因为解析模型并生成engine还是挺慢的。

C++

TensorRT版本改动挺多的,大家可以直接查看API文档

#include "NvInfer.h"
#include "NvOnnxParser.h"
#include "NvInferRuntimeCommon.h"
#include <string>
#include <iostream>
#include <fstream>

// Logger for TensorRT info/warning/errors
class Logger : public nvinfer1::ILogger
{
public:
  Logger(Severity severity = Severity::kWARNING) : reportableSeverity(severity)
  {
  }

  void log(Severity severity, char const* msg) noexcept
  // void log(Severity severity, const char* msg) noexcept
  {
    // suppress messages with severity enum value greater than the reportable
    if (severity > reportableSeverity)
      return;

    switch (severity)
    {
      case Severity::kINTERNAL_ERROR:
        std::cerr << "INTERNAL_ERROR: ";
        break;
      case Severity::kERROR:
        std::cerr << "ERROR: ";
        break;
      case Severity::kWARNING:
        std::cerr << "WARNING: ";
        break;
      case Severity::kINFO:
        std::cerr << "INFO: ";
        break;
      default:
        std::cerr << "UNKNOWN: ";
        break;
    }
    std::cerr << msg << std::endl;
  }

  Severity reportableSeverity;
};



static Logger g_logger_;

void onnxToTRTModel(const std::string &model_file,            // name of the onnx model
                    nvinfer1::IHostMemory *&trt_model_stream) // output buffer for the TensorRT model
{
  int verbosity = (int)nvinfer1::ILogger::Severity::kWARNING;

  // create the builder
  nvinfer1::IBuilder* builder = nvinfer1::createInferBuilder(g_logger_);
  // 创建INetworkDefinition 对象
  nvinfer1::INetworkDefinition* network = builder->createNetworkV2(1U <<static_cast<uint32_t>(nvinfer1::NetworkDefinitionCreationFlag::kEXPLICIT_BATCH));
  // 创建解析器
  auto parser = nvonnxparser::createParser(*network, g_logger_);

  // 解析onnx文件,并填充网络
  if (!parser->parseFromFile(model_file.c_str(), verbosity))
  {
    std::string msg("failed to parse onnx file");
    g_logger_.log(nvinfer1::ILogger::Severity::kERROR, msg.c_str());
    exit(EXIT_FAILURE);
  }

  // Build the engine
  builder->setMaxBatchSize(1);
  // 创建iBuilderConfig对象
  nvinfer1::IBuilderConfig* iBuilderConfig = builder->createBuilderConfig();
  // 设置engine可使用的最大GPU临时值
  iBuilderConfig ->setMaxWorkspaceSize(1 << 20);


  nvinfer1::ICudaEngine* engine = builder->buildEngineWithConfig(*network,*iBuilderConfig);

  // 将engine序列化,保存到文件中
  trt_model_stream = engine->serialize();
  // save engine
  std::ofstream p("../model.trt", std::ios::binary);
  if (!p) {
      std::cerr << "could not open plan output file" << std::endl;
  }
  p.write(reinterpret_cast<const char *>(trt_model_stream->data()), trt_model_stream->size());
  parser->destroy();
  engine->destroy();
  network->destroy();
   builder->destroy();
   iBuilderConfig->destroy();
}



int main() {
    nvinfer1::IHostMemory *trt_model_stream;
    onnxToTRTModel("../../config/pfe.onnx", trt_model_stream);
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(onnxToTensorRT)
find_package(CUDA)

SET(TENSORRT_PATH /home/xiaohu/3D/TensorRT-8.4.0.6/)
SET(TENSORRT_LIB_PATH /home/xiaohu/3D/TensorRT-8.4.0.6/lib)

include_directories(
   include
   ${TENSORRT_PATH}/include
   ${CUDA_INCLUDE_DIRS}
)

set(SOURCE_FILES
   onnxToTensorRT.cpp
)

file(GLOB TENSORRT_LIBS "${TENSORRT_LIB_PATH}/*.so")
cuda_add_executable(${PROJECT_NAME} ${SOURCE_FILES})
target_link_libraries(
   ${PROJECT_NAME}
   ${TENSORRT_LIBS}
   ${CUDA_LIBRARIES}
)

python

#############################################
# python api转
#############################################
import sys
import os
import argparse
import tensorrt as trt

EXPLICIT_BATCH = 1 << (int)(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="PyTorch Object Detection Inference")
    parser.add_argument("--onnx_path", type=str,
                        default='static_sim.onnx')
    parser.add_argument("--trt_path", type=str,
                        default='static_sim.trt')
    args = parser.parse_args()
    onnx_file_path = args.onnx_path
    engine_file_path = args.trt_path
    print('get start')
    TRT_LOGGER = trt.Logger()
    with trt.Builder(TRT_LOGGER) as builder, builder.create_network(EXPLICIT_BATCH) as network, trt.OnnxParser(network, TRT_LOGGER) as parser:
        config = builder.create_builder_config()
        config.max_workspace_size =( 1 << 30 ) * 2 # 2 GB
        builder.max_batch_size = 16
        config.set_flag(trt.BuilderFlag.FP16)
        # builder.fp16_mode = True
        # Parse model file

        print('Loading ONNX file from path {}...'.format(onnx_file_path))
        with open(onnx_file_path, 'rb') as model:
            print('Beginning ONNX file parsing')
            if not parser.parse(model.read()):
                print ('ERROR: Failed to parse the ONNX file.')
                for error in range(parser.num_errors):
                    print (parser.get_error(error))
        
        print(f"raw shape of {network.get_input(0).name} is: ", network.get_input(0).shape)
        print(f"raw shape of {network.get_input(1).name} is: ", network.get_input(1).shape)
        print(f"raw shape of {network.get_input(2).name} is: ", network.get_input(2).shape)


        print('Completed parsing of ONNX file')
        print('Building an engine from file {}; this may take a while...'.format(onnx_file_path))
        engine = builder.build_engine(network,config)
        print("Completed creating Engine")
        with open(engine_file_path, "wb") as f:
            f.write(engine.serialize())

trtexec

TensorRT-8.4.3.1/targets/x86_64-linux-gnu/bin/trtexec --onnx=static_sim.onnx --explicitBatch --saveEngine= static_sim.trt --workspace=1024
欢迎大家关注笔者,你的关注是我持续更博的最大动力


### 将ONNX模型换为TensorRT模型 为了实现从ONNXTensorRT换,主要依赖于NVIDIA提供的`trtexec`工具以及Python API。这允许用户不仅能够快速测试不同配置下的性能差异,还能方便地集成至生产环境中。 #### 使用 `trtexec` 命令行工具进行换 通过命令行调用`trtexec`来完成这一过程是最简便的方式之一。该工具提供了丰富的参数选项用于优化最终生成的TensorRT引擎文件(.engine),从而满足多样化的应用场景需求[^1]。 ```bash trtexec --onnx=model.onnx --saveEngine=model.engine ``` 上述命令展示了最基本的用法,即将指定路径下的`.onnx`文件作为输入并保存对应的TensorRT引擎文件。对于更复杂的场景,则可以通过增加更多参数来自定义构建流程,比如设置工作空间大小、启用FP16精度模式等。 #### 利用 Python API 实现自动化脚本 除了手动执行命令外,还可以借助官方提供的Python接口编写程序自动完成整个换过程。这种方式特别适合那些希望将其嵌入现有代码库中的开发者们。 ```python import tensorrt as trt TRT_LOGGER = trt.Logger(trt.Logger.WARNING) def build_engine(onnx_file_path): with trt.Builder(TRT_LOGGER) as builder, \ builder.create_network() as network, \ trt.OnnxParser(network, TRT_LOGGER) as parser: builder.max_workspace_size = 1 << 30 # 1GB builder.fp16_mode = True with open(onnx_file_path, 'rb') as model: if not parser.parse(model.read()): for error in range(parser.num_errors): print(parser.get_error(error)) return None engine = builder.build_cuda_engine(network) return engine # Save the engine to file with open("model.engine", "wb") as f: f.write(build_engine("model.onnx").serialize()) ``` 这段代码片段实现了创建一个简单的函数`build_engine()`,它接收ONNX模型路径作为参数,并返回编译后的TensorRT引擎对象。最后一步则是将这个引擎序列化后存储为二进制文件以便后续加载使用。 需要注意的是,在实际应用过程中可能还需要考虑其他因素的影响,例如批处理尺寸的选择、动态形状的支持等问题。此外,确保输入数据格式与预期一致也非常重要;特别是当涉及到图像类任务时,应当注意原始图片经过预处理之后的数据类型应匹配网络的要求——通常情况下这意味着要将像素值由整数形式换成浮点数表示[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

令狐少侠、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值