基于TensorRT的神经网络推理与加速

一. 引言

NVIDIA TensorRT是一种高性能神经网络推理(Inference)引擎,用于在生产环境中部署深度学习应用程序,应用于图像分类、分割和目标检测等,可提供最大的推理吞吐量和效率。TensorRT是第一款可编程推理加速器,能加速现有和未来的网络架构。TensorRT包含一个为优化生产环境中部署的深度学习模型而创建的库,可获取经过训练的神经网络(通常使用32位或16位数据),并针对降低精度的INT8运算来优化这些网络。借助CUDA的可编程性,TensorRT可以大幅度加速,服务提供商能够以经济实惠的成本部署这些计算密集型人工智能工作负载。TensorRT包含一个为优化生产环境中部署的深度学习模型而创建的库,可获取经过训练的神经网络(通常使用32位或16位数据),并针对降低精度的INT8运算来优化这些网络。借助CUDA的可编程性,TensorRT将能够加速助推深度 神经网络日益多样化、复杂的增长趋势。通过TensorRT的大幅度加速,服务提供商能够以经济实惠的成本部署这些计算密集型人工智能工作负载。已有来自各行各业的公司开始采用NVIDIA推理平台,借助此从数据中获得全新洞察,并为企业和消费者部署智能服务。

TensorRT由英伟达(NVIDIA)发布,目前包括TensorRT1、TensorRT 2、TensorRT 3,是深度学习软件包,支持FP16特性。TensorRT支持使用Caffe的模型。TensorRT相对简单易用,在深度学习算法推理阶段能将GPU的计算能力更大程度释放出来。 TensorRT在不断的改进过程中,在保证软件精度的同时,不断提高速度。TensorRT针对运行时性能自动优化训练过的神经网络。 TensorRT是一个C++库。

使用TensorRT包含两个阶段:构建(build)和部署(deployment)。在构建阶段,TensorRT对网络配置进行优化,并生成一个优化了的plan用于计算深度神经网络的前向传播。这个plan是一个优化了的目标代码,可以序列化存储在内存或磁盘上。 部署阶段通常采用长时间运行的服务或用户应用程序的形式,该服务或用户应用程序接受批量输入数据,通过对输入数据执行plan来执行推理,并返回批量输出数据。使用TensorRT,你无需在部署硬件上安装并运行深度学习框架。 TensorRT构建阶段:TensorRT运行时需要三个文件来部署一个分类神经网络:一个网络体系结构文件(deploy.prototxt),已训练的权值(net.caffemodel)和一个标签文件为每个输出类提供一个名称。另外,你必须定义batch size和输出层。 TensorRT对神经网络图(neural network graph)进行了几个重要的转换和优化:消除未使用的输出的层以避免不必要的计算;在可能的情况下,convolution、bias和ReLU层被融合以形成单个层,包括垂直层融合和水平层融合。 在TensorRT解析器读入已训练的网络和配置文件后,TensorRT在构建阶段对API用户透明地执行其转换。 在构建阶段,TensorRT优化网络,在部署阶段,TensorRT以最小化延迟和最大化吞吐量运行优化了的网络。 TensorRT 2.1关键特性:(1)、支持自定义层;(2)、INT8支持以用于性能改进;(3)、提供递归神经网络(LSTM(Long Short-Term Memory)、GRU(Gated Recurrent Unit))实现;(4)、”original” RNN层实现。 2017年9月,NVIDIA发布了神经网络推理加速器TensorRT3,TensorRT 3是一款针对人工智能应用生产部署的高性能优化编译器和运行时引擎,用于在生产环境中部署深度学习程序。它能够快速优化、验证并部署经过训练的神经网络, 从而在超大型数据中心、嵌入式GPU或车用GPU平台上开展推理工作。它能够确保高度精确的INT8和FP16网络执行。 TensorRT 3能支持Caffe2、Mxnet、Pytorch、TensorFlow等所有的深度学习框架,将TensorRT 3和NVIDIA的GPU结合起来,能在所有的框架中进行超快速和高效的推理传输,支持图像和语言识别、自然语言处理、可视化搜索和个性化推荐等AI服务。 借助该推理引擎可以大幅提升云端及包括机器人、无人驾驶汽车在内的终端设备的推理性能,并有效降低成本。使用TensorRT,你无需在部署硬件上安装并运行深度学习框架。TensorRT可以从多种框架(包括Caffe2、MXNet 和 PyTorch)中导入 开放神经网络交换 (ONNX) 格式的模型。

