算法部署知识点:TensorRT、Tensorflow、Flask、Docker、TFLite

算法部署知识点:TensorRT、Tensorflow、Flask、Docker、TFLite

前言

TensorRT

TensorRT定义

TensorRT是由Nvidia推出的一个高性能的深度学习推理(Inference)优化器和运行时引擎,它可以用于在生产环境中部署深度学习模型,实现高性能的推理任务。TensorRT支持多种深度学习框架,如TensorFlow、Caffe、PyTorch、MXNet等,并可以直接载入这些框架的已训练模型文件,也可以通过编程自行构建模型。

TensorRT的核心功能包括深度学习推理优化器和运行时引擎。推理优化器可以对输入的深度学习模型进行图层优化、张量融合、精度校准等操作,以生成最优化的推理引擎。而运行时引擎则负责在Nvidia的GPU或DLA上执行推理任务,以实现高性能的推理。

此外,TensorRT还支持多种神经网络层的定义,并提供了API接口,允许开发者自行实现特殊层的操作。这使得TensorRT可以更加灵活地应对各种深度学习模型。

总的来说,TensorRT是一个针对深度学习推理任务的高性能优化库,它可以帮助开发者在生产环境中更加高效地部署和运行深度学习模型。

TensorFlow: pb,ckpt

pytorch: pt,pth

keras: h5

显卡型号: tesla T4 | tesla V100

训练:V100、P40

推理:T4、P4

  • T4
    整数运算能力(INT8): 130 TOPS
    GPU 显存: 16GB
    显存带宽: 320GB/秒
    定义:推理加速(基于CUDA和cudnn的进行高性能推理加速引擎);用于从ONNX或tensorflow导入现有模型解析器,是对训练好的模型进行优化。
    当网络训练完后,可以将tf训练模型文件直接丢进tensorRT中,而不再需要依赖深度学习框架(Caffe,TensorFlow等)。
    tensorRT通过 组合层 和优化内核选择来优化网络,从而改善延迟、吞吐量(样本量/秒)、功效和内存消耗。
    理解:
    tensorRT可以将TensorFlow/pytorch的网络模型解析,然后与其中对应的层进行一一映射,把其他框架的模型统一全部 转换到tensorRT中,然后在tensorRT中可以针对NVIDIA自家GPU实施优化策略,并进行部署加速。

TensorRT对于网络结构进行了重构和优化,主要体现在:

  1. tensorRT通过解析网络模型将网络中无用的输出层消除以减小计算。
  2. 对于网络结构的垂直整合,即将目前主流神经网络的conv、BN、Relu三个层融合为了一个层。
  3. 对于网络的水平组合,水平组合是指将输入为相同张量和执行相同操作的层融合一起。
  4. 对于concat层,将contact层的输入直接送入下面的操作中,不用单独进行concat后在输入计算,相当于减少了一次传输吞吐。

TensorRT原理

低精度推理

TensorRT支持FP16和INT8的计算,在训练的时候一般是使用32位或者16位数据,它在推理时可以降低模型参数的位宽来进行低精度推理,通过在减少计算量和保持精度之间达到一个理想的权衡,以达到加速推断的目的。模型在推理计算时,是调用GPU的CUDA核进行计算的。

P16主要是P100和V100这两张卡支持;INT8主要针对的是 P4和P40这两张卡,P4是专门针对线上做推断的小卡。

int8量化算法

目标:将fp32的CNN转换为int8而不会造成明显的精度损失;

原因:int8方法具有更高的吞吐量和更低的内存需求;

为什么要量化而不使用int8直接训练?

模型训练是需要反向传播和梯度下降的,训练时的超参一般都是浮点型,如学习率等,int8类型无法进行训练。

samples文件夹下有一个命令行包装工具,叫trtexec,用来评测我们的网络模型,它有以下两个功能:

  1. 在指定的网络模型中,对随机输入数据进行基准测试。eg:可利用trtexc工具来测试 UFF/ONNX net-model 在推理时的表现。
  2. 对指定网络模型产生序列化引擎:使用完全流水线异步方式从多个线程运行具有多个执行上下文的引擎,以测试并行推理性能。
bash 复制代码
trtexec --deploy=/path/to/mnist.prototxt --model=/path/to/mnist.caffemodel --output=prob --batch=16 --saveEngine=mnist16.trt

定义: FP16(Full Precise Float 16): (比FP32)更省内存空间,更节约推理时间。

了解: Tesla系列工作站端显卡:p4, p6, p40, p100 --- 支持Pascal架构

do_Inference原理

