目录

1.简介

1.1与模型直接推理的比较

1.2流程图

1.3高性能

1.4多功能集成

2.预测部署示例--python

2.1模型获取

2.1.1paddlepaddle框架

 2.1.2Tensorflow、Pytorch、Caffe

2.2paddle-inference的使用

2.3完整可运行代码


1.简介

Paddle Inference 是飞桨的原生推理库, 作用于服务器端和云端,提供高性能的推理能力。

由于能力直接基于飞桨的训练算子,因此Paddle Inference 可以通用支持飞桨训练出的所有模型。

Paddle Inference 功能特性丰富,性能优异,针对不同平台不同的应用场景进行了深度的适配优化,做到高吞吐、低时延,保证了飞桨模型在服务器端即训即用,快速部署

1.1与模型直接推理的比较

训练好的模型直接转为eval评估模式也可以进行推理,那么为什么还要使用inference库呢。

相比于模型的推理模式,inference可使用MKLDNN、CUDNN、TensorRT进行预测加速,同时支持用 X2Paddle 工具从第三方框架(TensorFlow、Pytorh 、 Caffe 等)产出的模型,可联动PaddleSlim,支持加载量化、裁剪和蒸馏后的模型部署

eval模式的模型适用于训练好的模型直接进行预测,paddle inference适用于对推理性能、通用性有要求的用户,针对不同平台不同的应用场景进行了深度的适配优化,保证模型在服务器端即训即用,快速部署。

1.2流程图

1.3高性能

  • 内存/显存复用提升服务吞吐量

    • 在推理初始化阶段,对模型中的OP输出Tensor 进行依赖分析,将两两互不依赖的Tensor在内存/显存空间上进行复用,进而增大计算并行量,提升服务吞吐量。
  • 细粒度OP横向纵向融合减少计算量

    • 在推理初始化阶段,按照已有的融合模式将模型中的多个OP融合成一个OP,减少了模型的计算量的同时,也减少了 Kernel Launch的次数,从而能提升推理性能。目前Paddle Inference支持的融合模式多达几十个。
  • 内置高性能的CPU/GPU Kernel 

    • 内置同Intel、Nvidia共同打造的高性能kernel,保证了模型推理高性能的执行。

1.4多功能集成

  • 集成TensorRT加快GPU推理速度

    • Paddle Inference采用子图的形式集成TensorRT,针对GPU推理场景,TensorRT可对一些子图进行优化,包括OP的横向和纵向融合,过滤冗余的OP,并为OP自动选择最优的kernel,加快推理速度。
  • 集成oneDNN CPU推理加速引擎

    • 一行代码开始oneDNN加速,快捷高效。
  • 支持PaddleSlim量化压缩模型的部署

    • PaddleSlim是飞桨深度学习模型压缩工具,Paddle Inference可联动PaddleSlim,支持加载量化、裁剪和蒸馏后的模型并部署,由此减小模型存储空间、减少计算占用内存、加快模型推理速度。其中在模型量化方面,Paddle Inference在X86 CPU上做了深度优化,常见分类模型的单线程性能可提升近3倍,ERNIE模型的单线程性能可提升2.68倍。
  • 支持X2Paddle转换得到的模型

    • 除支持飞桨训练的模型外,也支持用 X2Paddle 工具从第三方框架(比如 TensorFlow、Pytorch 或者 Caffe 等)产出的模型。

2.预测部署示例--python

2.1模型获取

2.1.1paddlepaddle框架

paddlepaddle既支持动态图也支持静态图的开发,训练好的动态图模型可通过两部保存为静态图,静态图用于推理部署性能更优。

第一步:加载模型和参数,使用paddle.load()

model_state_dict = paddle.load('lenet.pdparams')
opt_state_dict = paddle.load('lenet.pdopt')
model.set_state_dict(model_state_dict)
optim.set_state_dict(opt_state_dict)

第二步:转为静态图后保存,调用paddle.jit.to_static转换paddle.jit.save保存

net = to_static(model, input_spec=[InputSpec(shape=[None, 1, 28, 28], name='x')])
paddle.jit.save(net, 'inference_model/lenet')

 2.1.2Tensorflow、Pytorch、Caffe

用 X2Paddle 工具从第三方框架(TensorFlow、Pytorh 、 Caffe 等)产出的模型转为paddlepaddle inference支持的模型。

2.2paddle-inference的使用

简单使用的几个步骤:

加载预测模型并进行预测配置

        首先,我们加载预测模型,并配置预测时的一些选项,根据配置创建预测引擎:

config = Config("inference_model/lenet/lenet.pdmodel", "inference_model/lenet/lenet.pdiparams") # 通过模型和参数文件路径加载
config.disable_gpu() # 使用cpu预测
predictor = create_predictor(config) # 根据预测配置创建预测引擎predictor

设置输入

        我们先通过获取输入Tensor的名称,再根据名称获取到输入Tensor的句柄。

# 获取输入变量名称
input_names = predictor.get_input_names()
input_handle = predictor.get_input_handle(input_names[0])

        下面我们准备输入数据,并将其拷贝至待预测的设备上。这里我们使用了随机数据,在实际使用中可以将其换为需要预测的真实图片。 

### 设置输入
fake_input = np.random.randn(1, 1, 28, 28).astype("float32")
input_handle.reshape([1, 1, 28, 28])
input_handle.copy_from_cpu(fake_input)

运行预测 

predictor.run()

获取输出

# 获取输出变量名称
output_names = predictor.get_output_names()
output_handle = predictor.get_output_handle(output_names[0])
output_data = output_handle.copy_to_cpu()

2.3完整可运行代码

准备模型:ResNet50,可从下面的链接下载,该模型是paddle静态图模型,可直接使用

wget https://paddle-inference-dist.bj.bcebos.com/Paddle-Inference-Demo/resnet50.tgz
tar zxf resnet50.tgz

# 获得模型目录即文件如下
resnet50/
├── inference.pdmodel
├── inference.pdiparams.info
└── inference.pdiparams

将以下代码保存为 python_demo.py 文件:

可以看到,这就是上述inference使用方式介绍的代码加上argparse解析库封装后得到的程序

import argparse
import numpy as np

# 引用 paddle inference 预测库
import paddle.inference as paddle_infer

def main():
    args = parse_args()

    # 创建 config
    config = paddle_infer.Config(args.model_file, args.params_file)

    # 根据 config 创建 predictor
    predictor = paddle_infer.create_predictor(config)

    # 获取输入的名称
    input_names = predictor.get_input_names()
    input_handle = predictor.get_input_handle(input_names[0])

    # 设置输入
    fake_input = np.random.randn(args.batch_size, 3, 318, 318).astype("float32")
    input_handle.reshape([args.batch_size, 3, 318, 318])
    input_handle.copy_from_cpu(fake_input)

    # 运行predictor
    predictor.run()

    # 获取输出
    output_names = predictor.get_output_names()
    output_handle = predictor.get_output_handle(output_names[0])
    output_data = output_handle.copy_to_cpu() # numpy.ndarray类型
    print("Output data size is {}".format(output_data.size))
    print("Output data shape is {}".format(output_data.shape))

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--model_file", type=str, help="model filename")
    parser.add_argument("--params_file", type=str, help="parameter filename")
    parser.add_argument("--batch_size", type=int, default=1, help="batch size")
    return parser.parse_args()

if __name__ == "__main__":
    main()

 执行程序:

# 参数输入为本章节第2步中下载的 ResNet50 模型
python python_demo.py --model_file ./resnet50/inference.pdmodel --params_file ./resnet50/inference.pdiparams --batch_size 2

结果

 

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