未验证 提交 09fe38cb 编写于 作者: C Cheerego 提交者: GitHub

synchronize with develop (#642)

* update_commitid1.3 (#641)

* update inference c++ API doc (#634)

* update inference c++ API doc

* fix link
上级 249ea3d8
......@@ -20,17 +20,20 @@ PaddleTensor 定义了预测最基本的输入输出的数据格式,常用字
## 利用Config 创建不同引擎
高层 API 底层有多种优化实现,我们称之为 engine;不同 engine 的切换通过传递不同的 Config 实现重载
高层 API 底层有多种优化实现,我们称之为 engine;不同 engine 的切换通过传递不同的 Config 实现重载
- `NativeConfig` 原生 engine,由 paddle 原生的 forward operator
组成,可以天然支持所有paddle 训练出的模型,
`Config` 有两种,`NativeConfig` 较简单和稳定,`AnalysisConfig` 功能更新,性能更好
- `AnalysisConfig` TensorRT mixed engine 用于 GPU
- `NativeConfig` 原生 engine,由 paddle 原生的 forward operator
组成,可以天然支持所有paddle 训练出的模型,
- `AnalysisConfig`
- 支持计算图的分析和优化
- 支持最新的各类 op fuse,性能一般比 `NativeConfig` 要好
- 支持 TensorRT mixed engine 用于 GPU
加速,用子图的方式支持了 [TensorRT] ,支持所有paddle
模型,并自动切割部分计算子图到 TensorRT 上加速(WIP),具体的使用方式可以参考[这里](http://paddlepaddle.org/documentation/docs/zh/1.1/user_guides/howto/inference/paddle_tensorrt_infer.html)
模型,并自动切割部分计算子图到 TensorRT 上加速,具体的使用方式可以参考[这里](http://paddlepaddle.org/documentation/docs/zh/1.1/user_guides/howto/inference/paddle_tensorrt_infer.html)
## 预测部署过程
## 基于 NativeConfig 的预测部署过程
总体上分为以下步骤
......@@ -70,68 +73,144 @@ CHECK(predictor->Run(slots, &outputs));
## 高阶使用
### 输入输出的内存管理
`PaddleTensor``data` 字段是一个 `PaddleBuf`,用于管理一段内存用于数据的拷贝。
`PaddleBuf` 在内存管理方面有两种模式:
1. 自动分配和管理内存
```c++
int some_size = 1024;
PaddleTensor tensor;
tensor.data.Resize(some_size);
```
```c++
int some_size = 1024;
PaddleTensor tensor;
tensor.data.Resize(some_size);
```
2. 外部内存传入
```c++
int some_size = 1024;
// 用户外部分配内存并保证 PaddleTensor 使用过程中,内存一直可用
void* memory = new char[some_size];
tensor.data.Reset(memory, some_size);
// ...
// 用户最后需要自行删除内存以避免内存泄漏
delete[] memory;
```
```c++
int some_size = 1024;
// 用户外部分配内存并保证 PaddleTensor 使用过程中,内存一直可用
void* memory = new char[some_size];
tensor.data.Reset(memory, some_size);
// ...
// 用户最后需要自行删除内存以避免内存泄漏
delete[] memory;
```
两种模式中,第一种比较方便;第二种则可以严格控制内存的管理,便于与 `tcmalloc` 等库的集成。
### 基于 contrib::AnalysisConfig 提升性能
*AnalyisConfig 目前正在预发布阶段,用 `namespace contrib` 进行了保护,后续可能会有调整*
### 基于 AnalysisConfig 提升性能
`AnalysisConfig` 是目前我们重点优化的版本。
类似 `NativeConfig``AnalysisConfig` 可以创建一个经过一系列优化的高性能预测引擎。 其中包含了计算图的分析和优化,以及对一些重要 Op 的融合改写等,**对使用了 While, LSTM, GRU 等模型性能有大幅提升**
类似 `NativeConfig``AnalysisConfig` 可以创建一个经过一系列优化的高性能预测引擎。 其中包含了计算图的分析和优化,以及对一些重要 Op 的融合改写等,比如对使用了 While, LSTM, GRU 等模型性能有大幅提升
`AnalysisConfig` 的使用方法也和 `NativeConfig` 类似,但 *目前仅支持 CPU,正在增加对GPU 的支持*
`AnalysisConfig` 的使用方法也和 `NativeConfig` 类似
```c++
AnalysisConfig config;
config.SetModel(dirname); // 设定模型的目录
config.EnableUseGpu(100, 0 /*gpu id*/); // 使用GPU, CPU下使用config.DisableGpu();
config.SwitchSpecifyInputNames(true); // 需要指定输入的 name
config.SwitchIrOptim(); // 打开优化开关,运行时会执行一系列的优化
AnalysisConfig config(dirname); // dirname 是模型的路径
// 对于不同的模型存储格式,也可以用 AnalysisConfig config(model_file, params_file)
config.EnableUseGpu(100/*初始显存池大小(MB)*/, 0 /*gpu id*/); // 使用GPU, CPU下使用config.DisableGpu();
config.SwitchIrOptim(); // 打开优化开关,运行时会执行一系列的计算图优化
```
这里需要注意的是,输入的 PaddleTensor 需要指定,比如之前的例子需要修改为
```c++
auto predictor =
paddle::CreatePaddlePredictor<paddle::contrib::AnalysisConfig>(config); // 注意这里需要 AnalysisConfig
auto predictor = paddle::CreatePaddlePredictor(config); // 注意这里需要 AnalysisConfig
// 创建输入 tensor
int64_t data[4] = {1, 2, 3, 4};
paddle::PaddleTensor tensor;
tensor.shape = std::vector<int>({4, 1});
tensor.data.Reset(data, sizeof(data));
tensor.dtype = paddle::PaddleDType::INT64;
tensor.name = "input0"; // 注意这里的 name 需要设定
```
后续的执行过程与 `NativeConfig` 完全一致。
### 多线程预测的建议
#### 数据并行的服务
这种场景下,每个服务线程执行同一种模型,支持 CPU 和 GPU。
Paddle 并没有相关的接口支持,但用户可以简单组合得出,下面演示最简单的实现,用户最好参考具体应用场景做调整
```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都创建好
predictors.emplace_back(std::move(main_predictor));
for (int i = 1; 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(...));
});
}
// 结尾
for (auto& t : threads) {
if (t.joinable()) t.join();
}
// 结束
```
#### 模型并行的服务
这种场景,使用多个线程/CPU核加速单个模型的预测,**目前只支持 CPU下使用 MKL/MKLDNN 的情况**
使用 `AnalysisConfig` 的对应接口来设置底层科学计算库使用线程的数目,具体参考 [SetCpuMathLibraryNumThreads](https://github.com/PaddlePaddle/Paddle/blob/release/1.3/paddle/fluid/inference/api/paddle_analysis_config.h#L159)
```c++
config.SetCpuMathLibraryNumThreads(8); // 一个模型使用 8 个线程加速预测
// 查询状态,可以使用如下接口
config.cpu_math_library_num_threads(); // return an int
```
### 性能建议
1. 在 CPU型号允许的情况下,尽量使用带 AVX 和 MKL 的版本
2. 复用输入和输出的 `PaddleTensor` 以避免频繁分配内存拉低性能
3. CPU或GPU预测,可以尝试把 `NativeConfig` 改成成 `AnalysisConfig` 来进行优化
#### CPU下可以尝试使用 Intel 的 `MKLDNN` 加速
MKLDNN 对 `CNN` 类的模型预测有不错的加速效果,可以尝试对比与 `MKLML` 的性能。
使用方法:
```c++
// AnalysisConfig config(...);
config.EnableMKLDNN();
// 查看 mkldnn 是否已经打开,可以用如下代码
config.mkldnn_enabled(); // return a bool
```
#### GPU 下可以尝试打开 `TensorRT` 子图加速引擎
通过计算图分析,Paddle 可以自动将计算图中部分子图切割,并调用 NVidia 的 `TensorRT` 来进行加速。
详细内容可以参考 [TensorRT 子图引擎](./paddle_tensorrt_infer.html)
## 详细代码参考
`AnalysisConfig` 完整接口可以参考 [这里](https://github.com/PaddlePaddle/Paddle/blob/release/1.3/paddle/fluid/inference/api/paddle_analysis_config.h#L35)
[inference demos](https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/fluid/inference/api/demo_ci)
Subproject commit 4550862e62899a55c59733331a2b2ca553ff2606
Subproject commit 2307baf5b0d0721b0ebd96ca403576879ec0b168
Subproject commit d233b20945bc22a220ffd05b74dbe47bdae69007
Subproject commit 2e55fd4630de30ecf86e5c59f89285e5786762ba
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册