You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

trace.cc 20 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. /**
  2. * Copyright 2019-2021 Huawei Technologies Co., Ltd
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "debug/trace.h"
  17. #include <iostream>
  18. #include <fstream>
  19. #include <map>
  20. #include <unordered_map>
  21. #include <vector>
  22. #include <string>
  23. #include <sstream>
  24. #include <utility>
  25. #include <stack>
  26. #include <algorithm>
  27. #include "ir/meta_func_graph.h"
  28. #include "ir/graph_utils.h"
  29. #include "frontend/operator/composite/composite.h"
  30. #include "ir/tensor.h"
  31. #include "debug/anf_ir_utils.h"
  32. #include "debug/common.h"
  33. #include "pipeline/jit/static_analysis/evaluator.h"
  34. #include "utils/log_adapter.h"
  35. namespace mindspore {
  36. // namespace to support debug trace information
  37. namespace trace {
  38. using abstract::AbstractBasePtr;
  39. using abstract::AnalysisContextPtr;
  40. using abstract::AnalysisEnginePtr;
  41. using abstract::AnfNodeConfigPtr;
  42. std::string GetAbstractStr(const abstract::AbstractBasePtr &abs) {
  43. if (abs == nullptr) {
  44. return "NullAbstract";
  45. }
  46. auto shape = abs->BuildShape()->cast<abstract::ShapePtr>();
  47. TypePtr type = abs->BuildType();
  48. std::ostringstream oss;
  49. if ((shape != nullptr) && (type != nullptr)) {
  50. oss << type->DumpText() << shape->DumpText();
  51. } else if (type != nullptr) {
  52. oss << type->DumpText();
  53. } else {
  54. oss << "Undefined";
  55. }
  56. return oss.str();
  57. }
  58. std::string GetGraphParamString(const FuncGraphPtr &graph, abstract::AbstractBasePtrList args_spec_list) {
  59. std::ostringstream oss;
  60. oss << "graph:" << graph->ToString() << " with args[";
  61. auto params = graph->parameters();
  62. for (size_t i = 0; i < args_spec_list.size(); i++) {
  63. oss << params[i]->ToString() << ":<" << GetAbstractStr(args_spec_list[i]) << ">,";
  64. }
  65. oss << "]";
  66. oss << GetDebugInfo(graph->debug_info(), kSourceLineTipDiscard);
  67. return oss.str();
  68. }
  69. void DumpInferStack(std::ostringstream &oss) {
  70. auto &infer_stack = GetCurrenGraphEvalStack();
  71. if (infer_stack.empty()) {
  72. return;
  73. }
  74. std::vector<std::pair<abstract::EvaluatorPtr, abstract::AnfNodeConfigPtr>> infer_vec;
  75. while (!infer_stack.empty()) {
  76. auto top = infer_stack.top();
  77. infer_vec.push_back(top);
  78. infer_stack.pop();
  79. }
  80. std::reverse(infer_vec.begin(), infer_vec.end());
  81. int index = 0;
  82. for (auto &item : infer_vec) {
  83. auto graph_infer = std::dynamic_pointer_cast<abstract::BaseFuncGraphEvaluator>(item.first);
  84. if (graph_infer == nullptr) {
  85. MS_LOG(WARNING) << "DumpInferStack failed, got null graph evaluator";
  86. infer_vec.clear();
  87. break;
  88. }
  89. auto graph_context = graph_infer->graph_context();
  90. if (graph_context == nullptr) {
  91. MS_LOG(INFO) << "Null context continue";
  92. continue;
  93. }
  94. auto graph = graph_context->func_graph();
  95. auto args_spec_list = graph_context->args_spec_list();
  96. oss << " #" << index++ << " " << GetGraphParamString(graph, args_spec_list);
  97. }
  98. }
  99. void TraceGraphEval() {
  100. auto &infer_stack = GetCurrenGraphEvalStack();
  101. std::ostringstream oss;
  102. if (infer_stack.empty()) {
  103. return;
  104. }
  105. MS_LOG(INFO) << "\n*******************************graph evaluate stack**********************************";
  106. oss << std::endl;
  107. DumpInferStack(oss);
  108. MS_LOG(INFO) << oss.str();
  109. MS_LOG(INFO) << "\n*************************************************************************************";
  110. }
  111. class AnalyzedFuncGraphExporter : public AnfExporter {
  112. public:
  113. AnalyzedFuncGraphExporter() : AnfExporter(true, false) {}
  114. ~AnalyzedFuncGraphExporter() override = default;
  115. void ExportFuncGraph(const std::string &filename, const std::vector<abstract::AnfNodeConfigPtr> &node_cfgs);
  116. void ExportOneFuncGraph(std::ofstream &ofs, const FuncGraphPtr &func_graph);
  117. void OutputCNodes(std::ofstream &ofs, const std::vector<AnfNodePtr> &nodes, const FuncGraphPtr &func_graph);
  118. void OutputCNode(std::ofstream &ofs, const CNodePtr &cnode, const FuncGraphPtr &func_graph, int *idx,
  119. std::map<AnfNodePtr, int> *const apply_map);
  120. private:
  121. std::string GetNodeType(const AnfNodePtr &nd) override;
  122. AbstractBasePtr GetNodeAbstract(const AnfNodePtr &nd);
  123. AnfNodeConfigPtr GetFordwardConfigPtr(const AnfNodeConfigPtr &cfg);
  124. std::vector<AnalysisContextPtr> ProcessFuncGraphCall(const CNodePtr &node, std::string *const op_comment);
  125. void OutputStatementComment(std::ofstream &ofs, const CNodePtr &node, const std::vector<AnalysisContextPtr> &ctxs);
  126. // key: context, val: whether the context has already been printed
  127. std::unordered_map<AnalysisContextPtr, bool> context_map_;
  128. std::vector<AnalysisContextPtr> context_vec_;
  129. AnalysisContextPtr cur_ctx_ = nullptr;
  130. AnalysisEnginePtr engine_ = nullptr;
  131. };
  132. std::unordered_map<FuncGraphPtr, TaggedNodeMap> CalcTaggedFuncGraphs() {
  133. std::unordered_map<FuncGraphPtr, TaggedNodeMap> tagged_func_graphs;
  134. auto &list = GetCNodeDebugStack();
  135. for (size_t i = 0; i < list.size(); ++i) {
  136. auto node_cfg = list[i];
  137. auto fg = node_cfg->context()->func_graph();
  138. auto node = node_cfg->node();
  139. tagged_func_graphs[fg][node] = i;
  140. }
  141. return tagged_func_graphs;
  142. }
  143. void OutputAnalyzedGraphWithType(const string &file_path) {
  144. AnalyzedFuncGraphExporter exporter;
  145. exporter.ExportFuncGraph(file_path, GetCNodeDebugStack());
  146. }
  147. std::string AnalyzedFuncGraphExporter::GetNodeType(const AnfNodePtr &node) {
  148. if (cur_ctx_ == nullptr) {
  149. return AnfExporter::GetNodeType(node);
  150. }
  151. MS_EXCEPTION_IF_NULL(engine_);
  152. auto cfg = engine_->MakeConfig(node, cur_ctx_);
  153. auto ret = engine_->analysis_cache().GetValue(cfg);
  154. if (ret == nullptr) {
  155. return "Undefined";
  156. }
  157. return GetAbstractStr(ret->abstract());
  158. }
  159. AbstractBasePtr AnalyzedFuncGraphExporter::GetNodeAbstract(const AnfNodePtr &node) {
  160. if (cur_ctx_ == nullptr) {
  161. return nullptr;
  162. }
  163. MS_EXCEPTION_IF_NULL(engine_);
  164. auto cfg = engine_->MakeConfig(node, cur_ctx_);
  165. auto ret = engine_->analysis_cache().GetValue(cfg);
  166. return ret == nullptr ? nullptr : ret->abstract();
  167. }
  168. AnfNodeConfigPtr AnalyzedFuncGraphExporter::GetFordwardConfigPtr(const AnfNodeConfigPtr &cfg) {
  169. AnfNodeConfigPtr cur_cfg = cfg;
  170. auto iter = engine_->anfnode_config_map().find(cur_cfg);
  171. while (iter != engine_->anfnode_config_map().end()) {
  172. auto node = cur_cfg->node();
  173. cur_cfg = iter->second;
  174. MS_LOG(DEBUG) << "Get forword node: " << node.get() << "[" << node->ToString() << "] --> " << cur_cfg->node().get()
  175. << "[" << cur_cfg->node()->ToString() << "]";
  176. iter = engine_->anfnode_config_map().find(cur_cfg);
  177. }
  178. return cur_cfg;
  179. }
  180. std::vector<AnalysisContextPtr> AnalyzedFuncGraphExporter::ProcessFuncGraphCall(const CNodePtr &node,
  181. std::string *const op_comment) {
  182. std::vector<AnalysisContextPtr> ret_contexts;
  183. if (node == nullptr) {
  184. return ret_contexts;
  185. }
  186. auto cfg = engine_->MakeConfig(node, cur_ctx_);
  187. cfg = GetFordwardConfigPtr(cfg);
  188. auto cnode = dyn_cast<CNode>(cfg->node());
  189. if (cnode == nullptr) {
  190. MS_LOG(DEBUG) << "CNode is nullptr";
  191. return ret_contexts;
  192. }
  193. ret_contexts.resize(cnode->size());
  194. const auto &inputs = cnode->inputs();
  195. for (size_t i = 0; i < inputs.size(); ++i) {
  196. auto op_abs = GetNodeAbstract(inputs[i]);
  197. if (op_abs == nullptr) {
  198. MS_LOG(DEBUG) << "Abstract of inputs[" << i << "] of cnode " << cnode->ToString() << " is nullptr";
  199. continue;
  200. }
  201. if (!op_abs->isa<abstract::FuncGraphAbstractClosure>() && !op_abs->isa<abstract::MetaFuncGraphAbstractClosure>()) {
  202. MS_LOG(DEBUG) << "Inputs[" << i << "] of cnode " << cnode->ToString() << " is of type " << op_abs->type_name()
  203. << ", not function, ignore it";
  204. // Get prototype of VirtualEvaluator for printing
  205. if (i == 0 && op_abs->isa<abstract::VirtualAbstractClosure>()) {
  206. auto func = dyn_cast<abstract::VirtualAbstractClosure>(op_abs);
  207. std::ostringstream oss;
  208. oss << "(";
  209. bool first_flag = false;
  210. for (const auto &arg : func->args_spec_list()) {
  211. if (!first_flag) {
  212. first_flag = true;
  213. } else {
  214. oss << ", ";
  215. }
  216. oss << GetAbstractStr(arg);
  217. }
  218. oss << ") -> " << GetAbstractStr(func->output()) << " ";
  219. *op_comment = oss.str();
  220. }
  221. continue;
  222. }
  223. auto evaluator = engine_->GetEvaluatorFor(dyn_cast<abstract::AbstractFunction>(op_abs));
  224. if (!evaluator->isa<abstract::BaseFuncGraphEvaluator>()) {
  225. MS_LOG(DEBUG) << "Evaluator for inputs[" << i << "] of cnode " << cnode->ToString() << " is of type "
  226. << evaluator->type_name() << ", not BaseFuncGraphEvaluator, ignore it.";
  227. continue;
  228. }
  229. auto base_fg_evaluator = dyn_cast<abstract::BaseFuncGraphEvaluator>(evaluator);
  230. auto ctx = base_fg_evaluator->graph_context();
  231. if (ctx != nullptr && context_map_.insert({ctx, false}).second) {
  232. MS_LOG(DEBUG) << "Add new context, ctx.addr = " << ctx.get() << "ctx = " << ctx->ToString();
  233. context_vec_.push_back(ctx);
  234. }
  235. ret_contexts[i] = ctx;
  236. }
  237. return ret_contexts;
  238. }
  239. void AnalyzedFuncGraphExporter::OutputStatementComment(std::ofstream &ofs, const CNodePtr &node,
  240. const std::vector<AnalysisContextPtr> &ctxs) {
  241. if (node == nullptr) {
  242. return;
  243. }
  244. // output type of each input argument
  245. auto &inputs = node->inputs();
  246. if (inputs.size() > 1) {
  247. ofs << " #(";
  248. for (size_t i = 1; i < inputs.size(); ++i) {
  249. if (i != 1) {
  250. ofs << ", ";
  251. }
  252. AnfNodePtr arg = inputs[i];
  253. ofs << GetNodeType(arg);
  254. }
  255. ofs << ")";
  256. }
  257. // output other comment, map the graph name to original representation(containing unicode character)
  258. std::ostringstream comment;
  259. comment << " #";
  260. bool has_comment = false;
  261. for (size_t i = 0; i < inputs.size(); ++i) {
  262. AnfNodePtr arg = inputs[i];
  263. if (!IsValueNode<FuncGraph>(arg)) {
  264. continue;
  265. }
  266. if (!has_comment) {
  267. has_comment = true;
  268. } else {
  269. comment << ",";
  270. }
  271. FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(arg);
  272. std::string func_graph_id = fg->debug_info()->get_id();
  273. comment << " fg_" << func_graph_id << "=" << fg->ToString() << "." << func_graph_id;
  274. if (ctxs.size() > i && ctxs[i] != nullptr) {
  275. comment << "(@ctx.addr=" << ctxs[i].get() << ")";
  276. }
  277. }
  278. if (has_comment) {
  279. ofs << comment.str();
  280. }
  281. ofs << " #scope: " << node->scope()->name();
  282. }
  283. void AnalyzedFuncGraphExporter::OutputCNode(std::ofstream &ofs, const CNodePtr &cnode, const FuncGraphPtr &func_graph,
  284. int *idx, std::map<AnfNodePtr, int> *const apply_map) {
  285. auto &inputs = cnode->inputs();
  286. std::string op_text = GetAnfNodeText(func_graph, inputs[0], *apply_map);
  287. // non-return node
  288. if (cnode != func_graph->get_return()) {
  289. int apply_idx = (*idx)++;
  290. (*apply_map)[cnode] = apply_idx;
  291. std::string type_info = GetNodeType(cnode);
  292. if (type_info == "Undefined") {
  293. ofs << " %" << apply_idx << " = " << op_text << "(";
  294. } else {
  295. ofs << " %" << apply_idx << " : " << type_info << " = " << op_text << "(";
  296. }
  297. } else {
  298. ofs << " " << op_text << "(";
  299. }
  300. for (size_t i = 1; i < inputs.size(); ++i) {
  301. if (i != 1) {
  302. ofs << ", ";
  303. }
  304. AnfNodePtr arg = inputs[i];
  305. ofs << GetAnfNodeText(func_graph, arg, *apply_map);
  306. }
  307. ofs << ")";
  308. // process function graph call
  309. std::string op_comment;
  310. auto contexts = ProcessFuncGraphCall(cnode, &op_comment);
  311. AnalysisContextPtr ctx = contexts.empty() ? nullptr : contexts[0];
  312. if (!op_comment.empty()) {
  313. ofs << " #" << GetAnfNodeText(func_graph, inputs[0], *apply_map) << ".prototype = " << op_comment;
  314. }
  315. // output comment
  316. OutputStatementComment(ofs, cnode, contexts);
  317. if (ctx != nullptr) {
  318. ofs << " @ctx.addr=" << ctx.get();
  319. }
  320. ofs << "\n";
  321. if (label_manage::GetGlobalTraceLabelType() == label_manage::TraceLabelType::kWithUniqueId) {
  322. ofs << trace::GetDebugInfo(cnode->debug_info(), " # ", kSourceLineTipDiscard) << "#"
  323. << label_manage::Label(cnode->debug_info()) << "\n";
  324. } else {
  325. ofs << trace::GetDebugInfo(cnode->debug_info(), " # ", kSourceLineTipDiscard) << "\n";
  326. }
  327. }
  328. void AnalyzedFuncGraphExporter::OutputCNodes(std::ofstream &ofs, const std::vector<AnfNodePtr> &nodes,
  329. const FuncGraphPtr &func_graph) {
  330. if (func_graph == nullptr) {
  331. return;
  332. }
  333. int idx = 1;
  334. std::map<AnfNodePtr, int> apply_map;
  335. for (const AnfNodePtr &node : nodes) {
  336. MS_EXCEPTION_IF_NULL(node);
  337. if (!node->isa<CNode>()) {
  338. continue;
  339. }
  340. auto iter = tagged_cnodes_.find(node);
  341. if (iter != tagged_cnodes_.end()) {
  342. ofs << "\n#------------------------> " << iter->second << "\n";
  343. }
  344. auto cnode = node->cast<CNodePtr>();
  345. OutputCNode(ofs, cnode, func_graph, &idx, &apply_map);
  346. }
  347. }
  348. void AnalyzedFuncGraphExporter::ExportOneFuncGraph(std::ofstream &ofs, const FuncGraphPtr &func_graph) {
  349. if (func_graph == nullptr) {
  350. return;
  351. }
  352. std::vector<AnfNodePtr> nodes = TopoSort(func_graph->get_return(), SuccIncoming, AlwaysInclude);
  353. std::vector<AnfNodePtr> parameters = func_graph->parameters();
  354. OrderedMap<AnfNodePtr, int, ParamPtrHasher, ParamPtrEqual> param_map;
  355. ofs << "# [No." << (exported.size() + 1) << "] " << func_graph->DumpText() << "."
  356. << func_graph->debug_info()->get_id();
  357. if (cur_ctx_ != nullptr) {
  358. ofs << " @ctx.addr=" << cur_ctx_.get();
  359. }
  360. ofs << "\n";
  361. if (label_manage::GetGlobalTraceLabelType() == label_manage::TraceLabelType::kWithUniqueId) {
  362. ofs << trace::GetDebugInfo(func_graph->debug_info(), "# ", kSourceLineTipDiscard) << "#"
  363. << label_manage::Label(func_graph->debug_info()) << "\n";
  364. } else {
  365. ofs << trace::GetDebugInfo(func_graph->debug_info(), "# ", kSourceLineTipDiscard) << "\n";
  366. }
  367. ofs << "funcgraph fg_" << func_graph->debug_info()->get_id();
  368. // output name of parent of graph if exists
  369. if (func_graph->parent() != nullptr) {
  370. ofs << "[fg_" << func_graph->parent()->debug_info()->get_id() << "]";
  371. }
  372. ofs << "(\n";
  373. OutputParameters(ofs, parameters, &param_map);
  374. exported[func_graph] = param_map;
  375. ofs << (!parameters.empty() ? " " : "") << ") {\n";
  376. OutputCNodes(ofs, nodes, func_graph);
  377. ofs << "}\n";
  378. }
  379. void AnalyzedFuncGraphExporter::ExportFuncGraph(const std::string &filename,
  380. const std::vector<abstract::AnfNodeConfigPtr> &node_cfgs) {
  381. if (node_cfgs.empty()) {
  382. MS_LOG(DEBUG) << "Node configs is empty";
  383. return;
  384. }
  385. context_map_.clear();
  386. context_vec_.clear();
  387. std::ofstream ofs(filename);
  388. if (!ofs.is_open()) {
  389. MS_LOG(ERROR) << "Open file '" << filename << "' failed!";
  390. return;
  391. }
  392. param_index = 1;
  393. auto tagged_func_graphs = CalcTaggedFuncGraphs();
  394. // 1. Output graph on the analysis stack
  395. for (const auto &node_cfg : node_cfgs) {
  396. auto ctx = node_cfg->context();
  397. if (engine_ == nullptr) {
  398. engine_ = node_cfg->engine();
  399. }
  400. if (context_map_.insert({ctx, false}).second) {
  401. context_vec_.push_back(ctx);
  402. }
  403. // If the graph has already been printed
  404. if (context_map_[ctx]) {
  405. continue;
  406. }
  407. context_map_[ctx] = true;
  408. auto fg = ctx->func_graph();
  409. // Set current context
  410. cur_ctx_ = ctx;
  411. tagged_cnodes_ = tagged_func_graphs[fg];
  412. ExportOneFuncGraph(ofs, fg);
  413. ofs << "\n\n";
  414. }
  415. tagged_cnodes_.clear();
  416. // Print separator between function graphs on analyzed graph call stack and others
  417. ofs << "#===============================================================================\n\n\n";
  418. // 2. Output other graphs
  419. size_t ctx_idx = 0;
  420. while (ctx_idx < context_vec_.size()) {
  421. auto ctx = context_vec_[ctx_idx++];
  422. if (context_map_[ctx]) {
  423. continue;
  424. }
  425. context_map_[ctx] = true;
  426. cur_ctx_ = ctx;
  427. ExportOneFuncGraph(ofs, ctx->func_graph());
  428. ofs << "\n\n";
  429. }
  430. ofs << "# num of total function graphs: " << context_map_.size() << "\n";
  431. ofs.close();
  432. }
  433. void GetEvalStackInfo(std::ostringstream &oss) {
  434. MS_LOG(INFO) << "Get graph analysis information begin";
  435. auto stack = GetCNodeDebugStack();
  436. if (stack.empty()) {
  437. MS_LOG(INFO) << "Length of analysis information stack is empty.";
  438. return;
  439. }
  440. string file_name = "analyze_fail.dat";
  441. auto ms_om_path = common::GetEnv("MS_OM_PATH");
  442. if (!ms_om_path.empty()) {
  443. auto path = ms_om_path + "/" + "analyze_fail.dat";
  444. auto realpath = Common::GetRealPath(path);
  445. if (!realpath.has_value()) {
  446. MS_EXCEPTION(ValueError) << "Get real path failed. path=" << path;
  447. }
  448. file_name = realpath.value();
  449. }
  450. OutputAnalyzedGraphWithType(file_name);
  451. oss << "\nThe function call stack (See file '" << file_name << "' for details):\n";
  452. int index = 0;
  453. std::string last_location_info = "";
  454. for (size_t i = 0; i < stack.size(); ++i) {
  455. auto node_cfg = stack[i];
  456. auto cnode = dyn_cast<CNode>(node_cfg->node());
  457. if (cnode == nullptr) {
  458. MS_LOG(DEBUG) << "CNode of elements[" << i << "] is nullptr.";
  459. continue;
  460. }
  461. auto debug_info = cnode->debug_info();
  462. auto this_location_info = trace::GetDebugInfo(debug_info, std::string(""));
  463. if (this_location_info.empty() || this_location_info == last_location_info) {
  464. continue;
  465. }
  466. last_location_info = this_location_info;
  467. oss << "# " << index++ << " " << this_location_info;
  468. }
  469. stack.clear();
  470. MS_LOG(INFO) << "Get graph analysis information *end*";
  471. }
  472. // trace the graph evaluator stack
  473. static std::stack<std::pair<abstract::EvaluatorPtr, abstract::AnfNodeConfigPtr>> graph_infer_stack;
  474. // trace the cnode infer debug info
  475. static std::vector<abstract::AnfNodeConfigPtr> cnode_debug_stack{};
  476. void TraceGraphEvalEnter(const abstract::EvaluatorPtr &eval, const abstract::AnfNodeConfigPtr &node) {
  477. if (eval == nullptr) {
  478. MS_LOG(EXCEPTION) << "GraphInferEnter got null eval";
  479. }
  480. if (eval->isa<abstract::FuncGraphEvaluator>() || eval->isa<abstract::MetaFuncGraphEvaluator>()) {
  481. graph_infer_stack.emplace(std::pair<abstract::EvaluatorPtr, abstract::AnfNodeConfigPtr>(eval, node));
  482. }
  483. }
  484. void TraceGraphEvalLeave(const abstract::EvaluatorPtr &eval) {
  485. if (eval == nullptr) {
  486. MS_LOG(EXCEPTION) << "GraphInferEnter got null eval";
  487. }
  488. if (eval->isa<abstract::FuncGraphEvaluator>() || eval->isa<abstract::MetaFuncGraphEvaluator>()) {
  489. graph_infer_stack.pop();
  490. }
  491. }
  492. void TraceEvalCNodeEnter(const abstract::AnfNodeConfigPtr &node_cfg) { cnode_debug_stack.push_back(node_cfg); }
  493. void TraceEvalCNodeLeave() { cnode_debug_stack.pop_back(); }
  494. std::vector<abstract::AnfNodeConfigPtr> &GetCNodeDebugStack() { return cnode_debug_stack; }
  495. std::stack<std::pair<abstract::EvaluatorPtr, abstract::AnfNodeConfigPtr>> &GetCurrenGraphEvalStack() {
  496. return graph_infer_stack;
  497. }
  498. void ClearTraceStack() {
  499. while (!graph_infer_stack.empty()) {
  500. graph_infer_stack.pop();
  501. }
  502. cnode_debug_stack.clear();
  503. }
  504. // Register trace provider to LogWriter.
  505. struct TraceProviderRegister {
  506. TraceProviderRegister() {
  507. LogWriter::set_trace_provider([](std::ostringstream &oss) {
  508. TraceGraphEval();
  509. std::ostringstream trace_info;
  510. GetEvalStackInfo(trace_info);
  511. if (trace_info.str().empty()) {
  512. DebugInfoPtr debug_info = TraceManager::GetParseOrResolveDebugInfo();
  513. if (debug_info != nullptr) {
  514. oss << "\n\n# " << trace::GetDebugInfo(debug_info);
  515. }
  516. } else {
  517. oss << trace_info.str();
  518. }
  519. });
  520. }
  521. ~TraceProviderRegister() = default;
  522. } trace_provider_regsiter;
  523. } // namespace trace
  524. } // namespace mindspore