yolov11 部署 TensorRT,预处理和后处理用 C++ cuda 加速,速度快到飞起

部署运行你感兴趣的模型镜像

  之前搞过不少部署,也玩过tensorRT部署模型(但都是模型推理用gpu,后处理还是用cpu进行),有网友问能出一篇tensorRT用gpu对模型后处理进行加速的。由于之前用的都是非cuda支持的边缘芯片,没有写过cuda代码,这个使得我犹豫不决。零零总总恶补了一点cuda编程,于是就有了这篇博客【yolov11 部署 TensorRT,预处理和后处理用 C++ cuda 加速,速度快到飞起】。既然用cuda实现,就不按照部署其他芯片(比如rk3588)那套导出onnx的流程修改导出onnx代码,要尽可能多的操作都在cuda上运行,这样导出onnx的方式就比较简单(yolov11官方导出onnx的方式)。

  rtx4090显卡、模型yolov11n(输入分辨率640x640,80个类别)、量化成FP16模型,最快1000fps

  本示例中,包含完整的代码、模型、测试图片、测试结果。

  后处理部分用cuda 核函数实现,并不是全部后处理都用cuda实现【cuda实现后处理代码】;纯cpu实现后处理部分代码分支【cpu实现后处理代码】

  使用的TensorRT版本:TensorRT-8.6.1.6
  cuda:11.4
  显卡:RTX4090

cuda 核函数主要做的操作

  由于按照yolov11官方导出的onnx,后处理需要做的操作只有nms了。mns流程:选出大于阈值的框,在对这些大于阈值的框进行排序,在进行nms操作。这几部中最耗时的操作(对类别得分选出最大对应的类别,判断是否大于阈值)是选出所有大于阈值的框,经过这一步后实际参加nms的框没有几个(比如图像中有30个目标,每个目标出来了15个框,也才450个框),因此主要对这一步操作“选出所有大于阈值的框”用cuda实现。当然后续还可以继续优化,把nms的过程用cuda核函数进行实现。

  核函数的实现如下:模型输出维度(1,(4+80),8400),主要思想流程用8400个线程,实现对80个类别选出最大值,并判断是否大于阈值。

__global__ void GetNmsBeforeBoxesKernel(float *SrcInput, int AnchorCount, int ClassNum, float ObjectThresh, int NmsBeforeMaxNum, DetectRect* OutputRects, int *OutputCount)
{
	/***
	功能说明:用8400个线程,实现对80个类别选出最大值,并判断是否大于阈值,把大于阈值的框记录下来后面用于参加mns
	SrcInput: 模型输出(1,84,8400)
	AnchorCount: 8400
	ClassNum: 80
	ObjectThresh: 目标阈值(大于该阈值的目标才输出)
	NmsBeforeMaxNum: 输入nms检测框的最大数量,前面申请的了一块儿显存来装要参加nms的框,防止越界
	OutputRects: 大于阈值的目标框
	OutputCount: 大于阈值的目标框个数
	***/
	
    int ThreadId = blockIdx.x * blockDim.x + threadIdx.x;
   
    if (ThreadId >= AnchorCount)
    {
        return;
    }

    float* XywhConf = SrcInput + ThreadId;
    float CenterX = 0, CenterY = 0, CenterW = 0, CenterH = 0;

    float MaxScore = 0;
    int MaxIndex = 0;

    DetectRect TempRect;
    for (int j = 4; j < ClassNum + 4; j ++) 
    {
        if (4 == j)
        {
            MaxScore = XywhConf[j * AnchorCount];
            MaxIndex = j;   
        } 
        else 
        {
            if (MaxScore <  XywhConf[j * AnchorCount])
            {
                MaxScore = XywhConf[j * AnchorCount];
                MaxIndex = j;   
            }
        }  
    }

    if (MaxScore > ObjectThresh)
    {
        int index = atomicAdd(OutputCount, 1);
    
        if (index > NmsBeforeMaxNum)
        {
            return;
        }

        CenterX = XywhConf[0 * AnchorCount];
        CenterY = XywhConf[1 * AnchorCount];
        CenterW = XywhConf[2 * AnchorCount];
        CenterH = XywhConf[3 * AnchorCount ];

        TempRect.classId = MaxIndex - 4;
        TempRect.score = MaxScore;
        TempRect.xmin = CenterX - 0.5 * CenterW;
        TempRect.ymin = CenterY - 0.5 * CenterH;
        TempRect.xmax = CenterX + 0.5 * CenterW;
        TempRect.ymax = CenterY + 0.5 * CenterH;

        OutputRects[index] = TempRect;
    }
}

