Are you sure you want to delete this task? Once this task is deleted, it cannot be recovered.
|
|
4 years ago | |
|---|---|---|
| .. | ||
| benchmark | 5 years ago | |
| src | 4 years ago | |
| CMakeLists.txt | 4 years ago | |
| README.md | 4 years ago | |
| mnist.sh | 5 years ago | |
| mnist_input.bin | 5 years ago | |
Linux IoT C++ 全流程 模型编译 模型代码生成 模型部署 推理应用 初级 中级 高级
本教程以MNIST分类模型推理代码为例,帮助用户了解codegen生成代码、编译构建、部署等流程。
用户可以使用脚本一键式编译生成MNIST分类模型的推理代码并执行推理,得到单次推理输出。下载MindSpore源码,进入mindspore/mindspore/lite/micro/examples/mnist_x86目录,执行脚本mnist.sh自动生成模型推理代码并编译工程目录,即可得到单次推理输出。
bash mnist.sh
推理结果如下:
======run benchmark======
input 0: mnist_input.bin
outputs:
name: Softmax-7, DataType: 43, Size: 40, Shape: [1 10], Data:
0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
======run success=======
也可以按照详细步骤从生成代码开始逐步完成使用codegen编译一个MNIST分类模型的全流程。
在编译此工程之前需要预先获取Ubuntu-x64 CPU平台的Release包,解压后得到mindspore-lite-{version}-linux-x64,将其拷贝到当前目录下。
{version}为版本号字符串,如1.2.0。
以本教程为例,预置x86平台的Release包目录如下:
mindspore-lite-{version}-linux-x64
└── tools
└── codegen # 代码生成工具
├── codegen # 可执行程序
├── include # 推理框架头文件
│ ├── nnacl # nnacl 算子头文件
│ └── wrapper
├── lib
│ └── libwrapper.a # MindSpore Lite CodeGen生成代码依赖的部分算子静态库
└── third_party
├── include
│ └── CMSIS # ARM CMSIS NN 算子头文件
└── lib
└── libcmsis_nn.a # ARM CMSIS NN 算子静态库
下载MNIST分类网络。使用Release包中的codegen编译MNIST分类模型,生成对应的x86平台推理代码。生成代码的具体命令如下:
./codegen --codePath=. --modelPath=mnist.ms --target=x86
codegen在当前目录下将生成mnist目录,其中包含了可编译构建的mnist分类模型的代码。
关于codegen的更多使用命令说明,可参见codegen使用说明。
接下来介绍如何构建MindSpore Lite CodeGen生成的模型推理代码工程,并在x86平台完成部署。上文中codegen生成的代码与mindspore/mindspore/lite/micro/example/mnist_x86相同,本章节编译、构建步骤将对该目录展开,用户也可参照相同操作,编译上文codegen生成mnist目录代码。
生成代码工程说明
进入mindspore/mindspore/lite/micro/example/mnist_x86目录中。
生成代码工程目录说明:
当前目录下预置了MNIST分类网络生成的代码。
mnist_x86/ # 生成代码的根目录
├── benchmark # 生成代码的benchmark目录
└── src # 模型推理代码目录
代码编译
组织模型生成的推理代码以及算子静态库,编译生成模型推理静态库并编译生成benchmark可执行文件,
进入代码工程目录下,新建并进入build目录:
mkdir build && cd build
开始编译:
cmake -DPKG_PATH={path to}/mindspore-lite-{version}-linux-x64 ..
make
{path to}和{version}需要用户根据实际情况填写。
代码工程编译成功结果:
Scanning dependencies of target net
[ 12%] Building C object src/CMakeFiles/net.dir/net.c.o
[ 25%] Building CXX object src/CMakeFiles/net.dir/session.cc.o
[ 37%] Building CXX object src/CMakeFiles/net.dir/tensor.cc.o
[ 50%] Building C object src/CMakeFiles/net.dir/weight.c.o
[ 62%] Linking CXX static library libnet.a
unzip raw static library libnet.a
raw static library libnet.a size:
-rw-r--r-- 1 user user 58K Mar 22 10:09 libnet.a
generate specified static library libnet.a
new static library libnet.a size:
-rw-r--r-- 1 user user 162K Mar 22 10:09 libnet.a
[ 62%] Built target net
Scanning dependencies of target benchmark
[ 75%] Building CXX object CMakeFiles/benchmark.dir/benchmark/benchmark.cc.o
[ 87%] Building C object CMakeFiles/benchmark.dir/benchmark/load_input.c.o
[100%] Linking CXX executable benchmark
[100%] Built target benchmark
此时在mnist_x86/build/src/目录下生成了libnet.a,推理执行库,在mnist_x86/build目录下生成了benchmark可执行文件。
代码部署
本示例部署于x86平台。由代码工程编译成功以后的产物为benchmark可执行文件,将其拷贝到用户的目标Linux服务器中即可执行。
在目标Linux服务上执行编译成功的二进制文件:
./benchmark mnist_input.bin net.bin
mnist_input.bin在
example/mnist_x86目录下,net.bin为模型参数文件,在example/mnist_x86/src目录下。
生成结果如下:
start run benchmark
input 0: mnist_input.bin
output size: 1
uint8:
Name: Softmax-7, DataType: 43, Size: 40, Shape: 1 10, Data:
0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
run benchmark success
本教程中的benchmark内部实现主要用于指导用户如何编写以及调用codegen编译的模型推理代码接口。以下为接口调用的详细介绍,详情代码可以参见examples/mnist_x86下的示例代码示例:
构建推理的上下文以及会话
本教程生成的代码为非并行代码,无需上下文context,可直接设为空。
size_t model_size = 0;
Context *context = nullptr;
session::LiteSession *session = mindspore::session::LiteSession::CreateSession(model_buffer, model_size, context);
if (session == nullptr) {
std::cerr << "create lite session failed" << std::endl;
return RET_ERROR;
}
输入数据准备
用户所需要准备的输入数据内存空间,若输入是持久化文件,可通过读文件方式获取。若输入数据已经存在内存中,则此处无需读取,可直接传入数据指针。
std::vector<MSTensor *> inputs = session->GetInputs();
MSTensor *input = inputs.at(0);
if (input == nullptr) {
return RET_ERROR;
}
// Assume we have got input data in memory.
memcpy(input->MutableData(), input_buffer, input->Size());
执行推理
session->RunGraph();
推理结束获取输出
Vector<String> outputs_name = session->GetOutputTensorNames();
for (const auto &name : outputs_name) {
auto output = session->GetOutputByTensorName(name);
// deal with output
......
}
释放内存session
delete session;
推理代码整体调用流程
// Assume we have got model_buffer data in memory.
size_t model_size = 0;
Context *context = nullptr;
session::LiteSession *session = mindspore::session::LiteSession::CreateSession(model_buffer, model_size, context);
if (session == nullptr) {
std::cerr << "create lite session failed" << std::endl;
return RET_ERROR;
}
std::vector<MSTensor *> inputs = session->GetInputs();
MSTensor *input = inputs.at(0);
if (input == nullptr) {
return RET_ERROR;
}
// Assume we have got input data in memory.
memcpy(input->MutableData(), input_buffer, input->Size());
session->RunGraph();
Vector<String> outputs_name = session->GetOutputTensorNames();
for (const auto &name : outputs_name) {
auto output = session->GetOutputByTensorName(name);
// deal with output
......
}
delete session;
阿对对队
C++ Python Text C Unity3D Asset other