2 // Copyright (c) 2016-2018 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
19 #include "program_dump_graph.h"
20 #include "to_string_utils.h"
21 #include "data_inst.h"
22 #include "condition_inst.h"
24 #include "gpu/ocl_toolkit.h"
26 #include "to_string_utils.h"
35 static const std::vector<std::string> colors =
82 "lightgoldenrodyellow",
156 void close_stream(std::ofstream& graph)
161 std::string get_node_id(const program_node* ptr)
163 return "node_" + std::to_string(reinterpret_cast<uintptr_t>(ptr));
166 void dump_full_node(std::ofstream& out, const program_node* node)
168 out << node->type()->to_string(*node);
172 std::string get_dir_path(build_options opts)
174 auto path = opts.get<build_option_type::graph_dumps_dir>()->directory_path;
180 if (path.back() != '/' && path.back() != '\\')
187 /// Returns given name for serialization process.
188 std::string get_serialization_network_name(build_options opts)
190 return opts.get<build_option_type::serialize_network>()->serialization_network_name;
193 std::string get_load_program_name(build_options opts)
195 return opts.get<build_option_type::load_program>()->load_program_name;
198 void dump_graph_init(std::ofstream& graph, const program_impl& program, std::function<bool(program_node const&)> const& filter)
200 const auto extr_oformat = [](program_node* ptr)
202 std::string out = fmt_to_str(ptr->get_output_layout().format);
204 if (!ptr->is_valid_output_layout())
210 const auto dump_mem_info = [](program_node* ptr)
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;
219 out += " (nonpadded)";
223 out += "\nl: " + padding.lower_size().to_string()
224 + "\nu: " + padding.upper_size().to_string();
230 graph << "digraph cldnn_program {\n";
231 for (auto& node : program.get_processing_order())
233 if (filter && !filter(*node))
238 #pragma clang diagnostic push
239 #pragma clang diagnostic ignored "-Wpotentially-evaluated-expression"
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" : "");
248 if (node_type_name != "struct cldnn::data" && node_type_name != "struct cldnn::input_layout" && !node->can_be_optimized())
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));
255 #pragma clang diagnostic pop
258 if (node->is_type<condition>())
260 graph << ", shape=diamond";
262 if (node->is_type<data>() || node->is_constant())
264 graph << ", shape=box";
266 if (node->is_type<internal_primitive>())
268 graph << ", color=blue";
271 if (node->is_reusing_memory())
273 graph << ", fillcolor=\"" << colors[node->get_reused_memory_color() % colors.size()] << "\" ";
274 graph << " style=filled ";
278 for (auto& user : node->get_users())
280 if (filter && !filter(*user))
285 if (std::find(user->get_dependencies().begin(), user->get_dependencies().end(), node) == user->get_dependencies().end())
287 graph << " " << get_node_id(node) << " -> " << get_node_id(user);
289 bool data_flow = node->is_in_data_flow() && user->is_in_data_flow();
293 graph << " [color=red]";
295 graph << " [color=red, style=dashed, label=\"usr\"]";
300 graph << " [style=dashed, label=\"usr\"]";
305 for (auto& dep : node->get_dependencies())
307 if (filter && !filter(*dep))
312 if (std::find(dep->get_users().begin(), dep->get_users().end(), node) != dep->get_users().end())
317 graph << " " << get_node_id(node) << " -> " << get_node_id(dep) << " [style=dashed, label=\"dep\", constraint=false];\n";
325 void dump_graph_processing_order(std::ofstream& graph, const program_impl& program)
327 for (auto node : program.get_processing_order())
328 graph << reinterpret_cast<uintptr_t>(node) << " (" << node->id() << ")\n";
333 void dump_graph_optimized(std::ofstream& graph, const program_impl& program)
335 for (auto& prim_id : program.get_optimized_out())
336 graph << prim_id << "\n";
341 void dump_graph_info(std::ofstream& graph, const program_impl& program, std::function<bool(program_node const&)> const& filter)
343 for (auto& node : program.get_processing_order())
345 if (filter && !filter(*node))
348 dump_full_node(graph, node);
349 graph << std::endl << std::endl;