Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
FluidDoc
提交
63861f32
F
FluidDoc
项目概览
PaddlePaddle
/
FluidDoc
通知
5
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
23
列表
看板
标记
里程碑
合并请求
111
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
FluidDoc
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
23
Issue
23
列表
看板
标记
里程碑
合并请求
111
合并请求
111
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
63861f32
编写于
9月 30, 2019
作者:
P
Pei Yang
提交者:
GitHub
9月 30, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refine native infer doc and index, test=develop, test=document_preview (#1431)
上级
3df76b0f
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
146 addition
and
151 deletion
+146
-151
doc/fluid/advanced_usage/deploy/inference/index_cn.rst
doc/fluid/advanced_usage/deploy/inference/index_cn.rst
+9
-1
doc/fluid/advanced_usage/deploy/inference/native_infer.md
doc/fluid/advanced_usage/deploy/inference/native_infer.md
+137
-150
未找到文件。
doc/fluid/advanced_usage/deploy/inference/index_cn.rst
浏览文件 @
63861f32
...
...
@@ -2,7 +2,15 @@
服务器端部署
############
PaddlePaddle Fluid 提供了 C++ API 来支持模型的部署上线
推理(Inference)指的是在设备上运行训练好的模型,依据输入数据来进行预测。Paddle Fluid提供了预测库及其C++和Python的API来支持模型的部署上线。
使用Paddle Fluid预测主要包含以下几个步骤:
1. 加载由Paddle Fluid训练的模型和参数文件;
2. 准备输入数据。即将待预测的数据(如图片)转换成Paddle Fluid模型接受的格式,并将其设定为预测引擎的输入;
3. 运行预测引擎,获得模型的输出;
4. 根据业务需求解析输出结果,获得需要的信息。
以上步骤使用的API会在后续部分进行详细介绍。
.. toctree::
:titlesonly:
...
...
doc/fluid/advanced_usage/deploy/inference/native_infer.md
浏览文件 @
63861f32
# C++ 预测 API介绍
为了更简单方便的预测部署,PaddlePaddle 提供了一套高层 API 预测接口。
预测库包含:
-
头文件主要包括:
-
`paddle_analysis_config.h `
-
`paddle_api.h `
-
`paddle_inference_api.h`
-
库文件:
-
`libpaddle_fluid.so`
-
`libpaddle_fluid.a`
为了更简单方便地预测部署,PaddlePaddle 提供了一套高层 C++ API 预测接口。
下面是详细介绍。
## 内容
-
[
NativePredictor使用
](
#NativePredictor使用
)
-
[
AnalysisPredictor使用
](
#AnalysisPredictor使用
)
-
[
输入输出的管理
](
#输入输出的管理
)
-
[
多线程预测
](
#多线程预测
)
-
[
性能建议
](
#性能建议
)
## <a name="NativePredictor使用">NativePredictor使用</a>
-
[
使用AnalysisPredictor进行高性能预测
](
#使用AnalysisPredictor进行高性能预测
)
-
[
使用AnalysisConfig管理预测配置
](
#使用AnalysisConfig管理预测配置
)
-
[
使用ZeroCopyTensor管理输入/输出
](
#使用ZeroCopyTensor管理输入/输出
)
-
[
C++预测样例编译测试
](
#C++预测样例编译测试
)
-
[
性能调优
](
#性能调优
)
`NativePredictor`
为原生预测引擎,底层由 PaddlePaddle 原生的 forward operator
组成,可以天然
**支持所有Paddle 训练出的模型**
。
#### NativePredictor 使用样例
```
c++
#include "paddle_inference_api.h"
namespace
paddle
{
// 配置NativeConfig
void
CreateConfig
(
NativeConfig
*
config
,
const
std
::
string
&
model_dirname
)
{
config
->
use_gpu
=
true
;
config
->
device
=
0
;
config
->
fraction_of_gpu_memory
=
0.1
;
/* for cpu
config->use_gpu=false;
config->SetCpuMathLibraryNumThreads(1);
*/
// 设置模型的参数路径
config
->
prog_file
=
model_dirname
+
"model"
;
config
->
param_file
=
model_dirname
+
"params"
;
// 当模型输入是多个的时候,这个配置是必要的。
config
->
specify_input_name
=
true
;
}
void
RunNative
(
int
batch_size
,
const
std
::
string
&
model_dirname
)
{
// 1. 创建NativeConfig
NativeConfig
config
;
CreateConfig
(
&
config
,
model_dirname
);
// 2. 根据config 创建predictor
auto
predictor
=
CreatePaddlePredictor
(
config
);
int
channels
=
3
;
int
height
=
224
;
int
width
=
224
;
float
*
data
=
new
float
[
batch_size
*
channels
*
height
*
width
];
// 3. 创建输入 tensor
PaddleTensor
tensor
;
tensor
.
name
=
"image"
;
tensor
.
shape
=
std
::
vector
<
int
>
({
batch_size
,
channels
,
height
,
width
});
tensor
.
data
=
PaddleBuf
(
static_cast
<
void
*>
(
data
),
sizeof
(
float
)
*
(
batch_size
*
channels
*
height
*
width
));
tensor
.
dtype
=
PaddleDType
::
FLOAT32
;
std
::
vector
<
PaddleTensor
>
paddle_tensor_feeds
(
1
,
tensor
);
// 4. 创建输出 tensor
std
::
vector
<
PaddleTensor
>
outputs
;
// 5. 预测
predictor
->
Run
(
paddle_tensor_feeds
,
&
outputs
,
batch_size
);
const
size_t
num_elements
=
outputs
.
front
().
data
.
length
()
/
sizeof
(
float
);
auto
*
data_out
=
static_cast
<
float
*>
(
outputs
.
front
().
data
.
data
());
}
}
// namespace paddle
int
main
()
{
// 模型下载地址 http://paddle-inference-dist.cdn.bcebos.com/tensorrt_test/mobilenet.tar.gz
paddle
::
RunNative
(
1
,
"./mobilenet"
);
return
0
;
}
```
## <a name="使用AnalysisPredictor进行高性能预测"> 使用AnalysisPredictor进行高性能预测</a>
Paddle Fluid采用 AnalysisPredictor 进行预测。AnalysisPredictor 是一个高性能预测引擎,该引擎通过对计算图的分析,完成对计算图的一系列的优化(如OP的融合、内存/显存的优化、 MKLDNN,TensorRT 等底层加速库的支持等),能够大大提升预测性能。
## <a name="AnalysisPredictor使用"> AnalysisPredictor使用</a>
AnalysisConfig 创建了一个高性能预测引擎。该引擎通过对计算图的分析,完成对计算图的一系列的优化(Op 的融合, MKLDNN,TRT等底层加速库的支持 etc),大大提升预测引擎的性能。
为了展示完整的预测流程,下面是一个使用 AnalysisPredictor 进行预测的完整示例,其中涉及到的具体概念和配置会在后续部分展开详细介绍。
#### AnalysisPredictor
使用样
例
#### AnalysisPredictor
预测示
例
```
c++
#include "paddle_inference_api.h"
...
...
@@ -101,25 +29,25 @@ namespace paddle {
void
CreateConfig
(
AnalysisConfig
*
config
,
const
std
::
string
&
model_dirname
)
{
// 模型从磁盘进行加载
config
->
SetModel
(
model_dirname
+
"/model"
,
model_dirname
+
"/params"
);
model_dirname
+
"/params"
);
// config->SetModel(model_dirname);
// 如果模型从内存中加载,可以使用SetModelBuffer接口
// config->SetModelBuffer(prog_buffer, prog_size, params_buffer, params_size);
config
->
EnableUseGpu
(
10
/*the initial size of the GPU memory pool in MB*/
,
0
/*gpu_id*/
);
config
->
EnableUseGpu
(
10
0
/*设定GPU初始显存池为MB*/
,
0
/*设定GPU ID为0*/
);
//开启GPU预测
/* for cpu
config->DisableGpu();
config->EnableMKLDNN(); //
可选
config->EnableMKLDNN(); //
开启MKLDNN加速
config->SetCpuMathLibraryNumThreads(10);
*/
//
当使用ZeroCopyTensor的时候,此处一定要设置为false。
//
使用ZeroCopyTensor,此处必须设置为false
config
->
SwitchUseFeedFetchOps
(
false
);
//
当多输入的时候,此处一定要
设置为true
//
若输入为多个,此处必须
设置为true
config
->
SwitchSpecifyInputNames
(
true
);
config
->
SwitchIrDebug
(
true
);
// 开关打开,会在每个图优化过程后生成dot文件,方便可视化。
// config->SwitchIrOptim(false);
// 默认为true。如果设置为false,关闭所有优化,执行过程同 NativePredictor
// config->EnableMemoryOptim(); // 开启内存/显存复用
config
->
SwitchIrDebug
(
true
);
// 可视化调试选项,若开启,则会在每个图优化过程后生成dot文件
// config->SwitchIrOptim(false);
// 默认为true。如果设置为false,关闭所有优化
// config->EnableMemoryOptim();
// 开启内存/显存复用
}
void
RunAnalysis
(
int
batch_size
,
std
::
string
model_dirname
)
{
...
...
@@ -127,7 +55,7 @@ void RunAnalysis(int batch_size, std::string model_dirname) {
AnalysisConfig
config
;
CreateConfig
(
&
config
,
model_dirname
);
// 2. 根据config 创建predictor
// 2. 根据config 创建predictor
,并准备输入数据,此处以全0数据为例
auto
predictor
=
CreatePaddlePredictor
(
config
);
int
channels
=
3
;
int
height
=
224
;
...
...
@@ -135,14 +63,13 @@ void RunAnalysis(int batch_size, std::string model_dirname) {
float
input
[
batch_size
*
channels
*
height
*
width
]
=
{
0
};
// 3. 创建输入
// 同NativePredictor样例一样,此处可以使用PaddleTensor来创建输入
// 以下的代码中使用了ZeroCopy的接口,同使用PaddleTensor不同的是:此接口可以避免预测中多余的cpu copy,提升预测性能。
auto
input_names
=
predictor
->
GetInputNames
();
// 使用了ZeroCopy接口,可以避免预测中多余的CPU copy,提升预测性能
auto
input_names
=
predictor
->
GetInputNames
();
auto
input_t
=
predictor
->
GetInputTensor
(
input_names
[
0
]);
input_t
->
Reshape
({
batch_size
,
channels
,
height
,
width
});
input_t
->
copy_from_cpu
(
input
);
// 4. 运行
// 4. 运行
预测引擎
CHECK
(
predictor
->
ZeroCopyRun
());
// 5. 获取输出
...
...
@@ -166,24 +93,61 @@ int main() {
```
## <a name="输入输出的管理"> 输入输出的管理</a>
### PaddleTensor 的使用
PaddleTensor可用于NativePredictor和AnalysisPredictor,在 NativePredictor样例中展示了PaddleTensor的使用方式。
PaddleTensor 定义了预测最基本的输入输出的数据格式,常用字段如下:
## <a name="使用AnalysisConfig管理预测配置"> 使用AnalysisConfig管理预测配置</a>
AnalysisConfig管理AnalysisPredictor的预测配置,提供了模型路径设置、预测引擎运行设备选择以及多种优化预测流程的选项。配置方法如下:
#### 设置模型和参数路径
从磁盘加载模型时,根据模型和参数文件存储方式不同,设置AnalysisConfig加载模型和参数的路径有两种形式:
-
`name`
,类型:string,用于指定输入数据对应的模型中variable的名字
-
`shape`
,类型:
`vector<int>`
, 表示一个Tensor的shape
-
`data`
,类型:
`PaddleBuf`
, 数据以连续内存的方式存储在
`PaddleBuf`
中,
`PaddleBuf`
可以接收外面的数据或者独立
`malloc`
内存,详细可以参考头文件中相关定义。
-
`dtype`
,类型:
`PaddleType`
, 有
`PaddleDtype::FLOAT32`
,
`PaddleDtype::INT64`
,
`PaddleDtype::INT32`
三种, 表示 Tensor 的数据类型。
-
`lod`
,类型:
`vector<vector<size_t>>`
,在处理变长输入的时候,需要对
`PaddleTensor`
设置LoD信息。可以参考
[
LoD-Tensor使用说明
](
../../../user_guides/howto/basic_concept/lod_tensor.html
)
*
conbined形式:模型文件夹
`model_dir`
下存在一个模型文件和多个参数文件时,传入模型文件夹路径,模型文件名默认为
`__model__`
。
```
c++
config
->
SetModel
(
"./model_dir"
);
```
*
非combined形式:模型文件夹
`model_dir`
下只有一个模型文件
`model`
和一个参数文件
`params`
时,传入模型文件和参数文件路径。
```
c++
config
->
SetModel
(
"./model_dir/model"
,
"./model_dir/params"
);
```
### ZeroCopyTensor的使用
ZeroCopyTensor的使用可避免预测时候准备输入以及获取输出时多余的数据copy,提高预测性能。
**只可用于AnalysisPredictor**
。
#### 通用优化配置
```
c++
config
->
SwitchIrOptim
(
true
);
// 开启计算图分析优化,包括OP融合等
config
->
EnableMemoryOptim
();
// 开启内存/显存复用
```
**Note:**
使用ZeroCopyTensor必须设置:
```
c++
config
->
SwitchUseFeedFetchOps
(
false
);
// 关闭feed和fetch OP使用,使用ZeroCopy接口必须设置此项
```
**Note:**
使用ZeroCopyTensor,务必在创建config时设置
`config->SwitchUseFeedFetchOps(false)`
#### 配置CPU预测
```
c++
config
->
DisableGpu
();
// 禁用GPU
config
->
EnableMKLDNN
();
// 开启MKLDNN,可加速CPU预测
config
->
SetCpuMathLibraryNumThreads
(
10
);
// 设置CPU Math库线程数,CPU核心数支持情况下可加速预测
```
#### 配置GPU预测
```
c++
config
->
EnableUseGpu
(
100
,
0
);
// 初始化100M显存,使用GPU ID为0
config
->
GpuDeviceId
();
// 返回正在使用的GPU ID
// 开启TensorRT预测,可提升GPU预测性能,需要使用带TensorRT的预测库
config
->
EnableTensorRtEngine
(
1
<<
20
/*workspace_size*/
,
batch_size
/*max_batch_size*/
,
3
/*min_subgraph_size*/
,
AnalysisConfig
::
Precision
::
kFloat32
/*precision*/
,
false
/*use_static*/
,
false
/*use_calib_mode*/
);
```
## <a name="使用ZeroCopyTensor管理输入/输出"> 使用ZeroCopyTensor管理输入/输出</a>
ZeroCopyTensor是AnalysisPredictor的输入/输出数据结构。ZeroCopyTensor的使用可以避免预测时候准备输入以及获取输出时多余的数据copy,提高预测性能。
**Note:**
使用ZeroCopyTensor,务必在创建config时设置
`config->SwitchUseFeedFetchOps(false);`
。
```
c++
// 通过创建的AnalysisPredictor获取输入和输出的tensor
auto
input_names
=
predictor
->
GetInputNames
();
auto
input_t
=
predictor
->
GetInputTensor
(
input_names
[
0
]);
...
...
@@ -201,54 +165,77 @@ output_t->copy_to_cpu(out_data /*数据指针*/);
std
::
vector
<
std
::
vector
<
size_t
>>
lod_data
=
{{
0
},
{
0
}};
input_t
->
SetLoD
(
lod_data
);
// 获取
t
ensor数据指针
// 获取
T
ensor数据指针
float
*
input_d
=
input_t
->
mutable_data
<
float
>
(
PaddlePlace
::
kGPU
);
// CPU下使用PaddlePlace::kCPU
int
output_size
;
float
*
output_d
=
output_t
->
data
<
float
>
(
PaddlePlace
::
kGPU
,
&
output_size
);
```
## <a name="多线程预测"> 多线程预测</a>
多线程场景下,每个服务线程执行同一种模型,支持 CPU 和 GPU。
## <a name="C++预测样例编译测试"> C++预测样例编译测试</a>
1.
下载或编译paddle预测库,参考
[
安装与编译C++预测库
](
./build_and_install_lib_cn.html
)
。
2.
下载
[
预测样例
](
https://paddle-inference-dist.bj.bcebos.com/tensorrt_test/paddle_inference_sample_v1.6.tar.gz
)
并解压,进入
`sample/inference`
目录下。
`inference` 文件夹目录结构如下:
```shell
inference
├── CMakeLists.txt
├── mobilenet_test.cc
├── thread_mobilenet_test.cc
├── mobilenetv1
│ ├── model
│ └── params
├── run.sh
└── run_impl.sh
```
- `mobilenet_test.cc` 为单线程预测的C++源文件
- `thread_mobilenet_test.cc` 为多线程预测的C++源文件
- `mobilenetv1` 为模型文件夹
- `run.sh` 为预测运行脚本文件
3.
配置编译与运行脚本
编译运行预测样例之前,需要根据运行环境配置编译与运行脚本
`run.sh`
。
`run.sh`
的选项与路径配置的部分如下:
```
shell
# 设置是否开启MKL、GPU、TensorRT,如果要使用TensorRT,必须打开GPU
WITH_MKL
=
ON
WITH_GPU
=
OFF
USE_TENSORRT
=
OFF
# 按照运行环境设置预测库路径、CUDA库路径、CUDNN库路径、模型路径
LIB_DIR
=
YOUR_LIB_DIR
CUDA_LIB_DIR
=
YOUR_CUDA_LIB_DIR
CUDNN_LIB_DIR
=
YOUR_CUDNN_LIB_DIR
MODEL_DIR
=
YOUR_MODEL_DIR
```
按照实际运行环境配置
`run.sh`
中的选项开关和所需lib路径。
4.
编译与运行样例
```shell
sh run.sh
```
## <a name="性能调优"> 性能调优</a>
### CPU下预测
1.
在CPU型号允许的情况下,尽量使用带AVX和MKL的版本。
2.
可以尝试使用Intel的 MKLDNN 加速。
3.
在CPU可用核心数足够时,可以将设置
`config->SetCpuMathLibraryNumThreads(num);`
中的num值调高一些。
### GPU下预测
1.
可以尝试打开 TensorRT 子图加速引擎, 通过计算图分析,Paddle可以自动将计算图中部分子图融合,并调用NVIDIA的 TensorRT 来进行加速,详细内容可以参考
[
使用Paddle-TensorRT库预测
](
./paddle_tensorrt_infer.html
)
。
### 多线程预测
Paddle Fluid支持通过在不同线程运行多个AnalysisPredictor的方式来优化预测性能,支持CPU和GPU环境。
使用多线程预测的样例详见
[
C++预测样例编译测试
](
#C++预测样例编译测试
)
中下载的
[
预测样例
](
https://paddle-inference-dist.cdn.bcebos.com/tensorrt_test/paddle_trt_samples_v1.6.tar.gz
)
中的
`thread_mobilenet_test.cc`
文件。可以将
`run.sh`
中
`mobilenet_test`
替换成
`thread_mobilenet_test`
再执行
下面演示最简单的实现,用户需要根据具体应用场景做相应的调整
```
c++
auto
main_predictor
=
paddle
::
CreatePaddlePredictor
(
config
);
const
int
num_threads
=
10
;
// 假设有 10 个服务线程
std
::
vector
<
std
::
thread
>
threads
;
std
::
vector
<
decl_type
(
main_predictor
)
>
predictors
;
// 将克隆的 predictor 放入 vector 供线程使用
for
(
int
i
=
0
;
i
<
num_threads
;
i
++
)
{
predictors
.
emplace_back
(
main_predictor
->
Clone
());
}
// 创建线程并执行
for
(
int
i
=
0
;
i
<
num_threads
;
i
++
)
{
threads
.
emplace_back
([
i
,
&
]{
auto
&
predictor
=
predictors
[
i
];
// 执行
CHECK
(
predictor
->
Run
(...));
});
}
// 线程join
for
(
auto
&
t
:
threads
)
{
if
(
t
.
joinable
())
t
.
join
();
}
// 结束
```
sh run.sh
```
## <a name="性能建议"> 性能建议</a>
1.
在CPU型号允许的情况下,尽量使用带AVX和MKL的版本
2.
CPU或GPU预测,可以尝试把
`NativeConfig`
改成
`AnalysisConfig`
来进行优化
3.
尽量使用
`ZeroCopyTensor`
避免过多的内存copy
4.
CPU下可以尝试使用Intel的
`MKLDNN`
加速
5.
GPU 下可以尝试打开
`TensorRT`
子图加速引擎, 通过计算图分析,Paddle可以自动将计算图中部分子图切割,并调用NVidia的
`TensorRT`
来进行加速。
详细内容可以参考
[
Paddle-TRT 子图引擎
](
./paddle_tensorrt_infer.html
)
即可运行多线程预测样例。
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录