From 1f1a07e64574aaefe42f12a4b29a5a391a41edb5 Mon Sep 17 00:00:00 2001 From: chenfei Date: Sun, 26 Jul 2020 12:37:40 +0800 Subject: [PATCH] don't insert assign from condition to true branch of while --- .../common/common_backend_optimization.cc | 4 +- .../ccsrc/backend/optimizer/common/helper.cc | 22 +++++ .../ccsrc/backend/optimizer/common/helper.h | 3 + .../convert_const_input_to_tensor_input.cc | 29 ++----- .../pass/convert_const_scalar_to_tensor.cc | 87 +++++++++++++++++++ .../pass/convert_const_scalar_to_tensor.h | 35 ++++++++ .../pass/convert_tuple_output_to_maketuple.cc | 6 +- .../ccsrc/backend/session/ascend_session.cc | 10 +-- .../ccsrc/backend/session/kernel_graph.cc | 1 - ...onvert_const_input_to_tensor_input_test.cc | 19 ++-- 10 files changed, 172 insertions(+), 44 deletions(-) create mode 100644 mindspore/ccsrc/backend/optimizer/pass/convert_const_scalar_to_tensor.cc create mode 100644 mindspore/ccsrc/backend/optimizer/pass/convert_const_scalar_to_tensor.h diff --git a/mindspore/ccsrc/backend/optimizer/common/common_backend_optimization.cc b/mindspore/ccsrc/backend/optimizer/common/common_backend_optimization.cc index 6b01c24faa..3513c216e5 100644 --- a/mindspore/ccsrc/backend/optimizer/common/common_backend_optimization.cc +++ b/mindspore/ccsrc/backend/optimizer/common/common_backend_optimization.cc @@ -22,6 +22,7 @@ #include "backend/optimizer/pass/convert_const_input_to_tensor_input.h" #include "backend/optimizer/pass/convert_tuple_input_to_dynamic_input.h" #include "backend/optimizer/pass/const_to_attr_strided_slice_grad.h" +#include "backend/optimizer/pass/convert_const_scalar_to_tensor.h" #include "utils/context/ms_context.h" #include "debug/anf_ir_dump.h" @@ -46,8 +47,9 @@ void BackendCommonOptimization(const std::shared_ptr &kern auto common_pm = std::make_shared("common_pm"); common_pm->AddPass(std::make_shared()); common_pm->AddPass(std::make_shared()); - common_pm->AddPass(std::make_shared()); common_pm->AddPass(std::make_shared()); + common_pm->AddPass(std::make_shared()); + common_pm->AddPass(std::make_shared()); common_pm->AddPass(std::make_shared()); optimizer->AddPassManager(common_pm); (void)optimizer->Optimize(kernel_graph); diff --git a/mindspore/ccsrc/backend/optimizer/common/helper.cc b/mindspore/ccsrc/backend/optimizer/common/helper.cc index 266130c6b1..577cec3a59 100644 --- a/mindspore/ccsrc/backend/optimizer/common/helper.cc +++ b/mindspore/ccsrc/backend/optimizer/common/helper.cc @@ -781,5 +781,27 @@ bool CheckSupportDataType(const AnfNodePtr &node, const std::set &suppor MS_LOG(DEBUG) << "Not supported data type. Node:" << node->DebugString(); return false; } + +ValueNodePtr MakeValueNode(const ValueNodePtr &value_node) { + MS_EXCEPTION_IF_NULL(value_node); + ValueNodePtr new_value_node = std::make_shared(value_node->value()); + new_value_node->set_abstract(value_node->abstract()); + // create kernel_info fo new value node + auto kernel_info = std::make_shared(); + new_value_node->set_kernel_info(kernel_info); + // create kernel_build_info for new value node + auto kernel_build_info_builder = std::make_shared(); + // set the format of value_node to DEFAULT_FORMAT + kernel_build_info_builder->SetOutputsFormat(std::vector{kOpFormat_DEFAULT}); + // set value node initial device data type = infer data type + std::vector types; + for (size_t index = 0; index < AnfAlgo::GetOutputTensorNum(value_node); ++index) { + types.push_back(kTypeUnknown); + } + kernel_build_info_builder->SetOutputsDeviceType(types); + AnfAlgo::SetSelectKernelBuildInfo(kernel_build_info_builder->Build(), new_value_node.get()); + return new_value_node; +} + } // namespace opt } // namespace mindspore diff --git a/mindspore/ccsrc/backend/optimizer/common/helper.h b/mindspore/ccsrc/backend/optimizer/common/helper.h index 92c8a73832..1e5f3ef931 100644 --- a/mindspore/ccsrc/backend/optimizer/common/helper.h +++ b/mindspore/ccsrc/backend/optimizer/common/helper.h @@ -194,6 +194,9 @@ bool GetBoolAttr(const AnfNodePtr &node, const std::string &attr_name); // Check node's data type is in supported data type set bool CheckSupportDataType(const AnfNodePtr &node, const std::set &supported_data_type_set); + +// Create a new value node of func graph,not kernel graph +ValueNodePtr MakeValueNode(const ValueNodePtr &value_node); } // namespace opt } // namespace mindspore #endif // MINDSPORE_CCSRC_BACKEND_OPTIMIZER_COMMON_HELPER_H_ diff --git a/mindspore/ccsrc/backend/optimizer/pass/convert_const_input_to_tensor_input.cc b/mindspore/ccsrc/backend/optimizer/pass/convert_const_input_to_tensor_input.cc index cb75d3689e..d15205f790 100644 --- a/mindspore/ccsrc/backend/optimizer/pass/convert_const_input_to_tensor_input.cc +++ b/mindspore/ccsrc/backend/optimizer/pass/convert_const_input_to_tensor_input.cc @@ -29,28 +29,8 @@ namespace mindspore { namespace opt { namespace { -ValueNodePtr MakeValueNode(const ValueNodePtr &value_node) { - MS_EXCEPTION_IF_NULL(value_node); - ValueNodePtr new_value_node = std::make_shared(value_node->value()); - new_value_node->set_abstract(value_node->abstract()); - // create kernel_info fo new value node - auto kernel_info = std::make_shared(); - new_value_node->set_kernel_info(kernel_info); - // create kernel_build_info for new value node - auto kernel_build_info_builder = std::make_shared(); - // set the format of value_node to DEFAULT_FORMAT - kernel_build_info_builder->SetOutputsFormat(std::vector{kOpFormat_DEFAULT}); - // set value node initial device data type = infer data type - std::vector types; - for (size_t index = 0; index < AnfAlgo::GetOutputTensorNum(value_node); ++index) { - types.push_back(kTypeUnknown); - } - kernel_build_info_builder->SetOutputsDeviceType(types); - AnfAlgo::SetSelectKernelBuildInfo(kernel_build_info_builder->Build(), new_value_node.get()); - return new_value_node; -} -AnfNodePtr CreateTensorInput(const KernelGraphPtr &kernel_graph, const AnfNodePtr &input_node) { +AnfNodePtr CreateTensorInput(const AnfNodePtr &node, const KernelGraphPtr &kernel_graph, const AnfNodePtr &input_node) { MS_EXCEPTION_IF_NULL(input_node); auto value_node = input_node->cast(); MS_EXCEPTION_IF_NULL(value_node); @@ -60,6 +40,9 @@ AnfNodePtr CreateTensorInput(const KernelGraphPtr &kernel_graph, const AnfNodePt if (value->isa()) { tensor_ptr = ScalarToTensor(value->cast()); } else if (value->isa()) { + if (!AnfAlgo::IsRealCNodeKernel(node)) { + return nullptr; + } tensor_ptr = CreateTupleTensor(value->cast()); } else { MS_LOG(EXCEPTION) << "The value should be a scalar or value tuple"; @@ -93,7 +76,7 @@ AnfNodePtr ConstInputToTensorInput(const FuncGraphPtr &func_graph, const CNodePt for (size_t i = 0; i < inputs.size() - 1; ++i) { auto input_node = inputs[i + 1]; if (IsValueNode(input_node) || IsValueNode(input_node)) { - auto tensor_input = CreateTensorInput(kernel_graph, input_node); + auto tensor_input = CreateTensorInput(cnode, kernel_graph, input_node); if (tensor_input == nullptr) { new_inputs.push_back(input_node); continue; @@ -139,7 +122,7 @@ AnfNodePtr ProcessGraphKernelOp(const AnfNodePtr &node) { const AnfNodePtr ConvertConstInputToTensorInput::Process(const FuncGraphPtr &func_graph, const AnfNodePtr &node, const EquivPtr &) const { - if (node == nullptr || func_graph == nullptr || AnfAlgo::CheckPrimitiveType(node, prim::kPrimTupleGetItem)) { + if (node == nullptr || func_graph == nullptr || !AnfAlgo::IsRealCNodeKernel(node)) { return nullptr; } if (!node->isa()) { diff --git a/mindspore/ccsrc/backend/optimizer/pass/convert_const_scalar_to_tensor.cc b/mindspore/ccsrc/backend/optimizer/pass/convert_const_scalar_to_tensor.cc new file mode 100644 index 0000000000..a8c2bbdf22 --- /dev/null +++ b/mindspore/ccsrc/backend/optimizer/pass/convert_const_scalar_to_tensor.cc @@ -0,0 +1,87 @@ +/** + * Copyright 2020 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 "backend/optimizer/pass/convert_const_scalar_to_tensor.h" + +#include +#include +#include + +#include "utils/graph_utils.h" +#include "backend/optimizer/common/helper.h" +#include "backend/session/anf_runtime_algorithm.h" +#include "backend/session/kernel_graph.h" +#include "backend/kernel_compiler/common_utils.h" +#include "runtime/device/kernel_info.h" + +namespace mindspore { +namespace opt { +namespace { +AnfNodePtr CreateTensorInput(const KernelGraphPtr &kernel_graph, const AnfNodePtr &input_node) { + MS_EXCEPTION_IF_NULL(input_node); + if (!input_node->isa()) { + return nullptr; + } + auto value_node = input_node->cast(); + MS_EXCEPTION_IF_NULL(value_node); + auto value = value_node->value(); + MS_EXCEPTION_IF_NULL(value); + if (!value->isa()) { + return nullptr; + } + tensor::TensorPtr tensor_ptr = ScalarToTensor(value->cast()); + if (tensor_ptr == nullptr) { + MS_LOG(WARNING) << "Create tensor of" << input_node->DebugString() << "failed"; + return nullptr; + } + auto tensor_input = std::make_shared(tensor_ptr); + MS_EXCEPTION_IF_NULL(tensor_input); + tensor_input->set_abstract(tensor_ptr->ToAbstract()); + if (kernel_graph != nullptr) { + tensor_input = kernel_graph->NewValueNode(tensor_input); + kernel_graph->AddValueNodeToGraph(tensor_input); + } else { + tensor_input = MakeValueNode(tensor_input); + } + tensor_input->set_scope(input_node->scope()); + return tensor_input; +} +} // namespace + +const AnfNodePtr ConvertConstScalarToTensor::Process(const FuncGraphPtr &func_graph, const AnfNodePtr &node, + const EquivPtr &) const { + if (node == nullptr || func_graph == nullptr || AnfAlgo::CheckPrimitiveType(node, prim::kPrimTupleGetItem)) { + return nullptr; + } + if (!node->isa()) { + return nullptr; + } + auto cnode = node->cast(); + bool input_changed = false; + for (size_t i = 0; i < cnode->inputs().size(); ++i) { + auto new_input = CreateTensorInput(func_graph->cast(), cnode->inputs()[i]); + if (new_input != nullptr) { + cnode->set_input(i, new_input); + input_changed = true; + } + } + auto kernel_graph = func_graph->cast(); + if (kernel_graph == nullptr || !input_changed) { + return nullptr; + } + return kernel_graph->NewCNode(cnode); +} +} // namespace opt +} // namespace mindspore diff --git a/mindspore/ccsrc/backend/optimizer/pass/convert_const_scalar_to_tensor.h b/mindspore/ccsrc/backend/optimizer/pass/convert_const_scalar_to_tensor.h new file mode 100644 index 0000000000..520da08b45 --- /dev/null +++ b/mindspore/ccsrc/backend/optimizer/pass/convert_const_scalar_to_tensor.h @@ -0,0 +1,35 @@ +/** + * Copyright 2020 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_CCSRC_BACKEND_OPTIMIZER_PASS_CONVERT_CONST_SCALAR_TO_TENSOR_H_ +#define MINDSPORE_CCSRC_BACKEND_OPTIMIZER_PASS_CONVERT_CONST_SCALAR_TO_TENSOR_H_ +#include + +#include "ir/anf.h" +#include "backend/optimizer/common/optimizer.h" + +namespace mindspore { +namespace opt { +class ConvertConstScalarToTensor : public PatternProcessPass { + public: + explicit ConvertConstScalarToTensor(bool multigraph = true) + : PatternProcessPass("convert_const_scalar_to_tensor", multigraph) {} + ~ConvertConstScalarToTensor() override = default; + const AnfNodePtr Process(const FuncGraphPtr &, const AnfNodePtr &, const EquivPtr &) const override; +}; +} // namespace opt +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_BACKEND_OPTIMIZER_PASS_CONVERT_CONST_SCALAR_TO_TENSOR_H_ diff --git a/mindspore/ccsrc/backend/optimizer/pass/convert_tuple_output_to_maketuple.cc b/mindspore/ccsrc/backend/optimizer/pass/convert_tuple_output_to_maketuple.cc index efe8d5320f..8bdc234e81 100644 --- a/mindspore/ccsrc/backend/optimizer/pass/convert_tuple_output_to_maketuple.cc +++ b/mindspore/ccsrc/backend/optimizer/pass/convert_tuple_output_to_maketuple.cc @@ -75,8 +75,10 @@ const AnfNodePtr ConvertTupleOutputToMaketuple::Process(const FuncGraphPtr &func } } auto kernel_graph = func_graph->cast(); - MS_EXCEPTION_IF_NULL(kernel_graph); - return cnode_input_changed ? kernel_graph->NewCNode(cnode) : nullptr; + if (kernel_graph == nullptr || !cnode_input_changed) { + return nullptr; + } + return kernel_graph->NewCNode(cnode); } } // namespace opt } // namespace mindspore diff --git a/mindspore/ccsrc/backend/session/ascend_session.cc b/mindspore/ccsrc/backend/session/ascend_session.cc index e220f20f12..e066b62b1b 100644 --- a/mindspore/ccsrc/backend/session/ascend_session.cc +++ b/mindspore/ccsrc/backend/session/ascend_session.cc @@ -881,22 +881,22 @@ void AscendSession::CreateMultiBranchOutput(NotNull graph, NotNu return; } memo->insert(graph.get()); - graph->UpdateChildGraphOrder(); for (auto &child_graph : graph->child_graph_order()) { CreateMultiBranchOutput(NOT_NULL(child_graph), memo); } - + // If graph has no output, the graph is the true graph of while and will call condition graph, no need insert assign + // from condition to true graph + if (graph->get_output_null()) { + return; + } std::map need_replace_list; auto node_list = GetCNodes(TopoSort(graph->get_return())); for (auto &node : node_list) { if (AnfAlgo::CheckPrimitiveType(node, prim::kPrimCall)) { // create a parameter to store the output of multiple branch and set the parameter as the condition graph's output - // auto multi_output_param = graph->NewParameter(); - auto origin_inputs = graph->inputs(); auto output_param = graph->TransTupleToMakeTuple(graph->NewParameter(node->abstract())); MS_EXCEPTION_IF_NULL(graph->MutableInputs()); - graph->MutableInputs()->operator=(origin_inputs); graph->AddChildGraphResult(output_param); std::vector depend_inputs = { diff --git a/mindspore/ccsrc/backend/session/kernel_graph.cc b/mindspore/ccsrc/backend/session/kernel_graph.cc index d8183c1b2b..528db5b76d 100644 --- a/mindspore/ccsrc/backend/session/kernel_graph.cc +++ b/mindspore/ccsrc/backend/session/kernel_graph.cc @@ -133,7 +133,6 @@ AnfNodePtr KernelGraph::MakeValueNode(const AnfNodePtr &node) { if (value_node == nullptr) { return nullptr; } - ValueNodePtr new_value_node = std::make_shared(value_node->value()); new_value_node->set_abstract(value_node->abstract()); this->SetKernelInfoForNode(new_value_node); diff --git a/tests/ut/cpp/pre_activate/pass/convert_const_input_to_tensor_input_test.cc b/tests/ut/cpp/pre_activate/pass/convert_const_input_to_tensor_input_test.cc index 290fab4ed9..5b303d15a5 100644 --- a/tests/ut/cpp/pre_activate/pass/convert_const_input_to_tensor_input_test.cc +++ b/tests/ut/cpp/pre_activate/pass/convert_const_input_to_tensor_input_test.cc @@ -99,18 +99,13 @@ TEST_F(TestHWConstInputToTensorInput, test_value_tuple_tensor_input) { EXPECT_NE(ret->input(1)->cast(), nullptr); auto cnode = ret->input(1)->cast()->input(1)->cast(); EXPECT_EQ(AnfAlgo::GetCNodeName(cnode), prim::kPrimDropoutGenMask->name()); - std::vector out; - for (size_t i = 1; i <= 4; i++) { - auto input = cnode->input(i); - ASSERT_TRUE(input != nullptr); - EXPECT_TRUE(IsValueNode(input)); - auto tensor = input->cast()->value()->cast(); - ASSERT_TRUE(tensor != nullptr); - int *data = (int *)(tensor->data_c()); - ASSERT_TRUE(data != nullptr); - out.push_back(*data); - } - EXPECT_EQ(out, std::vector({2, 4, 2, 2})); + auto input1 = cnode->input(1); + ASSERT_TRUE(input1 != nullptr); + EXPECT_TRUE(IsValueNode(input1)); + auto tensor = input1->cast()->value()->cast(); + ASSERT_TRUE(tensor != nullptr); + auto data = tensor->data_c(); + EXPECT_EQ(std::vector((int *)data, (int *)data + 4), std::vector({2, 4, 2, 2})); } } // namespace opt } // namespace mindspore