From 0294a4e29932605a99d9696d2b183a4d225bafac Mon Sep 17 00:00:00 2001 From: hjchen2 Date: Fri, 25 Jan 2019 13:46:09 +0800 Subject: [PATCH] Refine java api, add write_to_array and read_from_array op --- src/common/log.h | 8 +-- src/common/types.cpp | 6 +- src/common/types.h | 2 + src/framework/attribute.h | 4 ++ src/framework/executor.cpp | 1 + src/framework/load_ops.h | 9 +++ src/framework/lod_tensor.h | 2 + src/framework/program/op_desc.cpp | 4 +- src/io/jni/paddle_mobile_jni.cpp | 7 +- .../tensor_array_read_write_op.cpp | 43 +++++++++++ .../controlflow/tensor_array_read_write_op.h | 34 +++++++++ src/operators/controlflow/while_op.cpp | 36 ++++++++++ src/operators/controlflow/while_op.h | 30 ++++++++ .../arm/tensor_array_read_write_kernel.cpp | 58 +++++++++++++++ src/operators/kernel/arm/while_kernel.cpp | 33 +++++++++ .../kernel/tensor_array_read_write_kernel.h | 32 +++++++++ src/operators/kernel/while_kernel.h | 47 ++++++++++++ src/operators/math/gemm.h | 1 + src/operators/op_param.h | 58 +++++++++++++++ src/operators/reshape_op.cpp | 0 test/CMakeLists.txt | 16 ++--- test/operators/test_conv_op.cpp | 38 +++++----- test/operators/test_log_op.cpp | 1 - test/operators/test_quantize_op.cpp | 24 +++---- test/operators/test_sequence_pool_op.cpp | 72 +++++++++---------- test/operators/test_sigmoid_op.cpp | 1 - test/operators/test_tanh_op.cpp | 2 +- tools/ci_build.sh | 12 +++- tools/ci_run_test.sh | 41 +++++++++++ tools/docker_build_fpga.sh | 2 + tools/op.cmake | 13 ++++ 31 files changed, 540 insertions(+), 97 deletions(-) create mode 100644 src/operators/controlflow/tensor_array_read_write_op.cpp create mode 100644 src/operators/controlflow/tensor_array_read_write_op.h create mode 100644 src/operators/controlflow/while_op.cpp create mode 100644 src/operators/controlflow/while_op.h create mode 100644 src/operators/kernel/arm/tensor_array_read_write_kernel.cpp create mode 100644 src/operators/kernel/arm/while_kernel.cpp create mode 100644 src/operators/kernel/tensor_array_read_write_kernel.h create mode 100644 src/operators/kernel/while_kernel.h mode change 100755 => 100644 src/operators/reshape_op.cpp create mode 100644 tools/ci_run_test.sh diff --git a/src/common/log.h b/src/common/log.h index c5146533d1..d574818f86 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -85,18 +85,18 @@ struct Print { private: void print(LogLevel level) { - buffer_ << std::endl; + // buffer_ << std::endl; if (level == kLOG_ERROR) { - std::cerr << buffer_.str(); + std::cerr << buffer_.str() << std::endl; } else { - std::cout << buffer_.str(); + std::cout << buffer_.str() << std::endl; } } std::ostringstream buffer_; }; struct ToLog { - ToLog(LogLevel level = kLOG_DEBUG, const std::string &info = "") + explicit ToLog(LogLevel level = kLOG_DEBUG, const std::string &info = "") : level_(level) { unsigned blanks = (unsigned)(level > kLOG_DEBUG ? (level - kLOG_DEBUG) * 4 : 1); diff --git a/src/common/types.cpp b/src/common/types.cpp index 18d7330a81..7edfde6f85 100644 --- a/src/common/types.cpp +++ b/src/common/types.cpp @@ -81,6 +81,8 @@ const char *G_OP_TYPE_LOGICAL_AND = "logical_and"; const char *G_OP_TYPE_LOGICAL_OR = "logical_or"; const char *G_OP_TYPE_LOGICAL_NOT = "logical_not"; const char *G_OP_TYPE_LOGICAL_XOR = "logical_xor"; +const char *G_OP_TYPE_WRITE_TO_ARRAY = "write_to_array"; +const char *G_OP_TYPE_READ_FROM_ARRAY = "read_from_array"; const char *G_OP_TYPE_QUANTIZE = "quantize"; const char *G_OP_TYPE_DEQUANTIZE = "dequantize"; @@ -189,5 +191,7 @@ std::unordered_map< {G_OP_TYPE_LOGICAL_AND, {{"X", "Y"}, {"Out"}}}, {G_OP_TYPE_LOGICAL_OR, {{"X", "Y"}, {"Out"}}}, {G_OP_TYPE_LOGICAL_XOR, {{"X", "Y"}, {"Out"}}}, - {G_OP_TYPE_LOGICAL_NOT, {{"X"}, {"Out"}}}}; + {G_OP_TYPE_LOGICAL_NOT, {{"X"}, {"Out"}}}, + {G_OP_TYPE_WRITE_TO_ARRAY, {{"X", "I"}, {"Out"}}}, + {G_OP_TYPE_READ_FROM_ARRAY, {{"X", "I"}, {"Out"}}}}; } // namespace paddle_mobile diff --git a/src/common/types.h b/src/common/types.h index 2927e838fc..31d8020d4d 100644 --- a/src/common/types.h +++ b/src/common/types.h @@ -170,6 +170,8 @@ extern const char *G_OP_TYPE_LOGICAL_AND; extern const char *G_OP_TYPE_LOGICAL_OR; extern const char *G_OP_TYPE_LOGICAL_NOT; extern const char *G_OP_TYPE_LOGICAL_XOR; +extern const char *G_OP_TYPE_WRITE_TO_ARRAY; +extern const char *G_OP_TYPE_READ_FROM_ARRAY; extern const char *G_OP_TYPE_QUANTIZE; extern const char *G_OP_TYPE_DEQUANTIZE; diff --git a/src/framework/attribute.h b/src/framework/attribute.h index a21e0a4ec3..3bc9284bfa 100644 --- a/src/framework/attribute.h +++ b/src/framework/attribute.h @@ -90,6 +90,10 @@ class Attribute { attr.Set(attr_desc->l); break; } + case PADDLE_MOBILE__FRAMEWORK__PROTO__ATTR_TYPE__BLOCK: { + attr.Set(attr_desc->block_idx); + break; + } default: PADDLE_MOBILE_THROW_EXCEPTION("attr type not support"); } diff --git a/src/framework/executor.cpp b/src/framework/executor.cpp index db48534097..e5b3fadfed 100644 --- a/src/framework/executor.cpp +++ b/src/framework/executor.cpp @@ -65,6 +65,7 @@ Executor::Executor(const Program &program, for (int j = 0; j < ops.size(); ++j) { std::shared_ptr op_desc = ops[j]; DLOG << "create op: " << op_desc->Type(); + auto op_handler = OpRegistry::CreateOp( op_desc->Type(), op_desc->GetInputs(), op_desc->GetOutputs(), op_desc->GetAttrMap(), program_.scope); diff --git a/src/framework/load_ops.h b/src/framework/load_ops.h index fca5fd82a0..eadef7d668 100644 --- a/src/framework/load_ops.h +++ b/src/framework/load_ops.h @@ -297,3 +297,12 @@ LOAD_OP1(logical_not, CPU); #ifdef LOGICAL_XOR_OP LOAD_OP1(logical_xor, CPU); #endif +#ifdef WHILE_OP +LOAD_OP1(while, CPU); +#endif +#ifdef WRITE_TO_ARRAY_OP +LOAD_OP1(write_to_array, CPU); +#endif +#ifdef READ_FROM_ARRAY_OP +LOAD_OP1(read_from_array, CPU); +#endif diff --git a/src/framework/lod_tensor.h b/src/framework/lod_tensor.h index bd956c8668..8c35a48f5f 100644 --- a/src/framework/lod_tensor.h +++ b/src/framework/lod_tensor.h @@ -176,6 +176,8 @@ LoDTensor LodExpand(const LoDTensor &source, const LoD &lod, size_t level) { return tensor; } +using LoDTensorArray = std::vector; + // Get the absolute offset of a lod[start_level][start_idx:end_idx] and // relative length of details for every levels(i.e., [start_level: ]). // diff --git a/src/framework/program/op_desc.cpp b/src/framework/program/op_desc.cpp index c8cbe3b608..318dd643bb 100644 --- a/src/framework/program/op_desc.cpp +++ b/src/framework/program/op_desc.cpp @@ -41,9 +41,7 @@ OpDesc::OpDesc(PaddleMobile__Framework__Proto__OpDesc *desc) { for (int k = 0; k < desc->n_attrs; ++k) { PaddleMobile__Framework__Proto__OpDesc__Attr *attr = desc->attrs[k]; std::string attr_name(attr->name); - if (attr->type != PADDLE_MOBILE__FRAMEWORK__PROTO__ATTR_TYPE__BLOCK) { - attrs_[attr_name] = Attribute::GetAttrValue(attr); - } + attrs_[attr_name] = Attribute::GetAttrValue(attr); } } diff --git a/src/io/jni/paddle_mobile_jni.cpp b/src/io/jni/paddle_mobile_jni.cpp index 2a0bb2362c..12c0a6cbca 100644 --- a/src/io/jni/paddle_mobile_jni.cpp +++ b/src/io/jni/paddle_mobile_jni.cpp @@ -90,7 +90,8 @@ JNIEXPORT jboolean JNICALL Java_com_baidu_paddle_PML_loadQualified( #ifdef ENABLE_EXCEPTION try { isLoadOk = getPaddleMobileInstance()->Load( - jstring2cppstring(env, modelPath), optimize, qualified); + jstring2cppstring(env, modelPath), optimize, qualified, 1, + static_cast(lodMode)); } catch (paddle_mobile::PaddleMobileException &e) { ANDROIDLOGE("jni got an PaddleMobileException! ", e.what()); isLoadOk = false; @@ -116,7 +117,7 @@ JNIEXPORT jboolean JNICALL Java_com_baidu_paddle_PML_loadCombined( try { isLoadOk = getPaddleMobileInstance()->Load( jstring2cppstring(env, modelPath), jstring2cppstring(env, paramPath), - optimize); + optimize, false, 1, static_cast(lodMode)); } catch (paddle_mobile::PaddleMobileException &e) { ANDROIDLOGE("jni got an PaddleMobileException! ", e.what()); isLoadOk = false; @@ -142,7 +143,7 @@ JNIEXPORT jboolean JNICALL Java_com_baidu_paddle_PML_loadCombinedQualified( try { isLoadOk = getPaddleMobileInstance()->Load( jstring2cppstring(env, modelPath), jstring2cppstring(env, paramPath), - optimize, qualified); + optimize, qualified, 1, static_cast(lodMode)); } catch (paddle_mobile::PaddleMobileException &e) { ANDROIDLOGE("jni got an PaddleMobileException! ", e.what()); isLoadOk = false; diff --git a/src/operators/controlflow/tensor_array_read_write_op.cpp b/src/operators/controlflow/tensor_array_read_write_op.cpp new file mode 100644 index 0000000000..0ea8ac01c6 --- /dev/null +++ b/src/operators/controlflow/tensor_array_read_write_op.cpp @@ -0,0 +1,43 @@ +/* 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 "operators/controlflow/tensor_array_read_write_op.h" + +namespace paddle_mobile { +namespace operators { + +#ifdef WRITE_TO_ARRAY_OP +template +void WriteToArrayOp::InferShape() const {} +#endif // WRITE_TO_ARRAY_OP + +#ifdef READ_FROM_ARRAY_OP +template +void ReadFromArrayOp::InferShape() const {} +#endif // READ_FROM_ARRAY_OP + +} // namespace operators +} // namespace paddle_mobile + +namespace ops = paddle_mobile::operators; + +#ifdef PADDLE_MOBILE_CPU +#ifdef WRITE_TO_ARRAY_OP +REGISTER_OPERATOR_CPU(write_to_array, ops::WriteToArrayOp); +#endif // WRITE_TO_ARRAY_OP + +#ifdef READ_FROM_ARRAY_OP +REGISTER_OPERATOR_CPU(read_from_array, ops::ReadFromArrayOp); +#endif // READ_FROM_ARRAY_OP +#endif diff --git a/src/operators/controlflow/tensor_array_read_write_op.h b/src/operators/controlflow/tensor_array_read_write_op.h new file mode 100644 index 0000000000..21d3ca10ef --- /dev/null +++ b/src/operators/controlflow/tensor_array_read_write_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. */ + +#pragma once + +#include +#include "framework/operator.h" +#include "operators/kernel/tensor_array_read_write_kernel.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +#ifdef WRITE_TO_ARRAY_OP +DECLARE_OPERATOR(WriteToArray, WriteToArrayParam, WriteToArrayKernel); +#endif // WRITE_TO_ARRAY_OP + +#ifdef READ_FROM_ARRAY_OP +DECLARE_OPERATOR(ReadFromArray, ReadFromArrayParam, ReadFromArrayKernel); +#endif // WRITE_TO_ARRAY_OP + +} // namespace operators +} // namespace paddle_mobile diff --git a/src/operators/controlflow/while_op.cpp b/src/operators/controlflow/while_op.cpp new file mode 100644 index 0000000000..06eb7c5709 --- /dev/null +++ b/src/operators/controlflow/while_op.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. */ + +#include "operators/controlflow/while_op.h" + +namespace paddle_mobile { +namespace operators { + +#ifdef WHILE_OP +template +void WhileOp::InferShape() const { + // TODO(hjchen2) +} +#endif // WHILE_OP + +} // namespace operators +} // namespace paddle_mobile + +namespace ops = paddle_mobile::operators; + +#ifdef PADDLE_MOBILE_CPU +#ifdef WHILE_OP +REGISTER_OPERATOR_CPU(while, ops::WhileOp); +#endif // WHILE_OP +#endif diff --git a/src/operators/controlflow/while_op.h b/src/operators/controlflow/while_op.h new file mode 100644 index 0000000000..6f753a08ef --- /dev/null +++ b/src/operators/controlflow/while_op.h @@ -0,0 +1,30 @@ +/* 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. */ + +#pragma once + +#include +#include "framework/operator.h" +#include "operators/kernel/while_kernel.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +#ifdef WHILE_OP +DECLARE_OPERATOR(While, WhileParam, WhileKernel); +#endif // WHILE_OP + +} // namespace operators +} // namespace paddle_mobile diff --git a/src/operators/kernel/arm/tensor_array_read_write_kernel.cpp b/src/operators/kernel/arm/tensor_array_read_write_kernel.cpp new file mode 100644 index 0000000000..5d6b86c34c --- /dev/null +++ b/src/operators/kernel/arm/tensor_array_read_write_kernel.cpp @@ -0,0 +1,58 @@ +/* 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 "operators/kernel/tensor_array_read_write_kernel.h" + +namespace paddle_mobile { +namespace operators { + +#ifdef WRITE_TO_ARRAY_OP +template <> +bool WriteToArrayKernel::Init(WriteToArrayParam *param) { + return true; +} + +template <> +void WriteToArrayKernel::Compute( + const WriteToArrayParam ¶m) { + int64_t offset = param.index_->data()[0]; + if (offset >= param.output_->size()) { + param.output_->resize(offset); + } + framework::LoDTensor *out_tensor = &(param.output_->at(offset)); + out_tensor->set_lod(param.input_->lod()); + if (param.input_->memory_size() > 0) { + TensorCopy(*(param.input_), out_tensor); + } +} +#endif // WRITE_TO_ARRAY_OP + +#ifdef READ_FROM_ARRAY_OP +template <> +bool ReadFromArrayKernel::Init(ReadFromArrayParam *param) { + return true; +} + +template <> +void ReadFromArrayKernel::Compute( + const ReadFromArrayParam ¶m) { + int64_t offset = param.index_->data()[0]; + if (offset < param.input_->size()) { + TensorCopy(param.input_->at(offset), param.output_); + } +} +#endif // READ_FROM_ARRAY_OP + +} // namespace operators +} // namespace paddle_mobile diff --git a/src/operators/kernel/arm/while_kernel.cpp b/src/operators/kernel/arm/while_kernel.cpp new file mode 100644 index 0000000000..f27a897ffc --- /dev/null +++ b/src/operators/kernel/arm/while_kernel.cpp @@ -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. */ + +#include "operators/kernel/while_kernel.h" + +namespace paddle_mobile { +namespace operators { + +#ifdef WHILE_OP +template <> +bool WhileKernel::Init(WhileParam *param) { + return true; +} + +template <> +void WhileKernel::Compute(const WhileParam ¶m) { + // TODO(hjchen2) +} +#endif // WHILE_OP + +} // namespace operators +} // namespace paddle_mobile diff --git a/src/operators/kernel/tensor_array_read_write_kernel.h b/src/operators/kernel/tensor_array_read_write_kernel.h new file mode 100644 index 0000000000..8b666c0b40 --- /dev/null +++ b/src/operators/kernel/tensor_array_read_write_kernel.h @@ -0,0 +1,32 @@ +/* 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. */ + +#pragma once + +#include "framework/operator.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +#ifdef WRITE_TO_ARRAY_OP +DECLARE_KERNEL(WriteToArray, WriteToArrayParam); +#endif // WRITE_TO_ARRAY_OP + +#ifdef READ_FROM_ARRAY_OP +DECLARE_KERNEL(ReadFromArray, ReadFromArrayParam); +#endif // READ_FROM_ARRAY_OP + +} // namespace operators +} // namespace paddle_mobile diff --git a/src/operators/kernel/while_kernel.h b/src/operators/kernel/while_kernel.h new file mode 100644 index 0000000000..72b0f5f738 --- /dev/null +++ b/src/operators/kernel/while_kernel.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. */ + +#pragma once + +#include "framework/operator.h" +#include "operators/op_param.h" + +namespace paddle_mobile { +namespace operators { + +#ifdef WHILE_OP +template +class WhileParam : public OpParam { + public: + WhileParam(const VariableNameMap &inputs, const VariableNameMap &outputs, + const AttributeMap &attrs, const Scope &scope) + : inputs_(inputs), outputs_(outputs), scope_(scope) { + cond_ = + OpParam::GetVarValue("Condition", inputs, scope); + sub_block_ = OpParam::GetAttr("sub_block", attrs); + } + + public: + framework::LoDTensor *cond_; + int sub_block_; + const VariableNameMap inputs_; + const VariableNameMap outputs_; + const Scope scope_; +}; + +DECLARE_KERNEL(While, WhileParam); +#endif // WHILE_OP + +} // namespace operators +} // namespace paddle_mobile diff --git a/src/operators/math/gemm.h b/src/operators/math/gemm.h index 99c68de7c3..b6af1c838d 100644 --- a/src/operators/math/gemm.h +++ b/src/operators/math/gemm.h @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ #pragma once +#include #include #include "common/log.h" #include "memory/t_malloc.h" diff --git a/src/operators/op_param.h b/src/operators/op_param.h index 1f20f55056..959bfd7f74 100644 --- a/src/operators/op_param.h +++ b/src/operators/op_param.h @@ -2991,5 +2991,63 @@ class LogicalUnaryParam : public OpParam { }; #endif // LOGICAL_NOT_OP +// #ifdef WHILE_OP +// template +// class WhileParam : public OpParam { +// public: +// WhileParam(const VariableNameMap &inputs, +// const VariableNameMap &outputs, const AttributeMap &attrs, +// const Scope &scope) { +// cond_ = OpParam::GetVarValue("Condition", inputs, +// scope); block_desc_ = OpParam::GetAttr("sub_block", attrs); +// } +// +// public: +// framework::LoDTensor *cond_; +// const framework::BlockDesc *block_desc_; +// }; +// #endif // WHILE_OP + +#ifdef WRITE_TO_ARRAY_OP +template +class WriteToArrayParam : public OpParam { + public: + WriteToArrayParam(const VariableNameMap &inputs, + const VariableNameMap &outputs, const AttributeMap &attrs, + const Scope &scope) { + input_ = OpParam::GetVarValue("X", inputs, scope); + index_ = OpParam::GetVarValue("I", inputs, scope); + output_ = + OpParam::GetVarValue("Out", outputs, scope); + } + + public: + framework::LoDTensor *input_; + framework::LoDTensor *index_; + framework::LoDTensorArray *output_; +}; +#endif + +#ifdef READ_FROM_ARRAY_OP +template +class ReadFromArrayParam : public OpParam { + public: + ReadFromArrayParam(const VariableNameMap &inputs, + const VariableNameMap &outputs, const AttributeMap &attrs, + const Scope &scope) { + input_ = + OpParam::GetVarValue("X", inputs, scope); + index_ = OpParam::GetVarValue("I", inputs, scope); + output_ = OpParam::GetVarValue("Out", outputs, scope); + } + + public: + framework::LoDTensorArray *input_; + framework::LoDTensor *index_; + framework::LoDTensor *output_; +}; +#endif + } // namespace operators } // namespace paddle_mobile diff --git a/src/operators/reshape_op.cpp b/src/operators/reshape_op.cpp old mode 100755 new mode 100644 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 23634f33fe..aa47f270a1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -337,8 +337,8 @@ if (NOT FOUND_MATCH) target_link_libraries(test-genet paddle-mobile) # gen test - ADD_EXECUTABLE(test-sigmoid operators/test_sigmoid_op.cpp test_include.h) - target_link_libraries(test-sigmoid paddle-mobile) + ADD_EXECUTABLE(test-sigmoid-op operators/test_sigmoid_op.cpp test_include.h) + target_link_libraries(test-sigmoid-op paddle-mobile) # gen test ADD_EXECUTABLE(test-depthwise-conv-op operators/test_depthwise_conv_op.cpp test_helper.h test_include.h executor_for_test.h) @@ -408,14 +408,14 @@ if (NOT FOUND_MATCH) ADD_EXECUTABLE(test-ocr net/test_ocr.cpp test_helper.h test_include.h) target_link_libraries(test-ocr paddle-mobile) - ADD_EXECUTABLE(test-sequence-expand operators/test_sequence_expand_op.cpp test_helper.h test_include.h) - target_link_libraries(test-sequence-expand paddle-mobile) + ADD_EXECUTABLE(test-sequence-expand-op operators/test_sequence_expand_op.cpp test_helper.h test_include.h) + target_link_libraries(test-sequence-expand-op paddle-mobile) - ADD_EXECUTABLE(test-sequence-pool operators/test_sequence_pool_op.cpp test_helper.h test_include.h) - target_link_libraries(test-sequence-pool paddle-mobile) + ADD_EXECUTABLE(test-sequence-pool-op operators/test_sequence_pool_op.cpp test_helper.h test_include.h) + target_link_libraries(test-sequence-pool-op paddle-mobile) - 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) + ADD_EXECUTABLE(test-sequence-softmax-op operators/test_sequence_softmax_op.cpp test_helper.h test_include.h) + target_link_libraries(test-sequence-softmax-op paddle-mobile) # gen test ADD_EXECUTABLE(test-vgg16ssd net/test_vgg16ssd.cpp test_helper.h test_include.h) diff --git a/test/operators/test_conv_op.cpp b/test/operators/test_conv_op.cpp index c596c1def4..ffd4445eab 100644 --- a/test/operators/test_conv_op.cpp +++ b/test/operators/test_conv_op.cpp @@ -222,27 +222,8 @@ int TestConvOp(int in_channels, int in_height, int in_width, int out_channels, } // namespace paddle_mobile -int main(int argc, char *argv[]) { - if (argc < 5) { - LOG(paddle_mobile::kLOG_INFO) - << "Usage:\n" - << " ./test-int8-conv-op in_channels in_height in_width out_channels " - "[groups]\n" - << " params:\n" - << " -in_channels: int, input image's channels\n" - << " -in_height: int, input image's height\n" - << " -in_width: int, input image's width\n" - << " -out_channels: int, conv output channels\n"; - return 1; - } - int in_channels = atoi(argv[1]); - int in_height = atoi(argv[2]); - int in_width = atoi(argv[3]); - int out_channels = atoi(argv[4]); - int groups = 1; - if (argc == 6) { - groups = atoi(argv[5]); - } +int TestAll(const int in_channels, const int in_height, const int in_width, + const int out_channels, const int groups) { // kernel = 3, pad = 0, stride = 1 LOG(paddle_mobile::kLOG_INFO) << "float, kernel=3, pad=0, stride=1"; paddle_mobile::TestConvOp( @@ -313,3 +294,18 @@ int main(int argc, char *argv[]) { return 0; } + +int main() { + TestAll(1, 5, 5, 1, 1); + TestAll(1, 5, 5, 10, 1); + TestAll(10, 5, 5, 10, 10); + + TestAll(5, 33, 33, 5, 1); + TestAll(5, 33, 33, 13, 1); + TestAll(13, 33, 33, 13, 13); + + TestAll(5, 33, 13, 5, 1); + TestAll(5, 33, 13, 13, 1); + TestAll(13, 33, 13, 13, 13); + return 0; +} diff --git a/test/operators/test_log_op.cpp b/test/operators/test_log_op.cpp index 8d675f06de..2f29e8711b 100644 --- a/test/operators/test_log_op.cpp +++ b/test/operators/test_log_op.cpp @@ -76,6 +76,5 @@ int main() { paddle_mobile::TestLogOp({1, 1, 2, 3}); paddle_mobile::TestLogOp({1, 3, 11, 22}); paddle_mobile::TestLogOp({1, 32, 112, 112}); - std::cout << "test log op pass." << std::endl; return 0; } diff --git a/test/operators/test_quantize_op.cpp b/test/operators/test_quantize_op.cpp index 50c0e7bd05..f3b8fd151c 100644 --- a/test/operators/test_quantize_op.cpp +++ b/test/operators/test_quantize_op.cpp @@ -92,18 +92,10 @@ static float find_abs_max(const Tensor *input) { return max_abs; } -int TestQuqntizeOp(int argc, char *argv[]) { - if (argc < 5) { - std::cout << "Usage: ./test-quantize-op batch_size channel height width" - << std::endl; - return 1; - } - int batch_size = atoi(argv[1]); - int channel = atoi(argv[2]); - int height = atoi(argv[3]); - int width = atoi(argv[4]); - std::cout << "batch_size: " << batch_size << ", channel: " << channel - << ", height: " << height << ", width: " << width << std::endl; +int TestQuqntizeOp(const int batch_size, const int channel, const int height, + const int width) { + DLOG << "batch_size: " << batch_size << ", channel: " << channel + << ", height: " << height << ", width: " << width; framework::DDim dim = framework::make_ddim({batch_size, channel, height, width}); @@ -140,9 +132,7 @@ int TestQuqntizeOp(int argc, char *argv[]) { framework::Tensor output_cmp; output_cmp.Resize(output->dims()); float scale = 127 / output_scale_cmp; - // quantize(input, scale, &output_cmp); - // quantize(input, scale, &output_cmp); - quantize(input, scale, &output_cmp); + quantize(input, scale, &output_cmp); int8_t *output_cmp_data = output_cmp.data(); for (int i = 0; i < output->numel(); ++i) { PADDLE_MOBILE_ENFORCE(output_data[i] == output_cmp_data[i], @@ -157,5 +147,7 @@ int TestQuqntizeOp(int argc, char *argv[]) { } // namespace paddle_mobile int main(int argc, char *argv[]) { - return paddle_mobile::TestQuqntizeOp(argc, argv); + TestQuqntizeOp(1, 10, 10, 5); + TestQuqntizeOp(1, 111, 111, 5); + TestQuqntizeOp(5, 111, 111, 5); } diff --git a/test/operators/test_sequence_pool_op.cpp b/test/operators/test_sequence_pool_op.cpp index a8518d630a..3b377aa437 100644 --- a/test/operators/test_sequence_pool_op.cpp +++ b/test/operators/test_sequence_pool_op.cpp @@ -59,7 +59,7 @@ int TestSequencePoolOp(const framework::LoDTensor &input_x, int main(int argc, char *argv[]) { framework::LoDTensor input_x, output; // case 1 - std::cerr << "running max case 1" << std::endl; + DLOG << "running max case 1"; { std::vector data{1, 2, 3, 4}; input_x.Resize(framework::make_ddim({4, 1})); @@ -71,14 +71,14 @@ int main(int argc, char *argv[]) { std::vector expect_data{2, 4}; for (int i = 0; i < 2; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } // case 2 - std::cerr << "running max case 2" << std::endl; + DLOG << "running max case 2"; { std::vector data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; input_x.Resize(framework::make_ddim({data.size(), 1})); @@ -90,13 +90,13 @@ int main(int argc, char *argv[]) { std::vector expect_data{3, 10}; for (int i = 0; i < 2; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } - std::cerr << "running max case 3" << std::endl; + DLOG << "running max case 3"; // case 3 { std::vector data{1, 2, 3, 4, 5, 6, 7, 8}; @@ -109,14 +109,14 @@ int main(int argc, char *argv[]) { std::vector expect_data{3, 4, 7, 8}; for (int i = 0; i < 4; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } // case 4 - std::cerr << "running max case 4" << std::endl; + DLOG << "running max case 4"; { std::vector data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; @@ -129,14 +129,14 @@ int main(int argc, char *argv[]) { std::vector expect_data{6, 7, 8, 9, 10, 16, 17, 18, 19, 20}; for (int i = 0; i < 10; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } // case 1 - std::cerr << "running sum case 1" << std::endl; + DLOG << "running sum case 1"; { std::vector data{1, 2, 3, 4}; input_x.Resize(framework::make_ddim({4, 1})); @@ -148,14 +148,14 @@ int main(int argc, char *argv[]) { std::vector expect_data{3, 7}; for (int i = 0; i < 2; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } // case 2 - std::cerr << "running sum case 2" << std::endl; + DLOG << "running sum case 2"; { std::vector data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; input_x.Resize(framework::make_ddim({data.size(), 1})); @@ -167,14 +167,14 @@ int main(int argc, char *argv[]) { std::vector expect_data{6, 49}; for (int i = 0; i < 2; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } // case 3 - std::cerr << "running sum case 3" << std::endl; + DLOG << "running sum case 3"; { std::vector data{1, 2, 3, 4, 5, 6, 7, 8}; input_x.Resize(framework::make_ddim({4, 2})); @@ -186,14 +186,14 @@ int main(int argc, char *argv[]) { std::vector expect_data{4, 6, 12, 14}; for (int i = 0; i < 4; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } // case 4 - std::cerr << "running sum case 4" << std::endl; + DLOG << "running sum case 4"; { std::vector data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; @@ -206,14 +206,14 @@ int main(int argc, char *argv[]) { std::vector expect_data{7, 9, 11, 13, 15, 27, 29, 31, 33, 35}; for (int i = 0; i < 10; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } // case 1 - std::cerr << "running first case 1" << std::endl; + DLOG << "running first case 1"; { std::vector data{1, 2, 3, 4}; input_x.Resize(framework::make_ddim({4, 1})); @@ -225,14 +225,14 @@ int main(int argc, char *argv[]) { std::vector expect_data{1, 3}; for (int i = 0; i < 2; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } // case 2 - std::cerr << "running first case 2" << std::endl; + DLOG << "running first case 2"; { std::vector data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; input_x.Resize(framework::make_ddim({data.size(), 1})); @@ -244,14 +244,14 @@ int main(int argc, char *argv[]) { std::vector expect_data{1, 4}; for (int i = 0; i < 2; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } // case 3 - std::cerr << "running first case 3" << std::endl; + DLOG << "running first case 3"; { std::vector data{1, 2, 3, 4, 5, 6, 7, 8}; input_x.Resize(framework::make_ddim({4, 2})); @@ -263,14 +263,14 @@ int main(int argc, char *argv[]) { std::vector expect_data{1, 2, 5, 6}; for (int i = 0; i < 4; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } } // case 4 - std::cerr << "running first case 4" << std::endl; + DLOG << "running first case 4"; { std::vector data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; @@ -283,8 +283,8 @@ int main(int argc, char *argv[]) { std::vector expect_data{1, 2, 3, 4, 5, 11, 12, 13, 14, 15}; for (int i = 0; i < 10; ++i) { if (output.data()[i] != expect_data[i]) { - std::cerr << "output[" << i << "]: " << output.data()[i] - << " != expect[" << i << "]: " << expect_data[i] << std::endl; + DLOG << "output[" << i << "]: " << output.data()[i] + << " != expect[" << i << "]: " << expect_data[i]; return 1; } } diff --git a/test/operators/test_sigmoid_op.cpp b/test/operators/test_sigmoid_op.cpp index 40f6461a2c..260dd62781 100644 --- a/test/operators/test_sigmoid_op.cpp +++ b/test/operators/test_sigmoid_op.cpp @@ -76,6 +76,5 @@ int main() { paddle_mobile::TestSigmoidOp({1, 1, 2, 3}); paddle_mobile::TestSigmoidOp({1, 3, 11, 22}); paddle_mobile::TestSigmoidOp({1, 32, 112, 112}); - std::cout << "test sigmoid op pass." << std::endl; return 0; } diff --git a/test/operators/test_tanh_op.cpp b/test/operators/test_tanh_op.cpp index b800693107..d013b0eedf 100644 --- a/test/operators/test_tanh_op.cpp +++ b/test/operators/test_tanh_op.cpp @@ -58,7 +58,7 @@ int TestTanhOp(const std::vector input_shape) { const float *output_data = output->data(); for (int i = 0; i < output->numel(); ++i) { float gap = output_data[i] - output_cmp_data[i]; - if (std::abs(gap / (output_data[i] + 1e-5)) > 1e-3) { + if (gap > 1e-5 && std::abs(gap / (output_data[i] + 1e-5)) > 1e-3) { LOG(kLOG_INFO) << "output_data[" << i << "] = " << output_data[i] << ", output_cmp_data[" << i << "] = " << output_cmp_data[i]; diff --git a/tools/ci_build.sh b/tools/ci_build.sh index f21bcdc67e..e1f2a5271d 100755 --- a/tools/ci_build.sh +++ b/tools/ci_build.sh @@ -15,6 +15,7 @@ # limitations under the License. set -e +source ./ci_run_test.sh function print_usage() { echo "\n${RED}Usage${NONE}: @@ -63,7 +64,7 @@ function check_ndk() { } function build_android_armv7_cpu_only() { - rm -rf ../build/armeabi-v7a +# rm -rf ../build/armeabi-v7a cmake .. \ -B"../build/armeabi-v7a" \ -DANDROID_ABI="armeabi-v7a with NEON" \ @@ -82,7 +83,7 @@ function build_android_armv7_cpu_only() { } function build_android_armv7_gpu() { - rm -rf ../build/armeabi-v7a +# rm -rf ../build/armeabi-v7a cmake .. \ -B"../build/armeabi-v7a" \ -DANDROID_ABI="armeabi-v7a with NEON" \ @@ -231,6 +232,11 @@ function build_linux_fpga() { docker build -t paddle-mobile:dev - < Dockerfile fi docker run --rm -v `pwd`:/workspace paddle-mobile:dev bash /workspace/tools/docker_build_fpga.sh + cd - +} + +function run_android_test() { + ExecuteAndroidTest $1 } function main() { @@ -239,9 +245,11 @@ function main() { case $CMD in android_armv7) build_android_armv7 + run_android_test armeabi-v7a ;; android_armv8) build_android_armv8 + run_android_test arm64-v8a ;; ios) build_ios diff --git a/tools/ci_run_test.sh b/tools/ci_run_test.sh new file mode 100644 index 0000000000..bcdad5a99c --- /dev/null +++ b/tools/ci_run_test.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +operators= + +function AddTest() { + operators="${operators} $1" +} + +function ExecuteAndroidTest() { + platform=$1 + adb shell rm -rf /data/local/tmp/* + adb push ../build/${platform}/build/libpaddle-mobile.so /data/local/tmp/ + for op in ${operators} + do + adb push ../test/build/test-${op}-op /data/local/tmp/ + adb shell "cd /data/local/tmp/; LD_LIBRARY_PATH=. ./test-${op}-op" + echo "${BLUE}run test ${op} pass${NONE}" + done +} + +AddTest batchnorm +AddTest cast +AddTest conv +AddTest dequantize +#AddTest elementwiseadd +AddTest log +AddTest logical-and +AddTest logical-not +AddTest logical-or +AddTest logical-xor +AddTest pool +AddTest quantize +AddTest relu +AddTest relu6 +AddTest sequence-expand +AddTest sequence-pool +AddTest sequence-softmax +AddTest sigmoid +AddTest softmax +AddTest tanh +AddTest topk diff --git a/tools/docker_build_fpga.sh b/tools/docker_build_fpga.sh index 0927c328dd..31a28b1532 100644 --- a/tools/docker_build_fpga.sh +++ b/tools/docker_build_fpga.sh @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + apt-get update apt-get install -y gcc g++ cmake diff --git a/tools/op.cmake b/tools/op.cmake index cf68f24491..65afb07054 100644 --- a/tools/op.cmake +++ b/tools/op.cmake @@ -285,6 +285,9 @@ if(NOT FOUND_MATCH) set(LOGICAL_OR_OP ON) set(LOGICAL_NOT_OP ON) set(LOGICAL_XOR_OP ON) + set(WHILE_OP ON) + set(WRITE_TO_ARRAY_OP ON) + set(READ_FROM_ARRAY_OP ON) endif() # option(BATCHNORM_OP "" ON) @@ -559,3 +562,13 @@ endif() if (FUSION_DECONVADDRELU_OP) add_definitions(-DFUSION_DECONVADDRELU_OP) endif() + +if (WHILE_OP) + add_definitions(-DWHILE_OP) +endif() +if (WRITE_TO_ARRAY_OP) + add_definitions(-DWRITE_TO_ARRAY_OP) +endif() +if (READ_FROM_ARRAY_OP) + add_definitions(-DREAD_FROM_ARRAY_OP) +endif() -- GitLab