host device的方式转化将数据传输到GPU,然后异步执行做推断,推断的结果从GPU拿到Host(即设备到主机),接着将流进行同步。多个input,output结点用do_inference_2方法。

执行: convert-to-uff ./models/lenet5.pb --> 可生成lenet.uff文件

tensorflow: NWHC | tensorrt:NCWH (channel first)

uff-parser 解析tensorflow模型

先build_engine,trt.UffParser() /caffe/ONNXparser;

再对图像进行处理,do_inference进行异步方式推断

测试: python3 sample.py -d /home/featurize/work/TensorRT-6.0.1.5/data (需要install pycuda)

序列化

序列化将引擎转换为一种格式,以便以后存储和使用以进行推理。要用于推理,只需反序列化引擎即可。

序列化和反序列化是可选的。由于从网络定义创建引擎可能非常耗时,因此每次应用程序重新运行时都可以通过序列化一次并在推理时对其进行反序列化来避免重建引擎。因此,在构建引擎之后,用户通常希望将其序列化以供以后使用。

可以序列化引擎,也可以直接使用引擎进行推理。在将模型用于推理之前,序列化和反序列化是一个可选步骤-如果需要,可以直接使用引擎对象进行推理。

序列化引擎不能跨平台或TensorRT版本移植。

序列化引擎步骤

将序列化引擎保存到文件中,并从文件中读回:

  1. 序列化引擎并写入文件:
python 复制代码
with open("sample.engine", "wb") as f:
	f.write(engine.serialize))
  1. 从文件读取引擎并反序列化:
python 复制代码
with open("sample.engine","rb") as f,trt.Runtime(TRT_LOGGER) as runtime:
	engine = runtime. deserialize_cuda_engine(f.read())

使用python接口导入tf模型

  1. 导入TensorRT :import tensorrt as trt
  2. 创建冻结的TensorFlow模型
  3. 使用UFF转换器将冻结的Tensorflow模型转换为UFF文件
    $ convert-to-uff frozen_inference_graph. pb
  4. 定义路径。更改以下路径以反映Samples中包含的模型的位置
python 复制代码
model_file = '/data/mnist/mnist.uff'

5.创建builder , network和parser:

python 复制代码
with builder= trt. Builder(TRI_LOGGER) as builder, 
              builder.create_network() as network,trt UffParser O) as parser:	
	parser.register_input("Placeholder",(1,28,28))
	parser.register_output("fc2/Relu")
	parser.parse(model_file,network)
  • builder: 搜索其CUDA内核目录以获得最快的可用实现,因此必须使用相同的CPU来构建优化引擎将运行的GPU.

  • builder具有许多属性,可以设置这些属性以控制网络应运行的精度,以及目动调整参效。

  • 两个重要的属性: 最大batch size和最大workspace size.

  • 最大batch大小: 指定tensorRT将优化的批量大小。在运行时,可以选择较小的批量大小;

Linux下安装TensorRT

下载地址: https://developer.nvidia.com/zh-cn/tensorrt
TensorRT安装链接

在home下新建文件夹,命名为tensorrt_tar,然后将下载的压缩文件拷贝进来解压

bash 复制代码
tar xzvf TensorRT-6.0.1.5.Ubuntu-16.04.4.x86_64-gnu.cuda-9.0.cudnn7.3.tar

解压得到TensorRT-6.0.1.5的文件夹,将里边的lib绝对路径添加到环境变量中

bash 复制代码
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/featurize/work/TensorRT-6.0.1.5/lib

安装TensorRT

bash 复制代码
cd TensorRT-6.0.1.5/python
pip3 install tensorrt-6.0.1.5-py2.py3-none-any.whl

安装UFF,支持tensorflow模型转化

bash 复制代码
cd TensorRT-6.0.1.5/uff
pip3 install uff-0.5.5-py2.py3-none-any.whl

安装graphsurgeon,支持自定义结构

bash 复制代码
cd TensorRT-6.0.1.5/graphsurgeon
pip install graphsurgeon-0.3.2-py2.py3-none-any.whl

libcudart.so.10.0: cannot open shared object file错误的解决方案都是查看CUDA的版本,

但是如果CUDA版本正确的时候还是报这个错误的话,可以通过输入一下指令解决。

bash 复制代码
sudo ldconfig /usr/local/cuda-10.0/lib64

Tensorflow部署

简单描述:确定好输入和输出节点,把模型导出成SavedModel格式,然后用TF-Serving启动服务,调用方发http请求或者grpc请求就可以拿到预测结果了。

  • 保存权重文件:
    1.ModelCheckPoint
    2.model.save_weights()
    keras模型转化为SavedModel:
