1 /**
2 * Copyright 2019-2023 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 "include/common/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 <nlohmann/json.hpp>
23 #include "mindspore/core/ops/structure_ops.h"
24 #include "utils/label.h"
25 #include "utils/hash_map.h"
26 #include "utils/hash_set.h"
27 #include "utils/symbolic.h"
28 #include "utils/compile_config.h"
29 #include "ir/primitive.h"
30 #include "ir/func_graph.h"
31 #include "ir/graph_utils.h"
32 #include "ir/value.h"
33 #include "utils/trace_base.h"
34 #include "utils/anf_utils.h"
35 #include "include/common/utils/anfalgo.h"
36 #include "include/common/debug/anf_dump_utils.h"
37 #include "mindspore/core/utils/file_utils.h"
38 #include "ir/meta_func_graph.h"
39 #include "pipeline/jit/ps/parse/resolve.h"
40 #include "frontend/operator/composite/composite.h"
41 #include "frontend/expander/bprop/bprop_meta_func_graph.h"
42 #include "frontend/operator/composite/vmap.h"
43 #include "frontend/operator/composite/map.h"
44
45 using MetaFuncGraph = mindspore::MetaFuncGraph;
46 using MetaFuncGraphPtr = std::shared_ptr<MetaFuncGraph>;
47 namespace mindspore {
48
49 enum FormatLevel : int {
50 // When setting to basic level, ir will only contains operator and operands of nodes and title of subgraph with
51 // its debuginfo
52 kBasicLevel = 0,
53 // When setting to advanced level, ir will contains all the info except scope and debug info of nodes.
54 kAdvancedLevel,
55 // When setting to advanced level, ir will contains all the info.
56 kFullyLevel,
57 };
58
GetMultitypeFuncGraphText(const prim::MultitypeFuncGraphPtr & mt_func_graph)59 std::string GetMultitypeFuncGraphText(const prim::MultitypeFuncGraphPtr &mt_func_graph) {
60 auto py_funcs = mt_func_graph->GetPyFunctions();
61 if (py_funcs.empty()) {
62 return "";
63 }
64
65 std::ostringstream oss;
66
67 oss << "{";
68 bool is_first = true;
69 for (const auto &py_func : py_funcs) {
70 if (is_first) {
71 is_first = false;
72 } else {
73 oss << ", ";
74 }
75 oss << "(";
76 for (size_t i = 0; i < py_func.first.size(); ++i) {
77 if (i > 0) {
78 oss << ", ";
79 }
80 oss << py_func.first[i]->DumpText();
81 }
82 oss << ")";
83 }
84 oss << "}";
85
86 return oss.str();
87 }
88
Skip(const MetaFuncGraphPtr & meta_func_graph)89 inline bool Skip(const MetaFuncGraphPtr &meta_func_graph) {
90 return meta_func_graph->isa<prim::Tail>() || meta_func_graph->isa<prim::MakeTupleGradient>() ||
91 meta_func_graph->isa<prim::MakeListGradient>() || meta_func_graph->isa<prim::MakeDictGradient>() ||
92 meta_func_graph->isa<prim::TupleAdd>() || meta_func_graph->isa<prim::SequenceSliceGetItem>() ||
93 meta_func_graph->isa<prim::ListSliceSetItem>() || meta_func_graph->isa<prim::UnpackCall>() ||
94 meta_func_graph->isa<prim::ZipOperation>() || meta_func_graph->isa<prim::ListAppend>() ||
95 meta_func_graph->isa<prim::ListInsert>() || meta_func_graph->isa<prim::DoSignatureMetaFuncGraph>() ||
96 meta_func_graph->isa<prim::VmapMatchOutAxis>() || meta_func_graph->isa<prim::VmapGeneralPreprocess>() ||
97 meta_func_graph->isa<prim::GradAux>() || meta_func_graph->isa<prim::PyExecuteGradient>() ||
98 meta_func_graph->isa<prim::MutableGradient>() || meta_func_graph->isa<prim::ZerosLike>() ||
99 meta_func_graph->isa<prim::ListAdd>() || meta_func_graph->isa<prim::StarredGetItem>() ||
100 meta_func_graph->isa<prim::StarredUnpack>() || meta_func_graph->isa<prim::StarredUnpackMerge>() ||
101 meta_func_graph->isa<prim::IterConverter>() || meta_func_graph->isa<prim::HasNext>() ||
102 meta_func_graph->isa<prim::Next>();
103 }
104
GetMetaFuncGraphText(const MetaFuncGraphPtr & meta_func_graph)105 std::string GetMetaFuncGraphText(const MetaFuncGraphPtr &meta_func_graph) {
106 if (meta_func_graph == nullptr) {
107 return "";
108 }
109
110 std::ostringstream oss;
111 oss << meta_func_graph->type_name() << "_" << meta_func_graph->name();
112
113 if (meta_func_graph->isa<prim::MultitypeFuncGraph>()) {
114 prim::MultitypeFuncGraphPtr mt_func_graph = meta_func_graph->cast<prim::MultitypeFuncGraphPtr>();
115 oss << GetMultitypeFuncGraphText(mt_func_graph);
116 } else if (meta_func_graph
117 ->isa<prim::HyperMapPy>()) { // This statement must before 'meta_graph->isa<prim::HyperMap>()'
118 auto hyper_map = meta_func_graph->cast<prim::HyperMapPyPtr>();
119 if (hyper_map->GetFnLeaf() != nullptr) {
120 oss << "{fn_leaf: " << GetMetaFuncGraphText(hyper_map->GetFnLeaf()) << "}";
121 }
122 } else if (meta_func_graph->isa<prim::HyperMap>()) {
123 auto hyper_map = meta_func_graph->cast<prim::HyperMapPtr>();
124 if (hyper_map->GetFnLeaf() != nullptr) {
125 oss << "{fn_leaf: " << GetMetaFuncGraphText(hyper_map->GetFnLeaf()) << "}";
126 }
127 } else if (meta_func_graph->isa<prim::MapPy>()) { // This statement must before 'meta_graph->isa<prim::Map>()'
128 auto map = meta_func_graph->cast<prim::MapPyPtr>();
129 if (map->GetFnLeaf() != nullptr) {
130 oss << "{fn_leaf: " << GetMetaFuncGraphText(map->GetFnLeaf()) << "}";
131 }
132 } else if (meta_func_graph->isa<prim::Map>()) {
133 auto map = meta_func_graph->cast<prim::MapPtr>();
134 if (map->GetFnLeaf() != nullptr) {
135 oss << "{fn_leaf: " << GetMetaFuncGraphText(map->GetFnLeaf()) << "}";
136 }
137 } else if (meta_func_graph->isa<prim::GradOperation>()) {
138 prim::GradOperationPtr grad_op = meta_func_graph->cast<prim::GradOperationPtr>();
139 oss << "{get_all: " << grad_op->get_all_ << ", get_by_list: " << grad_op->get_by_list_
140 << ", sens_param: " << grad_op->sens_param_ << "}";
141 } else if (meta_func_graph->isa<prim::VmapGeneralRule>()) {
142 prim::VmapGeneralRulePtr general_rule_fg = meta_func_graph->cast<prim::VmapGeneralRulePtr>();
143 oss << "{prim: " << general_rule_fg->prim_name() << ", axis_size: " << general_rule_fg->axis_size() << "}";
144 } else if (meta_func_graph->isa<expander::bprop::BpropMetaFuncGraph>()) {
145 oss << "{" << meta_func_graph->name() << "}";
146 } else if (Skip(meta_func_graph)) {
147 // Do nothing.
148 } else {
149 MS_LOG(INTERNAL_EXCEPTION) << "Unknown MetaFuncGraph type " << meta_func_graph->type_name();
150 }
151
152 return oss.str();
153 }
154
GetPrimitiveText(const PrimitivePtr & prim)155 std::string GetPrimitiveText(const PrimitivePtr &prim) {
156 std::ostringstream oss;
157 if (!prim->instance_name().empty()) {
158 oss << " {";
159 oss << "instance name"
160 << ": ";
161 oss << prim->instance_name();
162 oss << "}";
163 }
164 auto attrs = prim->attrs();
165 if (!attrs.empty()) {
166 oss << " primitive_attrs: {";
167 oss << prim->GetAttrsText();
168 oss << "}";
169 }
170
171 if (prim->isa<prim::DoSignaturePrimitive>()) {
172 auto do_signature = dyn_cast<prim::DoSignaturePrimitive>(prim);
173 auto &func = do_signature->function();
174 if (func->isa<Primitive>()) {
175 auto sig_prim = dyn_cast<Primitive>(func);
176 oss << sig_prim->GetAttrsText();
177 }
178 }
179
180 return oss.str();
181 }
182
GetSequenceText(const ValuePtr & value,const std::shared_ptr<SubGraphIRInfo> & gsub)183 std::string GetSequenceText(const ValuePtr &value, const std::shared_ptr<SubGraphIRInfo> &gsub) {
184 std::ostringstream oss;
185 // Output ValueList, ValueTuple
186 ValueSequencePtr seq = dyn_cast<ValueSequence>(value);
187 MS_EXCEPTION_IF_NULL(seq);
188 MS_EXCEPTION_IF_NULL(value);
189 bool is_tuple = value->isa<ValueTuple>();
190 oss << (is_tuple ? "(" : "[");
191 bool first_flag = true;
192 for (auto elem : seq->value()) {
193 if (first_flag) {
194 first_flag = false;
195 } else {
196 oss << ", ";
197 }
198 oss << GetValueText(elem, gsub);
199 }
200 oss << (is_tuple ? ")" : "]");
201 return oss.str();
202 }
203
GetDictText(const ValuePtr & value,const std::shared_ptr<SubGraphIRInfo> & gsub)204 std::string GetDictText(const ValuePtr &value, const std::shared_ptr<SubGraphIRInfo> &gsub) {
205 std::ostringstream oss;
206 MS_EXCEPTION_IF_NULL(value);
207 ValueDictionaryPtr dict = value->cast<ValueDictionaryPtr>();
208 oss << "{";
209 bool first_flag = true;
210 for (const auto &elem : dict->value()) {
211 if (first_flag) {
212 first_flag = false;
213 } else {
214 oss << ", ";
215 }
216 oss << "\"" << elem.first->ToString() << "\": " << GetValueText(elem.second, gsub);
217 }
218 oss << "}";
219 return oss.str();
220 }
221
GetOtherValueText(const ValuePtr & value)222 std::string GetOtherValueText(const ValuePtr &value) {
223 std::ostringstream oss;
224 oss << value->type_name() << "[" << value->ToString() << "]";
225 return oss.str();
226 }
227
CanUseDumpText(const ValuePtr & value)228 static bool CanUseDumpText(const ValuePtr &value) {
229 return (value->isa<RefKey>() || value->isa<Scalar>() || value->isa<StringImm>() || value->isa<tensor::Tensor>() ||
230 value->isa<parse::Symbol>() || value->isa<None>() || value->isa<Null>() || value->isa<ValueSlice>() ||
231 value->isa<Type>() || value->isa<KeywordArg>() || value->isa<SymbolicKeyInstance>());
232 }
233
GetValueText(const ValuePtr & value,const std::shared_ptr<SubGraphIRInfo> & gsub)234 std::string GetValueText(const ValuePtr &value, const std::shared_ptr<SubGraphIRInfo> &gsub) {
235 MS_EXCEPTION_IF_NULL(value);
236 if (value->isa<Primitive>()) {
237 return GetPrimitiveText(value->cast<PrimitivePtr>());
238 }
239 if (value->isa<MetaFuncGraph>()) {
240 MetaFuncGraphPtr meta_func_graph = value->cast<MetaFuncGraphPtr>();
241 return GetMetaFuncGraphText(meta_func_graph);
242 }
243 if (value->isa<ValueSequence>()) {
244 return GetSequenceText(value, gsub);
245 }
246 if (value->isa<ValueDictionary>()) {
247 return GetDictText(value, gsub);
248 }
249 if (CanUseDumpText(value)) {
250 return value->DumpText();
251 } else {
252 return GetOtherValueText(value);
253 }
254 }
255
PrintTupleNodeUsedFlags(std::ostringstream & buffer,const abstract::AbstractSequencePtr & sequence_abs)256 void PrintTupleNodeUsedFlags(std::ostringstream &buffer, const abstract::AbstractSequencePtr &sequence_abs) {
257 if (sequence_abs == nullptr || sequence_abs->sequence_nodes() == nullptr || sequence_abs->sequence_nodes()->empty()) {
258 return;
259 }
260 static const bool dump_dde_detail = (common::GetCompileConfig("DUMP_IR_DDE_DETAIL") == "1");
261 if (dump_dde_detail) {
262 buffer << ", sequence_nodes={";
263 for (size_t i = 0; i < sequence_abs->sequence_nodes()->size(); ++i) {
264 auto node = (*sequence_abs->sequence_nodes())[i].lock();
265 if (node == nullptr) {
266 MS_LOG(DEBUG) << "The node in sequence_nodes is free.";
267 buffer << "node={<freed node>}";
268 } else {
269 buffer << "node={" << node << "/" << node->DebugString();
270 auto flags = GetSequenceNodeElementsUseFlags(node);
271 if (flags != nullptr) {
272 buffer << ", elements_use_flags: {ptr: " << flags << ", value: " << (*flags) << "}";
273 }
274 buffer << "}";
275 }
276 if (i != sequence_abs->sequence_nodes()->size() - 1) {
277 buffer << ", ";
278 }
279 }
280 buffer << "}";
281 } else {
282 buffer << ", elements_use_flags={";
283 for (size_t i = 0; i < sequence_abs->sequence_nodes()->size(); ++i) {
284 auto node = (*sequence_abs->sequence_nodes())[i].lock();
285 if (node == nullptr) {
286 continue;
287 }
288 auto flags = GetSequenceNodeElementsUseFlags(node);
289 if (flags != nullptr) {
290 buffer << (*flags);
291 break;
292 }
293 }
294 buffer << "}";
295 }
296 }
297
PrintNodeOutputType(std::ostringstream & buffer,const AnfNodePtr & node)298 void PrintNodeOutputType(std::ostringstream &buffer, const AnfNodePtr &node) {
299 if (node == nullptr) {
300 return;
301 }
302
303 ValuePtr tensor_value = nullptr;
304 StringImmPtr ref_key = nullptr;
305 abstract::AbstractSequencePtr sequence_abs = nullptr;
306 auto abstract = node->abstract();
307 if (abstract != nullptr) {
308 if (abstract->isa<abstract::AbstractTensor>()) {
309 tensor_value = abstract->BuildValue();
310 }
311 if (auto ref_tensor = abstract->cast_ptr<abstract::AbstractRefTensor>(); ref_tensor != nullptr) {
312 ref_key = dyn_cast<StringImm>(ref_tensor->ref_key_value());
313 } else if (auto map_tensor = abstract->cast_ptr<abstract::AbstractMapTensor>(); map_tensor != nullptr) {
314 ref_key = dyn_cast<StringImm>(map_tensor->ref_key_value());
315 }
316 sequence_abs = dyn_cast<abstract::AbstractSequence>(abstract);
317 }
318
319 abstract::BaseShapePtr shape = dyn_cast<abstract::BaseShape>(node->Shape());
320 TypePtr type = dyn_cast<Type>(node->Type());
321 if ((shape != nullptr) && (type != nullptr)) {
322 buffer << "<" << type << ", " << shape->ToString();
323 if (tensor_value != nullptr && tensor_value != kValueAny) {
324 buffer << ", value=...";
325 }
326 if (ref_key != nullptr) {
327 buffer << ", ref_key=" << ref_key->value();
328 }
329 PrintTupleNodeUsedFlags(buffer, sequence_abs);
330 buffer << ">";
331 } else if (type != nullptr) {
332 buffer << "<" << type;
333 if (tensor_value != nullptr && tensor_value != kValueAny) {
334 buffer << ", value=...";
335 }
336 if (ref_key != nullptr) {
337 buffer << ", ref_key=" << ref_key->value();
338 }
339 PrintTupleNodeUsedFlags(buffer, sequence_abs);
340 buffer << ">";
341 } else {
342 buffer << "<null>";
343 }
344 }
345
PrintNodeInputType(std::ostringstream & buffer,const AnfNodePtr & node)346 void PrintNodeInputType(std::ostringstream &buffer, const AnfNodePtr &node) {
347 if (node == nullptr) {
348 return;
349 }
350
351 const auto &inputs = GetInputs(node);
352 size_t len = inputs.size();
353 if (len > 1) {
354 // Skip inputs[0] which is Primitive value node
355 for (size_t i = 1; i < len; ++i) {
356 AnfNodePtr in = inputs[i];
357 if (i != 1) {
358 buffer << ", ";
359 }
360 PrintNodeOutputType(buffer, in);
361 }
362 }
363 }
364
PrintNodeOutputSymbolicInfo(std::ostringstream & buffer,const AnfNodePtr & node)365 void PrintNodeOutputSymbolicInfo(std::ostringstream &buffer, const AnfNodePtr &node) {
366 if (node == nullptr) {
367 return;
368 }
369 auto abstract = node->abstract();
370 if (abstract == nullptr) {
371 buffer << "<null>";
372 return;
373 }
374 auto shape = abstract->GetSymbolicShape();
375 auto value = abstract->GetSymbolicValue();
376 if (shape != nullptr || value != nullptr) {
377 if (shape != nullptr) {
378 buffer << "S:" << shape->ToString();
379 }
380 if (value != nullptr) {
381 buffer << "V:" << value->ToString();
382 }
383 } else {
384 buffer << "<null>";
385 }
386 }
387
PrintNodeInputSymbolicInfo(std::ostringstream & buffer,const AnfNodePtr & node)388 void PrintNodeInputSymbolicInfo(std::ostringstream &buffer, const AnfNodePtr &node) {
389 if (node == nullptr) {
390 return;
391 }
392 const auto &inputs = GetInputs(node);
393 if (inputs.size() <= 1) {
394 return;
395 }
396 for (size_t i = 1; i < inputs.size(); ++i) {
397 if (i != 1) {
398 buffer << ", ";
399 }
400 PrintNodeOutputSymbolicInfo(buffer, inputs[i]);
401 }
402 }
403
DumpSymbolicInfo(const AnfNodePtr & node,const FuncGraphPtr & fg,const std::shared_ptr<SubGraphIRInfo> & gsub)404 void DumpSymbolicInfo(const AnfNodePtr &node, const FuncGraphPtr &fg, const std::shared_ptr<SubGraphIRInfo> &gsub) {
405 if (node == nullptr || fg == nullptr || gsub == nullptr || fg->symbol_engine() == nullptr) {
406 return;
407 }
408 if (node != fg->get_return()) {
409 gsub->buffer << " : (";
410 PrintNodeInputSymbolicInfo(gsub->buffer, node);
411 gsub->buffer << ") -> (";
412 PrintNodeOutputSymbolicInfo(gsub->buffer, node);
413 gsub->buffer << ")";
414 } else {
415 gsub->buffer << " : (";
416 PrintNodeInputSymbolicInfo(gsub->buffer, node);
417 gsub->buffer << ")";
418 }
419 gsub->buffer << std::endl;
420 }
421
PrintParamSymbolicShape(std::ostringstream & buffer,const AnfNodePtr & node)422 void PrintParamSymbolicShape(std::ostringstream &buffer, const AnfNodePtr &node) {
423 if (node == nullptr) {
424 return;
425 }
426 auto abstract = node->abstract();
427 if (abstract == nullptr) {
428 return;
429 }
430 SymbolPtr shape = abstract->GetSymbolicShape();
431 if (shape != nullptr) {
432 buffer << " : " << shape->ToString();
433 }
434 }
435
GatherInputAndOutputInferType(std::ostringstream & buffer,const AnfNodePtr & node)436 void GatherInputAndOutputInferType(std::ostringstream &buffer, const AnfNodePtr &node) {
437 buffer << " : (";
438 PrintNodeInputType(buffer, node);
439 buffer << ") -> (";
440 PrintNodeOutputType(buffer, node);
441 buffer << ")";
442 }
443
DumpGlobalInfoEntry(const FuncGraphPtr & graph,std::ostringstream & buffer,size_t sub_graphs_size)444 void DumpGlobalInfoEntry(const FuncGraphPtr &graph, std::ostringstream &buffer, size_t sub_graphs_size) {
445 if (graph == nullptr) {
446 return;
447 }
448
449 buffer << "# IR entry: @" << graph->ToString() << std::endl;
450 buffer << "# Total subgraphs: " << sub_graphs_size << std::endl;
451 buffer << std::endl;
452
453 if (!graph->attrs().empty()) {
454 buffer << "# Attrs:" << std::endl;
455 for (const auto &attr : graph->attrs()) {
456 buffer << attr.first << ": ";
457 if (attr.second->isa<BoolImm>()) {
458 buffer << GetValue<bool>(attr.second);
459 } else if (attr.second->isa<StringImm>()) {
460 buffer << GetValue<std::string>(attr.second);
461 }
462 buffer << std::endl;
463 }
464 buffer << std::endl;
465 }
466 }
467
DumpKernelObjectType(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)468 void DumpKernelObjectType(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
469 auto inputs_str = AnfDumpHandler::PrintInputKernelObjectTypes(node);
470 auto outputs_str = AnfDumpHandler::PrintOutputKernelObjectTypes(node);
471 if (inputs_str.empty() && outputs_str.empty()) {
472 return;
473 }
474 gsub->buffer << " : (" << inputs_str << ") -> (" << outputs_str << ")" << std::endl;
475 }
476
DumpKernelInfo(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)477 void DumpKernelInfo(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
478 if (node == nullptr || gsub == nullptr) {
479 return;
480 }
481 auto kernel_info = node->kernel_info();
482 if (kernel_info == nullptr || !kernel_info->has_build_info()) {
483 return;
484 }
485 if (!AnfUtils::IsRealKernel(node)) {
486 DumpKernelObjectType(node, gsub);
487 return;
488 }
489
490 gsub->buffer << " : (";
491 gsub->buffer << AnfDumpHandler::PrintInputTypeShapeFormat(node);
492 gsub->buffer << ") -> (";
493 gsub->buffer << AnfDumpHandler::PrintOutputTypeShapeFormat(node);
494 gsub->buffer << ")";
495 gsub->buffer << std::endl;
496 DumpKernelObjectType(node, gsub);
497 }
498
DumpParams(const FuncGraphPtr & graph,std::ostringstream & buffer,OrderedMap<AnfNodePtr,int32_t> * para_map)499 int32_t DumpParams(const FuncGraphPtr &graph, std::ostringstream &buffer, OrderedMap<AnfNodePtr, int32_t> *para_map) {
500 if (graph == nullptr) {
501 MS_LOG(INFO) << "Parameter \'graph\' should not be null.";
502 return 0;
503 }
504 std::vector<AnfNodePtr> parameters = graph->parameters();
505 buffer << "# Total params: " << parameters.size() << std::endl;
506
507 if (parameters.empty()) {
508 return 0;
509 }
510 buffer << "# Params:" << std::endl;
511 // Dump parameters
512 int32_t para_num = 1;
513 for (const auto ¶m : parameters) {
514 if (param == nullptr) {
515 continue;
516 }
517 auto parameter_ptr = param->cast<ParameterPtr>();
518 if (parameter_ptr == nullptr) {
519 MS_LOG(INTERNAL_EXCEPTION) << "param cannot cast to ParameterPtr";
520 }
521 buffer << "%para" << para_num << "_" << parameter_ptr->name() << ": ";
522 // Print parameters' type and shape
523 PrintNodeOutputType(buffer, param);
524 PrintParamSymbolicShape(buffer, param);
525 if (parameter_ptr->has_default()) {
526 buffer << " : has_default";
527 }
528 auto kernel_info = param->kernel_info();
529 if (kernel_info != nullptr && kernel_info->has_build_info()) {
530 buffer << " : ";
531 buffer << AnfDumpHandler::PrintOutputTypeShapeFormat(param);
532 buffer << " : IsWeight: " << std::boolalpha << common::AnfAlgo::IsParameterWeight(parameter_ptr);
533 }
534 buffer << std::endl;
535
536 if (para_map != nullptr) {
537 (*para_map)[param] = para_num++;
538 }
539 if (param->func_graph() == nullptr) {
540 MS_LOG(EXCEPTION) << "Get func graph nullptr, node " << param->DebugString();
541 }
542 MS_LOG(DEBUG) << "Record param: " << param->ToString() << " graph belong : " << param->func_graph()->ToString();
543 }
544 return para_num;
545 }
546
DumpParameterOperator(const AnfNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub,const AnfNodePtr & op)547 void DumpParameterOperator(const AnfNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub, const AnfNodePtr &op) {
548 if (op->func_graph() != nullptr && op->func_graph() != node->func_graph()) {
549 gsub->buffer << "$(@" << op->func_graph()->ToString() << ":";
550 }
551 gsub->buffer << op->ToString();
552 if (op->func_graph() != nullptr && op->func_graph() != node->func_graph()) {
553 gsub->buffer << ")";
554 }
555 std::string func_str = GetNodeFuncStr(op);
556 if (!func_str.empty()) {
557 gsub->buffer << "[@" << func_str << "]";
558 }
559 }
560
DumpOperator(const AnfNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)561 void DumpOperator(const AnfNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
562 if (gsub == nullptr) {
563 MS_LOG(INFO) << "Parameter \'gsub\' should not be null.";
564 return;
565 }
566 auto cnode = dyn_cast<CNode>(node);
567 if (cnode == nullptr) {
568 MS_LOG(INTERNAL_EXCEPTION) << "Parameter \'node\' should be a CNode";
569 }
570 AnfNodePtr op = cnode->input(0);
571 MS_EXCEPTION_IF_NULL(op);
572 if (IsValueNode<FuncGraph>(op)) {
573 FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(op);
574 if (fg != nullptr) {
575 gsub->buffer << "call @" << fg->ToString();
576 }
577 } else if (op->isa<CNode>()) {
578 std::string func_str = GetNodeFuncStr(op);
579 if (gsub->local_var_map.find(op) != gsub->local_var_map.end()) {
580 gsub->buffer << "%" << gsub->local_var_map[op];
581 } else {
582 auto input = op->cast<CNodePtr>();
583 auto fg = input->func_graph();
584 if (fg == nullptr) {
585 MS_LOG(EXCEPTION) << "Get func graph nullptr, node " << node->DebugString();
586 }
587 gsub->buffer << "$(@" << fg->ToString() << ":" << input->ToString() << ")";
588 }
589 if (!func_str.empty()) {
590 gsub->buffer << "[@" << func_str << "]";
591 }
592 } else if (op->isa<ValueNode>()) {
593 auto value = GetValueNode(op);
594 if (value != nullptr) {
595 if (value->isa<Primitive>()) {
596 gsub->buffer << value->ToString();
597 } else {
598 gsub->buffer << GetValueText(value, gsub);
599 }
600 }
601 } else {
602 // It's Parameter.
603 DumpParameterOperator(node, gsub, op);
604 }
605 }
606
DumpParamterInOperand(const AnfNodePtr & node,const AnfNodePtr & in,const OrderedMap<AnfNodePtr,int32_t> & para_map,const std::shared_ptr<SubGraphIRInfo> & gsub)607 void DumpParamterInOperand(const AnfNodePtr &node, const AnfNodePtr &in,
608 const OrderedMap<AnfNodePtr, int32_t> ¶_map,
609 const std::shared_ptr<SubGraphIRInfo> &gsub) {
610 MS_EXCEPTION_IF_NULL(node);
611 MS_EXCEPTION_IF_NULL(node->func_graph());
612 MS_EXCEPTION_IF_NULL(in);
613 MS_EXCEPTION_IF_NULL(gsub);
614 if (in->func_graph() == nullptr) {
615 MS_LOG(INFO) << "Parameter should belong to a func graph. Check func graph: " << node->func_graph();
616 }
617 if (in->func_graph() != nullptr && in->func_graph() != node->func_graph()) {
618 gsub->buffer << "$(@" << in->func_graph()->ToString() << ":";
619 } else {
620 gsub->buffer << "%";
621 }
622 auto iter = para_map.find(in);
623 if (iter == para_map.end()) {
624 gsub->buffer << "para_" << in->ToString();
625 } else {
626 gsub->buffer << "para" << iter->second << "_" << in->ToString();
627 }
628 if (in->func_graph() != nullptr && in->func_graph() != node->func_graph()) {
629 gsub->buffer << ")";
630 }
631 }
632
DumpOperands(const AnfNodePtr & node,const OrderedMap<AnfNodePtr,int32_t> & para_map,const std::shared_ptr<SubGraphIRInfo> & gsub)633 void DumpOperands(const AnfNodePtr &node, const OrderedMap<AnfNodePtr, int32_t> ¶_map,
634 const std::shared_ptr<SubGraphIRInfo> &gsub) {
635 if (node == nullptr || gsub == nullptr) {
636 return;
637 }
638
639 gsub->buffer << "(";
640 const auto &inputs = GetInputs(node);
641 size_t len = inputs.size();
642 if (len > 1) {
643 // Skip inputs[0] which is Primitive valuenode
644 for (size_t i = 1; i < len; ++i) {
645 AnfNodePtr in = inputs[i];
646 MS_EXCEPTION_IF_NULL(in);
647 if (i != 1) {
648 gsub->buffer << ", ";
649 }
650 if (in->isa<Parameter>()) {
651 DumpParamterInOperand(node, in, para_map, gsub);
652 } else if (in->isa<CNode>()) {
653 auto iter = gsub->local_var_map.find(in);
654 if (iter != gsub->local_var_map.end()) {
655 gsub->buffer << "%" << iter->second;
656 } else {
657 auto input = in->cast<CNodePtr>();
658 auto fg = input->func_graph();
659 if (fg == nullptr) {
660 MS_LOG(EXCEPTION) << "Get func graph nullptr, node " << input->DebugString();
661 }
662 gsub->buffer << "$(@" << fg->ToString() << ":" << input->ToString() << ")";
663 }
664 } else if (in->isa<ValueNode>() && !IsValueNode<FuncGraph>(in)) {
665 // ValueNode except FuncGraph.
666 gsub->buffer << GetValueText(GetValueNode(in), gsub);
667 } else if (IsValueNode<FuncGraph>(in)) {
668 FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(in);
669 if (fg == nullptr) {
670 MS_LOG(EXCEPTION) << "Get func graph nullptr, node " << in->DebugString();
671 }
672 gsub->buffer << "@" << fg->ToString();
673 } else if (AnfUtils::IsCustomActorNode(in)) {
674 gsub->buffer << "%" << AnfUtils::GetCustomActorName(in);
675 } else {
676 gsub->buffer << in->ToString();
677 }
678 }
679 }
680 gsub->buffer << ")";
681 }
682
DumpParallelInfo(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)683 void DumpParallelInfo(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
684 if ((node == nullptr) || (gsub == nullptr)) {
685 return;
686 }
687
688 ValuePtr in_tmp = AnfDumpHandler::InStrategyValue(node);
689 if (in_tmp == nullptr) {
690 return;
691 }
692 gsub->buffer << " {in_strategy: ";
693 gsub->buffer << in_tmp->ToString();
694
695 ValuePtr out_tmp = AnfDumpHandler::OutStrategyValue(node);
696 if (out_tmp != nullptr) {
697 gsub->buffer << ", out_strategy: ";
698 gsub->buffer << out_tmp->ToString();
699 }
700
701 gsub->buffer << "}";
702 }
703
DumpAttrs(const mindspore::HashMap<std::string,ValuePtr> & attrs,const std::shared_ptr<SubGraphIRInfo> & gsub,bool check_strategy=false)704 void DumpAttrs(const mindspore::HashMap<std::string, ValuePtr> &attrs, const std::shared_ptr<SubGraphIRInfo> &gsub,
705 bool check_strategy = false) {
706 int i = 0;
707 for (const auto &attr : attrs) {
708 if (check_strategy && attr.first == PARALLEL_STRATEGY) {
709 continue; // Skip the strategy
710 }
711 if (i++ != 0) {
712 gsub->buffer << ", ";
713 }
714 gsub->buffer << attr.first << ": ";
715 if (attr.second == nullptr) {
716 gsub->buffer << "null";
717 } else {
718 if (CanUseDumpText(attr.second)) {
719 gsub->buffer << attr.second->DumpText();
720 } else {
721 gsub->buffer << attr.second->ToString();
722 }
723 }
724 }
725 }
726
DumpOperateAttrs(const AnfNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)727 void DumpOperateAttrs(const AnfNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
728 if (op == nullptr || gsub == nullptr) {
729 return;
730 }
731
732 if (IsValueNode<Primitive>(op)) {
733 PrimitivePtr primitive = GetValueNode<PrimitivePtr>(op);
734 if (!primitive->instance_name().empty()) {
735 gsub->buffer << " {";
736 gsub->buffer << "instance name"
737 << ": ";
738 gsub->buffer << primitive->instance_name();
739 gsub->buffer << "}";
740 }
741 auto attrs = primitive->attrs();
742 if (!attrs.empty()) {
743 gsub->buffer << " primitive_attrs: {";
744 DumpAttrs(attrs, gsub, true);
745 gsub->buffer << "}";
746 }
747 }
748 }
749
DumpCNodeAttrs(const CNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)750 void DumpCNodeAttrs(const CNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
751 if (op == nullptr || gsub == nullptr) {
752 return;
753 }
754 if (op->attrs().empty()) {
755 return;
756 }
757
758 auto attrs = op->attrs();
759 gsub->buffer << " cnode_attrs: {";
760 DumpAttrs(attrs, gsub);
761 gsub->buffer << "}";
762 }
763
DumpCNodePrimalAttrs(const CNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)764 void DumpCNodePrimalAttrs(const CNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
765 if (op == nullptr || gsub == nullptr) {
766 return;
767 }
768 if (op->primal_attrs().empty()) {
769 return;
770 }
771 auto primal_attrs = op->primal_attrs();
772 gsub->buffer << " cnode_primal_attrs: {";
773 DumpAttrs(primal_attrs, gsub);
774 gsub->buffer << "}";
775 }
776
DumpShape(const AnfNodePtr & node,const FuncGraphPtr & sub_graph,const std::shared_ptr<SubGraphIRInfo> & gsub)777 void DumpShape(const AnfNodePtr &node, const FuncGraphPtr &sub_graph, const std::shared_ptr<SubGraphIRInfo> &gsub) {
778 if (node == nullptr || sub_graph == nullptr || gsub == nullptr) {
779 return;
780 }
781
782 gsub->buffer << std::endl;
783 if (node != sub_graph->get_return()) {
784 gsub->buffer << " : (";
785 PrintNodeInputType(gsub->buffer, node);
786 gsub->buffer << ") -> (";
787 PrintNodeOutputType(gsub->buffer, node);
788 gsub->buffer << ")";
789 } else {
790 gsub->buffer << " : (";
791 PrintNodeInputType(gsub->buffer, node);
792 gsub->buffer << ")";
793 }
794
795 gsub->buffer << std::endl;
796 }
797
DumpLocationInCurrentScope(const DebugInfoPtr & debug_info,const std::shared_ptr<SubGraphIRInfo> & gsub)798 void DumpLocationInCurrentScope(const DebugInfoPtr &debug_info, const std::shared_ptr<SubGraphIRInfo> &gsub) {
799 auto dump_debug_info = debug_info;
800 std::list<DebugInfoPtr> need_dump_debug_infos;
801 const auto &shadow_debug_infos_map = debug_info->shadow_debug_infos_map();
802 HashSet<DebugInfoPtr> all_shadowed_debug_infos;
803 while (dump_debug_info != nullptr) {
804 need_dump_debug_infos.push_front(dump_debug_info);
805 auto iter = shadow_debug_infos_map.find(dump_debug_info);
806 if (iter != shadow_debug_infos_map.end()) {
807 DebugInfoPtr shadowed_debug_info = iter->first;
808 DebugInfoPtr shadow_debug_info = iter->second;
809 MS_LOG(DEBUG) << "Insert debug info, shadow_debug_info: " << shadow_debug_info << "/" << shadow_debug_info->name()
810 << "/" << shadow_debug_info->debug_name() << "/"
811 << trace::GetDebugInfoStr(shadow_debug_info, "", kSourceLineTipNextLine, true) << ", shadow_trace: "
812 << (shadow_debug_info->trace_info() != nullptr ? shadow_debug_info->trace_info()->name() : "none")
813 << ", shadowed_debug_info: " << shadowed_debug_info << "/" << shadowed_debug_info->name() << "/"
814 << shadowed_debug_info->debug_name() << "/"
815 << trace::GetDebugInfoStr(shadowed_debug_info, "", kSourceLineTipNextLine, true)
816 << ", shadowed_trace: "
817 << (shadowed_debug_info->trace_info() != nullptr ? shadowed_debug_info->trace_info()->name()
818 : "none");
819 need_dump_debug_infos.push_front(shadow_debug_info);
820 all_shadowed_debug_infos.emplace(shadowed_debug_info);
821 }
822 if (dump_debug_info->trace_info() == nullptr) {
823 break;
824 }
825 dump_debug_info = dump_debug_info->trace_info()->debug_info();
826 }
827 HashSet<std::string> visited_locations;
828 for (const auto &cur_debug_info : need_dump_debug_infos) {
829 if (cur_debug_info->location() != nullptr) {
830 auto debug_info_str = trace::GetDebugInfoStr(cur_debug_info, "", kSourceLineTipDiscard);
831 if (visited_locations.find(debug_info_str) == visited_locations.cend()) {
832 constexpr auto prefix = " # ";
833 gsub->buffer << prefix << debug_info_str;
834 if (all_shadowed_debug_infos.count(cur_debug_info) != 0) {
835 constexpr auto shared_code_line_hint =
836 "<~~This line of code can be shared by multiple nodes, and may be duplicated./";
837 gsub->buffer << shared_code_line_hint;
838 }
839 gsub->buffer << "\n";
840 (void)visited_locations.insert(debug_info_str);
841 }
842 }
843 }
844 }
845
DumpPrimalDebugInfos(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)846 void DumpPrimalDebugInfos(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
847 MS_EXCEPTION_IF_NULL(node);
848 auto primal_debug_infos = node->primal_debug_infos();
849 if (!primal_debug_infos.empty()) {
850 for (const auto &primal_debug_info : primal_debug_infos) {
851 std::string lines;
852 auto debug_info_str = trace::GetDebugInfoStr(primal_debug_info, " # ", kSourceLineTipDiscard);
853 if (!debug_info_str.empty()) {
854 lines += debug_info_str + "\n";
855 }
856 gsub->buffer << " # Corresponding forward node candidate:\n";
857 if (!lines.empty()) {
858 gsub->buffer << lines;
859 }
860 }
861 }
862 }
863
DumpDebugInfo(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub,const LocDumpMode & dump_location)864 void DumpDebugInfo(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub,
865 const LocDumpMode &dump_location) {
866 MS_EXCEPTION_IF_NULL(node);
867 // Dump comments firstly.
868 if (node->debug_info() != nullptr) {
869 const auto &debug_info = trace::GetSourceCodeDebugInfo(node->debug_info());
870 if (debug_info->location() != nullptr) {
871 const auto &comments = debug_info->location()->comments();
872 if (!comments.empty()) {
873 gsub->buffer << " # Comment:\n";
874 for (auto &comment : comments) {
875 gsub->buffer << " " << comment << '\n';
876 }
877 }
878 }
879 }
880
881 // Dump line info.
882 if (dump_location == kTopStack) {
883 auto fused_debug_infos = node->fused_debug_infos();
884 if (!fused_debug_infos.empty()) {
885 for (const auto &debug_info : fused_debug_infos) {
886 std::string lines;
887 gsub->buffer << " # Corresponding code candidate:\n";
888 auto debug_info_str = trace::GetDebugInfoStr(debug_info, " # ", kSourceLineTipDiscard);
889 if (!debug_info_str.empty()) {
890 lines += debug_info_str + "\n";
891 }
892 if (!lines.empty()) {
893 gsub->buffer << lines;
894 }
895 }
896 } else {
897 auto debug_info_str = trace::GetDebugInfoStr(node->debug_info(), " # ", kSourceLineTipDiscard);
898 if (!debug_info_str.empty()) {
899 gsub->buffer << debug_info_str << "\n";
900 }
901 }
902 DumpPrimalDebugInfos(node, gsub);
903 } else if (dump_location == kWholeStack) {
904 auto fused_debug_infos = node->fused_debug_infos();
905 if (!fused_debug_infos.empty()) {
906 for (const auto &debug_info : fused_debug_infos) {
907 gsub->buffer << " # Corresponding code candidate:\n";
908 DumpLocationInCurrentScope(debug_info, gsub);
909 }
910 } else {
911 DumpLocationInCurrentScope(node->debug_info(), gsub);
912 }
913 // Print whole stack primal infos
914 auto primal_debug_infos = node->primal_debug_infos();
915 if (!primal_debug_infos.empty()) {
916 for (const auto &primal_debug_info : primal_debug_infos) {
917 gsub->buffer << " # Corresponding forward node candidate:\n";
918 DumpLocationInCurrentScope(primal_debug_info, gsub);
919 }
920 }
921 }
922
923 // Dump side effect info.
924 auto effect_info = node->GetEffectInfo();
925 if (effect_info.HasEffect()) {
926 gsub->buffer << " # " << effect_info.ToString() << '\n';
927 }
928 }
929
DumpParameters(const FuncGraphPtr & func_graph,std::ostringstream & oss)930 void DumpParameters(const FuncGraphPtr &func_graph, std::ostringstream &oss) {
931 std::vector<AnfNodePtr> parameters = func_graph->parameters();
932 oss << "# Parameters: " << parameters.size() << ", (";
933 if (parameters.size() == 1) {
934 MS_EXCEPTION_IF_NULL(parameters[0]);
935 PrintNodeOutputType(oss, parameters[0]);
936 } else if (parameters.size() > 1) {
937 for (size_t idx = 0; idx < parameters.size() - 1; idx++) {
938 MS_EXCEPTION_IF_NULL(parameters[idx]);
939 PrintNodeOutputType(oss, parameters[idx]);
940 oss << ", ";
941 }
942 MS_EXCEPTION_IF_NULL(parameters[parameters.size() - 1]);
943 PrintNodeOutputType(oss, parameters[parameters.size() - 1]);
944 }
945 oss << ")\n";
946 }
947
DumpCNode(const CNodePtr & node,const FuncGraphPtr & sub_graph,const OrderedMap<AnfNodePtr,int32_t> & para_map,const std::shared_ptr<SubGraphIRInfo> & gsub,bool dump_full_name,LocDumpMode dump_location)948 void DumpCNode(const CNodePtr &node, const FuncGraphPtr &sub_graph, const OrderedMap<AnfNodePtr, int32_t> ¶_map,
949 const std::shared_ptr<SubGraphIRInfo> &gsub, bool dump_full_name, LocDumpMode dump_location) {
950 if (node == nullptr || sub_graph == nullptr || gsub == nullptr) {
951 return;
952 }
953
954 // Print for TopoSort circle indicator only.
955 if (node->has_user_data(kTopoSortCircle)) {
956 auto num = node->user_data<size_t>(kTopoSortCircle);
957 MS_EXCEPTION_IF_NULL(num);
958 gsub->buffer << "\n#------------------------> " << (*num) << "\n";
959 }
960
961 // Print node's name.
962 if (node != sub_graph->get_return()) {
963 gsub->buffer << " %" << gsub->local_var << "(" << node->ToString() << ")"
964 << " = ";
965 gsub->local_var_map[node] = gsub->local_var++;
966 } else {
967 gsub->buffer << " ";
968 }
969
970 if (node->weak_inputs().empty()) {
971 MS_LOG(INTERNAL_EXCEPTION) << "Input of CNode is empty";
972 }
973
974 // Print operator
975 DumpOperator(node, gsub);
976
977 // Print operands
978 DumpOperands(node, para_map, gsub);
979
980 if (gsub->format_level > kBasicLevel) {
981 // Print operator attrs
982 AnfNodePtr op = node->input(0);
983 DumpOperateAttrs(op, gsub);
984
985 // Print cnode attrs
986 DumpCNodeAttrs(node, gsub);
987
988 // Print cnode primal attrs
989 DumpCNodePrimalAttrs(node, gsub);
990
991 // Print parallel info
992 DumpParallelInfo(node, gsub);
993 }
994
995 if (gsub->format_level > kBasicLevel || node == sub_graph->get_return()) {
996 // Print shape info
997 DumpShape(node, sub_graph, gsub);
998
999 // Print symbolic shape or symbolic value
1000 DumpSymbolicInfo(node, sub_graph, gsub);
1001
1002 // Print kernel info
1003 DumpKernelInfo(node, gsub);
1004 } else {
1005 gsub->buffer << std::endl;
1006 }
1007
1008 // Use environment variables to control extra info.
1009 if (gsub->format_level > kAdvancedLevel) {
1010 if (dump_full_name) {
1011 gsub->buffer << " # Fullname with scope: (" << node->fullname_with_scope() << ")" << std::endl;
1012 } else {
1013 gsub->buffer << " # Scope: (" << node->scope()->name() << ")" << std::endl;
1014 }
1015 // Print debug info
1016 DumpDebugInfo(node, gsub, dump_location);
1017 }
1018 }
1019
OutputOrderList(const FuncGraphPtr & sub_graph,std::ostringstream & oss)1020 void OutputOrderList(const FuncGraphPtr &sub_graph, std::ostringstream &oss) {
1021 auto &order_list = sub_graph->order_list();
1022 if (order_list.empty()) {
1023 return;
1024 }
1025 constexpr int width = 4;
1026 oss << "# Order:\n";
1027 int i = 1;
1028 for (auto &weak_node : order_list) {
1029 const auto &node = weak_node.lock();
1030 if (node != nullptr) {
1031 oss << '#' << std::setw(width) << i << ": " << node->DebugString() << '\n';
1032 }
1033 ++i;
1034 }
1035 }
1036
DumpSymbolEngine(const FuncGraphPtr & sub_graph,std::ostringstream & oss,int format_level)1037 void DumpSymbolEngine(const FuncGraphPtr &sub_graph, std::ostringstream &oss, int format_level) {
1038 if (format_level <= kAdvancedLevel) {
1039 return;
1040 }
1041 if (sub_graph->symbol_engine() != nullptr && sub_graph->symbol_engine()->func_graph() == sub_graph) {
1042 oss << "\nsymbol engine details:\n";
1043 oss << sub_graph->symbol_engine()->DumpText();
1044 }
1045 }
1046
GetDumpFormatLevel()1047 int GetDumpFormatLevel() {
1048 static std::string format = common::GetEnv("MS_DEV_DUMP_IR_FORMAT");
1049 int format_level = 2;
1050 if (format.size() == 1) {
1051 try {
1052 format_level = std::stoi(format);
1053 } catch (const std::invalid_argument &ia) {
1054 MS_LOG(EXCEPTION) << "Invalid argument: " << ia.what() << " when parse " << format
1055 << ". Please set this env variable to number 0-2.";
1056 }
1057 } else if (format.size() > 1) {
1058 MS_LOG(EXCEPTION) << "MS_DEV_DUMP_IR_FORMAT should be a single number with one digit.";
1059 }
1060
1061 if (format_level < 0 || format_level > 2) {
1062 MS_LOG(EXCEPTION) << "Format level can only be from 0 to 2";
1063 }
1064
1065 return format_level;
1066 }
1067
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,LocDumpMode dump_location)1068 void DumpIRInSubgraph(const std::vector<AnfNodePtr> &nodes, OrderedMap<AnfNodePtr, int32_t> *para_map,
1069 OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> *const sub_graphs, int32_t total_para,
1070 bool dump_full_name, LocDumpMode dump_location) {
1071 if (para_map == nullptr || sub_graphs == nullptr) {
1072 return;
1073 }
1074
1075 for (const auto &node : nodes) {
1076 MS_EXCEPTION_IF_NULL(node);
1077 FuncGraphPtr sub_graph = node->func_graph();
1078 if (sub_graph == nullptr) {
1079 MS_LOG(DEBUG) << "Node[" << node->ToString() << "] belongs to no graph!";
1080 continue;
1081 }
1082 std::shared_ptr<SubGraphIRInfo> gsub = (*sub_graphs)[sub_graph];
1083 if (gsub == nullptr) {
1084 gsub = std::make_shared<SubGraphIRInfo>();
1085 gsub->local_var = 0;
1086 gsub->format_level = GetDumpFormatLevel();
1087 (*sub_graphs)[sub_graph] = gsub;
1088 }
1089 std::vector<AnfNodePtr> parameters = sub_graph->parameters();
1090 for (size_t idx = 0; idx < parameters.size(); idx++) {
1091 MS_EXCEPTION_IF_NULL(parameters[idx]);
1092 if ((*para_map).count(parameters[idx]) == 0) {
1093 (*para_map)[parameters[idx]] = total_para++;
1094 }
1095 }
1096 if (!node->isa<Parameter>()) {
1097 if (node->isa<CNode>()) {
1098 // Print and record output of operator if it is not 'Return'
1099 gsub->cnode_num++;
1100 DumpCNode(node->cast<CNodePtr>(), sub_graph, *para_map, gsub, dump_full_name, dump_location);
1101 } else if (AnfUtils::IsCustomActorNode(node)) {
1102 continue;
1103 } else {
1104 gsub->buffer << " " << node->ToString() << std::endl;
1105 }
1106 }
1107 }
1108 }
1109
DumpSubgraph(const OrderedMap<FuncGraphPtr,std::shared_ptr<SubGraphIRInfo>> * sub_graphs,const FuncGraphPtr & graph,OrderedMap<AnfNodePtr,int32_t> * para_map,std::ostringstream & oss)1110 void DumpSubgraph(const OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> *sub_graphs,
1111 const FuncGraphPtr &graph, OrderedMap<AnfNodePtr, int32_t> *para_map, std::ostringstream &oss) {
1112 if (sub_graphs == nullptr || graph == nullptr) {
1113 return;
1114 }
1115 int format_level = GetDumpFormatLevel();
1116 for (const auto &sg : *sub_graphs) {
1117 MS_EXCEPTION_IF_NULL(sg.first);
1118 if (*(sg.first->indirect())) {
1119 oss << "indirect: " << *(sg.first->indirect()) << "\n";
1120 }
1121 if (format_level > kBasicLevel) {
1122 oss << "subgraph attr:" << std::endl;
1123 for (const auto &attr : sg.first->attrs()) {
1124 oss << attr.first << ": ";
1125 if (attr.second->isa<BoolImm>()) {
1126 oss << GetValue<bool>(attr.second);
1127 } else if (attr.second->isa<StringImm>()) {
1128 oss << (GetValue<std::string>(attr.second));
1129 }
1130 oss << std::endl;
1131 }
1132 if (sg.first->symbol_engine() != nullptr) {
1133 oss << "subgraph symbol engine: " << sg.first->symbol_engine()->ToString() << " : "
1134 << sg.first->symbol_engine().get() << std::endl;
1135 }
1136 oss << "subgraph instance: " << sg.first->ToString() << " : " << sg.first.get() << std::endl;
1137
1138 // Dump side effect info.
1139 auto effect_info = sg.first->GetEffectInfo();
1140 if (effect_info.HasEffect()) {
1141 oss << "# " << effect_info.ToString() << '\n';
1142 }
1143 // Dump parameters info.
1144 if (sg.first != graph) {
1145 DumpParameters(sg.first, oss);
1146 }
1147 }
1148 if (trace::GetGlobalTraceLabelType() == trace::TraceLabelType::kWithUniqueId) {
1149 oss << trace::GetDebugInfoStr(sg.first->debug_info(), "# ", kSourceLineTipDiscard) << "#"
1150 << trace::Label(sg.first->debug_info()) << "\n";
1151 } else {
1152 oss << trace::GetDebugInfoStr(sg.first->debug_info(), "# ", kSourceLineTipDiscard) << "\n";
1153 }
1154 oss << "subgraph @" << sg.first->ToString();
1155 if (sg.first->manager() != nullptr && sg.first->parent() != nullptr) {
1156 oss << " parent: [subgraph @" << sg.first->parent()->ToString() << "]";
1157 }
1158 oss << "(";
1159 if (sg.first != graph) {
1160 std::vector<AnfNodePtr> parameters = sg.first->parameters();
1161 if (parameters.size() == 1) {
1162 MS_EXCEPTION_IF_NULL(parameters[0]);
1163 oss << "%para" << (*para_map)[parameters[0]] << "_" << parameters[0]->ToString();
1164 } else if (parameters.size() > 1) {
1165 for (size_t idx = 0; idx < parameters.size() - 1; idx++) {
1166 MS_EXCEPTION_IF_NULL(parameters[idx]);
1167 oss << "%para" << (*para_map)[parameters[idx]] << "_" << parameters[idx]->ToString();
1168 oss << ", ";
1169 }
1170 MS_EXCEPTION_IF_NULL(parameters[parameters.size() - 1]);
1171 oss << "%para" << (*para_map)[parameters[parameters.size() - 1]] << "_"
1172 << parameters[parameters.size() - 1]->ToString();
1173 }
1174 }
1175 oss << ") {" << std::endl;
1176 MS_EXCEPTION_IF_NULL(sg.second);
1177 oss << sg.second->buffer.str();
1178 oss << "}" << std::endl;
1179 OutputOrderList(sg.first, oss);
1180 DumpSymbolEngine(sg.first, oss, format_level);
1181 oss << std::endl;
1182 oss << std::endl;
1183 }
1184 }
1185
SetDumpConfigByString(const std::string & str,DumpConfig * dump_config)1186 void SetDumpConfigByString(const std::string &str, DumpConfig *dump_config) {
1187 MS_LOG(INFO) << "Set dump config:" << str;
1188 static mindspore::HashMap<std::string, enum LocDumpMode> dump_level_map = {
1189 {kDumpConfigLineLevel0, kOff}, {kDumpConfigLineLevel1, kTopStack}, {kDumpConfigLineLevel2, kWholeStack}};
1190 auto it = dump_level_map.find(str);
1191 if (it != dump_level_map.end()) {
1192 dump_config->dump_line_level = it->second;
1193 return;
1194 }
1195 if (str == kDumpConfigDisableBackend) {
1196 dump_config->disable_backend_dump = true;
1197 return;
1198 }
1199 if (str == kDumpConfigEnablePassIR) {
1200 dump_config->enable_dump_pass_ir = true;
1201 return;
1202 }
1203 }
1204
GetAllConfigStrings(const std::string & config_full_string)1205 std::shared_ptr<OrderedSet<std::string>> GetAllConfigStrings(const std::string &config_full_string) {
1206 size_t start_pos = 0;
1207 auto config_strings = std::make_shared<OrderedSet<std::string>>();
1208 // if '#' is the last char of str, the str is legal, so we use '<=' but not '<'.
1209 while (start_pos <= config_full_string.size()) {
1210 auto pos = config_full_string.find('#', start_pos);
1211 if (pos == std::string::npos) {
1212 pos = config_full_string.size();
1213 }
1214 auto substr = config_full_string.substr(start_pos, pos - start_pos);
1215 // Skip the '#'
1216 start_pos = pos + 1;
1217 if (substr.empty()) {
1218 continue;
1219 }
1220 (void)config_strings->insert(substr);
1221 }
1222 return config_strings;
1223 }
1224
ConfigsAreLegal(const std::shared_ptr<OrderedSet<std::string>> & config_strings)1225 bool ConfigsAreLegal(const std::shared_ptr<OrderedSet<std::string>> &config_strings) {
1226 // Value 'int' is used to mark config group id
1227 HashMap<std::string, int> config_white_list = {{kDumpConfigLineLevel0, 0},
1228 {kDumpConfigLineLevel1, 0},
1229 {kDumpConfigLineLevel2, 0},
1230 {kDumpConfigDisableBackend, 1},
1231 {kDumpConfigEnablePassIR, 2}};
1232 // Key 'int' is config group id, value is the config.
1233 HashMap<int, std::string> config_groups;
1234 for (const auto &config_string : *config_strings) {
1235 auto config_white_list_it = config_white_list.find(config_string);
1236 if (config_white_list_it == config_white_list.end()) {
1237 std::ostringstream buffer;
1238 buffer << "Support configs:\n"
1239 << "[0]: " << kDumpConfigLineLevel0 << "\n"
1240 << "[1]: " << kDumpConfigLineLevel1 << "\n"
1241 << "[2]: " << kDumpConfigLineLevel2 << "\n"
1242 << "[3]: " << kDumpConfigDisableBackend << "\n"
1243 << "[4]: " << kDumpConfigEnablePassIR;
1244 MS_LOG(WARNING) << "Illegal dump config:\n" << config_string << "\n" << buffer.str();
1245 return false;
1246 }
1247 auto group_id = config_white_list_it->second;
1248 // Check conflict configs.
1249 auto config_groups_it = config_groups.find(group_id);
1250 if (config_groups_it != config_groups.end()) {
1251 const auto &record_config = config_groups_it->second;
1252 MS_LOG(WARNING) << "Dump configs are conflict. Conflict configs: [" << record_config << "] and [" << config_string
1253 << "].\n"
1254 << "Please keep only one of them.";
1255 return false;
1256 }
1257 config_groups[group_id] = config_string;
1258 }
1259 return true;
1260 }
1261
GetDumpConfig()1262 DumpConfig GetDumpConfig() {
1263 static DumpConfig dump_config = DumpConfig();
1264 static bool parsed = false;
1265 if (parsed) {
1266 return dump_config;
1267 }
1268 parsed = true;
1269 // Start parse config.
1270 std::string str(common::GetCompileConfig("DUMP_IR_CONFIG"));
1271 auto constexpr max_string_len = 100;
1272 if (str.size() > max_string_len) {
1273 MS_LOG(WARNING) << "Dump ir config length exceed max length: " << max_string_len;
1274 return dump_config;
1275 }
1276 if (str.empty()) {
1277 return dump_config;
1278 }
1279 auto config_strings = GetAllConfigStrings(str);
1280 if (!ConfigsAreLegal(config_strings)) {
1281 return dump_config;
1282 }
1283 for (const auto &config : *config_strings) {
1284 SetDumpConfigByString(config, &dump_config);
1285 }
1286 return dump_config;
1287 }
1288
GetEnvDumpIrLineLevel(LocDumpMode * dump_location)1289 void GetEnvDumpIrLineLevel(LocDumpMode *dump_location) {
1290 const auto &config = GetDumpConfig();
1291 if (config.dump_line_level != kInValid) {
1292 *dump_location = config.dump_line_level;
1293 }
1294 }
1295
DumpNodeCounting(const OrderedMap<FuncGraphPtr,std::shared_ptr<SubGraphIRInfo>> * sub_graphs,std::ostringstream & oss,const std::vector<AnfNodePtr> & nodes)1296 void DumpNodeCounting(const OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> *sub_graphs,
1297 std::ostringstream &oss, const std::vector<AnfNodePtr> &nodes) {
1298 oss << "Node counting information:" << std::endl;
1299 oss << "Total number of nodes: " << nodes.size() << std::endl;
1300 auto total_cnode =
1301 std::accumulate((*sub_graphs).cbegin(), (*sub_graphs).cend(), 0,
1302 [](const int32_t previous, const std::pair<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> &pair) {
1303 return previous + pair.second->cnode_num;
1304 });
1305 oss << "Total number of cnodes: " << total_cnode << std::endl;
1306 oss << std::endl;
1307 }
1308
SaveIRFile(const std::string & filename,const std::string & str,const std::string & target_file)1309 void SaveIRFile(const std::string &filename, const std::string &str, const std::string &target_file) {
1310 std::string path;
1311 if (!target_file.empty()) {
1312 path = target_file;
1313 } else {
1314 path = GetSaveGraphsPathName(filename);
1315 }
1316 auto realpath = Common::CreatePrefixPath(path);
1317 if (!realpath.has_value()) {
1318 MS_LOG(ERROR) << "Get real path failed, path=" << path;
1319 return;
1320 }
1321
1322 ChangeFileMode(realpath.value(), S_IWUSR);
1323 std::ofstream fout(realpath.value());
1324 if (!fout.is_open()) {
1325 MS_LOG(ERROR) << "Open dump file '" << realpath.value() << "' failed!" << ErrnoToString(errno);
1326 return;
1327 }
1328
1329 // Output all content.
1330 fout << str;
1331 fout.close();
1332 // Set file mode to read only by user
1333 ChangeFileMode(realpath.value(), S_IRUSR);
1334 }
1335
1336 #ifdef ENABLE_DUMP_IR
ToJson(const CNodePtr & para_node,const int64_t global_rank_id,std::unordered_map<std::string,std::vector<uint32_t>> group_map)1337 nlohmann::ordered_json ToJson(const CNodePtr ¶_node, const int64_t global_rank_id,
1338 std::unordered_map<std::string, std::vector<uint32_t>> group_map) {
1339 nlohmann::ordered_json args;
1340 MS_EXCEPTION_IF_NULL(para_node);
1341 auto abs = para_node->abstract();
1342 MS_EXCEPTION_IF_NULL(abs);
1343 auto prim = GetCNodePrimitive(para_node);
1344 MS_EXCEPTION_IF_NULL(prim);
1345 args["op_name"] = para_node->UniqueName();
1346 args["op_type"] = prim->name();
1347 args["shape"] = abs->BuildShape()->ToString();
1348 args["data_type"] = abs->BuildType()->ToString();
1349 args["global_rank_id"] = std::to_string(global_rank_id);
1350 std::string group_name = "";
1351 std::string group = "group";
1352 if (prim->HasAttr(group)) {
1353 group_name = GetValue<std::string>(prim->GetAttr(group));
1354 }
1355 args["comm_group_name"] = group_name;
1356 if (prim->HasAttr(kAttrGroupRankIds)) {
1357 auto value_ptr = prim->GetAttr(kAttrGroupRankIds);
1358 args["comm_group_rank_ids"] = value_ptr->ToString();
1359 if (group_map.find(group_name) != group_map.end()) {
1360 std::ostringstream oss;
1361 oss << "(";
1362 const std::vector<uint32_t> group_ranks = group_map[group_name];
1363 (void)std::copy(group_ranks.begin(), group_ranks.end() - 1, std::ostream_iterator<int>(oss, ","));
1364 oss << group_ranks.back() << ")";
1365 args["comm_group_rank_ids"] = oss.str();
1366 }
1367 }
1368 if (prim->HasAttr(kAttrSrcRank) && prim->HasAttr(kAttrSrTag)) {
1369 args["src_rank"] = std::to_string(GetValue<int64_t>(prim->GetAttr(kAttrSrcRank)));
1370 args["sr_tag"] = std::to_string(GetValue<int64_t>(prim->GetAttr(kAttrSrTag)));
1371 }
1372 if (prim->HasAttr(kAttrDestRank) && prim->HasAttr(kAttrSrTag)) {
1373 args["dest_rank"] = std::to_string(GetValue<int64_t>(prim->GetAttr(kAttrDestRank)));
1374 args["sr_tag"] = std::to_string(GetValue<int64_t>(prim->GetAttr(kAttrSrTag)));
1375 }
1376 return args;
1377 }
1378
DumpParallelInfo(const FuncGraphPtr & graph,size_t * op_id,nlohmann::ordered_json * args,const int64_t global_rank_id,const std::unordered_map<std::string,std::vector<uint32_t>> & group_map)1379 void DumpParallelInfo(const FuncGraphPtr &graph, size_t *op_id, nlohmann::ordered_json *args,
1380 const int64_t global_rank_id,
1381 const std::unordered_map<std::string, std::vector<uint32_t>> &group_map) {
1382 MS_EXCEPTION_IF_NULL(graph);
1383 std::list<CNodePtr> graph_orders = graph->GetOrderedCnodes();
1384 for (auto &node : graph_orders) {
1385 MS_EXCEPTION_IF_NULL(node);
1386 if (IsValueNode<FuncGraph>(node->input(0))) {
1387 FuncGraphPtr sub_graph = node->input(0)->cast<ValueNodePtr>()->value()->cast<FuncGraphPtr>();
1388 DumpParallelInfo(sub_graph, op_id, args, global_rank_id, group_map);
1389 } else if (common::AnfAlgo::IsCommunicationOp(node)) {
1390 (*args)[std::to_string(*op_id)] = ToJson(node, global_rank_id, group_map);
1391 *op_id = *op_id + 1;
1392 } else if (node->input(0)->isa<CNode>() && node->input(0)->abstract() != nullptr) {
1393 auto abs = node->input(0)->abstract();
1394 if (abs->isa<abstract::FuncGraphAbstractClosure>()) {
1395 const auto &abstract_func_graph = abs->cast<abstract::FuncGraphAbstractClosurePtr>();
1396 MS_EXCEPTION_IF_NULL(abstract_func_graph->func_graph());
1397 DumpParallelInfo(abstract_func_graph->func_graph(), op_id, args, global_rank_id, group_map);
1398 } else if (abs->isa<abstract::PartialAbstractClosure>()) {
1399 const auto &abstract_partial_func = abs->cast<abstract::PartialAbstractClosurePtr>();
1400 const auto &abstract_fn = abstract_partial_func->fn();
1401 if (abstract_fn->isa<abstract::FuncGraphAbstractClosure>()) {
1402 const auto &abstract_func_graph = abstract_fn->cast<abstract::FuncGraphAbstractClosurePtr>();
1403 MS_EXCEPTION_IF_NULL(abstract_func_graph->func_graph());
1404 DumpParallelInfo(abstract_func_graph->func_graph(), op_id, args, global_rank_id, group_map);
1405 }
1406 }
1407 }
1408 }
1409 }
1410
DumpParallelJson(const std::string & filename,const FuncGraphPtr & graph,const int64_t global_rank_id,const std::unordered_map<std::string,std::vector<uint32_t>> & group_map)1411 void DumpParallelJson(const std::string &filename, const FuncGraphPtr &graph, const int64_t global_rank_id,
1412 const std::unordered_map<std::string, std::vector<uint32_t>> &group_map) {
1413 if (graph == nullptr) {
1414 return;
1415 }
1416 std::string save_path = "";
1417 if (!common::GetEnv("MA_LOG_DIR").empty()) {
1418 save_path = common::GetEnv("MA_LOG_DIR");
1419 }
1420 auto path = GetSaveGraphsPathName(filename, save_path);
1421 auto realpath = Common::CreatePrefixPath(path);
1422 if (!realpath.has_value()) {
1423 MS_LOG(ERROR) << "Get real path failed, path is " << path;
1424 return;
1425 }
1426
1427 ChangeFileMode(realpath.value(), S_IWUSR);
1428 std::ofstream fout(realpath.value());
1429 if (!fout.is_open()) {
1430 MS_LOG(ERROR) << "Open dump file '" << realpath.value() << "' failed!" << ErrnoToString(errno);
1431 return;
1432 }
1433 size_t op_id = 0;
1434 nlohmann::ordered_json args;
1435 args["hccl_algo"] = common::GetEnv("HCCL_ALGO");
1436 DumpParallelInfo(graph, &op_id, &args, global_rank_id, group_map);
1437 constexpr size_t json_dump_mode = 2;
1438 fout << args.dump(json_dump_mode);
1439
1440 fout.close();
1441 // Set file mode to read only by user
1442 ChangeFileMode(realpath.value(), S_IRUSR);
1443 }
1444
DumpIRHead(const FuncGraphPtr & top_func,std::ostringstream & ofs)1445 void DumpIRHead(const FuncGraphPtr &top_func, std::ostringstream &ofs) {
1446 MS_EXCEPTION_IF_NULL(top_func);
1447 auto sub_graphs = top_func->func_graphs_used_total();
1448 DumpGlobalInfoEntry(top_func, ofs, sub_graphs.size());
1449 OrderedMap<AnfNodePtr, int32_t> para_map;
1450 (void)DumpParams(top_func, ofs, ¶_map);
1451 ofs << std::endl;
1452 }
1453
DumpIR(const std::string & filename,const FuncGraphPtr & graph,bool dump_full_name,LocDumpMode dump_location,const std::string & target_file)1454 void DumpIR(const std::string &filename, const FuncGraphPtr &graph, bool dump_full_name, LocDumpMode dump_location,
1455 const std::string &target_file) {
1456 if (graph == nullptr) {
1457 return;
1458 }
1459 // Id auto increment in AddId(), and CheckIfPrintIrPass() would check id, so we call AddId() in advance.
1460 auto filename_with_id = Common::AddId(filename, ".ir");
1461 bool need_dump = Common::CheckIfPrintIrPass(filename);
1462 if (!need_dump) {
1463 return;
1464 }
1465
1466 std::ostringstream out_oss;
1467 DumpIR(out_oss, graph, dump_full_name, dump_location, false);
1468 SaveIRFile(filename_with_id, out_oss.str(), target_file);
1469 }
1470
DumpIR(std::ostringstream & out_oss,const FuncGraphPtr & graph,bool dump_full_name,int dump_location,bool avoid_circle)1471 void DumpIR(std::ostringstream &out_oss, const FuncGraphPtr &graph, bool dump_full_name, int dump_location,
1472 bool avoid_circle) {
1473 if (graph == nullptr) {
1474 return;
1475 }
1476 auto nodes =
1477 TopoSort(graph->get_return(), avoid_circle ? SuccIncoming : SuccDeeperSimple, AlwaysInclude, avoid_circle);
1478
1479 OrderedMap<AnfNodePtr, int32_t> para_map;
1480 std::ostringstream param_oss;
1481 int32_t total_para = DumpParams(graph, param_oss, ¶_map);
1482 OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> sub_graphs;
1483 // Check If update dump_location option by compile config
1484 GetEnvDumpIrLineLevel(reinterpret_cast<LocDumpMode *>(&dump_location));
1485 // Output ir in each sub graph
1486 DumpIRInSubgraph(nodes, ¶_map, &sub_graphs, total_para, dump_full_name, static_cast<LocDumpMode>(dump_location));
1487
1488 if (!avoid_circle) {
1489 // Output global info
1490 DumpGlobalInfoEntry(graph, out_oss, sub_graphs.size());
1491 // Output parameters info
1492 out_oss << param_oss.str();
1493 }
1494
1495 // Add counting information for nodes
1496 out_oss << std::endl;
1497 DumpNodeCounting(&sub_graphs, out_oss, nodes);
1498
1499 // Output each sub graph
1500 DumpSubgraph(&sub_graphs, graph, ¶_map, out_oss);
1501 }
1502
DumpIRForRDR(const std::string & filename,const FuncGraphPtr & graph,bool dump_full_name,LocDumpMode dump_location)1503 void DumpIRForRDR(const std::string &filename, const FuncGraphPtr &graph, bool dump_full_name,
1504 LocDumpMode dump_location) {
1505 if (graph == nullptr) {
1506 return;
1507 }
1508 auto path = Common::AddId(filename, ".ir");
1509 bool need_dump = Common::CheckIfPrintIrPass(filename);
1510 if (!need_dump) {
1511 return;
1512 }
1513 auto realpath = Common::CreatePrefixPath(path);
1514 if (!realpath.has_value()) {
1515 MS_LOG(ERROR) << "Get real path failed. path=" << path;
1516 return;
1517 }
1518
1519 ChangeFileMode(realpath.value(), S_IWUSR);
1520 std::ofstream fout(realpath.value());
1521 std::ostringstream buffer;
1522 if (!fout.is_open()) {
1523 MS_LOG(ERROR) << "Open dump file '" << realpath.value() << "' failed!" << ErrnoToString(errno);
1524 return;
1525 }
1526
1527 auto nodes = TopoSort(graph->get_return(), SuccDeeperSimple, AlwaysInclude);
1528 OrderedMap<AnfNodePtr, int32_t> para_map;
1529 int32_t total_para = DumpParams(graph, buffer, ¶_map);
1530 OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> sub_graphs;
1531 GetEnvDumpIrLineLevel(&dump_location);
1532 // Dump ir in each sub graph
1533 DumpIRInSubgraph(nodes, ¶_map, &sub_graphs, total_para, dump_full_name, dump_location);
1534 // Add counting information for nodes
1535 buffer << std::endl;
1536 DumpNodeCounting(&sub_graphs, buffer, nodes);
1537 // Dump global info
1538 DumpGlobalInfoEntry(graph, buffer, sub_graphs.size());
1539 // Output global info
1540 fout << buffer.str() << std::endl;
1541 buffer.str(std::string());
1542 buffer.clear();
1543
1544 // Output each sub graph
1545 DumpSubgraph(&sub_graphs, graph, ¶_map, buffer);
1546 fout << buffer.str();
1547
1548 fout.close();
1549 // Set file mode to read only by user
1550 ChangeFileMode(realpath.value(), S_IRUSR);
1551 }
1552 #else
DumpIR(const std::string &,const FuncGraphPtr &,bool,LocDumpMode,const std::string &,bool)1553 void DumpIR(const std::string &, const FuncGraphPtr &, bool, LocDumpMode, const std::string &, bool) {
1554 static bool already_printed = false;
1555 if (already_printed) {
1556 return;
1557 }
1558 already_printed = true;
1559 MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
1560 << "please recompile source to enable it. See help of building script.";
1561 }
1562
DumpIR(std::ostringstream &,const FuncGraphPtr &,bool,int,bool)1563 void DumpIR(std::ostringstream &, const FuncGraphPtr &, bool, int, bool) {
1564 static bool already_printed = false;
1565 if (already_printed) {
1566 return;
1567 }
1568 already_printed = true;
1569 MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
1570 << "please recompile source to enable it. See help of building script.";
1571 }
1572
DumpIRForRDR(const std::string &,const FuncGraphPtr &,bool,LocDumpMode)1573 void DumpIRForRDR(const std::string &, const FuncGraphPtr &, bool, LocDumpMode) {
1574 static bool already_printed = false;
1575 if (already_printed) {
1576 return;
1577 }
1578 already_printed = true;
1579 MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
1580 << "please recompile source to enable it. See help of building script.";
1581 }
1582 #endif
1583
OuputIrStyleCNodes(const FuncGraphPtr & func_graph,const std::vector<AnfNodePtr> & nodes,int32_t total_para,std::ostringstream & oss,OrderedMap<AnfNodePtr,int32_t> * para_map)1584 void AnfExporter::OuputIrStyleCNodes(const FuncGraphPtr &func_graph, const std::vector<AnfNodePtr> &nodes,
1585 int32_t total_para, std::ostringstream &oss,
1586 OrderedMap<AnfNodePtr, int32_t> *para_map) {
1587 MS_EXCEPTION_IF_NULL(func_graph);
1588 auto ¶meters = func_graph->parameters();
1589 std::shared_ptr<SubGraphIRInfo> gsub = std::make_shared<SubGraphIRInfo>();
1590 ParamIndexMap param_map;
1591 exported_[func_graph] = param_map;
1592 gsub->local_var = 0;
1593 gsub->format_level = GetDumpFormatLevel();
1594 for (size_t idx = 0; idx < parameters.size(); idx++) {
1595 MS_EXCEPTION_IF_NULL(parameters[idx]);
1596 if ((*para_map).count(parameters[idx]) == 0) {
1597 (*para_map)[parameters[idx]] = total_para++;
1598 }
1599 }
1600 for (const AnfNodePtr &node : nodes) {
1601 MS_EXCEPTION_IF_NULL(node);
1602 if (!node->isa<CNode>()) {
1603 continue;
1604 }
1605 auto cnode = node->cast<CNodePtr>();
1606 auto &inputs = cnode->inputs();
1607 for (size_t i = 0; i < inputs.size(); ++i) {
1608 if (IsValueNode<FuncGraph>(inputs[i])) {
1609 FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(inputs[i]);
1610 if (!func_graph_set_.contains(fg) && exported_.find(fg) == exported_.end() && export_used_) {
1611 func_graph_set_.add(fg);
1612 }
1613 }
1614 }
1615 DumpCNode(cnode, func_graph, *para_map, gsub);
1616 if (trace::GetGlobalTraceLabelType() == trace::TraceLabelType::kWithUniqueId) {
1617 gsub->buffer << trace::GetDebugInfoStr(cnode->debug_info(), " # ", kSourceLineTipDiscard) << "#"
1618 << trace::Label(cnode->debug_info()) << "\n";
1619 } else {
1620 std::string dgi = trace::GetDebugInfoStr(cnode->debug_info(), " # ", kSourceLineTipDiscard);
1621 if (dgi != "") {
1622 gsub->buffer << trace::GetDebugInfoStr(cnode->debug_info(), " # ", kSourceLineTipDiscard) << "\n";
1623 }
1624 }
1625 }
1626 if (!is_top_graph_) {
1627 if (parameters.size() == 1) {
1628 MS_EXCEPTION_IF_NULL(parameters[0]);
1629 oss << "%para" << (*para_map)[parameters[0]] << "_" << parameters[0]->ToString();
1630 } else if (parameters.size() > 1) {
1631 for (size_t idx = 0; idx < parameters.size() - 1; idx++) {
1632 MS_EXCEPTION_IF_NULL(parameters[idx]);
1633 oss << "%para" << (*para_map)[parameters[idx]] << "_" << parameters[idx]->ToString();
1634 oss << ", ";
1635 }
1636 MS_EXCEPTION_IF_NULL(parameters[parameters.size() - 1]);
1637 oss << "%para" << (*para_map)[parameters[parameters.size() - 1]] << "_"
1638 << parameters[parameters.size() - 1]->ToString();
1639 }
1640 } else {
1641 is_top_graph_ = false;
1642 }
1643 oss << ") {\n";
1644 oss << gsub->buffer.str();
1645 }
1646
ExportOneFuncGraph(const FuncGraphPtr & func_graph,const TaggedNodeMap & tagged_cnodes_map,std::ostringstream & oss,int32_t total_para,OrderedMap<AnfNodePtr,int32_t> * para_map)1647 void AnfExporter::ExportOneFuncGraph(const FuncGraphPtr &func_graph, const TaggedNodeMap &tagged_cnodes_map,
1648 std::ostringstream &oss, int32_t total_para,
1649 OrderedMap<AnfNodePtr, int32_t> *para_map) {
1650 if (func_graph == nullptr) {
1651 return;
1652 }
1653
1654 std::vector<AnfNodePtr> nodes = TopoSort(func_graph->get_return(), SuccIncoming, AlwaysInclude);
1655
1656 if (*(func_graph->indirect())) {
1657 oss << "indirect: " << *(func_graph->indirect()) << "\n";
1658 }
1659 oss << "subgraph attr:" << std::endl;
1660 for (const auto &attr : func_graph->attrs()) {
1661 oss << attr.first << ": ";
1662 MS_EXCEPTION_IF_NULL(attr.second);
1663 if (attr.second->isa<BoolImm>()) {
1664 oss << GetValue<bool>(attr.second);
1665 } else if (attr.second->isa<StringImm>()) {
1666 oss << (GetValue<std::string>(attr.second));
1667 }
1668 oss << std::endl;
1669 }
1670 oss << "subgraph instance: " << func_graph->ToString() << " : " << func_graph.get() << std::endl;
1671 // Dump side effect info.
1672 auto effect_info = func_graph->GetEffectInfo();
1673 if (effect_info.HasEffect()) {
1674 oss << "# " << effect_info.ToString() << '\n';
1675 }
1676 // Dump parameters info.
1677 DumpParameters(func_graph, oss);
1678 if (trace::GetGlobalTraceLabelType() == trace::TraceLabelType::kWithUniqueId) {
1679 oss << trace::GetDebugInfoStr(func_graph->debug_info(), "# ", kSourceLineTipDiscard) << "#"
1680 << trace::Label(func_graph->debug_info()) << "\n";
1681 } else {
1682 oss << trace::GetDebugInfoStr(func_graph->debug_info(), "# ", kSourceLineTipDiscard) << "\n";
1683 }
1684 oss << "subgraph @" << func_graph->ToString();
1685 if (func_graph->parent() != nullptr) {
1686 oss << " parent: [subgraph @" << func_graph->parent()->ToString() << "]";
1687 }
1688 oss << "(";
1689 OuputIrStyleCNodes(func_graph, nodes, total_para, oss, para_map);
1690
1691 oss << "}\n";
1692
1693 OutputOrderList(func_graph, oss);
1694 }
1695
ExportGlobalInfoEntry(const FuncGraphPtr & graph,std::ostringstream & buffer,int graph_size)1696 void ExportGlobalInfoEntry(const FuncGraphPtr &graph, std::ostringstream &buffer, int graph_size) {
1697 if (graph == nullptr) {
1698 return;
1699 }
1700
1701 buffer << "# IR entry: @" << graph->ToString() << std::endl;
1702 buffer << "# Total subgraph: " << graph_size;
1703 buffer << std::endl;
1704 buffer << std::endl;
1705 buffer << "# attrs: " << std::endl;
1706 for (const auto &attr : graph->attrs()) {
1707 buffer << attr.first << ": ";
1708 MS_EXCEPTION_IF_NULL(attr.second);
1709 if (attr.second->isa<BoolImm>()) {
1710 buffer << GetValue<bool>(attr.second);
1711 } else if (attr.second->isa<StringImm>()) {
1712 buffer << (GetValue<std::string>(attr.second));
1713 }
1714 buffer << std::endl;
1715 }
1716 }
1717
ExportFuncGraph(const std::string & filename,const FuncGraphPtr & func_graph)1718 void AnfExporter::ExportFuncGraph(const std::string &filename, const FuncGraphPtr &func_graph) {
1719 if (func_graph == nullptr) {
1720 return;
1721 }
1722
1723 std::ofstream ofs(filename);
1724 if (!ofs.is_open()) {
1725 MS_LOG(ERROR) << "Open file '" << filename << "' failed!" << ErrnoToString(errno);
1726 return;
1727 }
1728
1729 param_index_ = 1;
1730 int graph_size = 0;
1731 std::ostringstream oss;
1732 std::ostringstream paramoss;
1733 TaggedNodeMap tagged_cnodes_map;
1734 OrderedMap<AnfNodePtr, int32_t> para_map;
1735 int32_t total_para = DumpParams(func_graph, paramoss, ¶_map);
1736 func_graph_set_.add(func_graph);
1737 is_top_graph_ = true;
1738 while (!func_graph_set_.empty()) {
1739 FuncGraphPtr fg = *func_graph_set_.cbegin();
1740 ExportOneFuncGraph(fg, tagged_cnodes_map, oss, total_para, ¶_map);
1741 oss << "\n\n";
1742 (void)func_graph_set_.erase(fg);
1743 graph_size++;
1744 }
1745 std::ostringstream buffer;
1746 ExportGlobalInfoEntry(func_graph, buffer, graph_size);
1747 ofs << buffer.str() << paramoss.str() << "\n" << oss.str();
1748 ofs.close();
1749 }
1750
1751 #ifdef ENABLE_DUMP_IR
ExportIR(const std::string & filename,const FuncGraphPtr & func_graph)1752 void ExportIR(const std::string &filename, const FuncGraphPtr &func_graph) {
1753 bool need_dump = Common::CheckIfPrintIrPass(filename);
1754 if (func_graph == nullptr) {
1755 return;
1756 }
1757 if (!need_dump) {
1758 return;
1759 }
1760
1761 auto filepath = GetSaveGraphsPathName(Common::AddId(filename, ".ir"));
1762 auto real_filepath = Common::CreatePrefixPath(filepath);
1763 if (!real_filepath.has_value()) {
1764 MS_LOG(ERROR) << "The export ir path: " << filepath << " is not illegal.";
1765 return;
1766 }
1767 ChangeFileMode(real_filepath.value(), S_IWUSR);
1768 AnfExporter exporter;
1769 exporter.ExportFuncGraph(real_filepath.value(), func_graph);
1770 // Set file mode to read only by user
1771 ChangeFileMode(real_filepath.value(), S_IRUSR);
1772 }
1773 #else
ExportIR(const std::string &,const FuncGraphPtr &)1774 void ExportIR(const std::string &, const FuncGraphPtr &) {
1775 static bool already_printed = false;
1776 if (already_printed) {
1777 return;
1778 }
1779 already_printed = true;
1780 MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
1781 << "please recompile to enable it. See help of building script.";
1782 }
1783 #endif
1784
1785 #ifdef ENABLE_DUMP_IR
1786 // Register DumpIR Privider.
1787 struct DumpIRPrividerRegister {
DumpIRPrividerRegistermindspore::DumpIRPrividerRegister1788 DumpIRPrividerRegister() noexcept {
1789 DumpIRPrividerFunction func = &DumpIR;
1790 SetDumpIRPrivider(func);
1791 }
1792 ~DumpIRPrividerRegister() = default;
1793 } dump_ir_provider_register;
1794
1795 // Register DumpIR Storage.
1796 struct DumpIRStorageRegister {
DumpIRStorageRegistermindspore::DumpIRStorageRegister1797 DumpIRStorageRegister() noexcept {
1798 DumpIRStorageFunction func = &SaveIRFile;
1799 SetDumpIRStorage(func);
1800 }
1801 ~DumpIRStorageRegister() = default;
1802 } dump_ir_storage_register;
1803 #endif
1804 } // namespace mindspore
1805