diff --git a/src/common/types.cpp b/src/common/types.cpp index c25c5db30c7183b6685db03386ca9a9355ca6958..444789237f573f8da3eaf915abf61493967aabf8 100644 --- a/src/common/types.cpp +++ b/src/common/types.cpp @@ -37,6 +37,7 @@ const char *G_OP_TYPE_FUSION_CONV_ADD = "fusion_conv_add"; const char *G_OP_TYPE_LRN = "lrn"; const char *G_OP_TYPE_MUL = "mul"; const char *G_OP_TYPE_MULTICLASS_NMS = "multiclass_nms"; +const char *G_OP_TYPE_NORM = "norm"; const char *G_OP_TYPE_POLYGON_BOX_TRANSFORM = "polygon_box_transform"; const char *G_OP_TYPE_POOL2D = "pool2d"; const char *G_OP_TYPE_PRIOR_BOX = "prior_box"; @@ -169,5 +170,6 @@ std::unordered_map< {G_OP_TYPE_FUSION_DECONV_ADD_RELU, {{"Input"}, {"Out"}}}, {G_OP_TYPE_SEQUENCE_EXPAND, {{"X", "Y"}, {"Out"}}}, {G_OP_TYPE_SEQUENCE_POOL, {{"X"}, {"Out"}}}, - {G_OP_TYPE_SEQUENCE_SOFTMAX, {{"X"}, {"Out"}}}}; + {G_OP_TYPE_SEQUENCE_SOFTMAX, {{"X"}, {"Out"}}}, + {G_OP_TYPE_NORM, {{"X"}, {"Out", "Norm"}}}}; } // namespace paddle_mobile diff --git a/src/operators/kernel/arm/norm_kernel.cpp b/src/operators/kernel/arm/norm_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32617992cb1a60b44265343092f15316ea087df1 --- /dev/null +++ b/src/operators/kernel/arm/norm_kernel.cpp @@ -0,0 +1,36 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#ifdef NORM_OP + +#include "operators/kernel/norm_kernel.h" +#include "operators/kernel/central-arm-func/norm_arm_func.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool NormKernel::Init(NormParam *param) { + return true; +} + +template <> +void NormKernel::Compute(const NormParam ¶m) { + NormCompute(param); +} + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/kernel/central-arm-func/norm_arm_func.h b/src/operators/kernel/central-arm-func/norm_arm_func.h new file mode 100644 index 0000000000000000000000000000000000000000..e43c03484712cfb1f8baf96a9ca8cccc062672ca --- /dev/null +++ b/src/operators/kernel/central-arm-func/norm_arm_func.h @@ -0,0 +1,114 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#ifdef NORM_OP + +#pragma once + +#include +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +inline void GetDims(const framework::DDim &dim, int axis, int *pre, int *n, + int *post) { + *pre = 1; + *post = 1; + *n = dim[axis]; + for (int i = 0; i < axis; ++i) { + (*pre) *= dim[i]; + } + for (int i = axis + 1; i < dim.size(); ++i) { + (*post) *= dim[i]; + } +} + +template +void NormCompute(const NormParam ¶m) { + const float epsilon = param.Epsilon(); + int axis = param.Axis(); + + const framework::Tensor *input = param.InputX(); + framework::Tensor square; + framework::Tensor *norm = param.OutputNorm(); + framework::Tensor *out = param.Out(); + + auto x_dims = input->dims(); + if (axis < 0) { + axis += x_dims.size(); + } + + int pre, n, post; + GetDims(x_dims, axis, &pre, &n, &post); + square.Resize(input->dims()); + + const float *input_ptr = input->data(); + float *square_ptr = square.mutable_data(); + float *norm_ptr = norm->mutable_data(); + float *out_ptr = out->mutable_data(); + + const float *in_tmp = input_ptr; + float *square_tmp = square_ptr; + for (int i = 0; i < input->numel(); ++i) { + float element = *in_tmp; + *square_tmp = element * element; + square_tmp++; + in_tmp++; + } + + // const float *norm_tmp = norm_ptr; + // for (int i = 0; i < norm->numel(); ++i) { + // *norm_tmp = 0; + // norm_tmp++; + // } + + square_tmp = square_ptr; + float *norm_tmp = norm_ptr; + for (int i = 0; i < pre; ++i) { + for (int j = 0; j < post; ++j) { + for (int k = 0; k < n; ++k) { + if (k == 0) { + *norm_tmp = *square_tmp; + } else { + *norm_tmp += *(square_tmp + k * post); + } + } + float sum = *norm_tmp + epsilon; + *norm_tmp = sqrtf(sum); + norm_tmp++; + square_tmp++; + } + } + + in_tmp = input_ptr; + norm_tmp = norm_ptr; + float *out_tmp = out_ptr; + for (int i = 0; i < pre; ++i) { + for (int k = 0; k < n; ++k) { + for (int j = 0; j < post; ++j) { + *out_tmp = *in_tmp / *norm_tmp; + in_tmp++; + norm_tmp++; + out_tmp++; + } + norm_tmp = norm_ptr + i * post; + } + } +} + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/kernel/norm_kernel.h b/src/operators/kernel/norm_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..4f945bdb8b03a3952dd362df8b36a1db26f3fd93 --- /dev/null +++ b/src/operators/kernel/norm_kernel.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#ifdef NORM_OP + +#pragma once + +#include "framework/operator.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +template +class NormKernel + : public framework::OpKernelBase> { + public: + void Compute(const NormParam ¶m); + bool Init(NormParam *param); +}; + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/norm_op.cpp b/src/operators/norm_op.cpp new file mode 100644 index 0000000000000000000000000000000000000000..deed9f69d1cf40ee70a211b0c9a84e4afeef6623 --- /dev/null +++ b/src/operators/norm_op.cpp @@ -0,0 +1,52 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#ifdef NORM_OP + +#include "operators/norm_op.h" +#include "framework/op_proto_maker.h" +#include "framework/op_registry.h" + +namespace paddle_mobile { +namespace operators { + +template +void NormOp::InferShape() const { + auto x_dims = this->param_.InputX()->dims(); + this->param_.Out()->Resize(x_dims); + + int axis = this->param_.Axis(); + if (axis < 0) { + axis += x_dims.size(); + } + x_dims[axis] = 1; + this->param_.OutputNorm()->Resize(x_dims); +} + +} // namespace operators +} // namespace paddle_mobile + +namespace ops = paddle_mobile::operators; +#ifdef PADDLE_MOBILE_CPU +REGISTER_OPERATOR_CPU(norm, ops::NormOp); +#endif +#ifdef PADDLE_MOBILE_MALI_GPU +#endif +#ifdef PADDLE_MOBILE_FPGA +#endif + +#ifdef PADDLE_MOBILE_CL +#endif + +#endif diff --git a/src/operators/norm_op.h b/src/operators/norm_op.h new file mode 100644 index 0000000000000000000000000000000000000000..5bd6924af1d4aca125795be879cf67c09832965e --- /dev/null +++ b/src/operators/norm_op.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#ifdef NORM_OP + +#pragma once + +#include +#include "framework/operator.h" +#include "operators/kernel/norm_kernel.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { +using std::string; +template +class NormOp + : public framework::OperatorWithKernel, + NormKernel> { + public: + NormOp(const string &type, const VariableNameMap &inputs, + const VariableNameMap &outputs, const framework::AttributeMap &attrs, + std::shared_ptr scope) + : framework::OperatorWithKernel, + NormKernel>( + type, inputs, outputs, attrs, scope) {} + + void InferShape() const override; + + protected: +}; + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/op_param.h b/src/operators/op_param.h index 8976d8be8e0722fe6915af4786d55809a9f8ca7c..385be3b72f233c9a0951f17b8c61c23adc346988 100644 --- a/src/operators/op_param.h +++ b/src/operators/op_param.h @@ -280,6 +280,11 @@ class OpParam { return GetVarValue("OutputBox", outputs, scope); } + template + static T *OutputNormFrom(const VariableNameMap &outputs, const Scope &scope) { + return GetVarValue("Norm", outputs, scope); + } + template static T *OutputVariancesFrom(const VariableNameMap &outputs, const Scope &scope) { @@ -733,6 +738,41 @@ class LrnParam : public OpParam { }; #endif +#ifdef NORM_OP +template +class NormParam : OpParam { + typedef typename DtypeTensorTrait::gtype GType; + typedef typename DtypeTensorTrait::rtype RType; + + public: + NormParam(const VariableNameMap &inputs, const VariableNameMap &outputs, + const AttributeMap &attrs, const Scope &scope) { + input_x_ = InputXFrom(inputs, scope); + out_ = OutFrom(outputs, scope); + output_norm_ = OutputNormFrom(outputs, scope); + epsilon_ = GetAttr("epsilon", attrs); + axis_ = GetAttr("axis", attrs); + } + + const RType *InputX() const { return input_x_; } + + RType *Out() const { return out_; } + + RType *OutputNorm() const { return output_norm_; } + + const float &Epsilon() const { return epsilon_; } + + const int &Axis() const { return axis_; } + + private: + RType *input_x_; + RType *out_; + RType *output_norm_; + float epsilon_; + int axis_; +}; +#endif + #ifdef BATCHNORM_OP template class BatchNormParam : OpParam { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6cab082d98f6247e5254b8bfa4c6a208c50fb42c..2a7f5b23d47c2e53da6e52f0cb8b0ca75058bb38 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -394,4 +394,9 @@ if (NOT FOUND_MATCH) ADD_EXECUTABLE(test-sequence-softmax operators/test_sequence_softmax_op.cpp test_helper.h test_include.h) target_link_libraries(test-sequence-softmax paddle-mobile) + + # gen test + ADD_EXECUTABLE(test-vgg16ssd net/test_vgg16ssd.cpp test_helper.h test_include.h) + target_link_libraries(test-vgg16ssd paddle-mobile) + endif () diff --git a/test/net/test_vgg16ssd.cpp b/test/net/test_vgg16ssd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..387d6f38ea9185d0563b39defbed928bda0186bf --- /dev/null +++ b/test/net/test_vgg16ssd.cpp @@ -0,0 +1,46 @@ +/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include +#include "../test_helper.h" +#include "../test_include.h" + +int main() { + paddle_mobile::PaddleMobile paddle_mobile; + paddle_mobile.SetThreadNum(1); + auto time1 = paddle_mobile::time(); + + auto isok = + paddle_mobile.Load(std::string(g_vgg16_ssd_combined) + "/model", + std::string(g_vgg16_ssd_combined) + "/params", false); + if (isok) { + auto time2 = paddle_mobile::time(); + std::cout << "load cost :" << paddle_mobile::time_diff(time1, time1) << "ms" + << std::endl; + + std::vector dims{1, 3, 300, 300}; + Tensor input_tensor; + SetupTensor(&input_tensor, {1, 3, 300, 300}, static_cast(0), + static_cast(1)); + + std::vector input(input_tensor.data(), + input_tensor.data() + input_tensor.numel()); + + auto vec_result = paddle_mobile.Predict(input, dims); + + DLOG << vec_result; + } + + return 0; +} diff --git a/test/test_helper.h b/test/test_helper.h index 60e907fa6fb301b2e944a6d938f662225a743d41..7d677217a0fddecc23fb354b2b8b5c9a652746cf 100644 --- a/test/test_helper.h +++ b/test/test_helper.h @@ -50,6 +50,7 @@ static const char *g_yolo = "../models/yolo"; static const char *g_yolo_combined = "../models/yolo_combined"; static const char *g_yolo_mul = "../models/d"; static const char *g_fluid_fssd_new = "../models/fluid_fssd_new"; +static const char *g_vgg16_ssd_combined = "../models/vgg16_ssd_combined"; static const char *g_test_image_1x3x224x224 = "../images/test_image_1x3x224x224_float"; static const char *g_test_image_1x3x224x224_banana = diff --git a/tools/ios-cmake/ios.toolchain.cmake b/tools/ios-cmake/ios.toolchain.cmake index 6000f7a8e5dffcd8693b56539f4519840ddd8be8..12dd1721d488cd8ba776b8f302f137ad2d60fe73 100644 --- a/tools/ios-cmake/ios.toolchain.cmake +++ b/tools/ios-cmake/ios.toolchain.cmake @@ -146,6 +146,7 @@ if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) endif (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform") +set(CMAKE_IOS_SDK_ROOT "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk") # Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT if (NOT DEFINED CMAKE_IOS_SDK_ROOT) file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*") diff --git a/tools/op.cmake b/tools/op.cmake index 3563834e77fa5eba363fc64ba337dd30c95a3820..e98e95e4ed29ced5044315dd4fb59a1866964a82 100644 --- a/tools/op.cmake +++ b/tools/op.cmake @@ -215,6 +215,7 @@ endif() if(NOT FOUND_MATCH) message("--default--") + set(NORM_OP ON) set(BATCHNORM_OP ON) set(CONV_TRANSPOSE_OP ON) set(BOXCODER_OP ON) @@ -302,6 +303,9 @@ endif() # option(TRANSPOSE2_OP "" ON) # endif () +if (NORM_OP) + add_definitions(-DNORM_OP) +endif() if (BATCHNORM_OP) add_definitions(-DBATCHNORM_OP) endif()