From 11733d33a414435340e124d384d537a8de2c20a1 Mon Sep 17 00:00:00 2001 From: Liangliang He Date: Thu, 3 May 2018 19:48:30 +0800 Subject: [PATCH] Update documents --- README.md | 66 ++- docs/release_note.md => RELEASE.md | 2 +- docs/README | 8 +- docs/conf.py | 2 +- docs/developer/adding_a_new_op.md | 100 ----- docs/developer/logging.md | 9 - docs/developer/opencl_memory_layout.md | 59 --- docs/development/adding_a_new_op.md | 97 +++++ docs/development/contributing.md | 52 +++ docs/development/memory_layout.rst | 99 +++++ docs/docker/usage.md | 27 -- docs/faq.md | 50 +++ .../create_a_model_deployment.rst | 105 +++++ docs/getting_started/docker.rst | 19 + docs/getting_started/how_to_build.rst | 259 +++++++++++ docs/getting_started/introduction.md | 8 + docs/getting_started/op_lists.rst | 82 ++++ docs/getting_started/workflow.jpg | Bin 0 -> 119085 bytes docs/index.rst | 38 +- docs/user/introduction.md | 409 ------------------ 20 files changed, 862 insertions(+), 629 deletions(-) rename docs/release_note.md => RELEASE.md (82%) delete mode 100644 docs/developer/adding_a_new_op.md delete mode 100644 docs/developer/logging.md delete mode 100644 docs/developer/opencl_memory_layout.md create mode 100644 docs/development/adding_a_new_op.md create mode 100644 docs/development/contributing.md create mode 100644 docs/development/memory_layout.rst delete mode 100644 docs/docker/usage.md create mode 100644 docs/faq.md create mode 100644 docs/getting_started/create_a_model_deployment.rst create mode 100644 docs/getting_started/docker.rst create mode 100644 docs/getting_started/how_to_build.rst create mode 100644 docs/getting_started/introduction.md create mode 100644 docs/getting_started/op_lists.rst create mode 100644 docs/getting_started/workflow.jpg delete mode 100644 docs/user/introduction.md diff --git a/README.md b/README.md index 0feb59e8..eb431878 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,65 @@ -# **MACE** - *Mobile(Mi) Accelerated Compute Engine Library* +# MiAI Compute Engine +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) [![build status](http://v9.git.n.xiaomi.com/deep-computing/mace/badges/master/build.svg)](http://v9.git.n.xiaomi.com/deep-computing/mace/pipelines) -## Introduction -**Accelerating Neural Network with Heterogeneous Computing Devices in the phone.** +[Documentation](docs) | +[FAQ](docs/faq.md) | +[Release Notes](RELEASE.md) | +[MiAI Model Zoo](http://v9.git.n.xiaomi.com/deep-computing/mace-models) | +[Demo](mace/android) -Supported Devices: **CPU(NEON)/GPU/DSP**. +**MiAI Compute Engine** is a deep learning inference framework optimized for +mobile heterogeneous computing platforms. The design is focused on the following +targets: +* Performance + * The runtime is highly optimized with NEON, OpenCL and HVX. Except for the + inference speed, the initialization speed is also intensively optimized. +* Power consumption + * Chip dependent power options are included as advanced API. +* Memory usage and library footprint + * Graph level memory allocation optimization and buffer reuse is supported. +* Model protection + * Model protection is one the highest priority feature from the beginning of + the design. Various techniques are introduced like coverting models to C++ + code and literal obfuscations. +* Platform coverage + * A good coverage of recent Qualcomm, MediaTek, Pinecone and other ARM based + chips. CPU runtime is also compitable with most POSIX systems and + archetectures with limited performance. -## User Guide +## Getting Started -wiki url: [http://v9.git.n.xiaomi.com/deep-computing/mace/wikis/User%20Guide/introduction](http://v9.git.n.xiaomi.com/deep-computing/mace/wikis/User%20Guide/introduction) +## Performance +[MiAI Model Zoo](http://v9.git.n.xiaomi.com/deep-computing/mace-models) contains +several common neural networks models and built daily against several mobile +phones. The benchmark result can be found in the CI result page. + +## Communication +* GitHub issues: bug reports, usage issues, feature requests +* Gitter or Slack: +* QQ群: + +## Contributing +Any kind of contributions are welcome. For bug reports, feature requests, +please just open an issue without any hesitance. For code contributions, it's +strongly suggested to open an issue for discussion first. For more details, +please refer to [this guide](docs). + +## License +[Apache License 2.0](LICENSE). + +## Acknowledgement +*MiAI Compute Engine* depends on several open source projects located in +[third_party](mace/third_party) directory. Particularly, we learned a lot from +the following projects during the development: +* [nnlib](https://source.codeaurora.org/quic/hexagon_nn/nnlib): the DSP runtime + depends on this library. +* [TensorFlow](https://github.com/tensorflow/tensorflow), + [Caffe](https://github.com/BVLC/caffe), + [SNPE](https://developer.qualcomm.com/software/snapdragon-neural-processing-engine-ai), + [ARM ComputeLibrary](https://github.com/ARM-software/ComputeLibrary), + [ncnn](https://github.com/Tencent/ncnn) and many others: we learned many best + practices from these projects. + +Finally, we also thank the Qualcomm, Pinecone and MediaTek engineering teams for +their helps. diff --git a/docs/release_note.md b/RELEASE.md similarity index 82% rename from docs/release_note.md rename to RELEASE.md index cfe4babf..0a14d410 100644 --- a/docs/release_note.md +++ b/RELEASE.md @@ -1,6 +1,6 @@ Release Notes ===== -v0.6.0 +v0.6.0 (2018-04-04) ------ 1. Change mace header interfaces, only including necessary methods. diff --git a/docs/README b/docs/README index f5aee871..fe47370d 100644 --- a/docs/README +++ b/docs/README @@ -1,9 +1,7 @@ -MACE Documentations ---- +The documents are based on Sphinx, run the following commands to build the documents: -How to build the documents -``` pip install sphinx sphinx-autobuild pip install recommonmark make html -``` + +After building, the generated documents are located in _build. \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 4d3a1342..b47ce9ab 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,7 +6,7 @@ import recommonmark.parser import sphinx_rtd_theme -project = u'MACE' +project = u'MiAI Compute Engine' author = u'%s Developers' % project copyright = u'2018, %s' % author diff --git a/docs/developer/adding_a_new_op.md b/docs/developer/adding_a_new_op.md deleted file mode 100644 index 84889903..00000000 --- a/docs/developer/adding_a_new_op.md +++ /dev/null @@ -1,100 +0,0 @@ -Adding a New Op -=============== - -You can create a custum op if it is not covered by existing mace library. - -To add a custom op in mace you'll need to: - -- Define the new op class and Registry function in op_name.h and op_name.cc under mace/ops directory. - - -``` -op_name.cc - -#include "mace/ops/op_name.h" - -namespace mace { -namespace ops { - -void Register_Custom_Op(OperatorRegistry *op_registry) { - REGISTER_OPERATOR(op_registry, OpKeyBuilder("op_name") - .Device(DeviceType::CPU) - .TypeConstraint("T") - .Build(), - Custom_Op); - - REGISTER_OPERATOR(op_registry, OpKeyBuilder("op_name") - .Device(DeviceType::GPU) - .TypeConstraint("T") - .Build(), - Custom_Op); - - REGISTER_OPERATOR(op_registry, OpKeyBuilder("op_name") - .Device(DeviceType::GPU) - .TypeConstraint("T") - .Build(), - Custom_Op); -} - -} // namespace ops -} // namespace mace - -``` - - -``` -op_name.h - -#ifndef MACE_OPS_CUSTOM_OP_H_ -#define MACE_OPS_CUSTOM_OP_H_ - -#include "mace/core/operator.h" -#include "mace/kernels/custom_op.h" - -namespace mace { -namespace ops { - -template -class CustomOp : public Operator { - public: - CustomOp(const OperatorDef &op_def, Workspace *ws) - : Operator(op_def, ws), - functor_() {} - - bool Run(StatsFuture *future) override { - const Tensor *input = this->Input(INPUT); - Tensor *output = this->Output(OUTPUT); - - functor_(input, output, future); - return true; - } - - protected: - OP_INPUT_TAGS(INPUT); - OP_OUTPUT_TAGS(OUTPUT); - - private: - kernels::CustomOpFunctor functor_; -}; - -} // namespace ops -} // namespace mace - -#endif // MACE_OPS_CUSTOM_OP_H_ - -``` - -- To Add the new op. You need to implement the cpu version operation in a .h file and gpu version in op_name_opencl.cc and op_name.cl files under the mace/kernels directory. - -- Register the new op in core/operator.cc - - -- Test and Benchmark - - Add an op_name_test.cc file to test all functions of your new op both in cpu and gpu and make sure the new op works fine. - - Add an op_benchmark.cc file to benchmark all functions of your new op both in cpu or gpu. - - - - diff --git a/docs/developer/logging.md b/docs/developer/logging.md deleted file mode 100644 index 87063c75..00000000 --- a/docs/developer/logging.md +++ /dev/null @@ -1,9 +0,0 @@ -Logging -======= - -The rule of VLOG: -0. Ad hoc debug logging, should only be added in test or temporary ad hoc debugging -1. Important network level Debug/Latency trace log (Op run should never generate level 1 vlog) -2. Important op level Latency trace log -3. Unimportant Debug/Latency trace log -4. Verbose Debug/Latency trace log diff --git a/docs/developer/opencl_memory_layout.md b/docs/developer/opencl_memory_layout.md deleted file mode 100644 index cb7d3da5..00000000 --- a/docs/developer/opencl_memory_layout.md +++ /dev/null @@ -1,59 +0,0 @@ -OpenCL Image Storage Layout -=========================== - -Use **Image** object to optimize memory access and parallel computing based on OpenCL 2.0. - - -Design the corresponding **Image** format to optimize memory access for different Op algorithm. -Each pixel of **Image** object contains 4 elements(e.g. RGBA). - - -The Followings are the **Buffer** and **Image** format for all **Tensors**. - -Input/Output ---- -**Mace** use NHWC format Input/Output. - -| Tensor| Buffer| Image Size [Width, Height]| Explanation| -| --------- | :---------:|:--------:|:----:| -|Channel-Major Input/Output | NHWC | [W * (C+3)/4, N * H] | Default Input/Output format| -|Height-Major Input/Output | NHWC | [W * C, N * (H+3)/4] | Winograd Convolution format| -|Width-Major Input/Output | NHWC | [(W+3)/4 * C, N * H] | Winograd Convolution format| - -Each Pixel of **Image** contains 4 elements. The below table list the coordination relation -between **Image** and **Buffer**. - -| Tensor| Pixel Coordinate Relation| Explanation -| --------- | :---------:| :-----: | -|Channel-Major Input/Output | P[i, j] = {E[n, h, w, c] | (n=j/H, h=j%H, w=i%W, c=[i/W * 4 + k])}| k=[0, 4)| -|Height-Major Input/Output | P[i, j] = {E[n, h, w, c] | (n=j%N, h=[j/H*4 + k], w=i%W, c=i/W)}| k=[0, 4)| -|Width-Major Input/Output | P[i, j] = {E[n, h, w, c] | (n=j/H, h=j%H, w=[i%W*4 + k], c=i/W)}| k=[0, 4)| - - -Filter ---- -| Tensor| Buffer| Image Size [Width, Height]| Explanation| -| --------- | :---------:|:--------:|:----:| -|Convolution Filter | HWOI | [RoundUp<4>(I), H * W * (O+3)/4]|Convolution filter format,There is no difference compared to [H*w*I, (O+3)/4]| -|Depthwise Convlution Filter | HWIM | [H * W * M, (I+3)/4]|Depthwise-Convolution filter format| - -Each Pixel of **Image** contains 4 elements. The below table list the coordination relation -between **Image** and **Buffer**. - -| Tensor| Pixel Coordinate Relation| Explanation| -| --------- | :---------:| :-----:| -|Convolution Filter | P[m, n] = {E[h, w, o, i] | (h=T/W, w=T%W, o=[n/HW*4+k], i=m)}| HW= H * W, T=n%HW, k=[0, 4)| -|Depthwise Convlution Filter | P[m, n] = {E[h, w, i, 0] | (h=m/W, w=m%W, i=[n*4+k])}| only support multiplier == 1, k=[0, 4)| - -1-D Argument ---- -| Tensor| Buffer| Image Size [Width, Height]| Explanation| -| --------- | :---------:|:--------:|:----:| -|1-D Argument | W | [(W+3)/4, 1] | 1D argument format, e.g. Bias| - -Each Pixel of **Image** contains 4 elements. The below table list the coordination relation -between **Image** and **Buffer**. - -| Tensor| Pixel Coordinate Relation| Explanation| -| --------- | :---------:| :-----:| -|1-D Argument | P[i, 0] = {E[w] | w=i*4+k}| k=[0, 4)| diff --git a/docs/development/adding_a_new_op.md b/docs/development/adding_a_new_op.md new file mode 100644 index 00000000..a6f204f2 --- /dev/null +++ b/docs/development/adding_a_new_op.md @@ -0,0 +1,97 @@ +Adding a new Op +=============== + +You can create a custom op if it is not supported yet. + +To add a custom op, you need to finish the following steps. + +Define the Op class +-------------------- +Define the new Op class in `mace/ops/my_custom_op.h`. + +```c++ +#ifndef MACE_OPS_MY_CUSTOM_OP_H_ +#define MACE_OPS_MY_CUSTOM_OP_H_ + +#include "mace/core/operator.h" +#include "mace/kernels/my_custom_op.h" + +namespace mace { +namespace ops { + +template +class MyCustomOp : public Operator { + public: + MyCustomOp(const OperatorDef &op_def, Workspace *ws) + : Operator(op_def, ws), + functor_() {} + + bool Run(StatsFuture *future) override { + const Tensor *input = this->Input(INPUT); + Tensor *output = this->Output(OUTPUT); + + functor_(input, output, future); + return true; + } + + protected: + OP_INPUT_TAGS(INPUT); + OP_OUTPUT_TAGS(OUTPUT); + + private: + kernels::MyCustomOpFunctor functor_; +}; + +} // namespace ops +} // namespace mace + +#endif // MACE_OPS_MY_CUSTOM_OP_H_ + +``` + +Register the new Op +-------------------- +Define the Ops registering function in `mace/ops/my_custom_op.cc`. +```c++ +#include "mace/ops/my_custom_op.h" + +namespace mace { +namespace ops { + +void Register_My_Custom_Op(OperatorRegistry *op_registry) { + REGISTER_OPERATOR(op_registry, OpKeyBuilder("my_custom_op") + .Device(DeviceType::CPU) + .TypeConstraint("T") + .Build(), + Custom_Op); + + REGISTER_OPERATOR(op_registry, OpKeyBuilder("my_custom_op") + .Device(DeviceType::OPENCL) + .TypeConstraint("T") + .Build(), + Custom_Op); + + REGISTER_OPERATOR(op_registry, OpKeyBuilder("my_custom_op") + .Device(DeviceType::OPENCL) + .TypeConstraint("T") + .Build(), + Custom_Op); +} + +} // namespace ops +} // namespace mace + +``` +And then register the new Op in `mace/core/operator.cc`. + +Implement the Op kernel code +---------------------------- +You need to implement the CPU kernel in a `mace/kernels/my_custom_op.h` and +optionally OpenCL kernel in `mace/kernels/kernels/my_custom_op_opencl.cc` and +`mace/kernels/kernels/cl/my_custom_op.cl`. You can also optimize the CPU +kernel with NEON. + +Add test and benchmark +---------------------- +It's strongly recommended to add unit test and micro benchmark for your +new Op. If you wish to contribute back, it's required. diff --git a/docs/development/contributing.md b/docs/development/contributing.md new file mode 100644 index 00000000..97671e74 --- /dev/null +++ b/docs/development/contributing.md @@ -0,0 +1,52 @@ +Contributing guide +================== + +License +------- + +The source file should contains a license header. See the existing files +as an example. + +Python coding style +------------------- + +Changes to Python code should conform to [PEP8 Style Guide for Python +Code](https://www.python.org/dev/peps/pep-0008/). + +You can use pycodestyle to check the style. + +C++ coding style +---------------- + +Changes to C++ code should conform to [Google C++ Style +Guide](https://google.github.io/styleguide/cppguide.html). + +You can use cpplint to check the style and use clang-format to format +the code: + +```sh +clang-format -style="{BasedOnStyle: google, \ + DerivePointerAlignment: false, \ + PointerAlignment: Right, \ + BinPackParameters: false}" $file +``` + +C++ logging guideline +--------------------- + +The rule of VLOG level: + +``` +0. Ad hoc debug logging, should only be added in test or temporary ad hoc + debugging +1. Important network level Debug/Latency trace log (Op run should never + generate level 1 vlog) +2. Important op level Latency trace log +3. Unimportant Debug/Latency trace log +4. Verbose Debug/Latency trace log +``` + +C++ marco +---------- +C++ macros should start with `MACE_`, except for most common ones like `LOG` +and `VLOG`. diff --git a/docs/development/memory_layout.rst b/docs/development/memory_layout.rst new file mode 100644 index 00000000..f8e428ca --- /dev/null +++ b/docs/development/memory_layout.rst @@ -0,0 +1,99 @@ +Memory layout +=========================== + +CPU runtime memory layout +------------------------- +The CPU tensor buffer is organized in the following order: + ++-----------------------------+--------------+ +| Tensor type | Buffer | ++=============================+==============+ +| Intermediate input/output | NCHW | ++-----------------------------+--------------+ +| Convolution Filter | OIHW | ++-----------------------------+--------------+ +| Depthwise Convolution Filter| MIHW | ++-----------------------------+--------------+ +| 1-D Argument, length = W | W | ++-----------------------------+--------------+ + +OpenCL runtime memory layout +----------------------------- +OpenCL runtime uses 2D image with CL_RGBA channel order as the tensor storage. +This requires OpenCL 1.2 and above. + +The way of mapping the Tensor data to OpenCL 2D image (RGBA) is critical for +kernel performance. + +In CL_RGBA channel order, each 2D image pixel contains 4 data items. +The following tables describe the mapping from different type of tensors to +2D RGBA Image. + +Input/Output Tensor +~~~~~~~~~~~~~~~~~~~ + +The Input/Output Tensor is stored in NHWC format: + ++---------------------------+--------+----------------------------+-----------------------------+ +|Tensor type | Buffer | Image size [width, height] | Explanation | ++===========================+========+============================+=============================+ +|Channel-Major Input/Output | NHWC | [W * (C+3)/4, N * H] | Default Input/Output format | ++---------------------------+--------+----------------------------+-----------------------------+ +|Height-Major Input/Output | NHWC | [W * C, N * (H+3)/4] | Winograd Convolution format | ++---------------------------+--------+----------------------------+-----------------------------+ +|Width-Major Input/Output | NHWC | [(W+3)/4 * C, N * H] | Winograd Convolution format | ++---------------------------+--------+----------------------------+-----------------------------+ + +Each Pixel of **Image** contains 4 elements. The below table list the +coordination relation between **Image** and **Buffer**. + ++---------------------------+-------------------------------------------------------------------------+-------------+ +|Tensor type | Pixel coordinate relationship | Explanation | ++===========================+=========================================================================+=============+ +|Channel-Major Input/Output | P[i, j] = {E[n, h, w, c] | (n=j/H, h=j%H, w=i%W, c=[i/W * 4 + k])} | k=[0, 4) | ++---------------------------+-------------------------------------------------------------------------+-------------+ +|Height-Major Input/Output | P[i, j] = {E[n, h, w, c] | (n=j%N, h=[j/H*4 + k], w=i%W, c=i/W)} | k=[0, 4) | ++---------------------------+-------------------------------------------------------------------------+-------------+ +|Width-Major Input/Output | P[i, j] = {E[n, h, w, c] | (n=j/H, h=j%H, w=[i%W*4 + k], c=i/W)} | k=[0, 4) | ++---------------------------+-------------------------------------------------------------------------+-------------+ + + +Filter Tensor +~~~~~~~~~~~~~ + ++----------------------------+------+---------------------------------+------------------------------------------------------------------------------+ +| Tensor |Buffer| Image size [width, height] | Explanation | ++============================+======+=================================+==============================================================================+ +|Convolution Filter | HWOI | [RoundUp<4>(I), H * W * (O+3)/4]|Convolution filter format,There is no difference compared to [H*w*I, (O+3)/4]| ++----------------------------+------+---------------------------------+------------------------------------------------------------------------------+ +|Depthwise Convlution Filter | HWIM | [H * W * M, (I+3)/4] |Depthwise-Convolution filter format | ++----------------------------+------+---------------------------------+------------------------------------------------------------------------------+ + +Each Pixel of **Image** contains 4 elements. The below table list the +coordination relation between **Image** and **Buffer**. + ++----------------------------+-------------------------------------------------------------------+---------------------------------------+ +|Tensor type | Pixel coordinate relationship | Explanation | ++============================+===================================================================+=======================================+ +|Convolution Filter | P[m, n] = {E[h, w, o, i] | (h=T/W, w=T%W, o=[n/HW*4+k], i=m)}| HW= H * W, T=n%HW, k=[0, 4) | ++----------------------------+-------------------------------------------------------------------+---------------------------------------+ +|Depthwise Convlution Filter | P[m, n] = {E[h, w, i, 0] | (h=m/W, w=m%W, i=[n*4+k])} | only support multiplier == 1, k=[0, 4)| ++----------------------------+-------------------------------------------------------------------+---------------------------------------+ + +1-D Argument Tensor +~~~~~~~~~~~~~~~~~~~ + ++----------------+----------+------------------------------+---------------------------------+ +| Tensor type | Buffer | Image size [width, height] | Explanation | ++================+==========+==============================+=================================+ +| 1-D Argument | W | [(W+3)/4, 1] | 1D argument format, e.g. Bias | ++----------------+----------+------------------------------+---------------------------------+ + +Each Pixel of **Image** contains 4 elements. The below table list the +coordination relation between **Image** and **Buffer**. + ++--------------+---------------------------------+-------------+ +| Tensor type | Pixel coordinate relationship | Explanation | ++==============+=================================+=============+ +|1-D Argument | P[i, 0] = {E[w] | w=i*4+k} | k=[0, 4) | ++--------------+---------------------------------+-------------+ diff --git a/docs/docker/usage.md b/docs/docker/usage.md deleted file mode 100644 index 85dc4cd7..00000000 --- a/docs/docker/usage.md +++ /dev/null @@ -1,27 +0,0 @@ -Docker Images -========================================== - -* Login in [Xiaomi Docker Registry](http://docs.api.xiaomi.net/docker-registry/) - - ``` - docker login cr.d.xiaomi.net - ``` - -* Build with `Dockerfile` - - ``` - docker build -t cr.d.xiaomi.net/mace/mace-dev . - ``` - -* Pull image from docker registry - - ``` - docker pull cr.d.xiaomi.net/mace/mace-dev - ``` - -* Create container - - ``` - # Set 'host' network to use ADB - docker run -it --rm -v /local/path:/container/path --net=host cr.d.xiaomi.net/mace/mace-dev /bin/bash - ``` diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 00000000..a96305a5 --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,50 @@ +Frequently Asked Questions +========================== + +Why is the generated static library file size so huge? +------------------------------------------------------- +The static library is simply an archive of a set of object files which are +intermediate and contains many extra information, please check whether the +final binary file size is as expected. + +Why is the generated binary file (including shared library) size so huge? +------------------------------------------------------------------------- +When compiling the model into C++ code, the final binary may contains extra +debug symbols, they usually takes a lot of space. Try to strip the shared +library or binary. The common overhead of the file size including the compiled +model (excluding the model weights) after the strip should be less than 2MB. +If the model weights is embedded into the binary, the extra overhead should be +around {model weights size in float32}/2. + +OpenCL allocator failed with CL_OUT_OF_RESOURCES +------------------------------------------------ +OpenCL runtime usually requires continuous virtual memory for its image buffer, +the error will occur when the OpenCL driver can't find the continuous space +due to high memory usage or fragmentation. Several solutions can be tried: + +* Change the model by reducing its memory usage +* Split the Op with the biggest single memory buffer +* Changed from armeabi-v7a to arm64-v8a to expand the virtual address space +* Reduce the memory consumption of other modules of the same process + +Why the performance is worce than the official result for the same model? +------------------------------------------------------------------------- +The power options may not set properly, see `mace/public/mace_runtime.h` for +details. + +Why the UI is getting poor responsiveness when running model with GPU runtime? +------------------------------------------------------------------------------ +Try to set `limit_opencl_kernel_time` to `1`. If still not resolved, try to +modify the source code to use even smaller time intervals or changed to CPU +or DSP runtime. + +How to include more than one deployment files in one application(process)? +------------------------------------------------------------------------------ +This case may happen when an application is developed by multiple teams as +submodules. If the all the submodules are linked into a single shared library, +then use the same version of MiAI Compute Engine will resolve this issue. +Ortherwise, different deployment models are contained in different shared +libraries, it's not required to use the same MiAI version but you should +controls the exported symbols from the shared library. This is actually a +best practice for all shared library, please read about GNU loader +version script for more details. diff --git a/docs/getting_started/create_a_model_deployment.rst b/docs/getting_started/create_a_model_deployment.rst new file mode 100644 index 00000000..15a5b06c --- /dev/null +++ b/docs/getting_started/create_a_model_deployment.rst @@ -0,0 +1,105 @@ +Create a model deployment +========================= + +Each YAML deployment script describes a case of deployments (for example, +a smart camera application may contains face recognition, object recognition, +and voice recognition models, which can be defined in one deployment file), +which will generate one static library (if more than one ABIs specified, +there will be one static library for each). Each YAML scripts can contains one +or more models. + + +Model deployment file example +------------------------------- +TODO: change to a link to a standalone file with comments. + +.. code:: yaml + + # 配置文件名会被用作生成库的名称:libmace-${filename}.a + target_abis: [armeabi-v7a, arm64-v8a] + # 具体机型的soc编号,可以使用`adb shell getprop | grep ro.board.platform | cut -d [ -f3 | cut -d ] -f1`获取 + target_socs: [msm8998] + embed_model_data: 1 + vlog_level: 0 + models: # 一个配置文件可以包含多个模型的配置信息,最终生成的库中包含多个模型 + first_net: # 模型的标签,在调度模型的时候,会用这个变量 + platform: tensorflow + model_file_path: path/to/model64.pb # also support http:// and https:// + model_sha256_checksum: 7f7462333406e7dea87222737590ebb7d94490194d2f21a7d72bafa87e64e9f9 + input_nodes: input_node + output_nodes: output_node + input_shapes: 1,64,64,3 + output_shapes: 1,64,64,2 + runtime: gpu + limit_opencl_kernel_time: 0 + dsp_mode: 0 + obfuscate: 1 + fast_conv: 0 + input_files: + - path/to/input_files # support http:// + second_net: + platform: caffe + model_file_path: path/to/model.prototxt + weight_file_path: path/to/weight.caffemodel + model_sha256_checksum: 05d92625809dc9edd6484882335c48c043397aed450a168d75eb8b538e86881a + weight_sha256_checksum: 05d92625809dc9edd6484882335c48c043397aed450a168d75eb8b538e86881a + input_nodes: + - input_node0 + - input_node1 + output_nodes: + - output_node0 + - output_node1 + input_shapes: + - 1,256,256,3 + - 1,128,128,3 + output_shapes: + - 1,256,256,2 + - 1,1,1,2 + runtime: cpu + limit_opencl_kernel_time: 1 + dsp_mode: 0 + obfuscate: 1 + fast_conv: 0 + input_files: + - path/to/input_files # support http:// + +Configurations +-------------------- + ++--------------------------+----------------------------------------------------------------------------------------+ +| Configuration key | Description | ++==========================+========================================================================================+ +| target_abis | The target ABI to build, can be one or more of 'host', 'armeabi-v7a' or 'arm64-v8a' | ++--------------------------+----------------------------------------------------------------------------------------+ +| embed_model_data | Whether embedding model weights as the code, default to 1 | ++--------------------------+----------------------------------------------------------------------------------------+ +| platform | The source framework, tensorflow or caffe | ++--------------------------+----------------------------------------------------------------------------------------+ +| model_file_path | The path of the model file, can be local or remote | ++--------------------------+----------------------------------------------------------------------------------------+ +| weight_file_path | The path of the model weights file, used by Caffe model | ++--------------------------+----------------------------------------------------------------------------------------+ +| model_sha256_checksum | The SHA256 checksum of the model file | ++--------------------------+----------------------------------------------------------------------------------------+ +| weight_sha256_checksum | The SHA256 checksum of the weight file, used by Caffe model | ++--------------------------+----------------------------------------------------------------------------------------+ +| input_nodes | The input node names, one or more strings | ++--------------------------+----------------------------------------------------------------------------------------+ +| output_nodes | The output node names, one or more strings | ++--------------------------+----------------------------------------------------------------------------------------+ +| input_shapes | The shapes of the input nodes, in NHWC order | ++--------------------------+----------------------------------------------------------------------------------------+ +| output_shapes | The shapes of the output nodes, in NHWC order | ++--------------------------+----------------------------------------------------------------------------------------+ +| runtime | The running device, one of CPU, GPU or DSP | ++--------------------------+----------------------------------------------------------------------------------------+ +| limit_opencl_kernel_time | Whether splitting the OpenCL kernel within 1 ms to keep UI responsiveness, default to 0| ++--------------------------+----------------------------------------------------------------------------------------+ +| dsp_mode | Control the DSP precision and performance, default to 0 usually works for most cases | ++--------------------------+----------------------------------------------------------------------------------------+ +| obfuscate | Whether to obfuscate the model operator name, default to 0 | ++--------------------------+----------------------------------------------------------------------------------------+ +| fast_conv | Whether to enable Winograd convolution, **will increase memory consumption** | ++--------------------------+----------------------------------------------------------------------------------------+ +| input_files | Specify Numpy validation inputs. When not provided, [-1, 1] random values will be used | ++--------------------------+----------------------------------------------------------------------------------------+ diff --git a/docs/getting_started/docker.rst b/docs/getting_started/docker.rst new file mode 100644 index 00000000..3c6f5ec0 --- /dev/null +++ b/docs/getting_started/docker.rst @@ -0,0 +1,19 @@ +Docker Images +============= + +- Login in `Xiaomi Docker + Registry `__ + +``docker login cr.d.xiaomi.net`` + +- Build with ``Dockerfile`` + +``docker build -t cr.d.xiaomi.net/mace/mace-dev .`` + +- Pull image from docker registry + +``docker pull cr.d.xiaomi.net/mace/mace-dev`` + +- Create container + +``# Set 'host' network to use ADB docker run -it --rm -v /local/path:/container/path --net=host cr.d.xiaomi.net/mace/mace-dev /bin/bash`` diff --git a/docs/getting_started/how_to_build.rst b/docs/getting_started/how_to_build.rst new file mode 100644 index 00000000..47781280 --- /dev/null +++ b/docs/getting_started/how_to_build.rst @@ -0,0 +1,259 @@ +How to build +============ + +模型格式支持 +------------- + ++--------------+------------------------------------------------------------------------------------------+ +| 框架格式 | 支持情况 | ++==============+==========================================================================================+ +| TensorFlow | 推荐使用1.4以上版本,否则可能达不到最佳性能 (考虑到后续Android NN,建议首选TensorFLow) | ++--------------+------------------------------------------------------------------------------------------+ +| Caffe | 推荐使用1.0以上版本,低版本可能不支持,建议改用TensorFlow | ++--------------+------------------------------------------------------------------------------------------+ +| MXNet | 尚未支持 | ++--------------+------------------------------------------------------------------------------------------+ +| ONNX | 尚未支持 | ++--------------+------------------------------------------------------------------------------------------+ + +环境要求 +--------- + +``mace``\ 提供了包含开发运行所需环境的docker镜像,镜像文件可以参考\ ``./docker/``\ 。启动命令: + +.. code:: sh + + sudo docker pull cr.d.xiaomi.net/mace/mace-dev + sudo docker run -it --rm --privileged -v /dev/bus/usb:/dev/bus/usb --net=host -v /local/path:/container/path cr.d.xiaomi.net/mace/mace-dev /bin/bash + +如果用户希望配置开发机上的环境,可以参考如下环境要求: + ++---------------------+-----------------+---------------------------------------------------------------------------------------------------+ +| 软件 | 版本号 | 安装命令 | ++=====================+=================+===================================================================================================+ +| bazel | >= 0.5.4 | - | ++---------------------+-----------------+---------------------------------------------------------------------------------------------------+ +| android-ndk | r12c | - | ++---------------------+-----------------+---------------------------------------------------------------------------------------------------+ +| adb | >= 1.0.32 | apt install -y android-tools-adb | ++---------------------+-----------------+---------------------------------------------------------------------------------------------------+ +| tensorflow | 1.4.0 | pip install tensorflow==1.4.0 | ++---------------------+-----------------+---------------------------------------------------------------------------------------------------+ +| scipy | >= 1.0.0 | pip install scipy | ++---------------------+-----------------+---------------------------------------------------------------------------------------------------+ +| jinja2 | >= 2.10 | pip install jinja2 | ++---------------------+-----------------+---------------------------------------------------------------------------------------------------+ +| PyYaml | >= 3.12 | pip install pyyaml | ++---------------------+-----------------+---------------------------------------------------------------------------------------------------+ +| docker(for caffe) | >= 17.09.0-ce | `install doc `__ | ++---------------------+-----------------+---------------------------------------------------------------------------------------------------+ + +使用简介 +-------- + +1. 获取最新tag的代码 + +**建议尽可能使用最新tag下的代码,以及不要直接使用master分支的最新代码。** + +.. code:: sh + + git clone git@v9.git.n.xiaomi.com:deep-computing/mace.git + + # update + git fetch --all --tags --prune + + # get latest tag version + tag_name=`git describe --abbrev=0 --tags` + + # checkout to latest tag branch + git checkout -b ${tag_name} tags/${tag_name} + +2. 模型优化 + +- Tensorflow + +TensorFlow训练得到的模型进行一系列的转换,可以提升设备上的运行速度。TensorFlow提供了官方工具 +`TensorFlow Graph Transform +Tool `__ +来进行模型优化 +(此工具Docker镜像中已经提供,也可以直接点击`下载 `__\ 这个工具,用户亦可从官方源码编译\`)。以下分别是GPU模型和DSP模型的优化命令: + +.. code:: sh + + # GPU模型: + ./transform_graph \ + --in_graph=tf_model.pb \ + --out_graph=tf_model_opt.pb \ + --inputs='input' \ + --outputs='output' \ + --transforms='strip_unused_nodes(type=float, shape="1,64,64,3") + strip_unused_nodes(type=float, shape="1,64,64,3") + remove_nodes(op=Identity, op=CheckNumerics) + fold_constants(ignore_errors=true) + fold_batch_norms + fold_old_batch_norms + strip_unused_nodes + sort_by_execution_order' + + # DSP模型: + ./transform_graph \ + --in_graph=tf_model.pb \ + --out_graph=tf_model_opt.pb \ + --inputs='input' \ + --outputs='output' \ + --transforms='strip_unused_nodes(type=float, shape="1,64,64,3") + strip_unused_nodes(type=float, shape="1,64,64,3") + remove_nodes(op=Identity, op=CheckNumerics) + fold_constants(ignore_errors=true) + fold_batch_norms + fold_old_batch_norms + backport_concatv2 + quantize_weights(minimum_size=2) + quantize_nodes + strip_unused_nodes + sort_by_execution_order' + +- Caffe + +Caffe目前只支持最新版本,旧版本请使用Caffe的工具进行升级。 + +.. code:: bash + + # Upgrade prototxt + $CAFFE_ROOT/build/tools/upgrade_net_proto_text MODEL.prototxt MODEL.new.prototxt + + # Upgrade caffemodel + $CAFFE_ROOT/build/tools/upgrade_net_proto_binary MODEL.caffemodel MODEL.new.caffemodel + +3. 生成模型静态库 + +模型静态库的生成需要使用目标机型,\ ***并且要求必须在目标SOC的机型上编译生成静态库。*** + +我们提供了\ ``mace_tools.py``\ 工具,可以将模型文件转换成静态库。\ ``tools/mace_tools.py``\ 使用步骤: + + + +3.2 运行\ ``tools/mace_tools.py``\ 脚本 + +.. code:: sh + + # print help message + # python tools/mace_tools.py --help + # --config 配置文件的路径 + # --output_dir 编译结果的输出文件目录,默认为`./build` + # --round 调用`examples/mace_run`运行模型的次数,默认为`1` + # --tuning 对opencl的参数调参,该项通常只有开发人员用到,默认为`true` + # --mode 运行模式,包含build/run/validate/merge/all/benchmark,默认为`all` + + # 仅编译模型和生成静态库 + python tools/mace_tools.py --config=models/config.yaml --mode=build + + # 测试模型的运行时间 + python tools/mace_tools.py --config=models/config.yaml --mode=run --round=1000 + + # 对比编译好的模型在mace上与直接使用tensorflow或者caffe运行的结果,相似度使用`余弦距离表示` + # 其中使用OpenCL设备,默认相似度大于等于`0.995`为通过;DSP设备下,相似度需要达到`0.930`。 + python tools/mace_tools.py --config=models/config.yaml --mode=run --round=1000 + + # 将已编译好的多个模型合并成静态库 + # 比如编译了8个模型,决定使用其中2个模型,这时候可以不重新build,直接修改全局配置文件,合并生成静态库 + python tools/mace_tools.py --config=models/config.yaml --mode=merge + + # 运行以上所有项(可用于测试速度,建议 round=20) + python tools/mace_tools.py --config=models/config.yaml --mode=all --round=1000 + + # 模型Benchmark:查看每个Op的运行时间 + python tools/mace_tools.py --config=models/config.yaml --mode=benchmark + + # 查看模型运行时占用内存(如果有多个模型,可能需要注释掉一部分配置,只剩一个模型的配置) + python tools/mace_tools.py --config=models/config.yaml --mode=run --round=10000 & + adb shell dumpsys meminfo | grep mace_run + sleep 10 + kill %1 + +4. 发布 + +通过前面的步骤,我们得到了包含业务模型的库文件。在业务代码中,我们只需要引入下面3组文件(\ ``./build/``\ 是默认的编译结果输出目录): + +头文件(包含mace.h和各个模型的头文件): \* +``./build/${project_name}/${target_abi}/include/mace/public/*.h`` + +静态库(包含mace engine、opencl和模型相关库): \* +``./build/${project_name}/${target_abi}/*.a`` + +动态库(仅编译的模型中包含dsp模式时用到): \* +``./build/${project_name}/${target_abi}/libhexagon_controller.so`` + +模型数据文件(仅在EMBED\_MODEL\_DATA=0时产生): \* +``./build/${project_name}/data/${MODEL_TAG}.data`` + +编译过程中间文件: \* ``./build/${project_name}/build/`` + +库文件tar包: \* ``./build/${project_name}/${project_name}.tar.gz`` + +5. 使用 + +具体使用流程可参考\ ``mace/examples/mace_run.cc``\ ,下面列出关键步骤。 + +.. code:: cpp + + // 引入头文件 + #include "mace/public/mace.h" + #include "mace/public/{MODEL_TAG}.h" + + // 0. 设置内部存储 + const std::string file_path ="/path/to/store/internel/files"; + std::shared_ptr storage_factory( + new FileStorageFactory(file_path)); + ConfigKVStorageFactory(storage_factory); + + //1. 从文件或代码中Load模型数据,也可通过自定义的方式来Load (例如可自己实现压缩加密等) + // 如果使用的是数据嵌入的方式,将参数设为nullptr。 + unsigned char *model_data = mace::MACE_MODEL_TAG::LoadModelData(FLAGS_model_data_file.c_str()); + + //2. 创建net对象 + NetDef net_def = mace::MACE_MODEL_TAG::CreateNet(model_data); + + //3. 声明设备类型(必须与build时指定的runtime一致) + DeviceType device_type = DeviceType::OPENCL; + + //4. 定义输入输出名称数组 + std::vector input_names = {...}; + std::vector output_names = {...}; + + //5. 创建输入输出对象 + std::map inputs; + std::map outputs; + for (size_t i = 0; i < input_count; ++i) { + // Allocate input and output + int64_t input_size = + std::accumulate(input_shapes[i].begin(), input_shapes[i].end(), 1, + std::multiplies()); + auto buffer_in = std::shared_ptr(new float[input_size], + std::default_delete()); + // load input + ... + + inputs[input_names[i]] = mace::MaceTensor(input_shapes[i], buffer_in); + } + + for (size_t i = 0; i < output_count; ++i) { + int64_t output_size = + std::accumulate(output_shapes[i].begin(), output_shapes[i].end(), 1, + std::multiplies()); + auto buffer_out = std::shared_ptr(new float[output_size], + std::default_delete()); + outputs[output_names[i]] = mace::MaceTensor(output_shapes[i], buffer_out); + } + + //6. 创建MaceEngine对象 + mace::MaceEngine engine(&net_def, device_type, input_names, output_names); + + //7. 如果设备类型是OPENCL或HEXAGON,可以在此释放model_data + if (device_type == DeviceType::OPENCL || device_type == DeviceType::HEXAGON) { + mace::MACE_MODEL_TAG::UnloadModelData(model_data); + } + + //8. 执行模型,得到结果 + engine.Run(inputs, &outputs); + diff --git a/docs/getting_started/introduction.md b/docs/getting_started/introduction.md new file mode 100644 index 00000000..8cfc6b72 --- /dev/null +++ b/docs/getting_started/introduction.md @@ -0,0 +1,8 @@ +Introduction +============ + +TODO: describe the conceptions and workflow with diagram. +![alt text](workflow.jpg "MiAI workflow") + +TODO: describe the runtime. + diff --git a/docs/getting_started/op_lists.rst b/docs/getting_started/op_lists.rst new file mode 100644 index 00000000..6afa5d06 --- /dev/null +++ b/docs/getting_started/op_lists.rst @@ -0,0 +1,82 @@ +Operator lists +============== + ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| Operator | Android NN | Status | Remark | ++==================================+==============+========+=======================================================+ +| ADD | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| AVERAGE\_POOL\_2D | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| BATCH\_NORM | | Y | Fusion with activation is supported | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| BIAS\_ADD | | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| CHANNEL\_SHUFFLE | | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| CONCATENATION | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| CONV\_2D | Y | Y | Fusion with BN and activation layer is supported | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| DEPTHWISE\_CONV\_2D | Y | Y | Only multiplier = 1 is supported; Fusion is supported | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| DEPTH\_TO\_SPACE | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| DEQUANTIZE | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| EMBEDDING\_LOOKUP | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| FLOOR | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| FULLY\_CONNECTED | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| GROUP\_CONV\_2D | | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| HASHTABLE\_LOOKUP | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| L2\_NORMALIZATION | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| L2\_POOL\_2D | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| LOCAL\_RESPONSE\_NORMALIZATION | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| LOGISTIC | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| LSH\_PROJECTION | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| LSTM | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| MATMUL | | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| MAX\_POOL\_2D | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| MUL | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| PSROI\_ALIGN | | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| PRELU | | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| RELU | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| RELU1 | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| RELU6 | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| RELUX | | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| RESHAPE | Y | Y | Limited support | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| RESIZE\_BILINEAR | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| RNN | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| RPN\_PROPOSAL\_LAYER | | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| SOFTMAX | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| SPACE\_TO\_DEPTH | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| SVDF | Y | | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ +| TANH | Y | Y | | ++----------------------------------+--------------+--------+-------------------------------------------------------+ diff --git a/docs/getting_started/workflow.jpg b/docs/getting_started/workflow.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e00ebea13ac5e261feb38306938f97fa995d47c7 GIT binary patch literal 119085 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 U)P;m4%aaRMhU2rVBL2SqKi}m~TL1t6 literal 0 HcmV?d00001 diff --git a/docs/index.rst b/docs/index.rst index 4825759c..08400726 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,18 +1,32 @@ -MACE documentation -================================ -Welcome to MACE documentation. +MiAI Compute Engine Documentation +================================= +Welcome to MiAI Compute Engine documentation. +The main documentation is organized into the following sections: -Contents --------- +.. toctree:: + :maxdepth: 1 + :caption: Getting started + :name: sec-start + + getting_started/introduction + getting_started/create_a_model_deployment + getting_started/how_to_build + getting_started/docker + getting_started/op_lists + +.. toctree:: + :maxdepth: 1 + :caption: Development + :name: sec-devel + + development/contributing + development/adding_a_new_op + development/memory_layout .. toctree:: :maxdepth: 1 + :caption: FAQ + :name: sec-faq - self - user/introduction - docker/usage - developer/adding_a_new_op - developer/opencl_memory_layout - developer/logging - release_note + faq diff --git a/docs/user/introduction.md b/docs/user/introduction.md deleted file mode 100644 index 96338661..00000000 --- a/docs/user/introduction.md +++ /dev/null @@ -1,409 +0,0 @@ -Introduction -============ - -**MACE** - *Mobile(Mi) Accelerated Compute Engine Library* 是小米自主研发的移动端神经网络加速引擎。 - -## 特点 -1. 速度快 - * 专门为小米手机SoC优化(高通,MTK,澎湃),支持GPU(DSP基于nnlib)加速,在主流高通平台速度优于高通SNPE框架 (注: 速度跟模型结构有关,depthwise conv2d,1x1卷积MACE与SNPE持平,3x3卷积,通用卷积等优于SNPE。另外目前高通平台SNPE明显优于TensorFlow Lite, Caffe/Caffe2,ARM Compute Library,腾讯ncnn,百度MDL等开源框架)。 - * 支持不同SoC的自动调优 - * 模型数据通过mmap方式加载,启动速度快 -2. 内存占用少 - * MACE支持基于计算图依赖的内存优化技术,通过内存复用,能减少运行时内存占用,特别是对于依赖较简单的模型,内存优化效果明显 -3. 体积小 - * MACE本身无外部依赖,核心代码小于1MB (模型除外) -4. 内置模型加密功能 - * MACE支持模型混淆加密功能,模型直接编译成可执行代码而非数据文件,同时加强了敏感代码的混淆,增加了反向的难度 -5. 部署便捷 - * 用户接口简单,只需要一个头文件,MACE采用源码/静态库形式链接到用户程序,不会引入额外的动态库和模型数据文件(DSP版本需要一个额外的动态库) - -## 模型格式支持 -| 框架格式 | 支持情况 | -| ---------- |:-------:| -| TensorFlow | 推荐使用1.4以上版本,否则可能达不到最佳性能 (考虑到后续Android NN,建议首选TensorFLow) | -| Caffe | 推荐使用1.0以上版本,低版本可能不支持,建议改用TensorFlow | -| MXNet | 尚未支持 | -| ONNX | 尚未支持 | - - -## 环境要求 - -`mace`提供了包含开发运行所需环境的docker镜像,镜像文件可以参考`./docker/`。启动命令: -```sh -sudo docker pull cr.d.xiaomi.net/mace/mace-dev -sudo docker run -it --rm --privileged -v /dev/bus/usb:/dev/bus/usb --net=host -v /local/path:/container/path cr.d.xiaomi.net/mace/mace-dev /bin/bash -``` - -如果用户希望配置开发机上的环境,可以参考如下环境要求: - -| 软件 | 版本号 | 安装命令 | -| -------- |:--------------:|:---------------------:| -| bazel | >= 0.5.4 | - | -| android-ndk | r12c | - | -| adb | >= 1.0.32 | apt install -y android-tools-adb | -| tensorflow | 1.4.0 | pip install tensorflow==1.4.0 | -| scipy | >= 1.0.0 | pip install scipy | -| jinja2 | >= 2.10 | pip install jinja2 | -| PyYaml | >= 3.12 | pip install pyyaml | -| docker(for caffe) | >= 17.09.0-ce | [install doc](https://docs.docker.com/install/linux/docker-ce/ubuntu/#set-up-the-repository) | - -## 文件组织 - -``` -|-- tools --> mace编译运行相关的工具脚本 -| |-- mace_tools.py -| |-- ... -| -|-- mace -| |-- benchmark -| | -| |-- codegen --> 模型、opencl二进制文件和tuning数据生成的C++代码 -| | |-- models -| | |-- opencl -| | |-- opencl_bin -| | |-- tuning -| | -| |-- core -| | -| |-- examples -| | |-- mace_run.cc --> 运行mace模型的样例 -| | |-- ... -| | -| |-- kernels -| | -| |-- ops -| | -| |-- public --> mace的接口 -| -|-- docker --> mace开发环境的Dockerfile -``` - -## 使用简介 - -1\. 获取最新tag的代码 - -**建议尽可能使用最新tag下的代码,以及不要直接使用master分支的最新代码。** - -```sh -git clone git@v9.git.n.xiaomi.com:deep-computing/mace.git - -# update -git fetch --all --tags --prune - -# get latest tag version -tag_name=`git describe --abbrev=0 --tags` - -# checkout to latest tag branch -git checkout -b ${tag_name} tags/${tag_name} -``` - -2\. 模型优化 - -- Tensorflow - -TensorFlow训练得到的模型进行一系列的转换,可以提升设备上的运行速度。TensorFlow提供了官方工具 -[TensorFlow Graph Transform Tool](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tools/graph_transforms/README.md) -来进行模型优化 (在官方工具的基础上,我们做了一部分定制化,此工具Docker镜像中已经提供,也可以直接点击[下载](http://cnbj1-inner-fds.api.xiaomi.net/mace/tool/transform_graph)这个工具,`暂时不支持用户自己从官方源码编译`)。以下分别是GPU模型和DSP模型的优化命令: - -```sh -# GPU模型: -./transform_graph \ - --in_graph=tf_model.pb \ - --out_graph=tf_model_opt.pb \ - --inputs='input' \ - --outputs='output' \ - --transforms='strip_unused_nodes(type=float, shape="1,64,64,3") - strip_unused_nodes(type=float, shape="1,64,64,3") - remove_nodes(op=Identity, op=CheckNumerics) - fold_batch_norms - fold_old_batch_norms - strip_unused_nodes - sort_by_execution_order' - -# DSP模型: -./transform_graph \ - --in_graph=tf_model.pb \ - --out_graph=tf_model_opt.pb \ - --inputs='input' \ - --outputs='output' \ - --transforms='strip_unused_nodes(type=float, shape="1,64,64,3") - strip_unused_nodes(type=float, shape="1,64,64,3") - remove_nodes(op=Identity, op=CheckNumerics) - fold_constants(ignore_errors=true) - fold_batch_norms - fold_old_batch_norms - backport_concatv2 - quantize_weights(minimum_size=2) - quantize_nodes - strip_unused_nodes - sort_by_execution_order' -``` - -- Caffe - -Caffe目前只支持最新版本,旧版本请使用Caffe的工具进行升级。 -```bash -# Upgrade prototxt -$CAFFE_ROOT/build/tools/upgrade_net_proto_text MODEL.prototxt MODEL.new.prototxt - -# Upgrade caffemodel -$CAFFE_ROOT/build/tools/upgrade_net_proto_binary MODEL.caffemodel MODEL.new.caffemodel - -``` - -3\. 生成模型静态库 - -模型静态库的生成需要使用目标机型,***并且要求必须在目标SOC的机型上编译生成静态库。*** - - -我们提供了`mace_tools.py`工具,可以将模型文件转换成静态库。`tools/mace_tools.py`使用步骤: - - -3\.1 配置文件 - -配置文件使用yml文件格式,配置项如下: -```yaml -# 配置文件名会被用作生成库的名称:libmace-${filename}.a -target_abis: [armeabi-v7a, arm64-v8a] -# 具体机型的soc编号,可以使用`adb shell getprop | grep ro.board.platform | cut -d [ -f3 | cut -d ] -f1`获取 -target_socs: [msm8998] -embed_model_data: 1 -models: # 一个配置文件可以包含多个模型的配置信息,最终生成的库中包含多个模型 - first_net: # 模型的标签,在调度模型的时候,会用这个变量 - platform: tensorflow - model_file_path: path/to/model64.pb # also support http:// and https:// - model_sha256_checksum: 7f7462333406e7dea87222737590ebb7d94490194d2f21a7d72bafa87e64e9f9 - input_nodes: input_node - output_nodes: output_node - input_shapes: 1,64,64,3 - output_shapes: 1,64,64,2 - runtime: gpu - limit_opencl_kernel_time: 0 - dsp_mode: 0 - obfuscate: 1 - fast_conv: 0 - input_files: - - path/to/input_files # support http:// - second_net: - platform: caffe - model_file_path: path/to/model.prototxt - weight_file_path: path/to/weight.caffemodel - model_sha256_checksum: 05d92625809dc9edd6484882335c48c043397aed450a168d75eb8b538e86881a - weight_sha256_checksum: 05d92625809dc9edd6484882335c48c043397aed450a168d75eb8b538e86881a - input_nodes: - - input_node0 - - input_node1 - output_nodes: - - output_node0 - - output_node1 - input_shapes: - - 1,256,256,3 - - 1,128,128,3 - output_shapes: - - 1,256,256,2 - - 1,1,1,2 - runtime: cpu - limit_opencl_kernel_time: 1 - dsp_mode: 0 - obfuscate: 1 - fast_conv: 0 - input_files: - - path/to/input_files # support http:// -``` - -具体配置项含义如下表: - -| 配置项 | 含义 | -| ---------- |:--------------:| -| target_abis | 运行的ABI,可选包括安卓设备的armeabi-v7a,arm64-v8a等,以及开发人员的电脑终端(电脑终端使用‘host’表示)。可以同时指定多个ABI | -| embed_model_data | 是否将模型里的数据嵌入到代码中,默认为1 | -| platform | 模型对应的框架名称 [tensorflow | caffe] | -| model_file_path | 模型的路径,可以是一个http或https的下载链接 | -| weight_file_path | 权重文件的路径,可以是一个http或https的下载链接(caffe model)| -| model_sha256_checksum | The SHA256 checksum of the model file | -| weight_sha256_checksum | The SHA256 checksum of the weight file(caffe model) | -| input_nodes | 优化后的模型或其他框架模型的输入节点, 支持多个节点| -| output_nodes | 优化后的模型或其他框架模型的输出节点, 支持多个节点| -| input_shapes | 格式: NHWC. 模型的输入shape, 支持多个shape| -| output_shapes | 格式: NHWC. 模型的输出shape, 支持多个shape| -| runtime | 运行的设备,可选包含cpu、gpu和dsp | -| limit_opencl_kernel_time | 限制opencl的kernel每个work group运行时间在1ms以内,可能影响性能,默认关闭 | -| dsp_mode | 配置dsp的不同计算方式,以获得不同的精度和性能,一般使用默认值0即可 | -| obfuscate | 是否混淆模型内部各个操作的名称 | -| fast_conv| 使用最快的卷积算法,**可能会导致内存增多**| -| input_files| (可选). 指定模型输入文件,用于结果验证,必须与input_nodes对应。如未指定,则使用[-1,1]的随机值| - -3\.2 运行`tools/mace_tools.py`脚本 -```sh -# print help message -# python tools/mace_tools.py --help -# --config 配置文件的路径 -# --output_dir 编译结果的输出文件目录,默认为`./build` -# --round 调用`examples/mace_run`运行模型的次数,默认为`1` -# --tuning 对opencl的参数调参,该项通常只有开发人员用到,默认为`true` -# --mode 运行模式,包含build/run/validate/merge/all/benchmark,默认为`all` - -# 仅编译模型和生成静态库 -python tools/mace_tools.py --config=models/config.yml --mode=build - -# 测试模型的运行时间 -python tools/mace_tools.py --config=models/config.yml --mode=run --round=1000 - -# 对比编译好的模型在mace上与直接使用tensorflow或者caffe运行的结果,相似度使用`余弦距离表示` -# 其中使用OpenCL设备,默认相似度大于等于`0.995`为通过;DSP设备下,相似度需要达到`0.930`。 -python tools/mace_tools.py --config=models/config.yml --mode=run --round=1000 - -# 将已编译好的多个模型合并成静态库 -# 比如编译了8个模型,决定使用其中2个模型,这时候可以不重新build,直接修改全局配置文件,合并生成静态库 -python tools/mace_tools.py --config=models/config.yml --mode=merge - -# 运行以上所有项(可用于测试速度,建议 round=20) -python tools/mace_tools.py --config=models/config.yml --mode=all --round=1000 - -# 模型Benchmark:查看每个Op的运行时间 -python tools/mace_tools.py --config=models/config.yml --mode=benchmark - -# 查看模型运行时占用内存(如果有多个模型,可能需要注释掉一部分配置,只剩一个模型的配置) -python tools/mace_tools.py --config=models/config.yml --mode=run --round=10000 & -adb shell dumpsys meminfo | grep mace_run -sleep 10 -kill %1 - -``` - -4\. 发布 - -通过前面的步骤,我们得到了包含业务模型的库文件。在业务代码中,我们只需要引入下面3组文件(`./build/`是默认的编译结果输出目录): - -头文件(包含mace.h和各个模型的头文件): - * `./build/${project_name}/${target_abi}/include/mace/public/*.h` - -静态库(包含mace engine、opencl和模型相关库): - * `./build/${project_name}/${target_abi}/*.a` - -动态库(仅编译的模型中包含dsp模式时用到): - * `./build/${project_name}/${target_abi}/libhexagon_controller.so` - -模型数据文件(仅在EMBED_MODEL_DATA=0时产生): - * `./build/${project_name}/data/${MODEL_TAG}.data` - -编译过程中间文件: - * `./build/${project_name}/build/` - -库文件tar包: - * `./build/${project_name}/${project_name}.tar.gz` - -5\. 使用 - -具体使用流程可参考`mace/examples/mace_run.cc`,下面列出关键步骤。 - -```c++ -// 引入头文件 -#include "mace/public/mace.h" -#include "mace/public/{MODEL_TAG}.h" - -// 0. 设置内部存储 -const std::string file_path ="/path/to/store/internel/files"; -std::shared_ptr storage_factory( - new FileStorageFactory(file_path)); -ConfigKVStorageFactory(storage_factory); - -//1. 从文件或代码中Load模型数据,也可通过自定义的方式来Load (例如可自己实现压缩加密等) -// 如果使用的是数据嵌入的方式,将参数设为nullptr。 -unsigned char *model_data = mace::MACE_MODEL_TAG::LoadModelData(FLAGS_model_data_file.c_str()); - -//2. 创建net对象 -NetDef net_def = mace::MACE_MODEL_TAG::CreateNet(model_data); - -//3. 声明设备类型 -DeviceType device_type = DeviceType::GPU; - -//4. 定义输入输出名称数组 -std::vector input_names = {...}; -std::vector output_names = {...}; - -//5. 创建输入输出对象 -std::map inputs; -std::map outputs; -for (size_t i = 0; i < input_count; ++i) { - // Allocate input and output - int64_t input_size = - std::accumulate(input_shapes[i].begin(), input_shapes[i].end(), 1, - std::multiplies()); - auto buffer_in = std::shared_ptr(new float[input_size], - std::default_delete()); - // load input - ... - - inputs[input_names[i]] = mace::MaceTensor(input_shapes[i], buffer_in); -} - -for (size_t i = 0; i < output_count; ++i) { - int64_t output_size = - std::accumulate(output_shapes[i].begin(), output_shapes[i].end(), 1, - std::multiplies()); - auto buffer_out = std::shared_ptr(new float[output_size], - std::default_delete()); - outputs[output_names[i]] = mace::MaceTensor(output_shapes[i], buffer_out); -} - -//6. 创建MaceEngine对象 -mace::MaceEngine engine(&net_def, device_type, input_names, output_names); - -//7. 如果设备类型是GPU或者HEXAGON,可以在此释放model_data -if (device_type == DeviceType::GPU || device_type == DeviceType::HEXAGON) { - mace::MACE_MODEL_TAG::UnloadModelData(model_data); -} - -//8. 执行模型,得到结果 -engine.Run(inputs, &outputs); - -``` - -## 功能列表 -算子持续完善中,有新功能需求请联系我们。 - -| 操作 | Android NN | 状态 | 备注 | -| ------------- |:-------------:|:---------:|:-------------:| -| ADD | Y | Y | | -| AVERAGE_POOL_2D | Y | Y | | -| BATCH_NORM | | Y | 支持与激活层合并 | -| BIAS_ADD | | Y | | -| CHANNEL_SHUFFLE | | | | -| CONCATENATION | Y | Y | | -| CONV_2D | Y | Y | 支持stride,dilations,支持与batch norm和激活层合并 | -| DEPTHWISE_CONV_2D | Y | Y | 目前支持multiplier = 1以及与batch norm和激活层合并 | -| DEPTH_TO_SPACE | Y | | | -| DEQUANTIZE | Y | | | -| EMBEDDING_LOOKUP | Y | | | -| FLOOR | Y | | | -| FULLY_CONNECTED | Y | Y | | -| GROUP_CONV_2D | | | | -| HASHTABLE_LOOKUP | Y | | | -| L2_NORMALIZATION | Y | | | -| L2_POOL_2D | Y | | | -| LOCAL_RESPONSE_NORMALIZATION | Y | | | -| LOGISTIC | Y | Y | | -| LSH_PROJECTION | Y | | | -| LSTM | Y | | | -| MATMUL | | | | -| MAX_POOL_2D | Y | Y | | -| MUL | Y | | | -| PSROI_ALIGN | | | | -| PRELU | | Y | | -| RELU | Y | Y | | -| RELU1 | Y | Y | | -| RELU6 | Y | Y | | -| RELUX | | Y | | -| RESHAPE | Y | | | -| RESIZE_BILINEAR | Y | Y | | -| RNN | Y | | | -| RPN_PROPOSAL_LAYER | | | | -| SOFTMAX | Y | Y | | -| SPACE_TO_DEPTH | Y | | | -| SVDF | Y | | | -| TANH | Y | Y | | - - -## 性能对比 -待整理 -- GitLab