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_dump.h"
17 #if defined(_WIN32) || defined(_WIN64)
18 #include <stdlib.h>
19 #endif
20 #include <fstream>
21 #include <iomanip>
22 #include <memory>
23 #include <unordered_map>
24 #include "ir/primitive.h"
25 #include "ir/func_graph.h"
26 #include "runtime/device/kernel_info.h"
27 #include "ir/graph_utils.h"
28 #include "backend/session/anf_runtime_algorithm.h"
29 #include "frontend/parallel/ops_info/operator_info.h"
30 #include "pipeline/jit/base.h"
31 #include "debug/trace.h"
32 #include "utils/trace_base.h"
33
34 namespace mindspore {
ToShortString(const TypeId & typeId)35 const std::string ToShortString(const TypeId &typeId) {
36 std::string label = TypeIdLabel(typeId);
37 std::string prefix = "kNumberType";
38 if (prefix.length() > label.length()) {
39 return label;
40 }
41 auto position = label.find(prefix);
42 // position is 0 when label begins with prefix
43 if (position != 0) {
44 return label;
45 }
46 auto sub_position = position + prefix.length();
47 if (sub_position >= label.length()) {
48 return label;
49 }
50 return label.substr(sub_position);
51 }
52
PrintKernelFormatAndType(std::ostringstream & buffer,const std::string & fmt,const TypeId & type,const std::vector<size_t> & shape)53 void PrintKernelFormatAndType(std::ostringstream &buffer, const std::string &fmt, const TypeId &type,
54 const std::vector<size_t> &shape) {
55 buffer << "<" << ToShortString(type);
56 if (!fmt.empty()) {
57 buffer << "x" << fmt << shape;
58 }
59 buffer << ">";
60 }
61
PrintNodeOutputType(std::ostringstream & buffer,const AnfNodePtr & nd)62 void PrintNodeOutputType(std::ostringstream &buffer, const AnfNodePtr &nd) {
63 if (nd == nullptr) {
64 return;
65 }
66
67 ValuePtr tensor_value = nullptr;
68 auto abstract = nd->abstract();
69 if (abstract != nullptr && abstract->isa<abstract::AbstractTensor>()) {
70 tensor_value = abstract->BuildValue();
71 }
72 abstract::ShapePtr shape = dyn_cast<abstract::Shape>(nd->Shape());
73 TypePtr type = dyn_cast<Type>(nd->Type());
74 if ((shape != nullptr) && (type != nullptr)) {
75 buffer << "<" << type << ", " << shape->ToString();
76 if (tensor_value != nullptr && tensor_value != kAnyValue) {
77 buffer << ", value=...";
78 }
79 buffer << ">";
80 } else if (type != nullptr) {
81 buffer << "<" << type;
82 if (tensor_value != nullptr && tensor_value != kAnyValue) {
83 buffer << ", value=...";
84 }
85 buffer << ">";
86 } else {
87 buffer << "<null>";
88 }
89 }
90
PrintNodeInputType(std::ostringstream & buffer,const AnfNodePtr & nd)91 void PrintNodeInputType(std::ostringstream &buffer, const AnfNodePtr &nd) {
92 if (nd == nullptr) {
93 return;
94 }
95
96 const auto &inputs = GetInputs(nd);
97 size_t len = inputs.size();
98 if (len > 1) {
99 // skip inputs[0] which is Primitive value node
100 for (size_t i = 1; i < len; ++i) {
101 AnfNodePtr in = inputs[i];
102 if (i != 1) {
103 buffer << ", ";
104 }
105 PrintNodeOutputType(buffer, in);
106 }
107 }
108 }
109
PrintInputAndOutputInferType(std::ostringstream & buffer,const AnfNodePtr & nd)110 void PrintInputAndOutputInferType(std::ostringstream &buffer, const AnfNodePtr &nd) {
111 buffer << " : (";
112 PrintNodeInputType(buffer, nd);
113 buffer << ") -> (";
114 PrintNodeOutputType(buffer, nd);
115 buffer << ")";
116 }
117
118 struct SubGraphIRInfo {
119 int32_t local_var;
120 std::ostringstream buffer;
121 OrderedMap<AnfNodePtr, int32_t> local_var_map;
122 };
123
DumpGlobalInfoEntry(const FuncGraphPtr & graph,std::ostringstream & buffer)124 void DumpGlobalInfoEntry(const FuncGraphPtr &graph, std::ostringstream &buffer) {
125 if (graph == nullptr) {
126 return;
127 }
128
129 buffer << "#IR entry : @" << graph->ToString() << std::endl;
130 buffer << "#attrs :" << std::endl;
131 for (const auto &attr : graph->attrs()) {
132 buffer << attr.first << " : ";
133 if (attr.second->isa<BoolImm>()) {
134 buffer << GetValue<bool>(attr.second);
135 } else if (attr.second->isa<StringImm>()) {
136 buffer << GetValue<std::string>(attr.second);
137 }
138 buffer << std::endl;
139 }
140 }
141
DumpKernelInfo(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)142 void DumpKernelInfo(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
143 if (node == nullptr || gsub == nullptr) {
144 return;
145 }
146 auto kernel_info = node->kernel_info();
147 if (kernel_info == nullptr || !kernel_info->has_build_info()) {
148 return;
149 }
150
151 gsub->buffer << " : (";
152 size_t input_num = AnfAlgo::GetInputTensorNum(node);
153 for (size_t i = 0; i < input_num; ++i) {
154 if (i != 0) {
155 gsub->buffer << ", ";
156 }
157 auto format = AnfAlgo::GetInputFormat(node, i);
158 auto type = AnfAlgo::GetInputDeviceDataType(node, i);
159 auto shape = AnfAlgo::GetInputDeviceShape(node, i);
160 PrintKernelFormatAndType(gsub->buffer, format, type, shape);
161 }
162 gsub->buffer << ") -> (";
163 size_t output_num = AnfAlgo::GetOutputTensorNum(node);
164 for (size_t i = 0; i < output_num; ++i) {
165 if (i != 0) {
166 gsub->buffer << ", ";
167 }
168 auto format = AnfAlgo::GetOutputFormat(node, i);
169 auto type = AnfAlgo::GetOutputDeviceDataType(node, i);
170 auto shape = AnfAlgo::GetOutputDeviceShape(node, i);
171 PrintKernelFormatAndType(gsub->buffer, format, type, shape);
172 }
173 gsub->buffer << ")";
174 gsub->buffer << std::endl;
175 }
176
DumpParams(const FuncGraphPtr & graph,std::ostringstream & buffer,OrderedMap<AnfNodePtr,int32_t> * para_map)177 int32_t DumpParams(const FuncGraphPtr &graph, std::ostringstream &buffer, OrderedMap<AnfNodePtr, int32_t> *para_map) {
178 if (graph == nullptr) {
179 MS_LOG(INFO) << "Param graph is nullptr.";
180 return 0;
181 }
182 std::vector<AnfNodePtr> parameters = graph->parameters();
183 buffer << "#Total params : " << parameters.size() << std::endl;
184 buffer << std::endl;
185
186 // dump parameters
187 int32_t para = 1;
188 for (const auto &p : parameters) {
189 if (p == nullptr) {
190 continue;
191 }
192 auto parameter_ptr = p->cast<ParameterPtr>();
193 if (parameter_ptr == nullptr) {
194 MS_LOG(EXCEPTION) << "p cannot cast to ParameterPtr";
195 }
196 buffer << "%para" << para << "_" << parameter_ptr->name() << " : ";
197 // print parameters' type and shape
198 PrintNodeOutputType(buffer, p);
199 auto kernel_info = p->kernel_info();
200 if (kernel_info != nullptr && kernel_info->has_build_info()) {
201 buffer << " : ";
202 auto type = AnfAlgo::GetOutputDeviceDataType(p, 0);
203 auto format = AnfAlgo::GetOutputFormat(p, 0);
204 auto shape = AnfAlgo::GetOutputDeviceShape(p, 0);
205 PrintKernelFormatAndType(buffer, format, type, shape);
206 buffer << " : IsWeight:" << std::boolalpha << AnfAlgo::IsParameterWeight(parameter_ptr);
207 }
208 buffer << std::endl;
209
210 if (para_map != nullptr) {
211 (*para_map)[p] = para++;
212 }
213 MS_LOG(DEBUG) << "Record param: " << p->ToString() << " graph belong : " << p->func_graph()->ToString();
214 }
215 return para;
216 }
217
DumpOperator(const AnfNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)218 void DumpOperator(const AnfNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
219 if (op == nullptr) {
220 MS_LOG(INFO) << "Param op is nullptr";
221 return;
222 }
223 if (gsub == nullptr) {
224 MS_LOG(INFO) << "Param gsub is nullptr";
225 return;
226 }
227
228 if (IsValueNode<FuncGraph>(op)) {
229 FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(op);
230 if (fg != nullptr) {
231 gsub->buffer << "call @" << fg->ToString();
232 }
233 } else if (op->isa<CNode>()) {
234 if (gsub->local_var_map.find(op) != gsub->local_var_map.end()) {
235 gsub->buffer << "%" << gsub->local_var_map[op];
236 } else {
237 auto node = op->cast<CNodePtr>();
238 auto fg = node->func_graph();
239 gsub->buffer << "$(" << fg->ToString() << ":" << node->ToString() << ")";
240 }
241 } else if (op->isa<ValueNode>()) {
242 gsub->buffer << GetValueNode(op)->ToString();
243 } else {
244 gsub->buffer << op->ToString();
245 }
246 }
247
DumpOperands(const AnfNodePtr & nd,OrderedMap<AnfNodePtr,int32_t> * para_map,const std::shared_ptr<SubGraphIRInfo> & gsub)248 void DumpOperands(const AnfNodePtr &nd, OrderedMap<AnfNodePtr, int32_t> *para_map,
249 const std::shared_ptr<SubGraphIRInfo> &gsub) {
250 if (nd == nullptr || para_map == nullptr || gsub == nullptr) {
251 return;
252 }
253
254 gsub->buffer << "(";
255 const auto &inputs = GetInputs(nd);
256 size_t len = inputs.size();
257 if (len > 1) {
258 // skip inputs[0] which is Primitive valuenode
259 for (size_t i = 1; i < len; ++i) {
260 AnfNodePtr in = inputs[i];
261 MS_EXCEPTION_IF_NULL(in);
262 if (i != 1) {
263 gsub->buffer << ", ";
264 }
265 if (in->isa<Parameter>()) {
266 if (!(*para_map)[in]) {
267 gsub->buffer << "%para_" << in->ToString();
268 } else {
269 gsub->buffer << "%para" << (*para_map)[in] << "_" << in->ToString();
270 }
271 } else if (in->isa<CNode>()) {
272 if (gsub->local_var_map.find(in) != gsub->local_var_map.end()) {
273 gsub->buffer << "%" << gsub->local_var_map[in];
274 } else {
275 auto node = in->cast<CNodePtr>();
276 auto fg = node->func_graph();
277 gsub->buffer << "$(" << fg->ToString() << ":" << node->ToString() << ")";
278 }
279 } else if (in->isa<ValueNode>() && !IsValueNode<FuncGraph>(in)) {
280 // non Primitive valuenode
281 gsub->buffer << GetValueNode(in)->ToString();
282 } else if (IsValueNode<FuncGraph>(in)) {
283 FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(in);
284 gsub->buffer << "@" << fg->ToString();
285 } else {
286 gsub->buffer << in->ToString();
287 }
288 }
289 }
290 gsub->buffer << ")";
291 }
292
DumpParallelInfo(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)293 void DumpParallelInfo(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
294 if ((node == nullptr) || (gsub == nullptr)) {
295 return;
296 }
297
298 auto operator_info = node->user_data<parallel::OperatorInfo>();
299 if (operator_info == nullptr) {
300 return;
301 }
302
303 auto strategy = operator_info->strategy();
304 if (strategy == nullptr) {
305 return;
306 }
307
308 ValuePtr temp = MakeValue(strategy->GetInputDim());
309 gsub->buffer << " { strategy: ";
310 gsub->buffer << temp->ToString();
311 gsub->buffer << " }";
312 }
313
DumpAttrs(const std::unordered_map<std::string,ValuePtr> & attrs,const std::shared_ptr<SubGraphIRInfo> & gsub,bool check_strategy=false)314 void DumpAttrs(const std::unordered_map<std::string, ValuePtr> &attrs, const std::shared_ptr<SubGraphIRInfo> &gsub,
315 bool check_strategy = false) {
316 int i = 0;
317 for (const auto &attr : attrs) {
318 if (check_strategy && attr.first == PARALLEL_STRATEGY) {
319 continue; // skip the strategy
320 }
321 if (i++ != 0) {
322 gsub->buffer << ", ";
323 }
324 gsub->buffer << attr.first << ": ";
325 if (attr.second == nullptr) {
326 gsub->buffer << "null";
327 } else {
328 gsub->buffer << attr.second->ToString();
329 }
330 }
331 }
332
DumpOperateAttrs(const AnfNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)333 void DumpOperateAttrs(const AnfNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
334 if (op == nullptr || gsub == nullptr) {
335 return;
336 }
337
338 if (IsValueNode<Primitive>(op)) {
339 PrimitivePtr primitive = GetValueNode<PrimitivePtr>(op);
340 if (!primitive->instance_name().empty()) {
341 gsub->buffer << " {";
342 gsub->buffer << "instance name"
343 << ": ";
344 gsub->buffer << primitive->instance_name();
345 gsub->buffer << "}";
346 }
347 auto attrs = primitive->attrs();
348 if (!attrs.empty()) {
349 gsub->buffer << " primitive_attrs: {";
350 DumpAttrs(attrs, gsub, true);
351 gsub->buffer << "}";
352 }
353 }
354 }
355
DumpCNodeAttrs(const CNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)356 void DumpCNodeAttrs(const CNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
357 if (op == nullptr || gsub == nullptr) {
358 return;
359 }
360 if (op->attrs().empty()) {
361 return;
362 }
363
364 auto attrs = op->attrs();
365 gsub->buffer << " cnode_attrs: {";
366 DumpAttrs(attrs, gsub);
367 gsub->buffer << "}";
368 }
369
DumpCNodePrimalAttrs(const CNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)370 void DumpCNodePrimalAttrs(const CNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
371 if (op == nullptr || gsub == nullptr) {
372 return;
373 }
374 if (op->primal_attrs().empty()) {
375 gsub->buffer << std::endl;
376 return;
377 }
378 auto primal_attrs = op->primal_attrs();
379 gsub->buffer << " cnode_primal_attrs: {";
380 DumpAttrs(primal_attrs, gsub);
381 gsub->buffer << "}";
382 gsub->buffer << std::endl;
383 }
384
DumpShape(const AnfNodePtr & nd,const FuncGraphPtr & sub_graph,const std::shared_ptr<SubGraphIRInfo> & gsub)385 void DumpShape(const AnfNodePtr &nd, const FuncGraphPtr &sub_graph, const std::shared_ptr<SubGraphIRInfo> &gsub) {
386 if (nd == nullptr || sub_graph == nullptr || gsub == nullptr) {
387 return;
388 }
389
390 if (nd != sub_graph->get_return()) {
391 gsub->buffer << " : (";
392 PrintNodeInputType(gsub->buffer, nd);
393 gsub->buffer << ") -> (";
394 PrintNodeOutputType(gsub->buffer, nd);
395 gsub->buffer << ")";
396 } else {
397 gsub->buffer << " : (";
398 PrintNodeInputType(gsub->buffer, nd);
399 gsub->buffer << ")";
400 }
401
402 gsub->buffer << std::endl;
403 }
404
DumpCNode(const CNodePtr & nd,const FuncGraphPtr & sub_graph,OrderedMap<AnfNodePtr,int32_t> * const para_map,const std::shared_ptr<SubGraphIRInfo> & gsub,bool dump_full_name=false,LocDumpMode dump_location=kOff)405 void DumpCNode(const CNodePtr &nd, const FuncGraphPtr &sub_graph, OrderedMap<AnfNodePtr, int32_t> *const para_map,
406 const std::shared_ptr<SubGraphIRInfo> &gsub, bool dump_full_name = false,
407 LocDumpMode dump_location = kOff) {
408 if (nd == nullptr || sub_graph == nullptr || para_map == nullptr || gsub == nullptr) {
409 return;
410 }
411
412 if (nd != sub_graph->get_return()) {
413 gsub->buffer << " %" << gsub->local_var << "(" << nd->ToString() << ")"
414 << " = ";
415 gsub->local_var_map[nd] = gsub->local_var++;
416 } else {
417 gsub->buffer << " ";
418 }
419
420 if (nd->inputs().empty()) {
421 MS_LOG(EXCEPTION) << "Input of apply node is empty";
422 }
423
424 // print operator
425 AnfNodePtr op = nd->input(0);
426 DumpOperator(op, gsub);
427
428 // print operands
429 DumpOperands(nd, para_map, gsub);
430
431 // print operator attrs
432 DumpOperateAttrs(op, gsub);
433
434 // print cnode attrs
435 DumpCNodeAttrs(nd, gsub);
436
437 // print cnode primal attrs
438 DumpCNodePrimalAttrs(nd, gsub);
439
440 // print parallel info
441 DumpParallelInfo(nd, gsub);
442
443 // print shape info
444 DumpShape(nd, sub_graph, gsub);
445
446 // print kernel info
447 DumpKernelInfo(nd, gsub);
448
449 if (dump_full_name) {
450 gsub->buffer << " : (" << nd->fullname_with_scope() << ")" << std::endl;
451 }
452 if (dump_location == kTopStack) {
453 if (label_manage::GetGlobalTraceLabelType() == label_manage::TraceLabelType::kWithUniqueId) {
454 gsub->buffer << trace::GetDebugInfo(nd->debug_info(), " # ", kSourceLineTipDiscard) << "#"
455 << label_manage::Label(nd->debug_info()) << "\n";
456 auto primal_debug_infos = nd->primal_debug_infos();
457 if (!primal_debug_infos.empty()) {
458 gsub->buffer << " # Corresponding forward node candidate:\n";
459 for (auto &primal_debug_info : primal_debug_infos) {
460 gsub->buffer << trace::GetDebugInfo(primal_debug_info, " # ", kSourceLineTipDiscard) << "#"
461 << label_manage::Label(primal_debug_info) << "\n";
462 }
463 }
464 } else {
465 gsub->buffer << trace::GetDebugInfo(nd->debug_info(), " # ", kSourceLineTipDiscard) << "\n";
466 auto primal_debug_infos = nd->primal_debug_infos();
467 if (!primal_debug_infos.empty()) {
468 gsub->buffer << " # Corresponding forward node candidate:\n";
469 for (auto &primal_debug_info : primal_debug_infos) {
470 gsub->buffer << trace::GetDebugInfo(primal_debug_info, " # ", kSourceLineTipDiscard) << "\n";
471 }
472 }
473 }
474 } else if (dump_location == kWholeStack) {
475 auto traces = mindspore::trace::GetSourceLineList(nd);
476 for (auto &trace : traces) {
477 gsub->buffer << " # " << trace;
478 }
479 }
480 }
481
DumpIRInSubgraph(const std::vector<AnfNodePtr> & nodes,OrderedMap<AnfNodePtr,int32_t> * para_map,OrderedMap<FuncGraphPtr,std::shared_ptr<SubGraphIRInfo>> * const sub_graphs,int32_t total_para,bool dump_full_name=false,LocDumpMode dump_location=kOff)482 void DumpIRInSubgraph(const std::vector<AnfNodePtr> &nodes, OrderedMap<AnfNodePtr, int32_t> *para_map,
483 OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> *const sub_graphs, int32_t total_para,
484 bool dump_full_name = false, LocDumpMode dump_location = kOff) {
485 if (para_map == nullptr || sub_graphs == nullptr) {
486 return;
487 }
488
489 for (const auto &nd : nodes) {
490 MS_EXCEPTION_IF_NULL(nd);
491 FuncGraphPtr sub_graph = nd->func_graph();
492 if (sub_graph == nullptr) {
493 MS_LOG(DEBUG) << "Node[" << nd->ToString() << "] belongs to no graph!";
494 continue;
495 }
496 std::shared_ptr<SubGraphIRInfo> gsub = (*sub_graphs)[sub_graph];
497 if (gsub == nullptr) {
498 gsub = std::make_shared<SubGraphIRInfo>();
499 gsub->local_var = 0;
500 (*sub_graphs)[sub_graph] = gsub;
501 }
502 std::vector<AnfNodePtr> parameters = sub_graph->parameters();
503 for (size_t idx = 0; idx < parameters.size(); idx++) {
504 MS_EXCEPTION_IF_NULL(parameters[idx]);
505 if ((*para_map).count(parameters[idx]) == 0) {
506 (*para_map)[parameters[idx]] = total_para++;
507 }
508 }
509 if (!nd->isa<Parameter>()) {
510 if (nd->isa<CNode>()) {
511 // print and record output of operator if it is not 'Return'
512 DumpCNode(nd->cast<CNodePtr>(), sub_graph, para_map, gsub, dump_full_name, dump_location);
513 } else {
514 gsub->buffer << " " << nd->ToString() << std::endl;
515 }
516 }
517 }
518 }
519
DumpSubgraph(const OrderedMap<FuncGraphPtr,std::shared_ptr<SubGraphIRInfo>> * sub_graphs,const FuncGraphPtr & graph,OrderedMap<AnfNodePtr,int32_t> * para_map,std::ofstream & fout)520 void DumpSubgraph(const OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> *sub_graphs,
521 const FuncGraphPtr &graph, OrderedMap<AnfNodePtr, int32_t> *para_map, std::ofstream &fout) {
522 if (sub_graphs == nullptr || graph == nullptr) {
523 return;
524 }
525
526 fout << "#Total subgraph : " << sub_graphs->size() << std::endl;
527 fout << std::endl;
528
529 for (const auto &sg : *sub_graphs) {
530 fout << "subgraph attr:" << std::endl;
531 MS_EXCEPTION_IF_NULL(sg.first);
532 for (const auto &attr : sg.first->attrs()) {
533 fout << attr.first << " : ";
534 if (attr.second->isa<BoolImm>()) {
535 fout << GetValue<bool>(attr.second);
536 } else if (attr.second->isa<StringImm>()) {
537 fout << (GetValue<std::string>(attr.second));
538 }
539 fout << std::endl;
540 }
541 fout << "subgraph @" << sg.first->ToString() << "(";
542 if (sg.first != graph) {
543 std::vector<AnfNodePtr> parameters = sg.first->parameters();
544 if (parameters.size() == 1) {
545 MS_EXCEPTION_IF_NULL(parameters[0]);
546 fout << "%para" << (*para_map)[parameters[0]] << "_" << parameters[0]->ToString();
547 } else if (parameters.size() > 1) {
548 for (size_t idx = 0; idx < parameters.size() - 1; idx++) {
549 MS_EXCEPTION_IF_NULL(parameters[idx]);
550 fout << "%para" << (*para_map)[parameters[idx]] << "_" << parameters[idx]->ToString();
551 fout << ", ";
552 }
553 MS_EXCEPTION_IF_NULL(parameters[parameters.size() - 1]);
554 fout << "%para" << (*para_map)[parameters[parameters.size() - 1]] << "_"
555 << parameters[parameters.size() - 1]->ToString();
556 }
557 }
558 fout << ") {" << std::endl;
559 MS_EXCEPTION_IF_NULL(sg.second);
560 fout << sg.second->buffer.str();
561 fout << "}" << std::endl;
562 fout << std::endl;
563 }
564 }
565
GetEnvDumpIrLineLevel(LocDumpMode * dump_location)566 void GetEnvDumpIrLineLevel(LocDumpMode *dump_location) {
567 static std::unordered_map<std::string, enum LocDumpMode> dump_level_map = {
568 {std::to_string(kOff), kOff}, {std::to_string(kTopStack), kTopStack}, {std::to_string(kWholeStack), kWholeStack}};
569 static const auto dump_level_in_env = common::GetEnv("ENV_DUMP_IR_LINE_LEVEL");
570 auto it = dump_level_map.find(dump_level_in_env);
571 if (it == dump_level_map.end()) {
572 return;
573 }
574 // Use the env setting instead parameter setting.
575 *dump_location = it->second;
576 }
577
578 #ifdef ENABLE_DUMP_IR
DumpIR(const std::string & filename,const FuncGraphPtr & graph,bool dump_full_name,LocDumpMode dump_location,const std::string & target_file)579 void DumpIR(const std::string &filename, const FuncGraphPtr &graph, bool dump_full_name, LocDumpMode dump_location,
580 const std::string &target_file) {
581 GetEnvDumpIrLineLevel(&dump_location);
582 if (graph == nullptr) {
583 return;
584 }
585 auto path = GetSaveGraphsPathName(Common::AddId(filename, ".ir"));
586 if (!target_file.empty()) {
587 path = target_file;
588 }
589 auto realpath = Common::CreatePrefixPath(path);
590 if (!realpath.has_value()) {
591 MS_LOG(ERROR) << "Get real path failed, path=" << path;
592 return;
593 }
594
595 ChangeFileMode(realpath.value(), S_IWUSR);
596 std::ofstream fout(realpath.value());
597 std::ostringstream buffer;
598 if (!fout.is_open()) {
599 MS_LOG(ERROR) << "Open dump file '" << realpath.value() << "' failed!" << ErrnoToString(errno);
600 return;
601 }
602
603 auto nodes = TopoSort(graph->get_return(), SuccDeeperSimple, AlwaysInclude);
604 OrderedMap<AnfNodePtr, int32_t> para_map;
605 // dump global info
606 DumpGlobalInfoEntry(graph, buffer);
607 int32_t total_para = DumpParams(graph, buffer, ¶_map);
608
609 OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> sub_graphs;
610 // dump ir in each sub graph
611 DumpIRInSubgraph(nodes, ¶_map, &sub_graphs, total_para, dump_full_name, dump_location);
612
613 // output global info
614 fout << buffer.str() << std::endl;
615
616 // output each sub graph
617 DumpSubgraph(&sub_graphs, graph, ¶_map, fout);
618
619 fout.close();
620 // set file mode to read only by user
621 ChangeFileMode(realpath.value(), S_IRUSR);
622 }
623
DumpIRForRDR(const std::string & filename,const FuncGraphPtr & graph,bool dump_full_name,LocDumpMode dump_location)624 void DumpIRForRDR(const std::string &filename, const FuncGraphPtr &graph, bool dump_full_name,
625 LocDumpMode dump_location) {
626 GetEnvDumpIrLineLevel(&dump_location);
627 if (graph == nullptr) {
628 return;
629 }
630 auto path = Common::AddId(filename, ".ir");
631 auto realpath = Common::CreatePrefixPath(path);
632 if (!realpath.has_value()) {
633 MS_LOG(ERROR) << "Get real path failed. path=" << path;
634 return;
635 }
636
637 ChangeFileMode(realpath.value(), S_IWUSR);
638 std::ofstream fout(realpath.value());
639 std::ostringstream buffer;
640 if (!fout.is_open()) {
641 MS_LOG(ERROR) << "Open dump file '" << realpath.value() << "' failed!" << ErrnoToString(errno);
642 return;
643 }
644
645 auto nodes = TopoSort(graph->get_return(), SuccDeeperSimple, AlwaysInclude);
646 OrderedMap<AnfNodePtr, int32_t> para_map;
647 // dump global info
648 DumpGlobalInfoEntry(graph, buffer);
649 int32_t total_para = DumpParams(graph, buffer, ¶_map);
650
651 OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> sub_graphs;
652 // dump ir in each sub graph
653 DumpIRInSubgraph(nodes, ¶_map, &sub_graphs, total_para, dump_full_name, dump_location);
654
655 // output global info
656 fout << buffer.str() << std::endl;
657
658 // output each sub graph
659 DumpSubgraph(&sub_graphs, graph, ¶_map, fout);
660
661 fout.close();
662 // set file mode to read only by user
663 ChangeFileMode(realpath.value(), S_IRUSR);
664 }
665
666 #else
DumpIR(const std::string &,const FuncGraphPtr &,bool,LocDumpMode,const std::string &)667 void DumpIR(const std::string &, const FuncGraphPtr &, bool, LocDumpMode, const std::string &) {
668 static bool already_printed = false;
669 if (already_printed) {
670 return;
671 }
672 already_printed = true;
673 MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
674 << "please recompile source to enable it. See help of building script.";
675 }
DumpIRForRDR(const std::string &,const FuncGraphPtr &,bool,LocDumpMode)676 void DumpIRForRDR(const std::string &, const FuncGraphPtr &, bool, LocDumpMode) {
677 static bool already_printed = false;
678 if (already_printed) {
679 return;
680 }
681 already_printed = true;
682 MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
683 << "please recompile source to enable it. See help of building script.";
684 }
685 #endif
686 } // namespace mindspore
687