导出onnx模型

  按照yolov11官方导出的方式如下:

from ultralytics import YOLO
model = YOLO(model='yolov11n.pt')  # load a pretrained model (recommended for training)
results = model(task='detect', source=r'./bus.jpg', save=True)  # predict on an image

model.export(format="onnx", imgsz=640, simplify=True)

编译

  修改 CMakeLists.txt 对应的TensorRT位置
在这里插入图片描述

cd yolov11_tensorRT_postprocess_cuda
mkdir build
cd build
cmake ..
make

运行

# 运行时如果.trt模型存在则直接加载,若不存会自动先将onnx转换成 trt 模型,并存在给定的位置,然后运行推理。
cd build
./yolo_trt

测试效果

onnx 测试效果

在这里插入图片描述

tensorRT 测试效果

在这里插入图片描述

tensorRT 时耗(cuda实现部分后处理)

  示例中用cpu对图像进行预处理(由于本台机器搭建的环境不匹配,不能用cuda对预处理进行加速)、用rtx4090显卡进行模型推理、用cuda对后处理进行加速。使用的模型yolov11n(输入分辨率640x640,80个类别)、量化成FP16模型。以下给出的时耗是:预处理+模型推理+后处理。

cpu做预处理+模型推理+gpu做后处理
在这里插入图片描述

tensorRT 时耗(纯cpu实现后处理)【cpu实现后处理代码分支】

cpu做预处理+模型推理+cpu做后处理在这里插入图片描述

替换模型说明

  修改相关的路径


 std::string OnnxFile = "/root/autodl-tmp/yolov11_tensorRT_postprocess_cuda/models/yolov11n.onnx";
 std::string SaveTrtFilePath = "/root/autodl-tmp/yolov11_tensorRT_postprocess_cuda/models/yolov11n.trt";
 cv::Mat SrcImage = cv::imread("/root/autodl-tmp/yolov11_tensorRT_postprocess_cuda/images/test.jpg");

 int img_width = SrcImage.cols;
 int img_height = SrcImage.rows;
 std::cout << "img_width: " << img_width << " img_height: " << img_height << std::endl;

 CNN YOLO(OnnxFile, SaveTrtFilePath, 1, 3, 640, 640);
 
 auto t_start = std::chrono::high_resolution_clock::now();
 int Temp = 2000;
 
 int SleepTimes = 0;
 for (int i = 0; i < Temp; i++)
 {
     YOLO.Inference(SrcImage);
     std::this_thread::sleep_for(std::chrono::milliseconds(SleepTimes));
 }
 auto t_end = std::chrono::high_resolution_clock::now();
 float total_inf = std::chrono::duration<float, std::milli>(t_end - t_start).count();
 std::cout << "Info: " << Temp << " times infer and gpu postprocess ave cost: " << total_inf / float(Temp) - SleepTimes << " ms." << std::endl;