对于计算量庞大的CNN,效率一直是大家所关注的,接触过深度网络压缩的同学应该知道网络压缩最关键的两个思路,剪枝和量化。TensorRT可以将FP32位权值数据优化为 FP16 或者 INT8,而推理精度不发生明显的降低。同时可以合并卷积操作,将不同的层进行合并(包括水平与垂直),可以将对结果无影响的部分进行删除达到压缩的效果。

       关于TensorRT总结为以下几点:

1. TensorRT是NVIDIA开发的深度学习推理工具,只支持推理,不支持训练;

   目前TensorRT已经支持Caffe、Caffe2、TensorFlow、MxNet、Pytorch等主流深度学习库;

2. TensorRT底层针对NVIDIA显卡做了多方面的优化,不仅仅是量化,可以和 CUDA CODEC SDK 结合使用,

    也就是另一个开发包DeepStream;

3. TensorRT独立于深度学习框架,通过解析框架文件来实现,不需要额外安装DL库;

可从  https://developer.nvidia.com/nvidia-tensorrt-download 下载。可以参考官方TensorRT的介绍,更权威一些:https://developer.nvidia.com/tensorrt

二. 使用方式

      TensorRT只能用来做Inference(推理),不能用来进行train。 TensorRT基本处理过程:(1)、caffe model转化GIE的model,或者从磁盘或者网络加载GIE可用的model;(2)、运行GIE引擎(数据提前copy到GPU中);(3)、提取结果。 转化GIE model两种方式:(1)、caffeToGIEModel;(2)、参考sampleMNIST API自己构建GIE model.

用深度神经网络解决监督机器学习问题包含两个步骤:第一步是使用GPU对海量标签数据进行深度神经网络训练,训练时需要迭代的通过网络进行前向传播和反向传播。最终会生成训练好的model文件。第二步是推理(Inference)即使用训练好的模型对新 数据做出预测,仅需通过网络进行前向传播。TensorRT是一款高性能的推理引擎,旨在为常见的深度学习应用如图像分类、分割、目标检测等提供最大的推理吞吐量和效率。针对运行时性能,TensorRT会优化已训练的神经网络。

下面以Caffe为例介绍TensorRT的使用:

1. caffeToGIEModel - 将 caffe model 转换到 TensorRT 格式

 // 1.创建builder
IBuilder* builder = createInferBuilder(gLogger);
 
// 2.解析caffe模型,保存到 Network
INetworkDefinition* network = builder->createNetwork();
ICaffeParser* parser = createCaffeParser();
const IBlobNameToTensor* blobNameToTensor = parser->parse(locateFile(deployFile,                 directories).c_str(), locateFile(modelFile, directories).c_str(),*network, DataType::kFLOAT);
 
// 3.指定输出Tensor
for (auto& s : outputs)
    network->markOutput(*blobNameToTensor->find(s.c_str()));
 
// 4.构建engine
builder->setMaxBatchSize(maxBatchSize);
builder->setMaxWorkspaceSize(1 << 20);
 
ICudaEngine* engine = builder->buildCudaEngine(*network);
assert(engine);
 
// 5.销毁parser
network->destroy();
parser->destroy();
 
// 6.将engine序列化到GIE,退出
gieModelStream = engine->serialize();
engine->destroy();
builder->destroy();

2. 执行过程 main

// 1.从caffe模型创建GIE模型,序列化到流
IHostMemory *gieModelStream{nullptr};
caffeToGIEModel("mnist.prototxt", "mnist.caffemodel", std::vector < std::string > { OUTPUT_BLOB_NAME }, 1, gieModelStream);
 
// x.数据获取(略)
// x.解析mean文件(略)
 
// 2.反序列化,得到Runtime engine 
IRuntime* runtime = createInferRuntime(gLogger);
ICudaEngine* engine = runtime->deserializeCudaEngine(gieModelStream->data(), gieModelStream->size(), nullptr);
if (gieModelStream) gieModelStream->destroy();
 
// 3.创建上下文
IExecutionContext *context = engine->createExecutionContext();
 
// 4.运行inference
float prob[OUTPUT_SIZE];
doInference(*context, data, prob, 1);
 
// 5.销毁engine
context->destroy();
engine->destroy();
runtime->destroy();
 

3. 推理过程 doInference
const ICudaEngine& engine = context.getEngine();
// 传递给引擎的输入输出buffer指针- 需要精确的 IEngine::getNbBindings(),这里1个输入+1个输出
assert(engine.getNbBindings() == 2);
void* buffers[2];
 
// 1.为了绑定buffer,需要知道输入和输出tensor的names
int inputIndex = engine.getBindingIndex(INPUT_BLOB_NAME), 
outputIndex = engine.getBindingIndex(OUTPUT_BLOB_NAME);
 
// 2.创建 GPU buffer 和 stream
CHECK(cuda

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值