当前位置: 首页 > news >正文

ultralytics导出engine之后,用tensorrt c++ api加载报Serialization failed

一。问题复现

1.生成engine

在安装了ultralytics之后,或者直接用源码也一样。运行如下代码

(或者用命令行也行:yolo task=detect mode=export model=/home/kv183/tensorrt_starter/ultralytics-main/weights/yolov8s.pt format=engine )

from ultralytics import YOLO


if __name__ == '__main__':
    # Load a pretrained YOLO11n model
    model = YOLO("/home/kv183/tensorrt_starter/ultralytics-main/weights/yolov8s.pt")
    print(model.export(format='engine'))

注意,我在python环境中安装的tensorrt是8.6.1,跟我c++工程所用的tensorrt版本保持一致,其实这个python的tensorrt就是在从英伟达下载的tensorrt8.6.1的python目录中找到的wheel包。

另外说一下,这个python目录里的tensorrt_lean, tensorrt_dispatch是在考虑版本兼容、轻量化的时候才需要用到的, 如果不涉及就没必要用它们。

2.用tensorrt c++ api进行推理

本文并不详细讲解怎么用tensorrt c++ api进行推理,主要就是解决ultralytics导出engine的问题,所以就不详细讲相关代码了。其实问题就出在反序列化engine这一步,运行到第55行就会失败了,那个data就是engine文件的内容(用二进制模式读取文件内容)

报错如下:

[error]1: [runtime.cpp::parsePlan::314] Error Code 1: Serialization (Serialization assertion plan->header.magicTag == rt::kPLAN_MAGIC_TAG failed.)

二。问题分析

1.兼容性问题

 就这个报错本身来说,多半是兼容性问题,比如你生成engine用的tensorrt版本是A,它会在engine文件中写一个magicTag,但你推理的时候用的tensorrt版本是B,它在反序列化engine的时候发现文件中的magicTag与当前版本的不一致,就会报上面的错误并退出程序。

兼容性问题包括:tensorrt版本、系统(windows、linux)、gpu,具体可以看tensorrt文档

但我这里明显不会有兼容性问题,首先是在同一台电脑上,在wsl ubuntu中,c++用tensorrt8.6.1,python用的tensorrt也是相同版本。

2.文件格式问题

在c++项目中,yolov8s我有两个engine文件,绿色的是直接调tensorrt api,解析onnx然后生成的engine(其实跟用tensorrt提供的trtexec差不多,trtexec本身也是调tensorrt api的),而红色的就是用ultralytics生成的engine。

用vi看一下绿色的文件内容,开头可以看到ftrt几个字母,其实这叫魔数(Magic Number),它就是代表这个文件的格式,表明它是engine文件。很多文件都有魔数,比如zip文件是PK,pdf文件是%PDF。

接着用vi看一下红色的文件内容(即用ultralytics生成的engine)

 会发现在ftrt前面多了一些东西,这像是ultralytics自己写的一些元数据。

直接去看一下它导出engine文件的代码,如上图,确实在engine文件的开头加入了一些元数据。tensorrt当然是不支持这种操作的,其实这些元数据是ultralytics在加载engine文件进行推理的时候用的,比如输入shape、分类信息。

 上图就是ultralytics在加载engine时,会尝试加载元数据。

现在已经很明确了,解决这个问题的办法无非下面几个:

(1)不用ultralytics生成engine,只用它导出onnx文件,然后用trtexec解析onnx生成engine,或者自己直接调tensorrt api解析onnx生成engine。

(2)如果想在c++项目中使用ultralytics生成的engine,则

a)把ultralytics写元数据那几行代码注释掉,如下

b)如果不想改ultralytics的代码,则在c++项目中读取engine文件内容的时候, 跳过开头的元数据

再参考一下ultralytics加载engine的代码如上图,元数据的长度不是固定的,但是它开头的4个字节就是代表了元数据的长度。即ultralytics生成的engine文件的内容是:4字节的整型数+元数据+真正的engine内容。

接下来验证一下,采用方案(2)-a),即注释ultralytics中生成元数据的代码,重新生成engine,通过c++项目加载engine,成功推理如下:

 

相关文章:

  • 【Python爬虫(59)】解锁学术文献网站数据爬取:从登录到知识图谱构建
  • [算法--前缀和] 矩阵区域和
  • 【Golang】go语言异常处理快速学习
  • PHP应用程序设计:一个实际的例子(3)
  • 【博资考2】网安学院-北航网安基础部分(简洁版)
  • zabbix“专家坐诊”第276期问答
  • 八、Spring Boot:RESTful API 应用
  • 【链 表】
  • matlab 海浪模型和舰艇动力学模型
  • 【后端】微服务架构
  • 【学习笔记】Cadence电子设计全流程(三)Capture CIS 原理图绘制(中)
  • 和Claude对战黑白棋!一起开发AI对弈游戏
  • Python开发 Flask框架面试题及参考答案
  • 循环神经网络rnn
  • 第二十:【路由的props配置】
  • 鸿蒙-canvas-刮刮乐
  • MySQL 序列
  • Docker 之mysql从头开始——Docker下mysql安装、启动、配置、进入容器执行(查询)sql
  • Python常见面试题的详解21
  • 动态自定义标签属性页面(Tomcat 9)
  • 六省会共建交通枢纽集群,中部离经济“第五极”有多远?
  • 查幽门螺杆菌的这款同位素长期被海外垄断,秦山核电站实现突破
  • 第一集|好饭不怕晚,折腰若如初见
  • 病重老人被要求亲自取钱在农业银行门口去世?株洲警方介入
  • 西班牙政府排除因国家电网遭攻击导致大停电的可能
  • 第十届影像上海博览会落幕后,留给中国摄影收藏的三个问题