From 883ed94e5cd2c88b63d94b95e9024cd38ce4139c Mon Sep 17 00:00:00 2001 From: TeslaZhao Date: Sat, 7 May 2022 14:01:35 +0800 Subject: [PATCH] Update doc --- doc/Offical_Docs/5-1_Save_Model_Params_CN.md | 28 ++++++++- .../6-1_Cpp_Asynchronous_Framwork_CN.md | 37 ++++++++++-- .../6-2_Cpp_Serving_Protocols_CN.md | 31 +++++++++- doc/Offical_Docs/6-5_Cpp_ABTest_CN.md | 21 ++++++- .../7-1_Python_Pipeline_Design_CN.md | 43 ++++++++++++-- .../7-2_Python_Pipeline_Senior_CN.md | 57 +++++++++++++++---- .../7-3_Python_Pipeline_Optimize_CN.md | 52 ++++++++++++++--- .../7-4_Python_Pipeline_Benchmark_CN.md | 10 +++- doc/Offical_Docs/9-0_Kubernetes_Int_CN.md | 3 +- 9 files changed, 245 insertions(+), 37 deletions(-) diff --git a/doc/Offical_Docs/5-1_Save_Model_Params_CN.md b/doc/Offical_Docs/5-1_Save_Model_Params_CN.md index 2256d891..2faaae7b 100644 --- a/doc/Offical_Docs/5-1_Save_Model_Params_CN.md +++ b/doc/Offical_Docs/5-1_Save_Model_Params_CN.md @@ -1,11 +1,26 @@ # 保存用于 Serving 部署的模型参数 +- [背景介绍](#1) +- [功能设计](#2) +- [功能使用](#3) + - [PYTHON 命令执行](#3.1) + - [代码引入执行](#3.2) +- [Serving 部署](#4) + - [服务端部署示例](#4.1) + - [客户端部署示例](#4.2) + + + +## 背景介绍 + 模型参数信息保存在模型文件中,为什么还要保存用于 Paddle Serving 部署的模型参数呢,原因有3个: 1. 服务化场景分为客户端和服务端,服务端加载模型,而在客户端没有模型信息,但需要在客户端需实现数据拼装和类型转换。 2. 模型升级过程中 `feed vars` 和 `fetch vars` 的名称变化会导致代码升级,通过增加一个 `alias_name` 字段映射名称,代码无需升级。 3. 部署 `Web` 服务,并使用 `URL` 方式访问时,请求信息中缺少类型和维度信息,在服务端推理前需要进行转换。 + + ## 功能设计 飞桨训推一体框架中,从动态图模型训练到静态图推理部署,一体化流程如下所示 @@ -65,6 +80,7 @@ feed 与 fetch 变量的类型列表如下: | complex64 | 10 | complex128 | 11 | + ## 功能使用 @@ -84,6 +100,7 @@ Paddle 推理模型有3种形式,每种形式的读模型的方式都不同, | `model_filename` | str | None | 存储需要转换的模型Inference Program结构的文件名称。如果设置为None,则使用 `__model__` 作为默认的文件名 | | `params_filename` | str | None | 存储需要转换的模型所有参数的文件名称。当且仅当所有模型参数被保>存在一个单独的二进制文件中,它才需要被指定。如果模型参数是存储在各自分离的文件中,设置它的值为None | + **一.PYTHON 命令执行** @@ -99,6 +116,7 @@ python3 -m paddle_serving_client.convert --dirname ./your_inference_model_dir python3 -m paddle_serving_client.convert --dirname . --model_filename dygraph_model.pdmodel --params_filename dygraph_model.pdiparams --serving_server serving_server --serving_client serving_client ``` + **二.代码引入执行** @@ -108,10 +126,14 @@ import paddle_serving_client.io as serving_io serving_io.inference_model_to_serving(dirname, serving_server="serving_server", serving_client="serving_client", model_filename=None, params_filename=None) ``` + + ## Serving 部署 生成完的模型可直接用于服务化推理,服务端使用和客户端使用。 -**一.服务端使用** + + +**一.服务端部署示例** 示例一:C++ Serving 启动服务 ``` @@ -140,7 +162,9 @@ op: device_type: 0 ``` -**二.客户端使用** + + +**二.客户端部署示例** 通过 `client` 对象的 `load_client_config` 接口加载模型配置信息 ``` diff --git a/doc/Offical_Docs/6-1_Cpp_Asynchronous_Framwork_CN.md b/doc/Offical_Docs/6-1_Cpp_Asynchronous_Framwork_CN.md index 9bd3cdee..ed7daf54 100644 --- a/doc/Offical_Docs/6-1_Cpp_Asynchronous_Framwork_CN.md +++ b/doc/Offical_Docs/6-1_Cpp_Asynchronous_Framwork_CN.md @@ -1,7 +1,22 @@ # C++ Serving 异步模式 +- [设计方案](#1) + - [网络同步线程](#1.1) + - [异步调度线程](#1.2) + - [动态批量](#1.3) +- [使用案例](#2) + - [开启同步模式](#2.1) + - [开启异步模式](#2.2) +- [性能测试](#3) + - [测试数据](#3.1) + - [测试结论](#3.2) + + + ## 设计方案 + + **一.同步网络线程** Paddle Serving 的网络框架层面是同步处理模式,即 bRPC 网络处理线程从系统内核拿到完整请求数据后( epoll 模式),在同一线程内完成业务处理,C++ Serving 默认使用同步模式。同步模式比较简单直接,适用于模型预测时间短,或单个 Request 请求批量较大的情况。 @@ -12,6 +27,8 @@ Paddle Serving 的网络框架层面是同步处理模式,即 bRPC 网络处 Server 端线程数 N = 模型预测引擎数 N = 同时处理 Request 请求数 N,超发的 Request 请求需要等待当前线程处理结束后才能得到响应和处理。 + + **二.异步调度线程** 为了提高计算芯片吞吐和计算资源利用率,C++ Serving 在调度层实现异步多线程并发合并请求,实现动态批量推理。异步模型主要适用于模型支持批量,单个 Request 请求的无批量或较小,单次预测时间较长的情况。 @@ -22,6 +39,8 @@ Server 端线程数 N = 模型预测引擎数 N = 同时处理 Request 请求数 异步模式下,Server 端 N 个线程只负责接收 Request 请求,实际调用预测引擎是在异步框架的线程池中,异步框架的线程数可以由配置选项来指定。为了方便理解,我们假设每个 Request 请求批量均为1,此时异步框架会尽可能多得从请求池中取 n(n≤M)个 Request 并将其拼装为1个 Request(batch=n),调用1次预测引擎,得到1个 Response(batch = n),再将其对应拆分为 n 个 Response 作为返回结果。 + + **三.动态批量** 通常,异步框架合并多个请求的前提是所有请求的 `feed var` 的维度除 batch 维度外必须是相同的。例如,以 OCR 文字识别案例中检测模型为例,A 请求的 `x` 变量的 shape 是 [1, 3, 960, 960],B 请求的 `x` 变量的 shape 是 [2, 3, 960, 960],虽然第一个维度值不相同,但第一个维度属于 `batch` 维度,因此,请求 A 和 请求 B 可以合并。C 请求的 `x` 变量的 shape 是 [1, 3, 640, 480],由于除了 `batch` 维度外还有2个维度值不同,A 和 C 不能直接合并。 @@ -39,16 +58,21 @@ Server 端线程数 N = 模型预测引擎数 N = 同时处理 Request 请求数 场景3:`Shape-1 = [batch, 3, 320, 320], Shape-2 = [batch, 3, 960, 960]`。此时,`绝对值差 = 3*960*960 - 3*320*320 = 2457600`字节,`相对误差 = (3/3) * (320/960) * (320/960) = 0.3*0.3 = 0.09`,条件1和条件2均不满足,未触发动态 Padding。 + ## 使用案例 -**一.不开启异步模式** + + +**一.开启同步模式** 启动命令不使用 `--runtime_thread_num` 和 `--batch_infer_size` 时,属于同步处理模式,未开启异步模式。`--thread 16` 表示启动16个同步网络处理线程。 ``` python3 -m paddle_serving_server.serve --model uci_housing_model --thread 16 --port 9292 ``` + + **二.开启异步模式** 启动命令使用 `--runtime_thread_num 4` 和 `--batch_infer_size 32` 开启异步模式,Serving 框架会启动8个异步线程,单次合并最大批量为32,自动开启动态 Padding。 @@ -56,9 +80,9 @@ python3 -m paddle_serving_server.serve --model uci_housing_model --thread 16 --p python3 -m paddle_serving_server.serve --model uci_housing_model --thread 16 --port 9292 --runtime_thread_num 4 --batch_infer_size 32 --ir_optim --gpu_multi_stream --gpu_ids 0 ``` -## 测试数据 + -**一.测试环境** +## 性能测试 GPU:Tesla P4 7611 MiB Cuda:cuda11.2-cudnn8-trt8 @@ -76,7 +100,9 @@ python3 -m paddle_serving_server.serve --model resnet_v2_50_imagenet_model --por python3 -m paddle_serving_server.serve --model resnet_v2_50_imagenet_model --port 9393 --thread 64 --runtime_thread_num 8 --ir_optim --gpu_multi_stream --gpu_ids 1 --enable_prometheus --prometheus_port 19393 ``` -**二.测试数据** + + +**一.测试数据** 1. 同步模式 @@ -121,8 +147,9 @@ python3 -m paddle_serving_server.serve --model resnet_v2_50_imagenet_model --por |50 |1 |1.50 |50.60 |7578 |89.04 |121.545 |5000 |411.364 |331.118 |605.809 |874.543 |1285.650 |48.2343 |41.1369 |9350.0000 |2568777.6400 |295.8593| |70 |1 |3.80 |83.20 |7602 |89.59 |133.568 |7000 |524.073 |382.653 |799.463 |1202.179 |1576.809 |57.2885 |52.4077 |10761.0000 |3013600.9670 |315.2540| + -**三.测试结论** +**二.测试结论** 使用异步模式,并开启动态批量后,并发测试不同 shape 数据时,吞吐性能大幅提升。
diff --git a/doc/Offical_Docs/6-2_Cpp_Serving_Protocols_CN.md b/doc/Offical_Docs/6-2_Cpp_Serving_Protocols_CN.md index e37c19e5..9847e2b7 100644 --- a/doc/Offical_Docs/6-2_Cpp_Serving_Protocols_CN.md +++ b/doc/Offical_Docs/6-2_Cpp_Serving_Protocols_CN.md @@ -1,5 +1,19 @@ # C++ Serving 通讯协议 +- [网络框架](#0) +- [Tensor](#1) + - [1.1 构建 FLOAT32 Tensor](#1.1) + - [1.2 构建 STRING Tensor](#1.2) +- [Request](#2) + - [2.1 构建 Protobuf Request](#2.1) + - [2.2 构建 Json Request](#2.2) +- [Response](#3) + - [3.1 读取 Response 数据](#3.1) + + + +## 网络框架 + C++ Serving 基于 [bRPC](https://github.com/apache/incubator-brpc) 网络框架构建服务,支持 bRPC、gRPC 和 RESTful 协议请求。不限于开发语言和框架,甚至 `curl` 方式,只要按照上述协议封装数据并发送,Server 就能够接收、处理和返回结果。 对于支持的各种协议我们提供了部分的 Client SDK 示例供用户参考和使用,用户也可以根据自己的需求去开发新的 Client SDK,也欢迎用户添加其他语言/协议(例如 GRPC-Go、GRPC-C++ HTTP2-Go、HTTP2-Java 等)Client SDK 到我们的仓库供其他开发者借鉴和参考。 @@ -15,9 +29,7 @@ C++ Serving 基于 [bRPC](https://github.com/apache/incubator-brpc) 网络框架 C++ Serving 请求和应答的数据格式为 protobuf,重要的结构有以下3个: -- Tensor -- Request -- Response + ## Tensor @@ -110,6 +122,8 @@ Tensor 结构中重要成员 `elem_type`、`shape`、`lod` 和 `name/alias_name` |11|COMPLEX128 |20|STRING| + + **一.构建 FLOAT32 Tensor** 创建 Tensor 对象,通过 `mutable_float_data::Resize()` 设置 FLOAT32 类型数据长度,通过 memcpy 函数拷贝数据。 @@ -135,6 +149,8 @@ tensor->mutable_float_data()->Resize(total_number, 0); memcpy(tensor->mutable_float_data()->mutable_data(), float_datadata(), total_number * sizeof(float)); ``` + + **二.构建 STRING Tensor** 创建 Tensor 对象,通过 `set_tensor_content` 设置 string 类型数据。 @@ -154,6 +170,8 @@ tensor->set_alias_name(alias_name); tensor->set_tensor_content(string_data); ``` + + ## Request @@ -174,6 +192,8 @@ message Request { 当使用 bRPC 或 gRPC 进行请求时,使用 protobuf 或 Json 格式请求数据。 + + **一.构建 Protobuf Request** 创建 Request 对象,通过 `add_tensor` 接口来设置 Tensor。 @@ -187,6 +207,7 @@ for (auto &name : fetch_name) { Tensor *tensor = req.add_tensor(); ... ``` + **二.构建 Json Request** @@ -196,6 +217,8 @@ Tensor *tensor = req.add_tensor(); {"tensor":[{"float_data":[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],"elem_type":1,"name":"x","alias_name":"x","shape":[1,13]}],"fetch_var_names":["price"],"log_id":0} ``` + + ## Response Response 为服务端返回给客户端的结果,包含了 Tensor 数据、错误码、错误信息等。定义如下: @@ -231,6 +254,8 @@ Response 结构中核心成员: |-5002|"Paddle Serving Array Overflow Error."| |-5100|"Paddle Serving Op Inference Error."| + + **一.读取 Response 数据** 读取 Response 对象中 Tensor 数据示例如下 diff --git a/doc/Offical_Docs/6-5_Cpp_ABTest_CN.md b/doc/Offical_Docs/6-5_Cpp_ABTest_CN.md index 92881e21..e6ff4adb 100644 --- a/doc/Offical_Docs/6-5_Cpp_ABTest_CN.md +++ b/doc/Offical_Docs/6-5_Cpp_ABTest_CN.md @@ -1,9 +1,19 @@ # C++ Serving ABTest +- [功能设计](#1) +- [使用案例](#2) + - [1.1 安装 Paddle Serving Wheels](#2.1) + - [1.2 下载多个模型并保存模型参数](#2.2) + - [1.3 启动 A,B,C 3个服务](#2.3) + - [1.4 客户端注册 A,B,C 服务端地址](#2.4) + - [1.5 启动客户端并验证结果](#2.5) + ABTest 是一种功能测试方案,一般是为同一个产品目标制定多种方案,让一部分用户使用 A 方案,另一部分用户使用 B 或 C 方案,根据测试效果,如点击率、转化率等来评价方案的优劣。 模型服务化部署框架中,ABTest 属于一个重要的基础功能,为模型迭代升级提供实验环境。Paddle Serving 的 PYTHON SDK 中实现 ABTest 功能,为用户提供简单易用功能测试环境。 + + ## 功能设计 Paddle Serving 的 ABTest 功能是基于 PYTHON SDK 和 多个服务端构成。每个服务端加载不同模型,在客户端上注册多个服务端地址和访问比例,最终确定访问。 @@ -12,6 +22,7 @@ Paddle Serving 的 ABTest 功能是基于 PYTHON SDK 和 多个服务端构成
## 使用案例 @@ -20,9 +31,10 @@ Paddle Serving 的 ABTest 功能是基于 PYTHON SDK 和 多个服务端构成 1. 安装 Paddle Serving Wheels 2. 下载多个模型并保存模型参数 3. 启动 A,B,C 3个服务 -4. 客户端注册 A,B,C 服务端地址 +4. 客户端注册 A,B,C 服务端地址 5. 启动客户端并验证结果 + **一.安装 Paddle Serving Wheels** @@ -32,6 +44,8 @@ Paddle Serving 的 ABTest 功能是基于 PYTHON SDK 和 多个服务端构成 pip3 install paddle-serving-client==0.8.3 -i https://pypi.tuna.tsinghua.edu.cn/simple ``` + + **二.下载多个模型并保存模型参数** 本示例已提供了一键下载脚本 `sh get_data.sh`,下载 `bow`、`cnn`和`lstm` 3种不同方式训练的模型。 @@ -108,6 +122,8 @@ fetch_var { } ``` + + **三.启动 A,B,C 3个服务** 后台启动 `bow`、`cnn` 和 `lstm` 模型服务: @@ -123,6 +139,8 @@ python3 -m paddle_serving_server.serve --model imdb_cnn_model/ --port 9298 >/de python3 -m paddle_serving_server.serve --model imdb_lstm_model/ --port 9299 >/dev/null 2>&1 & ``` + + **四.客户端注册 A,B,C 服务端地址** 使用 `paddle_serving_client` 中 `Client::add_variant(self, tag, cluster, variant_weight)` 接口注册服务标签、服务地址和权重。框架会将所有权重求和后计算每个服务的比例。本示例中,bow 服务的权重是10,cnn 服务的权重是30, lstm的权重是60,每次请求分别请求到3个服务的比例是10%、30%和60%。 @@ -142,6 +160,7 @@ client.connect() ``` 如要在结果中打印请求到了哪个服务,在 `client.predict(feed, fetch, batch, need_variant_tag, logid)` 中设置 `need_variant_tag=True`。 + **五.启动客户端并验证结果** diff --git a/doc/Offical_Docs/7-1_Python_Pipeline_Design_CN.md b/doc/Offical_Docs/7-1_Python_Pipeline_Design_CN.md index 5ba7086f..24cbbf0d 100644 --- a/doc/Offical_Docs/7-1_Python_Pipeline_Design_CN.md +++ b/doc/Offical_Docs/7-1_Python_Pipeline_Design_CN.md @@ -1,5 +1,22 @@ # Python Pipeline 框架设计 +- [目标](#1) +- [框架设计](#2) + - [2.1 网络层设计](#2.1) + - [2.2 图执行引擎层](#2.2) + - [2.3 服务日志](#2.3) + - [2.4 错误信息](#2.4) +- [自定义信息](#3) + - [3.1 自定义 Web 服务 URL](#3.1) + - [3.2 自定义服务输入和输出结构](#3.2) + - [3.3 自定义服务并发和模型配置](#3.3) + - [3.4 自定义推理过程](#3.4) + - [3.5 自定义业务错误类型](#3.5) + + + + +## 目标 为了解决多个深度学习模型组合的复杂问题,Paddle Serving 团队设计了一个通用端到端多模型组合框架,其核心特点包括: 1. 通用性:框架既要满足通用模型的输入类型,又要满足模型组合的复杂拓扑关系。 @@ -7,6 +24,7 @@ 3. 高可用性:高可用的架构依赖每个服务的健壮性,服务状态可查询、异常可监控和管理是必备条件。 4. 易于开发与调试:使用 Python 语言开发可大幅提升研发效率,运行的错误信息准确帮助开发者快速定位问题。 + ## 框架设计 Python Pipeline 框架分为网络服务层和图执行引擎2部分,网络服务层处理多种网络协议请求和通用输入参数问题,图执行引擎层解决复杂拓扑关系。如下图所示 @@ -15,6 +33,8 @@ Python Pipeline 框架分为网络服务层和图执行引擎2部分,网络服 + + **一.网络服务层** 网络服务层包括了 gRPC-gateway 和 gRPC Server。gPRC gateway 接收 HTTP 请求,打包成 proto 格式后转发给 gRPC Server,一套处理程序可同时处理 HTTP、gRPC 2种类型请求。 @@ -69,6 +89,7 @@ rpc_port: 9988 http_port: 18089 ``` + **二.图执行引擎层** @@ -137,6 +158,7 @@ Channel的设计原则: + **三.服务日志** @@ -209,6 +231,8 @@ Pipeline 的日志模块在 `logger.py` 中定义,使用了 `logging.handlers. ``` + + **四. 错误信息** 框架提供的错误信息如下所示, 完整信息在 `error_catch.py` 中 `CustomExceptionCode` 类中定义。 @@ -246,6 +270,7 @@ class CustomExceptionCode(enum.Enum): UNKNOW = 10000 ``` + ## 自定义信息 @@ -256,8 +281,9 @@ class CustomExceptionCode(enum.Enum): - 自定义推理过程 - 自定义业务错误类型 + -1. 自定义 Web 服务 URL +**一.自定义 Web 服务 URL** 在 Web 服务中自定义服务名称是常见操作,尤其是将已有服务迁移到新框架。URL 中核心字段包括 `ip`、`port`、`name` 和 `method`,根据最新部署的环境信息设置前2个字段,重点介绍如何设置 `name` 和 `method`,框架提供默认的 `methon` 是 `prediciton`,如 `http://127.0.0.1:9999/ocr/prediction` 。 @@ -296,8 +322,9 @@ service PipelineService { } }; ``` + -2. 自定义服务输入和输出结构 +**二.自定义服务输入和输出结构** 输入和输出结构包括 proto 中 Request 和 Response 结构,以及 Op 前后处理返回。 @@ -307,10 +334,15 @@ service PipelineService { 修改后,需要[重新编译]() -3. 自定义服务并发和模型配置 + + +**三.自定义服务并发和模型配置** + 完整的配置信息可参考[配置信息]() -4. 自定义推理过程 + + +**四.自定义推理过程** 推理 Op 为开发者提供3个外部函数接口: @@ -435,8 +467,9 @@ class ResponseOp(Op): return resp ``` + -5. 自定义业务错误类型 +**五.自定义业务错误类型** 用户可根据业务场景自定义错误码,继承 ProductErrCode,在 Op 的 preprocess 或 postprocess 中返回列表中返回,下一阶段处理会根据自定义错误码跳过后置OP处理。 ```python diff --git a/doc/Offical_Docs/7-2_Python_Pipeline_Senior_CN.md b/doc/Offical_Docs/7-2_Python_Pipeline_Senior_CN.md index 06fcda1d..c372d080 100644 --- a/doc/Offical_Docs/7-2_Python_Pipeline_Senior_CN.md +++ b/doc/Offical_Docs/7-2_Python_Pipeline_Senior_CN.md @@ -2,18 +2,27 @@ 从设计上,Python Pipeline 框架实现轻量级的服务化部署,提供了丰富的核心功能,既能满足服务基本使用,又能满足特性需求。 -- 安装与环境检查 -- 服务启动与关闭 -- 本地与远程推理 -- 批量推理 -- 单机多卡推理 -- 多种计算芯片上推理 -- TensorRT 推理加速 -- MKLDNN 推理加速 -- 低精度推理 -- 复杂图结构 DAG 跳过某个 Op 运行 +- [安装与环境检查](#1) +- [服务启动与关闭](#2) +- [本地与远程推理](#3) +- [批量推理](#4) + - [4.1 客户端打包批量数据](#4.1) + - [4.2 服务端合并多个请求动态合并批量](#4.2) + - [4.3 Mini-Batch](#4.3) +- [单机多卡推理](#5) +- [多种计算芯片上推理](#6) +- [TensorRT 推理加速](#7) +- [MKLDNN 推理加速](#8) +- [低精度推理](#9) + - [9.1 CPU 低精度推理](#9.1) + - [9.2 GPU 和 TensorRT 低精度推理](#9.2) + - [9.3 性能测试](#9.3) +- [复杂图结构 DAG 跳过某个 Op 运行](#10) + + ## 安装与环境检查 + 在运行 Python Pipeline 服务前,确保当前环境下可部署且通过[安装指南](./2-0_Index_CN.md)已完成安装。其次,`v0.8.0`及以上版本提供了环境检查功能,检验环境是否安装正确。 输入以下命令,进入环境检查程序。 @@ -78,6 +87,8 @@ shutil.Error: Destination path '/home/work/Pipeline_test_cpu/PipelineServingLogs ``` + + ## 服务启动与关闭 服务启动需要三类文件,PYTHON 程序、模型文件和配置文件。以[Python Pipeline 快速部署案例](./3-2_QuickStart_Pipeline_OCR_CN.md)为例, @@ -125,6 +136,8 @@ python3 -m paddle_serving_server.serve stop # 触发 SIGINT 信号 python3 -m paddle_serving_server.serve kill # 触发 SIGKILL 信号,强制关闭 ``` + + ## 本地与远程推理 本地推理是指在服务所在机器环境下开启多进程推理,而远程推理是指本地服务请求远程 C++ Serving 推理服务。 @@ -184,6 +197,8 @@ op: fetch_list: ["prediction"] ``` + + ## 批量推理 Pipeline 支持批量推理,通过增大 batch size 可以提高 GPU 利用率。Python Pipeline 支持3种 batch 形式以及适用的场景如下: @@ -191,12 +206,15 @@ Pipeline 支持批量推理,通过增大 batch size 可以提高 GPU 利用率 - 场景2:服务端合并多个请求动态合并批量(Server auto-batching) - 场景3:拆分一个大批量的推理请求为多个小批量推理请求(Server mini-batch) + **一.客户端打包批量数据** 当输入数据是 numpy 类型,如shape 为[4, 3, 512, 512]的 numpy 数据,即4张图片,可直接作为输入数据。 当输入数据的 shape 不同时,需要按最大的shape的尺寸 Padding 对齐后发送给服务端 + + **二.服务端合并多个请求动态合并批量** 有助于提升吞吐和计算资源的利用率,当多个请求的 shape 尺寸不相同时,不支持合并。当前有2种合并策略,分别是: @@ -248,6 +266,8 @@ op: ``` + + **三.Mini-Batch** 拆分一个批量数据推理请求成为多个小块推理:会降低批量数据 Padding 对齐的大小,从而提升速度。可参考 [OCR 示例](),核心思路是拆分数据成多个小批量,放入 list 对象 feed_list 并返回 @@ -310,6 +330,8 @@ def preprocess(self, input_dicts, data_id, log_id): return feed_list, False, None, "" ``` + + ## 单机多卡推理 单机多卡推理与 `config.yml` 中配置4个参数关系紧密,`is_thread_op`、`concurrency`、`device_type` 和 `devices`,必须在进程模型和 GPU 模式,每张卡上可分配多个进程,即 M 个 Op 进程与 N 个 GPU 卡绑定。 @@ -346,6 +368,8 @@ op: 对于更灵活的进程与 GPU 卡绑定方式,会持续开发。 + + ## 多种计算芯片上推理 除了支持 CPU、GPU 芯片推理之外,Python Pipeline 还支持在多种计算硬件上推理。根据 `config.yml` 中的 `device_type` 和 `devices`来设置推理硬件和加速库如下: @@ -371,6 +395,7 @@ devices: "0" ir_optim: True ``` + ## TensorRT 推理加速 @@ -405,6 +430,7 @@ op: #开启 ir_optim ir_optim: True ``` + ## MKL-DNN 推理加速 @@ -439,6 +465,7 @@ op: #开启 MKLDNN use_mkldnn: True ``` + ## 低精度推理 @@ -446,7 +473,9 @@ Pipeline Serving支持低精度推理,CPU、GPU和TensoRT支持的精度类型 低精度推理需要有量化模型,配合`config.yml`配置一起使用,以[低精度示例]() 为例 -**一.CPU 低精度推理配置** + + +**一.CPU 低精度推理** 通过设置,`device_type` 和 `devices` 字段使用 CPU 推理,通过调整`precision`、`thread_num`和`use_mkldnn`参数选择低精度和性能调优。 @@ -484,6 +513,8 @@ op: use_mkldnn: True ``` + + **二.GPU 和 TensorRT 低精度推理** 通过设置`device_type` 和 `devices` 字段使用原生 GPU 或 TensorRT 推理,通过调整`precision`、`ir_optim`和`use_calib`参数选择低精度和性能调优,如开启 TensorRT,必须一同开启`ir_optim`,`use_calib`仅配合 int8 使用。 @@ -521,6 +552,8 @@ op: ir_optim: True ``` + + **三.性能测试** 测试环境如下: @@ -547,6 +580,8 @@ CPU 推理性能较好的配置是 + ## 复杂图结构 DAG 跳过某个 Op 运行 此应用场景一般在 Op 前后处理中有 if 条件判断时,不满足条件时,跳过后面处理。实际做法是在跳过此 Op 的 process 阶段,只要在 preprocess 做好判断,跳过 process 阶段,在和 postprocess 后直接返回即可。 diff --git a/doc/Offical_Docs/7-3_Python_Pipeline_Optimize_CN.md b/doc/Offical_Docs/7-3_Python_Pipeline_Optimize_CN.md index f0ec03f4..ef238019 100644 --- a/doc/Offical_Docs/7-3_Python_Pipeline_Optimize_CN.md +++ b/doc/Offical_Docs/7-3_Python_Pipeline_Optimize_CN.md @@ -1,11 +1,26 @@ # Python Pipeline 优化指南 +- [优化响应时长](#1) + - [1.1 分析响应时长](#1.1) + - [Pipeline Trace Tool](#1.1.1) + - [Pipeline Profile Tool](#1.1.2) + - [1.2 优化思路](#1.2) +- [优化服务吞吐](#2) + - [2.1 分析吞吐瓶颈](#2.1) + - [2.2 优化思路](#2.2) + - [增加 Op 并发](#2.2.1) + - [动态批量](#2.2.2) + - [CPU 与 GPU 处理分离](#2.2.3) + + 通常,服务的性能优化是基于耗时分析,首先要掌握服务运行的各阶段耗时信息,从中找到耗时最长的性能瓶颈再做针对性优化。对于模型推理服务化不仅要关注耗时,由于 GPU 芯片昂贵,更要关注服务吞吐,从而提升 GPU 利用率实现降本增效。因此,模型推理服务化可总结为: - 优化响应时长 - 优化服务吞吐 经过分析和调优后,各个阶段实现整体服务的性能最优。 + + ## 优化响应时长 首先,优化响应时长的主要思路首先要掌握各阶段耗时,并分析出性能瓶颈或者耗时占比较高的阶段,再针对性能瓶颈做专项优化。 @@ -14,7 +29,13 @@ Paddle Serving 提供2种耗时分析工具,`Pipeline Trace Tool` 和 `Pipelin - Pipeline Trace Tool : 统计服务端所有进程各个阶段的平均耗时,包括每个 `Op` 和 `Channel`,用于定量分析。 - Pipeline Profile Tool : 是可视化 Trace View 工具,生成多进程并发效果图,用定性和定量分析执行和并发效果。 -**一.Pipeline Trace Tool** + + +**一.耗时分析** + + + +1.Pipeline Trace Tool `Pipeline Trace Tool` 统计每个 `Op` 和 `Channel` 中各阶段的处理耗时, @@ -59,8 +80,9 @@ dag: chl1(In: ['uci'], Out: ['@DAGExecutor']) size[0/0] # uci Op 与 框架 ResponseOp 之间 Channel 中堆积的请求数。此值较大,说明下游 ReponseOp 消费能力不足。 ==================== TRACER ====================== ``` + -**二.Pipeline Profile Tool** +2.Pipeline Profile Tool ``` dag: @@ -101,8 +123,9 @@ python3.7 trace.py 通过图示中并发请求的处理流程可观测到推理阶段的流水线状态,以及多个请求在推理阶段的`间隔`信息,进行优化。 + -**三. 降低响应时长优化思路** +**二.降低响应时长优化思路** 根据 `Pipeline Trace Tool` 输出结果在不同阶段耗时长的问题,常见场景的优化方法如下: - Op 推理阶段(midp) 耗时长: @@ -126,8 +149,14 @@ python3.7 trace.py 此外,还有一些优化思路,如将 CPU 处理较慢的过程转换到 GPU 上处理等,客户端与服务端传输较大数据时,可使用共享内存方式传递内存或显存地址等。 + + ## 优化服务吞吐 + + +**一.分析吞吐瓶颈** + 服务的吞吐量受到多种多因素条件制约,如 Op 处理时长、传输数据耗时、并发数和 DAG 图结构等,可以将这些因素进一步拆解,当传输数据不是极端庞大的时候,最重要因素是流水线中`最慢 Op 的处理时长和并发数`。 ``` Op 处理时长: @@ -142,10 +171,15 @@ service_avg_cost = ∑op_concurrency 【关键路径】 批量预测平均耗时: avg_batch_cost = (N * pre + mid + post) / N ``` + + +**二.优化思路** 优化吞吐的主要方法是 `增大 Op 并发数`、`自动批量` 和 `CPU 与 GPU 处理分离` -**一.增加 Op 并发数** + + +1.增加 Op 并发** 调整 Op 的并发数量通过设置 `is_thread_op: False` 进程类型 Op 和 `uci` Op 的 `concurrency` 字段 ``` @@ -159,11 +193,15 @@ op: ``` Op 的进程数量不是越大越好,受到机器 CPU 核数、内存和显存大小的限制,推荐设置 Op 的并发数不超过系统 CPU 核数。 -**二.自动批量** + + +2.动态批量 + +动态批量是增加吞吐的有一种方法,开启方式可参考[Python Pipeline 核心功能](./7-2_Python_Pipeline_Senior_CN.md#批量推理) -自动配量是增加吞吐的有一种方法,开启方式可参考[Python Pipeline 核心功能](./7-2_Python_Pipeline_Senior_CN.md#批量推理) + -**三.CPU 与 GPU 处理分离** +3.CPU 与 GPU 处理分离 在 `CV` 模型中,对图片或视频的前后处理成为主要瓶颈时,可考虑此方案,即将前后处理过程独立成一个 Op 并独立设置并发度。 diff --git a/doc/Offical_Docs/7-4_Python_Pipeline_Benchmark_CN.md b/doc/Offical_Docs/7-4_Python_Pipeline_Benchmark_CN.md index 4df04ba6..2dce5d19 100644 --- a/doc/Offical_Docs/7-4_Python_Pipeline_Benchmark_CN.md +++ b/doc/Offical_Docs/7-4_Python_Pipeline_Benchmark_CN.md @@ -1,7 +1,13 @@ -本次提测的Serving版本,支持GPU预测,希望以此任务为例,对Paddle Serving支持GPU预测的性能给出测试数据。 +# Python Pipeline 性能测试 + +- [测试环境](#1) +- [性能指标](#2) + + ## 测试环境 +测试环境如下表所示: | | GPU | 显存 | CPU | 内存 | |----------|---------|----------|----------------------------------------------|------| | Serving端 | 4x Tesla P4-8GB | 7611MiB | Intel(R) Xeon(R) Gold 5117 CPU @ 2.00GHz 48核 | 216G | @@ -10,6 +16,8 @@ 使用单卡GPU,未开启TensorRT。 模型:ResNet_v2_50 + + ## 性能指标 |model_name |thread_num |batch_size |CPU_util(%) |GPU_memory(mb) |GPU_util(%) |qps(samples/s) |total count |mean(ms) |median(ms) |80 percent(ms) |90 percent(ms) |99 percent(ms) |total cost(s) |each cost(s)| diff --git a/doc/Offical_Docs/9-0_Kubernetes_Int_CN.md b/doc/Offical_Docs/9-0_Kubernetes_Int_CN.md index 16559a58..cd066809 100644 --- a/doc/Offical_Docs/9-0_Kubernetes_Int_CN.md +++ b/doc/Offical_Docs/9-0_Kubernetes_Int_CN.md @@ -3,6 +3,5 @@ Kubernetes 集群部署 服务部署经历从物理机、虚拟机、容器化、云原生4个阶段。云原生,提供集装箱组合模式的乐高生态,Docker、Kubernetes 已称为云原生时代基础设施,推动应用程序大发展。Kubernetes 的可扩展性和分布式架构一直是人工智能和机器学习的绝佳选择,随着解决方案不断成熟,推动机器学习大规模工程落地。 本章节介绍 Kubernetes 上集群化部署 Paddle Serving 方案以及企业级安全网关部署案例。 -- [Kubernetes 集群部署方案]() +- [Kubernetes 集群部署方案](./9-1_Kubernetes_CN.md) - [Kubernetes 安全网关部署案例]() - -- GitLab