最近在部署一个分割模型,本地用PyTorch跑没问题,但上了TensorRT就各种不对。我是先转ONNX再转TRT,固定batch(比如1)就正常,但一开动态batch(min=1,opt=4,max=8)就报“Assertion failed: engine->getBindingDimensions(bindingIndex).nbDims == 4”之类的错。搜了一圈,有说要在ONNX里显式加DynamicAxes的,也有说TRT的Profiles要设置对齐的,试了还是不行。有没有大佬指点一下,或者分享下你们现在常用的部署流程?感谢!
PyTorch转ONNX再转TensorRT,动态batch一直报错,有人踩过这坑吗?
全部回复
共 14 条试试在ONNX导出时把dynamic_axes的batch维和TRT profile的shape范围完全对齐,我之前卡了好久就是这么解决的。
别光看DynamicAxes,查查ONNX里reshape和transpose的输出维度,动态batch最坑的就是中间层把batch维弄丢了。
我上次是给输入加个identity节点锁shape才过的,你试试固定输入名加profile时用range匹配。
这报错看着像是ONNX导出时动态轴的名称和TRT profile里的绑定没对上,尤其是分割模型输出层经常有resize或reshape,动态维度传过去就乱了。我之前是把ONNX的dynamic_axes里所有维度的名字统一,然后在TRT里按顺序设置profile,并且把输入输出的shape都显式写全,不能只给输入设动态。另外建议直接用torch.onnx.export的dynamic_axes参数,别事后改ONNX,容易漏掉中间节点。你现在是用的onnx-tensorrt还是trtexec转的?如果是前者,可以试试换成trtexec加--minShapes那些参数,排查起来更直观。
这坑我太熟了,之前做检测模型的时候也被动态batch折磨过好久。你说的报错本质上是TRT在推理时拿到的输入维度跟你engine里profile定义的维度对不上,尤其是当ONNX导出时动态轴没写对,TRT就会默认按静态shape去解析。我后来是把ONNX的dynamic_axes显式加到输入和输出上,而且必须保证opset版本在11以上,不然动态shape的信息根本传不进去。另外profile的min/opt/max不光要设置,还得确认跟你实际输入数据的shape完全一致,比如你是NCHW的话,opt那组维度最好挑个真实会用到的尺寸,别随便填个4。还有个容易忽略的点,就是TRT的engine在序列化后重新加载时,如果输入shape跟profile不匹配,也会触发那个assert,所以每次推理前最好用context.set_binding_shape重新确认一下。我现在更倾向于直接用Torch-TensorRT或者把模型转成FP16的engine,反而省心不少,动态batch的问题少很多。你要是非走ONNX这条路,建议先拿onnxruntime验证下动态轴导出是否正确,能跑通再进TRT,排查起来更快。
我之前也是卡在这,得在onnx导出时把dynamic_axes设对,trt那边profile的shape范围要和它完全一致才行。
这坑我太熟了,当时搞检测模型也卡在这。你那个报错本质上是TRT拿到的输入还是4维静态shape,动态轴没真正传进去,ONNX里光加DynamicAxes不够,得确认导出时dynamic_axes的dict里每个维度的名字跟后续profile设置完全对上,大小写和顺序都不能错。另外TRT的profile里opt shape很关键,我之前就是opt设太大,显存不够直接崩,后来改成opt=4,min和max跟实际数据分布贴近才稳。还有个容易忽略的点,转ONNX时opset版本最好用13以上,有些算子对动态shape支持更完整。你现在是直接用trtexec转还是代码里build engine?如果代码里建议把network输入显式声明为动态维度,别依赖onnx解析自动推断,我之前就是漏了这步排查半天。另外可以试试先用固定shape把整个流程跑通,再加动态,这样能定位是转换问题还是推理时输入shape没对齐。分割模型的话输出层也可能有类似问题,建议把输出也设成动态,不然TRT对输出shape卡得比输入还死。
这坑我熟,多半是ONNX导出时dynamic_axes没把输入的batch维和输出的batch维一起绑定了,TRT那边Profile的shape范围也得跟ONNX完全对齐,差一个数都不行。另外建议用onnx-simplifier先处理一遍,有些动态shape的Resize或Gather算子会导致TRT解析出奇怪的维度。你报错那个nbDims==4,看着像某个中间层被推断成静态shape了,可以试着在转TRT时把preview features全开,或者干脆用onnxruntime的trt EP先跑通再排查。
这报错看着像是ONNX导出时动态轴没真正生效,TRT拿到的还是静态shape。建议先onnx.checker验证下输出,再用polygraphy对比下中间层,大概率是某个Resize或Gather把动态维度写死了。另外TRT的profile里opt shape最好和实际部署的常用尺寸一致,别拍脑袋填,我之前就是opt设太大导致显存分配错乱。
我现在一般直接走torch2trt或者用TensorRT自带的ONNX-GraphSurgeon改图,动态batch反而省心。你如果坚持ONNX中转,试试把opset版本拉到17以上,有些老版本对动态shape支持有bug。
这坑我熟,多半不是Profiles的问题,是ONNX导出时dynamic_axes没跟输入绑对。你试试导出时把input的axes={0:'batch'}写上,然后用trtexec加--minShapes验证下,能过再集成代码。另外TRT新版对隐式batch卡得严,建议直接走显式batch,省得后面又踩别的雷。
这问题太典型了,我当时搞动态batch也卡了好几天。你报错那个nbDims==4,大概率是ONNX导出时没把batch维设成symbolic,或者TRT那边profile的shape没跟模型实际输入对齐。建议你先用onnxruntime验证下动态轴是不是真生效了,很多模型转出来batch维还是写死的。另外试试直接用TensorRT的Python API搭网络,别走ONNX中转,分割模型算子不多,手写engine反而省心。还有个小坑,opt batch别设4,设成跟max一样8,有时候优化器会抽风。
ONNX导出时dynamic_axes要跟TRT profile的shape范围完全对上,你这报错八成是某个中间层维度写死了。
这个报错我之前也卡了很久,后来发现是ONNX导出时dynamic_axes只加了batch维度,但TRT那边要求所有维度的范围都得显式给到,尤其是H、W如果跟着变也得一起设进去。你试试把输入shape写成(1,3,-1,-1),然后导出时把axes={0: 'batch', 2: 'height', 3: 'width'}都配上,再用trtexer的--minShapes那些参数对齐一下。另外检查下模型里有没有resize或插值层,动态shape下这些算子有时会偷偷把维度搞成静态,导致binding维度对不上。我最后还是换了种思路,直接用onnxruntime做动态batch,省得跟TRT较劲,效果也够用。
这个报错大概率是ONNX里某个节点的输出shape没带上动态维度,TRT解析时对不上就炸了。你转ONNX的时候试试把dynamic_axes每个输入输出都显式写全,别偷懒用默认。另外TRT的profile里opt shape最好跟ONNX推导出来的一致,不然优化阶段会按错的维度去build。我上次也是卡在这,后来用polygraphy跑一遍onnx推理对比输出才定位到问题节点。
这个坑太典型了,大概率是ONNX里某些op的shape推导把batch维度写死了,转TRT后动态profile对不上就炸了。建议先用polygraphy或onnxruntime跑一下动态shape推理,看ONNX本身支不支持变batch,别急着怪TRT。另外TRT的optimization profile里min/opt/max三个shape必须和ONNX输入的dynamic axes严格对齐,尤其是分割模型里常有resize或interpolate,容易偷偷固定尺寸。我现在一般直接torch-tensorrt或者用trtexec加--minShapes/--optShapes/--maxShapes手动指定,比脚本转换稳不少。