\u200E
一行命令启动,十分钟内完成部署,Paddle Serving开放模型即服务功能
发布日期:2020-04-15T09:05:05.000+0000 浏览量:11819次

古人云:行百里者半九十。相信在深度学习领域中,不少做算法的小伙伴都会对这句话产生共鸣。辛辛苦苦搭建好网络,望眼欲穿得训练调试好模型,等到最后要部署,面对纷繁复杂的实际部署环境时,才发现原来终极大魔王在这里!

当然这个魔王不会喊打喊杀,但他会给你出难题,情景可能是这样的:
在此紧要关头,是否有什么捷径帮助小伙伴顺利通关呢?这个真的可以有,那就是国内最早开源开放、功能完备的开源深度学习平台飞桨所提供的 Paddle Serving 功能。
 
Paddle Serving 是飞桨的服务化部署框架,长期目标就是为人工智能落地的最后一公里提供越来越专业、可靠、易用的服务。随着飞桨开源框架推出最新的 1.7 版本,Paddle Serving 的最新版本也闪亮登场。有了它,和魔王的对话情景就要变一变啦!
 
Paddle Serving 真的那么好吗?当然!Paddle Serving 秉承模型即服务(Model As A Service,MAAS)的理念,全面打通并自动化飞桨训练框架与 Paddle Serving 的衔接流程,让用户在使用飞桨成功完成模型训练的那一刻,收获的不再只是模型,而是同时拥有了该模型的推理服务,使用户能够在几分钟内将模型转化为一个可以在服务器端部署的远程服务。总的来说,Paddle Serving 具有如下四大特点:
  • 简单易用:为了让使用飞桨的用户能够以极低的成本部署模型,Paddle Serving 设计了一套与飞桨开源框架无缝打通的预测部署 API。对于不需要较为复杂的数据预处理过程的普通模型来说,每一位模型算法工程师仅使用一行命令就可以轻松部署自己的模型服务。
  • 工业可用:为了达到工业级深度学习模型在线部署的要求,Paddle Serving 提供很多大规模场景需要的部署功能:
    • 分布式稀疏参数索引功能。
    • 高并发底层通信能力。
    • 模型管理、在线 A/B 流量测试、模型热加载。
  • 功能扩展:当前 Paddle Serving 支持 C++、Python、Golang 的客户端,未来也会面向不同类型的客户新增多种语言的客户端。在 Paddle Serving 的框架设计方面,尽管当前版本以支持飞桨模型的部署为核心功能,但是用户也可以很容易嵌入其它的机器学习库部署在线预测服务。
  • 高性能引擎支持:飞桨的 Paddle Inference 原生推理库作为当前 Paddle Serving 唯一支持的后端推理引擎,具备诸多高性能的特性,例如内存/显存复用、算子自动融合、TensorRT 子图以及 Paddle Lite 子图自动调用等功能。Paddle Serving 从客户端请求到服务端计算的整体流程如图 1 所示,整个底层通信都采用了高并发、低延时的 Baidu-RPC 服务,支撑深度学习模型在线部署的整个流程,使其性能进一步提高。
图 1 Paddle Serving 工作流程示意图
千言万语不如一个行动,具体 Paddle Serving 有哪些闪亮操作,咱们且往下看!

模型即服务:

一行命令启动推理服务

所谓模型即服务,是指成功训练出来的模型即可直接被用来部署上线一个推理业务。在这方面飞桨提供了专门的 API 接口用于将训练成功的模型保存成指定的格式,然后无需编写其他代码,直接使用 Paddle Serving 功能中的一条命令即可将这个模型部署到服务器上,形成线上推理业务。具体如何操作,请看下面的示例。
本例将使用房价预测模型来演示操作方法,下载及解压方式如下所示,下载解压后模型及相关配置文件保存在「uci_housing」文件夹中。
 
wget --no-check-certificate https://paddle-serving.bj.bcebos.com/uci_housing.tar.gz
tar -xzf uci_housing.tar.gz
作为服务端计算机环境中需要提前安装有 Paddle Serving 功能的 paddle_serving_server 模块,如果没有安装,则可以根据硬件环境使用选择其中一行命令安装。
pip install paddle_serving_server  //在CPU环境上安装paddle_serving_server
pip install paddle_serving_server_gpu   //在GPU环境上安装paddle_serving_server
下面见证奇迹的时候到了!请看一键启动模型推理服务:
 
