From 7089d82c3308f010f535cc2e564e2106c74e1863 Mon Sep 17 00:00:00 2001 From: wangzhengjun Date: Wed, 26 May 2021 15:20:31 +0800 Subject: [PATCH] add OptimizeAfterStage1 --- ge/graph/manager/graph_manager.cc | 5 +- ge/graph/optimize/graph_optimize.cc | 44 +++- ge/graph/optimize/graph_optimize.h | 3 + tests/ut/ge/CMakeLists.txt | 1 + .../ge/graph/optimize/graph_optimize_unittest.cc | 239 +++++++++++++++++++++ 5 files changed, 288 insertions(+), 4 deletions(-) create mode 100644 tests/ut/ge/graph/optimize/graph_optimize_unittest.cc diff --git a/ge/graph/manager/graph_manager.cc b/ge/graph/manager/graph_manager.cc index f9d24ac4..273d2195 100755 --- a/ge/graph/manager/graph_manager.cc +++ b/ge/graph/manager/graph_manager.cc @@ -886,6 +886,7 @@ Status GraphManager::PreRunOptimizeOriginalGraph(const GraphNodePtr &graph_node, GM_RUN_AND_DUMP_PERF("OptimizeSwitchOp", stages.preparer.SwitchOpOptimize, compute_graph); } GM_RUN_AND_DUMP_PERF("Optimize1", OptimizeStage1, compute_graph); + GM_RUN_AND_DUMP_PERF("OptimizeAfterStage1", stages.optimizer.OptimizeAfterStage1, compute_graph); GM_RUN_AND_DUMP_PERF("InferShape2", compute_graph->InferShapeInNeed); PassManager graph_pass; @@ -3118,7 +3119,7 @@ void GraphManager::PreRunThread(GraphManager *graph_manager) { GraphNodePtr graph_node = nullptr; Status ret = graph_manager->GetGraphNode(args.graph_id, graph_node); if (ret != SUCCESS) { - ReturnError(graph_manager, args.callback, GE_GRAPH_ALREADY_RUNNING, + ReturnError(graph_manager, args.callback, GE_GRAPH_GRAPH_NODE_NULL, "[RunGraph] graph not exist, graph_id=" + std::to_string(args.graph_id)); return; } @@ -3143,7 +3144,7 @@ void GraphManager::PreRunThread(GraphManager *graph_manager) { graph_node->Lock(); if (graph_node->GetRunFlag()) { - ReturnError(graph_manager, args.callback, GE_GRAPH_GRAPH_NODE_NULL, + ReturnError(graph_manager, args.callback, GE_GRAPH_ALREADY_RUNNING, "[RunGraph] graph already running, graph id=" + std::to_string(args.graph_id)); graph_node->Unlock(); return; diff --git a/ge/graph/optimize/graph_optimize.cc b/ge/graph/optimize/graph_optimize.cc index 1dc349a6..10ce3df3 100644 --- a/ge/graph/optimize/graph_optimize.cc +++ b/ge/graph/optimize/graph_optimize.cc @@ -155,7 +155,7 @@ Status GraphOptimize::OptimizeOriginalGraph(ComputeGraphPtr &compute_graph) { } auto graph_optimizer = instance_ptr->OpsKernelManagerObj().GetAllGraphOptimizerObjsByPriority(); - GELOGI("optimize by opskernel in original graph optimize phase. num of graph_optimizer is %lu.", + GELOGI("optimize by opskernel in original graph optimize phase. num of graph_optimizer is %zu.", graph_optimizer.size()); string exclude_core_Type = (core_type_ == kVectorCore) ? kAicoreEngine : kVectorEngine; GELOGD("[OptimizeOriginalGraph]: engine type will exclude: %s", exclude_core_Type.c_str()); @@ -194,7 +194,7 @@ Status GraphOptimize::OptimizeOriginalGraphJudgeInsert(ComputeGraphPtr &compute_ } auto graph_optimizer = instance_ptr->OpsKernelManagerObj().GetAllGraphOptimizerObjsByPriority(); - GELOGI("optimize by opskernel in original graph optimize phase. num of graph_optimizer is %lu.", + GELOGI("optimize by opskernel in judging insert phase. num of graph_optimizer is %zu.", graph_optimizer.size()); string exclude_core_Type = (core_type_ == kVectorCore) ? kAicoreEngine : kVectorEngine; if (graph_optimizer.size() != 0) { @@ -294,6 +294,46 @@ Status GraphOptimize::OptimizeGraphBeforeBuildForRts(ComputeGraphPtr &compute_gr return ret; } +Status GraphOptimize::OptimizeAfterStage1(ComputeGraphPtr &compute_graph) { + GE_CHECK_NOTNULL(compute_graph); + GELOGD("OptimizeAfterStage1 in"); + if (GetContext().GetHostExecFlag()) { + // graph exec on host, no need OptimizeAfterStage1 + return SUCCESS; + } + + Status ret = SUCCESS; + std::shared_ptr instance_ptr = ge::GELib::GetInstance(); + if (instance_ptr == nullptr || !instance_ptr->InitFlag()) { + REPORT_INNER_ERROR("E19999", "Gelib not init before, check invalid"); + GELOGE(GE_CLI_GE_NOT_INITIALIZED, "OptimizeAfterStage1 failed."); + return GE_CLI_GE_NOT_INITIALIZED; + } + + auto graph_optimizer = instance_ptr->OpsKernelManagerObj().GetAllGraphOptimizerObjsByPriority(); + GELOGI("Optimize by ops kernel in after stage1 phase, num of graph_optimizer is %zu.", graph_optimizer.size()); + string exclude_core_type = (core_type_ == kVectorCore) ? kAicoreEngine : kVectorEngine; + if (graph_optimizer.size() != 0) { + for (auto iter = graph_optimizer.begin(); iter != graph_optimizer.end(); ++iter) { + if (iter->first == exclude_core_type) { + GELOGI("[OptimizeAfterStage1]: engine type will exclude:%s.", exclude_core_type.c_str()); + continue; + } +#ifndef ONLY_COMPILE_OPEN_SRC + GELOGI("Begin to optimize graph after stage1 by engine %s.", iter->first.c_str()); + ret = (iter->second)->OptimizeAfterStage1(*compute_graph); +#endif + if (ret != SUCCESS) { + REPORT_INNER_ERROR("E19999", "Call OptimizeAfterStage1 failed, ret:%d, engine_name:%s, " + "graph_name:%s.", ret, iter->first.c_str(), compute_graph->GetName().c_str()); + GELOGE(ret, "[OptimizeAfterStage1]: graph optimize failed, ret:%d.", ret); + return ret; + } + } + } + return ret; +} + Status GraphOptimize::SetOptions(const ge::GraphManagerOptions &options) { if (options.framework_type >= static_cast(domi::FrameworkType::FRAMEWORK_RESERVED)) { REPORT_INNER_ERROR("E19999", "Param framework_type:%d in option check invalid", diff --git a/ge/graph/optimize/graph_optimize.h b/ge/graph/optimize/graph_optimize.h index 3a1960f7..702b7e33 100755 --- a/ge/graph/optimize/graph_optimize.h +++ b/ge/graph/optimize/graph_optimize.h @@ -58,6 +58,9 @@ class GraphOptimize { // for rts optimize before build to add attr and insert memcpy op Status OptimizeGraphBeforeBuildForRts(ComputeGraphPtr &compute_graph); + // optimize whole graph, using after stage1 + Status OptimizeAfterStage1(ComputeGraphPtr &graph); + // set options Status SetOptions(const GraphManagerOptions &options); diff --git a/tests/ut/ge/CMakeLists.txt b/tests/ut/ge/CMakeLists.txt index 40a94dd2..ef1cc191 100755 --- a/tests/ut/ge/CMakeLists.txt +++ b/tests/ut/ge/CMakeLists.txt @@ -803,6 +803,7 @@ set(MULTI_PARTS_TEST_FILES "graph/partition/dynamic_shape_partition_unittest.cc" "graph/manager/graph_manager_unittest.cc" "graph/optimize/mem_rw_conflict_optimize_unittest.cc" + "graph/optimize/graph_optimize_unittest.cc" "session/omg_omg_unittest.cc" "session/ge_api_unittest.cc" "session/inner_session_unittest.cc" diff --git a/tests/ut/ge/graph/optimize/graph_optimize_unittest.cc b/tests/ut/ge/graph/optimize/graph_optimize_unittest.cc new file mode 100644 index 00000000..5468ec97 --- /dev/null +++ b/tests/ut/ge/graph/optimize/graph_optimize_unittest.cc @@ -0,0 +1,239 @@ +/** + * 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 +#include +#include +#define protected public +#define private public +#include "graph/optimize/graph_optimize.h" +#include "init/gelib.h" +#include "ge/ge_api.h" +#undef private +#undef protected + +using namespace std; +using namespace testing; +using namespace ge; + +namespace { +const char *const kVectorCore = "VectorCore"; +const char *const kAicoreEngine = "AIcoreEngine"; +string CreateEngineConfigJson() { + GELOGI("Begin to create engine config json file."); + string base_path = PluginManager::GetPath(); + GELOGI("Base path is %s.", base_path.c_str()); + string dir_path = base_path.substr(0, base_path.rfind('/') + 1) + "plugin/nnengine/ge_config"; + string cmd = "mkdir -p " + dir_path; + system(cmd.c_str()); + string file_path = dir_path + "/engine_conf.json"; + GELOGI("Begin to write into the config file: %s.", file_path.c_str()); + ofstream ofs(file_path, ios::out); + EXPECT_EQ(!ofs, false); + ofs << "{\n" + " \"schedule_units\" : [ {\n" + " \"id\" : \"TS_1\",\n" + " \"name\" : \"1980_hwts\",\n" + " \"ex_attrs\" : \"\",\n" + " \"cal_engines\" : [\n" + " {\"id\" : \"DNN_VM_GE_LOCAL\", \"name\" : \"GE_LOCAL\", \"independent\" : false, \"attch\" : true, \"skip_assign_stream\" : true },\n" + " {\"id\" : \"AIcoreEngine\", \"name\" : \"AICORE\", \"independent\" : false, \"attch\" : false, \"skip_assign_stream\" : false}\n" + " ]\n" + " } ]\n" + "}"; + ofs.close(); + GELOGI("Json config file %s has been written.", file_path.c_str()); + return file_path; +} + +void DeleteFile(const string &file_name) { + auto ret = remove(file_name.c_str()); + if (ret == 0) { + GELOGI("Delete file successfully, file:%s.", file_name.c_str()); + } +} +} +class UtestGraphOptimizeTest : public testing::Test { + protected: + void SetUp() { + config_file_ = CreateEngineConfigJson(); + } + + void TearDown() { + DeleteFile(config_file_); + } + + private: + string config_file_; +}; + +class TestGraphOptimizerSuccess : public GraphOptimizer { + public: + ~TestGraphOptimizerSuccess() override { Finalize(); } + Status Initialize(const map &options) override { return SUCCESS; } + Status Finalize() override { return SUCCESS; } + Status OptimizeGraphPrepare(ComputeGraph& graph) override { return SUCCESS; } + Status OptimizeGraphBeforeBuild(ComputeGraph& graph) override { return SUCCESS; } + Status OptimizeOriginalGraph(ComputeGraph &graph) override { return SUCCESS; } + Status OptimizeOriginalGraphJudgeInsert(ComputeGraph &graph) override { return SUCCESS; } + Status OptimizeFusedGraph(ComputeGraph &graph) override { return SUCCESS; } + Status OptimizeWholeGraph(ComputeGraph &graph) override { return SUCCESS; } + Status GetAttributes(GraphOptimizerAttribute &attrs) const override { + attrs.engineName = "AIcoreEngine"; + attrs.scope = OPTIMIZER_SCOPE::ENGINE; + return SUCCESS; + } + Status OptimizeStreamGraph(ComputeGraph &graph, const RunContext &context) override { return SUCCESS; } + Status OptimizeFusedGraphAfterGraphSlice(ComputeGraph &graph) override { return SUCCESS; } + Status OptimizeAfterStage1(ComputeGraph &graph) override { return SUCCESS; } +}; + +class TestGraphOptimizerFail : public GraphOptimizer { + public: + ~TestGraphOptimizerFail() override { Finalize(); } + Status Initialize(const map &options) override { return SUCCESS; } + Status Finalize() override { return SUCCESS; } + Status OptimizeGraphPrepare(ComputeGraph& graph) override { return FAILED; } + Status OptimizeGraphBeforeBuild(ComputeGraph& graph) override { return FAILED; } + Status OptimizeOriginalGraph(ComputeGraph &graph) override { return FAILED; } + Status OptimizeOriginalGraphJudgeInsert(ComputeGraph &graph) override { return FAILED; } + Status OptimizeFusedGraph(ComputeGraph &graph) override { return FAILED; } + Status OptimizeWholeGraph(ComputeGraph &graph) override { return FAILED; } + Status GetAttributes(GraphOptimizerAttribute &attrs) const override { + attrs.engineName = "AIcoreEngine"; + attrs.scope = OPTIMIZER_SCOPE::ENGINE; + return SUCCESS; + } + Status OptimizeStreamGraph(ComputeGraph &graph, const RunContext &context) override { return FAILED; } + Status OptimizeFusedGraphAfterGraphSlice(ComputeGraph &graph) override { return FAILED; } + Status OptimizeAfterStage1(ComputeGraph &graph) override { return FAILED; } +}; + +TEST_F(UtestGraphOptimizeTest, test_OptimizeAfterStage1_succ) { + map options; + Status ret = ge::GELib::Initialize(options); + EXPECT_EQ(ret, SUCCESS); + + shared_ptr instance_ptr = ge::GELib::GetInstance(); + EXPECT_NE(instance_ptr, nullptr); + GraphOptimizerPtr graph_opt = MakeShared(); + instance_ptr->opsManager_.graph_optimizers_by_priority_.push_back(make_pair("AIcoreEngine", graph_opt)); + + ComputeGraphPtr compute_graph = MakeShared("test_graph"); + GraphOptimize base_optimize; + ret = base_optimize.OptimizeAfterStage1(compute_graph); + EXPECT_EQ(ret, SUCCESS); + + base_optimize.core_type_ = kVectorCore; + ret = base_optimize.OptimizeAfterStage1(compute_graph); + EXPECT_EQ(ret, SUCCESS); + + ret = instance_ptr->Finalize(); + EXPECT_EQ(ret, SUCCESS); +} + +TEST_F(UtestGraphOptimizeTest, test_OptimizeAfterStage1_fail) { + ComputeGraphPtr compute_graph = nullptr; + GraphOptimize base_optimize; + + // 1. Input graph is nullptr. + Status ret = base_optimize.OptimizeAfterStage1(compute_graph); + EXPECT_EQ(ret, PARAM_INVALID); + + // 2. GELib is not initialized. + compute_graph = MakeShared("test_graph"); + ret = base_optimize.OptimizeAfterStage1(compute_graph); + EXPECT_EQ(ret, GE_CLI_GE_NOT_INITIALIZED); + + // 3. The optimizer registered with the engine returned a failure. + map options; + ret = ge::GELib::Initialize(options); + EXPECT_EQ(ret, SUCCESS); + + shared_ptr instance_ptr = ge::GELib::GetInstance(); + EXPECT_NE(instance_ptr, nullptr); + GraphOptimizerPtr graph_opt = MakeShared(); + instance_ptr->opsManager_.graph_optimizers_by_priority_.push_back(make_pair("AIcoreEngine", graph_opt)); + ret = base_optimize.OptimizeAfterStage1(compute_graph); + EXPECT_EQ(ret, FAILED); + + ret = instance_ptr->Finalize(); + EXPECT_EQ(ret, SUCCESS); +} + +TEST_F(UtestGraphOptimizeTest, test_optimizers_succ) { + map options; + Status ret = ge::GELib::Initialize(options); + EXPECT_EQ(ret, SUCCESS); + + shared_ptr instance_ptr = ge::GELib::GetInstance(); + EXPECT_NE(instance_ptr, nullptr); + GraphOptimizerPtr graph_opt = MakeShared(); + instance_ptr->opsManager_.graph_optimizers_by_priority_.push_back(make_pair("AIcoreEngine", graph_opt)); + + ComputeGraphPtr compute_graph = MakeShared("test_graph"); + GraphOptimize base_optimize; + + ret = base_optimize.OptimizeOriginalGraph(compute_graph); + EXPECT_EQ(ret, SUCCESS); + + ret = base_optimize.OptimizeOriginalGraphJudgeInsert(compute_graph); + EXPECT_EQ(ret, SUCCESS); + + ret = base_optimize.OptimizeOriginalGraphForQuantize(compute_graph); + EXPECT_EQ(ret, SUCCESS); + + ret = base_optimize.OptimizeGraphBeforeBuildForRts(compute_graph); + EXPECT_EQ(ret, SUCCESS); + + ret = base_optimize.OptimizeWholeGraph(compute_graph); + EXPECT_EQ(ret, SUCCESS); + + ret = instance_ptr->Finalize(); + EXPECT_EQ(ret, SUCCESS); +} + +TEST_F(UtestGraphOptimizeTest, test_optimizers_fail) { + map options; + Status ret = ge::GELib::Initialize(options); + EXPECT_EQ(ret, SUCCESS); + + shared_ptr instance_ptr = ge::GELib::GetInstance(); + EXPECT_NE(instance_ptr, nullptr); + GraphOptimizerPtr graph_opt = MakeShared(); + instance_ptr->opsManager_.graph_optimizers_by_priority_.push_back(make_pair("AIcoreEngine", graph_opt)); + + ComputeGraphPtr compute_graph = MakeShared("test_graph"); + GraphOptimize base_optimize; + + ret = base_optimize.OptimizeOriginalGraph(compute_graph); + EXPECT_EQ(ret, FAILED); + + ret = base_optimize.OptimizeOriginalGraphJudgeInsert(compute_graph); + EXPECT_EQ(ret, FAILED); + + ret = base_optimize.OptimizeOriginalGraphForQuantize(compute_graph); + EXPECT_EQ(ret, FAILED); + + ret = base_optimize.OptimizeGraphBeforeBuildForRts(compute_graph); + EXPECT_EQ(ret, FAILED); + + ret = base_optimize.OptimizeWholeGraph(compute_graph); + EXPECT_EQ(ret, FAILED); + + ret = instance_ptr->Finalize(); + EXPECT_EQ(ret, SUCCESS); +}