如下内容根据我的理解整理而成,若有错误,欢迎指出,不胜感激。html
更新:看了一个NVIDIA关于TensorRT 6的分享视频,官方建议使用TensorRT的Python接口进行开发,且TensorRT提供的Parser不太好用,建议本身实现API来构建网络。git
本文首先根据TensorRT开发者指南梳理TensorRT的C++接口使用流程,而后基于TensorRT的官方例程“Hello World” For TensorRT来了解其具体使用方式。github
由上一篇Blog中的内容可知,模型从导入TensorRT到执行Inference大体通过下面三个阶段:算法
ILogger
编程
首先说明一个必须但不是很重要的类ILogger
,它用于记录一些日志信息。 在编程时,咱们须要声明一个全局的ILogger
对象gLogger,TensorRT中不少方法都须要它做为参数 (貌似须要继承ILogger
类来编写本身的Logger类)网络
IBuilder
异步
IBuilder
类应该算是最重要的一个类,在使用时,首先要使用TensorRT的全局方法createInferBuilder()
来建立一个IBuilder
类指针,而后由该指针调用IBuilder
类方法建立Network和Engine类的指针。ide
INetworkDefinition
ui
INetworkDefinition
类即为网络定义,可经过IBuilder
类方法createNetwork()
返回其指针。spa
ICudaEngine
ICudaEngine
类即为Engine,可经过IBuilder
类方法buildCudaEngine()/buildEngineWithConfig()
返回其指针。 注意,可经过导入模型生成Engine和经过反序列化来加载Engine两种Engine生成方式。
IParser
IParser
类对应着前文所述的三种不一样的解释器,可根据须要来使用。 IParser
类方法parse()
用于解析并加载模型及参数到TensorRT网络中(INetworkDefinition
类)
IExecutionContext
Engine的运行须要一个运行时环境,createExecutionContext()
方法为相应的ICudaEngine
生成一个IExecutionContext
类型的运行环境context。
一个简单的代码示例以下:
# builder IBuilder* builder = createInferBuilder(gLogger); # network INetworkDefinition* network = builder->createNetwork(); # parser -> load params to network CaffeParser* parser = createCaffeParser(); const IBlobNameToTensor* blobNameToTensor = parser->parse(args); # engine builder->setMaxBatchSize(maxBatchSize); IBuilderConfig * config = builder->createBuilderConfig(); config->setMaxWorkspaceSize(1 << 20); ICudaEngine* engine = builder->buildEngineWithConfig(*network, *config); # serialize engine if necessary IHostMemory *serializedModel = engine->serialize(); //# 若是是直接反序列化来获取engine,上述不少步骤都不须要 //IRuntime* runtime = createInferRuntime(gLogger); //ICudaEngine* engine = runtime->deserializeCudaEngine(modelData, modelSize, nullptr); # inference IExecutionContext *context = engine->createExecutionContext(); # 获取输入输出层的索引 int inputIndex = engine->getBindingIndex(INPUT_BLOB_NAME); int outputIndex = engine->getBindingIndex(OUTPUT_BLOB_NAME); # 指针指向输入输出层在GPU中的存储位置 void* buffers[2]; buffers[inputIndex] = inputbuffer; buffers[outputIndex] = outputBuffer; # 异步执行inference context->enqueue(batchSize, buffers, stream, nullptr); # clear serializedModel->destroy(); parser->destroy(); network->destroy(); config->destroy(); builder->destroy(); ...
疑问一:IBuilder配置参数 可根据须要来配置builder,其中比较重要的参数有两个:
疑问二:runtime vs context 在读开发者指南时,这两个概念有点乱,这里区分一下:
注意一:CUDA context 从开发者指南中可知,尽管可使用默认的CUDA context而不显式建立它,但官方不建议这么作,推荐在建立一个runtime或builder对象时,建立并配置本身的CUDA context。
理清上述流程后,该例子的cpp源码不难理解,具体细节这里再也不阐述。