预处理用cuda加速

  代码中已实现用CUDA_npp_LIBRARY进行预处理,如果有环境可以打开进一步加速(修改位置:CMakelist.txt 已进行了注释、用CPU或GPU预处理打开对应的宏 #define USE_GPU_PREPROCESS 1))

  重新搭建了一个支持用gpu对预处理进行加速的环境:rtx4090显卡、模型yolov11n(输入分辨率640x640,80个类别)、量化成FP16模型。对比结果如下:这台机器相比上面贴图中时耗更短,可能是这台机器的cpu性能比较强。以下给出的时耗是:预处理+模型推理+后处理。

cpu做预处理+模型推理+cpu做后处理
在这里插入图片描述
cpu做预处理+模型推理+gpu做后处理
在这里插入图片描述
gpu做预处理+gpu做后处理
在这里插入图片描述

后续优化点

1、把nms过程也用cuda实现,参加nms的框不多,但也是一个优化点,持续更新中

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

<think>好的,用户想了解如何使用TensorRT加速YOLOv5模型。我需要根据提供的引用资料系统指令来组织回答。首先,我需要确保所有数学表达式用$...$格式,独立公式用$$...$$,并且正确使用LaTeX语法。回答需要用中文,结构清晰,还要生成相关问题。 首先,我应该整理步骤。根据引用[1][2],主要步骤包括安装环境、转换模型、生成TensorRT引擎、测试推理。可能需要分点说明每个步骤的具体操作,比如安装TensorRTPyCUDA,转换模型权重,使用tensorrtx生成引擎,最后对比测试性能。 需要注意的是,用户可能对某些步骤不熟悉,比如环境配置或者命令的使用,所以需要详细说明必要的命令代码示例。同时,引用资料中的GitHub仓库地址关键命令要准确无误地引用。 另外,要确保回答中的技术术语正确,比如模型转换工具、推理引擎的生成步骤。可能需要提到FP16或INT8量化,这是TensorRT常用的优化方法,但根据引用内容,主要步骤是生成引擎,可能涉及转换ONNX使用tensorrtx项目中的gen_wts.py对应的生成命令。 还需要注意引用标识的正确添加,比如在提到转换权重或生成引擎时,末尾加上[^1]或[^2]。最后,生成的相关问题要围绕TensorRT加速的优化方法、性能分析、应用场景等,确保问题与主题相关。 检查是否有遗漏的步骤,比如是否需要在YOLOv5中导出模型为ONNX格式,或者是否需要特定的版本匹配。引用资料提到需要下载两个项目,tensorrtxyolov5,并且确保版本匹配,这一点必须包含在步骤中。 最后,确保回答结构清晰,分步骤说明,代码示例用正确的格式,并自然融入引用标识。生成的问题要帮助用户深入理解相关主题,可能包括量化方法、性能比较、部署注意事项等。</think>### 使用 TensorRT 加速 YOLOv5 模型的方法 #### 1. 环境准备 - **安装依赖库**:确保已安装 TensorRT、PyCUDA ONNX。TensorRT 需要与 CUDA 版本匹配[^1]。 - **克隆项目**: ```bash git clone https://github.com/wang-xinyu/tensorrtx.git # TensorRT 模型转换工具[^2] git clone https://github.com/ultralytics/yolov5.git # 官方 YOLOv5 代码库 ``` #### 2. 模型权重转换 - **导出 YOLOv5 模型为 ONNX**: ```bash cd yolov5 python export.py --weights best.pt --include onnx # 将训练好的 .pt 模型转换为 ONNX 格式 ``` - **生成 TensorRT 引擎文件**: ```bash cd tensorrtx/yolov5 python gen_wts.py -w ../yolov5/best.pt -o yolov5.weights # 将 .pt 转换为 TensorRT 支持的 .weights ``` 编译并生成引擎: ```bash mkdir build && cd build cmake .. && make ./yolov5 -s yolov5.weights yolov5.engine s # s 表示输入尺寸(如 640)[^2] ``` #### 3. 推理性能测试 - **原始 PyTorch 模型推理**: ```python python detect.py --weights best.pt --source input.jpg # 基准测试[^1] ``` - **TensorRT 引擎推理**: ```bash ./yolov5 -d yolov5.engine input.jpg # 使用生成的引擎加速推理 ``` 通过 FP16/INT8 量化可进一步提升速度,典型加速比为 2-5 倍。 #### 4. 关键优化技术 - **层融合(Layer Fusion)**:合并卷积、归一化激活函数,减少计算开销。 - **精度校准**:使用 FP16 或 INT8 量化降低计算精度,公式为: $$ Q(x) = \text{round}\left(\frac{x}{S}\right) + Z $$ 其中 $S$ 为缩放因子,$Z$ 为零点偏移。 --- §§ 相关问题 §§ 1. TensorRT 如何通过层融合优化计算效率? 2. INT8 量化会如何影响 YOLOv5 的检测精度? 3. 如何验证 TensorRT 引擎与原始 PyTorch 模型的输出一致性? 4. 在 Jetson 嵌入式设备上部署 TensorRT 有哪些注意事项?
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值