Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / src / graph_optimizer / add_required_reorders.cpp
1 /*
2 // Copyright (c) 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 <algorithm>
20
21 #include "pass_manager.h"
22 #include "program_node.h"
23 #include "mutable_data_inst.h"
24 #include "concatenation_inst.h"
25 #include "scale_inst.h"
26 #include "tensor_type.h"
27
28 /*
29 This pass checks if data formats (layouts) of output/input in hidden layers match.
30 If not than required reorder is added to the network.
31 */
32
33 /*
34 Add a reorder in between node and usr with reorder_layout as layout
35 */
36 void add_required_reorders::add_reorder(program_impl& p, program_node* node, program_node* usr, layout reorder_layout)
37 {
38
39     auto new_reorder = std::make_shared<reorder>(node->id() + "_reorder_" + usr->id(),
40                                                  node->id(),
41                                                  reorder_layout);
42     auto& new_reorder_node = p.get_or_create(new_reorder);
43
44     //ToDo: add a method to program_impl class which adds an intermediate node given a node and its user
45     auto it = std::find(usr->get_dependencies().begin(), usr->get_dependencies().end(), node);
46     if (it == usr->get_dependencies().end())
47     {
48         throw error("Inconcistency in topology description: user of a node is not present among its dependecies.", CLDNN_ERROR);
49     }
50     auto idx = it - usr->get_dependencies().begin();
51     if (idx < 0 || (size_t)idx >= usr->get_dependencies().size())
52     {
53         throw error("Internal Error: container index out of range exception.", CLDNN_ERROR);
54     }
55     p.add_intermediate(new_reorder_node, *usr, idx);
56 }
57
58 void add_required_reorders::run(program_impl& p)
59 {
60     auto usr_itr = p.get_processing_order().begin();
61     while (usr_itr != p.get_processing_order().end())
62     {
63         auto& usr = *usr_itr++;
64         if (usr->get_dependencies().size() == 0)
65             continue;  // only nodes with dependencies
66         if (usr->is_type<internal_primitive>() || usr->is_type<data>())
67             continue;
68         if (usr->type()->does_an_implementation_exist(p.get_engine(), *usr))
69             continue;
70
71         /*
72             First check if there are non data flow dependencies for the primitive
73             if so then choose the same output format as the data
74         */
75         bool correct_layout_selected = false;
76         for (auto& node : usr->get_dependencies())
77         {
78             if (!node->is_in_data_flow())
79             {
80                 /*
81                     ToDo: Here we should handle also the situation where primitive usr has data inputs in different formats
82                 */
83                 layout current_layout(usr->get_output_layout().data_type,
84                     node->get_output_layout().format,
85                     usr->get_output_layout().size);
86                 usr->set_output_layout(current_layout);
87                 if (usr->type()->does_possible_implementation_exist(p.get_engine(), *usr))
88                 {
89                     correct_layout_selected = true;
90                     break;
91                 }
92                 else
93                 {
94                     throw error("Internal Error: no layout format available for " + usr->id() +
95                         " comaptible with " + node->id(), CLDNN_ERROR);
96                 }
97             }
98         }
99
100         if (!correct_layout_selected) {
101             //This list of preffered layouts has been selected arbitrary due to developers' experience
102             cldnn::format preffered_layout_formats[]{
103                 cldnn::format::bfyx,
104                 cldnn::format::yxfb,
105                 cldnn::format::byxf,
106             };
107
108             for (auto new_layout_format : preffered_layout_formats)
109             {
110                 layout current_layout(usr->get_output_layout().data_type,
111                     new_layout_format,
112                     usr->get_output_layout().size);
113                 usr->set_output_layout(current_layout);
114                 if (usr->type()->does_possible_implementation_exist(p.get_engine(), *usr))
115                 {
116                     correct_layout_selected = true;
117                     break;
118                 }
119             }
120
121             if (!correct_layout_selected) {
122                 throw error("Internal Error: no implementation for " + usr->id() + " kernel which satisfies output format dependecies.", CLDNN_ERROR);
123             }
124         }
125
126         // layout is selected now add required reorders
127         auto dep_itr = usr->get_dependencies().begin();
128         while (dep_itr != usr->get_dependencies().end())
129         {
130             auto node = *dep_itr++;
131             //do not add a reorder if usr or node are reorders or does not belong to data_flow
132             if (!usr->is_type<reorder>() &&
133                 !node->is_type<reorder>() &&
134                 node->is_in_data_flow())
135             {
136                 if ((usr->get_output_layout()!=node->get_output_layout()))
137                 {
138                     add_reorder(p, node, usr, usr->get_output_layout());
139                 }
140             }
141         }
142     }
143 }