!13882 add README for mobilenetv2

From: @zoloft
Reviewed-by: @wangchengyuan,@zhujingxuan,@hangangqiang,@zhanghaibo5
Signed-off-by: @wangchengyuan
pull/13882/MERGE
mindspore-ci-bot 4 years ago committed by Gitee
commit 159071d438

@ -125,12 +125,10 @@ int main(void) {
if (output_tensor == nullptr) {
return -1;
}
SEGGER_RTT_printf(0, "***********mnist test start5.2***********\n");
float *casted_data = static_cast<float *>(output_tensor->MutableData());
if (casted_data == nullptr) {
return -1;
}
SEGGER_RTT_printf(0, "***********mnist test start5.3***********\n");
for (size_t j = 0; j < 10 && j < output_tensor->ElementsNum(); j++) {
SEGGER_RTT_printf(0, "output: [%d] is : [%d]/100\n", i, casted_data[i] * 100);
}

@ -1,3 +1,5 @@
# Arm Cortex-M编译部署
`Linux` `Cortex-M` `IOT` `C/C++` `全流程` `模型编译` `模型代码生成` `模型部署` `推理应用` `初级` `中级` `高级`
@ -9,8 +11,8 @@
- [STM32F746构建](#STM32F746构建)
- [STM32F746工程部署](#STM32F746工程部署)
- [更多详情](#更多详情)
- [Linux x86_64平台编译部署](#Linux x86_64平台编译部署)
- [Android平台编译部署](#STM32746平台编译部署)
- [Linux_x86_64编译部署](#Linux_x86_64编译部署)
- [Android平台编译部署](#Android平台编译部署)
<!-- /TOC -->
@ -30,39 +32,45 @@
- [GCC](https://gcc.gnu.org/releases.html) >= 7.3.0
- [CMake](https://cmake.org/download/) >= 3.18.3
### STM32F746构建与运行
### STM32F746构建
首先使用codegen编译LeNet模型生成对应的STM32F46推理代码。具体命令如下
首先使用codegen编译MNIST手写数字识别模型生成对应的STM32F46推理代码。具体命令如下
```bash
./codegen --codePath=. --modelPath=LeNet.ms --moduleName=LeNet --target=ARM32M
./codegen --codePath=. --modelPath=mnist.ms --target=ARM32M
```
#### 代码工程说明
```bash
├── LeNet
├── MNIST
└── include # 模型推理对外API头文件目录
└── operator_library
```
##### 算子静态库目录说明
##### 算子相关目录说明
在编译此工程之前需要预先获取Cortex-M 平台对应的[算子库]()
在编译此工程之前需要预先获取对应平台所需要的算子文件由于Cortex-M平台工程编译一般涉及到较复杂的交叉编译此处不提供直接预编译的算子库静态库而是用户根据模型自行组织文件自主编译Cortex-M7 、Coretex-M4、Cortex-M3等工程
预置算子静态库的目录如下:
```bash
├── operator_library # 对应平台算子库目录
├── include # 对应平台算子库头文件目录
└── lib # 对应平台算子库静态库目录
└── nnacl # 对应mindspore团队提供的平台算子库源文件
└── wrapper # 对应mindspore团队提供的平台算子库源文件
└── CMSIS # 对应Arm官方提供的CMSIS平台算子库源文件
```
生成代码工程目录如下:
模型推理对外API头文件可由mindspore团队发布的[Release包](https://www.mindspore.cn/tutorial/lite/zh-CN/master/use/downloads.html)中获取。
```bash
├── LeNet # 生成代码的根目录
├── MNIST # 生成代码的根目录
├── benchmark # 生成代码的benchmark目录
├── include # 模型推理代码对外暴露头文件目录
└── src # 模型推理代码目录
```
@ -81,7 +89,7 @@ make -v # 查看make版本
以上的命令均有成功返回值时表明环境准备ok可以继续进入下一步否则先安装上述环境
##### 生成STM32F746单板初始化代码([详情示例代码]())
##### 生成STM32F746单板初始化代码([详情示例代码](https://gitee.com/mindspore/mindspore/tree/master/mindspore/lite/micro/example/mnist_stm32f746))
1. 启动 STM32CubeMX新建project选择单板STM32F746IG
@ -98,26 +106,25 @@ make -v # 查看make版本
arm-none-eabi-objcopy -O binary -S build/test_stm32f746.elf build/test_stm32f746.bin
```
##### 编译生成模型静态库
##### 编译模型
1. 拷贝mindspore团队提供的cortex-m7的算子静态库以及对应头文件到STM32CubeMX生成的工程目录中。
1. 拷贝mindspore团队提供算子文件以及对应头文件到STM32CubeMX生成的工程目录中。
2. 拷贝codegen生成模型推理代码到 STM32CubeMX生成的代码工程目录中
```bash
├── .mxproject
└── build # 工程编译目录最终的elf文件存在于此
└── build # 工程编译输出目录
└── Core
└── Drivers
└── LeNet # codegen生成的cortex-m7 模型推理代码
└── Makefile # 组织工程makefile文件需要用户自己修改组织lenet && operator_library到工程目录中
└── operator_library # mindspore团队提供的对应平台算子库
└── mnist # codegen生成的cortex-m7 模型推理代码
└── Makefile # 组织工程makefile文件需要用户自己修改组织mnist && operator_library到工程目录中
└── startup_stm32f746xx.s
└── STM32F746IGKx_FLASH.ld
└── test_stm32f746.ioc
```
3. 修改makefile文件组织算子静态库以及模型推理代码
3. 修改makefile文件组织算子静态库以及模型推理代码,具体makefile文件内容参见[示例](https://gitee.com/mindspore/mindspore/tree/master/mindspore/lite/micro/example/mnist_stm32f746)。
```bash
# C includes
@ -126,17 +133,53 @@ make -v # 查看make版本
-IDrivers/STM32F7xx_HAL_Driver/Inc \
-IDrivers/STM32F7xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS/Device/ST/STM32F7xx/Include \
-Ioperator_library/include \ # 新增,指定算子库头文件目录
-ILeNet/include \ # 新增,指定模型推理代码头文件
-ILeNet/src # 新增,指定模型推理代码头文件
# libraries
LIBS = -lc -lm -lnosys -lops # 修改导入mindspore团队提供算子库
LIBDIR = -Ioperator_library/lib/arm32m # 新增,指定算子库所在路径
-Imnist/operator_library/include \ # 新增,指定算子库头文件目录
-Imnist/include \ # 新增,指定模型推理代码头文件
-Imnist/src # 新增,指定模型推理代码头文件
```
4. 在工程目录的Core/Src的main.c编写模型调用代码具体代码新增如下
```cpp
while (1) {
/* USER CODE END WHILE */
SEGGER_RTT_printf(0, "***********mnist test start***********\n");
const char *model_buffer = nullptr;
int model_size = 0;
session::LiteSession *session = mindspore::session::LiteSession::CreateSession(model_buffer, model_size, nullptr);
Vector<tensor::MSTensor *> inputs = session->GetInputs();
size_t inputs_num = inputs.size();
void *inputs_binbuf[inputs_num];
int inputs_size[inputs_num];
for (size_t i = 0; i < inputs_num; ++i) {
inputs_size[i] = inputs[i]->Size();
}
// here mnist only have one input data,just hard code to it's array;
inputs_binbuf[0] = mnist_inputs_data;
for (size_t i = 0; i < inputs_num; ++i) {
void *input_data = inputs[i]->MutableData();
memcpy(input_data, inputs_binbuf[i], inputs_size[i]);
}
int ret = session->RunGraph();
if (ret != lite::RET_OK) {
return lite::RET_ERROR;
}
Vector<String> outputs_name = session->GetOutputTensorNames();
for (int i = 0; i < outputs_name.size(); ++i) {
tensor::MSTensor *output_tensor = session->GetOutputByTensorName(outputs_name[i]);
if (output_tensor == nullptr) {
return -1;
}
float *casted_data = static_cast<float *>(output_tensor->MutableData());
if (casted_data == nullptr) {
return -1;
}
for (size_t j = 0; j < 10 && j < output_tensor->ElementsNum(); j++) {
SEGGER_RTT_printf(0, "output: [%d] is : [%d]/100\n", i, casted_data[i] * 100);
}
}
delete session;
SEGGER_RTT_printf(0, "***********mnist test end***********\n");
```
5. 在工程跟目中目录使用管理员权限打开`cmd` 执行 `make`进行编译
@ -161,14 +204,9 @@ load # 加载可执行文件到单板
c # 执行模型推理
```
#### 执行结果
```bash
```
## 更多详情
### [Linux x86_64平台编译部署]()
### [Linux_x86_64平台编译部署](https://www.mindspore.cn/tutorial/lite/zh-CN/master/quick_start/quick_start_codegen.html)
### [Android平台编译部署]()
### [Android平台编译部署](https://gitee.com/mindspore/mindspore/tree/master/mindspore/lite/micro/example/mobilenetv2)

@ -1,174 +0,0 @@
# Arm Cortex-M编译部署
`Linux` `Cortex-M` `IOT` `C/C++` `全流程` `模型编译` `模型代码生成` `模型部署` `推理应用` `初级` `中级` `高级`
<!-- TOC -->
- Arm Cortex-M编译部署
- [STM32F746编译依赖](#STM32F746编译依赖)
- [STM32F746构建](#STM32F746构建)
- [STM32F746工程部署](#STM32F746工程部署)
- [更多详情](#更多详情)
- [Linux x86_64平台编译部署](#Linux x86_64平台编译部署)
- [Android平台编译部署](#STM32746平台编译部署)
<!-- /TOC -->
## Arm Cortex-M编译部署
本教程以在STM32F746单板上编译部署生成模型代码为例演示了codegen编译模型在Cortex-M平台的使用。更多关于Arm Cortex-M的详情可参见其[官网](https://developer.arm.com/ip-products/processors/cortex-m)。
### STM32F746编译依赖
模型推理代码的编译部署需要在windows上安装[Jlink]((https://www.segger.com/))、[STM32CubeMX](https://www.st.com/content/st_com/en.html)、[gcc-arm-none-ebai](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm)等工具来进行交叉编译。
- [STM32CubeMX-Win](https://www.st.com/content/ccc/resource/technical/software/sw_development_suite/group0/0b/05/f0/25/c7/2b/42/9d/stm32cubemx_v6-1-1/files/stm32cubemx_v6-1-1.zip/jcr:content/translations/en.stm32cubemx_v6-1-1.zip) >= 6.0.1
- [gcc-arm-none-eabi](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) >= 9-2019-q4-major-win32
- [JLink-windows](https://www.segger.com/downloads/jlink/) >= 6.56
- [GCC](https://gcc.gnu.org/releases.html) >= 7.3.0
- [CMake](https://cmake.org/download/) >= 3.18.3
### STM32F746构建与运行
首先使用codegen编译LeNet模型生成对应的STM32F46推理代码。具体命令如下
```bash
./codegen --codePath=. --modelPath=LeNet.ms --moduleName=LeNet --target=ARM32M
```
#### 代码工程说明
```bash
├── LeNet
└── operator_library
```
##### 算子静态库目录说明
在编译此工程之前需要预先获取Cortex-M 平台对应的[算子库]()。
预置算子静态库的目录如下:
```bash
├── operator_library # 对应平台算子库目录
├── include # 对应平台算子库头文件目录
└── lib # 对应平台算子库静态库目录
```
生成代码工程目录如下:
```bash
├── LeNet # 生成代码的根目录
├── benchmark # 生成代码的benchmark目录
├── include # 模型推理代码对外暴露头文件目录
└── src # 模型推理代码目录
```
#### 代码工程编译
##### 环境测试
安装好交叉编译所需环境后需要在windows环境中依次将其加入到环境变量中
```bash
gcc -v # 查看GCC版本
arm-none-eabi-gdb -v # 查看交叉编译环境
jlink -v # 查看jlink版本
make -v # 查看make版本
```
以上的命令均有成功返回值时表明环境准备ok可以继续进入下一步否则先安装上述环境
##### 生成STM32F746单板初始化代码([详情示例代码]())
1. 启动 STM32CubeMX新建project选择单板STM32F746IG
2. 成功以后,选择`Makefile` `generator code`
3. 在生成的工程目录下打开`cmd`,执行`make`,测试初始代码是否成功编译。
```bash
# make成功结果
arm-none-eabi-size build/test_stm32f746.elf
text data bss dec hex filename
3660 20 1572 5252 1484 build/test_stm32f746.elf
arm-none-eabi-objcopy -O ihex build/test_stm32f746.elf build/test_stm32f746.hex
arm-none-eabi-objcopy -O binary -S build/test_stm32f746.elf build/test_stm32f746.bin
```
##### 编译生成模型静态库
1. 拷贝mindspore团队提供的cortex-m7的算子静态库以及对应头文件到STM32CubeMX生成的工程目录中。
2. 拷贝codegen生成模型推理代码到 STM32CubeMX生成的代码工程目录中
```bash
├── .mxproject
└── build # 工程编译目录最终的elf文件存在于此
└── Core
└── Drivers
└── LeNet # codegen生成的cortex-m7 模型推理代码
└── Makefile # 组织工程makefile文件需要用户自己修改组织lenet && operator_library到工程目录中
└── operator_library # mindspore团队提供的对应平台算子库
└── startup_stm32f746xx.s
└── STM32F746IGKx_FLASH.ld
└── test_stm32f746.ioc
```
3. 修改makefile文件组织算子静态库以及模型推理代码
```bash
# C includes
C_INCLUDES = \
-ICore/Inc \
-IDrivers/STM32F7xx_HAL_Driver/Inc \
-IDrivers/STM32F7xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS/Device/ST/STM32F7xx/Include \
-Ioperator_library/include \ # 新增,指定算子库头文件目录
-ILeNet/include \ # 新增,指定模型推理代码头文件
-ILeNet/src # 新增,指定模型推理代码头文件
# libraries
LIBS = -lc -lm -lnosys -lops # 修改导入mindspore团队提供算子库
LIBDIR = -Ioperator_library/lib/arm32m # 新增,指定算子库所在路径
```
4. 在工程目录的Core/Src的main.c编写模型调用代码具体代码新增如下
```cpp
```
5. 在工程跟目中目录使用管理员权限打开`cmd` 执行 `make`进行编译
```bash
make
```
### STM32F746工程部署
使用jlink 将可执行文件拷贝到单板上并做推理
```bash
jlinkgdbserver # 启动jlinkgdbserver 选定target device为STM32F746IG
jlinkRTTViewer # 启动jlinkRTTViewer 选定target devices为STM32F746IG
arm-none-eabi-gdb # 启动arm-gcc gdb服务
file build/target.elf # 打开调测文件
target remote 127.0.0.1 # 连接jlink服务器
monitor reset # 重置单板
monitor halt # 挂起单板
load # 加载可执行文件到单板
c # 执行模型推理
```
#### 执行结果
```bash
```
## 更多详情
### [Linux x86_64平台编译部署]()
### [Android平台编译部署]()

@ -1,55 +1,61 @@
# Android编译部署
`Linux` `Cortex-M` `IOT` `C/C++` `全流程` `模型编译` `模型代码生成` `模型部署` `推理应用` `初级` `中级` `高级`
`Linux` `Android` `IOT` `C/C++` `全流程` `模型编译` `模型代码生成` `模型部署` `推理应用` `初级` `中级` `高级`
<!-- TOC -->
- Arm Cortex-M编译部署
- [STM32F746编译依赖](#STM32F746编译依赖)
- [STM32F746构建](#STM32F746构建)
- [STM32F746工程部署](#STM32F746工程部署)
- Android编译部署
- [编译依赖](#编译依赖)
- [工程构建](#工程构建)
- [工程部署](#工程部署)
- [更多详情](#更多详情)
- [Linux x86_64平台编译部署](#Linux x86_64平台编译部署)
- [Android平台编译部署](#STM32746平台编译部署)
- [Linux_x86_64编译部署](#Linux_x86_64编译部署)
- [STM32F746编译部署](#STM32F746编译部署)
<!-- /TOC -->
## Arm Cortex-M编译部署
## Android编译部署
本教程以在STM32F746单板上编译部署生成模型代码为例演示了codegen编译模型在Cortex-M平台的使用。更多关于Arm Cortex-M的详情可参见其[官网](https://developer.arm.com/ip-products/processors/cortex-m)。
本教程以MobileNetv2在安卓手机编译部署为例使用用户快速了解codegen在安卓平台生成代码、工程构建以及部署的一系列流程。关于converter、codegen的获取以及详细参数介绍可参考mindspore的[编译构建介绍](https://www.mindspore.cn/tutorial/lite/zh-CN/master/use/build.html)。
### STM32F746编译依赖
### 编译依赖
模型推理代码的编译部署需要在windows上安装[Jlink]((https://www.segger.com/))、[STM32CubeMX](https://www.st.com/content/st_com/en.html)、[gcc-arm-none-ebai](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm)等工具来进行交叉编译
安卓平台的编译部署需要提前配置ANDROID_NDK到环境变量
- [STM32CubeMX-Win](https://www.st.com/content/ccc/resource/technical/software/sw_development_suite/group0/0b/05/f0/25/c7/2b/42/9d/stm32cubemx_v6-1-1/files/stm32cubemx_v6-1-1.zip/jcr:content/translations/en.stm32cubemx_v6-1-1.zip) >= 6.0.1
- [gcc-arm-none-eabi](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) >= 9-2019-q4-major-win32
- [JLink-windows](https://www.segger.com/downloads/jlink/) >= 6.56
- NDK 21.3
- [GCC](https://gcc.gnu.org/releases.html) >= 7.3.0
- [CMake](https://cmake.org/download/) >= 3.18.3
### STM32F746构建与运行
### 工程构建
#### 快速使用
首先使用codegen编译LeNet模型生成对应的STM32F46推理代码。具体命令如下
进入`mindspore/mindspore/lite/micro/examples/mobilenetv2`目录执行脚本`mobilenetv2.sh`自动生成模型推理代码并编译工程目录
```
bash mobilenetv2.sh
```
codegen编译MobileNetv2模型生成对应的模型推理代码。具体命令如下
```bash
./codegen --codePath=. --modelPath=LeNet.ms --moduleName=LeNet --target=ARM32M
./codegen --codePath=. --modelPath=mobilenetv2.ms --target=ARM64
```
#### 代码工程说明
关于codegen的更多使用命令说明可参见[codegen工具的详细介绍](https://www.mindspore.cn/tutorial/lite/zh-CN/master/use/downloads.html)
#### 生成代码工程说明
```bash
├── LeNet
├── mobilenetv2
└── operator_library
```
##### 算子静态库目录说明
在编译此工程之前需要预先获取Cortex-M 平台对应的[算子库]()。
在编译此工程之前需要预先获取安卓平台对应的[Release包](https://www.mindspore.cn/tutorial/lite/zh-CN/master/use/downloads.html)。
预置算子静态库的目录如下:
算子静态库的目录如下:
```bash
├── operator_library # 对应平台算子库目录
@ -60,7 +66,7 @@
生成代码工程目录如下:
```bash
├── LeNet # 生成代码的根目录
├── mobilenetv2 # 生成代码的根目录
├── benchmark # 生成代码的benchmark目录
├── include # 模型推理代码对外暴露头文件目录
└── src # 模型推理代码目录
@ -68,107 +74,46 @@
#### 代码工程编译
##### 环境测试
组织生成的模型推理代码以及安卓平台算子静态库编译模型推理静态库
安装好交叉编译所需环境后需要在windows环境中依次将其加入到环境变量中
进入代码工程目录新建并进入build目录
```bash
gcc -v # 查看GCC版本
arm-none-eabi-gdb -v # 查看交叉编译环境
jlink -v # 查看jlink版本
make -v # 查看make版本
mkdir mobilenetv2/build && cd mobilenetv2/build
```
以上的命令均有成功返回值时表明环境准备ok可以继续进入下一步否则先安装上述环境
##### 生成STM32F746单板初始化代码([详情示例代码]())
1. 启动 STM32CubeMX新建project选择单板STM32F746IG
2. 成功以后,选择`Makefile` `generator code`
开始编译
3. 在生成的工程目录下打开`cmd`,执行`make`,测试初始代码是否成功编译。
```bash
# make成功结果
arm-none-eabi-size build/test_stm32f746.elf
text data bss dec hex filename
3660 20 1572 5252 1484 build/test_stm32f746.elf
arm-none-eabi-objcopy -O ihex build/test_stm32f746.elf build/test_stm32f746.hex
arm-none-eabi-objcopy -O binary -S build/test_stm32f746.elf build/test_stm32f746.bin
```
##### 编译生成模型静态库
1. 拷贝mindspore团队提供的cortex-m7的算子静态库以及对应头文件到STM32CubeMX生成的工程目录中。
2. 拷贝codegen生成模型推理代码到 STM32CubeMX生成的代码工程目录中
```bash
├── .mxproject
└── build # 工程编译目录最终的elf文件存在于此
└── Core
└── Drivers
└── LeNet # codegen生成的cortex-m7 模型推理代码
└── Makefile # 组织工程makefile文件需要用户自己修改组织lenet && operator_library到工程目录中
└── operator_library # mindspore团队提供的对应平台算子库
└── startup_stm32f746xx.s
└── STM32F746IGKx_FLASH.ld
└── test_stm32f746.ioc
```
3. 修改makefile文件组织算子静态库以及模型推理代码
```bash
# C includes
C_INCLUDES = \
-ICore/Inc \
-IDrivers/STM32F7xx_HAL_Driver/Inc \
-IDrivers/STM32F7xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS/Device/ST/STM32F7xx/Include \
-Ioperator_library/include \ # 新增,指定算子库头文件目录
-ILeNet/include \ # 新增,指定模型推理代码头文件
-ILeNet/src # 新增,指定模型推理代码头文件
# libraries
LIBS = -lc -lm -lnosys -lops # 修改导入mindspore团队提供算子库
LIBDIR = -Ioperator_library/lib/arm32m # 新增,指定算子库所在路径
```
4. 在工程目录的Core/Src的main.c编写模型调用代码具体代码新增如下
```cpp
```
```bash
cmake -DPKG_PATH={path to}/mindspore-lite-{version}-inference-linux-x64 ..
make
```
5. 在工程跟目中目录使用管理员权限打开`cmd` 执行 `make`进行编译
`{path to}`和`{version}`需要用户根据实际情况填写。
```bash
make
```
此时在`mnist/build/src/`目录下生成了`libnet.a`,推理执行库,在`mnist/build`目录下生成了`benchmark`可执行文件。而对应的模型参数文件net.bin在生成的代码src目录下。
### STM32F746工程部署
### 工程部署
使用jlink 将可执行文件拷贝到单板上并做推理
adb将生成的可执行二进制文件benchmark、mobilenetv2_input.bin以及模型参数文件net.bin拷贝到目标安卓服务器执行以下命令即可
```bash
jlinkgdbserver # 启动jlinkgdbserver 选定target device为STM32F746IG
jlinkRTTViewer # 启动jlinkRTTViewer 选定target devices为STM32F746IG
arm-none-eabi-gdb # 启动arm-gcc gdb服务
file build/target.elf # 打开调测文件
target remote 127.0.0.1 # 连接jlink服务器
monitor reset # 重置单板
monitor halt # 挂起单板
load # 加载可执行文件到单板
c # 执行模型推理
./benchmark mobilenetv2_input.bin net.bin 100
```
#### 执行结果
```bash
=========run benchmark========
input 0: mobilenetv2_input.bin
name: Softmax-65, ,DataType: 43, Size: 4004, Shape:1 1001, Data:
0.000010,0.000010,0.000014,0.000091,0.000080,0.000717,0.000112,0.000738,0.000008,0.000003
=========run success========
```
## 更多详情
### [Linux x86_64平台编译部署]()
### [Linux_x86_64编译部署](https://www.mindspore.cn/tutorial/lite/zh-CN/master/quick_start/quick_start_codegen.html)
### [Android平台编译部署]()
### [STM32F746编译部署](https://gitee.com/mindspore/mindspore/tree/master/mindspore/lite/micro/example/mnist_stm32f746)

Loading…
Cancel
Save