diff --git a/.gitignore b/.gitignore index 8f92118b08bb30531869c28d32d335cc47116350..8c4450181d82116620d880c93789dee9dcda9d73 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,4 @@ metal/images/ metal/paddle-mobile/paddle-mobile/CPU/libpaddle-mobile.a *.xcuserdatad/ */xcuserdata/ +/venv/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f9fbcbc18d0bfe1d634dd6815b16a5f1862e846..9268c9a2d1ab3791805c539eb408560bc3aaff26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ set(CMAKE_CXX_FLAGS "-O3 -s -DNDEBUG ${CMAKE_CXX_FLAGS}") if(IS_IOS) set(CMAKE_CXX_FLAGS "-mfpu=neon -marm -fobjc-abi-version=2 -fobjc-arc \ -std=gnu++11 -stdlib=libc++ -isysroot ${CMAKE_OSX_SYSROOT} ${CMAKE_CXX_FLAGS}") + add_compile_options(-fembed-bitcode) else() set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") endif() diff --git a/README.md b/README.md index de7dd530c94b4a3055cbf07a4a19a55c21457ed0..b86860830066cf1b622ff3b449803b0446794b74 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,8 @@ Paddle-Mobile是PaddlePaddle组织下的项目,是一个致力于嵌入式平 ### 开发文档 开发文档主要是关于编译、运行等问题。做为开发者,它可以和贡献文档共同结合使用。 -[开发文档链接](https://github.com/PaddlePaddle/paddle-mobile/blob/develop/doc/development_doc.md) +* [iOS](https://github.com/PaddlePaddle/paddle-mobile/blob/develop/doc/development_ios.md) +* [Android](https://github.com/PaddlePaddle/paddle-mobile/blob/develop/doc/development_android.md) ### 贡献文档 - [贡献文档链接](https://github.com/PaddlePaddle/paddle-mobile/blob/develop/CONTRIBUTING.md) diff --git a/benchmark/arm_benchmark.md b/benchmark/arm_benchmark.md new file mode 100644 index 0000000000000000000000000000000000000000..280bec16e4baf035eb30138d49b2d31d038aa4c7 --- /dev/null +++ b/benchmark/arm_benchmark.md @@ -0,0 +1,36 @@ +|mobilenet arm v7|1线程|2线程|4线程| +|------------|----|-----|-----| +|麒麟970(ms)|108.180|63.935|37.545| +|麒麟960(ms)|108.588|63.073|36.822| +|高通845(ms)|85.952|48.890|28.641| +|高通835(ms)|105.434|62.752|37.131| +||||| +|mobilenetssd arm v7|1线程|2线程|4线程| +|麒麟970(ms)|212.686|127.205|77.485| +|麒麟960(ms)|212.641|125.338|75.250| +|高通845(ms)|182.863|95.671|56.857| +|高通835(ms)|213.849|127.717|77.006| +||||| +|googlenet(v1) arm v7|1线程|2线程|4线程| +|麒麟970(ms)|335.288|234.559|161.295| +|麒麟960(ms)|354.443|232.642|157.815| +|高通845(ms)|282.007|173.146|122.148| +|高通835(ms)|341.250|233.354|158.554| +||||| +|squeezenet arm v7|1线程|2线程|4线程| +|麒麟970(ms)|83.726|57.944|36.923| +|麒麟960(ms)|85.835|55.762|36.496| +|高通845(ms)|71.301|41.618|28.785| +|高通835(ms)|82.407|56.176|36.455| +||||| +|yolo arm v7|1线程|2线程|4线程| +|麒麟970(ms)|129.658|79.993|49.969| +|麒麟960(ms)|130.208|78.791|48.390| +|高通845(ms)|109.244|61.736|40.600| +|高通835(ms)|130.402|80.863|50.359| + + 测试机型信息: + 麒麟970:荣耀v10 (2.36GHz * 4 + 1.8GHz * 4) + 麒麟960:华为mate9 (2.36GHz * 4 + 1.8GHz * 4) + 骁龙835:小米6 (2.45GHz * 4 + 1.9GHz * 4) + 骁龙845:OPPO FindX (2.80GHz * 4 + 1.8GHz * 4) \ No newline at end of file diff --git a/benchmark/metal_benchmark.md b/benchmark/metal_benchmark.md new file mode 100644 index 0000000000000000000000000000000000000000..e3e5d0750f72fc395c402d516aa9fee02a0fcd7f --- /dev/null +++ b/benchmark/metal_benchmark.md @@ -0,0 +1,10 @@ +|mobilenetfssd|速度| +|------------|-----| +|A9(ms)|33.78| +|A10(ms)|24.05| +|A11(ms)|17.15| +||| +|genet|速度| +|A9(ms) |3.49| +|A10(ms)|2.54| +|A11(ms)|1.43| \ No newline at end of file diff --git a/doc/design_doc.md b/doc/design_doc.md index bf5f78e8d805465418cad8989945f2afa7ab5587..70292c6b0bd617930a9c9458b87cef34dee3347e 100644 --- a/doc/design_doc.md +++ b/doc/design_doc.md @@ -3,7 +3,7 @@ #### 以下是 paddle-mobile 代码的执行流程图: -![执行流程图](http://otkwwi4x8.bkt.clouddn.com/2018-07-02-15305189473720.png) +![执行流程图](http://mms-graph.bj.bcebos.com/paddle-mobile/git_images/flow_chart.png) #### 主要分为: Loader 模块、 Program 模块、 Executor 模块、 op 模块、 kernel 模块、scope variable Tensor 模块 @@ -14,12 +14,12 @@ 先来看一下模型, 模型分为两种结构: 一种为参数文件是散开的, 如下图, 红框为模型结构的 protobuf 文件, 其余为参数文件 -![模型描述](http://otkwwi4x8.bkt.clouddn.com/2018-07-02-15305190629577.png) +![模型描述](http://mms-graph.bj.bcebos.com/paddle-mobile/git_images/model_desc.png) 另一种为参数文件结合在一起的, 如下图, 红框内为模型结构描述的 protobuf 文件, 另一个文件为结合在一起的参数文件 -![模型描述combined](http://otkwwi4x8.bkt.clouddn.com/2018-07-02-15305191057130.png) +![模型描述combined](http://mms-graph.bj.bcebos.com/paddle-mobile/git_images/model_desc_combined.png) loader 模块的作用是将模型结构信息 load 进内存, 将红框内的 protobuf 文件 load 进内存, 并对模型结构进行优化(如将几个细粒度的 op 融合成 粗粒度的 op, 如将 conv、 add、 batchnorm、 relu 融合为 conv\_add\_batchnorm\_relu). @@ -161,7 +161,7 @@ sh build.sh android yolo ### 五. kernel kernel 为 op 的底层运算实现, 主要有两个函数, Init 和 Compute, 分别用来初始化、预处理 和 运算操作, 值得提出的是, kernel 会根据泛型特化到不同的平台, 如图所示: -![设备特化]![](http://otkwwi4x8.bkt.clouddn.com/2018-07-02-15305191401976.png) +![设备特化](http://mms-graph.bj.bcebos.com/paddle-mobile/git_images/devices.png) 不同平台的 kernel 实现, 为同一个 kernel 类不同泛型的特化实现, 目前有三个平台, arm、mali、fpga, 图中的 central-arm-func\ 目录为 op kernel 的 arm 实现, 它承担了 arm\ 目录下 kernel 的底层实现, 同时 arm 处理器作为中央处理器, central-arm-func\ 也可以作为其他协处理器的底层实现, 如: fpga 的某一个 op kernel 还没有 fpga 协处理器的实现, 就可以直接调用使用这里的 arm 实现. diff --git a/doc/development_doc.md b/doc/development_android.md similarity index 79% rename from doc/development_doc.md rename to doc/development_android.md index 3f45f956f00e78c23b60b4c108b8c90cf4065e04..528d7aa2def78103b8dbdcf0329279f029c85cac 100644 --- a/doc/development_doc.md +++ b/doc/development_android.md @@ -1,74 +1,3 @@ -### iOS&Android开发文档 - -# iOS开发文档 - -## 编译 - -```sh - -# 在 paddle-mobile 目录下: -cd tools - -sh build.sh ios - -# 如果只想编译某个特定模型的 op, 则需执行以下命令 -sh build.sh ios googlenet - -# 在这个文件夹下, 你可以拿到生成的 .a 库 -cd ../build/release/ios/build - -``` -#### 常见问题: - -1. No iOS SDK's found in default search path ... - - 这个问题是因为 tools/ios-cmake/ios.toolchain.cmake 找不到你最近使用的 iOS SDK 路径, 所以需要自己进行指定, - 以我当前的环境为例: 在 tools/ios-cmake/ios.toolchain.cmake 143行前添加我本地的 iOS SDK 路径: set(CMAKE_IOS_SDK_ROOT "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk") - -## 集成 - -``` -将上一步生成的: -libpaddle-mobile.a - -/src/ios_io/ 下的 -PaddleMobile.h -``` -拖入工程 - -#### oc 接口 - -接口如下: - -``` -/* - 创建对象 -*/ -- (instancetype)init; - -/* - load 模型, 开辟内存 -*/ -- (BOOL)load:(NSString *)modelPath andWeightsPath:(NSString *)weighsPath; - -/* - 进行预测, means 和 scale 为训练模型时的预处理参数, 如训练时没有做这些预处理则直接使用 predict -*/ -- (NSArray *)predict:(CGImageRef)image dim:(NSArray *)dim means:(NSArray *)means scale:(float)scale; - -/* - 进行预测 -*/ -- (NSArray *)predict:(CGImageRef)image dim:(NSArray *)dim; - -/* - 清理内存 -*/ -- (void)clear; - -``` - - # Android开发文档 用户可通过如下两种方式,交叉编译Android平台上适用的paddle-mobile库: diff --git a/doc/development_arm_linux.md b/doc/development_arm_linux.md new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/doc/development_ios.md b/doc/development_ios.md new file mode 100644 index 0000000000000000000000000000000000000000..1d4f28bd5bcde1c3068ddeae87627ae6686d886a --- /dev/null +++ b/doc/development_ios.md @@ -0,0 +1,85 @@ +# iOS开发文档 + +## CPU + +需要: xcode + +### 编译 + +```sh + +# 在 paddle-mobile 目录下: +cd tools + +sh build.sh ios + +# 如果只想编译某个特定模型的 op, 则需执行以下命令 +sh build.sh ios googlenet + +# 在这个文件夹下, 你可以拿到生成的 .a 库 +cd ../build/release/ios/build + +``` +#### 常见问题: + +1. No iOS SDK's found in default search path ... + + 这个问题是因为 tools/ios-cmake/ios.toolchain.cmake 找不到你最近使用的 iOS SDK 路径, 所以需要自己进行指定, + 以我当前的环境为例: 在 tools/ios-cmake/ios.toolchain.cmake 143行前添加我本地的 iOS SDK 路径: set(CMAKE_IOS_SDK_ROOT "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk") + +### 集成 + +``` +将上一步生成的: +libpaddle-mobile.a + +/src/ios_io/ 下的 +PaddleMobile.h +``` +拖入工程 + +#### oc 接口 + +接口如下: + +``` +/* + 创建对象 +*/ +- (instancetype)init; + +/* + load 模型, 开辟内存 +*/ +- (BOOL)load:(NSString *)modelPath andWeightsPath:(NSString *)weighsPath; + +/* + 进行预测, means 和 scale 为训练模型时的预处理参数, 如训练时没有做这些预处理则直接使用 predict +*/ +- (NSArray *)predict:(CGImageRef)image dim:(NSArray *)dim means:(NSArray *)means scale:(float)scale; + +/* + 进行预测 +*/ +- (NSArray *)predict:(CGImageRef)image dim:(NSArray *)dim; + +/* + 清理内存 +*/ +- (void)clear; + +``` + +## GPU + +需要: xcode、cocoapods + +``` +# 在 paddle-mobile 目录下: +cd metal + +pod install + +open paddle-mobile.xcworkspace + +``` diff --git a/doc/images/devices.png b/doc/images/devices.png deleted file mode 100644 index 413d32c249972ee96f678d50a5cd0b36a2a03e29..0000000000000000000000000000000000000000 Binary files a/doc/images/devices.png and /dev/null differ diff --git a/doc/images/flow_chart.png b/doc/images/flow_chart.png deleted file mode 100644 index c747230da43e2e688d7460704268631758d34596..0000000000000000000000000000000000000000 Binary files a/doc/images/flow_chart.png and /dev/null differ diff --git a/doc/images/model_desc.png b/doc/images/model_desc.png deleted file mode 100644 index 3c026b6192c8e1d84b3a82c3db91e022f35358c2..0000000000000000000000000000000000000000 Binary files a/doc/images/model_desc.png and /dev/null differ diff --git a/doc/images/model_desc_combined.png b/doc/images/model_desc_combined.png deleted file mode 100644 index 38e7388efcfdcad53f4e80ce0ac5d3b993eb986c..0000000000000000000000000000000000000000 Binary files a/doc/images/model_desc_combined.png and /dev/null differ diff --git a/metal/README.md b/metal/README.md index 90c517a2c10c28a9fcf26357e65ce2178a2fd8ac..2da6558b05b051b8b476f259d49fa3845e397b29 100644 --- a/metal/README.md +++ b/metal/README.md @@ -1,3 +1,12 @@ ## Paddle-Mobile -This folder is used to develop metal version for ios gpu +需要: xcode、 cocoapods + +``` +pod install + +open paddle-mobile.xcworkspace + +``` + +Demo 所需依赖的模型可在[这里](http://mms-graph.bj.bcebos.com/paddle-mobile%2FmodelsAndImages.zip)下载 diff --git a/python/tools/imagetools/imagetools.py b/tools/python/imagetools/imagetools.py similarity index 100% rename from python/tools/imagetools/imagetools.py rename to tools/python/imagetools/imagetools.py diff --git a/python/tools/imagetools/img2nchw.py b/tools/python/imagetools/img2nchw.py similarity index 100% rename from python/tools/imagetools/img2nchw.py rename to tools/python/imagetools/img2nchw.py diff --git a/python/tools/imagetools/img2nhwc.py b/tools/python/imagetools/img2nhwc.py similarity index 100% rename from python/tools/imagetools/img2nhwc.py rename to tools/python/imagetools/img2nhwc.py diff --git a/python/tools/imagetools/numpy2binary.py b/tools/python/imagetools/numpy2binary.py similarity index 100% rename from python/tools/imagetools/numpy2binary.py rename to tools/python/imagetools/numpy2binary.py diff --git a/tools/python/modeltools/.gitignore b/tools/python/modeltools/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4108f5244bc039cb95b06e391d51250bb9d0ce42 --- /dev/null +++ b/tools/python/modeltools/.gitignore @@ -0,0 +1,109 @@ +# Created by .ignore support plugin (hsz.mobi) +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +/yolo/datas/ +/mobilenet/datas/ diff --git a/tools/python/modeltools/core/__init__.py b/tools/python/modeltools/core/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/python/tools/mdl2fluid/framework.proto b/tools/python/modeltools/core/framework.proto similarity index 100% rename from python/tools/mdl2fluid/framework.proto rename to tools/python/modeltools/core/framework.proto diff --git a/python/tools/mdl2fluid/framework_pb2.py b/tools/python/modeltools/core/framework_pb2.py similarity index 100% rename from python/tools/mdl2fluid/framework_pb2.py rename to tools/python/modeltools/core/framework_pb2.py diff --git a/python/tools/mdl2fluid/op_types.py b/tools/python/modeltools/core/op_types.py similarity index 59% rename from python/tools/mdl2fluid/op_types.py rename to tools/python/modeltools/core/op_types.py index ff7d78d20835c605dc581ef14ad2d7d5171fea1d..89f6ee47dd5e46ae952c574f246c09f859b8a5db 100644 --- a/python/tools/mdl2fluid/op_types.py +++ b/tools/python/modeltools/core/op_types.py @@ -5,22 +5,28 @@ layer_mdl_conv = 'ConvolutionLayer' layer_mdl_deepwise_conv = 'DepthwiseConvolutionLayer' layer_mdl_relu = 'ReluLayer' layer_mdl_pointwise_add = 'PointwiseConvolutionLayer' +layer_mdl_pooling = 'PoolingLayer' +layer_mdl_softmax = 'SoftmaxLayer' # fluid ops op_fluid_fusion_conv_add = 'fusion_conv_add' op_fluid_relu = 'relu' +op_fluid_pooling = 'pool2d' +op_fluid_softmax = 'softmax' # dict mdk layer --- fluid op mdl2fluid_op_layer_dict = { layer_mdl_conv: op_fluid_fusion_conv_add, layer_mdl_deepwise_conv: op_fluid_fusion_conv_add, layer_mdl_relu: op_fluid_relu, - layer_mdl_pointwise_add: op_fluid_fusion_conv_add + layer_mdl_pointwise_add: op_fluid_fusion_conv_add, + layer_mdl_pooling: op_fluid_pooling, + layer_mdl_softmax: op_fluid_softmax } mdl_outputs_key = "outputs" mdl_inputs_key = "inputs" -mdl_weight_key = "weights" +mdl_weight_key = "weight" mdl_attrs_key = "params" # dict of mdl-input _out param to fluid input out attrs @@ -39,13 +45,30 @@ fusion_conv_add_dict = { relu_dict = { mdl_inputs_key: 'X', mdl_outputs_key: 'Out', - mdl_weight_key: () + # mdl_weight_key: () } + +pool2d_dict = { + mdl_inputs_key: 'X', + mdl_outputs_key: 'Out', + # mdl_weight_key: (), + mdl_attrs_key: ('pooling_type', 'global_pooling') + +} + +softmax_dict = { + mdl_inputs_key: 'X', + mdl_outputs_key: 'Out', + mdl_weight_key: (), + mdl_attrs_key: () +} # mdl layers --- fluid ops op_io_dict = { 'fusion_conv_add': fusion_conv_add_dict, - 'relu': relu_dict + 'relu': relu_dict, + 'pool2d': pool2d_dict, + 'softmax': softmax_dict } # fluid attr key --- mdl params key @@ -60,64 +83,3 @@ fluid_attrs_type_dict = { 'strides': 6, 'groups': 6 } - -# '': "bias_term", 是不是要add 目前 yolo的模型都是 bias_term = 1 - - -# attrs { -# name: "axis" -# type: INT -# i: 1 -# } - - -# attrs_name = { -# 'name': "workspace_size_MB", -# 'type': 'INT', -# 'i': '4096' -# } -# attrs -# { -# name: "data_format" -# type: STRING -# s: "AnyLayout" -# } -# attrs -# { -# name: "use_mkldnn" -# type: BOOLEAN -# b: false -# } -# attrs -# { -# name: "use_cudnn" -# type: BOOLEAN -# b: true -# } -# attrs -# { -# name: "dilations" -# type: INTS -# ints: 1 -# ints: 1 -# } -# attrs -# { -# name: "groups" -# type: INT -# i: 1 -# } -# attrs -# { -# name: "paddings" -# type: INTS -# ints: 0 -# ints: 0 -# } -# attrs -# { -# name: "strides" -# type: INTS -# ints: 1 -# ints: 1 -# } diff --git a/tools/python/modeltools/mobilenet/__init__.py b/tools/python/modeltools/mobilenet/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/python/modeltools/mobilenet/converter_mobilenet.py b/tools/python/modeltools/mobilenet/converter_mobilenet.py new file mode 100644 index 0000000000000000000000000000000000000000..da95c24212f48e3ed03dcf0481c14f3ffa881986 --- /dev/null +++ b/tools/python/modeltools/mobilenet/converter_mobilenet.py @@ -0,0 +1,347 @@ +import json +import os + +from core import framework_pb2 as framework_pb2, op_types as types +from mobilenet.swicher import Swichter +import shutil + + +def load_mdl(mdl_json_path): + # print('mdl json path : ' + mdl_json_path) + with open(mdl_json_path, 'r') as f: + return json.load(f) + + +class Converter: + 'convert mdlmodel to fluidmodel' + + def __init__(self, base_dir, mdl_json_path): + self.mdl_json_path = base_dir + mdl_json_path + self.base_dir = base_dir + print mdl_json_path + self.mdl_json = load_mdl(self.mdl_json_path) + self.program_desc = framework_pb2.ProgramDesc() + self.weight_list_ = [] + self.deepwise_weight_list_ = [] + # print(json_dick) + # layers = (json_dick['layer']) + # for layer in layers: + # print(layer) + + def convert(self): + print 'convert begin.....' + # add block_desc + block_desc = self.program_desc.blocks.add() + block_desc.idx = 0 + block_desc.parent_idx = -1 + self.package_ops(block_desc) + self.package_vars(block_desc) + print 'blocks: ' + print self.program_desc.blocks + print 'convert end.....' + desc_serialize_to_string = self.program_desc.SerializeToString() + + outputmodel_ = self.base_dir + 'datas/target/outputmodel/' + if os.path.exists(outputmodel_): + shutil.rmtree(outputmodel_) + os.makedirs(outputmodel_, 0777) + # todo copy weight files + # if os.path.exists(outputmodel_): + # shutil.rmtree(outputmodel_) + # shutil.copytree('yolo/datas/multiobjects/float32s_nchw_with_head/', 'mobilenet/datas/target/outputmodel/') + + f = open(outputmodel_ + "__model__", "wb") + f.write(desc_serialize_to_string) + f.close() + + def package_ops(self, block_desc): + + self.add_op_feed(block_desc) + + # add ops with layer + if 'layer' in self.mdl_json: + + layers_ = self.mdl_json['layer'] + for layer in layers_: + desc_ops_add = block_desc.ops.add() + + # print layer + # for i in layer: + # print i + if 'name' in layer: + l_name = layer['name'] + if 'type' in layer: + self.package_ops_type(desc_ops_add, layer) + + if 'weight' in layer: + self.package_ops_weight2inputs(desc_ops_add, layer) + + if 'output' in layer: + self.package_ops_outputs(desc_ops_add, layer) + + if 'input' in layer: + self.package_ops_inputs(desc_ops_add, layer) + + self.package_ops_attrs(desc_ops_add, layer) + + self.add_op_fetch(block_desc) + + def add_op_feed(self, block_desc): + desc_ops_add = block_desc.ops.add() + inputs_add = desc_ops_add.inputs.add() + inputs_add.parameter = 'X' + inputs_add.arguments.append('feed') + desc_ops_add.type = 'feed' + outputs_add = desc_ops_add.outputs.add() + outputs_add.parameter = 'Out' + outputs_add.arguments.append('data') + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'col' + # boolean + attrs_add.type = 0 + attrs_add.i = 0 + + def add_op_fetch(self, block_desc): + desc_ops_add = block_desc.ops.add() + inputs_add = desc_ops_add.inputs.add() + inputs_add.parameter = 'X' + inputs_add.arguments.append('conv_pred_87') + desc_ops_add.type = 'fetch' + outputs_add = desc_ops_add.outputs.add() + outputs_add.parameter = 'Out' + outputs_add.arguments.append('fetch') + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'col' + # boolean + attrs_add.type = 0 + attrs_add.i = 0 + + @staticmethod + def package_ops_attrs(desc_ops_add, layer): + # print l_params + # print desc_ops_add.type + if desc_ops_add.type == types.op_fluid_fusion_conv_add: + Converter.pack_fusion_conv_add_attr(desc_ops_add, layer) + elif desc_ops_add.type == types.op_fluid_relu: + # fusion_conv_add : attrs + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'use_mkldnn' + # boolean + attrs_add.type = 6 + attrs_add.b = 0 + + @staticmethod + def pack_fusion_conv_add_attr(desc_ops_add, layer): + + # fusion_conv_add : attrs + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'workspace_size_MB' + # 0-->INT + attrs_add.type = 0 + attrs_add.i = 4096 + + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'data_format' + # 2-->STRING + attrs_add.type = 2 + attrs_add.s = 'AnyLayout' + + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'use_mkldnn' + # boolean + attrs_add.type = 6 + attrs_add.b = 0 + + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'use_cudnn' + # boolean + attrs_add.type = 6 + attrs_add.b = 1 + + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'dilations' + # ints + attrs_add.type = 3 + attrs_add.ints.append(1) + attrs_add.ints.append(1) + + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'axis' + # int + attrs_add.type = 0 + attrs_add.i = 1 + + if 'param' in layer: + l_params = layer['param'] + + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'paddings' + # ints + attrs_add.type = 3 + attrs_add.ints.append(l_params[types.fusion_conv_add_attrs_dict.get('paddings')]) + attrs_add.ints.append(l_params[types.fusion_conv_add_attrs_dict.get('paddings')]) + + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'strides' + # ints + attrs_add.type = 3 + attrs_add.ints.append(l_params[types.fusion_conv_add_attrs_dict.get('strides')]) + attrs_add.ints.append(l_params[types.fusion_conv_add_attrs_dict.get('strides')]) + + attrs_add = desc_ops_add.attrs.add() + attrs_add.name = 'groups' + # int + attrs_add.type = 0 + attrs_add.i = l_params[types.fusion_conv_add_attrs_dict.get('groups')] + # attrs_add.i = 1 + + # + # op_attrs_tupl = types.op_io_dict.get(desc_ops_add.type) \ + # .get(types.mdl_attrs_key) + # + # + # + # + # # group stride padding + # print '----------------------' + # for i, val in enumerate(op_attrs_tupl): + # attrs_add = desc_ops_add.attrs.add() + # attr_name = op_attrs_tupl[i] + # print attr_name + # attrs_add.name = attr_name + # attrs_add.type = types.fluid_attrs_type_dict.get(attr_name) + # attrs_add. + # print l_params[types.fusion_conv_add_attrs_dict.get(attr_name)] + + # for p in l_params: + # attrs_add = desc_ops_add.attrs.add() + + @staticmethod + def package_ops_inputs(desc_ops_add, layer): + l_inputs = layer['input'] + for i in l_inputs: + inputs_add = desc_ops_add.inputs.add() + # print i + inputs_add.parameter = types.op_io_dict.get(desc_ops_add.type).get(types.mdl_inputs_key) + inputs_add.arguments.append(i) + + @staticmethod + def package_ops_outputs(desc_ops_add, layer): + l_outputs = layer['output'] + for o in l_outputs: + # print o + outputs_add = desc_ops_add.outputs.add() + dict = types.op_io_dict.get(desc_ops_add.type) + print 'desc_ops_add.type: ' + desc_ops_add.type + print dict + outputs_add.parameter = dict.get(types.mdl_outputs_key) + outputs_add.arguments.append(o) + + def package_ops_weight2inputs(self, desc_ops_add, layer): + l_weights = layer['weight'] + for w in l_weights: + self.weight_list_.append(w) + + if layer['type'] == types.layer_mdl_deepwise_conv: + # print l_weights[0] + self.deepwise_weight_list_.append(l_weights[0]) + + op_weight_tup = types.op_io_dict.get(desc_ops_add.type).get(types.mdl_weight_key) + if op_weight_tup is not None: + # print len(op_weight_tup) + for i, val in enumerate(op_weight_tup): + # print i + # print val + inputs_add = desc_ops_add.inputs.add() + inputs_add.parameter = op_weight_tup[i] + inputs_add.arguments.append(l_weights[i]) + + # for w in l_weights: + # inputs_add = desc_ops_add.inputs.add() + # # print w + # inputs_add.parameter = op_weight_tup[0] + # inputs_add.arguments.append(w) + + @staticmethod + def package_ops_type(desc_ops_add, layer): + l_type = layer['type'] + # print l_type + # print mdl2fluid_op_layer_dict.get(l_type) + desc_ops_add.type = types.mdl2fluid_op_layer_dict.get(l_type) + + def package_vars(self, block_desc): + vars_add = block_desc.vars.add() + vars_add.name = 'feed' + vars_add.type.type = 9 # 9 is FEED_MINIBATCH + vars_add.persistable = 1 + # fetch + vars_add = block_desc.vars.add() + vars_add.name = 'fetch' + vars_add.type.type = 10 # 10 is fetch list + vars_add.persistable = 1 + + json_matrix_ = self.mdl_json['matrix'] + # print json_matrix_ + for j in json_matrix_: + vars_add = block_desc.vars.add() + vars_add.name = j + vars_add.type.type = 7 # 7 is lodtensor + # print j + tensor = vars_add.type.lod_tensor.tensor + tensor.data_type = 5 # 5 is FP32 + + # print json_matrix_ + + dims_of_matrix = json_matrix_.get(j) + # dims_size = len(dims_of_matrix) + # print dims_size + + # if dims_size == 4: + # tensor.dims.append(dims_of_matrix[0]) # N + # tensor.dims.append(dims_of_matrix[3]) # C + # tensor.dims.append(dims_of_matrix[1]) # H + # tensor.dims.append(dims_of_matrix[2]) # W + # else: + + # issues in mdl model filter swich n and c + if j in self.deepwise_weight_list_ and len(dims_of_matrix) == 4: + print j + tensor.dims.append(dims_of_matrix[1]) + tensor.dims.append(dims_of_matrix[0]) + tensor.dims.append(dims_of_matrix[2]) + tensor.dims.append(dims_of_matrix[3]) + print tensor.dims + else: + for dims in dims_of_matrix: + # print dims + tensor.dims.append(dims) + + if j in self.weight_list_: + vars_add.persistable = 1 + dims_size = len(dims_of_matrix) + # print dims_size + # if dims_size == 4: + # # convert weight from nhwc to nchw + # Swichter().nhwc2nchw_one_slice_add_head( + # 'yolo/datas/multiobjects/float32s_nhwc/' + j + '.bin', + # 'yolo/datas/multiobjects/float32s_nchw_with_head/' + j, + # 'yolo/datas/multiobjects/float32s_nchw/' + j + '.tmp', + # dims_of_matrix[0], + # dims_of_matrix[1], + # dims_of_matrix[2], + # dims_of_matrix[3] + # ) + # else: + # Swichter().copy_add_head( + # 'yolo/datas/multiobjects/float32s_nhwc/' + j + '.bin', + # 'yolo/datas/multiobjects/float32s_nchw_with_head/' + j, + # 'yolo/datas/multiobjects/float32s_nchw/' + j + '.tmp' + # ) + else: + vars_add.persistable = 0 + + +mdl_path = "datas/sourcemodels/cls231_0802/mobileNetModel.json" +base_dir = "/Users/xiebaiyuan/PaddleProject/paddle-mobile/tools/python/modeltools/mobilenet/" +converter = Converter(base_dir, mdl_path) +converter.convert() diff --git a/python/tools/mdl2fluid/swicher.py b/tools/python/modeltools/mobilenet/swicher.py similarity index 86% rename from python/tools/mdl2fluid/swicher.py rename to tools/python/modeltools/mobilenet/swicher.py index bfe0360fd5b32f5e6fa61f6f05a0a384fb3a1e9b..04c10806029c562f429da583dcff7212b94cb162 100644 --- a/python/tools/mdl2fluid/swicher.py +++ b/tools/python/modeltools/mobilenet/swicher.py @@ -58,7 +58,7 @@ class Swichter: to_file = open(to_file_name, "wb") tmp = tmp_file.read() - head = self.read_head('/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/yolo/conv1_biases') + head = self.read_head('yolo/datas/yolo/conv1_biases') to_file.write(head) to_file.write(tmp) tmp_file.close() @@ -77,7 +77,7 @@ class Swichter: to_file = open(to_file_name, "wb") # tmp_file = open(tmp_file_name, "wb") - head = self.read_head('/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/yolo/conv1_biases') + head = self.read_head('yolo/datas/yolo/conv1_biases') to_file.write(head) to_file.write(from_file.read()) from_file.close() @@ -96,7 +96,7 @@ class Swichter: to_file = open(to_file_name, "wb") # tmp_file = open(tmp_file_name, "wb") - head = self.read_head('/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/yolo/conv1_biases') + head = self.read_head('yolo/datas/yolo/conv1_biases') to_file.write(head) to_file.write(read) from_file.close() @@ -104,12 +104,12 @@ class Swichter: pass # Swichter().nhwc2nchw_one_slice_add_head( -# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nhwc/conv1_0.bin', -# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw_with_head/conv1_0', -# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw/.tmp', +# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/modeltools/multiobjects/float32s_nhwc/conv1_0.bin', +# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/modeltools/multiobjects/float32s_nchw_with_head/conv1_0', +# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/modeltools/multiobjects/float32s_nchw/.tmp', # 32, # 3, 3, 3) -# Swichter().read_head('/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/yolo/conv1_biases') +# Swichter().read_head('/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/modeltools/yolo/conv1_biases') # Swichter().copy_add_head('datas/model.0.0.weight', 'datas/conv1_0', '') diff --git a/tools/python/modeltools/tools/__init__.py b/tools/python/modeltools/tools/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/python/tools/mdl2fluid/float2halffloat.py b/tools/python/modeltools/tools/float2halffloat.py similarity index 100% rename from python/tools/mdl2fluid/float2halffloat.py rename to tools/python/modeltools/tools/float2halffloat.py diff --git a/python/tools/mdl2fluid/loader.py b/tools/python/modeltools/tools/loader.py similarity index 73% rename from python/tools/mdl2fluid/loader.py rename to tools/python/modeltools/tools/loader.py index ef2258e365a84003b7b90ac480abbd9798f48f59..cb996c8bedd78004e667f1433bfdb20785e7792f 100644 --- a/python/tools/mdl2fluid/loader.py +++ b/tools/python/modeltools/tools/loader.py @@ -1,9 +1,4 @@ -import datetime import json -import os - -import google.protobuf as pbg -import framework_pb2 as framework_pb2 def loadmdl(json_path): diff --git a/python/tools/mdl2fluid/model_combine.py b/tools/python/modeltools/tools/model_combine.py similarity index 100% rename from python/tools/mdl2fluid/model_combine.py rename to tools/python/modeltools/tools/model_combine.py diff --git a/python/tools/mdl2fluid/model_reader.py b/tools/python/modeltools/tools/model_reader.py similarity index 71% rename from python/tools/mdl2fluid/model_reader.py rename to tools/python/modeltools/tools/model_reader.py index 8d53350db20739526b77663f791942299d4bc149..5f6e5f0cb9da8fb349e35211ed56f77bb9cf95da 100644 --- a/python/tools/mdl2fluid/model_reader.py +++ b/tools/python/modeltools/tools/model_reader.py @@ -1,6 +1,6 @@ import os -import framework_pb2 as framework_pb2 +from core import framework_pb2 as framework_pb2 def read_model(model_path): @@ -16,7 +16,7 @@ def read_model(model_path): # print desc.blocks except IOError: - print ": File not found. Creating a new file." + print ": File not found." def get_file_size(file_path): @@ -26,5 +26,5 @@ def get_file_size(file_path): return round(fsize, 2) -path = "newyolo/__model__" +path = '/Users/xiebaiyuan/PaddleProject/paddle-mobile/tools/python/modeltools/mobilenet/datas/sourcemodels/mobilenet_example/mobilenet/__model__' read_model(path) diff --git a/tools/python/modeltools/yolo/__init__.py b/tools/python/modeltools/yolo/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/python/tools/mdl2fluid/mdl2fluid.py b/tools/python/modeltools/yolo/mdl2fluid.py similarity index 89% rename from python/tools/mdl2fluid/mdl2fluid.py rename to tools/python/modeltools/yolo/mdl2fluid.py index a57a01d09eaf236fd9f890dcb9e8eead19aa7868..2c2d0f3e9498254f26da6ff1b88b8a33e1b31d27 100644 --- a/python/tools/mdl2fluid/mdl2fluid.py +++ b/tools/python/modeltools/yolo/mdl2fluid.py @@ -1,9 +1,7 @@ import json -import os -import framework_pb2 as framework_pb2 -import op_types as types -from swicher import Swichter +from core import framework_pb2 as framework_pb2, op_types as types +from yolo.swicher import Swichter import shutil @@ -40,10 +38,10 @@ class Converter: print self.program_desc.blocks print 'convert end.....' desc_serialize_to_string = self.program_desc.SerializeToString() - shutil.rmtree('newyolo/') - shutil.copytree('multiobjects/float32s_nchw_with_head', 'newyolo/') + shutil.rmtree('yolo/datas/newyolo/') + shutil.copytree('yolo/datas/multiobjects/float32s_nchw_with_head/', 'yolo/datas/newyolo/') - f = open("newyolo/__model__", "wb") + f = open("yolo/datas/newyolo/__model__", "wb") f.write(desc_serialize_to_string) f.close() @@ -312,9 +310,9 @@ class Converter: if dims_size == 4: # convert weight from nhwc to nchw Swichter().nhwc2nchw_one_slice_add_head( - '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nhwc/' + j + '.bin', - '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw_with_head/' + j, - '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw/' + j + '.tmp', + 'yolo/datas/multiobjects/float32s_nhwc/' + j + '.bin', + 'yolo/datas/multiobjects/float32s_nchw_with_head/' + j, + 'yolo/datas/multiobjects/float32s_nchw/' + j + '.tmp', dims_of_matrix[0], dims_of_matrix[1], dims_of_matrix[2], @@ -322,14 +320,14 @@ class Converter: ) else: Swichter().copy_add_head( - '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nhwc/' + j + '.bin', - '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw_with_head/' + j, - '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/float32s_nchw/' + j + '.tmp' + 'yolo/datas/multiobjects/float32s_nhwc/' + j + '.bin', + 'yolo/datas/multiobjects/float32s_nchw_with_head/' + j, + 'yolo/datas/multiobjects/float32s_nchw/' + j + '.tmp' ) else: vars_add.persistable = 0 -mdl_path = "/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/mdl2fluid/multiobjects/YOLO_Universal.json" +mdl_path = "yolo/datas/multiobjects/YOLO_Universal.json" converter = Converter(mdl_path) converter.convert() diff --git a/tools/python/modeltools/yolo/swicher.py b/tools/python/modeltools/yolo/swicher.py new file mode 100644 index 0000000000000000000000000000000000000000..04c10806029c562f429da583dcff7212b94cb162 --- /dev/null +++ b/tools/python/modeltools/yolo/swicher.py @@ -0,0 +1,115 @@ +from array import array + + +class Swichter: + def __init__(self): + pass + + def nhwc2nchw_one_slice(self, from_file_name, to_file_name, batch, channel, height, width): + from_file = open(from_file_name, "rb") + to_file = open(to_file_name, "wb") + + float_array = array("f") + float_array.fromfile(from_file, width * height * batch * channel) + float_write_array = array("f") + + for b in range(batch): + for c in range(channel): + for h in range(height): + for w in range(width): + float_value = float_array[b * channel * width * height + + channel * (h * width + w) + c] + + float_write_array.append(float_value) + + float_write_array.tofile(to_file) + from_file.close() + to_file.close() + + def copy(self, from_file_name, to_file_name): + from_file = open(from_file_name, "rb") + to_file = open(to_file_name, "wb") + + to_file.write(from_file.read()) + from_file.close() + to_file.close() + + def nhwc2nchw_one_slice_add_head(self, from_file_name, to_file_name, tmp_file_name, batch, channel, height, width): + from_file = open(from_file_name, "rb") + tmp_file = open(tmp_file_name, "wb+") + float_array = array("f") + float_array.fromfile(from_file, width * height * batch * channel) + float_write_array = array("f") + + for b in range(batch): + for c in range(channel): + for h in range(height): + for w in range(width): + float_value = float_array[b * channel * width * height + + channel * (h * width + w) + c] + + float_write_array.append(float_value) + + float_write_array.tofile(tmp_file) + tmp_file.close() + from_file.close() + + tmp_file = open(tmp_file_name, "rb") + to_file = open(to_file_name, "wb") + + tmp = tmp_file.read() + head = self.read_head('yolo/datas/yolo/conv1_biases') + to_file.write(head) + to_file.write(tmp) + tmp_file.close() + to_file.close() + + def read_head(self, head_file): + from_file = open(head_file, "rb") + read = from_file.read(24) + # print read + from_file.close() + # print read + return read + + def copy_add_head(self, from_file_name, to_file_name, tmp_file_name): + from_file = open(from_file_name, "rb") + to_file = open(to_file_name, "wb") + # tmp_file = open(tmp_file_name, "wb") + + head = self.read_head('yolo/datas/yolo/conv1_biases') + to_file.write(head) + to_file.write(from_file.read()) + from_file.close() + to_file.close() + pass + + def copy_padding_add_head(self, from_file_name, to_file_name, tmp_file_name, padding): + print'padding = %d' % padding + from_file = open(from_file_name, "rb") + # print len(from_file.read()) + from_file.seek(padding, 0) + + read = from_file.read() + print len(read) + + to_file = open(to_file_name, "wb") + # tmp_file = open(tmp_file_name, "wb") + + head = self.read_head('yolo/datas/yolo/conv1_biases') + to_file.write(head) + to_file.write(read) + from_file.close() + to_file.close() + pass + +# Swichter().nhwc2nchw_one_slice_add_head( +# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/modeltools/multiobjects/float32s_nhwc/conv1_0.bin', +# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/modeltools/multiobjects/float32s_nchw_with_head/conv1_0', +# '/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/modeltools/multiobjects/float32s_nchw/.tmp', +# 32, +# 3, 3, 3) + +# Swichter().read_head('/Users/xiebaiyuan/PaddleProject/paddle-mobile/python/tools/modeltools/yolo/conv1_biases') + +# Swichter().copy_add_head('datas/model.0.0.weight', 'datas/conv1_0', '')