development_android.md 6.4 KB
Newer Older
R
Ruilong Liu 已提交
1
# Android开发文档
2

L
liuruilong 已提交
3
用户可通过如下两种方式进行编译:
W
wangliu 已提交
4

R
Ray Liu 已提交
5
- 基于macOS 、Linux交叉编译
W
wangliu 已提交
6 7
- 基于Docker容器编译

R
Ray Liu 已提交
8
## 基于macOS 、Linux交叉编译
L
liuruilong 已提交
9 10 11 12 13 14 15 16 17 18 19

需要: NDK17及以上、cmake 3.0及以上

### 执行编译
在paddle-mobile根目录中,执行以下命令:

```

cd tools
sh build.sh android

R
Ray Liu 已提交
20
# 如果想编译只支持某些特定网络的库 (可以控制包体积, 编译出来的库就只包含了支持这些特定模型的算子), 可以使用
L
liuruilong 已提交
21 22 23

sh build.sh android  mobilenet googlenet

L
liuruilong 已提交
24
# 当然这些网络是需要在 cmakelist  中配置的(https://github.com/PaddlePaddle/paddle-mobile/blob/73769e7d05ef4820a115ad3fb9b1ca3f55179d03/CMakeLists.txt#L216), 目前配置了几个常见模型
L
liuruilong 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90

```

执行完毕后,生成的so位于 build/release/ 目录中

