最近在部署一个YOLOv8-seg模型到Jetson Orin上,用PyTorch转ONNX的时候设了dynamic_axes,转TensorRT时也加了--dynamicShapes,但推理时只要输入分辨率不是固定尺寸就报 “The provided input shape is not compatible with the engine” 或者有时直接崩。我看网上教程都说设了dynamic就行,但实际跑起来各种坑。我用的TensorRT是8.6,ONNX是从ultralytics官方脚本导出的。有没有人遇到过类似问题?是ONNX导出时opset版本的问题,还是TensorRT这边min/opt/max的profile设置不对?另外,分割头的输出形状变化是不是也要单独处理?求有实际部署经验的大佬指点一下,卡了两天了,谢谢!
PyTorch转ONNX再转TensorRT,Dynamic Shape一直报错,求大佬指点
全部回复
共 124 条ONNX里dynamic_axes没覆盖到所有输出,TensorRT建engine时profile也得设全,不然就这报错。
ONNX那边dynamic_axes光设batch不够,h和w也得显式标上,不然TRT压根不认。
这个坑我去年在Orin上踩过,YOLOv8-seg的dynamic shape确实比检测模型更容易出问题。你留意一下ONNX导出时的opset,ultralytics默认好像是17,但TensorRT 8.6对某些op的dynamic支持在17上是有bug的,试试降到16或者升到18对比下。另一个隐蔽点是min/opt/max这三个shape,很多人只填了opt,结果engine编译出来的profile只覆盖那一档,输入稍微变一点就报不兼容。分割头里的Resize和Concat节点在dynamic下特别容易让TRT推断出错误的维度范围,建议用trtexec加--minShapes/--optShapes/--maxShapes显式写全,再配合--verbose看它实际吃进去的profile。还有个经验是别直接用ultralytics导出的onnx跑TRT,先用onnxsim过一遍,把那些常量折叠和冗余transpose清掉,dynamic推理会稳很多。如果还是崩,可以先把seg分支单独拆出来测,确认是backbone还是proto那边的问题。
这个坑我去年在Orin上踩过一模一样的,YOLOv8-seg转TRT做动态shape确实比检测模型更容易出问题。你那个报错大概率不是opset的事,opset 12以上一般够用,问题多半出在TensorRT的optimization profile没配好。用trtexec加--dynamicShapes只是开了个口子,真正决定能跑哪些分辨率的是minShapes/optShapes/maxShapes这三个参数,如果只写--dynamicShapes而不显式指定profile,TRT有时会退化成一个很窄的范围,你喂进去的尺寸稍微偏一点就报incompatible。建议你转engine的时候把三个shape都写全,比如--minShapes=images:1x3x640x640 --optShapes=images:1x3x960x960 --maxShapes=images:1x3x1280x1280,注意seg模型还有输出mask的维度也要一起设。另外ultralytics导出的ONNX里如果dynamic_axes只标了batch没标h/w,那TRT那边再怎么设也没用,得回去检查ONNX的输入是不是真的dynamic。还有个隐蔽的点是YOLOv8-seg的proto分支对h/w有整除要求,分辨率不是32的倍数时中间层会直接对不齐崩掉。你可以先用polygraphy跑一下onnxruntime确认动态维度真的生效了,再往TRT走,能省不少排查时间。