1 问题出现

最近在使用TensorRT 7.2.3.4中的自带的trtexec工具转换yolov3-spp的onnx模型为TensorRT模型文件时出现了找不到ScatterND插件的错误,错误大致如下:

ModelImporter.cpp:135: No importer registered for op: ScatterND. Attempting to import as plugin.
builtin_op_importers.cpp:3771: Searching for plugin: ScatterND, plugin_version: 1, plugin_namespace:
INVALID_ARGUMENT: getPluginCreator could not find plugin ScatterND version 1
ERROR: builtin_op_importers.cpp:3773 In function importFallbackPluginImporter:

意思大概就是没有在TensorRT中找到ScatterND插件。

2 解决方案

2.1 解决方案1

自行编译:https://github.com/NVIDIA/trt-samples-for-hackathon-cn 下的的Plugins目录,该目录下包含了ScatterND插件

TensorRT – 解决INVALID_ARGUMENT: getPluginCreator could not find plugin ScatterND version 1,TensorRT找不到ScatterND插件的问题-StubbornHuang Blog

编译完成之后会生成ScatterND.so动态库, 在转换ONNX到Tensort模型的过程中在trtexec命令行中手动链接插件:

示例命令行:

trtexec --onnx=yolov3_spp.onnx --explicitBatch --saveEngine=yolov3_spp.engine --workspace=10240 --fp16 --verbose --plugins=ScatterND.so

此方式参考自:https://github.com/oreo-lp/AlphaPose_TRT,不过该方法未测试,因为在Windows系统上,使用makefile比较麻烦。

2.2 解决方案2

2.2.1 官方文档沧海寻珠

觉得第一种方式比较麻烦之后,总想寻找其他的比较省时省力的方式,在细细的查看了NVIDIA的官方文档之后,偶然在容器发行版本(https://docs.nvidia.com/deeplearning/tensorrt/container-release-notes/rel_21-07.html#rel_21-07)的说明上,

TensorRT 21.07的的主要更新提到:

The Python API documentation can be found in the /workspace/tensorrt/doc/python directory.
TensorRT 8.0.1.6. Note that the ONNX parser and plugin libraries bundled with this container are built from TensorRT Open Source Software: https://github.com/NVIDIA/TensorRT/releases/tag/21.07. Prominent updates to the 21.07 TensorRT Open Source Software release are:
Major upgrade to TensorRT 8.0.1.6 GA.
Added support for ONNX operators: Celu, CumSum, EyeLike, GatherElements, GlobalLpPool, GreaterOrEqual, LessOrEqual, LpNormalization, LpPool, ReverseSequence, and SoftmaxCrossEntropyLoss.
Enhanced support for ONNX operators: Resize, ConvTranspose, InstanceNormalization, QuantizeLinear, DequantizeLinear, Pad.
Added new plugins: EfficientNMS_TRT, EfficientNMS_ONNX_TRT, ScatterND.
Added new samples: engine_refit_onnx_bidaf, efficientdet, efficientnet.
Added docker build support for Ubuntu20.04 and RedHat/CentOS 8.3.
Added Python 3.9 support.
Updates to ONNX tools: Polygraphy v0.30.3, ONNX-GraphSurgeon v0.3.10, Pytorch Quantization toolkit v2.1.0.
Removed IPlugin and IPluginFactory interfaces.
Removed samples: samplePlugin, sampleMovieLens, sampleMovieLensMPS.
Removed docker build support for Ubuntu 16.04, and PowerPC.
TensorRT – 解决INVALID_ARGUMENT: getPluginCreator could not find plugin ScatterND version 1,TensorRT找不到ScatterND插件的问题-StubbornHuang Blog

上面的主要意思是针对TensorRT 8.0.1.6 GA的重大升级,其中就包括新增了插件EfficientNMS_TRT、EfficientNMS_ONNX_TRT、ScatterND。

binggo!

这意味着如果我们使用TensorRT 8.0.1.6以上的版本,那么TensorRT中就已经自带ScatterND,不用自己再去编译那么麻烦了。

这个想法也在TensorRT上的官方仓库得到了验证:https://github.com/NVIDIA/TensorRT/tree/master/plugin,在这个Plugins列表下就有ScatterPlugin,也是我们需要的version 1 版本。

TensorRT – 解决INVALID_ARGUMENT: getPluginCreator could not find plugin ScatterND version 1,TensorRT找不到ScatterND插件的问题-StubbornHuang Blog
TensorRT – 解决INVALID_ARGUMENT: getPluginCreator could not find plugin ScatterND version 1,TensorRT找不到ScatterND插件的问题-StubbornHuang Blog

2.2.2 编译成功

在阅读完上述官方文档之后,果然从官网下载最新的TensorRT-8.0.3.4版本,替换掉原来的TensorRT-7.2.3.4版本,重新用TensorRT-8.0.3.4的trtexec工具执行ONNX模型转换TensorRT模型命令行,转换成功了!!!

日志上出现了成功创建插件 : ScatterND的输出

TensorRT – 解决INVALID_ARGUMENT: getPluginCreator could not find plugin ScatterND version 1,TensorRT找不到ScatterND插件的问题-StubbornHuang Blog

转换过程中需要等待一定时间,最后成功截图。

TensorRT – 解决INVALID_ARGUMENT: getPluginCreator could not find plugin ScatterND version 1,TensorRT找不到ScatterND插件的问题-StubbornHuang Blog

2.2.3 在C++ API中使用插件ScatterND

在TensorRT模型转换完成之后,使用TensorRT C++ API在C++环境中进行加载,结果依然显示
getPluginCreator could not find plugin: ScatterND version: 1

[09/18/2021-10:02:19] [I] [TRT] [MemUsageChange] Init CUDA: CPU +345, GPU +0, no
w: CPU 10718, GPU 827 (MiB)
[09/18/2021-10:02:19] [I] [TRT] Loaded engine size: 360 MB
[09/18/2021-10:02:19] [I] [TRT] [MemUsageSnapshot] deserializeCudaEngine begin:
CPU 10719 MiB, GPU 827 MiB
[09/18/2021-10:02:20] [E] [TRT] 3: getPluginCreator could not find plugin: Scatt
erND version: 1
[09/18/2021-10:02:20] [E] [TRT] 1: [pluginV2Runner.cpp::nvinfer1::rt::load::292]
 Error Code 1: Serialization (Serialization assertion creator failed.Cannot dese
rialize plugin since corresponding IPluginCreator not found in Plugin Registry)
[09/18/2021-10:02:20] [E] [TRT] 4: [runtime.cpp::nvinfer1::Runtime::deserializeC
udaEngine::76] Error Code 4: Internal Error (Engine deserialization failed.)
加载模型失败

真的是令人头秃,明明使用trtexec成功转换了模型并且在日志中已经找到了ScatterND插件,为啥在C++中加载模型又找不到插件了呢?是不是遗忘了啥步骤?

再去翻了官方文档之后,发现如果在C++中需要使用插件,需要在最开始就初始化插件,这可以在TensorRT8.0.3.4官方demo的sampleSSD项目下的sampleSSD.cpp下的第123行发现初始化插件的代码:

initLibNvInferPlugins(&sample::gLogger.getTRTLogger(), "");

之后在项目中加上这句就显示模型加载成功了。

TensorRT – 解决INVALID_ARGUMENT: getPluginCreator could not find plugin ScatterND version 1,TensorRT找不到ScatterND插件的问题-StubbornHuang Blog

看完这篇博客,你还不原地起立?别别别,点赞就行!