TensorRT Developer Guide

TensorRT Developer Guide

Overview

NVIDIA TensorRT™是一个C ++库,可以帮助NVIDIA图形处理器(GPU)进行高性能推理。
TensorRT通过合并张量和图层,转换权重,选择高效的中间数据格式,并根据图层参数和
测量的性能从大型内核目录中进行选择,从而对网络进行定义并对其进行优化。
TensorRT包含导入方法,可帮助您为TensorRT表达训练有素的深度学习模型以优化和运行。 它是一种优化工具,可以应用图形优化和图层融合,并利用各种高度优化的内核集合找到该模
型的最快实现,以及可用于在推理上下文中执行此网络的运行时方法。

install

官方安装流程

c++简易安装

1,首先从官网 下载TensorRT安装文件

image

2, 解压缩文件

$ tar -xzvf TensorRT-4.0.0.3.Ubuntu-16.04.4.x86_64-gnu.cuda-9.0.cudnn7.0.tar.gz

3, 添加环境变量

$ vim ~/.bashrc

$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/TensorRT-4.0.0.3/lib

$ source ~/.bashrc

Working With TensorRT Using The C++ API

Instantiating TensorRT Objects in C++

首先,您都必须实现一个日志记录接口,TensorRT通过该接口打印错误,警告和信息性消息。
日志记录接口可用于创建多个运行时和构建器实例,但是日志记录接口是一个单例(整个应用程序
中只有一个类实例且这个实例所占资源在整个应用程序中是共享的),所以你必须为每个对象使用
同一个日志记录实例。

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;

Creating A Network Definition In C++

使用TensorRT进行inference的第一步是从您的模型创建TensorRT网络。实现此目的的最简单方法是使用
TensorRT解析器库导入模型,该解析器库支持以下格式的序列化模型:

sampleMNIST(BVLC和NVCaffe)

sampleOnnxMNIST 1.0和1.1,以及

sampleUffMNIST(用于TensorFlow)

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

在任何一种情况下,您都明确需要告诉TensorRT需要哪些tensors作为inference的输出。未标记为输出的tensors被认为是可被优化的瞬态值。输出tensors的数量没有限制,但是,将tensors标记为输出可能会禁止对tensors进行一些优化。在推理时,您将为引擎提供一个指向输入和输出缓冲区的指针数组。

现在我们只讨论如何基于一个caffe模型,导出网络定义。

  1. Create the TensorRT builder and network.
IBuilder* builder = createInferBuilder(gLogger);
nvinfer1::INetworkDefinition* network = builder->createNetwork();
  1. Parse caffe model to populate network, then set the outputs
std::vector<std::string> outputs{"prob"};
ICaffeParser* parser = createCaffeParser();
const IBlobNameToTensor* blobNameToTensor = parser->parse(deployFile,
                                                          modelFile,
                                                          *network,
                                                          DataType::kFLOAT);
 for (auto& s : outputs)
        network->markOutput(*blobNameToTensor->find(s.c_str()));

    builder->setMaxBatchSize(maxBatchSize);
    builder->setMaxWorkspaceSize(1 << 20);
  1. Build engine
ICudaEngine* engine = builder->buildCudaEngine(*network);
  1. Serialize engine
IHostMemory *serializedModel = engine->serialize();
// store model to disk
// <…>
serializedModel->destroy();

Performing Inference In C++

  1. Deserialize engine we serialized earlier
IRuntime* runtime = createInferRuntime(gLogger);

//get model from disk or hostMemory
ICudaEngine* engine = runtime->deserializeCudaEngine(trtModelStream->data(), trtModelStream->size(), nullptr);
  
IExecutionContext* context = engine->createExecutionContext();
  1. Use the input and output blob names to get the corresponding input and output index
int inputIndex = engine.getBindingIndex(INPUT_BLOB_NAME);
int outputIndex = engine.getBindingIndex(OUTPUT_BLOB_NAME);
  1. allocate GPU buffers
Dims3 inputDims = static_cast<Dims3&&>(engine->getBindingDimensions(inputIndex));
outputDims = static_cast<Dims3&&>(engine->getBindingDimensions(outputIndex));

size_t inputSize = batchSize * inputDims.d[0] * inputDims.d[1] * inputDims.d[2] * sizeof(float);
size_t outputSize = batchSize * outputDims.d[0] * outputDims.d[1] * outputDims.d[2] * sizeof(float);
void* buffers[2];

cudaMalloc(&buffers[inputIndex], inputSize);
cudaMalloc(&buffers[outputIndex], outputSize)

//copy dato to gpu
cudaMemcpy(buffers[inputIndex], input, batchSize * INPUT_H * INPUT_W * sizeof(float));
  1. do interence and get output
 context->execute(batchSize, buffers);
 cudaMemcpy(output.data(), buffers[outputIndex], output_size_, cudaMemcpyDeviceToHost);

请阅读官方demo/sampleMNIST,demo路径为TensorRT-4.0.1.6/samples/sampleMNIST

Working With Mixed Precision

混合精度是在计算方法中组合使用不同的数值精度。 TensorRT可以存储权重和激活,并以32位浮点,16位浮点或量化的8位整数执行层。

使用低于FP32的精度可减少内存使用,允许部署更大的网络。 数据传输花费的时间更少,计算性能也会提高,尤其是在Tensor Core支持该精度的GPU上。

默认情况下,TensorRT使用FP32推理,但它也支持FP16和INT8。 在运行FP16推理时,它会自动将FP32权重转换为FP16权重。
注意:指定网络的精度定义应用程序的最低可接受精度。 如果对于某些特定的内核参数集更快,或者如果不存在低精度内核,则可以选择更高精度的内核。

bool useFp16 = builder->platformHasFastFp16();

DataType modelDataType = useFp16 ? DataType::kHALF : DataType::kFLOAT; // create a 16-bit model if it's natively supported
const IBlobNameToTensor *blobNameToTensor =
        parser->parse(locateFile(deployFile).c_str(),               // caffe deploy file
                                 locateFile(modelFile).c_str(),     // caffe model file
                                 *network,                          // network definition that the parser will populate
                                 modelDataType);

 // set up the network for paired-fp16 format if available
if(useFp16)
    builder->setFp16Mode(true);

customer layer

These are the operations that are supported in a Caffe framework:

Convolution

Pooling

InnerProduct

SoftMax

ReLU, TanH, and Sigmoid

LRN

Power

ElementWise

Concatenation

Deconvolution

BatchNormalization

Scale

Crop

Reduction

Reshape

Permute

Dropout

可能存在支持的层不满足模型的特定需求。 在这种情况下,用户可以通过使用C++ API实现自定义层来扩展TensorRT功能。 自定义层(通常称为插件)由应用程序实现和实例化,它们必须跨越TensorRT引擎的生命周期。

要在C++中添加自定义图层,请实现IPluginExt类。 对于基于Caffe的网络,如果使用TensorRT Caffe Parser,您还将实现nvcaffeparser1 :: IPluginFactoryExt和nvinfer1 :: IPluginFactory类。
具体流程请参考demo/samplePlugin ,路径为/TensorRT-4.0.1.6/samples/samplePlugin

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容