Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / src / program_dump_graph.cpp
1 /*
2 // Copyright (c) 2016-2018 Intel Corporation
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
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
18
19 #include "program_dump_graph.h"
20 #include "to_string_utils.h"
21 #include "data_inst.h"
22 #include "condition_inst.h"
23
24 #include "gpu/ocl_toolkit.h"
25
26 #include "to_string_utils.h"
27
28 #include <algorithm>
29 #include <vector>
30
31 namespace cldnn
32 {
33     namespace
34     {
35         static const std::vector<std::string> colors =
36         {
37             "chartreuse",
38             "aquamarine",
39             "gold",
40             "green",
41             "blue",
42             "cyan",
43             "azure",
44             "beige",
45             "bisque",
46             "blanchedalmond",
47             "blueviolet",
48             "brown",
49             "burlywood",
50             "cadetblue",
51             "chocolate",
52             "coral",
53             "cornflowerblue",
54             "cornsilk",
55             "crimson",
56             "aliceblue",
57             "antiquewhite",
58             "deeppink",
59             "deepskyblue",
60             "dimgray",
61             "dodgerblue",
62             "firebrick",
63             "floralwhite",
64             "forestgreen",
65             "gainsboro",
66             "ghostwhite",
67             "goldenrod",
68             "greenyellow",
69             "honeydew",
70             "hotpink",
71             "indianred",
72             "indigo",
73             "ivory",
74             "khaki",
75             "lavender",
76             "lavenderblush",
77             "lawngreen",
78             "lemonchiffon",
79             "lightblue",
80             "lightcoral",
81             "lightcyan",
82             "lightgoldenrodyellow",
83             "lightgray",
84             "lightgrey",
85             "lightpink",
86             "lightsalmon",
87             "lightseagreen",
88             "lightskyblue",
89             "lightsteelblue",
90             "lightyellow",
91             "lime",
92             "limegreen",
93             "linen",
94             "magenta",
95             "maroon",
96             "mediumaquamarine",
97             "mediumblue",
98             "mediumorchid",
99             "mediumpurple",
100             "mediumseagreen",
101             "mediumslateblue",
102             "mediumspringgreen",
103             "mediumturquoise",
104             "mediumvioletred",
105             "midnightblue",
106             "mintcream",
107             "mistyrose",
108             "moccasin",
109             "navajowhite",
110             "navy",
111             "oldlace",
112             "olive",
113             "olivedrab",
114             "orange",
115             "orangered",
116             "orchid",
117             "palegoldenrod",
118             "palegreen",
119             "paleturquoise",
120             "palevioletred",
121             "papayawhip",
122             "peachpuff",
123             "peru",
124             "pink",
125             "plum",
126             "powderblue",
127             "purple",
128             "red",
129             "rosybrown",
130             "royalblue",
131             "saddlebrown",
132             "salmon",
133             "sandybrown",
134             "seagreen",
135             "seashell",
136             "sienna",
137             "silver",
138             "skyblue",
139             "slateblue",
140             "snow",
141             "springgreen",
142             "steelblue",
143             "tan",
144             "teal",
145             "thistle",
146             "tomato",
147             "turquoise",
148             "violet",
149             "wheat",
150             "white",
151             "yellow",
152             "yellowgreen",
153         };
154
155
156     void close_stream(std::ofstream& graph)
157     {
158         graph.close();
159     }
160
161     std::string get_node_id(const program_node* ptr)
162     {
163         return "node_" + std::to_string(reinterpret_cast<uintptr_t>(ptr));
164     }
165
166     void dump_full_node(std::ofstream& out, const program_node* node)
167     {
168         out << node->type()->to_string(*node);
169     }
170     }
171
172     std::string get_dir_path(build_options opts)
173     {
174         auto path = opts.get<build_option_type::graph_dumps_dir>()->directory_path;
175         if (path.empty())
176         {
177             return{};
178         }
179
180         if (path.back() != '/' && path.back() != '\\')
181         {
182             path += "/";
183         }
184         return path;
185     }
186
187     /// Returns given name for serialization process.
188     std::string get_serialization_network_name(build_options opts)
189     {
190         return opts.get<build_option_type::serialize_network>()->serialization_network_name;
191     }
192
193     std::string get_load_program_name(build_options opts)
194     {
195         return opts.get<build_option_type::load_program>()->load_program_name;
196     }
197
198     void dump_graph_init(std::ofstream& graph, const program_impl& program, std::function<bool(program_node const&)> const& filter)
199     {
200         const auto extr_oformat = [](program_node* ptr)
201         {
202             std::string out = fmt_to_str(ptr->get_output_layout().format);
203
204             if (!ptr->is_valid_output_layout())
205                 out += " (invalid)";
206
207             return out;
208         };
209
210         const auto dump_mem_info = [](program_node* ptr)
211         {
212             std::string out = "size_info: ";
213             auto out_layout = ptr->get_output_layout();
214             auto tensor_str = out_layout.size.to_string();
215             auto padding = out_layout.data_padding;
216             out += tensor_str;
217             if (!padding)
218             {
219                 out += " (nonpadded)";
220             }
221             else
222             {
223                 out += "\nl: " + padding.lower_size().to_string()
224                     + "\nu: " + padding.upper_size().to_string();
225             }
226             
227             return out;
228         };
229
230         graph << "digraph cldnn_program {\n";
231         for (auto& node : program.get_processing_order())
232         {
233             if (filter && !filter(*node))
234             {
235                 continue;
236             }
237             #ifdef __clang__
238                 #pragma clang diagnostic push
239                 #pragma clang diagnostic ignored "-Wpotentially-evaluated-expression"
240             #endif
241             auto& node_type = typeid(*node);
242             std::string node_type_name = get_extr_type(node_type.name());
243             graph << "    " << get_node_id(node) << "[label=\"" << node->id() << ":\n" << node_type_name << "\n out format: " + extr_oformat(node)
244                 << "\n out data_type: " + dt_to_str(node->get_output_layout().data_type)
245                 << "\\nprocessing number: " << program.get_processing_order().get_processing_number(node) << "\\n color:" << (node->is_reusing_memory() ? std::to_string(node->get_reused_memory_color()) : "none")
246                 << (node->can_be_optimized() ? "\\n optimized out" : "");
247
248             if (node_type_name != "struct cldnn::data" && node_type_name != "struct cldnn::input_layout" && !node->can_be_optimized())
249             {
250                 graph << "\\n Selected kernel: " << (node->get_selected_impl() == nullptr ? "none" : node->get_selected_impl().get()->get_kernel_name()
251                     + "\n" + dump_mem_info(node));
252             }
253             graph << "\"";
254             #ifdef __clang__
255                 #pragma clang diagnostic pop
256             #endif
257
258             if (node->is_type<condition>())
259             {
260                 graph << ", shape=diamond";
261             }
262             if (node->is_type<data>() || node->is_constant())
263             {
264                 graph << ", shape=box";
265             }
266             if (node->is_type<internal_primitive>())
267             {
268                 graph << ", color=blue";
269             }
270
271             if (node->is_reusing_memory())
272             {
273                 graph << ", fillcolor=\"" << colors[node->get_reused_memory_color() % colors.size()] << "\" ";
274                 graph << " style=filled ";
275             }
276             graph << "];\n";
277
278             for (auto& user : node->get_users())
279             {
280                 if (filter && !filter(*user))
281                 {
282                     continue;
283                 }
284                 bool doubled = true;
285                 if (std::find(user->get_dependencies().begin(), user->get_dependencies().end(), node) == user->get_dependencies().end())
286                     doubled = false;
287                 graph << "    " << get_node_id(node) << " -> " << get_node_id(user);
288
289                 bool data_flow = node->is_in_data_flow() && user->is_in_data_flow();
290                 if (data_flow)
291                 {
292                     if (doubled)
293                        graph << " [color=red]";
294                     else
295                        graph << " [color=red, style=dashed, label=\"usr\"]";
296                 }
297                 else
298                 {
299                     if (!doubled)
300                         graph << " [style=dashed, label=\"usr\"]";
301                 }
302                 graph << ";\n";
303             }
304
305             for (auto& dep : node->get_dependencies())
306             {
307                 if (filter && !filter(*dep))
308                 {
309                     continue;
310                 }
311
312                 if (std::find(dep->get_users().begin(), dep->get_users().end(), node) != dep->get_users().end())
313                 {
314                     continue;
315                 }
316
317                 graph << "   " << get_node_id(node) << " -> " << get_node_id(dep) << " [style=dashed, label=\"dep\", constraint=false];\n";
318             }
319         }
320         graph << "}\n";
321         close_stream(graph);
322     }
323
324
325     void dump_graph_processing_order(std::ofstream& graph, const program_impl& program)
326     { 
327         for (auto node : program.get_processing_order())
328             graph << reinterpret_cast<uintptr_t>(node) << " (" << node->id() << ")\n";
329         graph << '\n';
330         close_stream(graph);
331     }
332
333     void dump_graph_optimized(std::ofstream& graph, const program_impl& program)
334     {
335         for (auto& prim_id : program.get_optimized_out())
336             graph << prim_id << "\n";
337         graph << '\n';
338         close_stream(graph);
339     }
340
341     void dump_graph_info(std::ofstream& graph, const program_impl& program, std::function<bool(program_node const&)> const& filter)
342     {
343         for (auto& node : program.get_processing_order())
344         {
345             if (filter && !filter(*node))
346                 continue;
347
348             dump_full_node(graph, node);
349             graph << std::endl << std::endl;
350         }
351         close_stream(graph);
352     }
353 }
354
355