From 1e6e4f6027c92352710a07925b3073614ed60202 Mon Sep 17 00:00:00 2001 From: wang_shaocong Date: Mon, 1 Mar 2021 14:54:25 +0800 Subject: [PATCH] [MSLITE] Fix bug of the padding parameter of onnx pad operator. --- .../lite/nnacl/fp32/strided_slice_fp32.c | 1 - .../runtime/kernel/arm/base/resize_base.cc | 2 +- mindspore/lite/test/CMakeLists.txt | 1 + mindspore/lite/tools/converter/CMakeLists.txt | 1 + .../lite/tools/converter/anf_transform.cc | 7 + .../optimizer/common/pass_manager_extends.cc | 2 +- .../optimizer/graph/onnx_pad_adjust_pass.cc | 143 ++++++++++++++++++ .../optimizer/graph/onnx_pad_adjust_pass.h | 38 +++++ 8 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 mindspore/lite/tools/optimizer/graph/onnx_pad_adjust_pass.cc create mode 100644 mindspore/lite/tools/optimizer/graph/onnx_pad_adjust_pass.h diff --git a/mindspore/lite/nnacl/fp32/strided_slice_fp32.c b/mindspore/lite/nnacl/fp32/strided_slice_fp32.c index 3c9b917e9f..e6044cdae9 100644 --- a/mindspore/lite/nnacl/fp32/strided_slice_fp32.c +++ b/mindspore/lite/nnacl/fp32/strided_slice_fp32.c @@ -84,7 +84,6 @@ int DoStridedSlice(const void *in_data, void *out_data, StridedSliceParameter *p if (param->num_axes_ < DIMENSION_6D) { PadStridedSliceParameterTo6D(param); } - ChangeNegToPositive(param); size_t dim_offset[DIMENSION_6D - 1]; dim_offset[4] = in_shape[5]; diff --git a/mindspore/lite/src/runtime/kernel/arm/base/resize_base.cc b/mindspore/lite/src/runtime/kernel/arm/base/resize_base.cc index 1af7d9f4a4..4a04f10310 100644 --- a/mindspore/lite/src/runtime/kernel/arm/base/resize_base.cc +++ b/mindspore/lite/src/runtime/kernel/arm/base/resize_base.cc @@ -62,8 +62,8 @@ int ResizeBaseCPUKernel::CheckParameters() { if (InferShapeDone()) { new_height_ = out_tensors_.at(0)->shape().at(1); new_width_ = out_tensors_.at(0)->shape().at(2); + const_shape_ = true; } - const_shape_ = true; } } coordinate_transform_mode_ = parameter->coordinate_transform_mode_; diff --git a/mindspore/lite/test/CMakeLists.txt b/mindspore/lite/test/CMakeLists.txt index 9a9374f141..02e7cfe642 100644 --- a/mindspore/lite/test/CMakeLists.txt +++ b/mindspore/lite/test/CMakeLists.txt @@ -257,6 +257,7 @@ if(ENABLE_CONVERTER) ${LITE_DIR}/tools/optimizer/graph/slice_prepose_pass.cc ${LITE_DIR}/tools/optimizer/graph/mindir_adjust_pass.cc ${LITE_DIR}/tools/optimizer/graph/onnx_inputs_adjust_pass.cc + ${LITE_DIR}/tools/optimizer/graph/onnx_pad_adjust_pass.cc ${LITE_DIR}/tools/optimizer/graph/while_pass.cc ${LITE_DIR}/tools/optimizer/graph/if_pass.cc ${LITE_DIR}/tools/optimizer/graph/functionalize_control_op_pass.cc diff --git a/mindspore/lite/tools/converter/CMakeLists.txt b/mindspore/lite/tools/converter/CMakeLists.txt index 70f5a8fe87..575b845cbd 100644 --- a/mindspore/lite/tools/converter/CMakeLists.txt +++ b/mindspore/lite/tools/converter/CMakeLists.txt @@ -67,6 +67,7 @@ file(GLOB_RECURSE CONVERTER_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ../optimizer/graph/slice_prepose_pass.cc ../optimizer/graph/mindir_adjust_pass.cc ../optimizer/graph/onnx_inputs_adjust_pass.cc + ../optimizer/graph/onnx_pad_adjust_pass.cc ../optimizer/graph/while_pass.cc ../optimizer/graph/if_pass.cc ../optimizer/graph/functionalize_control_op_pass.cc diff --git a/mindspore/lite/tools/converter/anf_transform.cc b/mindspore/lite/tools/converter/anf_transform.cc index 28acec5da5..c9bd5547d8 100644 --- a/mindspore/lite/tools/converter/anf_transform.cc +++ b/mindspore/lite/tools/converter/anf_transform.cc @@ -45,6 +45,7 @@ #include "tools/optimizer/graph/group_depthwise_op_convert_pass.h" #include "tools/optimizer/graph/tflite_inputs_adjust_pass.h" #include "tools/optimizer/graph/onnx_inputs_adjust_pass.h" +#include "tools/optimizer/graph/onnx_pad_adjust_pass.h" #include "tools/optimizer/graph/update_conv2d_param_pass.h" #include "tools/optimizer/graph/unused_node_remove_pass.h" #include "tools/optimizer/graph/unused_cast_node_remove_pass.h" @@ -221,6 +222,12 @@ int AnfTransform::RunOnnxAdjustPass(const FuncGraphPtr &old_graph, const convert ReturnCode::GetSingleReturnCode()->UpdateReturnCode(RET_ERROR); return RET_ERROR; } + auto onnx_pad_adjust_pass = std::make_shared(); + if (!onnx_pad_adjust_pass->Run(old_graph)) { + MS_LOG(ERROR) << "onnx pad adjust failed."; + ReturnCode::GetSingleReturnCode()->UpdateReturnCode(RET_ERROR); + return RET_ERROR; + } return RET_OK; } diff --git a/mindspore/lite/tools/optimizer/common/pass_manager_extends.cc b/mindspore/lite/tools/optimizer/common/pass_manager_extends.cc index 326cfd732b..a20ef4b7c6 100644 --- a/mindspore/lite/tools/optimizer/common/pass_manager_extends.cc +++ b/mindspore/lite/tools/optimizer/common/pass_manager_extends.cc @@ -27,7 +27,7 @@ namespace mindspore { namespace opt { static size_t count = 0; -constexpr size_t kMaxRepassTimes = 9; +constexpr size_t kMaxRepassTimes = 12; const std::vector &PassManager::Passes() const { return passes_; } void PassManager::AddPass(const PassPtr &pass) { diff --git a/mindspore/lite/tools/optimizer/graph/onnx_pad_adjust_pass.cc b/mindspore/lite/tools/optimizer/graph/onnx_pad_adjust_pass.cc new file mode 100644 index 0000000000..380ca5a422 --- /dev/null +++ b/mindspore/lite/tools/optimizer/graph/onnx_pad_adjust_pass.cc @@ -0,0 +1,143 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * 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 "tools/optimizer/graph/onnx_pad_adjust_pass.h" +#include +#include +#include +#include +#include "ops/reshape.h" +#include "ops/transpose.h" +#include "ops/primitive_c.h" +#include "src/param_value_lite.h" +#include "tools/optimizer/common/gllo_utils.h" + +namespace mindspore::opt { +namespace { +constexpr uint32_t kTripleNum = 3; +} // namespace +ParameterPtr OnnxPadAdjustPass::CreateNewParameter(const FuncGraphPtr &func_graph, const std::vector &data) { + MS_ASSERT(func_graph != nullptr); + MS_ASSERT(data != nullptr); + auto parameter = func_graph->add_parameter(); + std::vector shape; + shape.push_back(static_cast(data.size())); + std::vector shape_vector; + (void)std::transform(shape.begin(), shape.end(), std::back_inserter(shape_vector), + [](const int32_t &value) { return static_cast(value); }); + auto type_id = static_cast(kNumberTypeInt32); + auto type_ptr = TypeIdToType(type_id); + auto abstract_tensor = std::make_shared(type_ptr, shape_vector); + parameter->set_abstract(abstract_tensor); + + ParamValueLitePtr param_value = std::make_shared(); + MS_ASSERT(param_value != nullptr); + param_value->set_tensor_shape(shape); + param_value->set_tensor_type(type_id); + param_value->set_format(schema::Format_NCHW); + + size_t size = data.size() * sizeof(int); + auto tensor_data = new (std::nothrow) uint8_t[size]; + if (tensor_data == nullptr) { + MS_LOG(ERROR) << "tensor_data is nullptr"; + return nullptr; + } + auto ret = memcpy_s(tensor_data, size, data.data(), size); + if (ret != 0) { + MS_LOG(ERROR) << "set tensor data failed."; + return nullptr; + } + param_value->SetTensorData(tensor_data, size); + parameter->set_default_param(param_value); + return parameter; +} + +CNodePtr OnnxPadAdjustPass::NewReshapeOpNode(const FuncGraphPtr &func_graph, const AnfNodePtr input_node, + const std::vector &shape) { + auto reshape_prim = std::make_shared(); + if (reshape_prim == nullptr) { + MS_LOG(ERROR) << "create reshape failed."; + return nullptr; + } + reshape_prim->set_attr("shape", MakeValue(shape)); + ValueNodePtr value_node = NewValueNode(reshape_prim); + auto new_parameter = CreateNewParameter(func_graph, shape); + new_parameter->set_name(input_node->fullname_with_scope() + "_reshape/shape"); + std::vector op_inputs = {value_node, input_node, new_parameter}; + auto reshape = func_graph->NewCNode(op_inputs); + reshape->set_fullname_with_scope(input_node->fullname_with_scope() + "_reshape"); + return reshape; +} + +CNodePtr OnnxPadAdjustPass::NewTransposeOpNode(const FuncGraphPtr &func_graph, const AnfNodePtr input_node, + std::vector perm) { + auto transpose_prim = std::make_shared(); + if (transpose_prim == nullptr) { + MS_LOG(ERROR) << "create transpose failed."; + return nullptr; + } + transpose_prim->set_attr("perm", MakeValue(perm)); + ValueNodePtr value_node = NewValueNode(transpose_prim); + auto new_parameter = CreateNewParameter(func_graph, perm); + new_parameter->set_name(input_node->fullname_with_scope() + "_transpose/perm"); + std::vector op_inputs = {value_node, input_node, new_parameter}; + auto reshape = func_graph->NewCNode(op_inputs); + reshape->set_fullname_with_scope(input_node->fullname_with_scope() + "_transpose"); + return reshape; +} + +bool OnnxPadAdjustPass::Run(const FuncGraphPtr &func_graph) { + MS_ASSERT(func_graph != nullptr); + auto cnodes = func_graph->GetOrderedCnodes(); + for (auto &cnode : cnodes) { + if (!CheckPrimitiveType(cnode, prim::kPrimPadFusion) || cnode->inputs().size() != kTripleNum) { + continue; + } + // get the second input node whose output is the padding parameter of pad. + auto input_node = cnode->input(2); + if (!input_node->isa()) { + continue; + } + // reshape the padding of pad operator to 2 x 4. + std::vector shape_pre = {2, 4}; + auto reshape_pre = NewReshapeOpNode(func_graph, input_node, shape_pre); + if (reshape_pre == nullptr) { + MS_LOG(ERROR) << "create reshape failed."; + return false; + } + std::vector perm = {1, 0}; + auto transpose = NewTransposeOpNode(func_graph, reshape_pre, perm); + if (transpose == nullptr) { + MS_LOG(ERROR) << "create transpose failed."; + return false; + } + // reshape the padding of pad operator to -1. + std::vector shape_pos = {-1}; + auto reshape_pos = NewReshapeOpNode(func_graph, transpose, shape_pos); + if (reshape_pos == nullptr) { + MS_LOG(ERROR) << "create reshape failed."; + return false; + } + + auto manager = func_graph->manager(); + if (manager == nullptr) { + MS_LOG(ERROR) << "manager is nullptr."; + return false; + } + manager->Replace(input_node, reshape_pos); + } + return true; +} +} // namespace mindspore::opt diff --git a/mindspore/lite/tools/optimizer/graph/onnx_pad_adjust_pass.h b/mindspore/lite/tools/optimizer/graph/onnx_pad_adjust_pass.h new file mode 100644 index 0000000000..d2ffcd58c5 --- /dev/null +++ b/mindspore/lite/tools/optimizer/graph/onnx_pad_adjust_pass.h @@ -0,0 +1,38 @@ +/** + * Copyright 2021 Huawei Technologies Co., Ltd + * + * 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. + */ + +#ifndef MINDSPORE_LITE_TOOLS_OPTIMIZER_GRAPH_ONNX_PAD_ADJUST_PASS_H_ +#define MINDSPORE_LITE_TOOLS_OPTIMIZER_GRAPH_ONNX_PAD_ADJUST_PASS_H_ +#include +#include +#include "backend/optimizer/common/pass.h" +#include "backend/optimizer/common/optimizer.h" + +namespace mindspore::opt { +class OnnxPadAdjustPass : public Pass { + public: + OnnxPadAdjustPass() : Pass("onnx_pad_adjust") {} + ~OnnxPadAdjustPass() override = default; + + bool Run(const FuncGraphPtr &func_graph) override; + + private: + ParameterPtr CreateNewParameter(const FuncGraphPtr &func_graph, const std::vector &data); + CNodePtr NewReshapeOpNode(const FuncGraphPtr &func_graph, const AnfNodePtr input_node, const std::vector &shape); + CNodePtr NewTransposeOpNode(const FuncGraphPtr &func_graph, const AnfNodePtr input_node, std::vector perm); +}; +} // namespace mindspore::opt +#endif // MINDSPORE_LITE_TOOLS_OPTIMIZER_GRAPH_ONNX_PAD_ADJUST_PASS_H_