diff --git a/src/common/types.cpp b/src/common/types.cpp index 56f9ec91445e72bfd886c3e97c28b4cf6c4ce956..278ec923e2de48dfb5b2f3e5bd7ee6f663a3d8fe 100644 --- a/src/common/types.cpp +++ b/src/common/types.cpp @@ -122,6 +122,15 @@ const char *G_OP_TYPE_PAD2D = "pad2d"; const char *G_OP_TYPE_FUSION_DECONV_ADD_BN_RELU = "fusion_deconv_add_bn_relu"; const char *G_OP_TYPE_FUSION_DECONV_ADD_BN = "fusion_deconv_add_bn"; const char *G_OP_TYPE_FUSION_DECONV_BN_RELU = "fusion_deconv_bn_relu"; +const char *G_OP_TYPE_ASSIGN = "assign"; +const char *G_OP_TYPE_REDUCE_PROD = "reduce_prod"; +const char *G_OP_TYPE_EQUAL = "equal"; +const char *G_OP_TYPE_CONDITIONAL_BLOCK = "conditional_block"; +const char *G_OP_TYPE_RANGE = "range"; +const char *G_OP_TYPE_WHILE = "while"; +const char *G_OP_TYPE_BEAM_SEARCH_DECODE = "beam_search_decode"; +const char *G_OP_TYPE_FILL_CONSTAN_BATCH_SIZE_LIKE = + "fill_constant_batch_size_like"; std::unordered_map< std::string, std::pair, std::vector>> @@ -234,5 +243,14 @@ std::unordered_map< {G_OP_TYPE_FUSION_DECONV_ADD_BN_RELU, {{"Input"}, {"Out"}}}, {G_OP_TYPE_FUSION_DECONV_ADD_BN, {{"Input"}, {"Out"}}}, {G_OP_TYPE_FUSION_DECONV_BN_RELU, {{"Input"}, {"Out"}}}, + {G_OP_TYPE_REDUCE_PROD, {{"X"}, {"Out"}}}, + {G_OP_TYPE_ASSIGN, {{"X"}, {"Out"}}}, + {G_OP_TYPE_EQUAL, {{"X", "Y"}, {"Out"}}}, + {G_OP_TYPE_RANGE, {{"Start", "End", "Step"}, {"Out"}}}, + {G_OP_TYPE_CONDITIONAL_BLOCK, {{"Input", "Cond"}, {"Out", "Scope"}}}, + {G_OP_TYPE_WHILE, {{"Condition", "X"}, {"Out", "StepScopes"}}}, + {G_OP_TYPE_BEAM_SEARCH_DECODE, + {{"Ids", "Scores"}, {"SentenceIds", "SentenceScores"}}}, + {G_OP_TYPE_FILL_CONSTAN_BATCH_SIZE_LIKE, {{"Input"}, {"Out"}}}, {G_OP_TYPE_PAD2D, {{"X"}, {"Out"}}}}; } // namespace paddle_mobile diff --git a/src/framework/load_ops.h b/src/framework/load_ops.h index 2738e2470ecdfcde6f259e3f20be80bebdd4c925..bf42130d0b4350bd013c0a1e3c05b7510aae1b9d 100644 --- a/src/framework/load_ops.h +++ b/src/framework/load_ops.h @@ -353,3 +353,21 @@ LOAD_OP1(assign_value, CPU); #ifdef EXP_OP LOAD_OP1(exp, CPU); #endif +#ifdef ASSIGN_OP +LOAD_OP1(assign, CPU); +#endif +#ifdef CONDITIONAL_BLOCK_OP +LOAD_OP1(conditional_block, CPU); +#endif +#ifdef EQUAL_OP +LOAD_OP1(equal, CPU); +#endif +#ifdef FILL_CONSTANT_BATCH_SIZE_LIKE_OP +LOAD_OP1(fill_constant_batch_size_like, CPU); +#endif +#ifdef RANGE_OP +LOAD_OP1(range, CPU); +#endif +#ifdef REDUCE_PROD_OP +LOAD_OP1(reduce_prod, CPU); +#endif diff --git a/src/framework/program/program_desc.cpp b/src/framework/program/program_desc.cpp index 7ec74874b678d564529c3d6d86e4db439a94cba9..a75bf01be15133f0c54de64aa03c06f52bf751a7 100644 --- a/src/framework/program/program_desc.cpp +++ b/src/framework/program/program_desc.cpp @@ -14,6 +14,7 @@ limitations under the License. */ #include #include +#include "framework/operator.h" #include "framework/program/program_desc.h" #include "framework/program/tensor_desc.h" @@ -51,6 +52,17 @@ void ProgramDesc::Description(std::string header) const { if (header.size()) { LOG(kLOG_INFO) << header; } + for (int i = 0; i < this->blocks_.size(); ++i) { + auto block = this->blocks_[i]; + for (int j = 0; j < block->Ops().size(); ++j) { + std::shared_ptr op_desc = block->Ops()[j]; + auto op_info_ptr = + OpInfoMap::Instance()->GetNullable(op_desc->Type()); + if (op_info_ptr == nullptr) { + DLOG << "Operator has not been registered :" << op_desc->Type().c_str(); + } + } + } for (int i = 0; i < this->blocks_.size(); ++i) { auto block = this->blocks_[i]; diff --git a/src/operators/assign_op.cpp b/src/operators/assign_op.cpp new file mode 100644 index 0000000000000000000000000000000000000000..adc038a2230be67f118a6005202600fcb4c10b15 --- /dev/null +++ b/src/operators/assign_op.cpp @@ -0,0 +1,39 @@ +/* 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 ASSIGN_OP + +#include "operators/assign_op.h" + +namespace paddle_mobile { +namespace operators { + +template +void AssignOp::InferShape() const { + PADDLE_MOBILE_ENFORCE(this->param_.Input() != nullptr, + "Input (X) of Assign op should not be null."); + PADDLE_MOBILE_ENFORCE(this->param_.Output() != nullptr, + "Output (Output) of Assign op should not be null."); +} + +} // namespace operators +} // namespace paddle_mobile + +namespace ops = paddle_mobile::operators; + +#ifdef PADDLE_MOBILE_CPU +REGISTER_OPERATOR_CPU(assign, ops::AssignOp); +#endif + +#endif // ASSIGN_OP diff --git a/src/operators/assign_op.h b/src/operators/assign_op.h new file mode 100644 index 0000000000000000000000000000000000000000..478330bc3bf1c6cfa4ec1a2e87331a25a0e1d1b6 --- /dev/null +++ b/src/operators/assign_op.h @@ -0,0 +1,33 @@ +/* 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 ASSIGN_OP + +#pragma once + +#include + +#include "framework/operator.h" +#include "operators/kernel/assign_kernel.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +DECLARE_OPERATOR(Assign, AssignParam, AssignKernel); + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/compare_op.cpp b/src/operators/compare_op.cpp index 312173a30bad7c5b3762de6f6abc3a735895704c..7332e33c6260ed70d096373cf1fe9fe6b6faca18 100644 --- a/src/operators/compare_op.cpp +++ b/src/operators/compare_op.cpp @@ -25,6 +25,14 @@ void LessThanOp::InferShape() const { } #endif // LESS_THAN_OP +#ifdef EQUAL_OP +template +void EqualOp::InferShape() const { + const auto &input_dims = this->param_.input_x_->dims(); + this->param_.output_->Resize(input_dims); +} +#endif // EQUAL_OP + } // namespace operators } // namespace paddle_mobile @@ -32,3 +40,6 @@ namespace ops = paddle_mobile::operators; #ifdef LESS_THAN_OP REGISTER_OPERATOR_CPU(less_than, ops::LessThanOp); #endif // LESS_THAN_OP +#ifdef EQUAL_OP +REGISTER_OPERATOR_CPU(equal, ops::EqualOp); +#endif // EQUAL_OP diff --git a/src/operators/compare_op.h b/src/operators/compare_op.h index 83ae88eae948694a8eef0845da699f1af8e2b8a9..5fbc350053abbc24ed956b8a7154adfe27b588c0 100644 --- a/src/operators/compare_op.h +++ b/src/operators/compare_op.h @@ -26,5 +26,9 @@ namespace operators { DECLARE_OPERATOR(LessThan, CompareParam, LessThanKernel); #endif // LESS_THAN_OP +#ifdef EQUAL_OP +DECLARE_OPERATOR(Equal, CompareParam, EqualKernel); +#endif // EQUAL_OP + } // namespace operators } // namespace paddle_mobile diff --git a/src/operators/conditional_block_op.cpp b/src/operators/conditional_block_op.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f1e6f7556c2960aa9c1eedb35e6e7aec20a12c9 --- /dev/null +++ b/src/operators/conditional_block_op.cpp @@ -0,0 +1,34 @@ +/* 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 CONDITIONAL_BLOCK_OP + +#include "operators/conditional_block_op.h" + +namespace paddle_mobile { +namespace operators { + +template +void ConditionalBlockOp::InferShape() const {} + +} // namespace operators +} // namespace paddle_mobile + +namespace ops = paddle_mobile::operators; + +#ifdef PADDLE_MOBILE_CPU +REGISTER_OPERATOR_CPU(conditional_block, ops::ConditionalBlockOp); +#endif + +#endif // CONDITIONAL_BLOCK_OP diff --git a/src/operators/conditional_block_op.h b/src/operators/conditional_block_op.h new file mode 100644 index 0000000000000000000000000000000000000000..8a5dfa5634c58a3ee08fbc20407dea7db5b515c0 --- /dev/null +++ b/src/operators/conditional_block_op.h @@ -0,0 +1,34 @@ +/* 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 CONDITIONAL_BLOCK_OP + +#pragma once + +#include + +#include "framework/operator.h" +#include "operators/kernel/conditional_block_kernel.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +DECLARE_OPERATOR(ConditionalBlock, ConditionalBlockParam, + ConditionalBlockKernel); + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/detection_ops.cpp b/src/operators/detection_ops.cpp index b87d1d3e80fd7945dd0cf4571041c18378e6ac1a..50df7229e1e0530c726e741d2f18818616213327 100644 --- a/src/operators/detection_ops.cpp +++ b/src/operators/detection_ops.cpp @@ -95,6 +95,17 @@ void RoiPerspectiveOp::InferShape() const { static_cast(transformed_width)}); auto out_dims = framework::make_ddim(out_dims_v); this->param_.output_->Resize(out_dims); + + std::vector mask_dims_v({rois_dims[0], // num_rois + 1, // channels + static_cast(transformed_height), + static_cast(transformed_width)}); + auto mask_dims = framework::make_ddim(mask_dims_v); + + std::vector matrix_dims_v({rois_dims[0], 9}); + auto matrix_dims = framework::make_ddim(matrix_dims_v); + this->param_.transform_Matrix_->Resize(matrix_dims); + this->param_.mask->Resize(mask_dims); } #endif diff --git a/src/operators/fill_constant_batch_size_like_op.cpp b/src/operators/fill_constant_batch_size_like_op.cpp new file mode 100644 index 0000000000000000000000000000000000000000..848ab436f288f0b0a54ece8ada9e7b0f2c7010bd --- /dev/null +++ b/src/operators/fill_constant_batch_size_like_op.cpp @@ -0,0 +1,25 @@ +/* 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 FILL_CONSTANT_BATCH_SIZE_LIKE_OP + +#include "operators/fill_constant_batch_size_like_op.h" + +namespace ops = paddle_mobile::operators; +#ifdef PADDLE_MOBILE_CPU +REGISTER_OPERATOR_CPU(fill_constant_batch_size_like, + ops::FillConstantBatchSizeLikeOp); +#endif + +#endif diff --git a/src/operators/fill_constant_batch_size_like_op.h b/src/operators/fill_constant_batch_size_like_op.h new file mode 100644 index 0000000000000000000000000000000000000000..dff76d85d10b6ca1ba538f1b62f34100c8668de5 --- /dev/null +++ b/src/operators/fill_constant_batch_size_like_op.h @@ -0,0 +1,96 @@ +/* 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 FILL_CONSTANT_BATCH_SIZE_LIKE_OP + +#pragma once + +#include +#include +#include "framework/data_type.h" +#include "framework/operator.h" +#include "framework/selected_rows.h" +#include "operators/math/math_function.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +template +class FillConstantBatchSizeLikeOp : public framework::OperatorBase { + public: + FillConstantBatchSizeLikeOp(const std::string &type, + const VariableNameMap &inputs, + const VariableNameMap &outputs, + const framework::AttributeMap attrs, + framework::Scope *scope) + : framework::OperatorBase(type, inputs, outputs, attrs, + scope), + param_(inputs, outputs, attrs, scope) {} + void RunImpl() { + auto data_type = + static_cast<_PaddleMobile__Framework__Proto__VarType__Type>( + param_.DataDtype()); + framework::Tensor *tensor = nullptr; + auto value = param_.Value(); + auto *outvar = param_.OutVar(); + + if (outvar->template IsType()) { + tensor = outvar->template GetMutable(); + } else if (outvar->template IsType()) { + tensor = outvar->template GetMutable() + ->mutable_value(); + } else { + PADDLE_MOBILE_THROW_EXCEPTION( + "fill constant batch size like op's output only" + "supports SelectedRows and LoDTensor"); + } + auto shape = param_.Shape(); + std::vector shape_int64(shape.size(), 0); + std::transform(shape.begin(), shape.end(), shape_int64.begin(), + [](int a) { return static_cast(a); }); + auto ddim = framework::make_ddim(shape_int64); + ddim[param_.OutputDimIdx()] = param_.Input()->dims()[param_.InputDimIdx()]; + tensor->Resize(ddim); + tensor->mutable_data(framework::ToTypeIndex(data_type)); + + math::SetConstant(tensor, value); + } + + void Init() {} + + void InferShape() const { + PADDLE_MOBILE_ENFORCE( + param_.Out() != nullptr, + "Output (Out) of fill_constant_batch_size_like op should not be null."); + + auto shape = param_.Shape(); + + std::vector shape_int64(shape.size(), 0); + std::transform(shape.begin(), shape.end(), shape_int64.begin(), + [](int a) { return static_cast(a); }); + DLOG << shape_int64; + auto ddim = framework::make_ddim(shape_int64); + ddim[param_.OutputDimIdx()] = param_.Input()->dims()[param_.InputDimIdx()]; + param_.Out()->Resize(ddim); + } + + protected: + FillConstantBatchSizeLikeParam param_; +}; + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/kernel/arm/assign_kernel.cpp b/src/operators/kernel/arm/assign_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..823bb3ca4188ad99e4b75492c7eed5d51745c177 --- /dev/null +++ b/src/operators/kernel/arm/assign_kernel.cpp @@ -0,0 +1,39 @@ +/* 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 ASSIGN_OP + +#include "operators/kernel/assign_kernel.h" +#include "framework/data_type.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool AssignKernel::Init(AssignParam* param) { + return true; +} + +template <> +void AssignKernel::Compute(const AssignParam& param) { + const auto* input = param.Input(); + auto* out = param.Output(); + out->mutable_data(); + framework::TensorCopy(*input, out); +} + +} // namespace operators +} // namespace paddle_mobile + +#endif // ASSIGN_OP diff --git a/src/operators/kernel/arm/compare_kernel.cpp b/src/operators/kernel/arm/compare_kernel.cpp index 35bb13363cea5a8de173cc7491afa5cc421e5746..d321740fd283ec16e64a90203c213ce41fe639b1 100644 --- a/src/operators/kernel/arm/compare_kernel.cpp +++ b/src/operators/kernel/arm/compare_kernel.cpp @@ -41,6 +41,11 @@ inline uint8_t Compare(const float x, const float y) { return static_cast(x < y); } +template +inline uint8_t Compare(const int x, const int y) { + return static_cast(x == y); +} + template inline uint8_t Compare(const int64_t x, const int64_t y) { return static_cast(x < y); @@ -184,6 +189,51 @@ struct CompareCompute { } }; +template +struct CompareCompute { + void operator()(const Tensor *X, const Tensor *Y, const int Axis, + Tensor *Out) { + const int *x = X->data(); + const int *y = Y->data(); + uint8_t *output = reinterpret_cast(Out->mutable_data()); + const auto &x_dims = X->dims(); + const auto &y_dims = Y->dims(); + /// axis = -1 represent the last dimensions. + int axis = (Axis == -1 ? x_dims.size() - y_dims.size() : Axis); + int batch = 1; + int channels = 1; + int elementwise_num = 1; + for (int i = 0; i < axis; ++i) { + batch *= x_dims[i]; + } + for (int i = 0; i < y_dims.size(); ++i) { + channels *= y_dims[i]; + } + for (int i = y_dims.size() + axis; i < x_dims.size(); ++i) { + elementwise_num *= x_dims[i]; + } + // if elementwise_num == 1, compare rowwise + if (elementwise_num == 1) { + for (int i = 0; i < batch; ++i) { + for (int j = 0; j < channels; ++j) { + int x_offset = i * channels + j; + output[x_offset] = Compare(x[x_offset], y[j]); + } + } + } else { + for (int i = 0; i < batch; ++i) { + for (int j = 0; j < channels; ++j) { + int x_offset = (i * channels + j) * elementwise_num; + int y_offset = j * elementwise_num; + for (int k = 0; k < elementwise_num; ++k) { + output[x_offset + k] = Compare(x[x_offset + k], y[y_offset]); + } + } + } + } + } +}; + #ifdef LESS_THAN_OP template <> bool LessThanKernel::Init(CompareParam *param) { @@ -205,5 +255,20 @@ void LessThanKernel::Compute(const CompareParam ¶m) { } #endif // LESS_THAN_OP +#ifdef EQUAL_OP +template <> +bool EqualKernel::Init(CompareParam *param) { + return true; +} + +template <> +void EqualKernel::Compute(const CompareParam ¶m) { + if (param.input_x_->type() == type_id().hash_code()) { + CompareCompute()(param.input_x_, param.input_y_, param.axis_, + param.output_); + } +} +#endif // EQUAL_OP + } // namespace operators } // namespace paddle_mobile diff --git a/src/operators/kernel/arm/conditional_block_kernel.cpp b/src/operators/kernel/arm/conditional_block_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..433f048187e0d2928196b6e10bc1974878aaac3d --- /dev/null +++ b/src/operators/kernel/arm/conditional_block_kernel.cpp @@ -0,0 +1,99 @@ +/* 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 CONDITIONAL_BLOCK_OP + +#include "operators/kernel/conditional_block_kernel.h" +#include +#include +#include "framework/data_type.h" + +namespace paddle_mobile { +namespace operators { + +class StepExecutor { + typedef std::shared_ptr> OperatorPtr; + + public: + StepExecutor(const framework::BlockDesc *block, framework::Scope *scope) + : scope_(scope) { + std::vector> ops = block->Ops(); + ops_of_block_.resize(ops.size()); + for (int i = 0; i < ops.size(); ++i) { + std::shared_ptr op_desc = ops[i]; + DLOG << "conditional block create op: " << ops.size() << "," + << op_desc->Type(); + auto op_handler = framework::OpRegistry::CreateOp( + op_desc->Type(), op_desc->GetInputs(), op_desc->GetOutputs(), + op_desc->GetAttrMap(), scope_); + op_handler->Init(); + ops_of_block_[i] = op_handler; + } + } + + void Run() { + for (int i = 0; i < ops_of_block_.size(); ++i) { + auto &op_handler = ops_of_block_[i]; + DLOG << "conditional block op InferShape: " << i + << "th: " << op_handler->Type(); + op_handler->InferShape(); + DLOG << "conditional block op Run: " << i << "th: " << op_handler->Type(); + op_handler->Run(); + } + } + + private: + framework::Scope *scope_; + std::vector ops_of_block_; +}; + +template <> +bool ConditionalBlockKernel::Init( + ConditionalBlockParam *param) { + return true; +} + +template <> +void ConditionalBlockKernel::Compute( + const ConditionalBlockParam ¶m) { + bool need_run; + if (param.isScalarCondition()) { + auto xs = param.Cond(); + PADDLE_MOBILE_ENFORCE( + xs[0]->type() == type_id().hash_code() && xs[0]->numel() == 1, + "condition input's data type should be bool, " + "numel should be 1, actual numel is %d", + xs[0]->numel()); + need_run = xs[0]->data()[0]; + } else { + auto xs = param.Input(); + need_run = std::all_of( + xs.begin(), xs.end(), + [](const framework::LoDTensor *t) { return t->numel() != 0; }); + } + + if (need_run) { + auto input = param.Input(); + auto sub = param.getSubBlock(); + auto ¤t_scope = param.GetScope()->NewScope(); + StepExecutor executor(sub, ¤t_scope); + executor.Run(); + param.GetScope()->DeleteScope(¤t_scope); + } +} + +} // namespace operators +} // namespace paddle_mobile + +#endif // CONDITIONAL_BLOCK_OP diff --git a/src/operators/kernel/arm/elementwise_add_kernel.cpp b/src/operators/kernel/arm/elementwise_add_kernel.cpp index 043d27e72f16ab4b38f31d6cff60bd2f4e89a649..c4bcbf6f7e8a33d7533b17b2ca00e00411aaeef3 100644 --- a/src/operators/kernel/arm/elementwise_add_kernel.cpp +++ b/src/operators/kernel/arm/elementwise_add_kernel.cpp @@ -28,7 +28,12 @@ bool ElementwiseAddKernel::Init(ElementwiseAddParam *param) { template <> void ElementwiseAddKernel::Compute( const ElementwiseAddParam ¶m) { - ElementwiseAddCompute(param); + if (param.InputX()->type() == type_id().hash_code()) { + ElementwiseAddCompute(param); + } else if (param.InputX()->type() == type_id().hash_code()) { + AddElememtWiseStruct()(param.InputX(), param.InputY(), + param.Axis(), param.Out()); + } param.Out()->set_lod(param.InputX()->lod()); } diff --git a/src/operators/kernel/arm/lod_reset_kernel.cpp b/src/operators/kernel/arm/lod_reset_kernel.cpp index f3bb206447c87941f150c70c2297d8d1c5976231..cb7f98c1e4f28bab3f4f7c4a95e98feeefd40788 100644 --- a/src/operators/kernel/arm/lod_reset_kernel.cpp +++ b/src/operators/kernel/arm/lod_reset_kernel.cpp @@ -28,6 +28,7 @@ template <> void LodResetKernel::Compute(const LodResetParam ¶m) { const auto *input = param.input_x_; const auto *lod_t = param.input_y_; + bool append = param.append; auto *output = param.output_; output->ShareDataWith(*input); @@ -47,13 +48,17 @@ void LodResetKernel::Compute(const LodResetParam ¶m) { // cast level0 to size_t std::vector ulevel0(level0.size(), 0); - for (int i = 0; i < level0.size(); ++i) { - ulevel0[i] = level0[i]; - } + std::transform(level0.begin(), level0.end(), ulevel0.begin(), + [](int a) { return static_cast(a); }); - framework::LoD target_lod; - target_lod.push_back(std::move(ulevel0)); - output->set_lod(target_lod); + if (append) { + auto *out_lod = output->mutable_lod(); + out_lod->push_back(ulevel0); + } else { + framework::LoD target_lod; + target_lod.push_back(ulevel0); + output->set_lod(target_lod); + } } } // namespace operators diff --git a/src/operators/kernel/arm/roi_perspective_kernel.cpp b/src/operators/kernel/arm/roi_perspective_kernel.cpp index 8cdb8f04b2f1808a9dff46ef04159ed291481292..c8b0cb8bf2a90f4d8483808fee7a37b3223e7099 100644 --- a/src/operators/kernel/arm/roi_perspective_kernel.cpp +++ b/src/operators/kernel/arm/roi_perspective_kernel.cpp @@ -208,6 +208,8 @@ void RoiPerspectiveKernel::Compute( const auto *input_x = param.input_x_; const auto *input_rois = param.input_rois_; auto *output = param.output_; + auto *transform_Matrix = param.transform_Matrix_; + auto *mask = param.mask; const auto &in_dims = input_x->dims(); const int channels = in_dims[1]; @@ -221,6 +223,9 @@ void RoiPerspectiveKernel::Compute( const float *input_data = input_x->data(); const float *rois_data = input_rois->data(); float *output_data = output->mutable_data(); + int *mask_data = mask->mutable_data(); + float *transform_matrix = + transform_Matrix->mutable_data({rois_num, 9}); std::vector roi2image(rois_num); const auto &lod = input_rois->lod().back(); @@ -240,9 +245,13 @@ void RoiPerspectiveKernel::Compute( } int image_id = roi2image[n]; // Get transform matrix - float transform_matrix[9]; + // float transform_matrix[9]; + float matrix[9]; get_transform_matrix(transformed_width, transformed_height, roi_x, - roi_y, transform_matrix); + roi_y, matrix); + for (int i = 0; i < 9; i++) { + transform_matrix[n * 9 + i] = matrix[i]; + } for (int c = 0; c < channels; ++c) { for (int out_h = 0; out_h < transformed_height; ++out_h) { for (int out_w = 0; out_w < transformed_width; ++out_w) { @@ -251,19 +260,24 @@ void RoiPerspectiveKernel::Compute( c * transformed_height * transformed_width + out_h * transformed_width + out_w; float in_w, in_h; - get_source_coords(transform_matrix, out_w, out_h, &in_w, - &in_h); + get_source_coords(matrix, out_w, out_h, &in_w, &in_h); if (in_quad(in_w, in_h, roi_x, roi_y)) { if ((-0.5 > in_w) || (in_w > (in_width - 0.5)) || (-0.5 > in_h) || (in_h > (in_height - 0.5))) { output_data[out_index] = 0.0; + mask_data[(n * transformed_height + out_h) * transformed_width + + out_w] = 0; } else { bilinear_interpolate(input_data, channels, in_width, in_height, image_id, c, in_w, in_h, output_data + out_index); + mask_data[(n * transformed_height + out_h) * transformed_width + + out_w] = 1; } } else { output_data[out_index] = 0.0; + mask_data[(n * transformed_height + out_h) * transformed_width + + out_w] = 1; } } } diff --git a/src/operators/kernel/arm/scale_kernel.cpp b/src/operators/kernel/arm/scale_kernel.cpp index 0cbeb492f829708bcc267613bb0430d88da2e6f0..92fffeaed74c4286f7e32153b8356952a4de1639 100644 --- a/src/operators/kernel/arm/scale_kernel.cpp +++ b/src/operators/kernel/arm/scale_kernel.cpp @@ -33,39 +33,49 @@ void ScaleKernel::Compute(const ScaleParam ¶m) { auto output = param.Out(); const float scale = param.Scale(); const float bias = param.Bias(); - const float *input_data = input->data(); - float *output_data = output->mutable_data(); + if (input->type() == type_id().hash_code()) { + const int64_t *input_data = input->data(); + int64_t *output_data = output->mutable_data(); - int i = 0; + int i = 0; + for (; i < output->numel(); ++i, ++output_data, ++input_data) { + *output_data = scale * (*input_data) + bias; + } + } else { + const float *input_data = input->data(); + float *output_data = output->mutable_data(); + + int i = 0; #if defined(__ARM_NEON__) || defined(__ARM_NEON) - float32x4_t vscale = vdupq_n_f32(scale); - float32x4_t vbias = vdupq_n_f32(bias); - for (; i < output->numel() - 15; i += 16) { - float32x4_t _in0 = vld1q_f32(input_data); - float32x4_t _in1 = vld1q_f32(input_data + 4); - float32x4_t _in2 = vld1q_f32(input_data + 8); - float32x4_t _in3 = vld1q_f32(input_data + 12); - _in0 = vmlaq_f32(vbias, vscale, _in0); - _in1 = vmlaq_f32(vbias, vscale, _in1); - _in2 = vmlaq_f32(vbias, vscale, _in2); - _in3 = vmlaq_f32(vbias, vscale, _in3); - vst1q_f32(output_data, _in0); - vst1q_f32(output_data + 4, _in1); - vst1q_f32(output_data + 8, _in2); - vst1q_f32(output_data + 12, _in3); - input_data += 16; - output_data += 16; - } - for (; i < output->numel() - 3; i += 4) { - float32x4_t _in0 = vld1q_f32(input_data); - _in0 = vmlaq_f32(vbias, vscale, _in0); - vst1q_f32(output_data, _in0); - input_data += 4; - output_data += 4; - } + float32x4_t vscale = vdupq_n_f32(scale); + float32x4_t vbias = vdupq_n_f32(bias); + for (; i < output->numel() - 15; i += 16) { + float32x4_t _in0 = vld1q_f32(input_data); + float32x4_t _in1 = vld1q_f32(input_data + 4); + float32x4_t _in2 = vld1q_f32(input_data + 8); + float32x4_t _in3 = vld1q_f32(input_data + 12); + _in0 = vmlaq_f32(vbias, vscale, _in0); + _in1 = vmlaq_f32(vbias, vscale, _in1); + _in2 = vmlaq_f32(vbias, vscale, _in2); + _in3 = vmlaq_f32(vbias, vscale, _in3); + vst1q_f32(output_data, _in0); + vst1q_f32(output_data + 4, _in1); + vst1q_f32(output_data + 8, _in2); + vst1q_f32(output_data + 12, _in3); + input_data += 16; + output_data += 16; + } + for (; i < output->numel() - 3; i += 4) { + float32x4_t _in0 = vld1q_f32(input_data); + _in0 = vmlaq_f32(vbias, vscale, _in0); + vst1q_f32(output_data, _in0); + input_data += 4; + output_data += 4; + } #endif - for (; i < output->numel(); ++i, ++output_data, ++input_data) { - *output_data = scale * (*input_data) + bias; + for (; i < output->numel(); ++i, ++output_data, ++input_data) { + *output_data = scale * (*input_data) + bias; + } } } diff --git a/src/operators/kernel/arm/slice_kernel.cpp b/src/operators/kernel/arm/slice_kernel.cpp index db3718612be94e78a38d412b52579c7abc1d98c8..aeb18c8d2074ff1b32e4892fb0ac2dd20aa5047c 100644 --- a/src/operators/kernel/arm/slice_kernel.cpp +++ b/src/operators/kernel/arm/slice_kernel.cpp @@ -19,18 +19,22 @@ limitations under the License. */ namespace paddle_mobile { namespace operators { +template void SliceCompute(const SliceParam& param) { auto input = param.input_; auto output = param.output_; - auto* input_ptr = input->data(); - auto* output_ptr = output->mutable_data(); + auto* input_ptr = input->data(); + auto* output_ptr = output->mutable_data(); auto out_dims = output->dims(); auto in_dims = input->dims(); auto starts = param.starts_; auto ends = param.ends_; int axes = param.axes_[0]; - int HW = input->dims()[axes + 1] * input->dims()[axes + 2]; - int batch_size = out_dims[axes - 1]; + int HW = 1; + if (in_dims.size() >= 2 && axes <= in_dims.size() - 2) { + HW = in_dims[axes + 1] * input->dims()[axes + 2]; + } + int batch_size = (out_dims.size() == 1) ? 1 : out_dims[axes - 1]; int input_channel = in_dims[axes]; int output_channel = out_dims[axes]; @@ -53,12 +57,22 @@ template <> void SliceKernel::Compute(const SliceParam& param) { int rank = param.input_->dims().size(); switch (rank) { + case 1: + if (param.input_->type() == type_id().hash_code()) { + SliceCompute(param); + } else if (param.input_->type() == type_id().hash_code()) { + SliceCompute(param); + } + break; + case 2: + SliceCompute(param); + break; case 4: - SliceCompute(param); + SliceCompute(param); break; case 5: if (param.input_->dims()[0] == 1) { - SliceCompute(param); + SliceCompute(param); } break; default: diff --git a/src/operators/kernel/arm/while_kernel.cpp b/src/operators/kernel/arm/while_kernel.cpp index 4794fd122cce141487598a19261fd3e0f66cfb27..43e88aad4da302e9221cfc51dad1a15544120d94 100644 --- a/src/operators/kernel/arm/while_kernel.cpp +++ b/src/operators/kernel/arm/while_kernel.cpp @@ -15,23 +15,25 @@ limitations under the License. */ #ifdef WHILE_OP #include "operators/kernel/while_kernel.h" +#include "framework/loader.h" +#include "framework/lod_tensor.h" #include "framework/op_registry.h" #include "framework/operator.h" namespace paddle_mobile { namespace operators { -class StepExecutor { +class WhileStepExecutor { typedef std::shared_ptr> OperatorPtr; public: - StepExecutor(const framework::BlockDesc *block, framework::Scope *scope) + WhileStepExecutor(const framework::BlockDesc *block, framework::Scope *scope) : scope_(scope) { std::vector> ops = block->Ops(); ops_of_block_.resize(ops.size()); for (int i = 0; i < ops.size(); ++i) { std::shared_ptr op_desc = ops[i]; - DLOG << "create op: " << op_desc->Type(); + DLOG << "while kernel create op: " << op_desc->Type(); auto op_handler = framework::OpRegistry::CreateOp( op_desc->Type(), op_desc->GetInputs(), op_desc->GetOutputs(), op_desc->GetAttrMap(), scope_); @@ -41,12 +43,46 @@ class StepExecutor { } void Run() { - for (auto &op_handler : ops_of_block_) { + for (int i = 0; i < ops_of_block_.size(); ++i) { + auto &op_handler = ops_of_block_[i]; + DLOG << "while kernel InferShape op: " << i + << "th : " << op_handler->Type(); op_handler->InferShape(); + DLOG << "while kernel Run op: " << i << "th : " << op_handler->Type(); op_handler->Run(); } } + void CreateVariables(Scope &scope, const WhileParam ¶m) { + for (const auto &var_desc : param.sub_block_->Vars()) { + auto var = scope.Var(var_desc->Name()); + if (var_desc->Type() == framework::VARTYPE_TYPE_LOD_TENSOR) { + if (var_desc->Persistable()) { + auto dim = var_desc->Tensor_desc().Dims(); + auto tensor = var->framework::Variable::GetMutable(); + tensor->Resize(framework::make_ddim(dim)); + } else { + auto dim = var_desc->Tensor_desc().Dims(); + if (dim.size() == 0) { + auto tensor = var->framework::Variable::GetMutable(); + framework::DDim dDim = {0}; + tensor->Resize(dDim); + } else { + for (auto &d : dim) { + if (d < 0) { + d *= -1; + } + } + auto tensor = var->framework::Variable::GetMutable(); + tensor->Resize(framework::make_ddim(dim)); + } + } + } else { + // TODO(codeWorm) + } + } + } + private: framework::Scope *scope_; std::vector ops_of_block_; @@ -59,9 +95,28 @@ bool WhileKernel::Init(WhileParam *param) { template <> void WhileKernel::Compute(const WhileParam ¶m) { + DLOG << "WhileKernel Compute"; + WhileStepExecutor executor(param.sub_block_, param.scope_); auto ¤t_scope = param.scope_->NewScope(); - StepExecutor executor(param.sub_block_, ¤t_scope); + executor.CreateVariables(current_scope, param); while (param.cond_->data()[0]) { + if (param.is_test) { + for (auto &name : current_scope.LocalVarNames()) { + auto *var = current_scope.Var(name); + if (var->IsType()) { + // Clear all lod information for all lod_tensors. + auto *t = var->GetMutable(); + framework::LoD empty_lod; + t->set_lod(empty_lod); + } else if (var->IsType()) { + // Clear elements of all tensor arrays. + auto *t = var->GetMutable(); + t->clear(); + } else { + // todo + } + } + } executor.Run(); } param.scope_->DeleteScope(¤t_scope); diff --git a/src/operators/kernel/assign_kernel.h b/src/operators/kernel/assign_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..0d06bb752190b3f720725c2296890e5059402b87 --- /dev/null +++ b/src/operators/kernel/assign_kernel.h @@ -0,0 +1,53 @@ +/* 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 ASSIGN_OP + +#pragma once + +#include +#include "framework/operator.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +template +class AssignParam : public OpParam { + typedef typename DtypeTensorTrait::gtype GType; + typedef typename DtypeTensorTrait::rtype RType; + + public: + AssignParam(const VariableNameMap &inputs, const VariableNameMap &outputs, + const AttributeMap &attrs, Scope *scope) + : OpParam(inputs, outputs, attrs, scope) { + input_ = OpParam::InputXFrom(inputs, *scope); + output_ = OpParam::OutFrom(outputs, *scope); + } + + const GType *Input() const { return input_; } + + GType *Output() const { return output_; } + + private: + GType *input_; + GType *output_; +}; + +DECLARE_KERNEL(Assign, AssignParam); + +} // namespace operators +} // namespace paddle_mobile + +#endif // ASSIGN_OP diff --git a/src/operators/kernel/central-arm-func/elementwise_add_arm_func.h b/src/operators/kernel/central-arm-func/elementwise_add_arm_func.h index 40db0f1dcf1085ce119f2173b6d9da740a2058bc..877ae712cf6e593337a4f46645c394be6d7da9ee 100644 --- a/src/operators/kernel/central-arm-func/elementwise_add_arm_func.h +++ b/src/operators/kernel/central-arm-func/elementwise_add_arm_func.h @@ -34,6 +34,42 @@ inline void ElementwiseAddCompute(const ElementwiseAddParam ¶m) { math::AddElememtWise(input_x, input_y, axis, output); } +template +struct AddElememtWiseStruct { + void operator()(const Tensor *X, const Tensor *Y, const int Axis, + Tensor *Out) {} +}; + +template +struct AddElememtWiseStruct { + void operator()(const Tensor *input, const Tensor *bias, const int Axis, + Tensor *output) { + const auto &x_dims = input->dims(); + const auto &y_dims = bias->dims(); + const int *input_data = input->data(); + const int *bias_data = bias->data(); + int *output_data = output->mutable_data(); + + if (x_dims == y_dims) { + size_t channels = 1; + size_t elementwise_num = 1; + for (int i = 0; i < y_dims.size(); ++i) { + channels *= y_dims[i]; + } +#pragma omp parallel for + for (int j = 0; j < channels; ++j) { + size_t offset = (0 * channels + j) * elementwise_num; + const int *input = input_data + offset; + const int bias = bias_data[j]; + int *output = output_data + offset; + for (int k = 0; k < elementwise_num; ++k) { + output[k] = math::Active(input[k] + bias); + } + } + } + } +}; + template class ElementwiseAddKernel; } // namespace operators diff --git a/src/operators/kernel/central-arm-func/multiclass_nms_arm_func.h b/src/operators/kernel/central-arm-func/multiclass_nms_arm_func.h index b021a574d680d44e9c2d9be5a8627671dedbadea..f44f348aa640fd2c3176ca365ca4c120ff570b95 100644 --- a/src/operators/kernel/central-arm-func/multiclass_nms_arm_func.h +++ b/src/operators/kernel/central-arm-func/multiclass_nms_arm_func.h @@ -294,6 +294,11 @@ void MultiClassNMSCompute(const MultiClassNMSParam& param) { } } } + + framework::LoD lod; + lod.emplace_back(batch_starts); + + outs->set_lod(lod); } } // namespace operators diff --git a/src/operators/kernel/compare_kernel.h b/src/operators/kernel/compare_kernel.h index 0f8a8ac74131054ebca53566dc38c374e9dafe4c..8932ca7757339717c13e16633b112adbda9ba2b2 100644 --- a/src/operators/kernel/compare_kernel.h +++ b/src/operators/kernel/compare_kernel.h @@ -24,5 +24,9 @@ namespace operators { DECLARE_KERNEL(LessThan, CompareParam); #endif // LESS_THAN_OP +#ifdef EQUAL_OP +DECLARE_KERNEL(Equal, CompareParam); +#endif // EQUAL_OP + } // namespace operators } // namespace paddle_mobile diff --git a/src/operators/kernel/conditional_block_kernel.h b/src/operators/kernel/conditional_block_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..851d558c2c96fe868df7f5dd93556323a685a2d1 --- /dev/null +++ b/src/operators/kernel/conditional_block_kernel.h @@ -0,0 +1,70 @@ +/* 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 CONDITIONAL_BLOCK_OP + +#pragma once + +#include +#include "framework/operator.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +template +class ConditionalBlockParam : public OpParam { + typedef typename DtypeTensorTrait::gtype GType; + typedef typename DtypeTensorTrait::rtype RType; + + public: + ConditionalBlockParam(const VariableNameMap &inputs, + const VariableNameMap &outputs, + const AttributeMap &attrs, Scope *scope) + : OpParam(inputs, outputs, attrs, scope) { + input_ = OpParam::GetMultiVarValue("Input", inputs, *scope); + cond_ = OpParam::GetMultiVarValue("Cond", inputs, *scope); + output_ = OpParam::OutFrom(outputs, *scope); + scope_ = OpParam::GetVar("Scope", outputs, *scope); + is_scalar_condition_ = GetAttr("is_scalar_condition", attrs); + sub_block_ = GetAttr("sub_block", attrs); + } + + const vector Input() const { return input_; } + + const vector Cond() const { return cond_; } + + GType *Output() const { return output_; } + + Variable *OutputScope() const { return scope_; } + + bool isScalarCondition() const { return is_scalar_condition_; } + + framework::BlockDesc *getSubBlock() const { return sub_block_; } + + private: + vector input_; + vector cond_; + GType *output_; + Variable *scope_; + bool is_scalar_condition_; + framework::BlockDesc *sub_block_; +}; + +DECLARE_KERNEL(ConditionalBlock, ConditionalBlockParam); + +} // namespace operators +} // namespace paddle_mobile + +#endif // CONDITIONAL_BLOCK_OP diff --git a/src/operators/kernel/detection_kernel.h b/src/operators/kernel/detection_kernel.h index 77c35b0253d06f2bc979861e53daeba815b46647..89c8348d5bc9b1a2a9fb84de14a3f73e26734154 100644 --- a/src/operators/kernel/detection_kernel.h +++ b/src/operators/kernel/detection_kernel.h @@ -204,6 +204,9 @@ class RoiPerspectiveParam : public OpParam { OpParam::GetVarValue("ROIs", inputs, *scope); output_ = OpParam::GetVarValue("Out", outputs, *scope); + transform_Matrix_ = OpParam::GetVarValue( + "TransformMatrix", outputs, *scope); + mask = OpParam::GetVarValue("Mask", outputs, *scope); spatial_scale_ = OpParam::GetAttr("spatial_scale", attrs); transformed_height_ = OpParam::GetAttr("transformed_height", attrs); @@ -214,6 +217,8 @@ class RoiPerspectiveParam : public OpParam { framework::Tensor *input_x_; framework::LoDTensor *input_rois_; framework::Tensor *output_; + framework::Tensor *transform_Matrix_; + framework::Tensor *mask; float spatial_scale_; int transformed_height_; diff --git a/src/operators/kernel/range_kernel.cpp b/src/operators/kernel/range_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9384eb0195e9b0f58804483ef9b7cdb91cd0f62e --- /dev/null +++ b/src/operators/kernel/range_kernel.cpp @@ -0,0 +1,49 @@ +/* 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 RANGE_OP + +#include "operators/kernel/range_kernel.h" +#include "framework/data_type.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool RangeKernel::Init(RangeParam* param) { + return true; +} + +template <> +void RangeKernel::Compute(const RangeParam& param) { + int start = param.Start()->data()[0]; + int end = param.End()->data()[0]; + int step = param.Step()->data()[0]; + auto* out = param.Output(); + + int64_t size = 0; + GetSize(start, end, step, &size); + out->Resize(framework::make_ddim({size})); + auto* out_data = out->mutable_data(); + auto value = start; + for (int64_t i = 0; i < size; ++i) { + out_data[i] = value; + value += step; + } +} + +} // namespace operators +} // namespace paddle_mobile + +#endif // RANGE_OP diff --git a/src/operators/kernel/range_kernel.h b/src/operators/kernel/range_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..b328b6769f386a2b597b17aad376c8422db47087 --- /dev/null +++ b/src/operators/kernel/range_kernel.h @@ -0,0 +1,70 @@ +/* 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 RANGE_OP + +#pragma once + +#include +#include "framework/operator.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +inline void GetSize(float start, float end, float step, int64_t *size) { + PADDLE_MOBILE_ENFORCE(!std::equal_to()(step, 0), + "The step of range op should not be 0."); + PADDLE_MOBILE_ENFORCE( + ((start < end) && (step > 0)) || ((start > end) && (step < 0)), + "The step should be greater than 0 while start < end. And the " + "step should be less than 0 while start > end."); + *size = std::is_integral::value + ? ((std::abs(end - start) + std::abs(step) - 1) / std::abs(step)) + : std::ceil(std::abs((end - start) / step)); +} + +template +class RangeParam : public OpParam { + typedef typename DtypeTensorTrait::gtype GType; + typedef typename DtypeTensorTrait::rtype RType; + + public: + RangeParam(const VariableNameMap &inputs, const VariableNameMap &outputs, + const AttributeMap &attrs, Scope *scope) + : OpParam(inputs, outputs, attrs, scope) { + start_ = OpParam::GetVarValue("Start", inputs, *scope); + end_ = OpParam::GetVarValue("End", inputs, *scope); + step_ = OpParam::GetVarValue("Step", inputs, *scope); + output_ = OpParam::OutFrom(outputs, *scope); + } + + GType *Start() const { return start_; } + const GType *End() const { return end_; } + const GType *Step() const { return step_; } + GType *Output() const { return output_; } + + private: + GType *start_; + GType *end_; + GType *step_; + GType *output_; +}; + +DECLARE_KERNEL(Range, RangeParam); + +} // namespace operators +} // namespace paddle_mobile + +#endif // RANGE_OP diff --git a/src/operators/kernel/reduce_prod_kernel.cpp b/src/operators/kernel/reduce_prod_kernel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c40e5c4615013b5f3be8ff9260866a55afc1c973 --- /dev/null +++ b/src/operators/kernel/reduce_prod_kernel.cpp @@ -0,0 +1,65 @@ +/* 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 REDUCE_PROD_OP + +#include "operators/kernel/reduce_prod_kernel.h" +#include +#include +#include "framework/data_type.h" + +namespace paddle_mobile { +namespace operators { + +template <> +bool ReduceProdKernel::Init(ReduceProdParam* param) { + return true; +} + +template <> +void ReduceProdKernel::Compute(const ReduceProdParam& param) { + auto* input = param.Input(); + if (input->type() == type_id().hash_code()) { + bool reduce_all = param.isReduceAll(); + auto* output = param.Output(); + auto dim = param.getDim(); + auto* out_data = output->mutable_data(); + const auto* input_x_data = input->data(); + + auto dims = param.getDim(); + bool keep_dim = param.isKeepDim(); + + if (reduce_all) { + size_t stride = 1; + for (int j = dim[0]; j < input->dims().size(); ++j) { + stride *= input->dims()[j]; + } + auto numel = output->numel(); + for (int i = 0; i < numel; i++) { + int64_t mul = 1; + for (int j = 0; j < stride; ++j, ++input_x_data) { + mul *= (*input_x_data); + } + out_data[i] = mul; + } + } else { + // todo + } + } +} + +} // namespace operators +} // namespace paddle_mobile + +#endif // REDUCE_PROD_OP diff --git a/src/operators/kernel/reduce_prod_kernel.h b/src/operators/kernel/reduce_prod_kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..73c93fdc0b175092868a2198775d6e21ef42846e --- /dev/null +++ b/src/operators/kernel/reduce_prod_kernel.h @@ -0,0 +1,65 @@ +/* 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 REDUCE_PROD_OP + +#pragma once + +#include +#include "framework/operator.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +template +class ReduceProdParam : public OpParam { + typedef typename DtypeTensorTrait::gtype GType; + typedef typename DtypeTensorTrait::rtype RType; + + public: + ReduceProdParam(const VariableNameMap &inputs, const VariableNameMap &outputs, + const AttributeMap &attrs, Scope *scope) + : OpParam(inputs, outputs, attrs, scope) { + input_ = OpParam::InputXFrom(inputs, *scope); + output_ = OpParam::OutFrom(outputs, *scope); + reduce_all_ = GetAttr("reduce_all", attrs); + keep_dim_ = GetAttr("keep_dim", attrs); + dim_ = GetAttr>("dim", attrs); + } + + const GType *Input() const { return input_; } + + GType *Output() const { return output_; } + + bool isReduceAll() const { return reduce_all_; } + + bool isKeepDim() const { return keep_dim_; } + + const vector getDim() const { return dim_; } + + private: + GType *input_; + GType *output_; + bool reduce_all_; + bool keep_dim_; + std::vector dim_; +}; + +DECLARE_KERNEL(ReduceProd, ReduceProdParam) + +} // namespace operators +} // namespace paddle_mobile + +#endif // REDUCE_PROD_OP diff --git a/src/operators/kernel/while_kernel.h b/src/operators/kernel/while_kernel.h index ba014a9079f6877f726d7697c487653b848f9dbb..6882ef047f4ec7be15ad8fc16a479f06f3563947 100644 --- a/src/operators/kernel/while_kernel.h +++ b/src/operators/kernel/while_kernel.h @@ -30,12 +30,14 @@ class WhileParam : public OpParam { cond_ = OpParam::GetVarValue("Condition", inputs, *scope); sub_block_ = OpParam::GetAttr("sub_block", attrs); + is_test = OpParam::GetAttr("is_test", attrs); } public: - const Scope *scope_; + Scope *scope_; framework::LoDTensor *cond_; framework::BlockDesc *sub_block_; + bool is_test; }; DECLARE_KERNEL(While, WhileParam); diff --git a/src/operators/lod_reset_op.cpp b/src/operators/lod_reset_op.cpp index 1eca733fd95e0893fe811da15290ee5878d1ac77..1f3152a9a587e52622e166309ecaad801ca0f618 100644 --- a/src/operators/lod_reset_op.cpp +++ b/src/operators/lod_reset_op.cpp @@ -23,6 +23,9 @@ template void LodResetOp::InferShape() const { const auto &input_dims = this->param_.input_x_->dims(); this->param_.output_->Resize(input_dims); + if (this->param_.append) { + this->param_.output_->set_lod(this->param_.input_x_->lod()); + } } } // namespace operators diff --git a/src/operators/math/activation.h b/src/operators/math/activation.h index d5a4cba4ce621478af877b5e7e3b8f8118be50dc..d2b465c2bcf9430b59f76afd8b44c55d7973f686 100644 --- a/src/operators/math/activation.h +++ b/src/operators/math/activation.h @@ -131,6 +131,11 @@ inline float Active(const float &x) { return x; } +template +inline int Active(const int &x) { + return x; +} + template <> inline float Active(const float &x) { return std::max(x, 0.f); diff --git a/src/operators/op_param.h b/src/operators/op_param.h index 029295aed3ebbd5a2e0633426c36ba3d2a396a29..42ea234710ad288f616c01905f44726a15893e74 100644 --- a/src/operators/op_param.h +++ b/src/operators/op_param.h @@ -1330,6 +1330,55 @@ class FillConstantParam : public OpParam { }; #endif +#ifdef FILL_CONSTANT_BATCH_SIZE_LIKE_OP +template +class FillConstantBatchSizeLikeParam : public OpParam { + typedef typename DtypeTensorTrait::gtype GType; + typedef typename DtypeTensorTrait::rtype RType; + + public: + FillConstantBatchSizeLikeParam(const VariableNameMap &inputs, + const VariableNameMap &outputs, + const AttributeMap &attrs, Scope *scope) + : OpParam(inputs, outputs, attrs, scope) { + input_ = InputFrom(inputs, *scope); + out_var_ = OutVarFrom(outputs, *scope); + out_ = OutFrom(outputs, *scope); + dtype_ = GetAttr("dtype", attrs); + shape_ = GetAttr>("shape", attrs); + value_ = GetAttr("value", attrs); + input_dim_idx_ = GetAttr("input_dim_idx", attrs); + output_dim_idx_ = GetAttr("output_dim_idx", attrs); + } + + Variable *OutVar() const { return out_var_; } + + const GType *Input() const { return input_; } + + GType *Out() const { return out_; } + + const int &DataDtype() const { return dtype_; } + + const vector &Shape() const { return shape_; } + + const float &Value() const { return value_; } + + int InputDimIdx() const { return input_dim_idx_; } + + int OutputDimIdx() const { return output_dim_idx_; } + + private: + GType *input_; + Variable *out_var_; + GType *out_; + int dtype_; + vector shape_; + float value_; + int input_dim_idx_; + int output_dim_idx_; +}; +#endif + #ifdef TRANSPOSE_OP template class TransposeParam : public OpParam { @@ -3236,6 +3285,7 @@ class LodResetParam : public OpParam { } else { target_lod_ = OpParam::GetAttr>("target_lod", attrs); } + append = OpParam::GetAttr("append", attrs); } public: @@ -3243,6 +3293,7 @@ class LodResetParam : public OpParam { GType *input_y_; GType *output_; std::vector target_lod_; + bool append; }; #endif // LOD_RESET_OP diff --git a/src/operators/range_op.cpp b/src/operators/range_op.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b7abb52f0f49bf271eebed1bf94544b17fa26fbf --- /dev/null +++ b/src/operators/range_op.cpp @@ -0,0 +1,45 @@ +/* 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 RANGE_OP + +#include "operators/range_op.h" + +namespace paddle_mobile { +namespace operators { + +template +void RangeOp::InferShape() const { + auto s_dims = this->param_.Start()->dims(); + PADDLE_MOBILE_ENFORCE((s_dims.size() == 1) && (s_dims[0] == 1), + "The shape of Input(Start) should be [1]."); + auto e_dims = this->param_.End()->dims(); + PADDLE_MOBILE_ENFORCE((e_dims.size() == 1) && (e_dims[0] == 1), + "The shape of Input(End) should be [1]."); + auto step_dims = this->param_.Step()->dims(); + PADDLE_MOBILE_ENFORCE((step_dims.size() == 1) && (step_dims[0] == 1), + "The shape of Input(Step) should be [1]."); + this->param_.Output()->Resize({-1}); +} + +} // namespace operators +} // namespace paddle_mobile + +namespace ops = paddle_mobile::operators; + +#ifdef PADDLE_MOBILE_CPU +REGISTER_OPERATOR_CPU(range, ops::RangeOp); +#endif + +#endif // ASSIGN_OP diff --git a/src/operators/range_op.h b/src/operators/range_op.h new file mode 100644 index 0000000000000000000000000000000000000000..a3ca1a56ff3d51e7020d165686c9a673873414c3 --- /dev/null +++ b/src/operators/range_op.h @@ -0,0 +1,33 @@ +/* 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 RANGE_OP + +#pragma once + +#include + +#include "framework/operator.h" +#include "operators/kernel/range_kernel.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +DECLARE_OPERATOR(Range, RangeParam, RangeKernel); + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/reduce_prod_op.cpp b/src/operators/reduce_prod_op.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d246965de05b24f23619b7bb4296da1a5b7f1a4c --- /dev/null +++ b/src/operators/reduce_prod_op.cpp @@ -0,0 +1,83 @@ +/* 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 REDUCE_PROD_OP + +#include "operators/reduce_prod_op.h" +#include + +namespace paddle_mobile { +namespace operators { + +template +void ReduceProdOp::InferShape() const { + PADDLE_MOBILE_ENFORCE(this->param_.Input() != nullptr, + "Input (X) of ReduceOp op should not be null."); + PADDLE_MOBILE_ENFORCE(this->param_.Output() != nullptr, + "Output (Output) of ReduceOp op should not be null."); + + auto x_dims = this->param_.Input()->dims(); + auto x_rank = x_dims.size(); + PADDLE_MOBILE_ENFORCE(x_rank <= 6, + "Tensors with rank at most 6 are supported."); + auto dims = this->param_.getDim(); + for (size_t i = 0; i < dims.size(); ++i) { + if (dims[i] < 0) dims[i] = x_rank + dims[i]; + PADDLE_MOBILE_ENFORCE( + dims[i] < x_rank, + "The dim should be in the range [-rank(input), rank(input))."); + } + sort(dims.begin(), dims.end()); + bool reduce_all = this->param_.isReduceAll(); + bool keep_dim = this->param_.isKeepDim(); + if (reduce_all) { + if (keep_dim) + this->param_.Output()->Resize( + framework::make_ddim(std::vector(x_rank, 1))); + else + this->param_.Output()->Resize({1}); + } else { + auto dims_vector = vectorize(x_dims); + if (keep_dim) { + for (size_t i = 0; i < dims.size(); ++i) { + dims_vector[dims[i]] = 1; + } + } else { + const int kDelFlag = -2; + for (size_t i = 0; i < dims.size(); ++i) { + dims_vector[dims[i]] = kDelFlag; + } + dims_vector.erase( + remove(dims_vector.begin(), dims_vector.end(), kDelFlag), + dims_vector.end()); + } + auto out_dims = framework::make_ddim(dims_vector); + this->param_.Output()->Resize(out_dims); + if (dims[0] != 0) { + // Only pass LoD when not reducing on the first dim. + this->param_.Output()->set_lod(this->param_.Input()->lod()); + } + } +} + +} // namespace operators +} // namespace paddle_mobile + +namespace ops = paddle_mobile::operators; + +#ifdef PADDLE_MOBILE_CPU +REGISTER_OPERATOR_CPU(reduce_prod, ops::ReduceProdOp); +#endif + +#endif // REDUCE_PROD_OP diff --git a/src/operators/reduce_prod_op.h b/src/operators/reduce_prod_op.h new file mode 100644 index 0000000000000000000000000000000000000000..46af419d2598b8dae123468c899a43c3d4a33c0c --- /dev/null +++ b/src/operators/reduce_prod_op.h @@ -0,0 +1,33 @@ +/* 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 REDUCE_PROD_OP + +#pragma once + +#include + +#include "framework/operator.h" +#include "operators/kernel/reduce_prod_kernel.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +DECLARE_OPERATOR(ReduceProd, ReduceProdParam, ReduceProdKernel); + +} // namespace operators +} // namespace paddle_mobile + +#endif diff --git a/src/operators/slice_op.cpp b/src/operators/slice_op.cpp index d1794b1fcef091e4b7675fc3a92325ed2d82a8a9..6cb9cebaa328a6b75bf5bbcef7179ab6ac1a9abb 100644 --- a/src/operators/slice_op.cpp +++ b/src/operators/slice_op.cpp @@ -56,10 +56,37 @@ void SliceOp::InferShape() const { this->param_.output_->dims().size())) == 3, "op only support slice channel now"); -#else - PADDLE_MOBILE_ENFORCE(input->dims().size() - axes[0] == 3, - "op only support slice channel now"); #endif + if (input->dims().size() >= 4) { + PADDLE_MOBILE_ENFORCE(input->dims().size() - axes[0] == 3, + "op only support slice channel now"); + } + auto starts = this->param_.starts_; + auto ends = this->param_.ends_; + framework::DDim out_dims(input->dims()); + PADDLE_MOBILE_ENFORCE(starts.size() == ends.size(), + "starts.size should equal ends.size"); + PADDLE_MOBILE_ENFORCE(axes.size() == starts.size(), + "axes.size should equal starts.size"); + int dim_value, start, end; + for (size_t i = 0; i < axes.size(); ++i) { + dim_value = out_dims[axes[i]]; + if (dim_value > 0) { + start = starts[i] < 0 ? (starts[i] + dim_value) : starts[i]; + end = ends[i] < 0 ? (ends[i] + dim_value) : ends[i]; + start = std::max(start, 0); + end = std::max(end, 0); + // start = std::min(start, dim_value); + end = std::min(end, dim_value); + // start = std::min(start, end); + PADDLE_MOBILE_ENFORCE(end > start, "end should greater than start"); + out_dims[axes[i]] = end - start; + } + } + output->Resize(out_dims); + if (axes[0] != 0) { + output->set_lod(input->lod()); + } } } // namespace operators diff --git a/tools/op.cmake b/tools/op.cmake index eb23a5b39163cf452cc3503a95ee8169cd4c0c93..358fb641cc3d08bca9a663324a3a87c9a72f5067 100755 --- a/tools/op.cmake +++ b/tools/op.cmake @@ -370,6 +370,12 @@ if(NOT FOUND_MATCH) set(ASSIGN_VALUE_OP ON) set(NEAREST_INTERP_OP ON) set(LEAKY_RELU_OP ON) + set(ASSIGN_OP ON) + set(CONDITIONAL_BLOCK_OP ON) + set(EQUAL_OP ON) + set(FILL_CONSTANT_BATCH_SIZE_LIKE_OP ON) + set(RANGE_OP ON) + set(REDUCE_PROD_OP ON) endif() # option(BATCHNORM_OP "" ON) @@ -719,3 +725,21 @@ endif() if (EXP_OP) add_definitions(-DEXP_OP) endif () +if (ASSIGN_OP) + add_definitions(-DASSIGN_OP) +endif() +if (CONDITIONAL_BLOCK_OP) + add_definitions(-DCONDITIONAL_BLOCK_OP) +endif() +if (EQUAL_OP) + add_definitions(-DEQUAL_OP) +endif() +if (FILL_CONSTANT_BATCH_SIZE_LIKE_OP) + add_definitions(-DFILL_CONSTANT_BATCH_SIZE_LIKE_OP) +endif() +if (RANGE_OP) + add_definitions(-DRANGE_OP) +endif() +if (REDUCE_PROD_OP) + add_definitions(-DREDUCE_PROD_OP) +endif()