使用c++ API处理TensorRT

  • 2 replies
  • 428 views
*

sisiy

  • *****
  • 174
    • 查看个人资料
使用c++ API处理TensorRT
« 于: 七月 23, 2019, 05:19:18 pm »
使用TensorRT执行推理的第一步是从模型创建一个TensorRT网络。最简单的方法是使用TensorRT解析器库导入模型,该库支持以下示例中的序列化模型:

"Hello World" For TensorRT (both BVLC and NVCaffe)https://docs.nvidia.com/deeplearning/sdk/tensorrt-sample-support-guide/index.html#mnist_sample

"Hello World" For TensorRT From ONNX https://docs.nvidia.com/deeplearning/sdk/tensorrt-sample-support-guide/index.html#onnx_mnist_sample

Import The TensorFlow Model And Run Inference (used for TensorFlow) https://docs.nvidia.com/deeplearning/sdk/tensorrt-sample-support-guide/index.html#mnist_uff_sample

另一种方法是直接使用TensorRT API定义模型。这需要您进行少量API调用来定义网络图中的每一层,并为模型的训练参数实现您自己的导入机制。

在这两种情况下,都需要显式地告诉TensorRT哪些张量是推理输出所必需的。没有标记为输出的张量被认为是可以被构造器优化掉的瞬态值。输出张量的数量没有限制,但是,将张量标记为输出可能会禁止对该张量进行一些优化。输入和输出张量也必须指定名称(使用ITensor::setName())。在推理时,您将为引擎提供指向输入和输出缓冲区的指针数组。为了确定引擎期望这些指针的顺序,可以使用张量名称进行查询。

TensorRT网络定义的一个重要方面是,它包含指向模型权重的指针,构建器将这些指针复制到优化的引擎中。如果通过解析器创建网络,解析器将拥有权重所占用的内存,因此在构建器运行之前不应该删除解析器对象。

« 最后编辑时间: 七月 23, 2019, 05:23:08 pm 作者 sisiy »

*

sisiy

  • *****
  • 174
    • 查看个人资料
Re: 使用c++ API处理TensorRT
« 回复 #1 于: 七月 24, 2019, 01:33:43 pm »
 以下部分突出显示了可以使用c++ API执行的TensorRT用户目标和任务。进一步的详细信息在<示例支持指南>(https://docs.nvidia.com/deeplearning/sdk/tensorrt-sample-support-guide/index.html )中提供。

假设您从一个经过训练的模型开始。本章将介绍使用TensorRT的以下必要步骤:
在你的模型中创建TensorRT网络定义
在网络中调用TensorRT构建器创建一个优化的运行时引擎
通过序列化和反序列化,从而能让引擎在下次运行的时候,能快速的重新创建。
为引擎提供数据以执行推理

C++ API vs Python API
在本质上,c++ API和Python API在支持您的需求方面应该非常接近。c++ API应该用于任何性能关键场景,以及安全性非常重要的情况,例如在汽车中。

Python API的主要好处是数据预处理和后处理很容易使用,因为您可以使用各种库,比如NumPy和SciPy。


*

sisiy

  • *****
  • 174
    • 查看个人资料
Re: 使用c++ API处理TensorRT
« 回复 #2 于: 七月 24, 2019, 02:10:28 pm »
2.1。用c++实例化TensorRT对象

为了运行推理,您需要使用IExecutionContext对象。为了创建IExecutionContext类型的对象,首先需要创建ICudaEngine(引擎)类型的对象。

引擎可以通过以下两种方式创建:
引擎可以通过两种方式创建: 第一种是通过用户模型中(包含)的网络定义。在这种情况下,引擎还能可选的被串行化保存下来,用于以后的使用。
第二种则是通过读取存盘后的串行化的引擎数据.。在这种情况下,性能更好,因为解析模型和创建中间对象的步骤被省略了。

需要全局创建ILogger类型的对象。它被用作TensorRT API的各种方法的参数。下面是一个演示如何创建日志程序的简单示例:
程序代码: [选择]
class Logger : public ILogger           
 {
     void log(Severity severity, const char* msg) override
     {
         // suppress info-level messages
         if (severity != Severity::kINFO)
             std::cout << msg << std::endl;
     }
 } gLogger;
 

使用全局TensorRT API方法createInferBuilder(gLogger)创建IBuilder类型的对象,如图5所示。


图5。使用iLogger作为输入参数创建IBuilder

为iBuilder定义的createNetwork方法用于创建iNetworkDefinition类型的对象,如图6所示。

图6。createNetwork()用于创建网络

使用INetwork定义作为输入创建一个可用的解析器(Caffe、ONNX或UFF):
ONNX: auto parser = nvonnxparser::createParser(*network, gLogger);
Caffe: auto parser = nvcaffeparser1::createCaffeParser();
UFF: auto parser = nvuffparser::createUffParser();

从类型为iParser的对象中调用一个名为parse()的方法来读取模型文件并填充图7中的TensorRT网络。

图7。解析模型文件解析模型文件
调用IBuilder的buildCudaEngine()方法创建ICudaEngine类型的对象,如图8所示:

图8。创建TensorRT引擎
可以选择序列化引擎并将其转储到文件中。

图9。创建TensorRT引擎——序列化TensorRT引擎
执行上下文用于执行推理。

图10。创建执行上下文
如果将序列化引擎保存并保存到文件中,则可以跳过上面描述的大部分步骤。
而IRuntime类型的对象,则是通过全局TensorRT API函数调用createInferRuntime(gLogger),来建立的,如图11所示:

图11。创建TensorRT运行时
有关TensorRT运行时的更多信息,请参见IRuntime类引用。
通过runtime函数deserializeCudaEngine()来建立引擎...
创建Builder和Runtime对象的时候,将使用当前(creating)线程中所关联的GPU上的CUDA Context。如果当前线程没有建立过CUDA Contet,则会默认自动创建一个。但推荐在创建runtime或者builder对象前,手工建立和配置好CUDA Context,(而不是依赖于自动创建的)。

« 最后编辑时间: 七月 24, 2019, 02:58:36 pm 作者 sisiy »