2 Copyright (c) 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.
21 from mo.middle.passes.fusing.mark_unfused_nodes import mark_unfused_nodes
22 from mo.utils.unittest.graph import build_graph
25 'placeholder_1': {'shape': None, 'type': 'Placeholder', 'kind': 'op', 'op': 'Placeholder'},
26 'placeholder_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
28 'scaleshift_1': {'type': 'ScaleShift', 'kind': 'op', 'op': 'ScaleShift'},
29 'scaleshift_1_w': {'value': None, 'shape': None, 'kind': 'data'},
30 'scaleshift_1_b': {'value': None, 'shape': None, 'kind': 'data'},
31 'scaleshift_1_data': {'value': None, 'shape': None, 'kind': 'data'},
32 # Mul and Add operations
33 'mul_1': {'type': 'Mul', 'kind': 'op', 'op': 'Mul'},
34 'mul_1_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
35 'mul_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
36 'add_1': {'type': 'Add', 'kind': 'op', 'op': 'Add'},
37 'add_1_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
38 'add_1_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
39 # Mul2 and Add2 operations
40 'mul_2': {'type': 'Mul', 'kind': 'op', 'op': 'Mul'},
41 'mul_2_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
42 'mul_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
43 'add_2': {'type': 'Add', 'kind': 'op', 'op': 'Add'},
44 'add_2_w': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
45 'add_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
47 'concat_1': {'type': 'Concat', 'kind': 'op', 'op': 'Concat'},
48 'concat_1_data': {'value': None, 'shape': None, 'kind': 'data'},
50 'conv_1': {'type': 'Convolution', 'kind': 'op', 'op': 'Conv2D', 'layout': 'NHWC'},
51 'conv_1_w': {'value': None, 'shape': None, 'kind': 'data'},
52 'conv_1_b': {'value': None, 'shape': None, 'kind': 'data'},
53 'conv_1_data': {'value': None, 'shape': None, 'kind': 'data'},
54 'conv_2': {'type': 'Convolution', 'kind': 'op', 'op': 'Conv2D', 'layout': 'NHWC'},
55 'conv_2_w': {'value': None, 'shape': None, 'kind': 'data'},
56 'conv_2_b': {'value': None, 'shape': None, 'kind': 'data'},
57 'conv_2_data': {'value': None, 'shape': None, 'kind': 'data'},
59 'fc_1': {'type': 'FullyConnected', 'kind': 'op', 'op': 'InnerProduct', 'layout': 'NHWC'},
60 'fc_1_w': {'value': None, 'shape': None, 'kind': 'data'},
61 'fc_1_b': {'value': None, 'shape': None, 'kind': 'data'},
62 'fc_1_data': {'value': None, 'shape': None, 'kind': 'data'},
64 'placeholder_2': {'shape': None, 'type': 'Placeholder', 'kind': 'op', 'op': 'Placeholder'},
65 'placeholder_2_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
66 'placeholder_3': {'shape': None, 'type': 'Placeholder', 'kind': 'op', 'op': 'Placeholder'},
67 'placeholder_3_data': {'value': None, 'shape': None, 'kind': 'data', 'data_type': None},
71 # Unit tests for forward and backward bfs (forward_bfs, backward_bfs)
72 class MarkFusedNodes(unittest.TestCase):
73 def test_mark_unfused_nodes_1(self):
74 # Placeholder->ScaleShift->Mul->Add
75 graph = build_graph(nodes_attributes,
76 [('placeholder_1', 'placeholder_1_data'),
77 ('placeholder_1_data', 'mul_1'),
79 ('mul_1', 'mul_1_data'),
80 ('mul_1_data', 'add_1'),
82 ('add_1', 'add_1_data'),
83 ('add_1_data', 'mul_2'),
85 ('mul_2', 'mul_2_data'),
86 ('mul_2_data', 'concat_1'),
87 ('concat_1', 'concat_1_data'),
88 ('placeholder_1_data', 'concat_1'),
90 {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
91 'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
92 'add_1_data': {'shape': np.array([1, 227, 227, 3])},
93 'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
94 'mul_1_w': {'shape': np.array([1]), 'value': 6},
95 'add_1_w': {'shape': np.array([1]), 'value': 6},
96 'mul_2_w': {'shape': np.array([1]), 'value': 6},
97 'concat_1_data': {'is_output': True}
100 graph.graph['layout'] = 'NHWC'
102 mark_unfused_nodes(graph, '.*mul.*')
104 self.assertFalse(graph.node['mul_1']['can_be_fused'], "can_be_fused should be False")
105 self.assertFalse(graph.node['mul_2']['can_be_fused'], "can_be_fused should be False")
106 self.assertTrue(graph.node['add_1']['can_be_fused'], "can_be_fused should be True")
108 def test_mark_unfused_nodes_2(self):
109 # Placeholder->ScaleShift->Mul->Add
110 graph = build_graph(nodes_attributes,
111 [('placeholder_1', 'placeholder_1_data'),
112 ('placeholder_1_data', 'mul_1'),
113 ('mul_1_w', 'mul_1'),
114 ('mul_1', 'mul_1_data'),
115 ('mul_1_data', 'add_1'),
116 ('add_1_w', 'add_1'),
117 ('add_1', 'add_1_data'),
118 ('add_1_data', 'mul_2'),
119 ('mul_2_w', 'mul_2'),
120 ('mul_2', 'mul_2_data'),
121 ('mul_2_data', 'concat_1'),
122 ('concat_1', 'concat_1_data'),
123 ('placeholder_1_data', 'concat_1'),
125 {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
126 'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
127 'add_1_data': {'shape': np.array([1, 227, 227, 3])},
128 'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
129 'mul_1_w': {'shape': np.array([1]), 'value': 6},
130 'add_1_w': {'shape': np.array([1]), 'value': 6},
131 'mul_2_w': {'shape': np.array([1]), 'value': 6},
132 'concat_1_data': {'is_output': True}
134 graph.graph['layout'] = 'NHWC'
136 mark_unfused_nodes(graph, '.*')
138 self.assertFalse(graph.node['mul_1']['can_be_fused'], "can_be_fused should be False")
139 self.assertFalse(graph.node['mul_2']['can_be_fused'], "can_be_fused should be False")
140 self.assertFalse(graph.node['add_1']['can_be_fused'], "can_be_fused should be False")
141 self.assertFalse(graph.node['placeholder_1']['can_be_fused'], "can_be_fused should be False")
142 self.assertFalse(graph.node['concat_1']['can_be_fused'], "can_be_fused should be False")
144 def test_mark_unfused_nodes_3(self):
145 # Placeholder->ScaleShift->Mul->Add
146 graph = build_graph(nodes_attributes,
147 [('placeholder_1', 'placeholder_1_data'),
148 ('placeholder_1_data', 'mul_1'),
149 ('mul_1_w', 'mul_1'),
150 ('mul_1', 'mul_1_data'),
151 ('mul_1_data', 'add_1'),
152 ('add_1_w', 'add_1'),
153 ('add_1', 'add_1_data'),
154 ('add_1_data', 'mul_2'),
155 ('mul_2_w', 'mul_2'),
156 ('mul_2', 'mul_2_data'),
157 ('mul_2_data', 'concat_1'),
158 ('concat_1', 'concat_1_data'),
159 ('placeholder_1_data', 'concat_1'),
161 {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
162 'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
163 'add_1_data': {'shape': np.array([1, 227, 227, 3])},
164 'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
165 'mul_1_w': {'shape': np.array([1]), 'value': 6},
166 'add_1_w': {'shape': np.array([1]), 'value': 6},
167 'mul_2_w': {'shape': np.array([1]), 'value': 6},
168 'concat_1_data': {'is_output': True}
170 graph.graph['layout'] = 'NHWC'
172 mark_unfused_nodes(graph, 'mul_1,add_1')
174 self.assertFalse(graph.node['mul_1']['can_be_fused'], "can_be_fused should be False")
175 self.assertFalse(graph.node['add_1']['can_be_fused'], "can_be_fused should be False")
176 self.assertTrue(graph.node['mul_2']['can_be_fused'], "can_be_fused should be True")
178 def test_mark_unfused_nodes_4(self):
179 # Placeholder->ScaleShift->Mul->Add
180 graph = build_graph(nodes_attributes,
181 [('placeholder_1', 'placeholder_1_data'),
182 ('placeholder_1_data', 'mul_1'),
183 ('mul_1_w', 'mul_1'),
184 ('mul_1', 'mul_1_data'),
185 ('mul_1_data', 'add_1'),
186 ('add_1_w', 'add_1'),
187 ('add_1', 'add_1_data'),
188 ('add_1_data', 'mul_2'),
189 ('mul_2_w', 'mul_2'),
190 ('mul_2', 'mul_2_data'),
191 ('mul_2_data', 'concat_1'),
192 ('concat_1', 'concat_1_data'),
193 ('placeholder_1_data', 'concat_1'),
195 {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
196 'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
197 'add_1_data': {'shape': np.array([1, 227, 227, 3])},
198 'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
199 'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
200 'add_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
201 'mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
202 'concat_1_data': {'is_output': True}
204 graph.graph['layout'] = 'NHWC'
206 mark_unfused_nodes(graph, '')
208 self.assertTrue(graph.node['mul_1']['can_be_fused'], "can_be_fused should be True")
209 self.assertTrue(graph.node['add_1']['can_be_fused'], "can_be_fused should be True")
210 self.assertTrue(graph.node['mul_2']['can_be_fused'], "can_be_fused should be True")
212 def test_mark_unfused_nodes_5(self):
213 # Placeholder->ScaleShift->Mul->Add
214 graph = build_graph(nodes_attributes,
215 [('placeholder_1', 'placeholder_1_data'),
216 ('placeholder_1_data', 'mul_1'),
217 ('mul_1_w', 'mul_1'),
218 ('mul_1', 'mul_1_data'),
219 ('mul_1_data', 'add_1'),
220 ('add_1_w', 'add_1'),
221 ('add_1', 'add_1_data'),
222 ('add_1_data', 'mul_2'),
223 ('mul_2_w', 'mul_2'),
224 ('mul_2', 'mul_2_data'),
225 ('mul_2_data', 'concat_1'),
226 ('concat_1', 'concat_1_data'),
227 ('placeholder_1_data', 'concat_1'),
229 {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
230 'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
231 'add_1_data': {'shape': np.array([1, 227, 227, 3])},
232 'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
233 'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
234 'add_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
235 'mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
236 'concat_1_data': {'is_output': True}
238 graph.graph['layout'] = 'NCHW'
240 mark_unfused_nodes(graph, '')
242 self.assertTrue(graph.node['mul_1']['can_be_fused'], "can_be_fused should be True")
243 self.assertTrue(graph.node['add_1']['can_be_fused'], "can_be_fused should be True")
244 self.assertTrue(graph.node['mul_2']['can_be_fused'], "can_be_fused should be True")
246 def test_mark_unfused_nodes_5(self):
247 # Placeholder->ScaleShift->Mul->Add
248 graph = build_graph(nodes_attributes,
249 [('placeholder_1', 'placeholder_1_data'),
250 ('placeholder_1_data', 'mul_1'),
251 ('mul_1_w', 'mul_1'),
252 ('mul_1', 'mul_1_data'),
253 ('mul_1_data', 'add_1'),
254 ('add_1_w', 'add_1'),
255 ('add_1', 'add_1_data'),
256 ('add_1_data', 'mul_2'),
257 ('mul_2_w', 'mul_2'),
258 ('mul_2', 'mul_2_data'),
259 ('mul_2_data', 'concat_1'),
260 ('concat_1', 'concat_1_data'),
261 ('placeholder_1_data', 'concat_1'),
263 {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
264 'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
265 'add_1_data': {'shape': np.array([1, 227, 227, 3])},
266 'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
267 'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
268 'add_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
269 'mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
270 'concat_1_data': {'is_output': True}
272 graph.graph['layout'] = 'NCHW'
274 mark_unfused_nodes(graph, '')
276 self.assertFalse(graph.node['mul_1']['can_be_fused'], "can_be_fused should be False")
277 self.assertFalse(graph.node['add_1']['can_be_fused'], "can_be_fused should be False")
278 self.assertFalse(graph.node['mul_2']['can_be_fused'], "can_be_fused should be False")
280 def test_mark_unfused_nodes_6(self):
281 # Placeholder->ScaleShift->Mul->Add
282 graph = build_graph(nodes_attributes,
283 [('placeholder_1', 'placeholder_1_data'),
284 ('placeholder_1_data', 'mul_1'),
285 ('mul_1_w', 'mul_1'),
286 ('mul_1', 'mul_1_data'),
287 ('mul_1_data', 'add_1'),
288 ('add_1_w', 'add_1'),
289 ('add_1', 'add_1_data'),
290 ('add_1_data', 'mul_2'),
291 ('mul_2_w', 'mul_2'),
292 ('mul_2', 'mul_2_data'),
293 ('mul_2_data', 'concat_1'),
294 ('concat_1', 'concat_1_data'),
295 ('placeholder_1_data', 'concat_1'),
297 {'placeholder_1_data': {'shape': np.array([1, 227, 227, 3])},
298 'mul_1_data': {'shape': np.array([1, 227, 227, 3])},
299 'add_1_data': {'shape': np.array([1, 227, 227, 3])},
300 'mul_2_data': {'shape': np.array([1, 227, 227, 3])},
301 'mul_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
302 'add_1_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
303 'mul_2_w': {'shape': np.array([3]), 'value': np.array([1, 2, 3])},
304 'concat_1_data': {'is_output': True}
306 graph.graph['layout'] = 'NHWC'
308 mark_unfused_nodes(graph, '')
310 self.assertTrue(graph.node['mul_1']['can_be_fused'], "can_be_fused should be True")
311 self.assertTrue(graph.node['add_1']['can_be_fused'], "can_be_fused should be True")
312 self.assertTrue(graph.node['mul_2']['can_be_fused'], "can_be_fused should be True")