python -m paddle_serving_server.serve --model uci_housing_model/ --thread 10 --port 9292 --name uci
其中各个参数的含义如下:
  • model:Server 端配置与模型文件所在目录。
  • thread:Server 端线程数。
  • port:Server 端预测服务端口号。
  • name:HTTP 预测服务的的名称,如果不指定 name,则会启动 RPC 预测服务。
当返回如下信息时则表示服务端启动成功。
* Running on http://0.0.0.0:9292/ (Press CTRL+C to quit)
线上推理服务部署成功后,本例中的 url 格式为「http://127.0.0.1:9292/uci/prediction」。需要使用推理服务的用户可以通过 HTTP 协议将输入数据以如下报文的格式发送给服务端。服务端在计算出结果后,会将推理出的价格返回给用户。
curl -H "Content-Type:application/json" -X POST -d '{"x": [0.0137, -0.1136, 0.2553, -0.0692, 0.0582, -0.0727, -0.1583, -0.0584, 0.6283, 0.4919, 0.1856, 0.0795, -0.0332], "fetch":["price"]}' http://127.0.0.1:9292/uci/prediction
模型的保存方法请参见:
https://github.com/PaddlePaddle/Serving/blob/a4d478d79e120229572bcd56a001688bd7e07b94/doc/SAVE.md
上面的操作方法适用于一些不需要较为复杂的数据预处理过程的普通模型,也就是输入数据可以直接被使用进行推理计算的模型。那么对于一些需要预处理的模型,Paddle Serving 有应对之法么?其实很简单。
一般咱们自己搞不定的事情会怎么处理呢?找朋友帮忙呗,一个好汉三个帮嘛!我们可以为服务端再配个朋友——客户端。让客户端将输入数据预处理为服务端可以读取的形式。
可能有人会问:「多了一个客户端,那操作会不会变得复杂呢?」严格的说,只是多了几个步骤,相信 10 分钟还是可以搞定的!下面我们就以 Bert As Service 业务为例,看看如何在十分钟之内将它部署上线!

十分钟构建 Bert As Service

Bert As Service 是 Github 社区比较火爆的代码库,其目标是给定输入一个句子,推理服务可以将句子表示成一个语义向量返回给客户端。Bert 模型是目前 NLP 领域比较热门的模型,在多种公开的 NLP 任务上都取得了很好的效果。如果使用 Bert 模型计算出的语义向量作为其他 NLP 模型的输入,这将对提升模型的表现有很大的帮助。所以可以想象如果你成功部署一台可以对外提供 Bert As Service 服务的服务器,那么你一定会很快成为社区中最靓的仔!。
为了实现这个目标,你仅需要四个步骤就可以使用 Paddle Serving 花十分钟部署上线一个这样的服务。
01
保存可服务模型
Paddle Serving 支持基于飞桨训练的各种模型,并通过指定模型的输入和输出变量来保存可服务模型。为了便于演示,我们从飞桨的预训练模型应用工具 PaddleHub 中加载一个已经训练好的 Bert 中文模型「bert_chinese_L-12_H-768_A-12」,并利用如下代码将该模型及相关配置文件保存为可以用于部署服务的格式。其中服务端和客户端的配置分别放在「bert_seq20_model」和「bert_seq20_client」文件夹中。
import paddlehub as hub
model_name = "bert_chinese_L-12_H-768_A-12"
#获取模型文件
module = hub.Module(model_name)
#获取模型的输入输出信息以及program
inputs, outputs, program = module.context(
    trainable=True, max_seq_len=20)
#将输入输出的名称与模型中的输入输出变量一一映射
feed_keys = ["input_ids""position_ids""segment_ids",
             "input_mask", ]
fetch_keys = ["pooled_output""sequence_output"]
feed_dict = dict(zip(feed_keys, [inputs[x] for x in feed_keys]))
fetch_dict = dict(zip(fetch_keys, [outputs[x] for x in fetch_keys]))
#保存serving需要的模型与配置文件,参数1是server端模型与配置文件保存的目录,参数2是client端配置文件保存的目录,参数3是输入dict,参数4是输出dict,参数5是模型的program
import paddle_serving_client.io as serving_io
serving_io.save_model("bert_seq20_model""bert_seq20_client",
                      feed_dict, fetch_dict, program)
