serving.md 13.1 KB
Newer Older
littletomatodonkey's avatar
littletomatodonkey 已提交
1
# Linux GPU/CPU 服务化部署功能开发文档
littletomatodonkey's avatar
littletomatodonkey 已提交
2
- [1 简介](#1---)
D
dyning 已提交
3
- [2 服务化部署开发](#2---)
littletomatodonkey's avatar
littletomatodonkey 已提交
4
  * [2.1 准备测试数据和部署环境](#21---)
D
dyning 已提交
5 6
  * [2.2 准备服务化部署模型](#22---)
  * [2.3 复制部署样例程序](#23---)
littletomatodonkey's avatar
littletomatodonkey 已提交
7 8 9 10 11
  * [2.4 初始化部署引擎](#24---)
  * [2.5 开发数据预处理程序](#25---)
  * [2.6 开发预测结果后处理程序](#26---)
  * [2.7 启动模型预测服务](#27---)
  * [2.8 开发客户端访问服务的程序](#28---)
D
dyning 已提交
12
  * [2.9 验证服务化部署功能的正确性](#29---)
littletomatodonkey's avatar
littletomatodonkey 已提交
13 14 15
- [3 FAQ](#3---)

<a name="1---"></a>
littletomatodonkey's avatar
littletomatodonkey 已提交
16

littletomatodonkey's avatar
littletomatodonkey 已提交
17
## 1 简介
littletomatodonkey's avatar
littletomatodonkey 已提交
18

littletomatodonkey's avatar
littletomatodonkey 已提交
19 20 21 22
Paddle Serving依托深度学习框架PaddlePaddle旨在帮助深度学习开发者和企业提供高性能、灵活易用的工业级在线推理服务。Paddle Serving支持RESTful、gRPC、bRPC等多种协议,提供多种异构硬件和多种操作系统环境下推理解决方案,和多种经典预训练模型示例。

本文档主要介绍飞桨模型在 Linux GPU/CPU 下服务化部署能力的开发。主要包含三个步骤:

littletomatodonkey's avatar
littletomatodonkey 已提交
23
(1)参考 [《Linux GPU/CPU 基础训练推理开发文档》](../train_infer_python/README.md) 完成模型的训练和基于Paddle Inference的模型推理开发。
littletomatodonkey's avatar
littletomatodonkey 已提交
24

littletomatodonkey's avatar
littletomatodonkey 已提交
25
(2)在Paddle Inference的模型推理基础上,完成服务化部署能力的开发(**本文档**)。
littletomatodonkey's avatar
littletomatodonkey 已提交
26

littletomatodonkey's avatar
littletomatodonkey 已提交
27
(3)参考[《Linux GPU/CPU 基础训练推理测试开发文档》](./test_serving.md),完成TIPC 服务化部署测试开发。
littletomatodonkey's avatar
littletomatodonkey 已提交
28 29

<a name="2---"></a>
littletomatodonkey's avatar
littletomatodonkey 已提交
30

littletomatodonkey's avatar
littletomatodonkey 已提交
31 32 33 34
## 2 服务化部署能力开发

一个模型的服务化部署开发流程如下图所示,一般包含9个步骤。

littletomatodonkey's avatar
littletomatodonkey 已提交
35
![pipline](./images/serving_deploy_pipeline.jpg)
littletomatodonkey's avatar
littletomatodonkey 已提交
36 37 38 39 40 41 42 43 44 45

其中核验点如图黄色区域所示,具体如下:
- 第7步:启动模型预测服务
- 第9步:验证服务化部署能力的正确性

<a name="21---"></a>
### 2.1 准备测试数据和部署环境

【基本流程】

D
dyning 已提交
46
**(1)准备测试数据:** 从验证集或者测试集中抽出至少一张图像,用于后续推理过程验证。
littletomatodonkey's avatar
littletomatodonkey 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

**(2)准备部署环境**

首先准备docker环境,AIStudio环境已经安装了合适的docker。如果是非AIStudio环境,请[参考文档](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.3/doc/doc_ch/environment.md#2)中的 "1.3.2 Docker环境配置" 安装docker环境。

然后安装Paddle Serving三个安装包,paddle-serving-server,paddle-serving-client 和 paddle-serving-app。

```
wget https://paddle-serving.bj.bcebos.com/test-dev/whl/paddle_serving_server_gpu-0.7.0.post102-py3-none-any.whl
pip3 install paddle_serving_server_gpu-0.7.0.post102-py3-none-any.whl

wget https://paddle-serving.bj.bcebos.com/test-dev/whl/paddle_serving_client-0.7.0-cp37-none-any.whl
pip3 install paddle_serving_client-0.7.0-cp37-none-any.whl

wget https://paddle-serving.bj.bcebos.com/test-dev/whl/paddle_serving_app-0.7.0-py3-none-any.whl
pip3 install paddle_serving_app-0.7.0-py3-none-any.whl
```

D
dyning 已提交
65
Paddle Serving Server更多不同运行环境的whl包下载地址,请参考:[下载页面](https://github.com/PaddlePaddle/Serving/blob/v0.7.0/doc/Latest_Packages_CN.md)
littletomatodonkey's avatar
littletomatodonkey 已提交
66 67

<a name="22---"></a>
D
dyning 已提交
68
### 2.2 准备服务化部署模型
littletomatodonkey's avatar
littletomatodonkey 已提交
69 70 71

【基本流程】

littletomatodonkey's avatar
littletomatodonkey 已提交
72
为了便于模型服务化部署,需要将jit.save保存的静态图模型(具体参考[《Linux GPU/CPU 基础训练推理开发文档》](../train_infer_python/README.md) 使用paddle_serving_client.convert按如下命令转换为服务化部署模型:
littletomatodonkey's avatar
littletomatodonkey 已提交
73 74 75 76 77 78 79 80

```
python3 -m paddle_serving_client.convert --dirname {静态图模型路径} --model_filename {模型结构文件} --params_filename {模型参数文件} --serving_server {转换后的服务器端模型和配置文件存储路径} --serving_client {转换后的客户端模型和配置文件存储路径}
```
上面命令中 "转换后的服务器端模型和配置文件" 将用于后续服务化部署。

【实战】

littletomatodonkey's avatar
littletomatodonkey 已提交
81
针对AlexNet网络,将静态图模型([下载地址](https://paddle-model-ecology.bj.bcebos.com/model/alexnet_reprod/alexnet_infer.tar) )转换为服务化部署模型的示例命令如下,转换完后在本地生成serving_server和serving_client两个文件夹。本教程后续主要使用serving_server文件夹中的模型。
littletomatodonkey's avatar
littletomatodonkey 已提交
82 83

```python
littletomatodonkey's avatar
littletomatodonkey 已提交
84 85 86 87 88 89
python3 -m paddle_serving_client.convert \
    --dirname ./alexnet_infer/ \
    --model_filename inference.pdmodel \
    --params_filename inference.pdiparams \
    --serving_server serving_server \
    --serving_client serving_client
littletomatodonkey's avatar
littletomatodonkey 已提交
90 91 92
```

<a name="23---"></a>
littletomatodonkey's avatar
littletomatodonkey 已提交
93

D
dyning 已提交
94
### 2.3 复制部署样例程序
littletomatodonkey's avatar
littletomatodonkey 已提交
95

littletomatodonkey's avatar
littletomatodonkey 已提交
96
**【基本流程】**
littletomatodonkey's avatar
littletomatodonkey 已提交
97

littletomatodonkey's avatar
littletomatodonkey 已提交
98 99
服务化部署的样例程序的目录地址为:"template/code/"

D
dyning 已提交
100
该目录下面包含3个文件,具体如下:
littletomatodonkey's avatar
littletomatodonkey 已提交
101

D
dyning 已提交
102
- web_service.py:用于开发服务端模型预测相关程序。由于使用多卡或者多机部署预测服务,设计高效的服务调度策略比较复杂,Paddle Serving将网络预测进行了封装,在这个程序里面开发者只需要关心部署服务引擎的初始化,模型预测的前处理和后处理开发,不用关心模型预测调度问题。
littletomatodonkey's avatar
littletomatodonkey 已提交
103 104 105

- config.yml:服务端模型预测相关配置文件,里面有各参数的详细说明。开发者只需要关注如下配置:http_port(服务的http端口),model_config(服务化部署模型的路径),device_type(计算硬件类型),devices(计算硬件ID)。

D
dyning 已提交
106
- pipeline_http_client.py:用于客户端访问服务的程序,开发者需要设置url(服务地址)、logid(日志ID)和测试图像。
littletomatodonkey's avatar
littletomatodonkey 已提交
107

littletomatodonkey's avatar
littletomatodonkey 已提交
108
**【实战】**
littletomatodonkey's avatar
littletomatodonkey 已提交
109

littletomatodonkey's avatar
littletomatodonkey 已提交
110
如果服务化部署AlexNet网络,需要拷贝上述三个文件到运行目录,建议在`$repo_name/deploy/serving`目录下。
littletomatodonkey's avatar
littletomatodonkey 已提交
111 112 113 114

<a name="24---"></a>
### 2.4 初始化部署引擎

littletomatodonkey's avatar
littletomatodonkey 已提交
115
**【基本流程】**
littletomatodonkey's avatar
littletomatodonkey 已提交
116

D
dyning 已提交
117
针对模型名称,修改web_service.py中类TIPCExampleService、TIPCExampleOp的名称,以及这些类初始化中任务名称name,同时通过uci_service.prepare_pipeline_config设置配置参数。
littletomatodonkey's avatar
littletomatodonkey 已提交
118

D
dyning 已提交
119
同时修改服务配置文件中的配置:OP名称,http_port(服务的http端口),model_config(服务化部署模型的路径),device_type(计算硬件类型),devices(计算硬件ID)
littletomatodonkey's avatar
littletomatodonkey 已提交
120

littletomatodonkey's avatar
littletomatodonkey 已提交
121
**【实战】**
littletomatodonkey's avatar
littletomatodonkey 已提交
122

D
dyning 已提交
123
针对AlexNet网络,(1)修改web_service.py文件后的代码如下:
littletomatodonkey's avatar
littletomatodonkey 已提交
124 125

```
D
dyning 已提交
126 127
from paddle_serving_server.web_service import WebService, Op

littletomatodonkey's avatar
littletomatodonkey 已提交
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
class AlexNetOp(Op):
    def init_op(self):
        pass

    def preprocess(self, input_dicts, data_id, log_id):
        pass

    def postprocess(self, input_dicts, fetch_dict, data_id, log_id):
        pass


class AlexNetService(WebService):
    def get_pipeline_response(self, read_op):
        alexnet_op = AlexNetOp(name="alexnet", input_ops=[read_op])
        return alexnet_op

uci_service = AlexNetService(name="alexnet")
D
dyning 已提交
145
uci_service.prepare_pipeline_config("config.yml")
littletomatodonkey's avatar
littletomatodonkey 已提交
146 147 148
uci_service.run_service()
```

D
dyning 已提交
149 150 151 152 153 154
(2)修改服务配置文件config.yml。
- http_port:使用默认的端口号18080
- OP名称:第14行更新为alexnet
- model_config:与2.2转换后服务化部署模型文件夹路径一致,这里使用默认配置 "./serving_server"
- device_type:使用默认配置1,基于GPU预测
- devices:使用默认配置"0",0号卡预测
littletomatodonkey's avatar
littletomatodonkey 已提交
155 156

<a name="25---"></a>
littletomatodonkey's avatar
littletomatodonkey 已提交
157

littletomatodonkey's avatar
littletomatodonkey 已提交
158 159
### 2.5 开发数据预处理程序

littletomatodonkey's avatar
littletomatodonkey 已提交
160
**【基本流程】**
littletomatodonkey's avatar
littletomatodonkey 已提交
161

D
dyning 已提交
162
web_service.py文件中的TIPCExampleOp类的preprocess函数用于开发数据预处理程序,包含输入、处理流程和输出三部分。
littletomatodonkey's avatar
littletomatodonkey 已提交
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

**(1)输入:** 一般开发者使用时,只需要关心input_dicts和log_id两个输入参数。这两个参数与客户端访问服务程序tipc_pipeline_http_client.py中的请求参数相对应,即:
```
    data = {"key": ["image"], "value": [image], "logid":logid}
```
其中key和value的数据类型都是列表,并且一一对应。input_dicts是一个字典,它的key和value和data中的key和value是一致的。log_id和data中的logid一致。

**(2)处理流程:** 数据预处理流程和基于Paddle Inference的模型预处理流程相同。

**(3)输出:** 需要返回四个参数,一般开发者使用时只关心第一个返回值,网络输入字典,其余返回值使用默认的即可。

```
{"input": input_imgs}, False, None, ""
```
上述网络输入字典的key可以通过服务化模型配置文件serving_server/serving_server_conf.prototxt中的feed_var字典的name字段获取。

littletomatodonkey's avatar
littletomatodonkey 已提交
179
**【实战】**
littletomatodonkey's avatar
littletomatodonkey 已提交
180

D
dyning 已提交
181
针对AlexNet网络的数据预处理开发,需要将[Paddle Inference中的preprocess_ops.py, 待补充文件路径] 复制到Paddle Serving的目录下,修改alex_web_service.py文件中代码如下:
littletomatodonkey's avatar
littletomatodonkey 已提交
182 183 184 185

添加头文件:

```py
D
dyning 已提交
186 187
import numpy as np
import sys
littletomatodonkey's avatar
littletomatodonkey 已提交
188 189 190
import base64
from PIL import Image
import io
D
dyning 已提交
191
from preprocess_ops import ResizeImage, CenterCropImage, NormalizeImage, ToCHW, Compose
littletomatodonkey's avatar
littletomatodonkey 已提交
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
```
修改AlexNetOp中的init_op和preprocess函数相关代码:

```py
class AlexNetOp(Op):
    def init_op(self):
        self.eval_transforms = Compose([
            ResizeImage(256), CenterCropImage(224),
            NormalizeImage(), ToCHW()])

    def preprocess(self, input_dicts, data_id, log_id):
        (_, input_dict), = input_dicts.items()
        batch_size = len(input_dict.keys())
        imgs = []
        for key in input_dict.keys():
            data = base64.b64decode(input_dict[key].encode('utf8'))
            byte_stream = io.BytesIO(data)
            img = Image.open(byte_stream)
            img = img.convert("RGB")
            img = self.eval_transforms(img)
            imgs.append(img[np.newaxis, :].copy())
        input_imgs = np.concatenate(imgs, axis=0)
        return {"input": input_imgs}, False, None, ""
```

<a name="26---"></a>
### 2.6 开发预测结果后处理程序

【基本流程】

D
dyning 已提交
222
web_service.py文件中的TIPCExampleOp类的 postprocess 函数用于开发预测结果后处理程序,包含输入、处理流程和输出三部分。
littletomatodonkey's avatar
littletomatodonkey 已提交
223 224 225 226 227 228 229 230 231 232 233 234 235

**(1)输入:** 包含四个参数,其中参数input_dicts、log_id和数据预处理函数preprocess中一样,data_id可忽略,fetch_dict 是网络预测输出字典,其中输出的key可以通过服务化模型配置文件serving_server/serving_server_conf.prototxt中的fetch_var字典的name字段获取。

**(2)处理流程:** 数据预处理流程和基于Paddle Inference的预测结果后处理一致。

**(3)输出:** 需要返回三个参数,一般开发者使用时只关心第一个返回值,预测结果字典,其余返回值使用默认的即可。

```
result, None, ""
```

【实战】

D
dyning 已提交
236
针对AlexNet网络的预测结果后处理开发,修改web_service.py文件中AlexNetOp中的postprocess函数相关代码如下:
littletomatodonkey's avatar
littletomatodonkey 已提交
237

littletomatodonkey's avatar
littletomatodonkey 已提交
238
```py
littletomatodonkey's avatar
littletomatodonkey 已提交
239
    def postprocess(self, input_dicts, fetch_dict, data_id, log_id):
littletomatodonkey's avatar
littletomatodonkey 已提交
240 241
        # 取输出结果
        score_list = list(fetch_dict.values())[0]
littletomatodonkey's avatar
littletomatodonkey 已提交
242 243 244 245 246 247 248 249 250 251 252 253 254
        result = {"class_id": [], "prob": []}
        for score in score_list:
            score = score.flatten()
            class_id = score.argmax()
            prob = score[class_id]
            result["class_id"].append(class_id)
            result["prob"].append(prob)
        result["class_id"] = str(result["class_id"])
        result["prob"] = str(result["prob"])
        return result, None, ""
```

<a name="27---"></a>
littletomatodonkey's avatar
littletomatodonkey 已提交
255

littletomatodonkey's avatar
littletomatodonkey 已提交
256 257
### 2.7 启动模型预测服务

littletomatodonkey's avatar
littletomatodonkey 已提交
258
**【基本流程】**
littletomatodonkey's avatar
littletomatodonkey 已提交
259 260 261 262

当完成服务化部署引擎初始化、数据预处理和预测结果后处理开发,则可以按如下命令启动模型预测服务:

```bash
D
dyning 已提交
263
python3 web_service.py &
littletomatodonkey's avatar
littletomatodonkey 已提交
264 265
```

littletomatodonkey's avatar
littletomatodonkey 已提交
266
**【实战】**
littletomatodonkey's avatar
littletomatodonkey 已提交
267

D
dyning 已提交
268
针对AlexNet网络, 启动成功的界面如下:
littletomatodonkey's avatar
littletomatodonkey 已提交
269

littletomatodonkey's avatar
littletomatodonkey 已提交
270
![](./images/serving_startup_visualization.jpg)
littletomatodonkey's avatar
littletomatodonkey 已提交
271 272

<a name="28---"></a>
littletomatodonkey's avatar
littletomatodonkey 已提交
273

littletomatodonkey's avatar
littletomatodonkey 已提交
274 275
### 2.8 开发客户端访问服务的程序

littletomatodonkey's avatar
littletomatodonkey 已提交
276
**【基本流程】**
littletomatodonkey's avatar
littletomatodonkey 已提交
277

D
dyning 已提交
278
当成功启动了模型预测服务,可以修改pipeline_http_client.py程序,访问该服务。主要设置url(服务地址)、logid(日志ID)和测试图像。其中服务地址的url的样式为 "http://127.0.0.1:18080/tipc_example/prediction" ,url的设置需要将url中的tipc_example更新为TIPCExampleService类初始化的name。
littletomatodonkey's avatar
littletomatodonkey 已提交
279

littletomatodonkey's avatar
littletomatodonkey 已提交
280
**【实战】**
littletomatodonkey's avatar
littletomatodonkey 已提交
281

D
dyning 已提交
282 283 284 285 286 287 288
针对AlexNet网络, 修改pipeline_http_client.py程序中的url(服务地址)、logid(日志ID)和测试图像地址,其中url改为:

```
url = "http://127.0.0.1:18080/alexnet/prediction"
```

客户端访问服务的命令如下:
littletomatodonkey's avatar
littletomatodonkey 已提交
289 290

```
D
dyning 已提交
291
python3 pipeline_http_client.py
littletomatodonkey's avatar
littletomatodonkey 已提交
292 293 294 295
```

访问成功的界面如下:

littletomatodonkey's avatar
littletomatodonkey 已提交
296
![](./images/serving_client_results.jpg)
littletomatodonkey's avatar
littletomatodonkey 已提交
297 298 299 300 301 302 303 304 305 306

【注意事项】
如果访问不成功,可能设置了代理影响的,可以用下面命令取消代理设置。

```
unset http_proxy
unset https_proxy
```

<a name="29---"></a>
littletomatodonkey's avatar
littletomatodonkey 已提交
307
### 2.9 验证服务化部署功能的正确性
littletomatodonkey's avatar
littletomatodonkey 已提交
308

littletomatodonkey's avatar
littletomatodonkey 已提交
309 310 311 312 313 314 315 316 317 318 319 320 321 322
**【基本流程】**

* 对于相同图像,分别使用Inference推理以及Serving部署,获取预测结果,比较二者结果。

**【实战】**

AlexNet中,模型推理的命令可以参考:[AlexNet 模型推理](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/README.md#512-%E6%A8%A1%E5%9E%8B%E6%8E%A8%E7%90%86)

模型部署的命令说明可以参考:[AlexNet模型部署](https://github.com/littletomatodonkey/AlexNet-Prod/blob/tipc/pipeline/Step5/AlexNet_paddle/deploy/serving/README.md#24-%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%AE%BF%E9%97%AE%E6%9C%8D%E5%8A%A1)

**【核验】**

* 二者预测结果完全相同
* 文档中给出基于相同图像的预测命令说明以及结果显示
littletomatodonkey's avatar
littletomatodonkey 已提交
323 324 325

<a name="3---"></a>
## 3 FAQ