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 19 kB

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