diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1a25d65e02afb09dabc96e1ec241346cff34f6f2..f07b2eeb93daa827361acc97951483c21092135f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -183,6 +183,10 @@ upstream 接下来等待 review,如果有需要修改的地方,参照上述步骤更新 origin 中的对应分支即可。 + +![](http://otkwwi4x8.bkt.clouddn.com/2018-06-20-15294877166787.jpg) +之后就可以提交代码了 + ## 删除远程分支 在 PR 被 merge 进主仓库后,我们可以在 PR 的页面删除远程仓库的分支。 @@ -219,7 +223,8 @@ upstream - 原因:如果仅仅修改一个文件但提交了十几个commit,每个commit只做了少量的修改,这会给评审人带来很大困扰。评审人需要逐一查看每个commit才能知道做了哪些修改,且不排除commit之间的修改存在相互覆盖的情况。 - 建议:每次提交时,保持尽量少的commit,可以通过`git commit --amend`补充上次的commit。对已经Push到远程仓库的多个commit,可以参考[squash commits after push](http://stackoverflow.com/questions/5667884/how-to-squash-commits-in-git-after-they-have-been-pushed)。 - 请注意每个commit的名称:应能反映当前commit的内容,不能太随意。 -3. 如果解决了某个Issue的问题,请在该Pull Request的**第一个**评论框中加上:`fix #issue_number`,这样当该PUll Request被合并后,会自动关闭对应的Issue。关键词包括:close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved,请选择合适的词汇。详细可参考[Closing issues via commit messages](https://help.github.com/articles/closing-issues-via-commit-messages)。 + +3. 如果解决了某个Issue的问题,请在该Pull Request的**第一个**评论框中加上:`fix #issue_number`,这样当该Pull Request被合并后,会自动关闭对应的Issue。关键词包括:close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved,请选择合适的词汇。详细可参考[Closing issues via commit messages](https://help.github.com/articles/closing-issues-via-commit-messages)。 此外,在回复评审人意见时,请您遵守以下约定: diff --git a/README.md b/README.md index b6ae2beed999d146c64ffc9ee495373d9b77a175..f8957545a64fff7723bd4c1c6bc2db1fd90d728b 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,104 @@ -# Paddle-Mobile - +# Paddle-Mobile [![Build Status](https://travis-ci.org/PaddlePaddle/paddle-mobile.svg?branch=develop&longCache=true&style=flat-square)](https://travis-ci.org/PaddlePaddle/paddle-mobile) -[![License](https://img.shields.io/badge/license-Apache%202-brightgreen.svg)](LICENSE) +[![Documentation Status](https://img.shields.io/badge/中文文档-最新-brightgreen.svg)](https://github.com/PaddlePaddle/paddle-mobile/tree/develop/doc) +[![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](LICENSE) + -This project is used to develop the next version deep learning freamwork for mobile device. -# Development -[Used model in development](https://mms-mis.cdn.bcebos.com/paddle-mobile/models.zip) +欢迎来到 Paddle-Mobile GitHub 项目。 -## cross-compilation to android +Paddle-Moible是PaddlePaddle组织下的项目,是一个致力于嵌入式平台的深度学习的框架。Paddle-Moible设计思想和PaddlePaddle的最新版fluid版本保持了高度一致,同时针对嵌入式做了大量优化。设计之初就对嵌入式的性能、体积、能耗、硬件平台覆盖等方面做了考虑。 -* NDK is required -* ANDROID_NDK environment variable is required +## Features -```bash -sh build.sh android -``` +- **ARM CPU** -## build for x86 -paddle-mobile is to run on arm platform. x86 only used to test not arm assembly code. So do not recommend compiling x86. + arm cpu是paddle-mobile的主要支持方向,cpu的通用性一直是其优势。嵌入式深度学习,需要大量的cpu汇编实现。我们正在紧锣密鼓的编码,为的是能充分硬件的每一点加速能力。 + arm cpu的优化工作还在进行中,现在使用了常规的cpu优化。在arm a73上paddle-mobile现在单核运行一次mobilenet 1.0是160+ms,显然这不是我们的最终目标,我们正在用大量的汇编改写,后续性能仍会有巨大提升空间。 + +- **Mali GPU** -Now only support osx. + Mali GPU是百度和ARM合作开发的,双方团队近期都在致力于将paddle的op能无缝运行在ACL(arm compute library)。目前已经支持squeezenet,googlenet,resnet等几个网络模型,后续会继续加大力度。使全部移动端paddle op能高效运行在mali gpu上。 + 在 +- **苹果设备的GPU Metal实现** + + 基于Metal实现的苹果设备的GPU预测库,也已经在实现中,近期也会有相应可运行版本。 + +- **FPGA** + + FPGA实现正在进行中,是基于Xilinx的ZU5目标开发板。 + +- **灵活性** + + * paddle-mobile cpu版不依赖任何第三库, 可进行快速集成。 + * 使用泛型特化进行平台切换, 可灵活切换 cpu、gpu 和其他协处理器。 + * 可根据特定的常见网络, 进行编译特定的 op, 降低编译时间, 减小包大小。 + * 使用 docker 编译, 提供统一的编译环境。 + * 高可拓展性, 方便拓展其他协处理器, 提供高性能 arm 算子实现, 方便其他协处理器开发者集成开发。 + * 直接兼容 paddle-fluid 模型, 不需要额外的转换操作。 + +- **体积** + + paddle-mobile从设计之初就深入考虑到移动端的包体积的问题,cpu实现中没有外部依赖。在编译过程中,如果该网络不需要的op是完全不会被打入的。同时编译选项优化也为体积压缩提供了帮助。 + 除了二进制体积,我们对代码体积极力避免过大。整个仓库不到5m的代码体积。 + + +## 文档 + +### 设计文档 + +关于paddle-mobile设计文档在下面链接中,如果想了解更多内容。[issue](https://github.com/PaddlePaddle/paddle-mobile/issues)中会有很多早期的设计和讨论过程。 +[设计文档链接](https://github.com/PaddlePaddle/paddle-mobile/blob/develop/doc/design_doc.md) + +### 开发文档 + +开发文档主要是关于编译、运行等问题。做为开发者,它可以和贡献文档共同结合使用。 +[开发文档]()https://github.com/PaddlePaddle/paddle-mobile/blob/develop/doc/development_doc.md + +### 贡献文档 +- [贡献文档链接](https://github.com/PaddlePaddle/paddle-mobile/blob/develop/CONTRIBUTING.md) +- 上面文档中涵盖了主要的贡献代码流程,如果在实践中您还遇到了其他问题,可以发[issue](https://github.com/PaddlePaddle/paddle-mobile/issues)。我们看到后会尽快处理。 + + +## 模型获得 +目前Paddle-Mobile仅支持Paddle fluid训练的模型。如果你手中的模型是不同种类的模型,需要进行模型转换才可以运行。 +### 1. 直接使用Paddle Fluid训练 +该方式最为可靠,推荐方式 +### 2. caffe转为Paddle Fluid模型 +[链接](https://github.com/PaddlePaddle/models/tree/develop/fluid/image_classification/caffe2fluid) +### 3. ONNX +ONNX全称为“Open Neural Network Exchange”,即“开放的神经网络切换”。该项目的目的是让不同的神经网络开发框架做到互通互用。 + +除直接使用PaddlePaddle训练fluid版本的模型外,还可以通过onnx转换得到个别Paddle fluid模型。 + +目前,百度也在做onnx支持工作。相关转换项目在这里:[paddle-onnx](https://github.com/PaddlePaddle/paddle-onnx)。 + +```flow +st=>start: 其他模型 +op1=>operation: onnx模型 +op2=>operation: paddle-onnx +op3=>operation: paddle fluid模型 +e=>end: paddle-mobile运行 +st->op1->op2->op3->e ``` -sh build.sh mac -``` -## Old Version of Mobile-Deep-Learning -The old version of MDL was I moved to here [Mobile-Deep-Learning](https://github.com/allonli/mobile-deep-learning) +### 4. 部分测试模型下载 +[下载链接](https://mms-mis.cdn.bcebos.com/paddle-mobile/models.zip) + +## 问题解决 + +欢迎提出或解决我们的问题,有疑问可以发issue. [Github Issues](https://github.com/PaddlePaddle/paddle-mobile/issues). + +## Copyright and License +Paddle-Mobile 提供相对宽松的Apache-2.0开源协议 [Apache-2.0 license](LICENSE). + +## 旧版 Mobile-Deep-Learning +原MDL(Mobile-Deep-Learning)工程被迁移到了这里 [Mobile-Deep-Learning](https://github.com/allonli/mobile-deep-learning) diff --git a/doc/design_doc.md b/doc/design_doc.md index 3ab649236dcb93fd9181d424870a87fec418448d..3407c78443de0f0c7d9ebab848122c2e089e9e41 100644 --- a/doc/design_doc.md +++ b/doc/design_doc.md @@ -3,8 +3,8 @@ #### 以下是 paddle-mobile 代码的执行流程图: -![执行流程图](./images/flow_chart.png "执行流程图") +![执行流程图](http://otkwwi4x8.bkt.clouddn.com/2018-07-02-15305189473720.png) #### 主要分为: Loader 模块、 Program 模块、 Executor 模块、 op 模块、 kernel 模块、scope variable Tensor 模块 @@ -15,11 +15,13 @@ 先来看一下模型, 模型分为两种结构: 一种为参数文件是散开的, 如下图, 红框为模型结构的 protobuf 文件, 其余为参数文件 -![模型描述](./images/model_desc.png "模型描述") + +![模型描述](http://otkwwi4x8.bkt.clouddn.com/2018-07-02-15305190629577.png) + 另一种为参数文件结合在一起的, 如下图, 红框内为模型结构描述的 protobuf 文件, 另一个文件为结合在一起的参数文件 -![模型描述combined](./images/model_desc_combined.png "模型描述combined") +![模型描述combined](http://otkwwi4x8.bkt.clouddn.com/2018-07-02-15305191057130.png) loader 模块的作用是将模型结构信息 load 进内存, 将红框内的 protobuf 文件 load 进内存, 并对模型结构进行优化(如将几个细粒度的 op 融合成 粗粒度的 op, 如将 conv、 add、 batchnorm、 relu 融合为 conv\_add\_batchnorm\_relu). 方便进行算法优化. @@ -160,7 +162,7 @@ sh build.sh android yolo ### 五. kernel kernel 为 op 的底层运算实现, 主要有两个函数, Init 和 Compute, 分别用来初始化、预处理 和 运算操作, 值得提出的是, kernel 会根据泛型特化到不同的平台, 如图所示: -![设备特化](./images/devices.png "设备特化") +![设备特化]![](http://otkwwi4x8.bkt.clouddn.com/2018-07-02-15305191401976.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/src/operators/kernel/central-arm-func/conv_add_bn_relu_func.h b/src/operators/kernel/central-arm-func/conv_add_bn_relu_func.h index a2604ebd49789ba06c85bbbf8ba4aef0d737ac7d..3f0b2496197873d90b08b1dafd8bcad0968f59a5 100644 --- a/src/operators/kernel/central-arm-func/conv_add_bn_relu_func.h +++ b/src/operators/kernel/central-arm-func/conv_add_bn_relu_func.h @@ -21,6 +21,7 @@ limitations under the License. */ namespace paddle_mobile { namespace operators { void ConvAddBNReluBasic(const FusionConvAddBNReluParam ¶m) { + const Tensor *input = param.Input(); Tensor filter = *param.Filter(); Tensor bias = *param.Bias(); @@ -32,6 +33,7 @@ void ConvAddBNReluBasic(const FusionConvAddBNReluParam ¶m) { Tensor *output = param.Output(); math::expand_bias(bias, axis, output->dims()); output->ShareDataWith(bias); + int groups = param.Groups(); std::vector strides = param.Strides(); std::vector paddings = param.Paddings(); diff --git a/src/operators/kernel/central-arm-func/conv_arm_func.h b/src/operators/kernel/central-arm-func/conv_arm_func.h index 7f27b9909829425889d3f73975625aa982f81916..6accf1937da5343a33d9dd739c125836f080f181 100644 --- a/src/operators/kernel/central-arm-func/conv_arm_func.h +++ b/src/operators/kernel/central-arm-func/conv_arm_func.h @@ -17,6 +17,7 @@ limitations under the License. */ #pragma once #include #include + #include "operators/op_param.h" namespace paddle_mobile { @@ -26,6 +27,7 @@ inline void ConvBasic(const ConvParam ¶m) { const Tensor *input = param.Input(); Tensor filter = *param.Filter(); Tensor *output = param.Output(); + int groups = param.Groups(); std::vector strides = param.Strides(); std::vector paddings = param.Paddings(); @@ -96,6 +98,7 @@ inline void ConvBasic(const ConvParam ¶m) { // vol2col vol2col(in_slice, dilations, strides, paddings, &col); } + // gemm Tensor out_slice = out_batch.Slice(g * out_step, (g + 1) * out_step); Tensor filter_slice = filter.Slice(g * out_step, (g + 1) * out_step); diff --git a/src/operators/kernel/central-arm-func/depthwise_conv_arm_func.h b/src/operators/kernel/central-arm-func/depthwise_conv_arm_func.h index f2c898dbb41f3f94858189ca7d9abe9d2d8ab03e..885f2051f645546c2585caa72aa9c80f8d352e6c 100644 --- a/src/operators/kernel/central-arm-func/depthwise_conv_arm_func.h +++ b/src/operators/kernel/central-arm-func/depthwise_conv_arm_func.h @@ -18,6 +18,7 @@ limitations under the License. */ #include #include #include "operators/kernel/central-arm-func/conv_arm_func.h" + #include "operators/op_param.h" namespace paddle_mobile { diff --git a/src/operators/math/depthwise_conv_3x3.cpp b/src/operators/math/depthwise_conv_3x3.cpp index f7900f4696d84b4d52034319dc147010e2e861bc..116126ce5c083457ab5279126e22fb70a604b08c 100644 --- a/src/operators/math/depthwise_conv_3x3.cpp +++ b/src/operators/math/depthwise_conv_3x3.cpp @@ -292,11 +292,13 @@ void DepthwiseConv3x3s1p1(const Tensor *input, const Tensor *filter, output_data[(l - 1) * l] += bias_data[j]; output_data[l * l - 1] += bias_data[j]; } + for (int i = 1; i < l - 1; ++i) { output_data[i * l] = w01 * input_data[i * l - l] + w02 * input_data[i * l - l + 1] + w11 * input_data[i * l] + w12 * input_data[i * l + 1] + w21 * input_data[i * l + l] + w22 * input_data[i * l + l + 1]; + output_data[i * l + l - 1] = w00 * input_data[i * l + l - 1 - l - 1] + w01 * input_data[i * l + l - 1 - l] + w10 * input_data[i * l + l - 1 - 1] +