From: @lichun30 Reviewed-by: @xchu42,@ji_chen Signed-off-by: @ji_chentags/v1.3.0
| @@ -48,50 +48,23 @@ namespace ge { | |||||
| using Cluster = DynamicShapePartitioner::Cluster; | using Cluster = DynamicShapePartitioner::Cluster; | ||||
| using ClusterPtr = std::shared_ptr<Cluster>; | using ClusterPtr = std::shared_ptr<Cluster>; | ||||
| static bool IsInExperimentalMode(const ComputeGraphPtr &root_graph) { | |||||
| static bool IsSingleOpScene(const ComputeGraphPtr &root_graph) { | |||||
| for (const auto &node : root_graph->GetAllNodes()) { | for (const auto &node : root_graph->GetAllNodes()) { | ||||
| GE_CHECK_NOTNULL(node->GetOpDesc()); | GE_CHECK_NOTNULL(node->GetOpDesc()); | ||||
| // not do partition in single op scene. | // not do partition in single op scene. | ||||
| bool is_singleop = false; | bool is_singleop = false; | ||||
| (void)AttrUtils::GetBool(node->GetOpDesc(), ATTR_SINGLE_OP_SCENE, is_singleop); | (void)AttrUtils::GetBool(node->GetOpDesc(), ATTR_SINGLE_OP_SCENE, is_singleop); | ||||
| if (is_singleop) { | if (is_singleop) { | ||||
| return false; | |||||
| } | |||||
| for (const auto &input_desc : node->GetOpDesc()->GetAllInputsDesc()) { | |||||
| auto type = input_desc.GetDataType(); | |||||
| if (type == DT_STRING || type == DT_RESOURCE || type == DT_STRING_REF) { | |||||
| if (std::getenv("EXPERIMENTAL_DYNAMIC_PARTITION") == nullptr) { | |||||
| return false; | |||||
| } else { | |||||
| GEEVENT("In dynamic shape scene, model contains data type:" | |||||
| "DT_STRING/DT_RESOURCE/DT_STRING_REF may not be supported well " | |||||
| "temporarily, please retry with \"unset EXPERIMENTAL_DYNAMIC_PARTITION\"."); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| for (const auto &output_desc : node->GetOpDesc()->GetAllOutputsDesc()) { | |||||
| auto type = output_desc.GetDataType(); | |||||
| if (type == DT_STRING || type == DT_RESOURCE || type == DT_STRING_REF) { | |||||
| if (std::getenv("EXPERIMENTAL_DYNAMIC_PARTITION") == nullptr) { | |||||
| return false; | |||||
| } else { | |||||
| GEEVENT("In dynamic shape scene, model contains data type:" | |||||
| "DT_STRING/DT_RESOURCE/DT_STRING_REF may not be supported well " | |||||
| "temporarily, please retry with \"unset EXPERIMENTAL_DYNAMIC_PARTITION\"."); | |||||
| break; | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | } | ||||
| } | } | ||||
| return true; | |||||
| return false; | |||||
| } | } | ||||
| Status DynamicShapePartitioner::Partition() { | Status DynamicShapePartitioner::Partition() { | ||||
| REQUIRE_NOT_NULL(root_graph_, "Graph is nullptr."); | REQUIRE_NOT_NULL(root_graph_, "Graph is nullptr."); | ||||
| if (!IsInExperimentalMode(root_graph_)) { | |||||
| GELOGD("Skip dynamic shape partition as not in experimental mode."); | |||||
| if (IsSingleOpScene(root_graph_)) { | |||||
| GELOGD("Skip dynamic shape partition as in single op scene."); | |||||
| REQUIRE(AttrUtils::SetBool(*root_graph_, ATTR_NAME_DYNAMIC_SHAPE_PARTITIONED, false), | REQUIRE(AttrUtils::SetBool(*root_graph_, ATTR_NAME_DYNAMIC_SHAPE_PARTITIONED, false), | ||||
| "Failed set dynamic shape partitioned flag on root graph."); | "Failed set dynamic shape partitioned flag on root graph."); | ||||
| return SUCCESS; | return SUCCESS; | ||||
| @@ -765,6 +765,7 @@ set(MULTI_PARTS_TEST_FILES | |||||
| "graph/preprocess/graph_preprocess_unittest.cc" | "graph/preprocess/graph_preprocess_unittest.cc" | ||||
| "graph/manager/hcom_util_unittest.cc" | "graph/manager/hcom_util_unittest.cc" | ||||
| "graph/manager/graph_caching_allocator_unittest.cc" | "graph/manager/graph_caching_allocator_unittest.cc" | ||||
| "graph/partition/dynamic_shape_partition_unittest.cc" | |||||
| "session/omg_omg_unittest.cc" | "session/omg_omg_unittest.cc" | ||||
| ) | ) | ||||
| @@ -0,0 +1,97 @@ | |||||
| /** | |||||
| * Copyright 2019-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 <gtest/gtest.h> | |||||
| #include "graph/partition/dynamic_shape_partition.h" | |||||
| #include "compute_graph.h" | |||||
| #include "inc/framework/common/types.h" | |||||
| #include "utils/graph_utils.h" | |||||
| #include "graph/debug/ge_attr_define.h" | |||||
| #define private public | |||||
| #define protected public | |||||
| namespace ge { | |||||
| namespace { | |||||
| GeTensorDescPtr CreateTensorDesc(std::initializer_list<int64_t> shape, Format format = FORMAT_NCHW, | |||||
| DataType data_type = DT_FLOAT) { | |||||
| GeShape ge_shape{vector<int64_t>(shape)}; | |||||
| GeTensorDescPtr tensor_desc = std::make_shared<GeTensorDesc>(); | |||||
| tensor_desc->SetShape(ge_shape); | |||||
| tensor_desc->SetFormat(format); | |||||
| tensor_desc->SetDataType(data_type); | |||||
| return tensor_desc; | |||||
| } | |||||
| class NodeBuilder { | |||||
| public: | |||||
| NodeBuilder(const std::string &name, const std::string &type) { op_desc_ = std::make_shared<OpDesc>(name, type); } | |||||
| NodeBuilder &AddInputDesc(std::initializer_list<int64_t> shape = {1, 1, 224, 224}, Format format = FORMAT_NCHW, | |||||
| DataType data_type = DT_FLOAT) { | |||||
| op_desc_->AddInputDesc(CreateTensorDesc(shape, format, data_type)->Clone()); | |||||
| return *this; | |||||
| } | |||||
| NodeBuilder &AddOutputDesc(std::initializer_list<int64_t> shape = {1, 1, 224, 224}, Format format = FORMAT_NCHW, | |||||
| DataType data_type = DT_FLOAT) { | |||||
| op_desc_->AddOutputDesc(CreateTensorDesc(shape, format, data_type)->Clone()); | |||||
| return *this; | |||||
| } | |||||
| NodeBuilder &AddOutputDesc(GeTensorDescPtr tensor_desc) { | |||||
| op_desc_->AddOutputDesc(tensor_desc->Clone()); | |||||
| return *this; | |||||
| } | |||||
| NodePtr Build(const ComputeGraphPtr &graph) { | |||||
| NodePtr node = graph->AddNode(op_desc_); | |||||
| return node; | |||||
| } | |||||
| private: | |||||
| OpDescPtr op_desc_; | |||||
| }; | |||||
| } // namespace | |||||
| class UtestDynamicShapePartition : public testing::Test { | |||||
| protected: | |||||
| void SetUp() {} | |||||
| void TearDown() {} | |||||
| }; | |||||
| TEST_F(UtestDynamicShapePartition, single_op_scene_success) { | |||||
| ComputeGraphPtr graph = std::make_shared<ComputeGraph>("default"); | |||||
| NodePtr node1 = | |||||
| NodeBuilder("node1", CONSTANTOP).AddInputDesc({1, 1, 224, 224}).AddOutputDesc({1, 1, 224, 224}).Build(graph); | |||||
| NodePtr add_n_node = | |||||
| NodeBuilder("add_n_node", ADDN).AddInputDesc({1, 1, 224, 224}).AddOutputDesc({1, 1, 224, 224}).Build(graph); | |||||
| NodePtr node2 = | |||||
| NodeBuilder("node2", RELU).AddInputDesc({1, 1, 224, 224}).AddOutputDesc({1, 1, 224, 224}).Build(graph); | |||||
| GraphUtils::AddEdge(node1->GetOutDataAnchor(0), add_n_node->GetInDataAnchor(0)); | |||||
| GraphUtils::AddEdge(add_n_node->GetOutDataAnchor(0), node2->GetInDataAnchor(0)); | |||||
| (void)AttrUtils::SetBool(add_n_node->GetOpDesc(), ATTR_SINGLE_OP_SCENE, true); | |||||
| DynamicShapePartitioner partitioner(graph); | |||||
| EXPECT_EQ(partitioner.Partition(), SUCCESS); | |||||
| } | |||||
| } // namespace ge | |||||