TensorRT的使用流程c++和python

TensorRT包含解析器parser,构建器builder,引擎engine,执行上下文context,其中解析器parser负责加载模型框架和权重。构建器builder负责构建网络,引擎engine和执行上下文context负责在网络中进行前向传播。

TensorRT模型的来源有两种:

  1、自定义构建TensorRT模型

  2、外界导入trt模型,以pytorch为例,pt文件转onnx转trt。

外界导入trt模型之后,创建流程如下:

读trt文件→创建runtime→runtime反序列化trt文件得到engine→engine创建context→为运行分配空间→将数据拷贝到分配的空间上→模型推理→后处理

class Logger : public ILogger {
public:
        void log(Severity severity, const char* msg) noexcept override
        {
                // suppress info-level messages
                if (severity <= Severity::kWARNING)
                        std::cout << msg << std::endl;
        }
}gLogger;
 
//假设模型已经被读入到vector<char> modeltrt中
initLibNvInferPlugins(&gLogger, "");
//模型导入
Logger m_logger;
IRuntime* runtime = createInferRuntime(gLogger);
ICudaEngine* engine = runtime->deserializeCudaEngine(modeltrt.data(), modeltrt.size(), nullptr);
IExecutionContext* context = engine->createExecutionContext();
 
//分配空间
void* buffers[2];
buffers[0] = buffers[1] = NULL;
cudaMallocManaged(&buffers[0], 3 * 640 * 640 * 4);
cudaMallocManaged(&buffers[1], 1 * 25200 * 85 * 4);
cudaStream_t stream;
cudaStreamCreate(&stream);
 
//假设输入数据已经复制到buffers上,运行
context->enqueueV2(buffers, stream, nullptr);

TensorRT_Python

TensorRT 是 NVIDIA 推出的一个高性能深度学习推理库,专门用于优化深度学习模型以在 NVIDIA GPU 上进行高效的推理。它可以对深度学习模型进行图层融合、精度混合以及其他优化,从而加快模型的推理速度并减少延迟。TensorRT 主要支持 FP32、FP16 和 INT8 精度。

下面我们通过 YOLOv5 的例子来讲解如何使用 TensorRT 进行推理。

安装 TensorRT

在安装 TensorRT 之前,确保你已经安装了 CUDA 和 cuDNN。然后,你可以通过 pip 安装 TensorRT:

pip install nvidia-pyindex pip install nvidia-tensorrt

使用 TensorRT 进行推理的步骤

  1. 导出模型为 ONNX 格式: YOLOv5 模型首先需要转换为 ONNX 格式。你可以使用 YOLOv5 的官方工具来完成这个步骤。

  2. python export.py --weights yolov5s.pt --include onnx
  3. ONNX 模型转换为 TensorRT 引擎: 使用 tensorrt 库将 ONNX 模型转换为 TensorRT 引擎。

  4. 加载 TensorRT 引擎并进行推理: 使用 tensorrt 库加载 TensorRT 引擎,并使用其进行推理。

下面是一个完整的例子,演示如何使用 TensorRT 库加载和推理 YOLOv5 的模型。

代码示例

首先,我们需要一些必要的库:

1. 导出模型为 ONNX 格式

python export.py --weights yolov5s.pt --include onnx

2. 将 ONNX 模型转换为 TensorRT 引擎

使用 TensorRT 的 trtexec 工具可以将 ONNX 模型转换为 TensorRT 引擎:

trtexec --onnx=yolov5s.onnx --saveEngine=yolov5s.trt --fp16

3. 加载 TensorRT 引擎并进行推理

下面是 Python 代码,演示如何加载 TensorRT 引擎并进行推理:

