|
- /**
- * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
- *
- * 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 "parser/tensorflow/tensorflow_parser.h"
- #include <algorithm>
- #include <iostream>
- #include "ge/ge_api_types.h"
- #include "parser/common/convert/pb2json.h"
- #include "parser/common/acl_graph_parser_util.h"
- #include "common/util/error_manager/error_manager.h"
- #include "external/graph/operator_factory.h"
- #include "external/parser/tensorflow_parser.h"
- #include "external/register/scope/scope_fusion_pass_register.h"
- #include "framework/common/debug/ge_log.h"
- #include "framework/omg/parser/parser_api.h"
- #include "framework/omg/parser/parser_inner_ctx.h"
- #include "graph/debug/ge_attr_define.h"
- #include "graph/utils/graph_utils.h"
- #include "graph/utils/node_utils.h"
- #include "graph/utils/type_utils.h"
- #include "iterator_fusion_pass.h"
- #include "omg/parser/op_parser.h"
- #include "omg/parser/parser_factory.h"
- #include "parser/common/acl_graph_parser_util.h"
- #include "parser/common/model_saver.h"
- #include "parser/common/op_map.h"
- #include "parser/common/op_parser_factory.h"
- #include "parser/common/parser_fp16_t.h"
- #include "parser/common/pass_manager.h"
- #include "parser/common/prototype_pass_manager.h"
- #include "parser/common/thread_pool.h"
- #include "parser/common/parser_utils.h"
- #include "parser/common/util.h"
- #include "parser/tensorflow/tensorflow_custom_parser_adapter.h"
- #include "parser/tensorflow/tensorflow_fusion_custom_parser_adapter.h"
- #include "parser/tensorflow/tensorflow_fusion_op_parser.h"
- #include "parser/tensorflow/tensorflow_op_parser.h"
- #include "parser/tensorflow/tensorflow_util.h"
- #include "register/op_registry.h"
- #include "register/register_utils.h"
- #include "register/scope/scope_pass_registry_impl.h"
- #include "parser/common/auto_mapping_subgraph_io_index_func.h"
- #include "graph/def_types.h"
-
- using ge::OpParserFactory;
- using ge::Pb2Json;
- using ge::PreChecker;
- using ge::TENSORFLOW_ATTR_DATA_FORMAT;
- using ge::TENSORFLOW_ATTR_DTYPE;
- using ge::TENSORFLOW_ATTR_SHAPE;
- using ge::TENSORFLOW_ATTR_T;
- using ge::TENSORFLOW_ATTR_TYPE_STRING;
- using ge::TENSORFLOW_ATTR_TYPE_TENSOR;
- using ge::TENSORFLOW_ATTR_TYPE_TYPE;
- using ge::TENSORFLOW_ATTR_VALUE;
- using ge::TENSORFLOW_NORMAL_INPUT_TENSOR_FLAG;
- using ge::TENSORFLOW_NORMAL_OUTPUT_TENSOR_FLAG;
- using ge::tensorflow_op_map;
- using ge::tensorflow_train_op_map;
- using ge::TENSORFLOWF_NODE_OP_CONST;
- using ge::TENSORFLOWF_NODE_OP_IDENTITY;
- using ge::TENSORFLOWF_NODE_OP_MERGE;
- using ge::TENSORFLOWF_NODE_OP_PLACEHOLDER;
- using ge::TENSORFLOWF_NODE_OP_SWITCH;
- using ge::TENSORFLOWF_NODE_OP_TRANSPOSE;
- using ge::TENSORFLOWF_TENSOR_NCHW;
- using ge::TENSORFLOWF_TENSOR_NHWC;
- using ge::TensorFlowFusionCustomParserAdapter;
- using ge::TensorFlowFusionOpParser;
- using ge::TensorFlowOpParser;
- using ge::ThreadPool;
- using ge::parser::fp16_t;
- using ge::parser::ModelSaver;
-
- namespace ge {
- graphStatus aclgrphParseTensorFlow(const char *model_file, ge::Graph &graph) {
- ErrorManager::GetInstance().SetStage(error_message::kModelCompile, error_message::kParser);
- GE_CHECK_NOTNULL(model_file);
- GetParserContext().type = domi::TENSORFLOW;
- std::map<string, string> options;
- options.insert(std::pair<string, string>(string(ge::FRAMEWORK_TYPE), to_string(domi::TENSORFLOW)));
-
- // load custom plugin so and proto
- AclGraphParserUtil acl_graph_parse_util;
- if (acl_graph_parse_util.AclParserInitialize(options) != domi::SUCCESS) {
- GELOGE(GRAPH_FAILED, "Parser Initialize failed.");
- return GRAPH_FAILED;
- }
-
- // Create an empty computegraph
- ge::ComputeGraphPtr compute_graph = ge::parser::MakeShared<ge::ComputeGraph>("tmpGraph" +
- std::to_string(ge::parser::GetCurrentTimestamp()));
- if (compute_graph == nullptr) {
- REPORT_CALL_ERROR("E19999", "New ComputeGraph failed");
- GELOGE(FAILED, "Create ComputeGraph fail.");
- return FAILED;
- }
-
- graph = ge::GraphUtils::CreateGraphFromComputeGraph(compute_graph);
- auto model_parser = domi::ModelParserFactory::Instance()->CreateModelParser(domi::TENSORFLOW);
- if (model_parser == nullptr) {
- REPORT_CALL_ERROR("E19999", "No Model Parser for tensorflow, check invalid");
- GELOGE(GRAPH_FAILED, "No Model Parser for tensorflow, check invalid");
- return FAILED;
- }
-
- // parse tensorflow model_file to GE graph
- ge::graphStatus ret = model_parser->Parse(model_file, graph);
- if (ret != ge::SUCCESS) {
- GELOGE(ret, "Parser graph %s failed.", ParserUtils::GetGraphName(graph).c_str());
- return ge::FAILED;
- }
-
- std::map<AscendString, AscendString> parser_params;
- if (acl_graph_parse_util.SetOutputNodeInfo(graph, parser_params) != ge::SUCCESS) {
- GELOGE(ret, "Set graph %s default output node failed.", ParserUtils::GetGraphName(graph).c_str());
- return ge::FAILED;
- }
- GELOGI("Parser graph %s success.", ParserUtils::GetGraphName(graph).c_str());
- return ge::SUCCESS;
- }
-
- graphStatus aclgrphParseTensorFlow(const char *model_file, const std::map<AscendString, AscendString> &parser_params,
- ge::Graph &graph) {
- ErrorManager::GetInstance().SetStage(error_message::kModelCompile, error_message::kParser);
- GE_CHECK_NOTNULL(model_file);
- GetParserContext().type = domi::TENSORFLOW;
- std::map<string, string> options;
- options.insert(std::pair<string, string>(string(ge::FRAMEWORK_TYPE), to_string(domi::TENSORFLOW)));
-
- // load custom plugin so and proto
- AclGraphParserUtil acl_graph_parse_util;
- domi::Status status = acl_graph_parse_util.AclParserInitialize(options);
- if (status != domi::SUCCESS) {
- GELOGE(GRAPH_FAILED, "Parser Initialize failed.");
- return GRAPH_FAILED;
- }
-
- string output_name;
- if (acl_graph_parse_util.ParseParamsBeforeGraph(parser_params, output_name) != ge::SUCCESS) {
- GELOGE(ge::FAILED, "Parser params before graph failed.");
- return ge::FAILED;
- }
- // Create an empty computegraph
- string graph_name = output_name.empty() ? ("tmpGraph" +
- std::to_string(ge::parser::GetCurrentTimestamp())) : output_name;
- ge::ComputeGraphPtr compute_graph = ge::parser::MakeShared<ge::ComputeGraph>(graph_name);
- if (compute_graph == nullptr) {
- REPORT_CALL_ERROR("E19999", "New ComputeGraph failed");
- GELOGE(FAILED, "Create ComputeGraph fail.");
- return FAILED;
- }
-
- graph = ge::GraphUtils::CreateGraphFromComputeGraph(compute_graph);
- auto model_parser = domi::ModelParserFactory::Instance()->CreateModelParser(domi::TENSORFLOW);
- if (model_parser == nullptr) {
- REPORT_CALL_ERROR("E19999", "No Model Parser for tensorflow, check invalid");
- GELOGE(GRAPH_FAILED, "No Model Parser for tensorflow, check invalid");
- return FAILED;
- }
-
- // parse tensorflow model_file to GE graph
- ge::graphStatus ret = model_parser->Parse(model_file, graph);
- if (ret != ge::SUCCESS) {
- GELOGE(ret, "Parser graph %s failed.", ParserUtils::GetGraphName(graph).c_str());
- return ge::FAILED;
- }
-
- if (acl_graph_parse_util.ParseParamsAfterGraph(graph, parser_params) != ge::SUCCESS) {
- GELOGE(ge::FAILED, "Parser params after graph failed.");
- return ge::FAILED;
- }
-
- if (acl_graph_parse_util.SetOutputNodeInfo(graph, parser_params) != ge::SUCCESS) {
- GELOGE(ge::FAILED, "Set graph %s default output node failed.", ParserUtils::GetGraphName(graph).c_str());
- return ge::FAILED;
- }
- GELOGI("AclgrphParse graph %s success.", ParserUtils::GetGraphName(graph).c_str());
- return ge::SUCCESS;
- }
-
- void AddDumpOriginName(const ge::NodePtr parent_node, const std::string& subgraph_name, ge::ComputeGraphPtr graph) {
- if (parent_node == nullptr) {
- return; // Root graph no need set dump origin name as parser always keep the origin node name
- }
- std::vector<std::string> original_names;
- (void)ge::AttrUtils::GetListStr(parent_node->GetOpDesc(), ge::ATTR_NAME_DATA_DUMP_ORIGIN_OP_NAMES, original_names);
- if (original_names.empty()) {
- original_names.emplace_back(parent_node->GetName());
- }
- // for fusion node also used original_names[0]
- std::string prefix = original_names[0].append("/").append(subgraph_name).append("/");
- for (const ge::NodePtr &node : graph->GetDirectNode()) {
- original_names[0] = prefix + node->GetName();
- if (!ge::AttrUtils::SetListStr(node->GetOpDesc(), ge::ATTR_NAME_DATA_DUMP_ORIGIN_OP_NAMES, original_names)) {
- GELOGW("Set dump origin name to %s fail.", node->GetOpDesc()->GetName().c_str());
- }
- GELOGD("Add dump origin name %s for node %s.", original_names[0].c_str(), node->GetName().c_str());
- }
- }
- } // namespace ge
-
- namespace ge {
- namespace {
- const int kTransposeInputIdx = 0;
- const uint32_t kThreadNum = 16;
- const size_t kInputNumUint = 2;
- const int kInputNumInt = 2;
- const int32_t kControlSlot = -1;
- const size_t kSoftmaxMultiple = 2;
- const set<string> kTfBlackFields = {"tensor_content"};
- const std::vector<std::string> kSkipCheckoutInputSizeNodes = {ge::parser::DATA, ge::parser::VARIABLE,
- ge::parser::FRAMEWORKOP, ge::parser::LAYERNORM};
- const std::vector<std::string> kMakeOperatorNotByIr = {ge::parser::ARG, ge::parser::VARIABLE, ge::parser::VARHANDLEOP,
- ge::parser::FRAMEWORKOP, ge::parser::DATA};
- const char *const kDpop = "DPOP";
- const char *const kFuncDefLibraryFilePath = "graph_def_library.pbtxt";
- const char *const kAttrNameIsScopeInnerNode = "_is_scope_inner_node";
- const char *const kExternalModel = "_external_model";
- struct ParseArg {
- const google::protobuf::Message *proto;
- std::string function_name;
- ge::NodePtr parent_node;
- std::string subgraph_name;
- ge::ComputeGraphPtr graph;
- };
-
- Status GenSubgraphParseTasks(const ge::ComputeGraphPtr &parent_graph, std::deque<ParseArg> &args) {
- GELOGI("Gen subgraph parse tasks start");
- for (auto &node : parent_graph->GetDirectNode()) {
- auto op_desc = node->GetOpDesc();
- GE_CHECK_NOTNULL(op_desc);
- for (const auto &subgraph_name_to_index : op_desc->GetSubgraphNameIndexes()) {
- auto i = subgraph_name_to_index.second;
- auto subgraph_iname = op_desc->GetSubgraphInstanceName(i);
- if (subgraph_iname.empty()) {
- GELOGW("The subgraph index %u of node %s is empty", i, node->GetName().c_str());
- continue;
- }
-
- // A function may be referenced multiple times in TF, change the graph name to ensure it is unique in GE
- auto unique_name = node->GetName() + std::to_string(i) + subgraph_iname;
- auto subgraph = ge::parser::MakeShared<ge::ComputeGraph>(unique_name);
- if (subgraph == nullptr) {
- REPORT_CALL_ERROR("E19999", "New ComputeGraph failed when create subgraph:%s", subgraph_iname.c_str());
- GELOGE(OUT_OF_MEMORY, "Failed to alloc subgraph %s", subgraph_iname.c_str());
- return OUT_OF_MEMORY;
- }
- auto ret = ge::NodeUtils::SetSubgraph(*node, i, subgraph);
- if (ret != SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Set subgraph:%s to node:%s(%s) failed, index:%u", subgraph_iname.c_str(),
- node->GetName().c_str(), node->GetType().c_str(), i);
- GELOGE(ret, "Set subgraph %s to node %s failed, index %u", subgraph_iname.c_str(), node->GetName().c_str(), i);
- return ret;
- }
-
- GELOGD("Add subgraph parse task to the queue, node %s, index %u, subgraph instance name %s",
- node->GetName().c_str(), i, subgraph_iname.c_str());
- args.push_back({nullptr, subgraph_iname, node, subgraph_name_to_index.first, subgraph});
- }
- }
- GELOGI("Gen subgraph parse tasks end");
- return SUCCESS;
- }
-
- Status PostOpProcessForSubgraph(const ParseArg &arg) {
- AddDumpOriginName(arg.parent_node, arg.subgraph_name, arg.graph);
- if (arg.parent_node == nullptr) {
- return SUCCESS;
- }
- std::string op_type = arg.parent_node->GetType();
- std::string op_name = arg.parent_node->GetName();
- domi::ParseSubgraphFuncV2 parse_func_v2 = nullptr;
- auto post_func = domi::OpRegistry::Instance()->GetParseSubgraphPostFunc(op_type);
- if (post_func == nullptr) {
- GELOGW("The subgraph post func for node %s type %s is null", op_name.c_str(), op_type.c_str());
- if (domi::OpRegistry::Instance()->GetParseSubgraphPostFunc(op_type, parse_func_v2) != SUCCESS ||
- parse_func_v2 == nullptr) {
- GELOGW("The subgraph post func v2 for node %s type %s is null", op_name.c_str(), op_type.c_str());
- return SUCCESS;
- }
- }
-
- GELOGD("Post process for subgraph %s node %s type %s subgraph name %s", arg.function_name.c_str(),
- arg.parent_node->GetName().c_str(), arg.parent_node->GetType().c_str(), arg.subgraph_name.c_str());
-
- // refresh node_name in subgraph
- for (const ge::NodePtr &node : arg.graph->GetDirectNode()) {
- if ((node->GetOpDesc() == nullptr) || (node->GetType() == "Variable") || (node->GetType() == "VariableV2")) {
- continue;
- }
- node->GetOpDesc()->SetName(node->GetOwnerComputeGraph()->GetName() + "/" + node->GetName());
- }
-
- auto graph = ge::GraphUtils::CreateGraphFromComputeGraph(arg.graph);
- Status ret = FAILED;
- if (post_func != nullptr) {
- ret = post_func(arg.subgraph_name, graph);
- } else if (parse_func_v2 != nullptr) {
- ret = parse_func_v2(arg.subgraph_name.c_str(), graph);
- }
- if (ret != SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Call ParseSubgraphPostFunc:%s failed, subgraph:%s, node:%s(%s), ret:0x%X",
- arg.function_name.c_str(), arg.subgraph_name.c_str(), arg.parent_node->GetName().c_str(),
- arg.parent_node->GetType().c_str(), ret);
- GELOGE(FAILED, "Failed to post-process subgraph %s on node %s type %s subgraph name %s", arg.function_name.c_str(),
- arg.parent_node->GetName().c_str(), arg.parent_node->GetType().c_str(), arg.subgraph_name.c_str());
- return FAILED;
- }
- return SUCCESS;
- }
-
- Status MappingAndAddSubGraph(const NodePtr &node, const Graph &graph, const ComputeGraphPtr &root_graph) {
- // Inner function, data format need be set by parant node
- GE_CHK_STATUS_RET(AutoMappingSubgraphDataFormat(node, graph),
- "[Call][AutoMappingSubgraphDataFormat] failed, node:%s, "
- "root graph:%s, graph:%s",
- node->GetName().c_str(), root_graph->GetName().c_str(),
- ParserUtils::GetGraphName(graph).c_str());
- // Inner function, input params have been checked by caller
- Status status = AutoMappingSubgraphIndexByDataNodeAndOutputNodesInfo(
- graph,
- [](int in, int &out) -> Status {
- out = in;
- return SUCCESS;
- },
- [](int in, int &out) -> Status {
- out = in;
- return SUCCESS;
- });
- if (status != SUCCESS) {
- GELOGE(INTERNAL_ERROR, "[Mapping][Subgraph]node:%s, sub graph name:%s.", node->GetName().c_str(),
- ParserUtils::GetGraphName(graph).c_str());
- REPORT_CALL_ERROR("E19999", "Failed to map sub graph input and output, node:%s, sub graph name:%s.",
- node->GetName().c_str(), ParserUtils::GetGraphName(graph).c_str());
- return INTERNAL_ERROR;
- }
-
- ComputeGraphPtr compute_graph = GraphUtils::GetComputeGraph(graph);
- GE_CHECK_NOTNULL(compute_graph);
- // Inner function, GetOpDesc has been checked by caller
- (void)node->GetOpDesc()->AddSubgraphName("f");
- auto ret = NodeUtils::SetSubgraph(*node, 0, compute_graph);
- if (ret != GRAPH_SUCCESS) {
- GELOGE(INTERNAL_ERROR, "[Set][Subgraph]Node:%s, sub graph name:%s.", node->GetName().c_str(),
- compute_graph->GetName().c_str());
- REPORT_CALL_ERROR("E19999", "Failed to set sub graph, node: %s, sub graph name: %s.", node->GetName().c_str(),
- compute_graph->GetName().c_str());
- return INTERNAL_ERROR;
- }
- for (const auto &sub_graph : compute_graph->GetAllSubgraphs()) {
- ret = root_graph->AddSubgraph(sub_graph);
- if (ret != GRAPH_SUCCESS) {
- GELOGE(INTERNAL_ERROR, "[Add][Subgraph]Node:%s, sub graph name:%s, sub sub graph name:%s.",
- node->GetName().c_str(), compute_graph->GetName().c_str(), sub_graph->GetName().c_str());
- REPORT_CALL_ERROR("E19999", "Failed to add sub graph to root graph, node:%s, sub graph name:%s.",
- node->GetName().c_str(), sub_graph->GetName().c_str());
- return INTERNAL_ERROR;
- }
- compute_graph->RemoveSubgraph(sub_graph);
- GELOGD("Add subgraph[%s] to root graph[%s].", sub_graph->GetName().c_str(), root_graph->GetName().c_str());
- }
- return SUCCESS;
- }
- } // namespace
-
- /**
- * @ingroup domi_omg
- * @brief Trans common decorate function to PartitionedCall.
- * @param [in] node_def: Node of common function.
- * @param [out] op: result of PartitionedCall OpDesc.
- * @return 0: SUCCESS / Others: FAILED
- */
- Status TensorFlowModelParser::DefunToPartitionedCall(const domi::tensorflow::NodeDef *node_def,
- ge::OpDescPtr &op) const {
- const string op_name = node_def->name();
- domi::tensorflow::AttrValue attr_call_inference;
- if (!ge::TensorFlowUtil::FindAttrValue(node_def, "_disable_call_shape_inference", attr_call_inference)) {
- ErrorManager::GetInstance().ATCReportErrMessage(
- "E19014", {"opname", "value", "reason"},
- {node_def->name(), "attr [_disable_call_shape_inference]",
- "may has no ir definition, if it is not a common decorate function operator"});
- GELOGE(FAILED,
- "Op %s has no ir definition, or has no attr [_disable_call_shape_inference] "
- "if it is a common decorate function operator.",
- op_name.c_str());
- return FAILED;
- }
-
- op = ge::parser::MakeShared<ge::OpDesc>(op_name, ge::parser::PARTITIONEDCALL);
- GE_CHECK_NOTNULL(op);
-
- size_t input_tensor_num = 0;
- size_t output_tensor_num = 0;
- GetInputOutputTensorNum(op, input_tensor_num, output_tensor_num);
-
- for (size_t i = 0; i < input_tensor_num; ++i) {
- ge::GeTensorDesc input_tensor;
- if (op->AddInputDesc(input_tensor) != ge::GRAPH_SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Add input desc to op:%s(%s) failed", op->GetName().c_str(), op->GetType().c_str());
- GELOGE(FAILED, "op [%s] type[%s] add input(%zu) tensor failed.", op_name.c_str(), op->GetType().c_str(), i);
- return FAILED;
- }
- }
-
- for (size_t i = 0; i < output_tensor_num; ++i) {
- ge::GeTensorDesc output_tensor;
- if (op->AddOutputDesc(output_tensor) != ge::GRAPH_SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Add output desc to op:%s(%s) failed", op->GetName().c_str(), op->GetType().c_str());
- GELOGE(FAILED, "op [%s] type[%s] add output(%zu) tensor failed.", op_name.c_str(), op->GetType().c_str(), i);
- return FAILED;
- }
- }
-
- GELOGI("After AddTensorDescToOpDesc op[%s]: type[%s] have input size: %zu, output size: %zu, disable inference: %d",
- op_name.c_str(), op->GetType().c_str(), op->GetInputsSize(), op->GetOutputsSize(), attr_call_inference.b());
-
- (void)op->AddSubgraphName("f");
- (void)op->SetSubgraphInstanceName(0, op_name);
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::TransNodeToOpDesc(const domi::tensorflow::NodeDef *node_def, ge::OpDescPtr &op,
- const string &op_type) const {
- GE_CHECK_NOTNULL(node_def);
- string node_name = node_def->name();
- ge::Operator op_factory = ge::OperatorFactory::CreateOperator(node_name.c_str(), op_type.c_str());
- if (ParserUtils::GetOperatorName(op_factory) != node_name || op_type == ge::parser::DATA) {
- if (std::find(kMakeOperatorNotByIr.begin(), kMakeOperatorNotByIr.end(), op_type) != kMakeOperatorNotByIr.end()) {
- op = ge::parser::MakeShared<ge::OpDesc>(node_name, op_type);
- GE_CHECK_NOTNULL(op);
- } else if (node_name == op_type) {
- // Trans @tensorflow.python.framework.Defun(...) to PartitionedCall.
- GE_RETURN_IF_ERROR(DefunToPartitionedCall(node_def, op));
- GE_CHECK_NOTNULL(op);
- } else {
- ErrorManager::GetInstance().ATCReportErrMessage("E10501", {"opname", "optype"}, {node_name, op_type});
- GELOGE(INTERNAL_ERROR, "IR for op[%s] optype[%s] is not registered.", node_name.c_str(), op_type.c_str());
- return FAILED;
- }
- } else {
- op = ge::OpDescUtils::GetOpDescFromOperator(op_factory);
- GE_CHECK_NOTNULL(op);
- GELOGI("After GetOpDescFromOperator op[%s]: type[%s] has input size: %zu, output size: %zu", op->GetName().c_str(),
- op->GetType().c_str(), op->GetInputsSize(), op->GetOutputsSize());
-
- GE_RETURN_IF_ERROR(AddTensorDescToOpDesc(op, node_def));
- GELOGI("After AddTensorDescToOpDesc op[%s]: type[%s] has input size: %zu, output size: %zu", op->GetName().c_str(),
- op->GetType().c_str(), op->GetInputsSize(), op->GetOutputsSize());
- }
- op_factory.BreakConnect();
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::ParseOpParams(const domi::tensorflow::NodeDef *node_def, ge::OpDescPtr &op,
- const shared_ptr<OpParser> &op_parser) {
- GE_CHECK_NOTNULL(node_def);
- GE_CHECK_NOTNULL(op);
- GE_CHECK_NOTNULL(op_parser);
-
- string node_name = node_def->name();
- string node_op = node_def->op();
-
- Status status = FAILED;
- domi::ParseParamByOpFunc parse_param_by_op_fn = domi::OpRegistry::Instance()->GetParseParamByOperatorFunc(node_op);
- if (parse_param_by_op_fn == nullptr) {
- shared_ptr<TensorFlowOpParser> tensorflow_op_parser = std::dynamic_pointer_cast<TensorFlowOpParser>(op_parser);
- GE_CHECK_NOTNULL(tensorflow_op_parser);
- status = tensorflow_op_parser->ParseParams(node_def, op);
- if (status != SUCCESS) {
- GELOGE(status, "Parse params for node[%s] failed", node_name.c_str());
- return status;
- }
- } else {
- ge::Operator op_src(node_def->name().c_str(), node_def->op().c_str());
- status = domi::OperatorAutoMapping(node_def, op_src);
- if (status != SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Auto mapping node_def:%s(%s) to operator failed", node_def->name().c_str(),
- node_def->op().c_str());
- GELOGE(status, "Node[%s] auto mapping failed.", node_name.c_str());
- return status;
- }
- std::shared_ptr<ge::TensorFlowCustomParserAdapter> tf_custom_op_parser =
- std::dynamic_pointer_cast<ge::TensorFlowCustomParserAdapter>(op_parser);
- GE_CHECK_NOTNULL(tf_custom_op_parser);
- status = tf_custom_op_parser->ParseParams(op_src, op);
- if (status != SUCCESS) {
- GELOGE(status, "Parse params for node[%s] failed", ParserUtils::GetOperatorName(op_src).c_str());
- return status;
- }
- }
- domi::tensorflow::AttrValue attr;
- if (ge::TensorFlowUtil::FindAttrValue(node_def, ATTR_NAME_QOS_SERVICE_LABEL, attr)) {
- (void)ge::AttrUtils::SetInt(*op, ATTR_NAME_QOS_SERVICE_LABEL, static_cast<int64_t>(attr.i()));
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::AddNode(const domi::tensorflow::NodeDef *node_def, ge::ComputeGraphPtr &graph,
- shared_ptr<ge::ScopeGraph> &scope_graph) {
- GE_CHECK_NOTNULL(node_def);
- GE_CHECK_NOTNULL(graph);
- GE_CHECK_NOTNULL(scope_graph);
- domi::tensorflow::AttrValue attr_value;
- if (ge::TensorFlowUtil::FindAttrValue(node_def, kAttrNameIsScopeInnerNode, attr_value) && attr_value.b()) {
- std::mutex graph_mutex;
- return AddScopeInnerNode(this, graph, &graph_mutex, node_def);
- }
- // node is released in destructor
- string node_name = node_def->name();
- string node_op = node_def->op();
- std::map<std::string, std::string>::const_iterator type_it = tensorflow_op_map.find(node_op);
- if (type_it == tensorflow_op_map.end()) {
- GELOGI("Can not find,maybe this node has no plugin node_name is %s, node_op is %s ", node_name.c_str(),
- node_op.c_str());
- ge::OpDescPtr op_desc;
- GE_RETURN_IF_ERROR(TransNodeToOpDesc(node_def, op_desc, node_op));
-
- ge::Operator op = ge::OpDescUtils::CreateOperatorFromOpDesc(op_desc);
- GE_CHK_STATUS(domi::OperatorAutoMapping(node_def, op));
- op.BreakConnect();
-
- ge::NodePtr node = nullptr;
- node = graph->AddNode(op_desc);
- if (node == nullptr) {
- DeleteFuisonNodeDef();
- GELOGE(FAILED, "add node failed.");
- return INTERNAL_ERROR;
- }
-
- node_map_[node_name] = node;
-
- return SUCCESS;
- }
-
- string op_type = type_it->second;
-
- // The type value is obtained from the definition map set of DaVinci.
- ge::OpDescPtr op;
- GE_RETURN_IF_ERROR(TransNodeToOpDesc(node_def, op, op_type));
-
- bool needFusion = IsFusionOp(scope_graph, node_def);
- // The number of inputs and outputs of each operator can be determined after the new IR design model is resolved.
- // Add tensordesc to the opdesc object of the operator
- // Process change of tensordesc initialization of opdesc,
- // Previous process: Tensordesc is constructed according to graph structure in builder stage
- // Current process: Tensordesc is determined before the opdesc of the operator is added to the graph
- Status status = FAILED;
- // create OpParser
- shared_ptr<OpParserFactory> factory = OpParserFactory::Instance(domi::TENSORFLOW);
- GE_CHECK_NOTNULL(factory);
- if (!needFusion) {
- shared_ptr<OpParser> op_parser = factory->CreateOpParser(op_type);
- // parse op param
- status = ParseOpParams(node_def, op, op_parser);
- if (status != SUCCESS) {
- GELOGE(status, "Parse params for node[%s] failed", node_name.c_str());
- return status;
- }
- }
- GELOGI("After op parser op[%s] type[%s] have input size: %zu, output size: %zu", op->GetName().c_str(),
- op->GetType().c_str(), op->GetInputsSize(), op->GetOutputsSize());
- // checkout op input number with IR
- GE_RETURN_IF_ERROR(CheckoutInputNum(op, node_def));
- ge::NodePtr node = graph->AddNode(op);
- if (node == nullptr) {
- DeleteFuisonNodeDef();
- GELOGE(FAILED, "add node failed.");
- return INTERNAL_ERROR;
- }
-
- node_map_[node_name] = node;
-
- if (needFusion) {
- shared_ptr<OpParser> fusion_op_parser = factory->CreateFusionOpParser(op_type);
- GE_CHECK_NOTNULL(fusion_op_parser);
- // Find all children of the fusion operator
- std::map<string, vector<const NodeDef *>>::const_iterator iter = fusion_op_nodedef_map_.find(node_def->name());
- if (iter == fusion_op_nodedef_map_.end()) {
- REPORT_INNER_ERROR("E19999", "FusionOp node %s has no children node, check invalid", node_name.c_str());
- GELOGE(FAILED, "FusionOp node %s has no children node!", node_name.c_str());
- return INTERNAL_ERROR;
- }
- vector<const domi::tensorflow::NodeDef *> node_def_v = iter->second;
- // parse fusion node param
- status = FusionNodeParseParams(fusion_op_parser, node_def, node);
- if (status != SUCCESS) {
- GELOGE(status, "Parse params for fusion node[%s] failed", node_name.c_str());
- return status;
- }
- // record original op names
- std::vector<std::string> namesTmp;
- for (auto &node_def_iter : node_def_v) {
- GE_CHECK_NOTNULL(node_def_iter);
- std::string nodeName = node_def_iter->name();
- namesTmp.push_back(nodeName);
- }
-
- ge::GraphUtils::RecordOriginalNames(namesTmp, node);
- status = RecordFusionResult(scope_graph, node_def, op);
- if (status != SUCCESS) {
- GELOGE(INTERNAL_ERROR, "Record fusion result for fusion op: %s failed", op->GetName().c_str());
- DeleteFuisonNodeDef();
- return status;
- }
- }
- return SUCCESS;
- }
-
- void TensorFlowModelParser::GetInputOutputTensorNum(const ge::OpDescPtr &op_desc, size_t &input_tensor_num,
- size_t &output_tensor_num) const {
- // The caller guarantees that the pointer is not null
- auto iter = op_node_context_map_.find(op_desc->GetName());
- if (iter == op_node_context_map_.end()) {
- return;
- }
- const OpNodeContext &op_context = iter->second;
- const std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> &dest_input_map = op_context.input_map;
- // input number
- input_tensor_num = 0;
- for (auto &input_vec : dest_input_map) {
- for (auto &input_v : input_vec.second) {
- if (input_v.second != kControlSlot) {
- input_tensor_num++;
- }
- }
- }
-
- // output number
- const std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> &src_output_map = op_context.output_map;
- int32_t max_anchor_index = 0;
- for (auto &src_output_iter : src_output_map) {
- for (auto &index_output_iter : src_output_iter.second) {
- if (index_output_iter.first > max_anchor_index) {
- max_anchor_index = index_output_iter.first;
- }
- }
- }
- output_tensor_num = max_anchor_index + 1;
- }
-
- Status TensorFlowModelParser::CheckoutInputNum(ge::OpDescPtr &op_desc, const domi::tensorflow::NodeDef *node) const {
- GE_CHECK_NOTNULL(node);
- GE_CHECK_NOTNULL(op_desc);
-
- if (std::find(kSkipCheckoutInputSizeNodes.begin(), kSkipCheckoutInputSizeNodes.end(), op_desc->GetType()) !=
- kSkipCheckoutInputSizeNodes.end()) {
- return SUCCESS;
- }
-
- // get input and output tensor number
- size_t input_tensor_num = 0;
- size_t output_tensor_num = 0;
- GetInputOutputTensorNum(op_desc, input_tensor_num, output_tensor_num);
-
- // get input and output tensor number from op desc
- size_t factory_input_size = op_desc->GetInputsSize();
- if (input_tensor_num != factory_input_size) {
- ErrorManager::GetInstance().ATCReportErrMessage(
- "E19014", {"opname", "value", "reason"},
- {op_desc->GetName(), "input number of tensorflow[" + std::to_string(input_tensor_num) + "]",
- "should be equal to factory size[" + std::to_string(factory_input_size) + "]"});
- GELOGE(FAILED, "op [%s], type[%s], The input number of tensorflow[%zu] should be equal to factory size[%zu]",
- op_desc->GetName().c_str(), op_desc->GetType().c_str(), input_tensor_num, factory_input_size);
- return FAILED;
- }
- return SUCCESS;
- }
-
- void TensorFlowModelParser::UpdateInputTensor(ge::OpDescPtr &op_desc, const std::vector<ge::GeTensorDesc> &input_desc,
- const size_t input_tensor_num) {
- // The caller guarantees that the pointer is not null
- for (size_t i = 0; i < input_tensor_num; ++i) {
- if (i < input_desc.size()) {
- // i is guaranteed to be valid, no check required.
- ge::graphStatus ret = op_desc->UpdateInputDesc(op_desc->GetInputNameByIndex(i), input_desc[i]);
- if (ret != ge::GRAPH_SUCCESS) {
- // UpdateInputDesc for dynamic intput will be failed, but it will be added in later op parser.
- GELOGI("op [%s], type[%s], input(%zu) with name %s is not updated", op_desc->GetName().c_str(),
- op_desc->GetType().c_str(), i, op_desc->GetInputNameByIndex(i).c_str());
- }
- } else {
- ge::GeTensorDesc input_tensor;
- // i is guaranteed to be valid, no check required.
- ge::graphStatus ret = op_desc->UpdateInputDesc(op_desc->GetInputNameByIndex(i), input_tensor);
- if (ret != ge::GRAPH_SUCCESS) {
- // UpdateInputDesc for dynamic intput will be failed, but it will be added in later op parser.
- GELOGI("op [%s], type[%s], input(%zu) with name %s is not updated", op_desc->GetName().c_str(),
- op_desc->GetType().c_str(), i, op_desc->GetInputNameByIndex(i).c_str());
- }
- }
- }
- }
-
- void TensorFlowModelParser::UpdateOutputTensor(ge::OpDescPtr &op_desc, const std::vector<ge::GeTensorDesc> &output_desc,
- size_t output_tensor_num) {
- // The caller guarantees that the pointer is not null
- for (size_t i = 0; i < output_tensor_num; ++i) {
- if (i < output_desc.size()) {
- // i is guaranteed to be valid, no check required.
- ge::graphStatus ret = op_desc->UpdateOutputDesc(op_desc->GetOutputNameByIndex(i), output_desc[i]);
- if (ret != ge::GRAPH_SUCCESS) {
- // UpdateOutputDesc for dynamic output will be failed, but it will be added in later op parser.
- GELOGI("op [%s], type[%s], output(%zu) with name %s is not updated", op_desc->GetName().c_str(),
- op_desc->GetType().c_str(), i, op_desc->GetInputNameByIndex(i).c_str());
- }
- } else {
- ge::GeTensorDesc output_tensor;
- // i is guaranteed to be valid, no check required.
- ge::graphStatus ret = op_desc->UpdateOutputDesc(op_desc->GetOutputNameByIndex(i), output_tensor);
- if (ret != ge::GRAPH_SUCCESS) {
- // UpdateOutputDesc for dynamic output will be failed, but it will be added in later op parser.
- GELOGI("op [%s], type[%s], output(%zu) with name %s is not updated", op_desc->GetName().c_str(),
- op_desc->GetType().c_str(), i, op_desc->GetInputNameByIndex(i).c_str());
- }
- }
- }
- }
-
- Status TensorFlowModelParser::AddTensorDescToOpDesc(ge::OpDescPtr &op_desc,
- const domi::tensorflow::NodeDef *node) const {
- GE_CHECK_NOTNULL(node);
- GE_CHECK_NOTNULL(op_desc);
- // get input and output attr from tensorflow
- const string type = node->op();
- domi::tensorflow::AttrValue input_attr_value;
- domi::tensorflow::AttrValue output_attr_value;
- ParserOperator temp_op;
- if (ge::TensorFlowUtil::FindAttrValue(node, ge::parser::ATTR_NAME_INPUT_TENSOR_DESC, input_attr_value)) {
- GE_CHK_STATUS_RET(ge::TensorFlowUtil::TransTensorDescriptor(input_attr_value, &temp_op,
- TENSORFLOW_NORMAL_INPUT_TENSOR_FLAG, type),
- "trans input_attr_value failed, op: %s", node->name().c_str());
- } else {
- GELOGD("Frameworkop has no input tensor desc, name:%s, type:%s.", node->name().c_str(), type.c_str());
- }
- if (ge::TensorFlowUtil::FindAttrValue(node, ge::ATTR_NAME_OUTPUT_TENSOR_DESC, output_attr_value)) {
- GE_CHK_STATUS_RET(ge::TensorFlowUtil::TransTensorDescriptor(output_attr_value, &temp_op,
- TENSORFLOW_NORMAL_OUTPUT_TENSOR_FLAG, type),
- "trans output_attr_value failed, op: %s", node->name().c_str());
- } else {
- GELOGD("Frameworkop has no output tensor desc, name:%s, type:%s.", node->name().c_str(), type.c_str());
- }
-
- auto iter = op_node_context_map_.find(op_desc->GetName());
- if (iter == op_node_context_map_.end()) {
- return SUCCESS;
- }
-
- const std::vector<ge::GeTensorDesc> &input_desc = temp_op.GetInputTensorDesc();
- const std::vector<ge::GeTensorDesc> &output_desc = temp_op.GetOutputTensorDesc();
-
- // get input and output tensor number
- size_t input_tensor_num = 0;
- size_t output_tensor_num = 0;
- GetInputOutputTensorNum(op_desc, input_tensor_num, output_tensor_num);
-
- // update input
- UpdateInputTensor(op_desc, input_desc, input_tensor_num);
-
- // update output
- UpdateOutputTensor(op_desc, output_desc, output_tensor_num);
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::AddEdges(ge::ComputeGraphPtr &graph) {
- GE_CHECK_NOTNULL(graph);
- for (auto &src_iter : op_node_context_map_) {
- string src_op_name = src_iter.first;
- OpNodeContext src_op_node_context = src_iter.second;
- std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> &src_output_map = src_op_node_context.output_map;
- // Traverse all output of the op_node
- for (auto &src_output_iter : src_output_map) {
- string dest_op_name = src_output_iter.first;
- auto dest_iter = op_node_context_map_.find(dest_op_name);
- if (dest_iter == op_node_context_map_.end()) {
- continue;
- }
- // Find that the output of the source node is equal to the destination node
- std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> &dest_input_map = dest_iter->second.input_map;
- std::map<std::string, std::vector<std::pair<int32_t, int32_t>>>::const_iterator
- input_iter = dest_input_map.find(src_op_name);
- // Find output and input
- if (input_iter == dest_input_map.end()) {
- continue;
- }
- auto iter = node_map_.find(src_op_name);
- if (iter == node_map_.end()) {
- continue;
- }
- ge::NodePtr src = iter->second;
- GE_CHECK_NOTNULL(src);
- auto iter1 = node_map_.find(dest_op_name);
- if (iter1 == node_map_.end()) {
- continue;
- }
- // Each pair builds an edge
- ge::NodePtr dest = iter1->second;
- GE_CHECK_NOTNULL(dest);
- if (src_output_iter.second.size() != input_iter->second.size()) {
- REPORT_INNER_ERROR("E19999", "Input size of op[%s]:%zu is not equal to Output size of op[%s]:%zu.",
- src_op_name.c_str(), input_iter->second.size(), dest_op_name.c_str(),
- src_output_iter.second.size());
- GELOGE(INTERNAL_ERROR, "Input size of op[%s]:%zu is not equal to Output size of op[%s]:%zu.",
- src_op_name.c_str(), input_iter->second.size(), dest_op_name.c_str(), src_output_iter.second.size());
- return INTERNAL_ERROR;
- }
- for (auto &outputpair : src_output_iter.second) {
- // Get control edge properties
- bool control = GetEdgesControlInfo(dest_op_name, outputpair.second);
- // Graph create new edge
- if (!control) {
- GELOGD("Start add edge: from %s:%d to %s:%d.", src->GetName().c_str(), outputpair.first,
- dest->GetName().c_str(), outputpair.second);
- ge::OutDataAnchorPtr out_archor_ptr = src->GetOutDataAnchor(outputpair.first);
- GE_CHECK_NOTNULL(out_archor_ptr);
- ge::InDataAnchorPtr in_archor_ptr = dest->GetInDataAnchor(outputpair.second);
- GE_CHECK_NOTNULL(in_archor_ptr);
- if (ge::GraphUtils::AddEdge(out_archor_ptr, in_archor_ptr) != ge::GRAPH_SUCCESS) {
- REPORT_INNER_ERROR("E19999", "Add link from op:%s to op:%s failed",
- src->GetName().c_str(), dest->GetName().c_str());
- GELOGE(FAILED, "Add link failed from op[%s] to op[%s].", src->GetName().c_str(), dest->GetName().c_str());
- return INTERNAL_ERROR;
- }
- } else {
- GELOGD("Start add contorl edge: from %s to %s.", src->GetName().c_str(), dest->GetName().c_str());
- ge::InControlAnchorPtr in_archor_ptr = dest->GetInControlAnchor();
- GE_CHECK_NOTNULL(in_archor_ptr);
- ge::OutControlAnchorPtr out_archor_ptr = src->GetOutControlAnchor();
- GE_CHECK_NOTNULL(out_archor_ptr);
- if (ge::GraphUtils::AddEdge(out_archor_ptr, in_archor_ptr) != ge::GRAPH_SUCCESS) {
- REPORT_INNER_ERROR("E19999", "Add link from op:%s to op:%s failed",
- src->GetName().c_str(), dest->GetName().c_str());
- GELOGE(FAILED, "Add link failed from op[%s] to op[%s].", src->GetName().c_str(), dest->GetName().c_str());
- return INTERNAL_ERROR;
- }
- }
- }
- dest_input_map.erase(input_iter);
- }
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::AddFmkNodeDefToMap(const domi::tensorflow::NodeDef *node_def,
- vector<string> &op_node_name_list) {
- GE_CHECK_NOTNULL(node_def);
- const string &node_name = node_def->name();
-
- nodedef_map_[node_name] = node_def;
-
- OpNodeContext op_node_context;
- op_node_context_map_[node_name] = op_node_context;
- op_node_name_list.push_back(node_name);
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::CheckOpShapeDim(const domi::tensorflow::NodeDef *node_def, const std::set<int> &dims,
- bool &valid) {
- GE_CHECK_NOTNULL(node_def);
- domi::tensorflow::AttrValue input_attr_value;
- bool is_attr_exist =
- ge::TensorFlowUtil::FindAttrValue(node_def, ge::parser::ATTR_NAME_INPUT_TENSOR_DESC, input_attr_value);
- GE_IF_BOOL_EXEC(!is_attr_exist, return SUCCESS);
- GE_CHK_BOOL_EXEC(input_attr_value.has_list(),
- REPORT_INNER_ERROR("E19999", "Attr:%s of node_def:%s(%s) is empty, check invalid",
- ge::parser::ATTR_NAME_INPUT_TENSOR_DESC.c_str(), node_def->name().c_str(),
- node_def->op().c_str());
- return PARAM_INVALID, "output attr value vector is empty");
-
- // list contain many TensorDescriptors
- domi::tensorflow::AttrValue_ListValue a_list = input_attr_value.list();
- for (int32_t i = 0; i < a_list.func_size(); i++) {
- ge::GeTensorDesc ge_desc;
- int32_t tf_datatype = 0;
- GE_CHK_BOOL_RET_STATUS(ge::TensorFlowUtil::ParseFromAttrValueList(ge_desc, a_list, i, tf_datatype), PARAM_INVALID,
- "parse ge_desc failed.");
-
- for (uint32_t j = 0; j < ge_desc.GetShape().GetDimNum(); ++j) {
- int64_t temp_dim = ge_desc.GetShape().GetDim(j);
- GE_IF_BOOL_EXEC(dims.count(temp_dim) > 0, valid = false);
- }
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::CheckOpType(const domi::tensorflow::NodeDef *node_def, string &op_type) {
- GE_CHECK_NOTNULL(node_def);
- bool valid = true;
- string node_name = node_def->name();
-
- std::map<std::string, set<int>> check_dims = {
- {ge::parser::SPARSESOFTMAXCROSSENTROPYWITHLOGITS, {10}},
- };
-
- GE_IF_BOOL_EXEC(
- op_type == ge::parser::SPARSESOFTMAXCROSSENTROPYWITHLOGITS,
- GE_CHK_STATUS_RET(CheckOpShapeDim(node_def, check_dims[op_type], valid), "failed to check op shape");
- GE_IF_BOOL_EXEC(!valid, op_type = ge::parser::FRAMEWORKOP;
- GELOGI("Set op %s to frameworkop", node_name.c_str());
- framework_ops_[node_name] = node_def;
- );
- );
-
- GE_IF_BOOL_EXEC(
- op_type == ge::parser::ADD || op_type == ge::parser::MULTIPLY || op_type == ge::parser::MEAN,
- for (const string &input_name
- : node_def->input()) {
- string tmp_input_name;
- GE_RETURN_IF_ERROR(CheckInputNodeName(input_name, &tmp_input_name, nullptr, nullptr));
- GELOGD("Add or Mul op %s input name is %s", node_name.c_str(), input_name.c_str());
- GE_IF_BOOL_EXEC(framework_ops_.find(tmp_input_name) != framework_ops_.end(),
- GELOGI("Set op %s to frameworkop", node_name.c_str());
- op_type = ge::parser::FRAMEWORKOP;);
- });
-
- return SUCCESS;
- }
-
- /*
- * @ingroup domi_omg
- * @brief Mapping TF's datatype to GE's datatype
- * @param [in] type, datatype types of operators in TF networks
- * @return ge::DataType
- */
- ge::DataType TensorFlowModelParser::ConvertToGeDataType(const uint32_t type) {
- ErrorManager::GetInstance().GenWorkStreamIdDefault();
-
- ge::DataType data_type = domi::TensorAssign::ConvertTensorflowDataType(type);
- return data_type;
- }
-
- Status TensorFlowModelParser::ParseNodeDef(TensorFlowModelParser *parser, ge::ComputeGraphPtr &graph,
- std::mutex *graphMutex, shared_ptr<ge::ScopeGraph> &scope_graph,
- const domi::tensorflow::NodeDef *node_def,
- error_message::Context error_context) {
- ErrorManager::GetInstance().SetErrorContext(error_context);
- // The caller guarantees that the pointer is not null
- string node_name = node_def->name();
- string node_op = node_def->op();
- GELOGD("TF op node name = %s, op type= %s", node_name.c_str(), node_op.c_str());
- domi::tensorflow::AttrValue attr_value;
- if (ge::TensorFlowUtil::FindAttrValue(node_def, kAttrNameIsScopeInnerNode, attr_value) && attr_value.b()) {
- return AddScopeInnerNode(parser, graph, graphMutex, node_def);
- }
-
- std::map<std::string, std::string>::const_iterator iterator = parser->adaptedOpTypeMap_.find(node_name);
- if (iterator == parser->adaptedOpTypeMap_.cend()) {
- REPORT_INNER_ERROR("E19999", "get adapted op type failed, node name = %s", node_name.c_str());
- GELOGE(FAILED, "get adapted op type failed, node name = %s", node_name.c_str());
- return FAILED;
- }
-
- string op_type = iterator->second;
- // Log printing for determining operator type
- domi::ImplyType implyType = domi::OpRegistry::Instance()->GetImplyType(op_type);
- GE_IF_BOOL_EXEC((implyType == domi::ImplyType::TVM) && (op_type != ge::parser::FRAMEWORKOP),
- GELOGD("TBE %s parsering", node_op.c_str()););
- GE_IF_BOOL_EXEC((implyType == domi::ImplyType::CCE) && (op_type != ge::parser::FRAMEWORKOP),
- GELOGD("CCE %s parsering", node_op.c_str()););
- GE_IF_BOOL_EXEC((implyType == domi::ImplyType::HCCL) && (op_type != ge::parser::FRAMEWORKOP),
- GELOGD("HCCL %s parsering", node_op.c_str()););
- GE_IF_BOOL_EXEC(op_type == ge::parser::FRAMEWORKOP,
- GELOGD("FRAMEWORKOP %s parsering", node_op.c_str()););
- GELOGD("TF op node name = %s, op type= %s, trans to op type %s", node_name.c_str(), node_op.c_str(), op_type.c_str());
-
- // Construct operator by IR
- ge::OpDescPtr op;
- ge::Operator op_factory = ge::OperatorFactory::CreateOperator(node_name.c_str(), op_type.c_str());
- if (ParserUtils::GetOperatorName(op_factory) != node_name) {
- if (std::find(kMakeOperatorNotByIr.begin(), kMakeOperatorNotByIr.end(), op_type) != kMakeOperatorNotByIr.end()) {
- op = ge::parser::MakeShared<ge::OpDesc>(node_name, op_type);
- GE_CHECK_NOTNULL(op);
- } else if (node_name == op_type) {
- GE_RETURN_IF_ERROR(parser->DefunToPartitionedCall(node_def, op));
- GE_CHECK_NOTNULL(op);
- ge::Operator op_tmp = ge::OpDescUtils::CreateOperatorFromOpDesc(op);
- GE_CHK_STATUS(domi::OperatorAutoMapping(node_def, op_tmp));
- op_tmp.BreakConnect();
- ge::NodePtr node;
- {
- std::lock_guard<std::mutex> lock(*graphMutex);
- node = graph->AddNode(op);
- }
- GE_CHECK_NOTNULL(node);
- {
- std::lock_guard<std::mutex> lock(parser->nodeMapMutex_);
- parser->node_map_[node_name] = node;
- }
- return SUCCESS;
- } else {
- REPORT_INPUT_ERROR("E10501", std::vector<std::string>({"opname", "optype"}),
- std::vector<std::string>({node_name, op_type}));
- GELOGE(INTERNAL_ERROR, "op[%s] type[%s] have no ir factory.]", node_name.c_str(), op_type.c_str());
- return FAILED;
- }
- } else {
- op = ge::OpDescUtils::GetOpDescFromOperator(op_factory);
- GE_CHECK_NOTNULL(op);
- GELOGD("After GetOpDescFromOperator op[%s] type[%s] have input size: %zu, output size: %zu", op->GetName().c_str(),
- op->GetType().c_str(), op->GetInputsSize(), op->GetOutputsSize());
-
- GE_RETURN_IF_ERROR(parser->AddTensorDescToOpDesc(op, node_def));
- GELOGD("After AddTensorDescToOpDesc op[%s] type[%s] have input size: %zu, output size: %zu", op->GetName().c_str(),
- op->GetType().c_str(), op->GetInputsSize(), op->GetOutputsSize());
- }
- GELOGD("TF op node name = %s, outpusize= %zu", node_name.c_str(), op->GetAllOutputsDesc().size());
- op_factory.BreakConnect();
-
- // create OpParser
- shared_ptr<OpParserFactory> factory = OpParserFactory::Instance(domi::TENSORFLOW);
- GE_CHECK_NOTNULL(factory);
- bool needFusion = parser->IsFusionOp(scope_graph, node_def);
- GELOGD("TF op node name = %s, op type= %s is fusion op(NO: 0; YES: 1)= %d", node_name.c_str(), node_op.c_str(),
- needFusion);
-
- Status status = FAILED;
- if (!needFusion) {
- shared_ptr<OpParser> op_parser = factory->CreateOpParser(op_type);
- status = parser->ParseOpParams(node_def, op, op_parser);
- if (status != SUCCESS) {
- GELOGE(status, "Parse params for node[%s] failed", node_name.c_str());
- return status;
- }
- }
- GELOGD("After op parser op[%s] type[%s] have input size: %zu, output size: %zu", op->GetName().c_str(),
- op->GetType().c_str(), op->GetInputsSize(), op->GetOutputsSize());
-
- // checkout op input number with IR
- GE_RETURN_IF_ERROR(parser->CheckoutInputNum(op, node_def));
-
- if (needFusion) {
- status = RecordFusionResult(scope_graph, node_def, op);
- if (status != SUCCESS) {
- GELOGE(INTERNAL_ERROR, "Record fusion result for fusion op: %s failed", op->GetName().c_str());
- return status;
- }
- }
-
- ge::NodePtr node;
- {
- std::lock_guard<std::mutex> lock(*graphMutex);
- node = graph->AddNode(op);
- }
-
- if (node == nullptr) {
- REPORT_CALL_ERROR("E19999", "Add node:%s(%s) to graph:%s failed", op->GetName().c_str(),
- op->GetType().c_str(), graph->GetName().c_str());
- GELOGE(FAILED, "add node failed.");
- return INTERNAL_ERROR;
- }
-
- if (needFusion) {
- shared_ptr<OpParser> fusion_op_parser = factory->CreateFusionOpParser(op_type);
- status = parser->FusionNodeParseParams(fusion_op_parser, node_def, node);
- GE_CHK_STATUS_EXEC(status, return status, "Parse Params for node %s failed", node_name.c_str());
- }
-
- {
- std::lock_guard<std::mutex> lock(parser->nodeMapMutex_);
- parser->node_map_[node_name] = node;
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::AdaptOpType(const domi::tensorflow::NodeDef *node_def, bool isDatasetInit) {
- // The caller guarantees that the pointer is not null
- string node_name = node_def->name();
- string node_op = node_def->op();
- string op_type;
- if (tensorflow_train_op_map.find(node_op) != tensorflow_train_op_map.end()) {
- op_type = tensorflow_train_op_map.at(node_op);
- GE_CHK_STATUS_RET(CheckOpType(node_def, op_type), "Failed to check op type");
- } else {
- op_type = ge::parser::FRAMEWORKOP;
- domi::tensorflow::AttrValue attr_call_inference;
- if ((node_name == node_op) &&
- ge::TensorFlowUtil::FindAttrValue(node_def, "_disable_call_shape_inference", attr_call_inference)) {
- op_type = node_op;
- }
- }
-
- GE_IF_BOOL_EXEC(isDatasetInit, op_type = ge::parser::FRAMEWORKOP);
- adaptedOpTypeMap_[node_name] = op_type;
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::AddFmkNode(ge::ComputeGraphPtr &graph, shared_ptr<ge::ScopeGraph> &scope_graph,
- vector<string> &op_node_name_list, bool is_dataset_init) {
- GE_CHECK_NOTNULL(graph);
- GE_CHECK_NOTNULL(scope_graph);
-
- GE_RETURN_IF_ERROR(AddFusionNodeDef(scope_graph, op_node_name_list));
- size_t op_node_list_size = op_node_name_list.size();
- for (size_t i = 0; i < op_node_list_size; ++i) {
- const string op_node_name = op_node_name_list[i];
- const domi::tensorflow::NodeDef *node_def = nodedef_map_[op_node_name];
- GE_CHECK_NOTNULL(node_def);
- GE_RETURN_IF_ERROR(AdaptOpType(node_def, is_dataset_init));
- }
- GELOGD("Add fusion nodedef and Adapt op type success");
-
- // Multithreading parallel parsing nodedef
- ThreadPool executor(kThreadNum);
- std::mutex graphMutex;
- std::vector<std::future<Status>> vectorFuture(op_node_list_size);
- ge::ComputeGraphPtr graph_tmp = ge::parser::MakeShared<ge::ComputeGraph>("tmpGraph");
- GE_CHECK_NOTNULL(graph_tmp);
- for (size_t j = 0; j < op_node_list_size; j++) {
- const string op_node_name = op_node_name_list[j];
- const domi::tensorflow::NodeDef *node_def = nodedef_map_[op_node_name];
- GE_CHECK_NOTNULL(node_def);
- std::future<Status> f =
- executor.commit(TensorFlowModelParser::ParseNodeDef, this, graph_tmp, &graphMutex, scope_graph, node_def,
- ErrorManager::GetInstance().GetErrorManagerContext());
- if (!f.valid()) {
- GELOGE(FAILED, "Future is invalid");
- return FAILED;
- }
- vectorFuture[j] = std::move(f);
- }
- GELOGD("Parse nodedef success");
- // Wait for the return value of each thread. If the thread does not finish processing, it will block here
- bool ret_flag = true;
- size_t futureSize = vectorFuture.size();
- for (size_t i = 0; i < futureSize; ++i) {
- Status retStatus = vectorFuture[i].get();
- if (retStatus != SUCCESS) {
- ret_flag = false;
- }
- }
- if (!ret_flag) {
- return FAILED;
- }
- return AddNodeToGraphAndMarkFormat(graph, op_node_name_list);
- }
-
- Status TensorFlowModelParser::AddNodeToGraphAndMarkFormat(ge::ComputeGraphPtr &graph,
- const vector<string> &op_node_name_list) {
- // Add ge:: nodeptr to graph in order
- size_t op_node_list_size = op_node_name_list.size();
- for (size_t j = 0; j < op_node_list_size; j++) {
- const string op_node_name = op_node_name_list[j];
- auto iterator = node_map_.find(op_node_name);
- if (iterator == node_map_.end()) {
- REPORT_INNER_ERROR("E19999", "node:%s can't find in node_map_, check invalid", op_node_name.c_str());
- GELOGE(FAILED, "add node failed.");
- return INTERNAL_ERROR;
- }
- GE_CHECK_NOTNULL(iterator->second);
- GE_CHK_STATUS_RET(iterator->second->SetOwnerComputeGraph(graph), "set owner compute graph failed");
- graph->AddNode(iterator->second);
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::ExcuteScopeFusionPasses(domi::tensorflow::GraphDef *const graph_def,
- shared_ptr<ge::ScopeGraph> &scope_graph) {
- // Identifying scope fusion operators based on scope rules
- GE_CHECK_NOTNULL(graph_def);
- ScopePassManager passmanager;
- PARSER_TIMESTAMP_START(BuildScopeGraph);
- scope_graph = passmanager.BuildScopeGraph(graph_def);
- GE_CHECK_NOTNULL(scope_graph);
- PARSER_TIMESTAMP_END(BuildScopeGraph, "TensorFlowModelParser::BuildScopeGraph");
- PARSER_TIMESTAMP_START(ScopeGraphPass);
- // Validate the non-general scope fusion pass.
- // The parameter is set to the name of the fusion rule.
- // Multiple names can be set and separated by ",".
- std::vector<std::string> enable_pass_names =
- ge::StringUtils::Split(ge::GetParserContext().enable_scope_fusion_passes, ',');
- auto &impl = ge::ScopeFusionPassRegistry::GetInstance().impl_;
- if (impl == nullptr) {
- REPORT_INNER_ERROR("E19999", "ScopeFusionPassRegistry is not properly initialized.");
- GELOGE(ge::MEMALLOC_FAILED, "ScopeFusionPassRegistry is not properly initialized.");
- return ge::MEMALLOC_FAILED;
- }
-
- for (size_t i = 0; i < enable_pass_names.size(); ++i) {
- if (enable_pass_names[i].empty()) {
- continue;
- }
- if (!impl->SetPassEnableFlag(enable_pass_names[i], true)) {
- GELOGW("Failed to set enable flag of scope fusion pass:%s", enable_pass_names[i].c_str());
- }
- }
- std::vector<std::string> scope_passes_list = impl->GetAllRegisteredPasses();
- Status ret = RunScopeFusionPass(scope_passes_list, passmanager, scope_graph);
- if (ret != SUCCESS) {
- GELOGE(ret, "Run scope fusion failed, ret:%u.", ret);
- return ret;
- }
- PARSER_TIMESTAMP_END(ScopeGraphPass, "TensorFlowModelParser::ScopeGraphPass");
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::ParseFromMemory(const char *data, uint32_t size, ge::ComputeGraphPtr &graph) {
- ErrorManager::GetInstance().SetStage(error_message::kModelCompile, error_message::kParser);
- GE_CHECK_NOTNULL(data);
- GE_CHECK_NOTNULL(graph);
-
- // Store objects parsed from pb files
- domi::tensorflow::GraphDef OriDef;
-
- bool read = ge::parser::ReadProtoFromArray(data, static_cast<int>(size), &OriDef);
- if (!read) {
- REPORT_INNER_ERROR("E19999", "read graph proto from binary failed");
- GELOGE(FAILED, "read_proto_from_binary failed.");
- return INTERNAL_ERROR;
- }
-
- domi::tensorflow::GraphDef graph_def;
- const bool is_empty_input = GetParserContext().input_dims.empty() && GetParserContext().out_nodes_map.empty();
- if (is_empty_input) {
- graph_def = OriDef;
- } else {
- GELOGI("Before Trim, the Graph Node size is:%d", OriDef.node_size());
- if (static_cast<bool>(TrimGraph(OriDef, &graph_def))) {
- GELOGE(FAILED, "Trim Graph fail.");
- return INTERNAL_ERROR;
- }
- GELOGI("After Trim, The graph_def.node_size():%d", graph_def.node_size());
- }
-
- GE_RETURN_WITH_LOG_IF_ERROR(ProtoTypePassManager::Instance().Run(&graph_def, domi::TENSORFLOW),
- "Run ProtoType Pass Failed");
-
- shared_ptr<ge::ScopeGraph> scope_graph = nullptr;
- Status ret = ExcuteScopeFusionPasses(&graph_def, scope_graph);
- if (ret != SUCCESS) {
- GELOGE(ret, "[TF ParseFromMemory] scope fusion failed.");
- return ret;
- }
- GELOGD("[TF ParseFromMemory] scope fusion success");
-
- // Add nodedef in the model to prechecker and check the general parameters
- for (int i = 0; i < graph_def.node_size(); i++) {
- const domi::tensorflow::NodeDef &node = graph_def.node(i);
- GE_RETURN_WITH_LOG_IF_ERROR(PreChecker::Instance().AddOp(&node, node.name(), node.op()),
- "Add node_def to PreChecker failed, node name: %s.", node.name().c_str());
- GE_RETURN_WITH_LOG_IF_ERROR(PreChecker::Instance().CheckName(&node), "Check node_def name failed, node name: %s.",
- node.name().c_str());
- if (node.op() != TENSORFLOWF_NODE_OP_IDENTITY) {
- GE_RETURN_WITH_LOG_IF_ERROR(PreChecker::Instance().CheckType(&node, true),
- "Check node_def type failed, node name: %s.", node.name().c_str());
- }
- }
-
- bool has_error = false;
- // save node name
- vector<string> op_node_name_list;
- for (int i = 0; i < graph_def.node_size(); i++) {
- const domi::tensorflow::NodeDef *node_def = graph_def.mutable_node(i);
-
- // If it is a fusion operator, put nodedef in the fusion_op_nodedef_map_
- GE_IF_BOOL_EXEC(MaybeFusionOp(scope_graph, node_def),
- GELOGI("Node: %s maybe a fusion op.", node_def->name().c_str()););
-
- // Do not exit immediately when there is an error, wait until all errors are collected before exiting
- GE_CHK_STATUS_EXEC(AddFmkNodeDefToMap(node_def, op_node_name_list), has_error = true,
- "add node failed.");
- }
-
- // The fusion operator has passed the verification.
- // The errors of internal non key operators (which will be ignored later)
- // do not affect the transformation of the whole model,
- // So clear the error information of non key operators
- // This function call affects the return value of prechecker::instance().Haserror()
- GE_RETURN_IF_ERROR(ClearFusionOpError(op_node_name_list));
-
- // Building input and input relationships for all OP nodes
- GE_RETURN_IF_ERROR(GetOpNodesContextFromGraph(graph_def));
- GELOGD("[TF ParseFromMemory] get op nodes context from graph success");
-
- // Infer input formats
- ge::GetParserContext().format = InferInputFormats();
- GELOGD("[TF ParseFromMemory] infer input formats success");
-
- // Building input-output relationship between fusionop and common op
- GE_RETURN_IF_ERROR(UpdateAllNodeOpContext(scope_graph, op_node_name_list));
-
- ret = AddFusionNodeDef(scope_graph, op_node_name_list);
- if (ret != SUCCESS) {
- GELOGE(ret, "Add fusion NodeDef failed.");
- DeleteFuisonNodeDef();
- return ret;
- }
- GELOGI("TF op node size = %zu.", op_node_name_list.size());
- // Loop analysis of op_nodes and map them to nodes in graph
- for (size_t i = 0; i < op_node_name_list.size(); i++) {
- GELOGI("TF op node name = %s.", op_node_name_list[i].c_str());
- const string op_node_name = op_node_name_list[i];
- const domi::tensorflow::NodeDef *node_def = nodedef_map_[op_node_name_list[i]];
- if (node_def == nullptr) {
- REPORT_INNER_ERROR("E19999", "Node:%s can't find in nodedef_map_, check invalid", op_node_name.c_str());
- GELOGE(INTERNAL_ERROR, "Node def is nullptr, name:%s.", op_node_name.c_str());
- DeleteFuisonNodeDef();
- return INTERNAL_ERROR;
- }
- const string &node_op = node_def->op();
- if (tensorflow_op_map.find(node_op) == tensorflow_op_map.cend()) {
- DeleteFuisonNodeDef();
- REPORT_INNER_ERROR("E19999", "Op type %s unsupport", node_op.c_str());
- GELOGE(FAILED, "Unsupport op type %s", node_op.c_str());
- return INTERNAL_ERROR;
- }
-
- ret = AddNode(node_def, graph, scope_graph);
- if (ret != SUCCESS) {
- GELOGE(ret, "Add node failed, name:%s.", op_node_name.c_str());
- DeleteFuisonNodeDef();
- return ret;
- }
- }
-
- DeleteFuisonNodeDef();
-
- GE_RETURN_IF_ERROR(AddEdges(graph));
- GE_RETURN_IF_ERROR(graph->TopologicalSorting());
-
- has_error = has_error || PreChecker::Instance().HasError();
- if (has_error) {
- GELOGE(PARAM_INVALID, "Precheck has errors.");
- return PARAM_INVALID;
- }
- GELOGI("[TF ParseFromMemory] Parse from memory success.");
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::GetFunctionProto(const string &file,
- domi::tensorflow::GraphDefLibrary &graph_def_library) {
- int pos = file.rfind('/');
- string graph_def_path = (pos == -1) ? kFuncDefLibraryFilePath : file.substr(0, pos) + "/" + kFuncDefLibraryFilePath;
- GELOGI("Function def libraray path is %s.", graph_def_path.c_str());
-
- bool read = ge::parser::ReadProtoFromText(graph_def_path.c_str(), &graph_def_library);
- if (!read) {
- GELOGE(INTERNAL_ERROR,
- "Get subgraph library failed. "
- "The model contains function operators. "
- "Need to use the script func2graph.py in the atc package to save the subgraphs to graph_def_library.pbtxt");
- ErrorManager::GetInstance().ATCReportErrMessage("E12029");
- return FAILED;
- }
-
- GELOGI("Get subgraph library success.");
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::Parse(const char *file, ge::Graph &graph) {
- ErrorManager::GetInstance().SetStage(error_message::kModelCompile, error_message::kParser);
- GE_CHECK_NOTNULL(file);
- ge::ComputeGraphPtr root_graph = ge::GraphUtils::GetComputeGraph(graph);
- GE_CHECK_NOTNULL(root_graph);
-
- Status ret = Parse(file, root_graph);
- if (ret != SUCCESS) {
- GELOGE(ret, "Parser graph %s failed.", ParserUtils::GetGraphName(graph).c_str());
- return ret;
- }
-
- GELOGI("Parser graph %s success.", ParserUtils::GetGraphName(graph).c_str());
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::Parse(const char *model_path, ge::ComputeGraphPtr &root_graph) {
- GE_CHECK_NOTNULL(model_path);
- GE_CHECK_NOTNULL(root_graph);
-
- GELOGI("Parse file %s", model_path);
- // Store objects parsed from pb files
- domi::tensorflow::GraphDef ori_def;
- bool read = ge::parser::ReadProtoFromBinaryFile(model_path, &ori_def);
- if (!read) {
- GELOGE(FAILED, "read tensorflow file failed when the inupt param value of --framework is 3.");
- return INTERNAL_ERROR;
- }
-
- // Trim graph by user input and output.
- domi::tensorflow::GraphDef graph_def;
- if (ge::GetParserContext().input_dims.empty() && ge::GetParserContext().out_nodes_map.empty()) {
- graph_def = ori_def;
- } else {
- GELOGI("Before Trim, the Graph Node size is:%d", ori_def.node_size());
- if (static_cast<bool>(TrimGraph(ori_def, &graph_def))) {
- GELOGE(FAILED, "Trim Graph fail.");
- return INTERNAL_ERROR;
- }
- GELOGI("After Trim, The graph_def.node size is:%d", graph_def.node_size());
- }
-
- // Construct ParseArg for root graph.
- google::protobuf::Message *root_proto = &graph_def;
- std::deque<ParseArg> tasks;
- tasks.push_back({root_proto, "root", nullptr, "", root_graph});
-
- // Get sub graph from graph_def_library.pbtxt which prepared before and stored in model_path.
- std::map<std::string, domi::tensorflow::GraphDef> function_name_to_graphdef;
-
- // Parse all root graph and sub graph.
- while (!tasks.empty()) {
- auto arg = tasks.front();
- tasks.pop_front();
-
- if (arg.proto == nullptr) {
- if (function_name_to_graphdef.empty() && (ori_def.library().function_size() > 0)) {
- GELOGI("Graph has function size: %d ", ori_def.library().function_size());
- domi::tensorflow::GraphDefLibrary graph_def_library;
- GE_CHK_STATUS_RET(GetFunctionProto(model_path, graph_def_library));
- for (auto &ge_graph_def : graph_def_library.graph_def()) {
- function_name_to_graphdef[ge_graph_def.name()] = ge_graph_def.graph();
- GELOGD("Graph_def name: %s, node size: %d", ge_graph_def.name().c_str(), ge_graph_def.graph().node_size());
- }
- }
-
- const std::map<std::string, domi::tensorflow::GraphDef>::const_iterator
- iter = function_name_to_graphdef.find(arg.function_name);
- if (iter == function_name_to_graphdef.end()) {
- ErrorManager::GetInstance().ATCReportErrMessage("E12013", {"functionname"}, {arg.function_name});
- GELOGE(FAILED, "Failed to get subgraph by function name %s", arg.function_name.c_str());
- return FAILED;
- }
- arg.proto = &(iter->second);
- }
-
- GELOGI("Begin to parse graph %s", arg.function_name.c_str());
- auto model_parser = domi::ModelParserFactory::Instance()->CreateModelParser(domi::FrameworkType::TENSORFLOW);
- auto ret = model_parser->ParseAllGraph(arg.proto, arg.graph);
- if (ret != SUCCESS) {
- GELOGE(ret, "Failed to parse graph %s, instance name %s", arg.function_name.c_str(),
- arg.graph->GetName().c_str());
- return ret;
- }
-
- ret = PostOpProcessForSubgraph(arg);
- if (ret != SUCCESS) {
- // the error log has been printed inner the function
- return ret;
- }
-
- ret = GenSubgraphParseTasks(arg.graph, tasks);
- if (ret != SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Failed to gen tasks on graph:%s for next iteration", arg.graph->GetName().c_str());
- GELOGE(ret, "Failed to gen tasks on graph %s for next iteration", arg.graph->GetName().c_str());
- return ret;
- }
- }
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::ParseAllGraph(const google::protobuf::Message *proto, ge::ComputeGraphPtr &graph) {
- ErrorManager::GetInstance().SetStage(error_message::kModelCompile, error_message::kParser);
- GE_CHECK_NOTNULL(proto);
- GE_CHECK_NOTNULL(graph);
-
- const domi::tensorflow::GraphDef *ori_graph =
- ge::PtrToPtr<google::protobuf::Message, domi::tensorflow::GraphDef>(proto);
- // Make a copy for operation without modifying the original graph def.
- domi::tensorflow::GraphDef graph_def = *ori_graph;
-
- GE_RETURN_WITH_LOG_IF_ERROR(ProtoTypePassManager::Instance().Run(&graph_def, domi::TENSORFLOW),
- "Run ProtoType Pass Failed");
-
- shared_ptr<ge::ScopeGraph> scope_graph = nullptr;
- Status ret = ExcuteScopeFusionPasses(&graph_def, scope_graph);
- if (ret != SUCCESS) {
- GELOGE(ret, "[TF Parse] scope fusion failed.");
- return ret;
- }
- GELOGD("[TF Parse] scope fusion success");
-
- GE_RETURN_IF_ERROR(OptimizeConstNodes4CustomOp(&graph_def));
- GELOGD("[TF Parse] optimize const nodes for custom op base success");
-
- // Add nodedef in the model to prechecker and check the general parameters
- // Prevent data residue in multiple calls
- PreChecker::Instance().Clear();
- for (int i = 0; i < graph_def.node_size(); i++) {
- const domi::tensorflow::NodeDef &node = graph_def.node(i);
- GE_RETURN_WITH_LOG_IF_ERROR(PreChecker::Instance().AddOp(&node, node.name(), node.op()),
- "Add node_def to PreChecker failed, node name: %s.", node.name().c_str());
-
- if (PreChecker::Instance().CheckName(&node) != SUCCESS) {
- GELOGE(FAILED, "Check op[%s] failed, name repeat in tensorflow pb file.", node.name().c_str());
- return FAILED;
- }
- if (node.op() != TENSORFLOWF_NODE_OP_IDENTITY) {
- if (PreChecker::Instance().CheckType(&node, true) != SUCCESS) {
- GELOGE(FAILED, "Check op[%s]'s optype failed, type is not supported.", node.name().c_str());
- return FAILED;
- }
- }
- }
-
- bool has_error = false;
- // save node name
- vector<string> op_node_name_list;
- for (int i = 0; i < graph_def.node_size(); i++) {
- const domi::tensorflow::NodeDef *node_def = graph_def.mutable_node(i);
-
- // If it is a fusion operator, put nodedef in the fusion_op_nodedef_map_
- if (MaybeFusionOp(scope_graph, node_def)) {
- GELOGI("Node: %s maybe a fusion op.", node_def->name().c_str());
- }
-
- // Do not exit immediately when there is an error, wait until all errors are collected before exiting
- GE_CHK_STATUS_EXEC(AddFmkNodeDefToMap(node_def, op_node_name_list), has_error = true);
- }
-
- // The fusion operator has passed the verification.
- // The errors of internal non key operators (which will be ignored later)
- // do not affect the transformation of the whole model,
- // So clear the error information of non key operators
- // This function call affects the return value of prechecker::instance().Haserror()
- GE_RETURN_IF_ERROR(ClearFusionOpError(op_node_name_list));
-
- // Building input and input relationships for all OP nodes
- GE_RETURN_IF_ERROR(GetOpNodesContextFromGraph(graph_def));
- GELOGD("[TF Parse] get op nodes context from graph success");
-
- // Infer input formats
- ge::GetParserContext().format = InferInputFormats();
- GELOGD("[TF Parse] infer input formats success");
-
- // Building input-output relationship between fusionop and common op
- GE_RETURN_IF_ERROR(UpdateAllNodeOpContext(scope_graph, op_node_name_list));
- GELOGD("[TF Parse] update all node op context success");
-
- // set user-designate-inputs-order
- std::vector<std::string> user_inputs_order;
- for (auto &input : ge::GetParserContext().user_input_dims) {
- user_inputs_order.push_back(input.first);
- }
- graph->SetInputsOrder(user_inputs_order);
-
- ret = AddFusionNodeDef(scope_graph, op_node_name_list);
- if (ret != SUCCESS) {
- GELOGE(ret, "Add fusion NodeDef failed.");
- DeleteFuisonNodeDef();
- return ret;
- }
- GELOGI("TF op node size = %zu.", op_node_name_list.size());
-
- // Loop analysis of op_nodes and map them to nodes in graph
- for (size_t i = 0; i < op_node_name_list.size(); i++) {
- GELOGI("TF op node name = %s.", op_node_name_list[i].c_str());
- const string op_node_name = op_node_name_list[i];
- const domi::tensorflow::NodeDef *node_def = nodedef_map_[op_node_name_list[i]];
- if (node_def == nullptr) {
- REPORT_INNER_ERROR("E19999", "Node:%s can't find in nodedef_map_, check invalid", op_node_name.c_str());
- GELOGE(INTERNAL_ERROR, "Cannot find [%s] in nodedef map.", op_node_name_list[i].c_str());
- DeleteFuisonNodeDef();
- return INTERNAL_ERROR;
- }
- const string &node_op = node_def->op();
-
- if (tensorflow_op_map.find(node_op) == tensorflow_op_map.end()) {
- GELOGW("%s not found in tensorflow_op_map.", node_op.c_str());
- }
- ret = AddNode(node_def, graph, scope_graph);
- if (ret != SUCCESS) {
- GELOGE(ret, "Add op[%s] failed", node_def->name().c_str());
- DeleteFuisonNodeDef();
- return ret;
- }
- }
-
- GELOGD("[TF Parse] parse tf node to geop success");
-
- DeleteFuisonNodeDef();
-
- GE_RETURN_IF_ERROR(AddEdges(graph));
- Graph dest_graph = GraphUtils::CreateGraphFromComputeGraph(graph);
- ParserUtils::OutputMapping final_output_nodes;
- GE_RETURN_IF_ERROR(ParserUtils::ExpandOneToManyGraph(dest_graph, final_output_nodes));
- GE_RETURN_IF_ERROR(UpdateOutputsInfo(final_output_nodes));
- GE_RETURN_IF_ERROR(RemoveIsolateNode(graph));
- GE_RETURN_IF_ERROR(CheckAndUpdateInputDesc(graph));
- GE_RETURN_IF_ERROR(graph->TopologicalSorting());
-
- if (has_error) {
- GELOGE(PARAM_INVALID, "Precheck has errors.");
- return PARAM_INVALID;
- }
- GELOGI("[TF Parser] Parse proto success.");
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::GetOpNodesContextFromGraph(const domi::tensorflow::GraphDef &graph_def) {
- // Build the input relationship first
- for (auto &iter : op_node_context_map_) {
- map<string, std::vector<std::pair<int32_t, int32_t>>> input_map;
- const string &op_node_name = iter.first;
- GE_RETURN_IF_ERROR(GetOpNodeInputMap(op_node_name, input_map));
-
- OpNodeContext &op_node_context = iter.second;
- op_node_context.input_map = input_map;
- }
-
- // Then build the output relationship
- GE_RETURN_IF_ERROR(GetOpNodeOutputMap(graph_def));
-
- return SUCCESS;
- }
-
- // Get the input relation of opnode includeing input_op and input_const
- Status TensorFlowModelParser::GetOpNodeInputMap(const string &op_node_name,
- map<string, std::vector<std::pair<int32_t, int32_t>>> &input_map) {
- // Get the current nodedef according to the node_name
- const domi::tensorflow::NodeDef *node_def = nodedef_map_[op_node_name];
- GE_CHECK_NOTNULL(node_def);
- int32_t input_index = 0;
- int32_t output_index = 0;
- for (const string &input_node_name : node_def->input()) {
- GELOGD("Get Op InputMap, node_name : %s, input node:%s", node_def->name().c_str(), input_node_name.c_str());
- string tmp_node_name;
- bool control = false;
- GE_RETURN_IF_ERROR(CheckInputNodeName(input_node_name, &tmp_node_name, &output_index, &control));
- input_map[tmp_node_name].push_back({output_index, control ? kControlSlot : input_index});
- SaveEdgesControlInfo(node_def->name(), control);
- input_index = control ? input_index : input_index + 1;
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::GetOpNodeOutputMap(const domi::tensorflow::GraphDef &graph_def) {
- // Loop through all nodes in graphdef
- for (const domi::tensorflow::NodeDef &node_def : graph_def.node()) {
- auto currentIter = op_node_context_map_.find(node_def.name());
- if (currentIter != op_node_context_map_.end()) {
- OpNodeContext &op_node_context = currentIter->second;
- // Find all input nodes of the current node
- for (auto &inputIter : op_node_context.input_map) {
- auto iter = op_node_context_map_.find(inputIter.first);
- if (iter != op_node_context_map_.end()) {
- std::vector<std::pair<int32_t, int32_t>> inputpairs = inputIter.second;
- OpNodeContext &op_node_context1 = iter->second;
- op_node_context1.output_map[node_def.name()].assign(inputpairs.begin(), inputpairs.end());
- }
- }
- }
- }
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::GeStoi(const string &input_node_name, const string &index_str, int32_t *index) {
- try {
- int32_t tmp_index = static_cast<int32_t>(std::stoi(index_str.c_str(), nullptr, 10));
- *index = tmp_index;
- } catch (std::invalid_argument &) {
- ErrorManager::GetInstance().ATCReportErrMessage("E10014", {"parameter", "value"},
- {"input_node_name(" + input_node_name + ")", index_str});
- GELOGE(INTERNAL_ERROR, "stl[stoi] input_node_name[%s] indexstr[%s] is invalid argument!", input_node_name.c_str(),
- index_str.c_str());
- return INTERNAL_ERROR;
- } catch (std::out_of_range &) {
- ErrorManager::GetInstance().ATCReportErrMessage("E10013", {"parameter", "value"},
- {"input_node_name(" + input_node_name + ")", index_str});
- GELOGE(INTERNAL_ERROR, "stl[stoi] input_node_name[%s] indexstr[%s] is out of range!", input_node_name.c_str(),
- index_str.c_str());
- return INTERNAL_ERROR;
- } catch (...) {
- ErrorManager::GetInstance().ATCReportErrMessage("E10015", {"parameter", "value"},
- {"input_node_name(" + input_node_name + ")", index_str});
- GELOGE(INTERNAL_ERROR, "stl[stoi] input_node_name[%s] indexstr[%s] is bad argument!", input_node_name.c_str(),
- index_str.c_str());
- return INTERNAL_ERROR;
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::CheckInputNodeName(const string &input_node_name, string *node_name, int32_t *index,
- bool *control) {
- // Processing scene: input: "^fastrcnn_predictions/map/while/Identity""
- string tmp_input_node_name = input_node_name;
- if (tmp_input_node_name.find("^") == 0) {
- tmp_input_node_name = tmp_input_node_name.substr(1, tmp_input_node_name.length() - 1);
- if (control != nullptr) {
- *control = true;
- }
- } else {
- if (control != nullptr) {
- *control = false;
- }
- }
-
- auto find = tmp_input_node_name.find(":");
- if (find == string::npos) {
- *node_name = tmp_input_node_name;
-
- if (index == nullptr) {
- return SUCCESS;
- }
- *index = 0;
-
- return SUCCESS;
- }
-
- string indexstr = tmp_input_node_name.substr(find + 1, tmp_input_node_name.length() - find - 1);
- *node_name = tmp_input_node_name.substr(0, find);
-
- if (index == nullptr) {
- return SUCCESS;
- }
-
- if (GeStoi(input_node_name, indexstr, index) != SUCCESS) {
- return INTERNAL_ERROR;
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::RunScopeFusionPass(const vector<string> &scope_passes_list,
- ScopePassManager &pass_manager,
- shared_ptr<ge::ScopeGraph> &scope_graph) {
- if (scope_passes_list.empty()) {
- return SUCCESS;
- }
- GE_CHECK_NOTNULL(scope_graph);
- auto &impl = ge::ScopeFusionPassRegistry::GetInstance().impl_;
- if (impl == nullptr) {
- REPORT_INNER_ERROR("E19999", "ScopeFusionPassRegistry is not properly initialized.");
- GELOGE(ge::MEMALLOC_FAILED, "ScopeFusionPassRegistry is not properly initialized.");
- return ge::MEMALLOC_FAILED;
- }
-
- for (auto &pass_name : scope_passes_list) {
- auto pass = impl->CreateScopeFusionPass(pass_name);
- if (pass == nullptr) {
- REPORT_INNER_ERROR("E19999", "Scope fusion pass[%s] is not registered.", pass_name.c_str());
- GELOGE(INTERNAL_ERROR, "Scope fusion pass[%s] is not registered.", pass_name.c_str());
- return INTERNAL_ERROR;
- }
- Status ret = pass_manager.AddPass(pass);
- if (ret != SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Add scope fusion pass[%s] failed.", pass_name.c_str());
- GELOGE(INTERNAL_ERROR, "Add scope fusion pass[%s] failed.", pass_name.c_str());
- return INTERNAL_ERROR;
- }
- }
- Status ret = pass_manager.Run(scope_graph);
- if (ret != SUCCESS && ret != domi::SCOPE_NOT_CHANGED) {
- GELOGE(FAILED, "Run scope fusion pass failed, ret:%u.", ret);
- return FAILED;
- }
- return SUCCESS;
- }
-
- bool TensorFlowModelParser::MaybeFusionOp(shared_ptr<ge::ScopeGraph> &scope_graph,
- const domi::tensorflow::NodeDef *node_def) {
- GE_CHECK_NOTNULL(scope_graph);
- GE_CHECK_NOTNULL(node_def);
- // If it is a fusion operator, put nodedef in the fusion_op_nodedef_map_
- ge::ScopeFusionOpInfo info;
- std::vector<ge::ScopeFusionOpInfo> info_list;
- auto &impl = scope_graph->impl_;
- if (impl->IsFusionOpChild(node_def->name(), info_list)) {
- GE_IF_BOOL_EXEC(info_list.size() > 0,
- for (size_t i = 0; i < info_list.size(); ++i) {
- fusion_op_type_map_[info_list[i].fusion_node_name].push_back(info_list[i].fusion_op_type);
- fusion_op_type_map_[info_list[i].fusion_node_name].push_back(info_list[i].description);
- fusion_op_nodedef_map_[info_list[i].fusion_node_name].push_back(node_def);
- if (info_list[i].fusion_op_type == "Dropout" &&
- (node_def->op() == "Add" || node_def->op() == "RandomUniform")) {
- fusion_op_nodedef_map_[info_list[i].fusion_node_name].push_back(nodedef_map_[node_def->input(0)]);
- }
- if (info_list[i].fusion_op_type == "LayerNorm" && node_def->op() == "Mean") {
- fusion_op_nodedef_map_[info_list[i].fusion_node_name].push_back(nodedef_map_[node_def->input(1)]);
- }
- fusion_op_policy_[info_list[i].fusion_node_name] = info_list[i].scope_pass;
- fusion_op_children_[node_def->name()] = info_list[i];
- });
- GE_IF_BOOL_EXEC(info_list.size() == 0, fusion_op_type_map_[info.fusion_node_name].push_back(info.fusion_op_type);
- fusion_op_type_map_[info.fusion_node_name].push_back(info.description);
- fusion_op_nodedef_map_[info.fusion_node_name].push_back(node_def);
- fusion_op_policy_[info.fusion_node_name] = info.scope_pass;
- fusion_op_children_[node_def->name()] = info);
-
- return true;
- }
-
- return false;
- }
-
- bool TensorFlowModelParser::IsFusionOpChild(const string &node_name, ge::ScopeFusionOpInfo *info) {
- GE_CHK_BOOL_EXEC(info != nullptr, REPORT_CALL_ERROR("E19999", "Param info is nullptr, check invalid");
- return false, "fusion info is null.");
- // 1.View in full match fusion strategy first
- // 2.View in scope fusion policy then
- auto iter = fusion_op_children_.find(node_name);
- if (iter != fusion_op_children_.end()) {
- info->node_name = fusion_op_children_[node_name].node_name;
- info->fusion_node_name = fusion_op_children_[node_name].fusion_node_name;
- info->fusion_op_type = fusion_op_children_[node_name].fusion_op_type;
- info->description = fusion_op_children_[node_name].description;
- info->scope_pass = fusion_op_children_[node_name].scope_pass;
-
- return true;
- }
-
- return false;
- }
-
- bool TensorFlowModelParser::FusionOpChildIgnore(const shared_ptr<ge::ScopeGraph> &scope_graph,
- const ge::ScopeFusionOpInfo &info) {
- GE_CHECK_NOTNULL(scope_graph);
- bool ignore = false;
- if (info.scope_pass) {
- // Scope fusion strategy
- auto &impl = scope_graph->impl_;
- ignore = impl->FusionOpChildIgnore(info);
- }
- return ignore;
- }
-
- bool TensorFlowModelParser::IsFusionOp(const shared_ptr<ge::ScopeGraph> &scope_graph,
- const domi::tensorflow::NodeDef *node_def) {
- // The caller guarantees that the pointer is not null
- auto &impl = scope_graph->impl_;
- return (impl->IsFusionOp(node_def));
- }
- Status TensorFlowModelParser::GetInPutIndex(shared_ptr<ge::ScopeGraph> &scope_graph, const ge::ScopeFusionOpInfo &info,
- const int32_t old_index, int32_t &new_index) {
- GE_CHECK_NOTNULL(scope_graph);
- if (info.scope_pass) {
- auto &impl = scope_graph->impl_;
- return impl->GetInputOrOutputIndex(info, old_index, true, new_index);
- }
- GELOGE(INTERNAL_ERROR, "Fusion op should come from scope fusion pass, node name:%s, fusion node name:%s",
- info.node_name.c_str(), info.fusion_node_name.c_str());
- return INTERNAL_ERROR;
- }
- Status TensorFlowModelParser::GetOutPutIndex(shared_ptr<ge::ScopeGraph> &scope_graph, const ge::ScopeFusionOpInfo &info,
- const int32_t old_index, int32_t &new_index) {
- GE_CHECK_NOTNULL(scope_graph);
- if (info.scope_pass) {
- auto &impl = scope_graph->impl_;
- return impl->GetInputOrOutputIndex(info, old_index, false, new_index);
- }
- GELOGE(INTERNAL_ERROR, "Fusion op should come from scope fusion pass, node name:%s, fusion node name:%s",
- info.node_name.c_str(), info.fusion_node_name.c_str());
- return INTERNAL_ERROR;
- }
-
- bool TensorFlowModelParser::ConstOpNeedUpdate(const string &op_name) {
- if (nodedef_map_[op_name]->op() != TENSORFLOWF_NODE_OP_CONST) {
- // Normal op need to update
- return true;
- } else {
- auto iter = op_node_context_map_.find(op_name);
- if (iter != op_node_context_map_.end()) {
- ge::ScopeFusionOpInfo info;
- auto outmap = iter->second.output_map;
- for (auto &out_node : outmap) {
- // if the const op output connected to are all fusion ops and the cosnt op is not in the update vector
- if (!IsFusionOpChild(out_node.first, &info)) {
- return true;
- }
- }
- }
- return true;
- }
- }
-
- Status TensorFlowModelParser::UpdateAllNodeOpContext(shared_ptr<ge::ScopeGraph> &scope_graph,
- vector<string> &op_node_name_list) {
- GE_CHECK_NOTNULL(scope_graph);
- vector<string> tmp_op_node_name_list;
- map<string, OpNodeContext> tmp_fusion_op_node_context_map;
-
- for (auto &op_node_name : op_node_name_list) {
- auto iter = op_node_context_map_.find(op_node_name);
- if (iter != op_node_context_map_.end()) {
- ge::ScopeFusionOpInfo info;
- if (IsFusionOpChild(op_node_name, &info) && nodedef_map_[op_node_name]->op() != TENSORFLOWF_NODE_OP_CONST) {
- // This node is a fusion operator
- const std::map<std::string, OpNodeContext>::const_iterator
- fusion_iter = tmp_fusion_op_node_context_map.find(info.fusion_node_name);
- if (fusion_iter == tmp_fusion_op_node_context_map.end()) {
- OpNodeContext op_node_context;
- tmp_fusion_op_node_context_map[info.fusion_node_name] = op_node_context;
- tmp_op_node_name_list.push_back(info.fusion_node_name);
- }
-
- OpNodeContext &fusion_op_node_context = tmp_fusion_op_node_context_map[info.fusion_node_name];
- OpNodeContext &normal_op_node_context = op_node_context_map_[op_node_name];
- GE_RETURN_IF_ERROR(UpdateFusionOpContext(scope_graph, info, fusion_op_node_context, normal_op_node_context));
-
- // Delete fusion operator context
- op_node_context_map_.erase(iter);
- } else {
- // This node is a common operator
- OpNodeContext &normal_op_node_context = op_node_context_map_[op_node_name];
- GE_RETURN_IF_ERROR(UpdateNormalOpContext(scope_graph, op_node_name, normal_op_node_context));
- tmp_op_node_name_list.push_back(op_node_name);
- }
- }
- }
-
- // update op_node_name_list
- op_node_name_list.clear();
- op_node_name_list.assign(tmp_op_node_name_list.begin(), tmp_op_node_name_list.end());
-
- // update op_node_context_map_
- for (const auto &iter : tmp_fusion_op_node_context_map) {
- op_node_context_map_[iter.first] = iter.second;
- }
- // Normalized context
- GE_RETURN_IF_ERROR(NormalizeAllNodeOpContext());
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::UpdateFusionOpContext(shared_ptr<ge::ScopeGraph> &scope_graph,
- const ge::ScopeFusionOpInfo &info,
- OpNodeContext &fusion_op_node_context,
- OpNodeContext &normal_op_node_context) {
- GE_CHECK_NOTNULL(scope_graph);
- if (FusionOpChildIgnore(scope_graph, info)) {
- // The inner children operators of the fusion operator can be ignored directly
- // if they do not establish the edge relationship with other outer ordinary / fusion operators
- return SUCCESS;
- }
-
- GE_CHK_STATUS_RET(UppdateInputMap(scope_graph, info, fusion_op_node_context, normal_op_node_context),
- "UppdateInputMap ret fail");
- GE_CHK_STATUS_RET(UppdateOutputMap(scope_graph, info, fusion_op_node_context, normal_op_node_context),
- "UppdateOutputMap ret fail");
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::UppdateInputMap(shared_ptr<ge::ScopeGraph> &scope_graph,
- const ge::ScopeFusionOpInfo &info, OpNodeContext &fusion_op_node_context,
- OpNodeContext &normal_op_node_context) {
- GE_CHECK_NOTNULL(scope_graph);
- for (auto &iter : normal_op_node_context.input_map) {
- string input_node_name = iter.first;
- std::vector<std::pair<int32_t, int32_t>> &pairs = iter.second;
- ge::ScopeFusionOpInfo from_info;
- int32_t from_index = 0;
- int32_t to_index = 0;
- if (!ConstOpNeedUpdate(input_node_name)) {
- GELOGI("%s is const node connected to a fusion child, ignore", input_node_name.c_str());
- continue;
- }
- if (IsFusionOpChild(input_node_name, &from_info)) {
- if (info.fusion_node_name == from_info.fusion_node_name) {
- // Ignore two sub operators in the same fusion operator
- continue;
- }
-
- for (auto &pair : pairs) {
- GE_RETURN_WITH_LOG_IF_ERROR(GetOutPutIndex(scope_graph, from_info, pair.first, from_index),
- "GetOutPutIndex failed ,input_node_name %s.", input_node_name.c_str());
- GE_RETURN_WITH_LOG_IF_ERROR(GetInPutIndex(scope_graph, info, pair.second, to_index),
- "GetInPutIndex failed ,input_node_name %s.", input_node_name.c_str());
- fusion_op_node_context.input_map[from_info.fusion_node_name].push_back({from_index, to_index});
- UpdateEdgesControlInfo(info);
- GELOGD("[Update op context] update fusion input map for fusion input, %s:%d TO %s:%d",
- from_info.fusion_node_name.c_str(), from_index, info.fusion_node_name.c_str(), to_index);
- }
- } else {
- for (auto &pair : pairs) {
- from_index = pair.first;
- GE_RETURN_WITH_LOG_IF_ERROR(GetInPutIndex(scope_graph, info, pair.second, to_index),
- "GetInPutIndex input_node_name %s.", input_node_name.c_str());
- fusion_op_node_context.input_map[input_node_name].push_back({from_index, to_index});
- UpdateEdgesControlInfo(info);
- GELOGD("[Update op context] update fusion input map for normal input, %s:%d TO %s:%d",
- input_node_name.c_str(), from_index, info.fusion_node_name.c_str(), to_index);
- }
- }
- }
- return SUCCESS;
- }
- Status TensorFlowModelParser::UppdateOutputMap(shared_ptr<ge::ScopeGraph> &scope_graph,
- const ge::ScopeFusionOpInfo &info, OpNodeContext &fusion_op_node_context,
- OpNodeContext &normal_op_node_context) {
- GE_CHECK_NOTNULL(scope_graph);
- for (auto &iter : normal_op_node_context.output_map) {
- string output_node_name = iter.first;
- std::vector<std::pair<int32_t, int32_t>> &pairs = iter.second;
- ge::ScopeFusionOpInfo to_info;
- int32_t from_index = 0;
- int32_t to_index = 0;
- if (IsFusionOpChild(output_node_name, &to_info)) {
- if (info.fusion_node_name == to_info.fusion_node_name) {
- // Ignore two sub operators in the same fusion operator
- continue;
- }
- for (auto &pair : pairs) {
- GE_RETURN_WITH_LOG_IF_ERROR(GetOutPutIndex(scope_graph, info, pair.first, from_index),
- "fusion GetOutPutIndex failed ,output_node_name %s.", output_node_name.c_str());
- GE_RETURN_WITH_LOG_IF_ERROR(GetInPutIndex(scope_graph, to_info, pair.second, to_index),
- "fusion GetInPutIndex failed ,output_node_name %s.", output_node_name.c_str());
- fusion_op_node_context.output_map[to_info.fusion_node_name].push_back({from_index, to_index});
- GELOGD("[Update op context] update fusion output map for fusion output, %s:%d TO %s:%d",
- info.fusion_node_name.c_str(), from_index, to_info.fusion_node_name.c_str(), to_index);
- }
- } else {
- for (auto &pair : pairs) {
- to_index = pair.second;
- GE_RETURN_WITH_LOG_IF_ERROR(GetOutPutIndex(scope_graph, info, pair.first, from_index),
- "not fusion,GetOutPutIndex failed ,output_node_name %s.", output_node_name.c_str());
- fusion_op_node_context.output_map[output_node_name].push_back({from_index, to_index});
- GELOGD("[Update op context] update fusion output map for normal output, %s:%d TO %s:%d",
- info.fusion_node_name.c_str(), from_index, output_node_name.c_str(), to_index);
- }
- }
- }
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::EraseNormalOpOutputIfChild(shared_ptr<ge::ScopeGraph> &scope_graph,
- const string &op_node_name,
- OpNodeContext &normal_op_node_context) {
- std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> tmp_output_map;
- for (auto iter = normal_op_node_context.output_map.begin(); iter != normal_op_node_context.output_map.end();) {
- string output_node_name = iter->first;
- ge::ScopeFusionOpInfo to_info;
- if (IsFusionOpChild(output_node_name, &to_info) &&
- nodedef_map_[output_node_name]->op() != TENSORFLOWF_NODE_OP_CONST) {
- // Fuse operator, update index
- std::vector<std::pair<int32_t, int32_t>> &pairs = iter->second;
- int32_t to_index = 0;
- for (auto &pair : pairs) {
- int32_t from_index = pair.first;
- GE_RETURN_WITH_LOG_IF_ERROR(GetInPutIndex(scope_graph, to_info, pair.second, to_index),
- "GetInPutIndex failed ,output_node_name %s.", output_node_name.c_str());
- tmp_output_map[to_info.fusion_node_name].push_back({from_index, to_index});
- GELOGD("[Update op context] update normal output map for fusion output, %s:%d TO %s:%d", op_node_name.c_str(),
- from_index, to_info.fusion_node_name.c_str(), to_index);
- }
-
- iter = normal_op_node_context.output_map.erase(iter);
- } else {
- iter++;
- }
- }
-
- for (auto &iter : tmp_output_map) {
- normal_op_node_context.output_map[iter.first] = iter.second;
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::UpdateNormalOpContext(shared_ptr<ge::ScopeGraph> &scope_graph, const string &op_node_name,
- OpNodeContext &normal_op_node_context) {
- GE_CHECK_NOTNULL(scope_graph);
- std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> tmp_input_map;
-
- for (auto iter = normal_op_node_context.input_map.begin(); iter != normal_op_node_context.input_map.end();) {
- string input_node_name = iter->first;
- ge::ScopeFusionOpInfo from_info;
- if (IsFusionOpChild(input_node_name, &from_info) &&
- nodedef_map_[input_node_name]->op() != TENSORFLOWF_NODE_OP_CONST) {
- // Fuse operator, update index
- std::vector<std::pair<int32_t, int32_t>> &pairs = iter->second;
- int32_t from_index = 0;
- for (auto &pair : pairs) {
- int32_t to_index = pair.second;
- GE_RETURN_WITH_LOG_IF_ERROR(GetOutPutIndex(scope_graph, from_info, pair.first, from_index),
- "GetOutPutIndex failed ,input_node_name %s.", input_node_name.c_str());
- tmp_input_map[from_info.fusion_node_name].push_back({from_index, to_index});
- GELOGD("[Update op context] update normal input map for fusion input, %s:%d TO %s:%d",
- from_info.fusion_node_name.c_str(), from_index, op_node_name.c_str(), to_index);
- }
-
- iter = normal_op_node_context.input_map.erase(iter);
- } else {
- iter++;
- }
- }
-
- Status ret = EraseNormalOpOutputIfChild(scope_graph, op_node_name, normal_op_node_context);
- if (ret != SUCCESS) {
- return ret;
- }
-
- for (auto &iter : tmp_input_map) {
- normal_op_node_context.input_map[iter.first] = iter.second;
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::NormalizeAllNodeOpContext() {
- for (auto iter = op_node_context_map_.begin(); iter != op_node_context_map_.end();) {
- OpNodeContext &context = iter->second;
- NormalizeInputOrOutputMap(iter->first, context.input_map);
- NormalizeInputOrOutputMap(iter->first, context.output_map);
-
- if ((context.input_map.size() == 0) && (context.output_map.size() == 0)) {
- GELOGD("[Update op context] node: %s will be removed at the back.", iter->first.c_str());
- iter = op_node_context_map_.erase(iter);
- } else {
- iter++;
- }
- }
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::NormalizeInputOrOutputMap(
- const string &node_name, std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> &context_map) {
- if (context_map.empty()) {
- return SUCCESS;
- }
-
- for (auto iter = context_map.begin(); iter != context_map.end();) {
- std::vector<std::pair<int32_t, int32_t>> &pairs = iter->second;
- std::vector<std::pair<int32_t, int32_t>> temp_pairs;
- std::set<std::string> compare_set;
-
- for (auto &pair : pairs) {
- bool is_fusion_child = (fusion_op_children_.find(node_name) != fusion_op_children_.cend()) ||
- (fusion_op_children_.find(iter->first) != fusion_op_children_.cend());
- bool is_fusion_op = (fusion_op_type_map_.find(node_name) != fusion_op_type_map_.cend()) ||
- (fusion_op_type_map_.find(iter->first) != fusion_op_type_map_.cend());
- if (((pair.first == ge::kFusionDisableIndex) || (pair.second == ge::kFusionDisableIndex)) &&
- (is_fusion_child || is_fusion_op)) {
- // The edge will be cut off at the back, ignoring
- continue;
- }
-
- string name = to_string(pair.first) + ":" + to_string(pair.second);
- const std::set<std::string>::const_iterator compare_iter = compare_set.find(name);
- if (compare_iter != compare_set.end()) {
- // pair<from,to> repeat, ignore
- continue;
- }
-
- temp_pairs.push_back(pair);
- compare_set.insert(name);
- }
-
- if (temp_pairs.empty()) {
- // If there is no pair, the context can be deleted
- iter = context_map.erase(iter);
- continue;
- } else {
- iter++;
- }
-
- pairs.clear();
- pairs.assign(temp_pairs.begin(), temp_pairs.end());
- }
-
- return SUCCESS;
- }
-
- void TensorFlowModelParser::DeleteFuisonNodeDef() {
- for (auto &fusion_nodedef : fusion_nodedef_list) {
- GE_DELETE_NEW_SINGLE(fusion_nodedef);
- }
- }
-
- void TensorFlowModelParser::SaveEdgesControlInfo(const string &node_name, const bool control) {
- if (control) {
- // If the control attribute is true, save the control attribute to edges_control_map
- edges_control_map[node_name].push_back(kControlSlot);
- }
- }
-
- void TensorFlowModelParser::UpdateEdgesControlInfo(const ge::ScopeFusionOpInfo &info) {
- const std::map<std::string, std::vector<int32_t>>::const_iterator iter = edges_control_map.find(info.node_name);
- if (iter != edges_control_map.end()) {
- // Delete the original fusion operator node information and add the fusion operator control edge information
- edges_control_map.erase(iter);
- edges_control_map[info.fusion_node_name].push_back(kControlSlot);
- }
- }
-
- bool TensorFlowModelParser::GetEdgesControlInfo(const string &node_name, const int32_t index) const {
- // If the node name is included, then confirm whether the index is the same
- auto iter = edges_control_map.find(node_name);
- if (iter != edges_control_map.end()) {
- for (auto &i : iter->second) {
- if (i == index) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- Status TensorFlowModelParser::ClearFusionOpError(const vector<string> &op_node_name_list) {
- for (const auto &name : op_node_name_list) {
- ge::ScopeFusionOpInfo info;
- if (IsFusionOpChild(name, &info)) {
- const NodeDef *node = nodedef_map_[name];
- GE_CHECK_NOTNULL(node);
- GE_RETURN_WITH_LOG_IF_ERROR(PreChecker::Instance().Clear(node, "fused and removed."),
- "Clear pre-checking for node %s failed.", node->name().c_str());
- }
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::ToJson(const char *model_file, const char *json_file) {
- GE_CHK_BOOL_RET_STATUS(model_file != nullptr, FAILED, "model_file is nullptr.");
- GE_CHK_BOOL_RET_STATUS(json_file != nullptr, FAILED, "json_file is nullptr.");
- domi::tensorflow::GraphDef graph_def;
- nlohmann::json j;
-
- GE_RETURN_WITH_LOG_IF_FALSE(ge::parser::ReadProtoFromBinaryFile(model_file, &graph_def),
- "ReadProtoFromBinaryFile failed, file:%s.", model_file);
-
- Pb2Json::Message2Json(graph_def, kTfBlackFields, j, true);
- return ModelSaver::SaveJsonToFile(json_file, j);
- }
-
- Status TensorFlowWeightsParser::ParseFromMemory(const char *data, uint32_t size, ge::ComputeGraphPtr &graph) {
- (void)data;
- (void)size;
- (void)graph;
- return SUCCESS;
- }
-
- Status TensorFlowWeightsParser::Parse(const char *file, ge::Graph &graph) {
- (void)file;
- (void)graph;
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::ParseProto(const google::protobuf::Message *proto, ge::ComputeGraphPtr &graph) {
- ErrorManager::GetInstance().SetStage(error_message::kModelCompile, error_message::kParser);
- ErrorManager::GetInstance().GenWorkStreamIdDefault();
- PARSER_TIMESTAMP_START(ParseProto);
- GE_CHECK_NOTNULL(proto);
- GE_CHECK_NOTNULL(graph);
- ge::GetParserContext().train_flag = true;
-
- const domi::tensorflow::GraphDef *graph_def_in =
- ge::PtrToPtr<google::protobuf::Message, domi::tensorflow::GraphDef>(proto);
- // Make a copy for operation without modifying the original graph def.
- domi::tensorflow::GraphDef graph_def_operation = *graph_def_in;
- domi::tensorflow::GraphDef *graph_def = &graph_def_operation;
-
- GE_RETURN_WITH_LOG_IF_ERROR(ProtoTypePassManager::Instance().Run(graph_def, domi::TENSORFLOW),
- "Run ProtoType Pass Failed");
-
- shared_ptr<ge::ScopeGraph> scope_graph = nullptr;
- Status ret = ExcuteScopeFusionPasses(graph_def, scope_graph);
- if (ret != SUCCESS) {
- GELOGE(ret, "[TF Parser] scope fusion failed.");
- return ret;
- }
- GELOGD("[TF Parser] scope fusion success");
-
- bool has_error = false;
-
- // Graphdef optimizes identity
- PARSER_TIMESTAMP_START(GraphDefOptimize);
- GE_RETURN_IF_ERROR(GraphDefOptimize(graph_def));
- PARSER_TIMESTAMP_END(GraphDefOptimize, "TensorFlowModelParser::GraphDefOptimize");
- GELOGD("[TF Parser] graph def optimize success");
-
- // Optimization for TVM operator
- PARSER_TIMESTAMP_START(OptimizeConstNodes4CustomOp);
- GE_RETURN_IF_ERROR(OptimizeConstNodes4CustomOp(graph_def));
- PARSER_TIMESTAMP_END(OptimizeConstNodes4CustomOp, "TensorFlowModelParser::OptimizeConstNodes4CustomOp");
- GELOGD("[TF Parser] optimize const nodes for custom op success");
-
- GE_RETURN_IF_ERROR(GetTensorflowGraphInOutMap(graph_def));
- GE_RETURN_IF_ERROR(RemoveIsolateNode(graph_def));
-
- vector<string> op_node_name_list;
- bool isDatasetInit = false;
- PARSER_TIMESTAMP_START(AddFmkNodeDefToMap);
- for (int i = 0; i < graph_def->node_size(); i++) {
- const domi::tensorflow::NodeDef *node_def = graph_def->mutable_node(i);
- if (node_def->op() == ge::parser::IDENTITY && node_def->input_size() == 0) {
- continue;
- }
- if (node_def->op() == ge::parser::SNAPSHOT && node_def->input_size() == 0) {
- continue;
- }
- GE_IF_BOOL_EXEC(node_def->op() == "MakeIterator", isDatasetInit = true);
-
- // If it is a fusion operator, put nodedef in the fusion_op_nodedef_map_
- if (MaybeFusionOp(scope_graph, node_def)) {
- GELOGI("Node: %s maybe a fusion op.", node_def->name().c_str());
- }
-
- // Do not exit immediately when there is an error, wait until all errors are collected before exiting
- ret = AddFmkNodeDefToMap(node_def, op_node_name_list);
- GE_CHK_STATUS_EXEC(ret, return PARAM_INVALID, "add node_def to map failed");
- }
- PARSER_TIMESTAMP_END(AddFmkNodeDefToMap, "TensorFlowModelParser::AddFmkNodeDefToMap");
- GELOGI("[TF Parser] TF subgraph isDatasetInit: %d.", isDatasetInit);
-
- // Build input and output relationships for all OP nodes
- PARSER_TIMESTAMP_START(GetOpNodesContextFromGraph);
- GE_RETURN_IF_ERROR(GetOpNodesContextFromGraph(*graph_def));
- PARSER_TIMESTAMP_END(GetOpNodesContextFromGraph, "TensorFlowModelParser::GetOpNodesContextFromGraph");
- GELOGD("[TF Parser] Get op nodes context from graph success");
-
- // Building input-output relationship between fusionop and common op
- GE_RETURN_IF_ERROR(UpdateAllNodeOpContext(scope_graph, op_node_name_list));
-
- GELOGI("[TF Parser] TF op node size = %zu.", op_node_name_list.size());
- PARSER_TIMESTAMP_START(AddFmkNode);
- // Loop analysis of op_nodes and map them to nodes in graph
- ret = AddFmkNode(graph, scope_graph, op_node_name_list, isDatasetInit);
- PARSER_TIMESTAMP_END(AddFmkNode, "TensorFlowModelParser::AddFmkNode");
- GE_CHK_STATUS_EXEC(ret, DeleteFuisonNodeDef();
- return ret, "AddFmkNode failed");
- GELOGD("[TF Parser] Add framework node success");
-
- ret = AddEdges(graph);
-
- Graph dest_graph = GraphUtils::CreateGraphFromComputeGraph(graph);
- ParserUtils::OutputMapping final_output_nodes;
- GE_RETURN_IF_ERROR(ParserUtils::ExpandOneToManyGraph(dest_graph, final_output_nodes));
- GE_RETURN_IF_ERROR(UpdateOutputsInfo(final_output_nodes));
-
- DeleteFuisonNodeDef();
- GE_CHK_STATUS_EXEC(ret, return ret, "AddEdges failed");
- GELOGD("[TF Parser] Add edges success");
-
- PARSER_TIMESTAMP_START(RemoveIsolateNode);
- // Delete isolated nodes
- GE_RETURN_IF_ERROR(RemoveIsolateNode(graph));
- GE_RETURN_IF_ERROR(CheckAndUpdateInputDesc(graph));
-
- PARSER_TIMESTAMP_END(RemoveIsolateNode, "TensorFlowModelParser::RemoveIsolateNode");
- PARSER_TIMESTAMP_START(TopologicalSorting);
- GE_RETURN_IF_ERROR(graph->TopologicalSorting());
- PARSER_TIMESTAMP_END(TopologicalSorting, "TensorFlowModelParser::TopologicalSorting");
-
- ge::parser::PassManager iterator_fusion_pass;
- try {
- (void)iterator_fusion_pass.AddPass("ParseProto::IteratorFusionPass", new ge::IteratorFusionPass(domi::TENSORFLOW));
- } catch (std::bad_alloc &e) {
- GELOGE(INTERNAL_ERROR, "Add pass failed, bad memory allocation occurs.");
- return INTERNAL_ERROR;
- }
- ret = iterator_fusion_pass.Run(graph);
- if (ret != SUCCESS && ret != ge::NOT_CHANGED) {
- GELOGE(ret, "Run graph passes optimize for preprocess failed, ret:%u.", ret);
- return ret;
- }
-
- has_error = has_error || PreChecker::Instance().HasError();
- if (has_error) {
- GELOGE(PARAM_INVALID, "Precheck has errors.");
- return PARAM_INVALID;
- }
- GELOGI("[TF Parser] Parse proto success.");
- PARSER_TIMESTAMP_END(ParseProto, "TensorFlowModelParser::ParseProto");
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::ParseProtoWithSubgraph(const google::protobuf::Message *root_proto,
- domi::GetGraphCallback callback, ge::ComputeGraphPtr &root_graph) {
- ErrorManager::GetInstance().SetStage(error_message::kModelCompile, error_message::kParser);
- ErrorManager::GetInstance().GenWorkStreamIdDefault();
- GE_CHECK_NOTNULL(root_proto);
- GE_CHECK_NOTNULL(callback);
- GE_CHECK_NOTNULL(root_graph);
-
- PARSER_TIMESTAMP_START(ParseProtoWithSubgraph);
- std::vector<std::unique_ptr<google::protobuf::Message>> proto_holder;
- std::deque<ParseArg> tasks;
- tasks.push_back({root_proto, "root", nullptr, "", root_graph});
-
- while (!tasks.empty()) {
- auto arg = tasks.front();
- tasks.pop_front();
-
- if (arg.proto == nullptr) {
- auto proto = callback(root_proto, arg.function_name);
- if (proto == nullptr) {
- REPORT_CALL_ERROR("E19999", "callback execute failed, func_name:%s", arg.function_name.c_str());
- GELOGE(FAILED, "Failed to get function by name %s", arg.function_name.c_str());
- return FAILED;
- }
- arg.proto = proto.get();
- proto_holder.emplace_back(std::move(proto));
- }
-
- GELOGI("Begin to parse graph %s", arg.function_name.c_str());
- auto model_parser = domi::ModelParserFactory::Instance()->CreateModelParser(domi::FrameworkType::TENSORFLOW);
- auto ret = model_parser->ParseProto(arg.proto, arg.graph);
- if (ret != SUCCESS) {
- GELOGE(ret, "Failed to parse graph %s, instance name %s", arg.function_name.c_str(),
- arg.graph->GetName().c_str());
- return ret;
- }
-
- ret = PostOpProcessForSubgraph(arg);
- if (ret != SUCCESS) {
- // the error log has been printed inner the function
- return ret;
- }
-
- ret = GenSubgraphParseTasks(arg.graph, tasks);
- if (ret != SUCCESS) {
- GELOGE(ret, "Failed to gen tasks on graph %s for next iteration", arg.graph->GetName().c_str());
- return ret;
- }
- }
- auto add_ret = AddExternalGraph(root_graph);
- if (add_ret != SUCCESS) {
- GELOGE(add_ret, "Failed to add external graph for root graph %s.", root_graph->GetName().c_str());
- return add_ret;
- }
- PARSER_TIMESTAMP_EVENT_END(ParseProtoWithSubgraph, "TensorFlowModelParser::ParseProtoWithSubgraph");
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::ParseProto(const std::string &serialized_proto, ge::ComputeGraphPtr &graph) {
- if (serialized_proto.empty()) {
- GELOGE(FAILED, "Deserialize proto failed as serialized proto is empty");
- return FAILED;
- }
- domi::tensorflow::GraphDef graph_def;
- if (!graph_def.ParseFromString(serialized_proto)) {
- GELOGE(FAILED, "Proto object GraphDef parse serialized proto failed");
- return FAILED;
- }
- return ParseProto(ge::PtrToPtr<domi::tensorflow::GraphDef, const google::protobuf::Message>(&graph_def), graph);
- }
-
- Status TensorFlowModelParser::ParseProtoWithSubgraph(const std::string &root_proto, domi::GetGraphCallbackV2 callback,
- ge::ComputeGraphPtr &root_graph) {
- ErrorManager::GetInstance().SetStage(error_message::kModelCompile, error_message::kParser);
- ErrorManager::GetInstance().GenWorkStreamIdDefault();
- GE_CHECK_NOTNULL(callback);
- GE_CHECK_NOTNULL(root_graph);
-
- PARSER_TIMESTAMP_START(ParseProtoWithSubgraph);
- std::deque<ParseArg> tasks;
- tasks.push_back({nullptr, "root", nullptr, "", root_graph});
- bool root_parsed = false;
-
- while (!tasks.empty()) {
- auto arg = tasks.front();
- tasks.pop_front();
-
- auto model_parser = domi::ModelParserFactory::Instance()->CreateModelParser(domi::FrameworkType::TENSORFLOW);
-
- Status ret = SUCCESS;
- if (root_parsed) {
- GELOGI("Begin to parse serialized proto of sub graph %s", arg.function_name.c_str());
- ret = model_parser->ParseProto(callback(arg.function_name), arg.graph);
- } else {
- GELOGI("Begin to parse serialized proto of root graph");
- ret = model_parser->ParseProto(root_proto, arg.graph);
- root_parsed = true;
- }
-
- if (ret != SUCCESS) {
- GELOGE(ret, "Failed to parse graph %s, instance name %s", arg.function_name.c_str(),
- arg.graph->GetName().c_str());
- return ret;
- }
-
- ret = PostOpProcessForSubgraph(arg);
- if (ret != SUCCESS) {
- return ret; // the error log has been printed inner the function
- }
-
- ret = GenSubgraphParseTasks(arg.graph, tasks);
- if (ret != SUCCESS) {
- GELOGE(ret, "Failed to gen tasks for sub graph of graph %s", arg.graph->GetName().c_str());
- return ret;
- }
- }
- auto add_ret = AddExternalGraph(root_graph);
- if (add_ret != SUCCESS) {
- GELOGE(add_ret, "Failed to add external graph for root graph %s.", root_graph->GetName().c_str());
- return add_ret;
- }
- PARSER_TIMESTAMP_EVENT_END(ParseProtoWithSubgraph, "TensorFlowModelParser::ParseProtoWithSubgraph");
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::OptimizeSnapShot(domi::tensorflow::NodeDef *curr_mode_def,
- map<string, NodeDef *> &nodedef_map,
- const std::pair<string, int> &input_data,
- const std::vector<string> &control_list) {
- GE_CHECK_NOTNULL(curr_mode_def);
- string curr_node_name = curr_mode_def->name();
- auto context_iter = op_node_context_map_.find(curr_node_name);
- if (context_iter == op_node_context_map_.end()) {
- REPORT_INNER_ERROR("E19999", "Node:%s can't find in op_node_context_map_, check invalid", curr_node_name.c_str());
- GELOGE(FAILED, "Can't find op node context.");
- return INTERNAL_ERROR;
- }
- OpNodeContext op_node_context = context_iter->second;
-
- std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> output_map = op_node_context.output_map;
- for (auto &output_iter : output_map) {
- const string &output_node_name = output_iter.first;
- domi::tensorflow::NodeDef *output_node_def = nodedef_map[output_node_name];
- GE_CHECK_NOTNULL(output_node_def);
- auto inputs = output_node_def->mutable_input();
- std::vector<std::string> added_inputs;
- for (auto &input : *inputs) {
- string node_name;
- bool is_control = false;
- if (CheckInputNodeName(input, &node_name, nullptr, &is_control) != SUCCESS) {
- GELOGE(FAILED, "parse node input info failed, node %s, input %s.", output_node_def->name().c_str(),
- input.c_str());
- return FAILED;
- }
- if (node_name == curr_node_name) {
- if (is_control) {
- input = "^" + input_data.first;
- } else if (input_data.second == 0) {
- input = input_data.first;
- } else {
- input = input_data.first + ":" + std::to_string(input_data.second);
- }
- GELOGD("Optimize Snapshot node, dest:%s, set input:%s.", output_node_name.c_str(), input.c_str());
-
- for (auto &item : control_list) {
- bool is_exist_input = false;
- for (auto &tmp_input : output_node_def->input()) {
- string tmp_node_name;
- if (CheckInputNodeName(tmp_input, &tmp_node_name, nullptr, nullptr) != SUCCESS) {
- GELOGE(INTERNAL_ERROR, "parse node input info failed, node %s, input %s.",
- output_node_def->name().c_str(), tmp_input.c_str());
- return FAILED;
- }
- if (tmp_node_name == item) {
- is_exist_input = true;
- break;
- }
- }
- if (!is_exist_input) {
- added_inputs.push_back("^" + item);
- }
- }
- }
- }
- for (std::string added_input : added_inputs) {
- GELOGD("Optimize Snapshot node, dest:%s, set control input:%s.", output_node_name.c_str(), added_input.c_str());
- output_node_def->add_input(added_input);
- }
- }
- // Clear the input of snapshot and become an isolated node
- curr_mode_def->clear_input();
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::GraphDefOptimizeSnapShot(domi::tensorflow::GraphDef *graph_def,
- map<string, NodeDef *> &nodedef_map,
- const vector<NodeDef *> &nodedef_to_optimize) {
- GE_CHECK_NOTNULL(graph_def);
- if (!nodedef_to_optimize.empty()) {
- // Building input and input relationships for all OP nodes
- GE_RETURN_IF_ERROR(GetOpNodesContextFromGraph(*graph_def));
- GELOGD("Optimize snapshot num:%zu.", nodedef_to_optimize.size());
- } else {
- return SUCCESS;
- }
-
- for (auto &curr_node_def : nodedef_to_optimize) {
- GE_CHECK_NOTNULL(curr_node_def);
- std::pair<string, int> input_data; // src node name, src index
- vector<string> control_list;
- uint32_t data_input_cnt = 0;
- for (auto &input : curr_node_def->input()) {
- string node_name;
- int input_index = 0;
- bool is_control = false;
- if (CheckInputNodeName(input, &node_name, &input_index, &is_control) != SUCCESS) {
- GELOGE(FAILED, "parse SnapShot input info failed, node %s, input %s.", curr_node_def->name().c_str(),
- input.c_str());
- return FAILED;
- }
- if (is_control) {
- control_list.push_back(node_name);
- } else {
- data_input_cnt++;
- input_data = std::make_pair(node_name, input_index);
- }
- }
- if (data_input_cnt != 1) {
- REPORT_INNER_ERROR("E19999", "Node:%s's input data size:%u not equal to 1, check invalid",
- curr_node_def->name().c_str(), data_input_cnt);
- GELOGE(FAILED, "%s op data input size %u invalid", curr_node_def->name().c_str(), data_input_cnt);
- return FAILED;
- }
- // Optimize Snapshot Node
- GE_CHK_STATUS_RET(OptimizeSnapShot(curr_node_def, nodedef_map, input_data, control_list));
- }
- GELOGI("GraphDefOptimizeSnapShot success.");
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::SetDestNodeName(const domi::tensorflow::NodeDef *const node_current,
- domi::tensorflow::NodeDef *const node_dest, const int32_t input_idx,
- const bool is_control, bool &clear_input_flag) {
- GELOGI("current node name is %s ", node_current->name().c_str());
- clear_input_flag = true;
- if (is_control) {
- string node_current_name = node_current->input(0);
- string current_name;
- if (CheckInputNodeName(node_current_name, ¤t_name, nullptr, nullptr) != SUCCESS) {
- GELOGE(FAILED, "CheckInputNodeName failed, node is: %s", node_current_name.c_str());
- return FAILED;
- }
- current_name = "^" + current_name;
- GELOGI("set nodeCurrentNameTmp: %s", current_name.c_str());
- node_dest->set_input(input_idx, current_name);
- } else {
- node_dest->set_input(input_idx, node_current->input(0).c_str());
- GELOGD("%s op set input:%s.", node_dest->name().c_str(), node_current->input(0).c_str());
- }
- // DestroyTemporaryVariable node have only one input and one output.
- // If the number of inputs is greater than 1, all subsequent inputs are
- // control edge inputs. Therefore, after deleting DestroyTemporaryVariable,
- // these control edge inputs can be directly connected to nodeDst.
- for (int i = 1; i < node_current->input_size(); ++i) {
- node_dest->add_input(node_current->input(i));
- }
- return SUCCESS;
- }
-
- void TensorFlowModelParser::OptimizeDestroyTemporaryVariable(domi::tensorflow::GraphDef *const graph_def,
- domi::tensorflow::NodeDef *const nodeCurrent,
- bool &clearInputFlag) const {
- // Internal call to ensure that the parameter is not empty.
- GELOGI("DestroyTemporaryVariable optimizing.");
- for (int w = 0; w < graph_def->node_size(); w++) {
- domi::tensorflow::NodeDef *nodeDst = graph_def->mutable_node(w);
- GE_IF_BOOL_EXEC(nodeDst->name() == nodeCurrent->name(), continue);
- for (int k = 0; k < nodeDst->input_size(); k++) {
- string nodeDstInputName = nodeDst->input(k);
- string nodeDstInputNameTmp;
- bool isControl = false;
- if (CheckInputNodeName(nodeDstInputName, &nodeDstInputNameTmp, nullptr, &isControl) != SUCCESS) {
- GELOGE(FAILED, "CheckInputNodeName failed, node is: %s", nodeDstInputName.c_str());
- return;
- }
- if (nodeDstInputNameTmp != nodeCurrent->name()) {
- continue;
- }
- if (SetDestNodeName(nodeCurrent, nodeDst, k, isControl, clearInputFlag) != SUCCESS) {
- GELOGE(FAILED, "CheckInputNodeName failed, node is: %s", nodeCurrent->name().c_str());
- return;
- }
- GELOGI("Optimize DestroyTemporaryVariable successful.");
- }
- }
- }
-
- Status TensorFlowModelParser::GraphDefOptimizeDestroyTemporaryVariable(
- domi::tensorflow::GraphDef *graph_def, domi::tensorflow::NodeDef *const nodeCurrent) const {
- if (graph_def == nullptr || nodeCurrent == nullptr) {
- REPORT_INNER_ERROR("E19999", "Param graph_def or nodeCurrent is nullptr, check invalid");
- GELOGE(FAILED, "input param is nullptr.");
- return FAILED;
- }
- if (nodeCurrent->op() != ge::parser::DESTROYTEMPORARYVARIABLE) {
- return SUCCESS;
- }
-
- GELOGI("Optimize DestroyTemporaryVariable, node name is :%s.", nodeCurrent->name().c_str());
- bool clearInputFlag = false;
-
- google::protobuf::Map<std::string, domi::tensorflow::AttrValue> *attr_map_destroy = nodeCurrent->mutable_attr();
- domi::tensorflow::AttrValue var_name_attr_destroy = (*attr_map_destroy)[ge::VAR_ATTR_NAME];
-
- for (int j = 0; j < graph_def->node_size(); j++) {
- domi::tensorflow::NodeDef *nodeTmpVar = graph_def->mutable_node(j);
- GE_IF_BOOL_EXEC(nodeTmpVar->op() != ge::parser::TEMPORARYVARIABLE, continue);
-
- google::protobuf::Map<std::string, domi::tensorflow::AttrValue> *attr_map_tmp = nodeTmpVar->mutable_attr();
- domi::tensorflow::AttrValue var_name_attr_tmp = (*attr_map_tmp)[ge::VAR_ATTR_NAME];
-
- if (var_name_attr_destroy.s() != var_name_attr_tmp.s()) {
- continue;
- }
-
- // Optimize destroytemporaryvariable operator
- OptimizeDestroyTemporaryVariable(graph_def, nodeCurrent, clearInputFlag);
-
- if (clearInputFlag) {
- nodeCurrent->clear_input(); // Clear the destroytemporaryvariable input to become an isolated node
- break;
- }
- }
- if (!clearInputFlag) {
- REPORT_INNER_ERROR("E19999", "Optimize DestroyTemporaryVariable failed, node name is :%s.",
- nodeCurrent->name().c_str());
- GELOGE(INTERNAL_ERROR, "Optimize DestroyTemporaryVariable failed, node name is :%s.", nodeCurrent->name().c_str());
- return FAILED;
- }
-
- return SUCCESS;
- }
-
- struct DelTransposeInfo {
- domi::tensorflow::NodeDef *node_def; // transpose
- domi::tensorflow::NodeDef *nextNodeDef; // transpose --> [next]
- int inputIdx;
- };
-
- Status GetTransposeInfo(domi::tensorflow::GraphDef *graph_def, std::map<std::string, std::string> &softmaxInfo,
- std::map<std::string, DelTransposeInfo> &transposeInfo) {
- GE_CHECK_NOTNULL(graph_def);
- for (int i = 0; i < graph_def->node_size(); ++i) {
- auto node_def = graph_def->mutable_node(i);
- if (node_def->op() == ge::parser::TRANSPOSE) {
- DelTransposeInfo transpose;
- transpose.node_def = node_def;
- transposeInfo.insert(std::make_pair(node_def->name(), transpose));
- } else if (node_def->op() == ge::parser::SOFTMAX) {
- softmaxInfo.insert(std::make_pair(node_def->name(), node_def->input(0)));
- GELOGI("softmax name:%s, input name:%s", node_def->name().c_str(), node_def->input(0).c_str());
- }
- }
-
- for (auto &itTranspose : transposeInfo) {
- for (int j = 0; j < graph_def->node_size(); ++j) {
- auto nextNodeDef = graph_def->mutable_node(j);
- bool bFind = false;
- for (int k = 0; k < nextNodeDef->input_size(); ++k) {
- if (nextNodeDef->input(k) == itTranspose.first) {
- itTranspose.second.nextNodeDef = nextNodeDef;
- itTranspose.second.inputIdx = k;
- GELOGI("transpose info name:%s, next name:%s, idx:%d", itTranspose.second.node_def->name().c_str(),
- nextNodeDef->name().c_str(), k);
- bFind = true;
- break;
- }
- }
- if (bFind) {
- break;
- }
- }
- }
- return SUCCESS;
- }
-
- Status EraseTransposeNode(std::map<std::string, std::string> &softmaxInfo,
- std::map<std::string, DelTransposeInfo> &transposeInfo) {
- std::map<std::string, DelTransposeInfo>::const_iterator itTranspose = transposeInfo.begin();
- for (; itTranspose != transposeInfo.end();) {
- // transpose --> softmax
- bool bErase = true;
- if (softmaxInfo.find(itTranspose->second.node_def->input(0)) != softmaxInfo.end() ||
- softmaxInfo.find(itTranspose->second.nextNodeDef->name()) != softmaxInfo.end()) {
- bErase = false;
- }
-
- if (bErase) {
- GELOGI("erase node name:%s, input(0):%s", itTranspose->first.c_str(),
- itTranspose->second.node_def->input(0).c_str());
- itTranspose = transposeInfo.erase(itTranspose);
- } else {
- ++itTranspose;
- }
- }
-
- if ((softmaxInfo.size() <= SIZE_MAX / kSoftmaxMultiple) &&
- (softmaxInfo.size() * kSoftmaxMultiple != transposeInfo.size())) {
- GELOGW("softmax size[%zu], transpose size[%zu]", softmaxInfo.size(), transposeInfo.size());
- return FAILED;
- }
-
- return SUCCESS;
- }
-
- void TensorFlowModelParser::OptimizeTranspose(std::map<std::string, DelTransposeInfo> &transposeInfo) {
- for (auto &it : transposeInfo) {
- auto transpose = it.second;
- transpose.nextNodeDef->set_input(transpose.inputIdx, transpose.node_def->input(kTransposeInputIdx));
- transpose.node_def->clear_input();
- }
- }
-
- void TensorFlowModelParser::SoftmaxAddAttr(domi::tensorflow::GraphDef *const graph_def) {
- // The caller guarantees that the pointer is not null
- for (int i = 0; i < graph_def->node_size(); ++i) {
- auto node_def = graph_def->mutable_node(i);
- if (node_def->op() == ge::parser::SOFTMAX) {
- domi::tensorflow::AttrValue attr_value;
- attr_value.set_i(1);
- ge::TensorFlowUtil::AddNodeAttr("axis", attr_value, node_def);
- GELOGI("SoftmaxAddAttr, name: %s, input name:%s", node_def->name().c_str(), node_def->input(0).c_str());
- }
- }
- }
-
- Status TensorFlowModelParser::GraphDefOptimize(domi::tensorflow::GraphDef *graph_def) {
- GE_CHECK_NOTNULL(graph_def);
- map<string, NodeDef *> nodedef_map;
- vector<string> op_node_name_list;
- // Save Snapshot
- vector<NodeDef *> snapshot_to_optimize;
-
- for (int i = 0; i < graph_def->node_size(); i++) {
- // mutable_node return vale is not empty
- domi::tensorflow::NodeDef *node_def = graph_def->mutable_node(i);
- const string &node_name = node_def->name();
- Status ret = AddFmkNodeDefToMap(node_def, op_node_name_list);
- GE_CHK_STATUS_EXEC(ret, return PARAM_INVALID, "add node_def to map failed");
- if (node_def->op() == ge::parser::SNAPSHOT) {
- snapshot_to_optimize.push_back(node_def);
- }
- nodedef_map[node_name] = node_def;
- }
-
- // Optimize for Snapshot
- GE_RETURN_IF_ERROR(GraphDefOptimizeSnapShot(graph_def, nodedef_map, snapshot_to_optimize));
-
- for (int i = 0; i < graph_def->node_size(); i++) {
- domi::tensorflow::NodeDef *nodeCurrent = graph_def->mutable_node(i);
- GE_CHK_STATUS_RET(GraphDefOptimizeDestroyTemporaryVariable(graph_def, nodeCurrent));
- }
-
- // These member variables will be rebuilt later and need to be cleared here.
- nodedef_map_.clear();
- op_node_context_map_.clear();
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::RemoveIsolateNode(const ge::ComputeGraphPtr &graph) {
- GE_CHECK_NOTNULL(graph);
-
- auto nodes = graph->GetDirectNode();
- for (auto &n : nodes) {
- // get front 4 char
- if (n->GetName().substr(0, 4) == "dpop") {
- continue;
- }
- if ((n->GetType() == ge::parser::DATA) ||
- (ge::GetParserContext().out_nodes_map.find(n->GetName()) != ge::GetParserContext().out_nodes_map.end())) {
- GELOGI("Can not remove op [%s] because it is data or out node.", n->GetName().c_str());
- continue;
- }
- GE_IF_BOOL_EXEC((((n->GetInAllNodes().size() == 0) && (n->GetOutDataNodes().size() == 0)) ||
- ((n->GetType() == ge::parser::CONSTANTOP || n->GetType() == ge::parser::CONSTANT) &&
- (n->GetOutDataNodes().size() == 0))),
- GE_CHK_STATUS_RET(ge::GraphUtils::IsolateNode(n, {}), "Isolate removed node: %s, type: %s failed",
- n->GetName().c_str(), n->GetType().c_str());
- GE_CHK_STATUS_RET(ge::GraphUtils::RemoveNodeWithoutRelink(graph, n),
- "Remove node: %s, type: %s without relink failed", n->GetName().c_str(),
- n->GetType().c_str()););
- }
- return SUCCESS;
- }
-
- // The format specified by the command line argument is preferred,
- // if not specified, use InferInputFormats to infer,
- // and if the inference fails, the default NHWC format is used.
- domiTensorFormat_t TensorFlowModelParser::InferInputFormats() {
- GE_IF_BOOL_EXEC(ge::GetParserContext().format != DOMI_TENSOR_RESERVED, return ge::GetParserContext().format);
-
- domiTensorFormat_t global_input_format = DOMI_TENSOR_RESERVED;
- set<const NodeDef *> visited_node;
- for (auto &node_item : nodedef_map_) {
- // Infer format for data node and save it to ge::GetParserContext().format.
- domiTensorFormat_t format = DOMI_TENSOR_RESERVED;
- const NodeDef *node = node_item.second;
- if (node == nullptr) {
- return format;
- }
- auto it = tensorflow_op_map.find(node->op());
- if (it != tensorflow_op_map.end() && it->second == ge::parser::DATA) {
- GE_IF_BOOL_EXEC(GetNodeFormat(node, NO_TRANSPOSE, format, visited_node) != SUCCESS,
- GELOGW("Cannot infer input format, the NHWC format is used by default, and you can also "
- "specify format by command line arguments.");
- return domi::DOMI_TENSOR_NHWC);
-
- GE_IF_BOOL_EXEC(global_input_format == DOMI_TENSOR_RESERVED, global_input_format = format);
-
- GE_IF_BOOL_EXEC(
- format != DOMI_TENSOR_RESERVED && format != global_input_format,
- GELOGW("Multiple data ops with different formats are not supported, "
- "the NHWC format is used by default, and you can also specify format by command line arguments.");
- return domi::DOMI_TENSOR_NHWC);
- }
- }
-
- return global_input_format == DOMI_TENSOR_RESERVED ? domi::DOMI_TENSOR_NHWC : global_input_format;
- }
-
- Status TensorFlowModelParser::GetNodeFormat(const NodeDef *node, TfTranspose pred_transpose, domiTensorFormat_t &format,
- set<const NodeDef *> &visited_node) {
- GE_CHECK_NOTNULL(node);
- // Avoid repeated visits.
- GE_IF_BOOL_EXEC(visited_node.find(node) != visited_node.end(), return SUCCESS);
- visited_node.emplace(node);
-
- GE_IF_BOOL_EXEC(node->op() == TENSORFLOWF_NODE_OP_SWITCH || node->op() == TENSORFLOWF_NODE_OP_MERGE, return SUCCESS);
-
- // If node has a data_format attribute, format is set according to data_format.
- domi::tensorflow::AttrValue attr;
- if (ge::TensorFlowUtil::FindAttrValue(node, TENSORFLOW_ATTR_DATA_FORMAT, attr) && node->op() != ge::parser::BIASADD) {
- GE_RETURN_IF_ERROR(ge::TensorFlowUtil::CheckAttrHasType(attr, TENSORFLOW_ATTR_TYPE_STRING));
-
- format = (attr.s() == TENSORFLOWF_TENSOR_NCHW) ? domi::DOMI_TENSOR_NCHW : domi::DOMI_TENSOR_NHWC;
-
- GE_IF_BOOL_EXEC(format == domi::DOMI_TENSOR_NCHW && pred_transpose == TO_NCHW, format = domi::DOMI_TENSOR_NHWC);
- GE_IF_BOOL_EXEC(format == domi::DOMI_TENSOR_NHWC && pred_transpose == TO_NHWC, format = domi::DOMI_TENSOR_NCHW);
- GE_IF_BOOL_EXEC((format == domi::DOMI_TENSOR_NCHW && pred_transpose == TO_NHWC) ||
- (format == domi::DOMI_TENSOR_NHWC && pred_transpose == TO_NCHW),
- GELOGI("Format conflicts with transpose.");
- return FAILED);
-
- return SUCCESS;
- }
-
- TfTranspose transpose;
- GE_RETURN_IF_ERROR(GetFormatTranspose(node, transpose));
- GE_IF_BOOL_EXEC(pred_transpose == transpose && pred_transpose != NO_TRANSPOSE,
- GELOGI("Multiple transpose conflicts.");
- return FAILED);
-
- // If node does not have the data_format attribute, format is set according to the output node.
- string node_name = node->name();
- GE_IF_BOOL_EXEC(op_node_context_map_.find(node_name) == op_node_context_map_.end(),
- GELOGI("node %s not found in op_node_context_map_", node_name.c_str());
- return FAILED);
-
- domiTensorFormat_t inferred_format = DOMI_TENSOR_RESERVED;
- const OpNodeContext &node_ctx = op_node_context_map_.at(node_name);
-
- for (const auto &output_item : node_ctx.output_map) {
- auto node_iter = nodedef_map_.find(output_item.first);
- GE_IF_BOOL_EXEC(node_iter == nodedef_map_.end(),
- GELOGI("node %s not found in nodedef_map_", output_item.first.c_str());
- return FAILED);
-
- const NodeDef *output_node = node_iter->second;
- GE_CHECK_NOTNULL(output_node);
- domiTensorFormat_t output_format = DOMI_TENSOR_RESERVED;
- GE_RETURN_IF_ERROR(GetNodeFormat(output_node, transpose, output_format, visited_node));
-
- GE_IF_BOOL_EXEC(output_format != DOMI_TENSOR_RESERVED && inferred_format != DOMI_TENSOR_RESERVED &&
- output_format != inferred_format,
- GELOGI("Multiple output formats conflict.");
- return FAILED);
-
- inferred_format = output_format;
- }
-
- format = inferred_format;
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::GetFormatTranspose(const NodeDef *transpose_node, TfTranspose &transpose_direc) const {
- GE_CHECK_NOTNULL(transpose_node);
- transpose_direc = NO_TRANSPOSE;
-
- GE_IF_BOOL_EXEC(transpose_node->op() != TENSORFLOWF_NODE_OP_TRANSPOSE, return SUCCESS);
-
- GE_IF_BOOL_EXEC(transpose_node->input_size() != kInputNumInt, GELOGI("Input size of transpose is not 2.");
- return FAILED);
-
- string perm_node_name = transpose_node->input(1);
- auto it = nodedef_map_.find(perm_node_name);
- GE_IF_BOOL_EXEC(it == nodedef_map_.end(), GELOGI("Node %s not found in nodedef_map_.", perm_node_name.c_str());
- return FAILED);
-
- const NodeDef *perm_node = it->second;
- GE_CHECK_NOTNULL(perm_node);
- domi::tensorflow::AttrValue attr_value;
- GE_IF_BOOL_EXEC(perm_node->op() != TENSORFLOWF_NODE_OP_CONST, GELOGI("Input node of transpose is not const.");
- return FAILED);
-
- GE_IF_BOOL_EXEC(!ge::TensorFlowUtil::FindAttrValue(perm_node, TENSORFLOW_ATTR_DTYPE, attr_value), return FAILED);
- GE_IF_BOOL_EXEC(ge::TensorFlowUtil::CheckAttrHasType(attr_value, TENSORFLOW_ATTR_TYPE_TYPE) != SUCCESS,
- return FAILED);
- domi::tensorflow::DataType type = attr_value.type();
- GE_IF_BOOL_EXEC(type != domi::tensorflow::DT_INT32 && type != domi::tensorflow::DT_INT64, return FAILED);
-
- GE_IF_BOOL_EXEC(!ge::TensorFlowUtil::FindAttrValue(perm_node, TENSORFLOW_ATTR_VALUE, attr_value), return FAILED);
- GE_IF_BOOL_EXEC(ge::TensorFlowUtil::CheckAttrHasType(attr_value, TENSORFLOW_ATTR_TYPE_TENSOR) != SUCCESS,
- return FAILED);
- const TensorProto &tensor = attr_value.tensor();
- const domi::tensorflow::TensorShapeProto &tensor_shape = tensor.tensor_shape();
- GE_IF_BOOL_EXEC(tensor_shape.dim_size() != 1 || tensor_shape.dim(0).size() != parser::DIM_DEFAULT_SIZE,
- return SUCCESS);
- GE_IF_BOOL_EXEC(tensor.tensor_content().empty(), return SUCCESS);
-
- vector<int64_t> perm_value;
-
- GE_IF_BOOL_EXEC(
- type == domi::tensorflow::DT_INT32,
- const int32_t *data = reinterpret_cast<const int32_t *>(tensor.tensor_content().data());
- for (int i = 0; i < parser::DIM_DEFAULT_SIZE; i++) {
- perm_value.push_back(data[i]);
- });
-
- GE_IF_BOOL_EXEC(
- type == domi::tensorflow::DT_INT64,
- const int64_t *data = reinterpret_cast<const int64_t *>(tensor.tensor_content().data());
- for (int i = 0; i < parser::DIM_DEFAULT_SIZE; i++) {
- perm_value.push_back(data[i]);
- });
-
- // 0, 1, 2, 3 present dim num.
- vector<int64_t> perm_to_nchw = {0, 3, 1, 2};
- vector<int64_t> perm_to_nhwc = {0, 2, 3, 1};
- GE_IF_BOOL_EXEC(perm_value == perm_to_nchw, transpose_direc = TO_NCHW);
- GE_IF_BOOL_EXEC(perm_value == perm_to_nhwc, transpose_direc = TO_NHWC);
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::TrimGraph(const domi::tensorflow::GraphDef &input_graph_def,
- domi::tensorflow::GraphDef *output_graph_def) {
- GE_CHECK_NOTNULL(output_graph_def);
- if (!ge::GetParserContext().input_dims.empty() && ge::GetParserContext().out_nodes_map.empty()) {
- return TrimGraphByInput(input_graph_def, output_graph_def);
- } else {
- return TrimGraphByOutput(input_graph_def, output_graph_def);
- }
- }
- Status TensorFlowModelParser::TrimGraphByInput(const domi::tensorflow::GraphDef &input_graph_def,
- domi::tensorflow::GraphDef *const output_graph_def) {
- // The caller guarantees that the pointer is not null
- std::set<string> delete_nodes;
- std::set<string> input_nodes;
- for (auto &iter : ge::GetParserContext().input_dims) {
- input_nodes.insert(iter.first);
- }
- std::map<string, const NodeDef *> node_lookup;
- for (const NodeDef &node : input_graph_def.node()) {
- node_lookup[node.name()] = &node;
- }
- std::vector<string> current_inputs;
- for (auto &iter : ge::GetParserContext().input_dims) {
- current_inputs.push_back(iter.first);
- }
- while (!current_inputs.empty()) {
- std::set<string> next_inputs;
- for (const string ¤t_input : current_inputs) {
- delete_nodes.insert(current_input);
- GE_CHK_BOOL_EXEC(node_lookup.count(current_input) > 0U,
- ErrorManager::GetInstance().ATCReportErrMessage("E10016", {"parameter", "opname"},
- {"input_shape", current_input});
- return FAILED, "Input op[%s] not found in graph.", current_input.c_str());
- const NodeDef *current_node = node_lookup[current_input];
- GE_CHECK_NOTNULL(current_node);
- for (const string &input_name : current_node->input()) {
- string input_node_name = NodeNameFromInput(input_name);
- if (delete_nodes.count(input_node_name) == 0U) {
- next_inputs.insert(input_node_name);
- }
- }
- }
- current_inputs = std::vector<string>(next_inputs.begin(), next_inputs.end());
- }
- domi::tensorflow::GraphDef filtered_graph_def;
- filtered_graph_def.mutable_node()->Clear();
- for (const NodeDef &node : input_graph_def.node()) {
- if (static_cast<bool>(input_nodes.count(node.name()))) {
- *(filtered_graph_def.mutable_node()->Add()) = node;
- }
- if (delete_nodes.count(node.name()) == 0U) {
- *(filtered_graph_def.mutable_node()->Add()) = node;
- }
- }
- output_graph_def->Clear();
- for (const NodeDef &node : filtered_graph_def.node()) {
- if (static_cast<bool>(input_nodes.count(node.name()))) {
- NodeDef placeholder_node = node;
- placeholder_node.clear_input();
- GE_IF_BOOL_EXEC(node.op() != "Placeholder", placeholder_node.set_op("Placeholder"));
- domi::tensorflow::AttrValue attr_value;
- domi::tensorflow::TensorShapeProto *data_shape = attr_value.mutable_shape();
- GE_CHECK_NOTNULL(data_shape);
- const ge::ParserContext &ctx = ge::GetParserContext();
- std::map<std::string, std::vector<int64_t>> input_dims = ctx.input_dims;
- std::vector<int64_t> designated_dims = input_dims.at(node.name());
- for (int32_t i = 0; i < static_cast<int32_t>(designated_dims.size()); i++) {
- data_shape->add_dim()->set_size(designated_dims[i]);
- }
- google::protobuf::Map<std::string, domi::tensorflow::AttrValue> *attr = placeholder_node.mutable_attr();
- (*attr)[TENSORFLOW_ATTR_SHAPE] = attr_value;
- GE_CHECK_NOTNULL(output_graph_def->mutable_node());
- *(output_graph_def->mutable_node()->Add()) = placeholder_node;
- } else {
- GE_CHECK_NOTNULL(output_graph_def->mutable_node());
- *(output_graph_def->mutable_node()->Add()) = node;
- }
- }
- return SUCCESS;
- }
- Status TensorFlowModelParser::TrimGraphByOutput(const domi::tensorflow::GraphDef &input_graph_def,
- domi::tensorflow::GraphDef *const output_graph_def) {
- // The caller guarantees that the pointer is not null
- std::set<string> required_nodes;
- std::set<string> input_nodes;
- for (auto &iter : ge::GetParserContext().input_dims) {
- required_nodes.insert(iter.first);
- input_nodes.insert(iter.first);
- }
- for (auto &iter : ge::GetParserContext().out_nodes_map) {
- required_nodes.insert(iter.first);
- }
- std::map<string, const NodeDef *> node_lookup;
- for (const NodeDef &node : input_graph_def.node()) {
- node_lookup[node.name()] = &node;
- }
- std::vector<string> current_inputs;
- for (auto &iter : ge::GetParserContext().out_nodes_map) {
- current_inputs.push_back(iter.first);
- }
- while (!current_inputs.empty()) {
- std::set<string> next_inputs;
- for (const string ¤t_input : current_inputs) {
- required_nodes.insert(current_input);
- GE_IF_BOOL_EXEC(static_cast<bool>(input_nodes.count(current_input)), continue);
- GE_CHK_BOOL_EXEC(node_lookup.count(current_input) > 0U,
- ErrorManager::GetInstance().ATCReportErrMessage("E10016", {"parameter", "opname"},
- {"out_nodes", current_input});
- return FAILED, "op[%s] not found in graph.", current_input.c_str());
- const NodeDef *current_node = node_lookup[current_input];
- GE_CHECK_NOTNULL(current_node);
- for (const string &input_name : current_node->input()) {
- string input_node_name = NodeNameFromInput(input_name);
- if (required_nodes.count(input_node_name) == 0U) {
- next_inputs.insert(input_node_name);
- }
- }
- }
- current_inputs = std::vector<string>(next_inputs.begin(), next_inputs.end());
- }
- domi::tensorflow::GraphDef filtered_graph_def;
- filtered_graph_def.mutable_node()->Clear();
- for (const NodeDef &node : input_graph_def.node()) {
- if (static_cast<bool>(required_nodes.count(node.name()))) {
- *(filtered_graph_def.mutable_node()->Add()) = node;
- }
- }
- output_graph_def->Clear();
- for (const NodeDef &node : filtered_graph_def.node()) {
- if (static_cast<bool>(input_nodes.count(node.name()))) {
- NodeDef placeholder_node = node;
- placeholder_node.clear_input();
- GE_IF_BOOL_EXEC(node.op() != "Placeholder", placeholder_node.set_op("Placeholder"));
- domi::tensorflow::AttrValue attr_value;
- domi::tensorflow::TensorShapeProto *data_shape = attr_value.mutable_shape();
- GE_CHECK_NOTNULL(data_shape);
- const ge::ParserContext &ctx = ge::GetParserContext();
- std::map<std::string, std::vector<int64_t>> input_dims = ctx.input_dims;
- std::vector<int64_t> designated_dims = input_dims.at(node.name());
- for (int32_t i = 0; i < static_cast<int32_t>(designated_dims.size()); i++) {
- data_shape->add_dim()->set_size(designated_dims[i]);
- }
- google::protobuf::Map<std::string, domi::tensorflow::AttrValue> *attr = placeholder_node.mutable_attr();
- (*attr)[TENSORFLOW_ATTR_SHAPE] = attr_value;
- GE_CHECK_NOTNULL(output_graph_def->mutable_node());
- *(output_graph_def->mutable_node()->Add()) = placeholder_node;
- } else {
- GE_CHECK_NOTNULL(output_graph_def->mutable_node());
- *(output_graph_def->mutable_node()->Add()) = node;
- }
- }
- return SUCCESS;
- }
- string TensorFlowModelParser::NodeNameFromInput(const string &input_name) {
- string prefix;
- string node_name;
- string suffix;
- std::vector<string> input_parts = ge::StringUtils::Split(input_name, ':');
- suffix = (input_parts.size() < kInputNumUint) ? "" : (":" + input_parts[1]);
- string tmp_name = input_parts[0];
- GE_IF_BOOL_EXEC(input_parts[0].find("^") == 0, tmp_name = tmp_name.substr(1, tmp_name.length() - 1));
- node_name = tmp_name;
- return node_name;
- }
-
- Status TensorFlowModelParser::FusionNodeParseParams(shared_ptr<OpParser> &op_parser,
- const domi::tensorflow::NodeDef *node_def,
- ge::NodePtr &node) const {
- GE_CHECK_NOTNULL(node_def);
- GE_CHECK_NOTNULL(node);
- GE_CHECK_NOTNULL(op_parser);
-
- GELOGI("FusionNodeParseParams:node name:%s.", node_def->name().c_str());
-
- // The fusion operator deals with parseparams separately
- shared_ptr<TensorFlowFusionOpParser> tensorflow_fusion_op_parser =
- std::dynamic_pointer_cast<TensorFlowFusionOpParser>(op_parser);
- GE_IF_BOOL_EXEC(tensorflow_fusion_op_parser == nullptr,
- REPORT_INNER_ERROR("E19999", "Param op_parser is not TensorFlowFusionOpParser Type, check invalid");
- GELOGE(FAILED, "node :%s can not get fusion parser, please check!", node_def->name().c_str());
- return INTERNAL_ERROR);
-
- // Find all children of the fusion operator
- auto iter = fusion_op_nodedef_map_.find(node_def->name());
- if (iter == fusion_op_nodedef_map_.end()) {
- REPORT_INNER_ERROR("E19999", "Node:%s can't find in fusion_op_nodedef_map_, check invalid",
- node_def->name().c_str());
- GELOGE(FAILED, "FusionOp node %s has no children node!", node_def->name().c_str());
- return INTERNAL_ERROR;
- }
-
- (void)ge::AttrUtils::SetStr(node->GetOpDesc(), ge::ATTR_NAME_FUSIONOP_ORIGINAL_TYPE, node_def->op());
- vector<const domi::tensorflow::NodeDef *> node_def_v = iter->second;
- domi::FusionParseParamByOpFunc parse_param_func =
- domi::OpRegistry::Instance()->GetFusionParseParamByOpFunc(node->GetType(), node_def->op());
- Status status = FAILED;
- if (parse_param_func == nullptr) {
- status = tensorflow_fusion_op_parser->ParseParams(node_def_v, node);
- GE_CHK_STATUS_EXEC(status, return status, "Parse Params for fusionop node %s failed", node_def->name().c_str());
- } else {
- vector<ge::Operator> op_src_vec;
- for (const auto &node_def_src : node_def_v) {
- ge::Operator op_src(node_def_src->name().c_str(), node_def_src->op().c_str());
- status = domi::OperatorAutoMapping(node_def_src, op_src);
- if (status != SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Auto mapping node_def:%s(%s) to operator failed", node_def_src->name().c_str(),
- node_def_src->op().c_str());
- GELOGE(status, "Node[%s] auto mapping failed", node_def_src->name().c_str());
- return status;
- }
- auto op_desc = ge::OpDescUtils::GetOpDescFromOperator(op_src);
- GE_CHECK_NOTNULL(op_desc);
- for (int32_t i = 0; i < node_def_src->input_size(); i++) {
- ge::GeTensorDesc tensor_desc;
- tensor_desc.SetName(node_def_src->input(i));
- if (op_desc->AddInputDesc(tensor_desc) != GRAPH_SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Add input desc to op:%s(%s) failed", op_desc->GetName().c_str(),
- op_desc->GetType().c_str());
- GELOGE(FAILED, "Op [%s] type[%s] add input(%d) tensor failed.", op_desc->GetName().c_str(),
- op_desc->GetType().c_str(), i);
- return FAILED;
- }
- }
- op_src_vec.push_back(op_src);
- }
- shared_ptr<TensorFlowFusionCustomParserAdapter> tf_custom_fusion_op_paser =
- std::dynamic_pointer_cast<TensorFlowFusionCustomParserAdapter>(tensorflow_fusion_op_parser);
- status = tf_custom_fusion_op_paser->ParseParams(op_src_vec, node);
- if (status != SUCCESS) {
- GELOGE(status, "Parse params for fusionop node %s failed", node_def->name().c_str());
- return status;
- }
- }
-
- return SUCCESS;
- }
-
- /**
- * @ingroup domi_omg
- * @brief Optimizing const nodes for custom operators
- * @param [in] graph_def graph object
- * @return true optimize successfully
- * @return false optimize failed
- *
- */
- Status TensorFlowModelParser::OptimizeConstNodes4CustomOp(domi::tensorflow::GraphDef *graph_def) const {
- GE_CHECK_NOTNULL(graph_def);
- // 1. find all the nodes in the graph and save them to all_nodedef_map
- map<string, NodeDef *> all_nodedef_map;
- int graph_node_size = graph_def->node_size();
- for (int i = 0; i != graph_node_size; ++i) {
- // mutable_node return vale is not empty
- domi::tensorflow::NodeDef *current_node = graph_def->mutable_node(i);
- string node_name = current_node->name();
- all_nodedef_map[node_name] = current_node;
- }
- GELOGD("node size is: %zu", all_nodedef_map.size());
-
- // 2. move input to attr.
- for (auto &it_node_map : all_nodedef_map) {
- domi::tensorflow::NodeDef *current_node = it_node_map.second;
- GE_CHECK_NOTNULL(current_node);
- string current_op_name = current_node->op();
-
- // 2.1. check whether the current op is register for move to attr.
- const std::vector<domi::RemoveInputConfigure> &move_input_vec =
- domi::OpRegistry::Instance()->GetRemoveInputConfigure(current_op_name);
- // 2.2 check whether the current op is a TVM op.
- const bool is_unknown_custom_op = move_input_vec.empty() ||
- (domi::OpRegistry::Instance()->GetImplyTypeByOriOpType(current_op_name) != domi::ImplyType::TVM);
- if (is_unknown_custom_op) {
- GELOGI("op %s is not TVM op, move input size: %zu", current_op_name.c_str(), move_input_vec.size());
- continue;
- }
- GELOGD("Current op %s is registered for remove input and tvm op", current_op_name.c_str());
-
- // 2.3 copy input to attr
- set<uint32_t> unused_inputs;
- for (const auto &it : move_input_vec) {
- uint32_t move_index;
- if (it.inputIdx >= 0) {
- move_index = it.inputIdx;
- } else {
- GE_IF_BOOL_EXEC(
- -it.inputIdx > current_node->input_size(),
- ErrorManager::GetInstance().ATCReportErrMessage(
- "E12004", {"opname", "inputIdx", "inputsize"},
- {current_op_name, std::to_string(-it.inputIdx), std::to_string(current_node->input_size())});
- GELOGE(INTERNAL_ERROR,
- "Op[%s] register failed, inputIdx[-%d] should be greater than inputsize[%d] when inputIdx < 0.",
- current_op_name.c_str(), it.inputIdx, current_node->input_size());
- return PARAM_INVALID);
- move_index = current_node->input_size() + it.inputIdx;
- }
- // For an isolated node in deep lab V3 networ.
- // solve the problem of protobuf index less current_size.
- GE_IF_BOOL_EXEC(current_node->input_size() == 0, GELOGI("Input size is 0, already optimized"); continue);
-
- if (it.moveType == domi::OMG_REMOVE_TYPE_WITH_COND) {
- domi::tensorflow::AttrValue attr_value;
- GE_IF_BOOL_EXEC(!(ge::TensorFlowUtil::FindAttrValue(current_node, it.attrName, attr_value)),
- REPORT_INNER_ERROR("E19999", "Op:%s register AttrName[%s] has no value, check invalid",
- current_op_name.c_str(), it.attrName.c_str());
- GELOGE(INTERNAL_ERROR, "AttrName[%s] has no value!", it.attrName.c_str());
- return PARAM_INVALID);
- GE_IF_BOOL_EXEC(attr_value.b() == it.attrValue, unused_inputs.insert(move_index));
- } else if (it.moveType == domi::OMG_REMOVE_INPUT_WITH_ORIGINAL_TYPE && it.originalType == current_op_name) {
- GELOGD("Input %s:%d will be removed.", current_op_name.c_str(), move_index);
- unused_inputs.insert(move_index);
- } else if (it.moveType == domi::OMG_INPUT_REORDER) {
- auto inputs = current_node->input();
- if (static_cast<size_t>(inputs.size()) != it.input_order.size()) {
- REPORT_INNER_ERROR("E19999", "Input size of node:%s(%s) is mismatched, new order size:%zu, input size:%d",
- current_node->name().c_str(), current_node->op().c_str(), it.input_order.size(),
- inputs.size());
- GELOGE(INTERNAL_ERROR, "Size of input is mismatched, new order size is %zu, input size is %d.",
- it.input_order.size(), inputs.size());
- return INTERNAL_ERROR;
- }
- for (size_t i = 0; i < it.input_order.size(); ++i) {
- int new_index = it.input_order[i];
- const bool is_input_invalid = (new_index < 0) || (new_index >= inputs.size());
- if (is_input_invalid) {
- REPORT_INNER_ERROR("E19999", "New order of %s has invalid index %d, out of range(0, %d)",
- it_node_map.first.c_str(), new_index, inputs.size());
- GELOGE(INTERNAL_ERROR, "New order of %s has invalid index %d.", it_node_map.first.c_str(), new_index);
- return INTERNAL_ERROR;
- }
- current_node->set_input(i, inputs[new_index]);
- }
- GELOGI("The input sequence of the node has been rearranged, node name:%s.", it_node_map.first.c_str());
- }
- }
-
- // 2.4 remove the input const nodes
- Status ret = RemoveInputs(graph_def, current_node, unused_inputs, all_nodedef_map);
- if (ret != SUCCESS) {
- REPORT_CALL_ERROR("E19999", "remove input for op:%s failed", current_op_name.c_str());
- GELOGE(INTERNAL_ERROR, "Op[%s] remove input failed.", current_op_name.c_str());
- return ret;
- }
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::AddControlEdgeAfterRemoveInputs(domi::tensorflow::GraphDef *graph_def,
- domi::tensorflow::NodeDef *node_def,
- const map<string, NodeDef *> &all_node_map,
- const vector<string> &removed_inputs_vec) const {
- GE_CHECK_NOTNULL(graph_def);
- GE_CHECK_NOTNULL(node_def);
- for (const auto &remove_input : removed_inputs_vec) {
- string input_node_name = NodeNameFromInput(remove_input);
- auto it = all_node_map.find(input_node_name);
- if (it == all_node_map.end()) {
- REPORT_INNER_ERROR("E19999", "Node:%s can't find in all_node_map, check invalid", input_node_name.c_str());
- GELOGE(FAILED, "Can not find node name:%s in all node map.", input_node_name.c_str());
- return FAILED;
- }
- NodeDef *input_node_def = it->second;
- if ((input_node_def->op() == parser::SWITCH) || (input_node_def->op() == parser::REFSWITCH)) {
- NodeDef *identity_node_def = graph_def->add_node();
- GE_CHECK_NOTNULL(identity_node_def);
- std::string remove_input_name = remove_input;
- remove_input_name = remove_input_name.find(":") == std::string::npos ?
- input_node_name : (remove_input_name.replace(remove_input_name.find(":"), 1, "_"));
- input_node_name = remove_input_name + "_identity";
- identity_node_def->set_name(input_node_name);
- identity_node_def->set_op(parser::IDENTITY);
- identity_node_def->add_input(remove_input);
- }
- string control_input = "^" + input_node_name;
- node_def->add_input(control_input);
- GELOGD("Add control input:%s for node:%s", control_input.c_str(), node_def->name().c_str());
- }
- return SUCCESS;
- }
- /**
- * @ingroup domi_omg
- * @brief Delete input from nodedef
- * @param [in] node_def Nodedef object
- * @param [in] remove_index_set Index collection of input nodes to be deleted
- * @return true remove successfully
- * @return false remove failed
- *
- */
- Status TensorFlowModelParser::RemoveInputs(domi::tensorflow::GraphDef *graph_def, domi::tensorflow::NodeDef *node_def,
- const set<uint32_t> &remove_index_set,
- const map<string, NodeDef *> &all_node_map) const {
- GE_CHECK_NOTNULL(node_def);
- if (remove_index_set.empty()) {
- GELOGI("The size of remove_index_set is zero.");
- return SUCCESS;
- }
-
- map<string, vector<int>> remove_inputs_map;
- for (auto &it : remove_index_set) {
- const string &input_node_name = node_def->input(it);
- remove_inputs_map[input_node_name].emplace_back(it);
- GELOGD("Push input:%s, index:%d into remove map.", input_node_name.c_str(), it);
- }
-
- RemoveInputAttr(node_def, remove_inputs_map);
-
- int index = 0;
- vector<string> removed_inputs_vec;
- auto *inputs = node_def->mutable_input();
- for (auto input_it = inputs->begin(); input_it != inputs->end(); ++index) {
- // 1.decide whether to remove the input
- bool flag = false;
- for (auto &remove_input : remove_inputs_map) {
- string remove_input_name = remove_input.first;
- vector<int> remove_input_indexs = remove_input.second;
- if (((*input_it) == remove_input_name) &&
- (std::find(remove_input_indexs.begin(), remove_input_indexs.end(), index) != remove_input_indexs.end())) {
- GELOGD("Remove input:%s, index:%d", remove_input_name.c_str(), index);
- flag = true;
- removed_inputs_vec.emplace_back(remove_input_name);
- break;
- }
- }
-
- if (flag) {
- // 2 remove the input
- input_it = inputs->erase(input_it);
- } else {
- ++input_it;
- }
- }
-
- Status ret = AddControlEdgeAfterRemoveInputs(graph_def, node_def, all_node_map, removed_inputs_vec);
- if (ret != SUCCESS) {
- GELOGE(FAILED, "Add control edges for node:%s failed.", node_def->name().c_str());
- return FAILED;
- }
- return SUCCESS;
- }
-
- void TensorFlowModelParser::RemoveInputAttr(domi::tensorflow::NodeDef *node_def,
- const map<string, vector<int>> &remove_inputs_map) const {
- // The caller guarantees that the pointer is not null
- auto *inputs = node_def->mutable_input();
- google::protobuf::Map<std::string, domi::tensorflow::AttrValue> *attr_map = node_def->mutable_attr();
- const google::protobuf::Map<std::string, domi::tensorflow::AttrValue>::iterator it =
- attr_map->find(ge::ATTR_NAME_INPUT_TENSOR_DESC);
- if (it == attr_map->end()) {
- GELOGW("Failed to find input desc from tf node_def[%s]", node_def->name().c_str());
- return;
- }
- domi::tensorflow::AttrValue *input_attr_value = &(it->second);
- auto tmp_attr = input_attr_value->mutable_list()->mutable_func();
- auto attr_it = tmp_attr->begin();
- int index = 0;
- for (auto input_it = inputs->begin(); input_it != inputs->end(); ++input_it, ++index) {
- // 1.decide whether to remove the input
- bool flag = false;
- for (auto &remove_input : remove_inputs_map) {
- string remove_input_name = remove_input.first;
- vector<int> remove_input_indexs = remove_input.second;
- if ((*input_it) == remove_input_name &&
- std::find(remove_input_indexs.begin(), remove_input_indexs.end(), index) != remove_input_indexs.end()) {
- GELOGD("Remove input attr:%s, index:%d", remove_input_name.c_str(), index);
- flag = true;
- break;
- }
- }
-
- if (flag) {
- // 2.1 remove the input attr
- if (!tmp_attr->empty() && (attr_it != tmp_attr->end())) {
- attr_it = tmp_attr->erase(attr_it);
- } else {
- ++attr_it;
- }
- } else {
- ++attr_it;
- }
- }
- }
-
- Status TensorFlowModelParser::GetTensorflowGraphInOutMap(domi::tensorflow::GraphDef *graph_def) {
- GE_CHECK_NOTNULL(graph_def);
- for (int i = 0; i < graph_def->node_size(); i++) {
- domi::tensorflow::NodeDef *node = graph_def->mutable_node(i);
- const string &node_name = node->name();
- node_inputs_outputs_map_.emplace(node_name, std::pair<set<string>, set<string>>{});
- for (const auto &input : node->input()) {
- string input_node_name;
- GE_RETURN_IF_ERROR(CheckInputNodeName(input, &input_node_name, nullptr, nullptr));
- node_inputs_outputs_map_[node_name].first.insert(input_node_name);
- node_inputs_outputs_map_[input_node_name].second.insert(node_name);
- }
- }
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::RemoveIsolateNode(domi::tensorflow::GraphDef *graph_def) {
- GE_CHECK_NOTNULL(graph_def);
- set<string> node_to_delete;
- for (int i = 0; i < graph_def->node_size(); i++) {
- domi::tensorflow::NodeDef *node = graph_def->mutable_node(i);
- const string &node_name = node->name();
- if (node_inputs_outputs_map_.find(node_name) == node_inputs_outputs_map_.end()) {
- REPORT_INNER_ERROR("E19999", "Node:%s can't find in node_inputs_outputs_map_, check invalid", node_name.c_str());
- GELOGE(FAILED, "Can not find input output context, node:%s.", node_name.c_str());
- return FAILED;
- }
- if ((node_inputs_outputs_map_[node_name].first.empty() && node_inputs_outputs_map_[node_name].second.empty() &&
- node->op() != kDpop) ||
- (node->op() == ge::parser::CONSTANT && node_inputs_outputs_map_[node_name].second.empty())) {
- GELOGI("%s will inset to node_to_delete", node_name.c_str());
- node_to_delete.insert(node_name);
- }
- }
-
- // delete isolate nodes
- auto nodeList = graph_def->mutable_node();
- for (auto iter = nodeList->begin(); iter != nodeList->end();) {
- if (node_to_delete.count(iter->name()) != 0) {
- GELOGI("%s has zero input and output, will delete.", iter->name().c_str());
- iter = nodeList->erase(iter);
- } else {
- iter++;
- }
- }
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::RecordFusionResult(const std::shared_ptr<ge::ScopeGraph> &scope_graph,
- const domi::tensorflow::NodeDef *node, const ge::OpDescPtr &op_desc) {
- // The caller guarantees that the pointer is not null
- GELOGI("RecordFusionResult for %s start.", op_desc->GetName().c_str());
- auto &impl_scope_graph = scope_graph->impl_;
- ge::FusionScopesResult *fusion_result = impl_scope_graph->GetFusionScopesResults(node);
- if (fusion_result == nullptr) {
- GELOGW("fusion_result is not found.");
- return SUCCESS;
- }
-
- std::vector<std::string> original_names;
- auto nodes = fusion_result->Nodes();
- std::transform(nodes.begin(), nodes.end(), std::back_inserter(original_names),
- [](ge::OperatorPtr n) -> std::string { return ParserUtils::GetOperatorName(*n); });
-
- GELOGI("Op %s original_names size = %zu.", op_desc->GetName().c_str(), original_names.size());
- bool ret = ge::AttrUtils::SetListStr(op_desc, ge::ATTR_NAME_DATA_DUMP_ORIGIN_OP_NAMES, original_names);
- if (!ret) {
- GELOGW("Set %s to %s fail.", ge::ATTR_NAME_DATA_DUMP_ORIGIN_OP_NAMES.c_str(), op_desc->GetName().c_str());
- }
- auto outputs_desc = op_desc->GetAllOutputsDesc();
- auto &impl = fusion_result->impl_;
- for (auto &fusion_output : impl->GetOutputs()) {
- for (size_t i = 0; i < fusion_output.second.size(); ++i) {
- if (fusion_output.second[i] == ge::kFusionDisableIndex) {
- continue;
- }
-
- if (fusion_output.second[i] >= static_cast<int32_t>(op_desc->GetOutputsSize())) {
- REPORT_INNER_ERROR("E19999", "fusion output index:%d of node:%s(%s) must less than outputs desc size %zu.",
- fusion_output.second[i], op_desc->GetName().c_str(), op_desc->GetType().c_str(),
- op_desc->GetOutputsSize());
- GELOGE(PARAM_INVALID, "fusion output index %d must less than outputs desc size %zu.", fusion_output.second[i],
- op_desc->GetOutputsSize());
- return PARAM_INVALID;
- }
-
- ret = ge::AttrUtils::SetStr(op_desc->MutableOutputDesc(fusion_output.second[i]),
- ge::ATTR_NAME_DATA_DUMP_ORIGIN_NAME, fusion_output.first);
- if (!ret) {
- GELOGW("Set %s to %s %d output fail.", ge::ATTR_NAME_DATA_DUMP_ORIGIN_NAME.c_str(), op_desc->GetName().c_str(),
- fusion_output.second[i]);
- }
-
- ret = ge::AttrUtils::SetInt(op_desc->MutableOutputDesc(fusion_output.second[i]),
- ge::ATTR_NAME_DATA_DUMP_ORIGIN_OUTPUT_INDEX, i);
- if (!ret) {
- GELOGW("Set %s to %s %d output fail.", ge::ATTR_NAME_DATA_DUMP_ORIGIN_OUTPUT_INDEX.c_str(),
- op_desc->GetName().c_str(), fusion_output.second[i]);
- }
- }
- }
-
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::SetOriginNodeContext(const NodeDef *node_def, OpNodeContext &op_node_context,
- const std::vector<std::pair<std::string, int32_t>> &inputs,
- const std::vector<std::pair<std::string, int32_t>> &outputs) {
- int32_t in_index = 0;
- for (const auto &in : inputs) {
- bool is_ctrl = in.second == kControlSlot;
- op_node_context.input_map[in.first].emplace_back(std::make_pair(in.second, is_ctrl ? kControlSlot : in_index));
- SaveEdgesControlInfo(node_def->name(), is_ctrl);
- in_index = is_ctrl ? in_index : in_index + 1;
- }
- int32_t out_index = 0;
- for (const auto &out : outputs) {
- bool is_ctrl = out.second == kControlSlot;
- op_node_context.output_map[out.first].emplace_back(std::make_pair(is_ctrl ? kControlSlot : out_index, out.second));
- out_index = is_ctrl ? out_index : out_index + 1;
- }
- return SUCCESS;
- }
-
- void TensorFlowModelParser::GetFusionInputInfo(
- const string &fusion_op_name, OpNodeContext &fusion_context,
- std::map<string, std::pair<std::string, std::pair<int32_t, int32_t>>> &remap_data_input,
- std::map<string, std::vector<string>> &remap_ctrl_input, std::set<string> &fusion_input_nodes) {
- for (const auto &fusion_input : fusion_context.input_map) {
- string fusion_src_name = fusion_input.first;
- for (const auto &fusion_idx_pair : fusion_input.second) {
- string key = fusion_op_name + std::to_string(fusion_idx_pair.second);
- if (fusion_idx_pair.second != kControlSlot) {
- remap_data_input[key] = {fusion_src_name, {fusion_idx_pair.first, fusion_idx_pair.second}};
- } else {
- remap_ctrl_input[key].emplace_back(fusion_src_name);
- }
- }
- fusion_input_nodes.insert(fusion_src_name);
- }
- }
-
- void TensorFlowModelParser::GetFusionOutputInfo(
- const string &fusion_op_name, OpNodeContext &fusion_context,
- std::map<string, std::vector<std::pair<std::string, std::pair<int32_t, int32_t>>>> &remap_data_output,
- std::map<string, std::vector<string>> &remap_ctrl_output, std::set<string> &fusion_output_nodes) {
- for (const auto &fusion_output : fusion_context.output_map) {
- string fusion_dst_name = fusion_output.first;
- for (const auto &fusion_idx_pair : fusion_output.second) {
- string key = fusion_op_name + std::to_string(fusion_idx_pair.first);
- if (fusion_idx_pair.first != kControlSlot) {
- remap_data_output[key].emplace_back(
- std::make_pair(fusion_dst_name, std::make_pair(fusion_idx_pair.first, fusion_idx_pair.second)));
- } else {
- remap_ctrl_output[key].emplace_back(fusion_dst_name);
- }
- }
- fusion_output_nodes.insert(fusion_dst_name);
- }
- }
-
- void TensorFlowModelParser::UpdateInnerInputMap(const string &fusion_op_name, OpNodeContext &fusion_context,
- const std::vector<std::string> &inner_nodes_name,
- std::set<string> &fusion_input_nodes) {
- std::map<string, std::pair<std::string, std::pair<int32_t, int32_t>>> remap_data_input;
- std::map<string, std::vector<string>> remap_ctrl_input;
- GetFusionInputInfo(fusion_op_name, fusion_context, remap_data_input, remap_ctrl_input, fusion_input_nodes);
-
- for (const auto &node_name : inner_nodes_name) {
- auto context_iter = op_node_context_map_.find(node_name);
- if (context_iter != op_node_context_map_.end()) {
- OpNodeContext &op_node_context = context_iter->second;
- // update input map of inner node
- std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> tmp_input_map;
- for (auto iter = op_node_context.input_map.begin(); iter != op_node_context.input_map.end();) {
- string src_name = iter->first;
- if (src_name == ge::kInputFromFusionScope) {
- std::vector<std::pair<int32_t, int32_t>> &input_idx = iter->second;
- for (const auto &in_pair : input_idx) {
- if (in_pair.second != kControlSlot) {
- auto data = remap_data_input[fusion_op_name + std::to_string(in_pair.first)];
- tmp_input_map[data.first].emplace_back(std::make_pair(data.second.first, in_pair.second));
- GELOGI("Update inner input, src:%s, idx:%u->%u", data.first.c_str(), data.second.first, in_pair.second);
- }
- }
- auto ctrl = remap_ctrl_input[fusion_op_name + std::to_string(kControlSlot)];
- for (const auto &ctrl_in : ctrl) {
- tmp_input_map[ctrl_in].emplace_back(std::make_pair(kControlSlot, kControlSlot));
- SaveEdgesControlInfo(node_name, kControlSlot);
- }
- iter = op_node_context.input_map.erase(iter);
- } else {
- ++iter;
- }
- }
- op_node_context.input_map.insert(tmp_input_map.cbegin(), tmp_input_map.cend());
- // update output map of pre node
- for (const auto &in_iter : op_node_context.input_map) {
- auto src_iter = op_node_context_map_.find(in_iter.first);
- if (src_iter != op_node_context_map_.end()) {
- std::vector<std::pair<int32_t, int32_t>> input_pairs = in_iter.second;
- OpNodeContext &src_context = src_iter->second;
- src_context.output_map[node_name].assign(input_pairs.begin(), input_pairs.end());
- }
- }
- }
- }
- }
-
- void TensorFlowModelParser::UpdateInnerOutputMap(const string &fusion_op_name, OpNodeContext &fusion_context,
- const std::vector<std::string> &inner_nodes_name,
- std::set<string> &fusion_output_nodes) {
- std::map<string, std::vector<std::pair<std::string, std::pair<int32_t, int32_t>>>> remap_data_output;
- std::map<string, std::vector<string>> remap_ctrl_output;
- GetFusionOutputInfo(fusion_op_name, fusion_context, remap_data_output, remap_ctrl_output, fusion_output_nodes);
- for (const auto &node_name : inner_nodes_name) {
- auto context_iter = op_node_context_map_.find(node_name);
- if (context_iter != op_node_context_map_.end()) {
- OpNodeContext &op_node_context = context_iter->second;
- // update output map of inner node
- std::map<std::string, std::vector<std::pair<int32_t, int32_t>>> tmp_output_map;
- for (auto iter = op_node_context.output_map.begin(); iter != op_node_context.output_map.end();) {
- string dst_name = iter->first;
- if (dst_name == ge::kOutputToFusionScope) {
- std::vector<std::pair<int32_t, int32_t>> &output_idx = iter->second;
- for (const auto &out_pair : output_idx) {
- if (out_pair.second != kControlSlot) {
- auto data_outputs = remap_data_output[fusion_op_name + std::to_string(out_pair.second)];
- for (const auto &data : data_outputs) {
- tmp_output_map[data.first].emplace_back(std::make_pair(out_pair.first, data.second.second));
- GELOGI("Update inner output, dst:%s, idx:%u->%u.", data.first.c_str(), out_pair.first,
- data.second.second);
- }
- }
- }
- auto ctrl = remap_ctrl_output[fusion_op_name + std::to_string(kControlSlot)];
- for (const auto &ctrl_in : ctrl) {
- tmp_output_map[ctrl_in].emplace_back(std::make_pair(kControlSlot, kControlSlot));
- }
- iter = op_node_context.output_map.erase(iter);
- } else {
- ++iter;
- }
- }
- op_node_context.output_map.insert(tmp_output_map.cbegin(), tmp_output_map.cend());
- // update input map of pre node
- for (const auto &out_iter : op_node_context.output_map) {
- auto dst_iter = op_node_context_map_.find(out_iter.first);
- if (dst_iter != op_node_context_map_.end()) {
- std::vector<std::pair<int32_t, int32_t>> output_pairs = out_iter.second;
- OpNodeContext &dst_context = dst_iter->second;
- dst_context.input_map[node_name].assign(output_pairs.begin(), output_pairs.end());
- }
- }
- }
- }
- }
-
- Status TensorFlowModelParser::UpdateInnerNodeContext(const string &fusion_op_name,
- const std::vector<std::string> &inner_nodes_name) {
- auto fusion_iter = op_node_context_map_.find(fusion_op_name);
- if (fusion_iter == op_node_context_map_.end()) {
- REPORT_INNER_ERROR("E19999", "Node:%s can't find in op_node_context_map_, check invalid", fusion_op_name.c_str());
- GELOGE(INTERNAL_ERROR, "Can't find context for fusion node %s.", fusion_op_name.c_str());
- return INTERNAL_ERROR;
- }
- OpNodeContext &fusion_context = fusion_iter->second;
- std::set<string> fusion_input_nodes;
- std::set<string> fusion_output_nodes;
- UpdateInnerInputMap(fusion_op_name, fusion_context, inner_nodes_name, fusion_input_nodes);
- UpdateInnerOutputMap(fusion_op_name, fusion_context, inner_nodes_name, fusion_output_nodes);
- for (const auto &in_name : fusion_input_nodes) {
- auto fusion_in = op_node_context_map_.find(in_name);
- if (fusion_in != op_node_context_map_.end()) {
- OpNodeContext &fusion_in_context = fusion_in->second;
- fusion_in_context.output_map.erase(fusion_op_name);
- }
- }
- for (const auto &out_name : fusion_output_nodes) {
- auto fusion_out = op_node_context_map_.find(out_name);
- if (fusion_out != op_node_context_map_.end()) {
- OpNodeContext &fusion_out_context = fusion_out->second;
- fusion_out_context.input_map.erase(fusion_op_name);
- }
- }
- op_node_context_map_.erase(fusion_op_name);
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::AddFusionInnerNodeDef(shared_ptr<ge::ScopeGraph> &scope_graph,
- const string &fusion_op_name, vector<string> &node_name_list) {
- auto &impl_scope_graph = scope_graph->impl_;
- GE_CHECK_NOTNULL(impl_scope_graph);
- ge::FusionScopesResult *fusion_result = impl_scope_graph->GetFusionScopesResults(fusion_op_name);
- GE_CHECK_NOTNULL(fusion_result);
- auto &impl_fusion_rlt = fusion_result->impl_;
- GE_CHECK_NOTNULL(impl_fusion_rlt);
- ge::FusionInnerNodesInfo inner_nodes_info = impl_fusion_rlt->GetInnerNodesInfo();
- vector<string> inner_nodes_name;
- for (const auto &info : inner_nodes_info) {
- string node_name;
- string type;
- std::vector<std::pair<std::string, int32_t>> inputs;
- std::vector<std::pair<std::string, int32_t>> outputs;
- const ge::Operator *op = nullptr;
- std::tie(node_name, type, inputs, outputs, op) = info;
- NodeDef *node_def = new (std::nothrow) NodeDef();
- GE_CHECK_NOTNULL(node_def);
- node_def->set_name(node_name);
- node_def->set_op(type);
- nodedef_map_[node_name] = node_def;
- fusion_nodedef_list.push_back(node_def);
- for (const auto &in : inputs) {
- // The input value is not used in the subsequent process. The value is added only for placeholders.
- node_def->add_input(in.first);
- }
- domi::tensorflow::AttrValue attr_value;
- attr_value.set_b(true);
- ge::TensorFlowUtil::AddNodeAttr(kAttrNameIsScopeInnerNode, attr_value, node_def);
- OpNodeContext &op_node_context = op_node_context_map_[node_name];
- Status ret = SetOriginNodeContext(node_def, op_node_context, inputs, outputs);
- if (ret != SUCCESS) {
- GELOGE(ret, "Failed to add context and attrs, node:%s.", node_name.c_str());
- return ret;
- }
- scope_inner_node_map_.insert({node_name, op});
- node_name_list.emplace_back(node_name);
- inner_nodes_name.emplace_back(node_name);
- GELOGI("Add fusion inner node def, name:%s, type:%s.", node_name.c_str(), type.c_str());
- }
- Status ret = UpdateInnerNodeContext(fusion_op_name, inner_nodes_name);
- if (ret != SUCCESS) {
- GELOGE(ret, "Failed to update inner node context, fusion_op_name:%s.", fusion_op_name.c_str());
- return ret;
- }
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::AddFusionNodeDef(shared_ptr<ge::ScopeGraph> &scope_graph,
- vector<string> &node_name_list) {
- vector<string> node_name_list_new;
- size_t op_node_list_size = node_name_list.size();
- DumpAllNodeContext("BeforeAddFusionNodeDef");
- for (size_t i = 0; i < op_node_list_size; ++i) {
- const string op_node_name = node_name_list[i];
- std::map<string, vector<const NodeDef *>>::const_iterator iter = fusion_op_nodedef_map_.find(op_node_name);
- if (iter != fusion_op_nodedef_map_.end()) {
- vector<string> fusion_op_info = fusion_op_type_map_[op_node_name];
- if (fusion_op_info[0] != ge::kScopeToMultiNodes) {
- NodeDef *node_def = new (std::nothrow) NodeDef();
- GE_CHECK_NOTNULL(node_def);
- node_def->set_name(op_node_name);
- node_def->set_op(fusion_op_info[0]);
- nodedef_map_[op_node_name] = node_def;
- fusion_nodedef_list.push_back(node_def);
- OpNodeContext &node_context = op_node_context_map_[node_def->name()];
- for (const auto &input : node_context.input_map) {
- // The input value is not used in the subsequent process. The value is added only for placeholders.
- node_def->add_input(input.first);
- }
- node_name_list_new.emplace_back(op_node_name);
- GELOGI("Add Fusion node def, name:%s, type:%s.", node_def->name().c_str(), node_def->op().c_str());
- } else {
- Status ret = AddFusionInnerNodeDef(scope_graph, op_node_name, node_name_list_new);
- if (ret != SUCCESS) {
- REPORT_INNER_ERROR("E19999",
- "Failed to add fusion inner nodes for fusion op:%s, "
- "please check FusionScopesResult set in scope fusion pass",
- op_node_name.c_str());
- GELOGE(ret, "Failed to add fusion inner node, fusion_op_name:%s.", op_node_name.c_str());
- return ret;
- }
- GELOGI("Add fusion inner nodes successfully, fusion name:%s.", op_node_name.c_str());
- op_node_context_map_.erase(op_node_name);
- }
- } else {
- node_name_list_new.emplace_back(op_node_name);
- }
- }
- node_name_list.clear();
- node_name_list.assign(node_name_list_new.begin(), node_name_list_new.end());
- DumpAllNodeContext("AfterAddFusionNodeDef");
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::AddScopeInnerNode(TensorFlowModelParser *parser, ge::ComputeGraphPtr &graph,
- std::mutex *const graph_mutex,
- const domi::tensorflow::NodeDef *node_def) {
- // This is an internal function. The pointer input parameter is not empty when this function is invoked.
- string node_name = node_def->name();
- string node_op = node_def->op();
- auto iter = parser->scope_inner_node_map_.find(node_name);
- if (iter == parser->scope_inner_node_map_.end()) {
- REPORT_INNER_ERROR("E19999", "Node:%s can't find in scope_inner_node_map_, check invalid", node_name.c_str());
- GELOGE(PARAM_INVALID, "Failed to find scope inner node:%s, type:%s.", node_name.c_str(), node_op.c_str());
- return PARAM_INVALID;
- }
- const ge::Operator *op = iter->second;
- ge::OpDescPtr op_desc = ge::OpDescUtils::GetOpDescFromOperator(*op);
- GE_CHECK_NOTNULL(op_desc);
- ge::NodePtr node;
- {
- std::lock_guard<std::mutex> lock(*graph_mutex);
- node = graph->AddNode(op_desc);
- }
- if (node == nullptr) {
- REPORT_CALL_ERROR("E19999", "Add node:%s(%s) to graph:%s failed", op_desc->GetName().c_str(),
- op_desc->GetType().c_str(), graph->GetName().c_str());
- GELOGE(INTERNAL_ERROR, "Failed to Add scope inner node:%s, type:%s.", op_desc->GetName().c_str(),
- op_desc->GetType().c_str());
- return INTERNAL_ERROR;
- }
- {
- std::lock_guard<std::mutex> lock(parser->nodeMapMutex_);
- parser->node_map_[node_name] = node;
- }
- GELOGI("Add scope inner node successfully, node name:%s, type:%s.", op_desc->GetName().c_str(),
- op_desc->GetType().c_str());
- return SUCCESS;
- }
-
- void TensorFlowModelParser::DumpNodeContext(const string &node_name, const OpNodeContext &ctx, const string &phase) {
- GELOGD("phase:%s === Begin to dump context for node:%s ===", phase.c_str(), node_name.c_str());
- for (const auto &input : ctx.input_map) {
- for (const auto &input_idx : input.second) {
- GELOGD(" Input info: %s:%d --> in_idx %d.", input.first.c_str(), input_idx.first, input_idx.second);
- }
- }
- for (const auto &output : ctx.output_map) {
- for (const auto &output_idx : output.second) {
- GELOGD(" Output info: out_idx %d --> %s:%d.", output_idx.first, output.first.c_str(), output_idx.second);
- }
- }
- GELOGD("phase:%s === End to dump context for node:%s ===", phase.c_str(), node_name.c_str());
- }
-
- void TensorFlowModelParser::DumpAllNodeContext(const string &phase) const {
- if (!IsLogEnable(GE_MODULE_NAME, DLOG_DEBUG)) {
- return;
- }
- for (const auto &iter : op_node_context_map_) {
- DumpNodeContext(iter.first, iter.second, phase);
- }
- }
-
- Status TensorFlowModelParser::CheckAndUpdateInputDesc(const ge::ComputeGraphPtr &compute_graph) {
- GE_CHECK_NOTNULL(compute_graph);
- for (auto &node : compute_graph->GetDirectNode()) {
- auto op_desc = node->GetOpDesc();
- GE_CHECK_NOTNULL(op_desc);
- for (auto &in_anchor : node->GetAllInDataAnchors()) {
- if (!(op_desc->IsOptionalInput(static_cast<uint32_t>(in_anchor->GetIdx())))) {
- continue;
- }
- auto peer_out_anchor = in_anchor->GetPeerOutAnchor();
- auto in_desc = op_desc->MutableInputDesc(static_cast<uint32_t>(in_anchor->GetIdx()));
- if ((peer_out_anchor != nullptr) && (in_desc == nullptr)) {
- // The input is connected to the peer output but TensorDesc is invalid, update TensorDesc to valid.
- ge::GeTensorDesc tensor_desc;
- auto ret = op_desc->UpdateInputDesc(static_cast<uint32_t>(in_anchor->GetIdx()), tensor_desc);
- if (ret != ge::GRAPH_SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Update index:%d of input desc in op:%s(%s) failed", in_anchor->GetIdx(),
- op_desc->GetName().c_str(), op_desc->GetType().c_str());
- GELOGE(ret, "Failed to update input desc, node:%s, index:%d.", node->GetName().c_str(), in_anchor->GetIdx());
- return ret;
- }
- GELOGI("Update input desc to valid, node:%s, index:%d.", node->GetName().c_str(), in_anchor->GetIdx());
- } else if ((peer_out_anchor == nullptr) && (in_desc != nullptr)) {
- // The input is not connected to the peer output but TensorDesc is valid, update TensorDesc to invalid.
- ge::GeTensorDesc tensor_desc(ge::GeShape(), FORMAT_RESERVED, DT_UNDEFINED);
- auto ret = op_desc->UpdateInputDesc(static_cast<uint32_t>(in_anchor->GetIdx()), tensor_desc);
- if (ret != ge::GRAPH_SUCCESS) {
- REPORT_CALL_ERROR("E19999", "Update index:%d of input desc in op:%s(%s) failed", in_anchor->GetIdx(),
- op_desc->GetName().c_str(), op_desc->GetType().c_str());
- GELOGE(ret, "Failed to update input desc, node:%s, index:%d.", node->GetName().c_str(), in_anchor->GetIdx());
- return ret;
- }
- GELOGI("Update input desc to invalid, node:%s, index:%d.", node->GetName().c_str(), in_anchor->GetIdx());
- }
- }
- }
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::UpdateOutputsInfo(const ParserUtils::OutputMapping &final_output_nodes) {
- auto &user_specified_nodes = ge::GetParserContext().user_out_nodes;
- if (!user_specified_nodes.empty()) {
- for (auto &output_node_info : user_specified_nodes) {
- ParserUtils::UpdateOutputNodeInfo(final_output_nodes, output_node_info);
- }
- }
- return SUCCESS;
- }
-
- Status TensorFlowModelParser::AddExternalGraph(const ComputeGraphPtr &root_graph) {
- GE_CHECK_NOTNULL(root_graph);
- for (const NodePtr &node : root_graph->GetAllNodes()) {
- if ((node == nullptr) || (node->GetOpDesc() == nullptr)) {
- continue;
- }
- std::string model_data;
- if (AttrUtils::GetStr(node->GetOpDesc(), kExternalModel, model_data) && !model_data.empty()) {
- ge::Model model;
- auto load_ret = ge::Model::Load(ge::PtrToPtr<char_t, const uint8_t>(model_data.data()), model_data.size(), model);
- if (load_ret != GRAPH_SUCCESS) {
- GELOGE(INTERNAL_ERROR, "[Parse][ExternalModel]Node:%s.", node->GetName().c_str());
- REPORT_CALL_ERROR("E19999", "Failed to parse external model, node:%s.", node->GetName().c_str());
- return INTERNAL_ERROR;
- }
- Graph graph = model.GetGraph();
- GELOGD("Get subgraph[%s] from model[%s].", ParserUtils::GetGraphName(graph).c_str(), node->GetName().c_str());
- Status ret = MappingAndAddSubGraph(node, graph, root_graph);
- if (ret != SUCCESS) {
- GELOGE(INTERNAL_ERROR, "[Mapping][Subgraph]Node:%s.", node->GetName().c_str());
- REPORT_CALL_ERROR("E19999", "Failed to map and add sub graph, node:%s.", node->GetName().c_str());
- return INTERNAL_ERROR;
- }
- (void)node->GetOpDesc()->DelAttr(kExternalModel);
- }
- }
- return SUCCESS;
- }
- } // namespace ge
-
- namespace domi {
- REGISTER_MODEL_PARSER_CREATOR(TENSORFLOW, ge::TensorFlowModelParser);
- REGISTER_WEIGHTS_PARSER_CREATOR(TENSORFLOW, ge::TensorFlowWeightsParser);
- } // namespace domi
|