| @@ -45,7 +45,7 @@ using abstract::AnfNodeConfigPtr; | |||||
| std::string GetAbstractStr(const abstract::AbstractBasePtr &abs) { | std::string GetAbstractStr(const abstract::AbstractBasePtr &abs) { | ||||
| if (abs == nullptr) { | if (abs == nullptr) { | ||||
| return "Null Abstract"; | |||||
| return "NullAbstract"; | |||||
| } | } | ||||
| auto shape = abs->BuildShape()->cast<abstract::ShapePtr>(); | auto shape = abs->BuildShape()->cast<abstract::ShapePtr>(); | ||||
| TypePtr type = abs->BuildType(); | TypePtr type = abs->BuildType(); | ||||
| @@ -132,7 +132,8 @@ class AnalyzedFuncGraphExporter : public AnfExporter { | |||||
| std::string GetNodeType(const AnfNodePtr &nd) override; | std::string GetNodeType(const AnfNodePtr &nd) override; | ||||
| AbstractBasePtr GetNodeAbstract(const AnfNodePtr &nd); | AbstractBasePtr GetNodeAbstract(const AnfNodePtr &nd); | ||||
| AnfNodeConfigPtr GetFordwardConfigPtr(const AnfNodeConfigPtr &cfg); | AnfNodeConfigPtr GetFordwardConfigPtr(const AnfNodeConfigPtr &cfg); | ||||
| AnalysisContextPtr ProcessFuncGraphCall(const CNodePtr &node); | |||||
| std::vector<AnalysisContextPtr> ProcessFuncGraphCall(const CNodePtr &node, std::string *const op_comment); | |||||
| void OutputStatementComment(std::ofstream &ofs, const CNodePtr &node, const std::vector<AnalysisContextPtr> &ctxs); | |||||
| // key: context, val: whether the context has already been printed | // key: context, val: whether the context has already been printed | ||||
| std::unordered_map<AnalysisContextPtr, bool> context_map_; | std::unordered_map<AnalysisContextPtr, bool> context_map_; | ||||
| @@ -170,21 +171,7 @@ std::string AnalyzedFuncGraphExporter::GetNodeType(const AnfNodePtr &node) { | |||||
| if (ret == nullptr) { | if (ret == nullptr) { | ||||
| return "Undefined"; | return "Undefined"; | ||||
| } | } | ||||
| auto abs = ret->abstract(); | |||||
| if (abs == nullptr) { | |||||
| return "Undefined"; | |||||
| } | |||||
| auto dtype = abs->BuildType(); | |||||
| auto shape = abs->BuildShape(); | |||||
| std::ostringstream oss; | |||||
| if (dtype != nullptr && abs->isa<abstract::AbstractTensor>() && shape != nullptr) { | |||||
| oss << dtype->DumpText() << shape->DumpText(); | |||||
| } else if (dtype != nullptr) { | |||||
| oss << dtype->DumpText(); | |||||
| } else { | |||||
| oss << "Undefined"; | |||||
| } | |||||
| return oss.str(); | |||||
| return GetAbstractStr(ret->abstract()); | |||||
| } | } | ||||
| AbstractBasePtr AnalyzedFuncGraphExporter::GetNodeAbstract(const AnfNodePtr &node) { | AbstractBasePtr AnalyzedFuncGraphExporter::GetNodeAbstract(const AnfNodePtr &node) { | ||||
| @@ -210,44 +197,115 @@ AnfNodeConfigPtr AnalyzedFuncGraphExporter::GetFordwardConfigPtr(const AnfNodeCo | |||||
| return cur_cfg; | return cur_cfg; | ||||
| } | } | ||||
| AnalysisContextPtr AnalyzedFuncGraphExporter::ProcessFuncGraphCall(const CNodePtr &node) { | |||||
| std::vector<AnalysisContextPtr> AnalyzedFuncGraphExporter::ProcessFuncGraphCall(const CNodePtr &node, | |||||
| std::string *const op_comment) { | |||||
| std::vector<AnalysisContextPtr> ret_contexts; | |||||
| if (node == nullptr) { | if (node == nullptr) { | ||||
| return nullptr; | |||||
| return ret_contexts; | |||||
| } | } | ||||
| auto cfg = engine_->MakeConfig(node, cur_ctx_); | auto cfg = engine_->MakeConfig(node, cur_ctx_); | ||||
| cfg = GetFordwardConfigPtr(cfg); | cfg = GetFordwardConfigPtr(cfg); | ||||
| auto cnode = dyn_cast<CNode>(cfg->node()); | auto cnode = dyn_cast<CNode>(cfg->node()); | ||||
| if (cnode == nullptr) { | if (cnode == nullptr) { | ||||
| MS_LOG(DEBUG) << "CNode is nullptr"; | MS_LOG(DEBUG) << "CNode is nullptr"; | ||||
| return nullptr; | |||||
| return ret_contexts; | |||||
| } | } | ||||
| ret_contexts.resize(cnode->size()); | |||||
| const auto &inputs = cnode->inputs(); | const auto &inputs = cnode->inputs(); | ||||
| auto op_abs = GetNodeAbstract(inputs[0]); | |||||
| if (op_abs == nullptr) { | |||||
| MS_LOG(DEBUG) << "Abstract of inputs[0] of cnode " << cnode->ToString() << " is nullptr"; | |||||
| return nullptr; | |||||
| } | |||||
| for (size_t i = 0; i < inputs.size(); ++i) { | |||||
| auto op_abs = GetNodeAbstract(inputs[i]); | |||||
| if (op_abs == nullptr) { | |||||
| MS_LOG(DEBUG) << "Abstract of inputs[" << i << "] of cnode " << cnode->ToString() << " is nullptr"; | |||||
| continue; | |||||
| } | |||||
| if (!op_abs->isa<abstract::FuncGraphAbstractClosure>() && !op_abs->isa<abstract::MetaFuncGraphAbstractClosure>()) { | |||||
| MS_LOG(DEBUG) << "Inputs[0] of cnode " << cnode->ToString() << " is of type " << op_abs->type_name() | |||||
| << ", not function, ignore it"; | |||||
| return nullptr; | |||||
| if (!op_abs->isa<abstract::FuncGraphAbstractClosure>() && !op_abs->isa<abstract::MetaFuncGraphAbstractClosure>()) { | |||||
| MS_LOG(DEBUG) << "Inputs[" << i << "] of cnode " << cnode->ToString() << " is of type " << op_abs->type_name() | |||||
| << ", not function, ignore it"; | |||||
| // Get prototype of VirtualEvaluator for printing | |||||
| if (i == 0 && op_abs->isa<abstract::VirtualAbstractClosure>()) { | |||||
| auto func = dyn_cast<abstract::VirtualAbstractClosure>(op_abs); | |||||
| std::ostringstream oss; | |||||
| oss << "("; | |||||
| bool first_flag = false; | |||||
| for (const auto &arg : func->args_spec_list()) { | |||||
| if (!first_flag) { | |||||
| first_flag = true; | |||||
| } else { | |||||
| oss << ", "; | |||||
| } | |||||
| oss << GetAbstractStr(arg); | |||||
| } | |||||
| oss << ") -> " << GetAbstractStr(func->output()) << " "; | |||||
| *op_comment = oss.str(); | |||||
| } | |||||
| continue; | |||||
| } | |||||
| auto evaluator = engine_->GetEvaluatorFor(dyn_cast<abstract::AbstractFunction>(op_abs)); | |||||
| if (!evaluator->isa<abstract::BaseFuncGraphEvaluator>()) { | |||||
| MS_LOG(DEBUG) << "Evaluator for inputs[" << i << "] of cnode " << cnode->ToString() << " is of type " | |||||
| << evaluator->type_name() << ", not BaseFuncGraphEvaluator, ignore it."; | |||||
| continue; | |||||
| } | |||||
| auto base_fg_evaluator = dyn_cast<abstract::BaseFuncGraphEvaluator>(evaluator); | |||||
| auto ctx = base_fg_evaluator->graph_context(); | |||||
| if (ctx != nullptr && context_map_.insert({ctx, false}).second) { | |||||
| MS_LOG(DEBUG) << "Add new context, ctx.addr = " << ctx.get() << "ctx = " << ctx->ToString(); | |||||
| context_vec_.push_back(ctx); | |||||
| } | |||||
| ret_contexts[i] = ctx; | |||||
| } | } | ||||
| return ret_contexts; | |||||
| } | |||||
| auto evaluator = engine_->GetEvaluatorFor(dyn_cast<abstract::AbstractFunction>(op_abs)); | |||||
| if (!evaluator->isa<abstract::BaseFuncGraphEvaluator>()) { | |||||
| MS_LOG(DEBUG) << "Evaluator for inputs[0] of cnode " << cnode->ToString() << " is of type " | |||||
| << evaluator->type_name() << ", not BaseFuncGraphEvaluator, ignore it."; | |||||
| return nullptr; | |||||
| void AnalyzedFuncGraphExporter::OutputStatementComment(std::ofstream &ofs, const CNodePtr &node, | |||||
| const std::vector<AnalysisContextPtr> &ctxs) { | |||||
| if (node == nullptr) { | |||||
| return; | |||||
| } | } | ||||
| auto base_fg_evaluator = dyn_cast<abstract::BaseFuncGraphEvaluator>(evaluator); | |||||
| auto ctx = base_fg_evaluator->graph_context(); | |||||
| if (ctx != nullptr && context_map_.insert({ctx, false}).second) { | |||||
| MS_LOG(DEBUG) << "Add new context, ctx.addr = " << ctx.get() << "ctx = " << ctx->ToString(); | |||||
| context_vec_.push_back(ctx); | |||||
| // output type of each input argument | |||||
| auto &inputs = node->inputs(); | |||||
| if (inputs.size() > 1) { | |||||
| ofs << " #("; | |||||
| for (size_t i = 1; i < inputs.size(); ++i) { | |||||
| if (i != 1) { | |||||
| ofs << ", "; | |||||
| } | |||||
| AnfNodePtr arg = inputs[i]; | |||||
| ofs << GetNodeType(arg); | |||||
| } | |||||
| ofs << ")"; | |||||
| } | |||||
| // output other comment, map the graph name to original representation(containing unicode character) | |||||
| std::ostringstream comment; | |||||
| comment << " #"; | |||||
| bool has_comment = false; | |||||
| for (size_t i = 0; i < inputs.size(); ++i) { | |||||
| AnfNodePtr arg = inputs[i]; | |||||
| if (!IsValueNode<FuncGraph>(arg)) { | |||||
| continue; | |||||
| } | |||||
| if (!has_comment) { | |||||
| has_comment = true; | |||||
| } else { | |||||
| comment << ","; | |||||
| } | |||||
| FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(arg); | |||||
| std::string func_graph_id = fg->debug_info()->get_id(); | |||||
| comment << " fg_" << func_graph_id << "=" << fg->ToString() << "." << func_graph_id; | |||||
| if (ctxs.size() > i && ctxs[i] != nullptr) { | |||||
| comment << "(@ctx.addr=" << ctxs[i].get() << ")"; | |||||
| } | |||||
| } | |||||
| if (has_comment) { | |||||
| ofs << comment.str(); | |||||
| } | } | ||||
| return ctx; | |||||
| ofs << " #scope: " << node->scope()->name(); | |||||
| } | } | ||||
| void AnalyzedFuncGraphExporter::OutputCNode(std::ofstream &ofs, const CNodePtr &cnode, const FuncGraphPtr &func_graph, | void AnalyzedFuncGraphExporter::OutputCNode(std::ofstream &ofs, const CNodePtr &cnode, const FuncGraphPtr &func_graph, | ||||
| @@ -278,10 +336,15 @@ void AnalyzedFuncGraphExporter::OutputCNode(std::ofstream &ofs, const CNodePtr & | |||||
| ofs << ")"; | ofs << ")"; | ||||
| // process function graph call | // process function graph call | ||||
| auto ctx = ProcessFuncGraphCall(cnode); | |||||
| std::string op_comment; | |||||
| auto contexts = ProcessFuncGraphCall(cnode, &op_comment); | |||||
| AnalysisContextPtr ctx = contexts.empty() ? nullptr : contexts[0]; | |||||
| if (!op_comment.empty()) { | |||||
| ofs << " #" << GetAnfNodeText(func_graph, inputs[0], *apply_map) << ".prototype = " << op_comment; | |||||
| } | |||||
| // output comment | // output comment | ||||
| OutputStatementComment(ofs, cnode); | |||||
| OutputStatementComment(ofs, cnode, contexts); | |||||
| if (ctx != nullptr) { | if (ctx != nullptr) { | ||||
| ofs << " @ctx.addr=" << ctx.get(); | ofs << " @ctx.addr=" << ctx.get(); | ||||
| } | } | ||||
| @@ -432,10 +495,10 @@ void GetEvalStackInfo(std::ostringstream &oss) { | |||||
| } | } | ||||
| OutputAnalyzedGraphWithType(); | OutputAnalyzedGraphWithType(); | ||||
| oss << "\nThe function call stack:\n"; | |||||
| oss << "\nThe function call stack (See file 'analyze_fail.dat' for details):\n"; | |||||
| int index = 0; | int index = 0; | ||||
| std::string last_py_func = ""; | |||||
| std::string last_location_info = ""; | |||||
| for (size_t i = 0; i < stack.size(); ++i) { | for (size_t i = 0; i < stack.size(); ++i) { | ||||
| auto node_cfg = stack[i]; | auto node_cfg = stack[i]; | ||||
| @@ -446,13 +509,13 @@ void GetEvalStackInfo(std::ostringstream &oss) { | |||||
| } | } | ||||
| auto debug_info = cnode->debug_info(); | auto debug_info = cnode->debug_info(); | ||||
| auto this_py_func = debug_info->get_python_func_belonged(); | |||||
| if (i > 0 && (this_py_func == last_py_func)) { | |||||
| MS_LOG(DEBUG) << "Python function of elements[" << i << "] is same as previous."; | |||||
| auto this_location_info = trace::GetDebugInfo(debug_info, std::string("")); | |||||
| if (this_location_info.empty() || this_location_info == last_location_info) { | |||||
| continue; | continue; | ||||
| } | } | ||||
| last_py_func = this_py_func; | |||||
| oss << "# " << index++ << " " << trace::GetDebugInfo(debug_info, std::string("")); | |||||
| last_location_info = this_location_info; | |||||
| oss << "# " << index++ << " " << this_location_info; | |||||
| } | } | ||||
| stack.clear(); | stack.clear(); | ||||
| @@ -463,6 +526,7 @@ void GetEvalStackInfo(std::ostringstream &oss) { | |||||
| static std::stack<std::pair<abstract::EvaluatorPtr, abstract::AnfNodeConfigPtr>> graph_infer_stack; | static std::stack<std::pair<abstract::EvaluatorPtr, abstract::AnfNodeConfigPtr>> graph_infer_stack; | ||||
| // trace the cnode infer debug info | // trace the cnode infer debug info | ||||
| static std::vector<abstract::AnfNodeConfigPtr> cnode_debug_stack{}; | static std::vector<abstract::AnfNodeConfigPtr> cnode_debug_stack{}; | ||||
| void TraceGraphEvalEnter(const abstract::EvaluatorPtr &eval, const abstract::AnfNodeConfigPtr &node) { | void TraceGraphEvalEnter(const abstract::EvaluatorPtr &eval, const abstract::AnfNodeConfigPtr &node) { | ||||
| if (eval == nullptr) { | if (eval == nullptr) { | ||||
| MS_LOG(EXCEPTION) << "GraphInferEnter got null eval"; | MS_LOG(EXCEPTION) << "GraphInferEnter got null eval"; | ||||