02
启动服务端
在服务端的计算机上使用如下命令启动服务,其中 gpu_ids 表示 GPU 索引号。
python -m paddle_serving_server_gpu.serve --model bert_seq20_model --thread 10 --port 9292 --gpu_ids 0
当返回如下信息时则表示服务端启动成功。
Server[baidu::paddle_serving::predictor::general_model:: GeneralModelServiceImpl] is serving on port=9292.
03
配置客户端数据预处理逻辑
Paddle Serving 拥有针对多个经典数据集的数据预处理模块,对于本示例的中文 Bert 语义表示的计算,我们采用 paddle_serving_app 下的 ChineseBertReader 类对数据作预处理操作,这样开发者可以很容易获得一个原始中文句子所对应的语义向量,用于作为推理服务模型的输入。安装 paddle_serving_app 的方法如下所示。
pip install paddle_serving_app
04
配置客户端访问服务器获取推理结果
import os
import sys
from paddle_serving_client import Client
from paddle_serving_app import ChineseBertReader
#定义数据预处理reader
reader = ChineseBertReader()
#指定要获取的预测结果
fetch = ["pooled_output"]
#指定server端地址
endpoint_list = ["127.0.0.1:9292"]
#定义client类
client = Client()
#加载client配置文件
client.load_client_config("bert_seq20_client/serving_client_conf.prototxt")
#连接server端
client.connect(endpoint_list)
#从标准输入读取数据,发送给server端,并打印结果
for line in sys.stdin:
    feed_dict = reader.process(line)
    result = client.predict(feed=feed_dict, fetch=fetch)
    print(result)
将需要推理中文句子制作成 txt 文件,例如 data.txt。然后运行脚本访问服务器,即可获取推理结果。
cat data.txt | python bert_client.py
Bert As Service 示例相关的脚本请参见:
https://github.com/PaddlePaddle/Serving/tree/develop/python/examples/bert

部署后吞吐性能大幅领先

功能怎么样,数据说了算!吞吐性能是对相同线上服务部署质量的重要评价指标。在 4 块 NVIDIA Tesla V100 上对基于 Paddle Serving 部署的 Bert As Service 进行性能测试,并与基于业界同类最优产品实现的 Bert As Service 做比对。在采用了相同的 batch size 和并发数的条件下,其比对数据结果如图 2 所示,使用 Paddle Serving 部署的服务的吞吐性能大幅领先,batch size 为 128 的请况下,吞吐率超出 58.3%!
 
图 2 Paddle Serving 性能压力测试吞吐量示意图
此外,如下表所示,飞桨的工程师们还提供了多个其它任务领域的模型推理服务示例以及性能分析的工具。欢迎各位小伙伴根据自己的需求下载使用。

性能可视化工具 Timeline

Paddle Serving 支持性能可视化工具 Timeline,该工具可以查看客户端启动后各个进程的各阶段 timeline。以 Bert As Service 服务为例,Timeline 可视化后的结果如图 3 所示,其中 bert_pre 代表客户端的数据预处理阶段,client_infer 代表客户端完成预测请求的发送和接收结果的阶段,每个进程的第二行展示的是服务端各个算子的 timeline。
通过 Timeline 用户可以很容易发现预估服务在各个环节的耗时,有的放矢的优化预估流程。针对 Bert 这样的热门模型,在接下来的版本中,Paddle Serving 还会在 paddle_serving_app 中持续开放新的高性能预处理 reader 接口。
 
图 3 Timeline 性能可视化工具界面效果图
Timeline 的使用方法请参见:
https://github.com/PaddlePaddle/Serving/tree/develop/python/examples/util

写在最后

Paddle Serving 是面向社区用户的核心诉求进行打造,在易用性方面相比此前的版本有了大幅度提升,用户甚至不需要掌握多深厚的飞桨相关知识即可使用 Paddle Serving 部署模型推理服务,极大的提升了部署效率。Paddle Serving 会在接下来的版本中继续降低用户的使用门槛,提供更多语言类型的客户端,以及 Kubernetes 部署的相关组件,开放更多能够开箱即用的模型,敬请关注!
如果您加入官方 QQ 群,您将遇上大批志同道合的深度学习同学。官方 QQ 群:703252161
如果您想详细了解更多飞桨的相关内容,请参阅以下文档。
  • 飞桨 Paddle Serving 项目地址:
    https://github.com/PaddlePaddle/Serving/tree/v0.2.0
  • 飞桨开源框架项目地址:
    GitHub: https://github.com/PaddlePaddle/Paddle
    Gitee: https://gitee.com/paddlepaddle/Paddle