| @@ -142,6 +142,7 @@ set(TRAIN_SRC_LIST | |||
| "graph/passes/atomic_addr_clean_pass.cc" | |||
| "graph/passes/mark_same_addr_pass.cc" | |||
| "graph/passes/mark_graph_unknown_status_pass.cc" | |||
| "graph/passes/dynamic_single_op_reset_shape_pass.cc" | |||
| "graph/passes/mark_agnostic_pass.cc" | |||
| "graph/partition/dynamic_shape_partition.cc" | |||
| "graph/partition/stage_partition.cc" | |||
| @@ -433,6 +434,7 @@ set(INFER_SRC_LIST | |||
| "graph/passes/atomic_addr_clean_pass.cc" | |||
| "graph/passes/mark_same_addr_pass.cc" | |||
| "graph/passes/mark_graph_unknown_status_pass.cc" | |||
| "graph/passes/dynamic_single_op_reset_shape_pass.cc" | |||
| "graph/passes/mark_agnostic_pass.cc" | |||
| "graph/common/omg_util.cc" | |||
| "graph/common/bcast.cc" | |||
| @@ -109,6 +109,7 @@ OMG_HOST_SRC_FILES := \ | |||
| graph/passes/atomic_addr_clean_pass.cc \ | |||
| graph/passes/mark_same_addr_pass.cc \ | |||
| graph/passes/mark_graph_unknown_status_pass.cc \ | |||
| graph/passes/dynamic_single_op_reset_shape_pass.cc \ | |||
| graph/passes/mark_agnostic_pass.cc \ | |||
| graph/common/omg_util.cc \ | |||
| graph/common/bcast.cc \ | |||
| @@ -111,6 +111,7 @@ LIBGE_LOCAL_SRC_FILES := \ | |||
| graph/passes/atomic_addr_clean_pass.cc \ | |||
| graph/passes/mark_same_addr_pass.cc \ | |||
| graph/passes/mark_graph_unknown_status_pass.cc \ | |||
| graph/passes/dynamic_single_op_reset_shape_pass.cc \ | |||
| graph/passes/mark_agnostic_pass.cc \ | |||
| graph/partition/dynamic_shape_partition.cc \ | |||
| graph/partition/stage_partition.cc \ | |||
| @@ -47,6 +47,8 @@ const char *const kEngineNameDefault = "default"; | |||
| const char *const kVectorEngine = "VectorEngine"; | |||
| const char *const kAIcoreEngine = "AIcoreEngine"; | |||
| const char *const kFileNameSuffix = "online"; | |||
| const int kDynamicDimSize = 1; | |||
| const int64_t kDynamicDimValue = -2; | |||
| std::map<ge::OpEngineType, std::string> engine_type_map{ | |||
| {ge::ENGINE_SYS, kEngineNameDefault}, {ge::ENGINE_AICORE, kAIcoreEngine}, {ge::ENGINE_VECTOR, kVectorEngine}}; | |||
| @@ -231,6 +233,42 @@ static void GetOpsProtoPath(string &opsproto_path) { | |||
| opsproto_path = (path_base + "ops/op_proto/custom/" + ":") + (path_base + "ops/op_proto/built-in/"); | |||
| } | |||
| static Status CheckShapeReset(const OpDescPtr &op_desc, bool &change_shape_flag) { | |||
| GE_CHECK_NOTNULL_EXEC(op_desc, return PARAM_INVALID); | |||
| change_shape_flag = false; | |||
| for (size_t i = 0; i < op_desc->GetAllInputsDesc().size(); i++) { | |||
| auto input_desc = op_desc->MutableInputDesc(static_cast<uint32_t>(i)); | |||
| GE_CHECK_NOTNULL(input_desc); | |||
| // pass scalar input desc | |||
| auto dims = input_desc->GetShape().GetDims(); | |||
| if (dims.size() == kDynamicDimSize && dims[0] == kDynamicDimValue) { | |||
| change_shape_flag = true; | |||
| } | |||
| } | |||
| return SUCCESS; | |||
| } | |||
| static void ResetTensorVecShape(const vector<GeTensor> &inputs, vector<GeTensor> &inputs_dynamic) { | |||
| for (auto input : inputs) { | |||
| auto input_desc = input.GetTensorDesc(); | |||
| GeShape shape_ori = input_desc.GetShape(); | |||
| Format format_ori = input_desc.GetFormat(); | |||
| DataType type_ori = input_desc.GetDataType(); | |||
| std::vector<int64_t> dynamic_shape_dims = {kDynamicDimValue}; | |||
| GeShape dynamic_shape(dynamic_shape_dims); | |||
| ge::GeTensor inputTensor; | |||
| ge::GeTensorDesc desc(shape_ori, format_ori, type_ori); | |||
| if (shape_ori.GetDims().size() > 0) { | |||
| desc.SetShape(dynamic_shape); | |||
| } | |||
| inputTensor.SetTensorDesc(desc); | |||
| inputs_dynamic.push_back(inputTensor); | |||
| } | |||
| } | |||
| class GeGenerator::Impl { | |||
| public: | |||
| Impl(OmgContext &omg_context) : omg_context_(omg_context) {} | |||
| @@ -557,7 +595,9 @@ Status GeGenerator::CheckForSingleOp(OpDescPtr &op_desc, const vector<GeTensor> | |||
| Status GeGenerator::BuildSingleOp(OpDescPtr &op_desc, const vector<GeTensor> &inputs, const vector<GeTensor> &outputs, | |||
| const string &model_file_name, OpEngineType engine_type, ModelBufferData &model_buff, | |||
| bool is_offline) { | |||
| if (!is_offline) { | |||
| (void)AttrUtils::SetBool(op_desc, ATTR_DYNAMIC_SHAPE_SINGLE_AICPU, true); | |||
| } | |||
| if (CheckForSingleOp(op_desc, inputs, outputs) != SUCCESS) { | |||
| GELOGE(PARAM_INVALID, "input param is invalid when build single op!"); | |||
| return PARAM_INVALID; | |||
| @@ -605,7 +645,18 @@ Status GeGenerator::BuildSingleOp(OpDescPtr &op_desc, const vector<GeTensor> &in | |||
| } | |||
| GeModelPtr &ge_model = name_to_ge_model.begin()->second; | |||
| GELOGD("The opType in op_desc_tmp is [%s]", op_desc_tmp->GetType().c_str()); | |||
| GE_CHK_STATUS_RET_NOLOG(impl_->SaveParams(ge_model, op_desc_tmp->GetType(), op_attrs, inputs, outputs)); | |||
| bool dynamic_flag = false; | |||
| if (CheckShapeReset(op_desc, dynamic_flag) == SUCCESS && dynamic_flag) { | |||
| vector<GeTensor> inputs_dynamic; | |||
| vector<GeTensor> outputs_dynamic; | |||
| ResetTensorVecShape(inputs, inputs_dynamic); | |||
| ResetTensorVecShape(outputs, outputs_dynamic); | |||
| GE_CHK_STATUS_RET_NOLOG( | |||
| impl_->SaveParams(ge_model, op_desc_tmp->GetType(), op_attrs, inputs_dynamic, outputs_dynamic)); | |||
| } else { | |||
| GE_CHK_STATUS_RET_NOLOG(impl_->SaveParams(ge_model, op_desc_tmp->GetType(), op_attrs, inputs, outputs)); | |||
| } | |||
| GE_CHK_STATUS_RET_NOLOG(impl_->SaveModel(model_file_name, ge_model, model_buff)); | |||
| return SUCCESS; | |||
| } | |||
| @@ -68,6 +68,7 @@ | |||
| #include "graph/passes/iterator_op_pass.h" | |||
| #include "graph/passes/link_gen_mask_nodes_pass.h" | |||
| #include "graph/passes/mark_graph_unknown_status_pass.h" | |||
| #include "graph/passes/dynamic_single_op_reset_shape_pass.h" | |||
| #include "graph/passes/merge_pass.h" | |||
| #include "graph/passes/merge_input_memcpy_pass.h" | |||
| #include "graph/passes/merge_to_stream_merge_pass.h" | |||
| @@ -649,11 +650,22 @@ Status GraphManager::ReplaceSubgraphWithOriGraph(const ComputeGraphPtr &compute_ | |||
| Status GraphManager::SetSubgraph(uint64_t session_id, ComputeGraphPtr compute_graph, GraphPartitioner &partitioner) { | |||
| GE_CHECK_NOTNULL(compute_graph); | |||
| PassManager pass_for_dynamic_shape_reset_optimize; | |||
| GE_CHK_STATUS_RET(pass_for_dynamic_shape_reset_optimize.AddPass( | |||
| "SetSubgraph::AfterSetSubgraph::DynamicSingleOpResetShapePass", new (std::nothrow) DynamicSingleOpResetShapePass)) | |||
| GE_TIMESTAMP_START(pass_for_dynamic_shape_reset_optimize); | |||
| Status ret = pass_for_dynamic_shape_reset_optimize.Run(compute_graph); | |||
| GE_TIMESTAMP_END(pass_for_dynamic_shape_reset_optimize, "SetSubgraph::AfterSetSubgraph"); | |||
| if (ret != SUCCESS && ret != NOT_CHANGED) { | |||
| GELOGE(ret, "Run passes when optimize subgraph failed"); | |||
| return ret; | |||
| } | |||
| auto sub_graph_map = partitioner.GetSubGraphMap(); | |||
| GELOGD("Directly optimize subgraph with build mode:%s, and step:%s.", | |||
| options_.build_mode.c_str(), | |||
| options_.build_step.c_str()); | |||
| Status ret = OptimizeSubGraphWithMultiThreads(compute_graph, sub_graph_map, session_id); | |||
| ret = OptimizeSubGraphWithMultiThreads(compute_graph, sub_graph_map, session_id); | |||
| if (ret != SUCCESS) { | |||
| GELOGE(ret, "Multiply optimize subgraph failed"); | |||
| return ret; | |||
| @@ -0,0 +1,105 @@ | |||
| /** | |||
| * 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 "graph/passes/dynamic_single_op_reset_shape_pass.h" | |||
| #include "common/ge_inner_error_codes.h" | |||
| #include "graph/utils/node_utils.h" | |||
| #include "graph/utils/graph_utils.h" | |||
| #include "graph/utils/tensor_utils.h" | |||
| #include "graph/utils/op_desc_utils.h" | |||
| #include "graph/utils/type_utils.h" | |||
| #include "graph/debug/ge_attr_define.h" | |||
| namespace ge { | |||
| namespace { | |||
| const int64_t kDynamicShapeDim = -2; | |||
| const char *const kEngineNameAiCpu = "aicpu_ascend_kernel"; | |||
| const char *const kEngineNameAiCpuTf = "aicpu_tf_kernel"; | |||
| } // namespace | |||
| Status DynamicSingleOpResetShapePass::Run(ComputeGraphPtr graph) { | |||
| GE_CHECK_NOTNULL(graph); | |||
| std::shared_ptr<GELib> instance = ge::GELib::GetInstance(); | |||
| if (instance == nullptr || !instance->InitFlag()) { | |||
| GELOGE(ge::GE_CLI_GE_NOT_INITIALIZED, "Run CompileNodesPass failed."); | |||
| return ge::GE_CLI_GE_NOT_INITIALIZED; | |||
| } | |||
| for (const auto &node : graph->GetDirectNode()) { | |||
| GE_CHECK_NOTNULL(node->GetOpDesc()); | |||
| // pass input and output node | |||
| if (node->GetType() == DATA || node->GetType() == CONSTANT || node->GetType() == CONSTANTOP || | |||
| node->GetType() == NETOUTPUT) { | |||
| continue; | |||
| } | |||
| // pass node without attr: ATTR_DYNAMIC_SHAPE_SINGLE_AICPU | |||
| bool single_aicpu_unknown = false; | |||
| if (!AttrUtils::GetBool(node->GetOpDesc(), ATTR_DYNAMIC_SHAPE_SINGLE_AICPU, single_aicpu_unknown) || | |||
| !single_aicpu_unknown) { | |||
| continue; | |||
| } | |||
| // pass not aicpu node. | |||
| auto op_desc = node->GetOpDesc(); | |||
| string engine_name = op_desc->GetOpEngineName(); | |||
| if (engine_name.empty()) { | |||
| GELOGE(GRAPH_FAILED, "Get engine failed of node[%s].", node->GetName().c_str()); | |||
| return GRAPH_FAILED; | |||
| } | |||
| if (engine_name != kEngineNameAiCpu && engine_name != kEngineNameAiCpuTf) { | |||
| continue; | |||
| } | |||
| // reset aicpu shape to unknown shape | |||
| if (ResetOpShape(op_desc) != SUCCESS) { | |||
| GELOGE(ge::GE_CLI_GE_NOT_INITIALIZED, "Reset node[%s] dynamic shapr failed.", node->GetName().c_str()); | |||
| return ge::GE_CLI_GE_NOT_INITIALIZED; | |||
| } | |||
| GELOGD("Reset dynamic aicpu node [%s] shape success!", node->GetName().c_str()); | |||
| } | |||
| GELOGD("Reset dynamic aicpu nodes shape of graph [%s] success!", graph->GetName().c_str()); | |||
| return SUCCESS; | |||
| } | |||
| Status DynamicSingleOpResetShapePass::ResetOpShape(OpDescPtr &op_desc) { | |||
| GE_CHECK_NOTNULL(op_desc); | |||
| std::vector<int64_t> dynamic_shape_dims = {kDynamicShapeDim}; | |||
| GeShape dynamic_shape(dynamic_shape_dims); | |||
| for (size_t i = 0; i < op_desc->GetAllInputsDesc().size(); i++) { | |||
| auto input_desc = op_desc->MutableInputDesc(static_cast<uint32_t>(i)); | |||
| GE_CHECK_NOTNULL(input_desc); | |||
| // pass scalar input desc | |||
| auto dims_ori = input_desc->GetShape().GetDims(); | |||
| if (dims_ori.size() == 0) { | |||
| continue; | |||
| } | |||
| input_desc->SetShape(dynamic_shape); | |||
| } | |||
| for (size_t i = 0; i < op_desc->GetAllOutputsDesc().size(); i++) { | |||
| auto output_desc = op_desc->MutableOutputDesc(static_cast<uint32_t>(i)); | |||
| GE_CHECK_NOTNULL(output_desc); | |||
| // pass scalar input desc | |||
| auto output_dims_ori = output_desc->GetShape().GetDims(); | |||
| if (output_dims_ori.size() == 0) { | |||
| continue; | |||
| } | |||
| output_desc->SetShape(dynamic_shape); | |||
| } | |||
| return SUCCESS; | |||
| } | |||
| } // namespace ge | |||
| @@ -0,0 +1,32 @@ | |||
| /** | |||
| * 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 GE_GRAPH_PASSES_DYNAMIC_SINGLE_OP_RESET_SHAPE_PASS_H_ | |||
| #define GE_GRAPH_PASSES_DYNAMIC_SINGLE_OP_RESET_SHAPE_PASS_H_ | |||
| #include "graph/graph.h" | |||
| #include "inc/graph_pass.h" | |||
| #include "init/gelib.h" | |||
| namespace ge { | |||
| class DynamicSingleOpResetShapePass : public GraphPass { | |||
| public: | |||
| Status Run(ComputeGraphPtr graph) override; | |||
| private: | |||
| Status ResetOpShape(OpDescPtr &op_desc); | |||
| }; | |||
| } // namespace ge | |||
| #endif // GE_GRAPH_PASSES_DYNAMIC_SINGLE_OP_RESET_SHAPE_PASS_H_ | |||
| @@ -1 +1 @@ | |||
| Subproject commit bd2cfdfa85a3d9dcbd7dc825f5759c7f8b3ffa9a | |||
| Subproject commit a83f6219922830574b9faad591d9a96ef23cc0f8 | |||
| @@ -182,6 +182,7 @@ set(COMMON_SRC_FILES | |||
| "${GE_CODE_DIR}/ge/graph/passes/atomic_addr_clean_pass.cc" | |||
| "${GE_CODE_DIR}/ge/graph/passes/mark_same_addr_pass.cc" | |||
| "${GE_CODE_DIR}/ge/graph/passes/mark_graph_unknown_status_pass.cc" | |||
| "${GE_CODE_DIR}/ge/graph/passes/dynamic_single_op_reset_shape_pass.cc" | |||
| "${GE_CODE_DIR}/ge/graph/passes/mark_agnostic_pass.cc" | |||
| "${GE_CODE_DIR}/ge/graph/passes/dimension_compute_pass.cc" | |||
| "${GE_CODE_DIR}/ge/graph/passes/dimension_adjust_pass.cc" | |||