未验证 提交 60210911 编写于 作者: H huzhiqiang 提交者: GitHub

add new features into doc ,new features include tailoring library、compiling x86、new API (#2312)

* add new features into documents: tailoring library according model, new API, x86_compiling test=develop
上级 b2fc597d
......@@ -245,8 +245,21 @@ config.set_model_dir(FLAGS_model_dir);
// 根据MobileConfig创建PaddlePredictor
std::shared_ptr<PaddlePredictor> predictor = CreatePaddlePredictor<MobileConfig>(config);
// 获得模型的输入和输出名称
std::vector<std::string> input_names = predictor->GetInputNames();
for (int i = 0; i < input_names.size(); i ++) {
printf("Input name[%d]: %s\n", i, input_names[i].c_str());
}
std::vector<std::string> output_names = predictor->GetOutputNames();
for (int i = 0; i < output_names.size(); i ++) {
printf("Output name[%d]: %s\n", i, output_names[i].c_str());
}
// 准备输入数据
// (1)根据index获取输入Tensor
std::unique_ptr<Tensor> input_tensor(std::move(predictor->GetInput(0)));
// (2)根据名称获取输入Tensor
// std::unique_ptr<Tensor> input_tensor(std::move(predictor->GetInputByName(input_names[0])));
input_tensor->Resize({1, 3, 224, 224});
auto* data = input_tensor->mutable_data<float>();
for (int i = 0; i < ShapeProduction(input_tensor->shape()); ++i) {
......@@ -257,7 +270,10 @@ for (int i = 0; i < ShapeProduction(input_tensor->shape()); ++i) {
predictor->Run();
// 获取输出
// (1)根据index获取输出Tensor
std::unique_ptr<const Tensor> output_tensor(std::move(predictor->GetOutput(0)));
// (2)根据名称获取输出Tensor
// std::unique_ptr<const Tensor> output_tensor(std::move(predictor->GetOutput(output_names[0])));
printf("Output dim: %d\n", output_tensor->shape()[1]);
for (int i = 0; i < ShapeProduction(output_tensor->shape()); i += 100) {
printf("Output[%d]: %f\n", i, output_tensor->data<float>()[i]);
......@@ -290,7 +306,53 @@ for (int i = 0; i < ShapeProduction(output_tensor->shape()); i += 100) {
返回类型:`std::unique_ptr<Tensor>`
## `GetInputNames()`
获取所有输入Tensor的名称。
参数:
- `None`
返回:所有输入Tensor的名称
返回类型:`std::vector<std::string>`
## `GetOutputNames()`
获取所有输出Tensor的名称。
参数:
- `None`
返回:所有输出Tensor的名称
返回类型:`std::vector<std::string>`
## `GetInputByName(name)`
根据名称获取输出Tensor的指针,用来获取模型的输出结果。
参数:
- `name(const std::string)` - 输入Tensor的名称
返回:输入Tensor`的指针
返回类型:`std::unique_ptr<Tensor>`
## `GetTensor(name)`
根据名称获取输出Tensor的指针。
参数:
- `name(const std::string)` - Tensor的名称
返回:指向`const Tensor`的指针
返回类型:`std::unique_ptr<const Tensor>`
## `Run()`
......
......@@ -30,6 +30,7 @@ Paddle-Lite 框架是 PaddleMobile 新一代架构,重点支持移动端推理
- [Java实例]({{site.baseurl}}/develop/java_demo)
- [Android/IOS APP demo](https://github.com/PaddlePaddle/Paddle-Lite-Demo)
- [模型转化方法]({{site.baseurl}}/develop/model_optimize_tool)
- [根据模型裁剪预测库方法]({{site.baseurl}}/develop/library_tailoring)
## 进阶
......
# 裁剪预测库方法
Paddle-Lite支持**根据模型裁剪预测库**功能。Paddle-Lite的一般编译会将所有已注册的operator打包到预测库中,造成库文件体积膨胀;**裁剪预测库**能针对具体的模型,只打包优化后该模型需要的operator,有效降低预测库文件大小。
#效果展示
| mobilenet_v1 | libpaddle_full_api_shared.so | libpaddle_light_api_shared.so | libpaddle_lite_jni.so |
| ------------------ | ---------------------------- | ----------------------------- | --------------------- |
| mobilenet_v1 | 14M | 14M | 6.2M |
| 裁剪后mobilenet_v1 | 7.7M | 7.5M | 2.5M |
#实现过程:
## 1、转化模型时记录优化后模型信息
说明:使用model_optimize_tool转化模型时,选择 `--record_tailoring_info =true` 会将优化后模型的OP和kernel信息保存到输出文件夹,这些信息将用于编译裁剪后的动态库。
注意:需要使用Paddle-Lite 最新版本(release/v2.0.0之后)代码编译出的model_optimize_tool
例如:
```
./model_optimize_tool --model_dir=./mobilenet_v1 --optimize_out_type=naive_buffer --optimize_out=mobilenet_v1NB --record_tailoring_info =true --valid_targets=arm
```
效果:优化后模型使用的OP和kernel信息被保存在 `mobilenet_v1NB`文件夹中的隐藏文件里了
##2、根据模型信息编译裁剪后的预测库
说明:编译Paddle-Lite时选择`--build_tailor=ON` ,并且用 `–-opt_model_dir=` 指定优化后的模型的地址
例如:
```
./lite/tools/build.sh --arm_os=android --arm_abi=armv7 --arm_lang=gcc --android_stl=c++_static --build_extra=ON --build_tailor=ON --opt_model_dir=../mobilenet_v1NB full_publish
```
**注意**:上面命令中的`../mobilenet_v1NB`是第1步得到的转化模型的输出路径
**效果**:编译出来的动态库文件变小,且可以运行优化后的模型。
| | libpaddle_full_api_shared.so | libpaddle_light_api_shared.so | libpaddle_lite_jni.so |
| ------------------ | ---------------------------- | ----------------------------- | --------------------- |
| mobilenet_v1 | 14M | 14M | 6.2M |
| 裁剪后mobilenet_v1 | 7.7M | 7.5M | 2.5M |
编译出的C++预测库文件位于 :
`build.lite.android.armv7.gcc/inference_lite_lib.android.armv7/cxx/lib/`
编译出的Java预测库文件位于:
`build.lite.android.armv7.gcc/inference_lite_lib.android.armv7/java/so/`
## 3、运行裁剪后的预测库文件
注意:基于某一模型裁剪出的预测库只能支持优化工具转化后的该模型,例如根据mobilenetV1裁剪出的 full_api预测库只能运行以protobuf格式转化出的模型mobilenetV1_opt_nb, 裁剪出的light_api预测库只能运行以naive_buffer格式转化出的模型mobilenetV1_opt_nb, 运行其他模型可能会出现`segementation fault:undifined op or kernel`。 模型转化方法参考:[使用model_optimize_tool转化模型](../model_optimize_tool))。
**示例1**:使用裁剪后的light_api预测库运行mobilenetv1
1、执行第二步编译后,light_api的C++ 示例位于
`/Paddle-Lite/build.lite.android.armv7.gcc/inference_lite_lib.android.armv7/demo/cxx/mobile_light`
输入`make`命令执行编译可编译出可执行文件mobilenetv1_light_api
2、使用adb将mobilenetV1_NB模型和mobilenetv1_light_api传到手机后执行demo:
`./mobilenetv1_light_api --model_dir=./mobilenetV1_NB`
注意:`mobilenetV1_NB`是用`mobilenetV1`模型转化的naive_buffer格式模型(不需要设置` --record_tailoring_info =true`,转化流程参考:[使用model_optimize_tool转化模型](../model_optimize_tool))。
**示例2**:使用裁剪后的full_api预测库运行mobilenetv1
1、执行第二步编译后,full_api的C++ 示例位于
`/Paddle-Lite/build.lite.android.armv7.gcc/inference_lite_lib.android.armv7/demo/cxx/mobile_light`
替换mobilenetv1_full_api.cc代码内容:
```C++
#include <gflags/gflags.h>
#include <stdio.h>
#include <vector>
#include "paddle_api.h" // NOLINT
#include "paddle_use_kernels.h" // NOLINT
#include "paddle_use_ops.h" // NOLINT
#include "paddle_use_passes.h" // NOLINT
using namespace paddle::lite_api; // NOLINT
DEFINE_string(model_dir, "", "Model dir path.");
int64_t ShapeProduction(const shape_t& shape) {
int64_t res = 1;
for (auto i : shape) res *= i;
return res;
}
void RunModel() {
// 1. Set CxxConfig
CxxConfig config;
config.set_model_file(FLAGS_model_dir + "model");
config.set_param_file(FLAGS_model_dir + "params");
std::vector<Place> valid_places{Place{TARGET(kARM), PRECISION(kFloat)}};
config.set_valid_places(valid_places);
// 2. Create PaddlePredictor by CxxConfig
std::shared_ptr<PaddlePredictor> predictor =
CreatePaddlePredictor<CxxConfig>(config);
// 3. Prepare input data
std::unique_ptr<Tensor> input_tensor(std::move(predictor->GetInput(0)));
input_tensor->Resize(shape_t({1, 3, 224, 224}));
auto* data = input_tensor->mutable_data<float>();
for (int i = 0; i < ShapeProduction(input_tensor->shape()); ++i) {
data[i] = 1;
}
// 4. Run predictor
predictor->Run();
// 5. Get output
std::unique_ptr<const Tensor> output_tensor(
std::move(predictor->GetOutput(0)));
printf("Output dim: %d\n", output_tensor->shape()[1]);
for (int i = 0; i < ShapeProduction(output_tensor->shape()); i += 100) {
printf("Output[%d]: %f\n", i, output_tensor->data<float>()[i]);
}
}
int main(int argc, char** argv) {
google::ParseCommandLineFlags(&argc, &argv, true);
RunModel();
return 0;
}
```
2、使用adb将mobilenetV1_PB模型和mobilenetv1_full_api传到手机后执行demo:
`./mobilenetv1_full_api --model_dir=./mobilenetV1_PB`
注意:`mobilenetV1_PB`是用`mobilenetV1`模型转化的protobuf格式模型(不需要设置` --record_tailoring_info =true`,转化流程参考:[使用model_optimize_tool转化模型](../model_optimize_tool))。
......@@ -50,7 +50,8 @@ fluid模型有两种形式,combined形式(权重保存为一个param文件
--optimize_out_type=(protobuf|naive_buffer) \
--optimize_out=<output_optimize_model_dir> \
--valid_targets=(arm|opencl|x86) \
--prefer_int8_kernel=(true|false)
--prefer_int8_kernel=(true|false) \
--record_tailoring_info =(true|false)
```
| 选项 | 说明 |
......@@ -62,7 +63,7 @@ fluid模型有两种形式,combined形式(权重保存为一个param文件
| --optimize_out | 优化模型的输出路径。 |
| --valid_targets | 指定模型可执行的backend,目前可支持x86、arm、opencl,您可以同时指定多个backend(以空格分隔),Model Optimize Tool将会自动选择最佳方式。默认为arm。 |
| --prefer_int8_kernel | 若待优化模型为int8量化模型(如量化训练得到的量化模型),则设置该选项为true以使用int8内核函数进行推理加速,默认为false。 |
| --record_tailoring_info | 当使用**根据模型裁剪库文件**功能时,则设置该选项为true,以记录优化后模型含有的kernel和OP信息,默认为false。 |
* 如果待优化的fluid模型是非combined形式,请设置`--model_dir`,忽略`--model_file``--param_file`
* 如果待优化的fluid模型是combined形式,请设置`--model_file``--param_file`,忽略`--model_dir`
* 优化后的模型包括__model__.nb和param.nb文件。
......@@ -183,7 +183,7 @@ sudo make install
至此,完成 Linux 交叉编译环境的准备。
### 3、Mac OS 开发环境(只支持 tiny publish 编译 )
### 3、Mac OS 开发环境
#### 交叉编译环境要求
......@@ -218,6 +218,12 @@ brew cask install java
至此,完成 Mac 交叉编译环境的准备。
#### Mac下Full Publish编译时需要**注意**
1. cmake版本需要为cmake 3.10
2. Paddle-Lite项目路径中不可以含有中文字符
3. 编译时如果报错: `Too many open files`
解决方法:修改mac电脑的 “程序可打开的最大文件数“,例如:`ulimit -n 1024`
## 二、编译PaddleLite
### 下载代码
......
......@@ -51,7 +51,7 @@ $ ./model_optimize_tool \
# 四. Lite API
为了方便您的使用,我们提供了C++与Java两种API,并且提供了相应的api使用的[完整示例](../demos),您可以参考示例中的说明快速了解C++/Java的API使用方法,并集成到您自己的项目中去。需要说明的是,为了减少第三方库的依赖、提高Lite预测框架的通用性,在移动端使用Lite API您需要准备Naive Buffer存储格式的模型,具体方法可参考第2节`模型优化`
为了方便您的使用,我们提供了C++与Java两种API,并且提供了相应的api使用的[C++完整示例](../cpp_demo)[Java完整示例](../java_demo),您可以参考示例中的说明快速了解C++/Java的API使用方法,并集成到您自己的项目中去。需要说明的是,为了减少第三方库的依赖、提高Lite预测框架的通用性,在移动端使用Lite API您需要准备Naive Buffer存储格式的模型,具体方法可参考第2节`模型优化`
# 五. 测试工具
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册