jni 头文件位于 [https://github.com/PaddlePaddle/paddle-mobile/tree/develop/src/io/jni](https://github.com/PaddlePaddle/paddle-mobile/tree/develop/src/io/jni)

c++ 头文件位于 [https://github.com/PaddlePaddle/paddle-mobile/blob/develop/src/io/paddle_inference_api.h](https://github.com/PaddlePaddle/paddle-mobile/blob/develop/src/io/paddle_inference_api.h) 

单测可执行文件位于 test/build 目录中。

如果有环境问题, 可以看接下来的环节

### 环境配置

##### 下载Android NDK

如果你的电脑安装了Android Studio, 可以在 Android Studio 中直接下载安装 NDK

或者可以在 [https://developer.android.com/ndk/](https://developer.android.com/ndk/) 这里自行下载,也可以通过以下命令获取:

- Mac平台
```
wget https://dl.google.com/android/repository/android-ndk-r17b-darwin-x86_64.zip
unzip android-ndk-r17b-darwin-x86_64.zip

```
- Linux平台
```
wget https://dl.google.com/android/repository/android-ndk-r17b-linux-x86_64.zip
unzip android-ndk-r17b-linux-x86_64.zip
```

##### 设置环境变量
工程中自带的独立工具链会根据环境变量NDK_ROOT查找NDK,因此需要配置环境变量:

```
export NDK_ROOT = "path to ndk"
```

##### 安装 CMake

- Mac平台

mac 平台下可以使用 homebrew 安装

```
brew install cmake

```
- Linux平台

linux 下可以使用 apt-get 进行安装
```
apt-get install cmake

```

##### Tips:
如果想要获得体积更小的库,可选择编译支持指定模型结构的库。
如执行如下命令:

```
sh build.sh android googlenet
```
会得到一个支持googlnet的体积更小的库。
W
wangliu 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

## 基于Docker容器编译
### 1. 安装 docker
安装 docker 的方式,参考官方文档 [https://docs.docker.com/install/](https://docs.docker.com/install/)
### 2. 使用 docker 搭建构建环境
首先进入 paddle-mobile 的目录下,执行 `docker build`
以 Linux/Mac 为例 (windows 建议在 'Docker Quickstart Terminal' 中执行)

```
$ docker build -t paddle-mobile:dev - < Dockerfile
```
使用 `docker images` 可以看到我们新建的 image

```
$ docker images
REPOSITORY      TAG     IMAGE ID       CREATED         SIZE
paddle-mobile   dev     33b146787711   45 hours ago    372MB
```
### 3. 使用 docker 构建
进入 paddle-mobile 目录,执行 docker run

```
$ docker run -it --mount type=bind,source=$PWD,target=/paddle-mobile paddle-mobile:dev
root@5affd29d4fc5:/ # cd /paddle-mobile
# 生成构建 android 产出的 Makefile
root@5affd29d4fc5:/ # rm CMakeCache.txt
root@5affd29d4fc5:/ # cmake -DCMAKE_TOOLCHAIN_FILE=tools/toolchains/arm-android-neon.cmake
# 生成构建 linux 产出的 Makefile
root@5affd29d4fc5:/ # rm CMakeCache.txt
root@5affd29d4fc5:/ # cmake -DCMAKE_TOOLCHAIN_FILE=tools/toolchains/arm-linux-gnueabi.cmake
```
### 4. 设置编译选项
可以通过 ccmake 设置编译选项

```
root@5affd29d4fc5:/ # ccmake .
                                                     Page 1 of 1
 CMAKE_ASM_FLAGS
 CMAKE_ASM_FLAGS_DEBUG
 CMAKE_ASM_FLAGS_RELEASE
 CMAKE_BUILD_TYPE
 CMAKE_INSTALL_PREFIX             /usr/local
 CMAKE_TOOLCHAIN_FILE             /paddle-mobile/tools/toolchains/arm-android-neon.cmake
 CPU                              ON
 DEBUGING                         ON
 FPGA                             OFF
 LOG_PROFILE                      ON
 MALI_GPU                         OFF
 NET                              googlenet
 USE_EXCEPTION                    ON
 USE_OPENMP                       OFF
```
修改选项后,按 `c`, `g` 更新 Makefile
### 5. 构建
使用 make 命令进行构建

```
root@5affd29d4fc5:/ # make
```
### 6. 查看构建产出
构架产出可以在 host 机器上查看,在 paddle-mobile 的目录下,build 以及 test/build 下,可以使用 adb 指令或者 scp 传输到 device 上执行

R
Ray Liu 已提交
153
## 测试
W
wangliu 已提交
154
在编译完成后,我们提供了自动化的测试脚本,帮助用户将运行单测文件所需要的模型及库文件push到Android设备中,执行以下命令:
155

W
wangliu 已提交
156 157 158 159 160
```
cd tools/android-debug-script
sh run_on_android.sh (npm) 可选参数npm,用于选择是否传输模型文件到手机上
```
出现如下提示:
161

W
wangliu 已提交
162 163 164 165 166
```
**** choose OP or NET to test ****
which to test :
```
输入名称即可运行对应的测试文件。
167

R
Ray Liu 已提交
168
## 部署
W
wangliu 已提交
169
Android应用可通过JNI接口调用底层C/C++,paddle-mobile对外提供的JNI接口如下:
170

171 172
##### 1 load接口  加载模型参数
- 用于加载参数文件分散的模型
W
wangliu 已提交
173
```
174 175 176 177 178 179 180 181
/**
     * Load seperated parameters
     * @param modelDir
     * @return
     */
    public static native boolean load(String modelDir);
```
- 用于加载参数文件合并的模型文件
W
wangliu 已提交
182
```
183 184 185 186 187 188 189
/**
     * Load combined parameters
     * @param modelPath
     * @param paramPath
     * @return
     */
    public static native boolean loadCombined(String modelPath,String paramPath);
190

191
```
W
wangliu 已提交
192
##### 2 predict接口 执行预测
193
- 接受预处理过的RGB数组的predict接口
W
wangliu 已提交
194 195 196 197
```
/**
*@param buf 输入数据
*@return 输出数据
198
JNIEXPORT jfloatArray JNICALL Java_com_baidu_paddle_PML_predictImage(
W
wangliu 已提交
199 200
    JNIEnv *env, jclass thiz, jfloatArray buf);
```
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
- 接受原始yuv数据的predict接口
```
 /**
     *
     * @param buf yuv420格式的字节数组
     * @param imgWidth yuv数据的宽
     * @param imgHeight yuv数据的高
     * @param ddims 输入数据的形状
     * @param meanValues 模型训练时各通道的均值
     * @return
     */

    public static native float[] predictYuv(byte[] buf, int imgWidth, int imgHeight, int[] ddims, float[]meanValues);

```
W
wangliu 已提交
216
##### 3 clear接口 销毁实例、清理内存操作
217

W
wangliu 已提交
218 219 220 221
```
JNIEXPORT void JNICALL Java_com_baidu_paddle_PMLL_clear(JNIEnv *env,
                                                        jclass thiz);
```
222 223