python 复制代码
tf.saved_model.save(model,'/keras_save_graph')
  • 查看模型文件命令:
bash 复制代码
saved_model_cli show --dir ./keras_save_graph --all
  • 签名信息:
bash 复制代码
saved_model_cli show --dir ./keras_save_graph --tag-set serve --signature_def serving_default
  • 检查保存模型是否正常工作:(输入2个样本,28x28)
bash 复制代码
saved_model_cli run --dir ./keras_save_graph --tag-set serve --signature_def serving_default
                    --input_exprs 'flatten_input=np.ones((2,28,28))'  
  • 还可以用程序进行验证:
bash 复制代码
loaded_saved_model = tf.saved_model.load('./keras_save_graph')		
                       print(list(loaded_saved_model.signatures.keys())	
inference = loaded_saved_model.signatures['serving_default']	

使用SaveModel导出训练模型并添加签名

签名的好处

  1. 可以限定函数的输入类型,以防止调用函数时调错,
  2. 一个函数有了input_signature之后,在tensorflow里边才可以保存成savedmodel。在保存成savedmodel的过程中,需要使用get_concrete_function函数把一个tf.function标注的普通的python函数变成带有图定义的函数。

Flask + Docker 简易部署

  1. Saver端:模型的离线训练与导出
    使用SavedModel,将训练好的模型导出为pb文件,检查保存的模型的SignatureDef、Inputs、Outputs等信息,命令(saved_model_cli)
  2. tf.server进行模型加载与在线预测
    基于Docker的方式搭建tf-server,拉取tf/serving的镜像,新建服务实例
  3. Client端 构建请求
    Docker:容器,可以理解成一个"黑盒"。在项目变得庞大以后,往往我们会疲于管理整个项目的部署和维护。如果我们将整个项目用一个"容器"装起来,那么我们仅仅只用维护一个配置文件告诉计算机每次部署要把什么东西装进"容器",甚至借用一些工具把这个过程自动化,部署就会变得很方便。

部署环境:

Ubuntu18.04 显卡:Tesla的P40 搭建Docker

Docker 封装 Flask 应用:

  1. 创建一个 Dockerfile 文件,添加部署到服务器上的路径以及启动的
bash 复制代码
python文件名和变量名。
FROM python:3.6
WORKDIR /Project/demo
COPY requirements.txt ./
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
CMD ["gunicorn", "start:app", "-c", "./gunicorn.conf.py"]
  1. 开始构建Docker镜像,登陆远程服务器终端,把镜像 pull 下来。
bash 复制代码
sudo docker build -t 'testflask' sudo docker images
  1. 部署到服务器上
bash 复制代码
sudo apt-get install docker.io
  1. 运行docker镜像:
bash 复制代码
sudo docker run -d -p 80:80 --name test-flask-1 testflask
  1. 更新项目的时候,维护好配置文件,build一下,push 上去,在服务器 pull 下来,重新运行即可。

基于tflite的Android部署

tf.lite.TFLiteConverter.from_saved_model()(推荐):转换 SavedModel。

  1. build.gradle: 添加tf-lite-gpu
  2. model放在asset文件下,tf相关的文件放于tflite文件夹下
  3. 设置tfliteOption( nnapi、cpu、gpu ),构造函数(loadModelFile)掉用tfliteModel,初始化图像数据,分配内存;
  4. 做预测的构造函数recognizeImage,先把bitmap转化为byteBuffer;
  5. 接下来就是runInference操作(tflite.run()),得到所以的概率值。
相关推荐
进击的小头1 小时前
第7篇:基于传递函数的PI控制器设计
python·算法
TracyCoder1231 小时前
LeetCode Hot100(62/100)——62. 不同路径
算法·leetcode·职场和发展
jing-ya1 小时前
day 50 图论part2
java·算法·深度优先·图论
仰泳的熊猫2 小时前
题目2268:蓝桥杯2016年第七届真题-密码脱落
数据结构·c++·算法·蓝桥杯
我能坚持多久2 小时前
【初阶数据结构09】——对堆用法的深入刨析
数据结构·算法
kaikaile19952 小时前
基于PCNN和NSCT的图像融合MATLAB实现
开发语言·图像处理·算法·matlab
Zik----2 小时前
cs研究生面试机试题(持续更新)
算法
1231566802 小时前
PAT 1017 A除以B
c语言·数据结构·算法·pat考试
芯片-嵌入式2 小时前
具身智能(2):OpenExplorer下的模型量化
人工智能·深度学习·算法