class YoLov5TRT(object):
    def __init__(self, engine_file_path):
        # 创建一个 Runtime 对象
        self.trt_logger = trt.Logger(trt.Logger.INFO)
        self.runtime = trt.Runtime(self.trt_logger)

        # 反序列化 TensorRT 引擎
        with open(engine_file_path, "rb") as f:
            self.engine = self.runtime.deserialize_cuda_engine(f.read())

        # 创建执行上下文
        self.context = self.engine.create_execution_context()

        # 分配输入和输出内存
        self.inputs, self.outputs, self.bindings, self.stream = self.allocate_buffers()

    def allocate_buffers(self):
        inputs = []
        outputs = []
        bindings = []
        stream = cuda.Stream()

        for binding in self.engine:
            size = trt.volume(self.engine.get_binding_shape(binding)) * self.engine.max_batch_size
            dtype = trt.nptype(self.engine.get_binding_dtype(binding))

            # 分配主机和设备内存
            host_mem = cuda.pagelocked_empty(size, dtype)
            device_mem = cuda.mem_alloc(host_mem.nbytes)

            # 记录绑定
            bindings.append(int(device_mem))

            if self.engine.binding_is_input(binding):
                inputs.append(host_mem)
            else:
                outputs.append(host_mem)

        return inputs, outputs, bindings, stream

    def infer(self, image):
        # 预处理图像
        input_image = self.preprocess_image(image)
        np.copyto(self.inputs[0], input_image.ravel())

        # 将输入数据从主机复制到设备
        cuda.memcpy_htod_async(self.inputs[0], self.bindings[0], self.stream)

        # 执行推理
        self.context.execute_async_v2(bindings=self.bindings, stream_handle=self.stream.handle)

        # 将输出数据从设备复制到主机
        cuda.memcpy_dtoh_async(self.outputs[0], self.bindings[1], self.stream)
        self.stream.synchronize()

        return self.postprocess_results(self.outputs[0])

    def preprocess_image(self, image):
        # Resize and normalize the image
        input_shape = (self.engine.max_batch_size, 3, 640, 640)
        image = cv2.resize(image, (640, 640))
        image = image.astype(np.float32) / 255.0
        image = np.transpose(image, (2, 0, 1))
        image = np.expand_dims(image, axis=0)
        return image

    def postprocess_results(self, output):
        # 后处理推理结果
        # 这里的实现取决于模型的输出格式
        return output

# 创建 YOLOv5 TensorRT 推理对象
yolov5_trt = YoLov5TRT("yolov5s.trt")

# 读取输入图像
image = cv2.imread("image.jpg")

# 执行推理
output = yolov5_trt.infer(image)

# 打印或处理输出结果
print(output)

总结

这个示例演示了如何使用 TensorRT 库加载并推理 YOLOv5 模型。主要步骤包括:

  1. 将模型导出为 ONNX 格式。

  2. 使用 TensorRT 工具将 ONNX 模型转换为 TensorRT 引擎。

  3. 使用 TensorRT Python API 加载引擎并进行推理。

希望这个例子能帮助你更好地理解如何使用 TensorRT 进行高效的模型推理。

TensorRT_C++

TensorRT 是 NVIDIA 提供的一个用于深度学习推理的高性能库。它可以对经过训练的神经网络进行优化,生成一个高效的推理引擎,并能够在 NVIDIA 的 GPU 上高效运行。TensorRT 支持多种模型格式,包括 Caffe、TensorFlow、ONNX 等,并且可以对模型进行图层融合、精度混合、内存优化等操作,以实现更快的推理速度和更低的延迟。

使用 TensorRT 进行 YOLOv5 推理的步骤

  1. 导出模型为 ONNX 格式: 首先需要将 YOLOv5 模型转换为 ONNX 格式。

  2. 将 ONNX 模型转换为 TensorRT 引擎: 使用 TensorRT 的 trtexec 工具将 ONNX 模型转换为 TensorRT 引擎。

  3. 使用 C++ 加载 TensorRT 引擎并进行推理: 使用 C++ API 加载 TensorRT 引擎,并实现前处理、推理和后处理。

1. 导出模型为 ONNX 格式

首先需要使用 YOLOv5 的官方工具将模型导出为 ONNX 格式:

python export.py --weights yolov5s.pt --include onnx

2. 将 ONNX 模型转换为 TensorRT 引擎

使用 TensorRT 的 trtexec 工具将 ONNX 模型转换为 TensorRT 引擎:

trtexec --onnx=yolov5s.onnx --saveEngine=yolov5s.trt --fp16

3. 使用 C++ 加载 TensorRT 引擎并进行推理

下面是一个完整的 C++ 示例代码,演示如何加载 TensorRT 引擎并进行推理。

必要的库和头文件

你需要安装并包含以下库和头文件:

