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.

anf_ir_utils.cc 22 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  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/anf_ir_utils.h"
  17. #include <fstream>
  18. #include <map>
  19. #include <memory>
  20. #include <unordered_map>
  21. #include <algorithm>
  22. #include <iomanip>
  23. #include "ir/graph_utils.h"
  24. #include "utils/symbolic.h"
  25. #include "ir/meta_func_graph.h"
  26. #include "ir/param_info.h"
  27. #include "pybind_api/ir/tensor_py.h"
  28. #include "pipeline/jit/parse/python_adapter.h"
  29. #include "pipeline/jit/parse/resolve.h"
  30. #include "frontend/operator/composite/composite.h"
  31. #include "frontend/operator/composite/map.h"
  32. #include "utils/ordered_map.h"
  33. #include "utils/ordered_set.h"
  34. #include "utils/utils.h"
  35. #include "utils/shape_utils.h"
  36. #include "debug/trace.h"
  37. #include "utils/label.h"
  38. #include "utils/ms_context.h"
  39. #include "frontend/operator/ops.h"
  40. #include "pipeline/jit/base.h"
  41. #include "debug/common.h"
  42. using mindspore::tensor::TensorPy;
  43. namespace mindspore {
  44. // ============================================= MindSpore IR Exporter =============================================
  45. std::string AnfExporter::GetNodeType(const AnfNodePtr &nd) {
  46. abstract::ShapePtr shape = nd->Shape() == nullptr ? nullptr : dyn_cast<abstract::Shape>(nd->Shape());
  47. TypePtr type = dyn_cast<Type>(nd->Type());
  48. std::ostringstream oss;
  49. if ((nullptr != shape) && (nullptr != type)) {
  50. oss << type->DumpText() << shape->DumpText();
  51. } else if (nullptr != type) {
  52. oss << type->DumpText();
  53. } else {
  54. oss << "Undefined";
  55. }
  56. return oss.str();
  57. }
  58. int AnfExporter::GetParamIndex(const FuncGraphPtr &func_graph, const AnfNodePtr &param, bool throw_excp) {
  59. if (func_graph == nullptr || param == nullptr) {
  60. return -1;
  61. }
  62. FuncGraphPtr fg = func_graph;
  63. while (fg != nullptr) {
  64. if (exported.find(fg) == exported.end()) {
  65. if (!check_integrity_) {
  66. break;
  67. }
  68. MS_LOG(EXCEPTION) << "Can not find func graph '" << fg->DumpText() << "." << fg->debug_info()->get_id() << "'";
  69. }
  70. auto param_map = exported[fg];
  71. if (param_map.find(param) != param_map.end()) {
  72. return param_map[param];
  73. }
  74. fg = fg->parent();
  75. }
  76. if (throw_excp) {
  77. MS_LOG(EXCEPTION) << "Can not find index for param '" << param->DumpText() << "' for func graph '"
  78. << func_graph->DumpText() << "." << func_graph->debug_info()->get_id() << "'";
  79. }
  80. return -1;
  81. }
  82. // try to find index of parameter for SymbolicKeyInstance from all exported graphs
  83. // NOTICE: Suppose name of all parameters in SymbolicKeyInstance are different
  84. int AnfExporter::GetParamIndexFromExported(const AnfNodePtr &param) {
  85. if (param == nullptr) {
  86. return -1;
  87. }
  88. int ret = -1;
  89. for (const auto &item : exported) {
  90. auto pram_iter = item.second.find(param);
  91. if (pram_iter != item.second.end()) {
  92. return pram_iter->second;
  93. }
  94. }
  95. return ret;
  96. }
  97. std::string AnfExporter::GetValueNodeText(const FuncGraphPtr &fg, const ValueNodePtr &node) {
  98. MS_EXCEPTION_IF_NULL(node);
  99. return GetValueText(fg, node->value());
  100. }
  101. std::string AnfExporter::GetMultitypeFuncGraphText(const prim::MultitypeFuncGraphPtr &mt_func_graph) {
  102. auto py_funcs = mt_func_graph->GetPyFunctions();
  103. if (py_funcs.empty()) {
  104. return "";
  105. }
  106. std::ostringstream oss;
  107. oss << "{";
  108. bool is_first = true;
  109. for (const auto &py_func : py_funcs) {
  110. if (is_first) {
  111. is_first = false;
  112. } else {
  113. oss << ", ";
  114. }
  115. oss << "(";
  116. for (size_t i = 0; i < py_func.first.size(); ++i) {
  117. if (i > 0) {
  118. oss << ", ";
  119. }
  120. oss << py_func.first[i]->DumpText();
  121. }
  122. oss << ")";
  123. }
  124. oss << "}";
  125. return oss.str();
  126. }
  127. inline bool Skip(const MetaFuncGraphPtr &meta_func_graph) {
  128. return meta_func_graph->isa<prim::Tail>() || meta_func_graph->isa<prim::MakeTupleGradient>() ||
  129. meta_func_graph->isa<prim::MakeListGradient>() || meta_func_graph->isa<prim::TupleAdd>() ||
  130. meta_func_graph->isa<prim::TupleSlice>() || meta_func_graph->isa<prim::UnpackCall>() ||
  131. meta_func_graph->isa<prim::ZipOperation>() || meta_func_graph->isa<prim::ListAppend>() ||
  132. meta_func_graph->isa<prim::DoSignatureMetaFuncGraph>();
  133. }
  134. /* inherit relation of MetaFuncGraph
  135. *
  136. * MetaGraph
  137. * ├── MultitypeGraph
  138. * ├── HyperMap
  139. * │ └── HyperMapPy
  140. * ├── Map
  141. * │ └── MapPy
  142. * ├── Tail
  143. * ├── MakeTupleGradient
  144. * ├── MakeListGradient
  145. * ├── GradOperation
  146. * └── TupleAdd
  147. */
  148. std::string AnfExporter::GetMetaFuncGraphText(const MetaFuncGraphPtr &meta_func_graph) {
  149. if (meta_func_graph == nullptr) {
  150. return "";
  151. }
  152. std::ostringstream oss;
  153. oss << meta_func_graph->type_name() << "::" << meta_func_graph->name();
  154. if (meta_func_graph->isa<prim::MultitypeFuncGraph>()) {
  155. prim::MultitypeFuncGraphPtr mt_func_graph = meta_func_graph->cast<prim::MultitypeFuncGraphPtr>();
  156. oss << GetMultitypeFuncGraphText(mt_func_graph);
  157. } else if (meta_func_graph
  158. ->isa<prim::HyperMapPy>()) { // this statement must before 'meta_graph->isa<prim::HyperMap>()'
  159. auto hyper_map = meta_func_graph->cast<prim::HyperMapPyPtr>();
  160. if (hyper_map->GetFnLeaf() != nullptr) {
  161. oss << "{fn_leaf=" << GetMetaFuncGraphText(hyper_map->GetFnLeaf()) << "}";
  162. }
  163. } else if (meta_func_graph->isa<prim::HyperMap>()) {
  164. auto hyper_map = meta_func_graph->cast<prim::HyperMapPtr>();
  165. if (hyper_map->GetFnLeaf() != nullptr) {
  166. oss << "{fn_leaf=" << GetMetaFuncGraphText(hyper_map->GetFnLeaf()) << "}";
  167. }
  168. } else if (meta_func_graph->isa<prim::MapPy>()) { // this statement must before 'meta_graph->isa<prim::Map>()'
  169. auto map = meta_func_graph->cast<prim::MapPyPtr>();
  170. if (map->GetFnLeaf() != nullptr) {
  171. oss << "{fn_leaf=" << GetMetaFuncGraphText(map->GetFnLeaf()) << "}";
  172. }
  173. } else if (meta_func_graph->isa<prim::Map>()) {
  174. auto map = meta_func_graph->cast<prim::MapPtr>();
  175. if (map->GetFnLeaf() != nullptr) {
  176. oss << "{fn_leaf=" << GetMetaFuncGraphText(map->GetFnLeaf()) << "}";
  177. }
  178. } else if (meta_func_graph->isa<prim::GradOperation>()) {
  179. prim::GradOperationPtr grad_op = meta_func_graph->cast<prim::GradOperationPtr>();
  180. oss << "{get_all=" << grad_op->get_all_ << ", get_by_list=" << grad_op->get_by_list_
  181. << ", sens_param=" << grad_op->sens_param_ << "}";
  182. } else if (Skip(meta_func_graph)) {
  183. // do nothing
  184. } else {
  185. MS_LOG(EXCEPTION) << "Unknown MetaFuncGraph type " << meta_func_graph->type_name();
  186. }
  187. return oss.str();
  188. }
  189. std::string AnfExporter::GetPrimitiveText(const PrimitivePtr &prim) {
  190. std::ostringstream oss;
  191. if (prim == nullptr) {
  192. return oss.str();
  193. }
  194. oss << prim->type_name() << "::" << prim->name();
  195. // output primitive type
  196. oss << "{prim_type=" << static_cast<int>(prim->prim_type()) << "}";
  197. // output primitive attributes
  198. oss << prim->GetAttrsText();
  199. if (prim->isa<prim::DoSignaturePrimitive>()) {
  200. auto do_signature = dyn_cast<prim::DoSignaturePrimitive>(prim);
  201. auto &func = do_signature->function();
  202. if (func->isa<Primitive>()) {
  203. auto sig_prim = dyn_cast<Primitive>(func);
  204. oss << sig_prim->GetAttrsText();
  205. }
  206. }
  207. return oss.str();
  208. }
  209. std::string AnfExporter::GetNameSpaceText(const parse::NameSpacePtr &ns) {
  210. std::ostringstream oss;
  211. if (ns == nullptr) {
  212. return oss.str();
  213. }
  214. // dump related module information in Namespace
  215. oss << ns->type_name() << "::" << ns->module();
  216. return oss.str();
  217. }
  218. std::string AnfExporter::GetSymbolicKeyInstanceText(const FuncGraphPtr &func_graph,
  219. const SymbolicKeyInstancePtr &sym_inst) {
  220. MS_EXCEPTION_IF_NULL(func_graph);
  221. MS_EXCEPTION_IF_NULL(sym_inst);
  222. AnfNodePtr sym_node = sym_inst->node();
  223. MS_EXCEPTION_IF_NULL(sym_node);
  224. std::ostringstream oss;
  225. if (sym_node->isa<Parameter>()) {
  226. int idx = GetParamIndex(func_graph, sym_node, false);
  227. // if can not find SymbolicKeyInstance related parameter from ancestors,
  228. // try to find from all exported graphs
  229. if (idx < 0) {
  230. idx = GetParamIndexFromExported(sym_node);
  231. }
  232. if (idx < 0) {
  233. ParameterPtr p = dyn_cast<Parameter>(sym_node);
  234. if (p == nullptr) {
  235. MS_LOG(EXCEPTION) << "Sym_inst's node could not cast to parameter";
  236. }
  237. MS_LOG(WARNING) << "Can not find SymbolicKeyInstance: " << p->name();
  238. }
  239. oss << "SymInst(%para" << idx << ")";
  240. } else {
  241. MS_LOG(WARNING) << "SymbolicKeyInstance does not embed a parameter: " << sym_node->ToString();
  242. oss << "SymInst(cnode_" << sym_node->ToString() << ")";
  243. }
  244. return oss.str();
  245. }
  246. std::string AnfExporter::GetSequenceText(const FuncGraphPtr &func_graph, const ValuePtr &value) {
  247. std::ostringstream oss;
  248. // output ValueList, ValueTuple
  249. ValueSequeuePtr seq = dyn_cast<ValueSequeue>(value);
  250. MS_EXCEPTION_IF_NULL(seq);
  251. MS_EXCEPTION_IF_NULL(value);
  252. bool is_tuple = value->isa<ValueTuple>();
  253. oss << (is_tuple ? "(" : "[");
  254. bool first_flag = true;
  255. for (auto elem : seq->value()) {
  256. if (first_flag) {
  257. first_flag = false;
  258. } else {
  259. oss << ", ";
  260. }
  261. oss << GetValueText(func_graph, elem);
  262. }
  263. oss << (is_tuple ? ")" : "]");
  264. return oss.str();
  265. }
  266. std::string AnfExporter::GetDictText(const FuncGraphPtr &func_graph, const ValuePtr &value) {
  267. std::ostringstream oss;
  268. ValueDictionaryPtr dict = value->cast<ValueDictionaryPtr>();
  269. oss << "{";
  270. bool first_flag = true;
  271. for (const auto &elem : dict->value()) {
  272. if (first_flag) {
  273. first_flag = false;
  274. } else {
  275. oss << ", ";
  276. }
  277. oss << "\"" << elem.first << "\": " << GetValueText(func_graph, elem.second);
  278. }
  279. oss << "}";
  280. return oss.str();
  281. }
  282. std::string AnfExporter::GetOtherValueText(const FuncGraphPtr &, const ValuePtr &value) {
  283. std::ostringstream oss;
  284. if (check_integrity_) {
  285. MS_LOG(EXCEPTION) << "Need to process type: " << value->type_name() << ", dump text: " << value->DumpText();
  286. }
  287. oss << value->type_name() << "[" << value->DumpText() << "]";
  288. return oss.str();
  289. }
  290. std::string AnfExporter::GetValueText(const FuncGraphPtr &func_graph, const ValuePtr &value) {
  291. std::ostringstream oss;
  292. bool is_null_ptr = (func_graph == nullptr || value == nullptr);
  293. if (is_null_ptr) {
  294. return oss.str();
  295. }
  296. if (value->isa<Primitive>()) {
  297. oss << GetPrimitiveText(value->cast<PrimitivePtr>());
  298. } else if (value->isa<MetaFuncGraph>()) {
  299. MetaFuncGraphPtr meta_func_graph = value->cast<MetaFuncGraphPtr>();
  300. oss << GetMetaFuncGraphText(meta_func_graph);
  301. } else if (value->isa<SymbolicKeyInstance>()) {
  302. oss << GetSymbolicKeyInstanceText(func_graph, value->cast<SymbolicKeyInstancePtr>());
  303. } else if (value->isa<RefKey>()) {
  304. oss << value->DumpText();
  305. } else if (value->isa<Scalar>() || value->isa<StringImm>()) {
  306. oss << value->DumpText();
  307. } else if (value->isa<tensor::Tensor>()) {
  308. oss << value->DumpText();
  309. } else if (value->isa<parse::Symbol>() || value->isa<None>() || value->isa<Null>()) {
  310. oss << value->DumpText();
  311. } else if (value->isa<ValueSequeue>()) {
  312. oss << GetSequenceText(func_graph, value);
  313. } else if (value->isa<ValueDictionary>()) {
  314. oss << GetDictText(func_graph, value);
  315. } else if (value->isa<ValueSlice>()) {
  316. ValueSlicePtr slice = value->cast<ValueSlicePtr>();
  317. oss << slice->DumpText();
  318. } else if (value->isa<Type>()) {
  319. oss << value->DumpText();
  320. } else if (value->isa<parse::NameSpace>()) {
  321. oss << GetNameSpaceText(value->cast<parse::NameSpacePtr>());
  322. } else if (value->isa<parse::PyObjectWrapper>()) {
  323. oss << value->type_name();
  324. } else if (value->isa<KeywordArg>()) {
  325. KeywordArgPtr keyword_arg = value->cast<KeywordArgPtr>();
  326. oss << keyword_arg->DumpText();
  327. } else {
  328. return GetOtherValueText(func_graph, value);
  329. }
  330. return oss.str();
  331. }
  332. // this function is used to output node in CNode's inputs
  333. std::string AnfExporter::GetAnfNodeText(const FuncGraphPtr &func_graph, const AnfNodePtr &node,
  334. const std::map<AnfNodePtr, int> &apply_map) {
  335. std::ostringstream oss;
  336. if (func_graph == nullptr || node == nullptr) {
  337. return oss.str();
  338. }
  339. if (node->isa<CNode>()) {
  340. auto iter = apply_map.find(node);
  341. if (iter == apply_map.end()) {
  342. MS_LOG(EXCEPTION) << "Can not find node '" << node->DumpText() << "' in apply_map";
  343. }
  344. oss << "%" << iter->second;
  345. } else if (node->isa<Parameter>()) {
  346. // Parameter maybe a free variable, so check it in its own funcgraph.
  347. oss << "%para" << GetParamIndex(node->func_graph(), node, check_integrity_);
  348. } else if (IsValueNode<FuncGraph>(node)) {
  349. FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(node);
  350. oss << fg->type_name() << "::fg_" << fg->debug_info()->get_id();
  351. if (!func_graph_set.contains(fg) && exported.find(fg) == exported.end() && export_used_) {
  352. func_graph_set.add(fg);
  353. }
  354. } else if (node->isa<ValueNode>()) {
  355. oss << GetValueNodeText(func_graph, node->cast<ValueNodePtr>());
  356. } else {
  357. MS_LOG(EXCEPTION) << "Unknown node '" << node->DumpText() << "'";
  358. }
  359. return oss.str();
  360. }
  361. void AnfExporter::OutputParameters(std::ofstream &ofs, const std::vector<AnfNodePtr> &parameters,
  362. OrderedMap<AnfNodePtr, int, ParamPtrHasher, ParamPtrEqual> *param_map) {
  363. bool first_flag = true;
  364. for (const AnfNodePtr &param : parameters) {
  365. if (first_flag) {
  366. first_flag = false;
  367. ofs << " ";
  368. } else {
  369. ofs << " , ";
  370. }
  371. (*param_map)[param] = param_index;
  372. std::string type_info = GetNodeType(param);
  373. // output parameter and type
  374. if (type_info == "Undefined") {
  375. ofs << "%para" << param_index;
  376. } else {
  377. ofs << "%para" << param_index << " : " << type_info;
  378. }
  379. // output comment
  380. ofs << " # " << param->DumpText() << "\n";
  381. param_index += 1;
  382. }
  383. }
  384. void AnfExporter::OutputStatementComment(std::ofstream &ofs, const CNodePtr &node) {
  385. if (node == nullptr) {
  386. return;
  387. }
  388. // output type of each input argument
  389. auto &inputs = node->inputs();
  390. if (inputs.size() > 1) {
  391. ofs << " #(";
  392. for (size_t i = 1; i < inputs.size(); ++i) {
  393. if (i != 1) {
  394. ofs << ", ";
  395. }
  396. AnfNodePtr arg = inputs[i];
  397. ofs << GetNodeType(arg);
  398. }
  399. ofs << ")";
  400. }
  401. // output other comment, map the graph name to original representation(containing unicode character)
  402. std::ostringstream comment;
  403. comment << " #";
  404. bool has_comment = false;
  405. for (size_t i = 0; i < inputs.size(); ++i) {
  406. AnfNodePtr arg = inputs[i];
  407. if (!IsValueNode<FuncGraph>(arg)) {
  408. continue;
  409. }
  410. if (!has_comment) {
  411. has_comment = true;
  412. } else {
  413. comment << ",";
  414. }
  415. FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(arg);
  416. std::string func_graph_id = fg->debug_info()->get_id();
  417. comment << " fg_" << func_graph_id << "=" << fg->ToString() << "." << func_graph_id;
  418. }
  419. if (has_comment) {
  420. ofs << comment.str();
  421. }
  422. ofs << " #scope: " << node->scope()->name();
  423. }
  424. void AnfExporter::OutputCNodes(std::ofstream &ofs, const std::vector<AnfNodePtr> &nodes,
  425. const FuncGraphPtr &func_graph) {
  426. if (func_graph == nullptr) {
  427. return;
  428. }
  429. int idx = 1;
  430. std::map<AnfNodePtr, int> apply_map;
  431. for (const AnfNodePtr &node : nodes) {
  432. MS_EXCEPTION_IF_NULL(node);
  433. if (!node->isa<CNode>()) {
  434. continue;
  435. }
  436. auto iter = tagged_cnodes_.find(node);
  437. if (iter != tagged_cnodes_.end()) {
  438. ofs << "\n#------------------------> " << iter->second << "\n";
  439. }
  440. auto cnode = node->cast<CNodePtr>();
  441. auto &inputs = cnode->inputs();
  442. std::string op_text = GetAnfNodeText(func_graph, inputs[0], apply_map);
  443. // non-return node
  444. if (node != func_graph->get_return()) {
  445. int apply_idx = idx++;
  446. apply_map[node] = apply_idx;
  447. std::string type_info = GetNodeType(node);
  448. if (type_info == "Undefined") {
  449. ofs << " %" << apply_idx << " = " << op_text << "(";
  450. } else {
  451. ofs << " %" << apply_idx << " : " << type_info << " = " << op_text << "(";
  452. }
  453. } else {
  454. ofs << " " << op_text << "(";
  455. }
  456. for (size_t i = 1; i < inputs.size(); ++i) {
  457. if (i != 1) {
  458. ofs << ", ";
  459. }
  460. AnfNodePtr arg = inputs[i];
  461. ofs << GetAnfNodeText(func_graph, arg, apply_map);
  462. }
  463. ofs << ")";
  464. // output comment
  465. OutputStatementComment(ofs, cnode);
  466. ofs << "\n";
  467. if (label_manage::GetGlobalTraceLabelType() == label_manage::TraceLabelType::kWithUniqueId) {
  468. ofs << trace::GetDebugInfo(cnode->debug_info(), " # ", kSourceLineTipDiscard) << "#"
  469. << label_manage::Label(cnode->debug_info()) << "\n";
  470. } else {
  471. ofs << trace::GetDebugInfo(cnode->debug_info(), " # ", kSourceLineTipDiscard) << "#" << cnode->ToString()
  472. << "\n";
  473. }
  474. }
  475. }
  476. void AnfExporter::OutputOrderList(std::ofstream &ofs, const FuncGraphPtr &func_graph) {
  477. auto &order_list = func_graph->order_list();
  478. if (order_list.empty()) {
  479. return;
  480. }
  481. constexpr int width = 4;
  482. ofs << "# order:\n";
  483. int i = 1;
  484. for (auto &node : order_list) {
  485. ofs << '#' << std::setw(width) << i << ": " << node->DebugString() << '\n';
  486. ++i;
  487. }
  488. }
  489. void AnfExporter::ExportOneFuncGraph(std::ofstream &ofs, const FuncGraphPtr &func_graph) {
  490. if (func_graph == nullptr) {
  491. return;
  492. }
  493. std::vector<AnfNodePtr> nodes = TopoSort(func_graph->get_return(), SuccIncoming, AlwaysInclude);
  494. std::vector<AnfNodePtr> parameters = func_graph->parameters();
  495. OrderedMap<AnfNodePtr, int, ParamPtrHasher, ParamPtrEqual> param_map;
  496. if (*(func_graph->switch_input())) {
  497. ofs << "switch_input: " << *(func_graph->switch_input()) << "\n";
  498. }
  499. if (*(func_graph->switch_layer_input())) {
  500. ofs << "switch_layer_input: " << *(func_graph->switch_layer_input()) << "\n";
  501. }
  502. ofs << "# [No." << (exported.size() + 1) << "] " << func_graph->DumpText() << "."
  503. << func_graph->debug_info()->get_id() << "\n";
  504. if (label_manage::GetGlobalTraceLabelType() == label_manage::TraceLabelType::kWithUniqueId) {
  505. ofs << trace::GetDebugInfo(func_graph->debug_info(), "# ", kSourceLineTipDiscard) << "#"
  506. << label_manage::Label(func_graph->debug_info()) << "\n";
  507. } else {
  508. ofs << trace::GetDebugInfo(func_graph->debug_info(), "# ", kSourceLineTipDiscard) << "\n";
  509. }
  510. ofs << "funcgraph fg_" << func_graph->debug_info()->get_id();
  511. // output name of parent of graph if exists
  512. if (func_graph->parent() != nullptr) {
  513. ofs << "[fg_" << func_graph->parent()->debug_info()->get_id() << "]";
  514. }
  515. ofs << "(\n";
  516. OutputParameters(ofs, parameters, &param_map);
  517. exported[func_graph] = param_map;
  518. ofs << (!parameters.empty() ? " " : "") << ") {\n";
  519. OutputCNodes(ofs, nodes, func_graph);
  520. ofs << "}\n";
  521. OutputOrderList(ofs, func_graph);
  522. }
  523. void AnfExporter::ExportFuncGraph(const std::string &filename, const FuncGraphPtr &func_graph) {
  524. if (func_graph == nullptr) {
  525. return;
  526. }
  527. std::ofstream ofs(filename);
  528. if (!ofs.is_open()) {
  529. MS_LOG(ERROR) << "Open file '" << filename << "' failed!";
  530. return;
  531. }
  532. param_index = 1;
  533. func_graph_set.add(func_graph);
  534. while (!func_graph_set.empty()) {
  535. FuncGraphPtr fg = *func_graph_set.begin();
  536. ExportOneFuncGraph(ofs, fg);
  537. ofs << "\n\n";
  538. (void)func_graph_set.erase(fg);
  539. }
  540. ofs << "# num of total function graphs: " << exported.size();
  541. ofs.close();
  542. }
  543. void AnfExporter::ExportFuncGraph(const std::string &filename, const std::vector<TaggedGraph> &graphs) {
  544. if (graphs.empty()) {
  545. return;
  546. }
  547. std::ofstream ofs(filename);
  548. if (!ofs.is_open()) {
  549. MS_LOG(ERROR) << "Open file '" << filename << "' failed!";
  550. return;
  551. }
  552. param_index = 1;
  553. for (const auto &tagged_graph : graphs) {
  554. tagged_cnodes_ = tagged_graph.second;
  555. ExportOneFuncGraph(ofs, tagged_graph.first);
  556. tagged_cnodes_.clear();
  557. ofs << "\n\n";
  558. }
  559. ofs << "# num of total function graphs: " << graphs.size();
  560. ofs.close();
  561. }
  562. #ifdef ENABLE_DUMP_IR
  563. void ExportIR(const std::string &filename, const FuncGraphPtr &func_graph) {
  564. if (func_graph == nullptr) {
  565. return;
  566. }
  567. auto real_filename = pipeline::GetSaveGraphsPathName(Common::AddId(filename, ".dat"));
  568. AnfExporter exporter;
  569. ChangeFileMode(real_filename, S_IRWXU);
  570. exporter.ExportFuncGraph(real_filename, func_graph);
  571. // set file mode to read only by user
  572. ChangeFileMode(real_filename, S_IRUSR);
  573. }
  574. void ExportIR(const std::string &filename, const std::vector<TaggedGraph> &graphs) {
  575. auto real_filename = pipeline::GetSaveGraphsPathName(Common::AddId(filename, ".dat"));
  576. AnfExporter exporter("", false);
  577. ChangeFileMode(real_filename, S_IRWXU);
  578. exporter.ExportFuncGraph(real_filename, graphs);
  579. // set file mode to read only by user
  580. ChangeFileMode(real_filename, S_IRUSR);
  581. }
  582. #else
  583. void ExportIR(const std::string &, const std::string &, const FuncGraphPtr &) {
  584. static bool already_printed = false;
  585. if (already_printed) {
  586. return;
  587. }
  588. already_printed = true;
  589. MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
  590. << "please recompile source to enable it. See help of building script.";
  591. }
  592. void ExportIR(const std::string &filename, const std::vector<TaggedGraph> &graphs) {
  593. static bool already_printed = false;
  594. if (already_printed) {
  595. return;
  596. }
  597. already_printed = true;
  598. MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
  599. << "please recompile source to enable it. See help of building script.";
  600. }
  601. #endif
  602. } // namespace mindspore