为了寻找更便捷的使用自定义层的方法,我把关注点放在了IPluginV2类上。
因为IPluginV2的方法在Developer Guide上叙述的不多,仅仅有一个地方做了详细描述,也就是4.1Adding Custom Layers Using The C++ API.
在我看来现在的IPluginV2方法有两个打开方法:
(1)IPluginV2方法使用tensorRT已有的自定义层
(2)IPluginV2方法使用自己定义的自定义层
IPluginV2方法使用tensorRT已有的自定义层
已经支持的自定义层
在研发者手册中已经清楚的写了,已经被tensorRT官方支持的自定义层,有以下这些:
RPROI_TRT
Normalize_TRT
PriorBox_TRT
GridAnchor_TRT
NMS_TRT
LReLU_TRT
Reorg_TRT
Region_TRT
Clip_TRT
其实,在fastercnn的sample中就已经使用了IPluginV2.
sampleFasterRCNN,sampleSSD
在main函数中调用了initLibNvInferPlugins()方法
initLibNvInferPlugins(&gLogger.getTRTLogger(), "");
而且,开发手册上说
To use TensorRT registered plugins in your application, the libnvinfer_plugin.so library must be loaded and all plugins must be registered. This can be done by calling initLibNvInferPlugins(void* logger, const char* libNamespace)() in your application code.
也就是说这个方法是用来加载libnvibfer_plugin.so的,所以,我尝试将NvInferPlugin.h中的createRPNROIPlugin类的声明注释掉,这个sample也是照样能跑的。
这就说明,当使用InitLibNvInferPlugins这个方法的时候,并没有读头文件中的声明,而是直接在.so文件中找。
同理,在sampleSSD中,也是只用了initLibNvInferPlugins方法,然后所有的Permute,PriorBox,DetectionOutput层都能成功解析。
从sampleSSD中看出,initLibNvInferPlugins方法对两个版本的IPlugin都有用(INvPlugin*和nvinfer1::IPluginV2),因为Permute方法只有用IPlugin定义的头文件,没有IPluginV2的头文件声明。
以下是两个版本的IPlugin的支持的自定义层的总结:(其中,在注释中也清楚的写了IPlugin->IPluginV2的对应关系)
## INvPlugin
INvPlugin* createFasterRCNNPlugin # 被createRPNROIPlugin取代
INvPlugin* createSSDNormalizePlugin # 被createNormalizePlugin取代
INvPlugin* createSSDPermutePlugin # 建议用shuffle层进行permute操作
INvPlugin* createSSDPriorBoxPlugin # 被createPriorBoxPlugin取代
INvPlugin* createSSDAnchorGeneratorPlugin # 被createAnchorGeneratorPlugin取代
INvPlugin* createSSDDetectionOutputPlugin # 被createNMSPlugin取代
INvPlugin* createConcatPlugin # 被写进了最新版本的TensorRT的concat层中(支持concat)
INvPlugin* createPReLUPlugin # 被createLReLUPlugin取代
INvPlugin* createYOLOReorgPlugin # 被createReorgPlugin取代
INvPlugin* createYOLORegionPlugin # 被createRegionPlugin取代
## nvinfer1::IPluginV2
nvinfer1::IPluginV2* createRPNROIPlugin
nvinfer1::IPluginV2* createNormalizePlugin
nvinfer1::IPluginV2* createPriorBoxPlugin
nvinfer1::IPluginV2* createAnchorGeneratorPlugin
nvinfer1::IPluginV2* createNMSPlugin
nvinfer1::IPluginV2* createLReLUPlugin
nvinfer1::IPluginV2* createReorgPlugin
nvinfer1::IPluginV2* createRegionPlugin
nvinfer1::IPluginV2* createClipPlugin
nvinfer1::IPluginV2* createBatchedNMSPlugin
所以除了concat被兼容了,permute被用shuffle操作实现了,其余的在V2版本都进行了更新。
除此之外,V2版本增加了Clip和BatchedNMSPlugin的支持,clip用来设定value值在某个区间内,BatchedNMS是在每个batch的所有类上执行NMS。而上面的NMSPlugin是通过执行非最大抑制来基于位置和置信度预测生成检测输出(为ssd服务的)。
定义好的自定义层,是根据prototxt的type属性,进行匹配
除此之外,发现TensorRT定义好的无论是IPlugin还是IPluginV2的自定义层,都是按照“type”匹配的,我把prototxt中RPROI的层name改完之后,不会报错,但是改了type的值(type: “RPROI”)之后,就会报错无法解析。