#include <NvInfer.h>
#include <NvOnnxParser.h>
#include <cuda_runtime_api.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <fstream>
#include <memory>
#include <vector>
YOLOv5 推理类
class YoLov5TRT {
public:
    YoLov5TRT(const std::string& engine_file_path);
    ~YoLov5TRT();
    std::vector<float> infer(const cv::Mat& image);

private:
    void loadEngine(const std::string& engine_file_path);
    void preprocessImage(const cv::Mat& image, float* gpu_input);
    std::vector<float> postprocessResults(float* gpu_output);

    nvinfer1::IRuntime* runtime_;
    nvinfer1::ICudaEngine* engine_;
    nvinfer1::IExecutionContext* context_;
    cudaStream_t stream_;
    void* buffers_[2];
    int input_size_;
    int output_size_;
};

YoLov5TRT::YoLov5TRT(const std::string& engine_file_path) {
    loadEngine(engine_file_path);
}

YoLov5TRT::~YoLov5TRT() {
    cudaStreamDestroy(stream_);
    cudaFree(buffers_[0]);
    cudaFree(buffers_[1]);
    context_->destroy();
    engine_->destroy();
    runtime_->destroy();
}

void YoLov5TRT::loadEngine(const std::string& engine_file_path) {
    // 创建 Runtime
    runtime_ = nvinfer1::createInferRuntime(gLogger);
    std::ifstream engine_file(engine_file_path, std::ios::binary);
    if (!engine_file) {
        std::cerr << "Failed to open engine file." << std::endl;
        return;
    }
    engine_file.seekg(0, std::ifstream::end);
    size_t fsize = engine_file.tellg();
    engine_file.seekg(0, std::ifstream::beg);
    std::vector<char> engine_data(fsize);
    engine_file.read(engine_data.data(), fsize);
    engine_file.close();

    // 反序列化引擎
    engine_ = runtime_->deserializeCudaEngine(engine_data.data(), fsize, nullptr);
    context_ = engine_->createExecutionContext();

    // 获取输入输出大小
    input_size_ = 1 * 3 * 640 * 640;  // 假设输入是 640x640 的图像
    output_size_ = 1 * 25200 * 7;     // 假设输出是 25200x7

    // 分配 GPU 内存
    cudaMalloc(&buffers_[0], input_size_ * sizeof(float));
    cudaMalloc(&buffers_[1], output_size_ * sizeof(float));

    cudaStreamCreate(&stream_);
}

void YoLov5TRT::preprocessImage(const cv::Mat& image, float* gpu_input) {
    cv::Mat resized;
    cv::resize(image, resized, cv::Size(640, 640));
    resized.convertTo(resized, CV_32FC3, 1.0 / 255);
    std::vector<float> input_data(input_size_);
    std::memcpy(input_data.data(), resized.data, input_data.size() * sizeof(float));
    cudaMemcpyAsync(gpu_input, input_data.data(), input_size_ * sizeof(float), cudaMemcpyHostToDevice, stream_);
}

std::vector<float> YoLov5TRT::postprocessResults(float* gpu_output) {
    std::vector<float> output_data(output_size_);
    cudaMemcpyAsync(output_data.data(), gpu_output, output_size_ * sizeof(float), cudaMemcpyDeviceToHost, stream_);
    cudaStreamSynchronize(stream_);
    return output_data;
}

std::vector<float> YoLov5TRT::infer(const cv::Mat& image) {
    preprocessImage(image, static_cast<float*>(buffers_[0]));

    // 执行推理
    context_->enqueueV2(buffers_, stream_, nullptr);

    return postprocessResults(static_cast<float*>(buffers_[1]));
}
主程序
int main() {
    // 加载 TensorRT 引擎
    YoLov5TRT yolov5_trt("yolov5s.trt");

    // 读取输入图像
    cv::Mat image = cv::imread("image.jpg");

    // 执行推理
    std::vector<float> output = yolov5_trt.infer(image);

    // 打印或处理输出结果
    for (const auto& val : output) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}

总结

这个示例展示了如何使用 C++ 和 TensorRT 进行 YOLOv5 模型的推理。主要步骤包括:

  1. 将模型导出为 ONNX 格式。

  2. 使用 TensorRT 工具将 ONNX 模型转换为 TensorRT 引擎。

  3. 使用 C++ API 加载引擎,并实现图像的前处理和后处理。

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值