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 进行推理的步骤
-
导出模型为 ONNX 格式: YOLOv5 模型首先需要转换为 ONNX 格式。你可以使用 YOLOv5 的官方工具来完成这个步骤。
-
python export.py --weights yolov5s.pt --include onnx
-
将 ONNX 模型转换为 TensorRT 引擎: 使用
tensorrt
库将 ONNX 模型转换为 TensorRT 引擎。 -
加载 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 模型。主要步骤包括:
-
将模型导出为 ONNX 格式。
-
使用 TensorRT 工具将 ONNX 模型转换为 TensorRT 引擎。
-
使用 TensorRT Python API 加载引擎并进行推理。
希望这个例子能帮助你更好地理解如何使用 TensorRT 进行高效的模型推理。
TensorRT_C++
TensorRT 是 NVIDIA 提供的一个用于深度学习推理的高性能库。它可以对经过训练的神经网络进行优化,生成一个高效的推理引擎,并能够在 NVIDIA 的 GPU 上高效运行。TensorRT 支持多种模型格式,包括 Caffe、TensorFlow、ONNX 等,并且可以对模型进行图层融合、精度混合、内存优化等操作,以实现更快的推理速度和更低的延迟。
使用 TensorRT 进行 YOLOv5 推理的步骤
-
导出模型为 ONNX 格式: 首先需要将 YOLOv5 模型转换为 ONNX 格式。
-
将 ONNX 模型转换为 TensorRT 引擎: 使用 TensorRT 的
trtexec
工具将 ONNX 模型转换为 TensorRT 引擎。 -
使用 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 模型的推理。主要步骤包括:
-
将模型导出为 ONNX 格式。
-
使用 TensorRT 工具将 ONNX 模型转换为 TensorRT 引擎。
-
使用 C++ API 加载引擎,并实现图像的前处理和后处理。