赞
踩
总共有九个头文件,其中NvInfer.h, NvInferPlugin.h, NvUtils.h是公用的,其他的分别用来支持tensorRT支持的三个框架:Caffe, Onnx和Uff(tensorflow).
首先介绍,共用的三个头文件。
占坑,6000多行,最后写这个。
继承于ILayer
里面有很多函数,都是add函数,调用上面的各种类。
这个头文件包含了Nvidia提供的TensorRT plugin的API,说白了就是这个头文件中包含的是已经被Nvidia官方实现了的自定义层,这些层以API的形式提供给大家。
可使用的有以下type的层。
RPROI_TRT
Normalize_TRT
PriorBox_TRT
GridAnchor_TRT
NMS_TRT
LReLU_TRT
Reorg_TRT
Region_TRT
Clip_TRT
如sampleFasterRCNN和sampleSSD中那样,在调用parser之前载入链接库:
initLibNvInferPlugins(&gLogger.getTRTLogger(), "");
TensorRT Developer Guide上的原文是这么描述的:
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的,所有这个层的定义都已经写好并被编译到了这个链接库中。这里的NvInferPugin.h头文件只是一个告知API的作用。
这就说明,当使用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服务的)。
除此之外,发现TensorRT定义好的无论是IPlugin还是IPluginV2的自定义层,都是按照“type”匹配的,我把prototxt中RPROI的层name改完之后,不会报错,但是改了type的值(type: “RPROI”)之后,就会报错无法解析。
这个头文件除了在plugin的命名空间写了相关层的声明,还在nvinfer1命名空间中定义了PluginType这个枚举类,定义在nvinfer1中是关键,可能是为了调用方便。
这个头文件主要包含了三个函数(5.1.5.0版本),同样是闭源封装在链接库中。
这三个函数写在了nvinfer1命名空间中的utils命名空间中。
作用是对Weights的形状和格式进行调节,变成TensorRT可以读取的格式。
reshapeWeights
reorderSubBuffers
transposeSubBuffers
留坑,暂时还没有用到这三个函数中的任意一个。
这三个函数都是对输入的Weights做格式调节的函数。
考虑到一些框架的Weights保存方式和TensorRT的希望的读取方式不同,所以需要这三个工具函数进行调节。
这个头文件主要包括了caffeParser的相关基类。
具体结构如下:
namespace nvcaffeparser1 {
class IBlobNameToTensor
class IBinaryProtoBlob
class IPluginFactory
class IPluginFactoryExt : public IPluginFactory
class IPluginFactoryV2
class ICaffeParser
TENSORRTAPI ICaffeParser* createCaffeParser();
TENSORRTAPI void shutdownProtobufLibrary();
}
extern "C" TENSORRTAPI void* createNvCaffeParser_INTERNAL();
用来解析caffe的model的类。
已知,想要构建caffe-tensorRT的引擎,需要的是prototxt文件和一个binaryproto格式的权重数据文件( .caffemodel)
class ICaffeParser { public: virtual const IBlobNameToTensor* parse(const char* deploy, const char* model, nvinfer1::INetworkDefinition& network, nvinfer1::DataType weightType) = 0; virtual const IBlobNameToTensor* parseBuffers(const char* deployBuffer, std::size_t deployLength, const char* modelBuffer, std::size_t modelLength, nvinfer1::INetworkDefinition& network, nvinfer1::DataType weightType) = 0; virtual IBinaryProtoBlob* parseBinaryProto(const char* fileName) = 0; virtual void setProtobufBufferSize(size_t size) = 0; virtual void setPluginFactory(IPluginFactory* factory) = 0; virtual void destroy() = 0; virtual void setPluginFactoryV2(IPluginFactoryV2* factory) = 0; virtual void setPluginNamespace(const char* libNamespace) = 0; protected: virtual ~ICaffeParser() {} };
总的来说, 类 ICaffeParser主要包含了解析model和设置plugin的两大类函数。
这个类用于ICaffeParser对model进行解析之后,存储和查询tensor。
内部只有一个find方法
virtual nvinfer1::ITensor* find(const char* name) const = 0;
具体用法实例:
...
const IBlobNameToTensor* blobNameToTensor = parser->parse(locateFile(deployFile).c_str(),
locateFile(modelFile).c_str(),
*network,
dataType);
gLogInfo << "End parsing model..." << std::endl;
// Specify which tensors are outputs
for (auto& s : outputs)
network->markOutput(*blobNameToTensor->find(s.c_str()));
...
即parser之后返回的就是一个IBlobNameToTensor*指针,然后根据outputs的数量,进行network->markOutput来标记输出层。
这里这个通过blob名字获取blob的接口函数find()的用途,还可以开发。
这个类用于ICaffeParser对a binaryproto file 进行解析之后,存储和查询数据。和上个类完全不同。
主要有三个函数
virtual const void* getData() = 0;
virtual nvinfer1::DimsNCHW getDimensions() = 0;
virtual nvinfer1::DataType getDataType() = 0;
用来获取存在binaryproto文件中的数据,以及对应的dim和type。
类 IPluginFactory / 类 IPluginFactoryV2都只有两个函数,一个是isPlugin(),另一个是createPlugin().
bool isPlugin(const char* name) override
{
return isPluginExt(name);
}
bool isPluginExt(const char* name) override
{
return !strcmp(name, "ip2");
}
即当该层(tensor)的名称为“ip2”的时候,返回True,否则返回False。
//! \brief Creates a ICaffeParser object.
//! \return A pointer to the ICaffeParser object is returned.
//! \see nvcaffeparser1::ICaffeParser
TENSORRTAPI ICaffeParser* createCaffeParser();
就是用来创建caffeparser的函数,闭源.
//! \brief Shuts down protocol buffers library.
//! \note No part of the protocol buffers library can be used after this function is called.
TENSORRTAPI void shutdownProtobufLibrary();
没用到过,挖坑。
extern "C" TENSORRTAPI void* createNvCaffeParser_INTERNAL();
挖坑。
主要有以下几个部分
namespace nvonnxparser{
class IParserError
class IParser
createParser()
}
extern "C" TENSORRTAPI void* createNvOnnxParser_INTERNAL(void* network, void* logger, int version);
extern "C" TENSORRTAPI int getNvOnnxParserVersion();
用来报错的一个类
同caffe-tensorRT的ICaffeParser类相似。
class IParser { public: virtual bool parse(void const* serialized_onnx_model, size_t serialized_onnx_model_size)= 0; virtual bool parseFromFile(const char* onnxModelFile, int verbosity) = 0; virtual bool supportsModel(void const* serialized_onnx_model, size_t serialized_onnx_model_size)= 0; virtual bool parseWithWeightDescriptors( void const* serialized_onnx_model, size_t serialized_onnx_model_size, uint32_t weight_count, onnxTensorDescriptorV1 const* weight_descriptors)= 0; virtual bool supportsOperator(const char* op_name) const = 0; virtual void destroy() = 0; virtual int getNbErrors() const = 0; virtual IParserError const* getError(int index) const = 0; virtual void clearErrors() = 0; protected: virtual ~IParser() {} };
很明显,这里没有像ICaffeParser那样存在IPluginFactory的类,所以这么看来,至少在这个头文件中是不支持像caffe一样扩展的。
头文件中是这么写的
namespace nvonnxparser { #ifdef SWIG inline IParser* createParser(nvinfer1::INetworkDefinition* network, nvinfer1::ILogger* logger) { return static_cast<IParser*>( createNvOnnxParser_INTERNAL(network, logger, NV_ONNX_PARSER_VERSION)); } #endif // SWIG namespace { #ifdef _MSC_VER TENSORRTAPI IParser* createParser(nvinfer1::INetworkDefinition& network, nvinfer1::ILogger& logger) #else inline IParser* createParser(nvinfer1::INetworkDefinition& network, nvinfer1::ILogger& logger) #endif { return static_cast<IParser*>( createNvOnnxParser_INTERNAL(&network, &logger, NV_ONNX_PARSER_VERSION)); }} }
结合createNvOnnxParser_INTERNAL,定义了一下在“SWIG”或者c++的“_MSC_VER”两种情况下,调用createParser的方法。(具体的暂时也不是特别清楚)
- _MSC_VER:
_MSC_VER是微软公司推出的C/C++编译器在ANSI/ISO C99标准之外扩展的宏定义,用来定义当前微软公司自己的编译器的主版本。- SWIG
C ++ API也可用于创建在Python中使用的自定义层。 C ++是实现自定义层的首选语言(例如,轻松访问CUDA和cuDNN等库)。可以使用Python setuptools中的SWIG插件打包在C ++中创建的自定义层,然后可以将插件加载到Python应用程序中(请参考使用Python API和TensorRT Python绑定创建网络)。相同的自定义层实现可用于C ++和Python。
所以看来好像就是在为python扩展留个接口。
定义了创建pluginFactory的方法
注意,这个是nvonnxparser命名空间下的IPluginFactory类。
namespace nvonnxparser { class IPluginFactory : public nvinfer1::IPluginFactory { public: virtual void destroy() = 0; protected: virtual ~IPluginFactory() {} };} extern "C" TENSORRTAPI void* createNvOnnxParserPluginFactory_INTERNAL(void* logger, int version); namespace nvonnxparser { #ifdef SWIG inline IPluginFactory* createPluginFactory(nvinfer1::ILogger* logger) { return static_cast<IPluginFactory*>( createNvOnnxParserPluginFactory_INTERNAL(logger, NV_ONNX_PARSER_VERSION)); } #endif // SWIG namespace { inline IPluginFactory* createPluginFactory(nvinfer1::ILogger& logger) { return static_cast<IPluginFactory*>( createNvOnnxParserPluginFactory_INTERNAL(&logger, NV_ONNX_PARSER_VERSION)); } } }
总的来说就是定义createPluginFactory的方法,调用了外部函数createNvOnnxParserPluginFactory_INTERNAL().
(这里还没看,具体哪里用到了这个头文件)
这是用于Nvidia TensorRT推理引擎的开放式神经网络交换(ONNX)解析器的配置管理器的API文档。
它提供有关各个功能,类和方法的信息。 使用左侧的索引来浏览文档。
有关使用ONNX Parser和TensorRT的更高级别信息和一般建议,请参阅随附的用户指南和示例。
class IOnnxConfig { protected: virtual ~IOnnxConfig() {} public: typedef int Verbosity; virtual void setModelDtype(const nvinfer1::DataType) = 0; virtual nvinfer1::DataType getModelDtype() const = 0; virtual const char* getModelFileName() const = 0; virtual void setModelFileName(const char* onnxFilename) = 0; virtual Verbosity getVerbosityLevel() const = 0; virtual void addVerbosity() = 0; //!< Increase verbosity Level. virtual void reduceVerbosity() = 0; //!< Decrease verbosity Level. virtual void setVerbosityLevel(Verbosity) = 0; //!< Set to specific verbosity Level. virtual const char* getTextFileName() const = 0; virtual void setTextFileName(const char* textFileName) = 0; virtual const char* getFullTextFileName() const = 0; virtual void setFullTextFileName(const char* fullTextFileName) = 0; virtual bool getPrintLayerInfo() const = 0; virtual void setPrintLayerInfo(bool) = 0; virtual void destroy() = 0; };
这个类主要描述了一些和日志还有name相关的config,这里不做赘述,头文件的注释写得很清楚。
TENSORRTAPI IOnnxConfig* createONNXConfig();
同样构建这个类的函数,也是闭源的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。