From 788257151b74b904d2037f5cdbced4dff7c7d9ac Mon Sep 17 00:00:00 2001
From: andyjpaddle <87074272+andyjpaddle@users.noreply.github.com>
Date: Tue, 19 Apr 2022 16:20:35 +0800
Subject: [PATCH] add tipc for cpp infer (#5499)
---
.../Step6/test_tipc/README.md | 2 +-
.../mobilenet_v3_small/inference_cpp.txt | 14 +
.../test_tipc/docs/test_inference_cpp.md | 245 +++++++++++
.../Step6/test_tipc/test_inference_cpp.sh | 74 ++++
tutorials/tipc/README.md | 2 +-
tutorials/tipc/infer_cpp/README.md | 9 +
tutorials/tipc/infer_cpp/test_infer_cpp.md | 379 +++++++++++++++++-
7 files changed, 719 insertions(+), 6 deletions(-)
create mode 100755 tutorials/mobilenetv3_prod/Step6/test_tipc/configs/mobilenet_v3_small/inference_cpp.txt
create mode 100644 tutorials/mobilenetv3_prod/Step6/test_tipc/docs/test_inference_cpp.md
create mode 100644 tutorials/mobilenetv3_prod/Step6/test_tipc/test_inference_cpp.sh
diff --git a/tutorials/mobilenetv3_prod/Step6/test_tipc/README.md b/tutorials/mobilenetv3_prod/Step6/test_tipc/README.md
index e0f0b38e..238c3802 100644
--- a/tutorials/mobilenetv3_prod/Step6/test_tipc/README.md
+++ b/tutorials/mobilenetv3_prod/Step6/test_tipc/README.md
@@ -60,7 +60,7 @@ test_tipc
- 更多部署方式测试(coming soon):
- [Linux GPU/CPU PYTHON 服务化部署测试](docs/test_serving_infer_python.md)
- [Linux GPU/CPU C++ 服务化部署测试]
- - [Linux GPU/CPU C++ 推理测试]
+ - [Linux GPU/CPU C++ 推理测试](docs/test_inference_cpp.md)
- [Paddle.js 部署测试]
- [Paddle2ONNX 测试](docs/test_paddle2onnx.md)
- [Lite ARM CPU 部署测试](docs/test_lite_infer_cpp_arm_cpu.md)
diff --git a/tutorials/mobilenetv3_prod/Step6/test_tipc/configs/mobilenet_v3_small/inference_cpp.txt b/tutorials/mobilenetv3_prod/Step6/test_tipc/configs/mobilenet_v3_small/inference_cpp.txt
new file mode 100755
index 00000000..d7eafc9c
--- /dev/null
+++ b/tutorials/mobilenetv3_prod/Step6/test_tipc/configs/mobilenet_v3_small/inference_cpp.txt
@@ -0,0 +1,14 @@
+# model load config
+use_gpu 0
+gpu_id 0
+gpu_mem 4000
+cpu_math_library_num_threads 10
+use_mkldnn 1
+use_tensorrt 0
+use_fp16 0
+
+# cls config
+cls_model_path ./deploy/inference_cpp/mobilenet_v3_small_infer/inference.pdmodel
+cls_params_path ./deploy/inference_cpp/mobilenet_v3_small_infer/inference.pdiparams
+resize_short_size 256
+crop_size 224
diff --git a/tutorials/mobilenetv3_prod/Step6/test_tipc/docs/test_inference_cpp.md b/tutorials/mobilenetv3_prod/Step6/test_tipc/docs/test_inference_cpp.md
new file mode 100644
index 00000000..8830f4f3
--- /dev/null
+++ b/tutorials/mobilenetv3_prod/Step6/test_tipc/docs/test_inference_cpp.md
@@ -0,0 +1,245 @@
+# Linux GPU/CPU C++ 推理功能测试
+
+Linux GPU/CPU C++ 推理功能测试的主程序为`test_inference_cpp.sh`,可以测试基于C++预测引擎的推理功能。
+
+## 1. 测试结论汇总
+
+- 推理相关:
+
+| 算法名称 | 模型名称 | device_CPU | device_GPU | tensorrt | mkldnn |
+| :----: | :----: | :----: | :----: | :----: | :----: |
+| MobileNetV3 | mobilenet_v3_small | 支持 | 支持 | 支持 | 支持 |
+
+## 2. 测试流程
+
+### 2.1 准备数据和推理模型
+
+#### 2.1.1 准备数据
+
+从验证集或者测试集中抽出至少一张图像,用于后续的推理过程验证。
+
+#### 2.1.2 准备推理模型
+
+* 如果已经训练好了模型,可以参考[模型导出](../../tools/export_model.py),导出`inference model`,用于模型预测。得到预测模型后,假设模型文件放在`inference`目录下,则目录结构如下。
+
+```
+mobilenet_v3_small_infer/
+|--inference.pdmodel
+|--inference.pdiparams
+|--inference.pdiparams.info
+```
+**注意**:上述文件中,`inference.pdmodel`文件存储了模型结构信息,`inference.pdiparams`文件存储了模型参数信息。注意两个文件的路径需要与[配置文件](../configs/mobilenet_v3_small/inference_cpp.txt)中的`cls_model_path`和`cls_params_path`参数对应一致。
+
+### 2.2 准备环境
+
+#### 2.2.1 运行准备
+
+配置合适的编译和执行环境,其中包括编译器,cuda等一些基础库,建议安装docker环境,[参考链接](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/install/docker/linux-docker.html)。
+
+#### 2.2.2 编译opencv库
+
+* 首先需要从opencv官网上下载Linux环境下的源码,以3.4.7版本为例,下载及解压缩命令如下:
+
+```
+cd deploy/inference_cpp
+wget https://github.com/opencv/opencv/archive/3.4.7.tar.gz
+tar -xvf 3.4.7.tar.gz
+```
+
+* 编译opencv,首先设置opencv源码路径(`root_path`)以及安装路径(`install_path`),`root_path`为下载的opencv源码路径,`install_path`为opencv的安装路径。在本例中,源码路径即为当前目录下的`opencv-3.4.7/`。
+
+```shell
+cd ./opencv-3.4.7
+export root_path=$PWD
+export install_path=${root_path}/opencv3
+```
+
+* 然后在opencv源码路径下,按照下面的命令进行编译。
+
+```shell
+rm -rf build
+mkdir build
+cd build
+
+cmake .. \
+ -DCMAKE_INSTALL_PREFIX=${install_path} \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DBUILD_SHARED_LIBS=OFF \
+ -DWITH_IPP=OFF \
+ -DBUILD_IPP_IW=OFF \
+ -DWITH_LAPACK=OFF \
+ -DWITH_EIGEN=OFF \
+ -DCMAKE_INSTALL_LIBDIR=lib64 \
+ -DWITH_ZLIB=ON \
+ -DBUILD_ZLIB=ON \
+ -DWITH_JPEG=ON \
+ -DBUILD_JPEG=ON \
+ -DWITH_PNG=ON \
+ -DBUILD_PNG=ON \
+ -DWITH_TIFF=ON \
+ -DBUILD_TIFF=ON
+
+make -j
+make install
+```
+
+* `make install`完成之后,会在该文件夹下生成opencv头文件和库文件,用于后面的代码编译。
+
+以opencv3.4.7版本为例,最终在安装路径下的文件结构如下所示。**注意**:不同的opencv版本,下述的文件结构可能不同。
+
+```
+opencv3/
+|-- bin :可执行文件
+|-- include :头文件
+|-- lib64 :库文件
+|-- share :部分第三方库
+```
+
+#### 2.2.3 下载或者编译Paddle预测库
+
+* 有2种方式获取Paddle预测库,下面进行详细介绍。
+
+##### 预测库源码编译
+* 如果希望获取最新预测库特性,可以从Paddle github上克隆最新代码,源码编译预测库。
+* 可以参考[Paddle预测库官网](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/05_inference_deployment/inference/build_and_install_lib_cn.html#id16)的说明,从github上获取Paddle代码,然后进行编译,生成最新的预测库。使用git获取代码方法如下。
+
+```shell
+git clone https://github.com/PaddlePaddle/Paddle.git
+```
+
+* 进入Paddle目录后,使用如下命令编译。
+
+```shell
+rm -rf build
+mkdir build
+cd build
+
+cmake .. \
+ -DWITH_CONTRIB=OFF \
+ -DWITH_MKL=ON \
+ -DWITH_MKLDNN=ON \
+ -DWITH_TESTING=OFF \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DWITH_INFERENCE_API_TEST=OFF \
+ -DON_INFER=ON \
+ -DWITH_PYTHON=ON
+make -j
+make inference_lib_dist
+```
+
+更多编译参数选项可以参考Paddle C++预测库官网:[https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/05_inference_deployment/inference/build_and_install_lib_cn.html#id16](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/05_inference_deployment/inference/build_and_install_lib_cn.html#id16)。
+
+
+* 编译完成之后,可以在`build/paddle_inference_install_dir/`文件下看到生成了以下文件及文件夹。
+
+```
+build/paddle_inference_install_dir/
+|-- CMakeCache.txt
+|-- paddle
+|-- third_party
+|-- version.txt
+```
+
+其中`paddle`就是之后进行C++预测时所需的Paddle库,`version.txt`中包含当前预测库的版本信息。
+
+##### 直接下载安装
+
+* [Paddle预测库官网](https://paddleinference.paddlepaddle.org.cn/user_guides/download_lib.html)上提供了不同cuda版本的Linux预测库,可以在官网查看并选择合适的预测库版本。
+
+ 以`manylinux_cuda11.1_cudnn8.1_avx_mkl_trt7_gcc8.2`版本为例,使用下述命令下载并解压:
+
+
+```shell
+wget https://paddle-inference-lib.bj.bcebos.com/2.2.2/cxx_c/Linux/GPU/x86-64_gcc8.2_avx_mkl_cuda11.1_cudnn8.1.1_trt7.2.3.4/paddle_inference.tgz
+
+tar -xvf paddle_inference.tgz
+```
+
+最终会在当前的文件夹中生成`paddle_inference/`的子文件夹,文件内容和上述的paddle_inference_install_dir一样。
+
+
+#### 2.2.4 编译C++预测Demo
+
+* 编译命令如下,其中Paddle C++预测库、opencv等其他依赖库的地址需要换成自己机器上的实际地址。
+
+
+```shell
+sh tools/build.sh
+```
+
+具体地,`tools/build.sh`中内容如下。
+
+```shell
+OPENCV_DIR=your_opencv_dir
+LIB_DIR=your_paddle_inference_dir
+CUDA_LIB_DIR=your_cuda_lib_dir
+CUDNN_LIB_DIR=your_cudnn_lib_dir
+TENSORRT_DIR=your_tensorrt_lib_dir
+
+BUILD_DIR=build
+rm -rf ${BUILD_DIR}
+mkdir ${BUILD_DIR}
+cd ${BUILD_DIR}
+cmake .. \
+ -DPADDLE_LIB=${LIB_DIR} \
+ -DWITH_MKL=ON \
+ -DDEMO_NAME=clas_system \
+ -DWITH_GPU=OFF \
+ -DWITH_STATIC_LIB=OFF \
+ -DWITH_TENSORRT=OFF \
+ -DTENSORRT_DIR=${TENSORRT_DIR} \
+ -DOPENCV_DIR=${OPENCV_DIR} \
+ -DCUDNN_LIB=${CUDNN_LIB_DIR} \
+ -DCUDA_LIB=${CUDA_LIB_DIR} \
+
+make -j
+```
+
+上述命令中,
+
+* `OPENCV_DIR`为opencv编译安装的地址(本例中为`opencv-3.4.7/opencv3`文件夹的路径);
+
+* `LIB_DIR`为下载的Paddle预测库(`paddle_inference`文件夹),或编译生成的Paddle预测库(`build/paddle_inference_install_dir`文件夹)的路径;
+
+* `CUDA_LIB_DIR`为cuda库文件地址,在docker中一般为`/usr/local/cuda/lib64`;
+
+* `CUDNN_LIB_DIR`为cudnn库文件地址,在docker中一般为`/usr/lib64`。
+
+* `TENSORRT_DIR`是tensorrt库文件地址,在dokcer中一般为`/usr/local/TensorRT-7.2.3.4/`,TensorRT需要结合GPU使用。
+
+在执行上述命令,编译完成之后,会在当前路径下生成`build`文件夹,其中生成一个名为`clas_system`的可执行文件。
+
+
+### 2.3 功能测试
+
+
+测试方法如下所示,希望测试不同的模型文件,只需更换为自己的参数配置文件,即可完成对应模型的测试。
+
+```bash
+bash test_tipc/test_inference_cpp.sh ${your_params_file}
+```
+
+以`mobilenet_v3_small`的`Linux GPU/CPU C++推理测试`为例,命令如下所示。
+
+```bash
+bash test_tipc/test_inference_cpp.sh test_tipc/configs/mobilenet_v3_small/inference_cpp.txt
+```
+
+输出结果如下,表示命令运行成功。
+
+```bash
+Run successfully with command - ./deploy/inference_cpp/build/clas_system test_tipc/configs/mobilenet_v3_small/inference_cpp.txt ./images/demo.jpg > ./log/infer_cpp/infer_cpp_use_cpu_use_mkldnn.log 2>&1 !
+```
+
+最终log中会打印出结果,如下所示
+```
+img_file_list length: 1
+result:
+ class id: 8
+ score: 0.9014719725
+Current image path: ./images/demo.jpg
+Current time cost: 0.1409450000 s, average time cost in all: 0.1409450000 s.
+```
+详细log位于`./log/infer_cpp/infer_cpp_use_cpu_use_mkldnn.log`中。
+
+如果运行失败,也会在终端中输出运行失败的日志信息以及对应的运行命令。可以基于该命令,分析运行失败的原因。
diff --git a/tutorials/mobilenetv3_prod/Step6/test_tipc/test_inference_cpp.sh b/tutorials/mobilenetv3_prod/Step6/test_tipc/test_inference_cpp.sh
new file mode 100644
index 00000000..ad609057
--- /dev/null
+++ b/tutorials/mobilenetv3_prod/Step6/test_tipc/test_inference_cpp.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+source test_tipc/common_func.sh
+
+function func_parser_key_cpp(){
+ strs=$1
+ IFS=" "
+ array=(${strs})
+ tmp=${array[0]}
+ echo ${tmp}
+}
+
+function func_parser_value_cpp(){
+ strs=$1
+ IFS=" "
+ array=(${strs})
+ tmp=${array[1]}
+ echo ${tmp}
+}
+
+FILENAME=$1
+
+dataline=$(cat ${FILENAME})
+lines=(${dataline})
+
+# parser params
+dataline=$(awk 'NR==1, NR==14{print}' $FILENAME)
+IFS=$'\n'
+lines=(${dataline})
+
+# parser load config
+use_gpu_key=$(func_parser_key_cpp "${lines[1]}")
+use_gpu_value=$(func_parser_value_cpp "${lines[1]}")
+use_mkldnn_key=$(func_parser_key_cpp "${lines[5]}")
+use_mkldnn_value=$(func_parser_value_cpp "${lines[5]}")
+use_tensorrt_key=$(func_parser_key_cpp "${lines[6]}")
+use_tensorrt_value=$(func_parser_value_cpp "${lines[6]}")
+use_fp16_key=$(func_parser_key_cpp "${lines[7]}")
+use_fp16_value=$(func_parser_value_cpp "${lines[7]}")
+
+LOG_PATH="./log/infer_cpp"
+mkdir -p ${LOG_PATH}
+status_log="${LOG_PATH}/results_infer_cpp.log"
+
+function func_infer_cpp(){
+ # inference cpp
+ if test $use_gpu_value -gt 0; then
+ if test $use_tensorrt_value -gt 0; then
+ if test $use_fp16_value -gt 0; then
+ _save_log_path="${LOG_PATH}/infer_cpp_${use_gpu_key}_${use_tensorrt_key}_${use_fp16_key}.log"
+ else
+ _save_log_path="${LOG_PATH}/infer_cpp_${use_gpu_key}_${use_tensorrt_key}.log"
+ fi
+ else
+ _save_log_path="${LOG_PATH}/infer_cpp_${use_gpu_key}.log"
+ fi
+ else
+ if test $use_mkldnn_value -gt 0; then
+ _save_log_path="${LOG_PATH}/infer_cpp_use_cpu_${use_mkldnn_key}.log"
+ else
+ _save_log_path="${LOG_PATH}/infer_cpp_use_cpu.log"
+ fi
+ fi
+ # run infer cpp
+ inference_cpp_cmd="./deploy/inference_cpp/build/clas_system"
+ inference_cpp_img="./images/demo.jpg"
+ infer_cpp_full_cmd="${inference_cpp_cmd} ${FILENAME} ${inference_cpp_img} > ${_save_log_path} 2>&1 "
+ eval $infer_cpp_full_cmd
+ last_status=${PIPESTATUS[0]}
+ status_check $last_status "${infer_cpp_full_cmd}" "${status_log}"
+}
+
+echo "################### run test cpp inference ###################"
+
+func_infer_cpp
diff --git a/tutorials/tipc/README.md b/tutorials/tipc/README.md
index 962f5c1b..d9fb54dc 100644
--- a/tutorials/tipc/README.md
+++ b/tutorials/tipc/README.md
@@ -19,7 +19,7 @@
- 更多部署方式开发文档
- [Linux GPU/CPU PYTHON 服务化部署开发文档](./serving_python/README.md)
- Linux GPU/CPU C++ 服务化部署开发文档 (coming soon)
- - Linux GPU/CPU C++ 推理开发文档 (coming soon)
+ - [Linux GPU/CPU C++ 推理开发文档](./infer_cpp/README.md)
- Paddle.js 部署开发文档 (coming soon)
- [Paddle2ONNX 开发文档](./paddle2onnx/README.md)
- [Lite ARM CPU 部署开发文档](./lite_infer_cpp_arm_cpu/README.md)
diff --git a/tutorials/tipc/infer_cpp/README.md b/tutorials/tipc/infer_cpp/README.md
index 576dc4ec..aab19f5c 100644
--- a/tutorials/tipc/infer_cpp/README.md
+++ b/tutorials/tipc/infer_cpp/README.md
@@ -38,3 +38,12 @@ Paddle Inference 是飞桨的原生推理库, 作用于服务器端和云端
参考[C++推理文档开发文档](./infer_cpp.md)得到可执行的代码。
+## 3. C++推理功能测试开发与规范
+
+### 3.1 开发流程
+
+具体参考[C++推理功能测试开发文档](./test_infer_cpp.md)
+
+### 3.2 核验点
+
+具体参考[C++推理功能测试开发文档](./test_infer_cpp.md)
diff --git a/tutorials/tipc/infer_cpp/test_infer_cpp.md b/tutorials/tipc/infer_cpp/test_infer_cpp.md
index d8dc7821..e66544b7 100644
--- a/tutorials/tipc/infer_cpp/test_infer_cpp.md
+++ b/tutorials/tipc/infer_cpp/test_infer_cpp.md
@@ -2,7 +2,378 @@
# 目录
-- [1. 简介](#1---)
-- [2. 基本C++推理功能测试开发](#2---)
-- [3. 高级C++推理功能测试开发](#3---)
-- [4. FAQ](#4---)
+- [1. 简介](#1)
+- [2. 命令与配置文件解析](#2)
+ - [2.1 命令解析](#2.1)
+ - [2.2 配置文件和运行命令映射解析](#2.2)
+- [3. 基本C++推理功能测试开发](#3)
+ - [3.1 准备系统环境](#3.1)
+ - [3.2 准备输入数据和推理模型](#3.2)
+ - [3.3 准备推理所需代码](#3.3)
+ - [3.4 编译得到可执行代码](#3.4)
+ - [3.5 运行得到结果](#3.5)
+ - [3.6 填写配置文件](#3.6)
+ - [3.7 验证配置正确性](#3.7)
+ - [3.8 撰写说明文档](#3.8)
+- [4. FAQ](#4)
+
+
+
+## 1. 简介
+
+Paddle Inference 是飞桨的原生推理库, 作用于服务器端和云端,提供高性能的推理能力。相比于直接基于预训练模型进行预测,Paddle Inference可使用MKLDNN、CUDNN、TensorRT进行预测加速,从而实现更优的推理性能。
+更多关于Paddle Inference推理引擎的介绍,可以参考[Paddle Inference官网教程](https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/05_inference_deployment/inference/inference_cn.html)。
+本文档主要介绍飞桨模型在 Linux GPU/CPU 下基于C++预测引擎的推理过程开发。
+
+
+
+## 2. 命令与配置文件解析
+
+
+
+### 2.1 命令解析
+
+基于paddle inference的C++预测命令如下:
+```
+run_scripts configs_path img_path
+```
+
+* `run_scripts`:最终编译好的可执行命令。
+* `configs_path`:设置模型路径、是否使用GPU、是否开启mkldnn、是否开启TensorRT等。
+* `img_path`:待预测的图像路径。
+
+
+
+### 2.2 配置文件解析
+完整的`inference_cpp.txt`配置文件共有14行,包含两个方面的内容。
+* 运行环境参数配置:第1~8行
+* 模型参数配置:第10~14行
+
+具体内容见[inference_cpp.txt](../../mobilenetv3_prod/Step6/test_tipc/configs/mobilenet_v3_small/inference_cpp.txt)
+
+配置文件中主要有以下2种类型的字段。
+
+* 一行内容以空格为分隔符:该行可以被解析为`key value`的格式,需要根据实际的含义修改该行内容,下面进行详细说明。
+* 一行内容为`# xxxxx`:该行内容为注释信息,无需修改。
+
+配置参数(点击以展开详细内容或者折叠)
+
+
+| 行号 | 参考内容 | 含义 | key是否需要修改 | value是否需要修改 | 修改内容 |
+|----|-------------------------------------|---------------|-----------|-------------|----------------------------------|
+| 2 | use_gpu | 是否使用GPU | 否 | 是 | value根据是否使用GPU进行修改 |
+| 3 | gpu_id | 使用的GPU卡号 | 否 | 是 | value修改为自己的GPU ID |
+| 4 | gpu_mem | 显存 | 否 | 是 | value修改为自己的GPU 显存 |
+| 5 | cpu_math_library_num_thread | 底层科学计算库所用线程的数量 | 否 | 是 | value修改为合适的线程数 |
+| 6 | use_mkldnn | 是否使用MKLDNN加速 | 否 | 是 | value根据是否使用MKLDNN进行修改 |
+| 7 | use_tensorrt | 是否使用tensorRT进行加速 | 否 | 是 | value根据是否使用tensorRT进行修改 |
+| 8 | use_fp16 | 是否使用半精度浮点数进行计算,该选项仅在use_tensorrt为true时有效 | 否 | 是 | value根据在开启tensorRT时是否使用半精度进行修改|
+| 11 | cls_model_path | 预测模型结构文件路径 | 否 | 是 | value修改为预测模型结构文件路径 |
+| 12 | cls_params_path | 预测模型参数文件路径 | 否 | 是 | vvalue修改为预测模型参数文件路径 |
+| 13 | resize_short_size | 预处理时图像缩放大小 | 否 | 是 | value修改为预处理时图像缩放大小
+| 14 | crop_size | 预处理时图像裁剪后的大小 | 否 | 是 | value修改为预处理时图像裁剪后的大小
+
+
+