2eb72af2bbfd1b7f86a072f2112539f2e5c712fd
[platform/upstream/dldt.git] / ngraph / test / backend / broadcast.in.cpp
1 //*****************************************************************************
2 // Copyright 2017-2020 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 #include <algorithm>
18 #include <cinttypes>
19 #include <cmath>
20 #include <cstdlib>
21 #include <numeric>
22 #include <random>
23 #include <string>
24
25 #include "gtest/gtest.h"
26 #include "ngraph/ngraph.hpp"
27 #include "ngraph/runtime/tensor.hpp"
28 #include "runtime/backend.hpp"
29 #include "util/all_close.hpp"
30 #include "util/all_close_f.hpp"
31 #include "util/ndarray.hpp"
32 #include "util/test_control.hpp"
33 #include "util/test_tools.hpp"
34
35 NGRAPH_SUPPRESS_DEPRECATED_START
36
37 using namespace std;
38 using namespace ngraph;
39
40 static string s_manifest = "${MANIFEST}";
41
42 NGRAPH_TEST(${BACKEND_NAME}, broadcast_scalar_vector)
43 {
44     Shape shape_a{};
45     auto A = make_shared<op::Parameter>(element::f32, shape_a);
46     Shape shape_r{4};
47     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
48                                    ParameterVector{A});
49
50     auto backend = runtime::Backend::create("${BACKEND_NAME}");
51
52     // Create some tensors for input/output
53     auto a = backend->create_tensor(element::f32, shape_a);
54     copy_data(a, vector<float>{6});
55     auto result = backend->create_tensor(element::f32, shape_r);
56
57     auto handle = backend->compile(f);
58     handle->call_with_validate({result}, {a});
59     EXPECT_TRUE(test::all_close_f(
60         (vector<float>{6, 6, 6, 6}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
61 }
62
63 NGRAPH_TEST(${BACKEND_NAME}, broadcast_scalar_matrix)
64 {
65     Shape shape_a{};
66     auto A = make_shared<op::Parameter>(element::f32, shape_a);
67     Shape shape_r{2, 2};
68     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0, 1}),
69                                    ParameterVector{A});
70
71     auto backend = runtime::Backend::create("${BACKEND_NAME}");
72
73     // Create some tensors for input/output
74     auto a = backend->create_tensor(element::f32, shape_a);
75     copy_data(a, vector<float>{6});
76     auto result = backend->create_tensor(element::f32, shape_r);
77
78     auto handle = backend->compile(f);
79     handle->call_with_validate({result}, {a});
80     EXPECT_TRUE(test::all_close_f(
81         (vector<float>{6, 6, 6, 6}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
82 }
83
84 NGRAPH_TEST(${BACKEND_NAME}, broadcast_scalar_tensor)
85 {
86     Shape shape_a{};
87     auto A = make_shared<op::Parameter>(element::f32, shape_a);
88     Shape shape_r{2, 2, 2};
89     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0, 1, 2}),
90                                    ParameterVector{A});
91
92     auto backend = runtime::Backend::create("${BACKEND_NAME}");
93
94     // Create some tensors for input/output
95     auto a = backend->create_tensor(element::f32, shape_a);
96     copy_data(a, vector<float>{6});
97     auto result = backend->create_tensor(element::f32, shape_r);
98
99     auto handle = backend->compile(f);
100     handle->call_with_validate({result}, {a});
101     EXPECT_TRUE(test::all_close_f((vector<float>{6, 6, 6, 6, 6, 6, 6, 6}),
102                                   read_vector<float>(result),
103                                   MIN_FLOAT_TOLERANCE_BITS));
104 }
105
106 NGRAPH_TEST(${BACKEND_NAME}, broadcast_trivial)
107 {
108     Shape shape{2, 2, 2};
109     auto A = make_shared<op::Parameter>(element::f32, shape);
110     auto f =
111         make_shared<Function>(make_shared<op::Broadcast>(A, shape, AxisSet{}), ParameterVector{A});
112
113     auto backend = runtime::Backend::create("${BACKEND_NAME}");
114
115     // Create some tensors for input/output
116     auto a = backend->create_tensor(element::f32, shape);
117     copy_data(a, vector<float>{2, 4, 6, 8, 16, 32, 64, 128});
118     auto result = backend->create_tensor(element::f32, shape);
119
120     auto handle = backend->compile(f);
121     handle->call_with_validate({result}, {a});
122     EXPECT_TRUE(test::all_close_f((vector<float>{2, 4, 6, 8, 16, 32, 64, 128}),
123                                   read_vector<float>(result),
124                                   MIN_FLOAT_TOLERANCE_BITS));
125 }
126
127 NGRAPH_TEST(${BACKEND_NAME}, broadcast_vector_colwise)
128 {
129     Shape shape_a{3};
130     auto A = make_shared<op::Parameter>(element::f32, shape_a);
131     Shape shape_r{3, 4};
132     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{1}),
133                                    ParameterVector{A});
134
135     auto backend = runtime::Backend::create("${BACKEND_NAME}");
136
137     // Create some tensors for input/output
138     auto a = backend->create_tensor(element::f32, shape_a);
139     copy_data(a, vector<float>{1, 2, 3});
140     auto result = backend->create_tensor(element::f32, shape_r);
141
142     auto handle = backend->compile(f);
143     handle->call_with_validate({result}, {a});
144     EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3}),
145                                   read_vector<float>(result),
146                                   MIN_FLOAT_TOLERANCE_BITS));
147 }
148
149 NGRAPH_TEST(${BACKEND_NAME}, broadcast_vector_rowwise)
150 {
151     Shape shape_a{4};
152     auto A = make_shared<op::Parameter>(element::f32, shape_a);
153     Shape shape_r{3, 4};
154     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
155                                    ParameterVector{A});
156
157     auto backend = runtime::Backend::create("${BACKEND_NAME}");
158
159     // Create some tensors for input/output
160     auto a = backend->create_tensor(element::f32, shape_a);
161     copy_data(a, vector<float>{1, 2, 3, 4});
162     auto result = backend->create_tensor(element::f32, shape_r);
163
164     auto handle = backend->compile(f);
165     handle->call_with_validate({result}, {a});
166     EXPECT_TRUE(test::all_close_f((vector<float>{1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4}),
167                                   read_vector<float>(result),
168                                   MIN_FLOAT_TOLERANCE_BITS));
169 }
170
171 // Test hybrid mechanism after broadcast
172 NGRAPH_TEST(${BACKEND_NAME}, broadcast_vector_rowwise_reversed)
173 {
174     Shape shape_a{4};
175     auto A = make_shared<op::Parameter>(element::f32, shape_a);
176     Shape shape_r{3, 4};
177     auto broadcast = make_shared<op::Broadcast>(A, shape_r, AxisSet{0});
178     auto reverse = make_shared<op::Reverse>(broadcast, AxisSet{1});
179     auto f = make_shared<Function>(reverse, ParameterVector{A});
180
181     auto backend = runtime::Backend::create("${BACKEND_NAME}");
182
183     // Create some tensors for input/output
184     auto a = backend->create_tensor(element::f32, shape_a);
185     copy_data(a, vector<float>{1, 2, 3, 4});
186     auto result = backend->create_tensor(element::f32, shape_r);
187
188     auto handle = backend->compile(f);
189     handle->call_with_validate({result}, {a});
190     EXPECT_TRUE(test::all_close_f((vector<float>{4, 3, 2, 1, 4, 3, 2, 1, 4, 3, 2, 1}),
191                                   read_vector<float>(result),
192                                   MIN_FLOAT_TOLERANCE_BITS));
193 }
194
195 NGRAPH_TEST(${BACKEND_NAME}, broadcast_vector_rowwise_int64)
196 {
197     Shape shape_a{4};
198     auto A = make_shared<op::Parameter>(element::i64, shape_a);
199     Shape shape_r{3, 4};
200     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
201                                    ParameterVector{A});
202
203     auto backend = runtime::Backend::create("${BACKEND_NAME}");
204
205     // Create some tensors for input/output
206     auto a = backend->create_tensor(element::i64, shape_a);
207     copy_data(a, vector<int64_t>{1, 2, 3, 4});
208     auto result = backend->create_tensor(element::i64, shape_r);
209
210     auto handle = backend->compile(f);
211     handle->call_with_validate({result}, {a});
212     EXPECT_EQ((vector<int64_t>{1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4}), read_vector<int64_t>(result));
213 }
214
215 NGRAPH_TEST(${BACKEND_NAME}, broadcast_scalar_to_matrix_int64)
216 {
217     Shape shape_a{1};
218     auto A = make_shared<op::Parameter>(element::i64, shape_a);
219     Shape shape_r{3, 1};
220     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
221                                    ParameterVector{A});
222
223     auto backend = runtime::Backend::create("${BACKEND_NAME}");
224
225     // Create some tensors for input/output
226     auto a = backend->create_tensor(element::i64, shape_a);
227     copy_data(a, vector<int64_t>{4});
228     auto result = backend->create_tensor(element::i64, shape_r);
229
230     auto handle = backend->compile(f);
231     handle->call_with_validate({result}, {a});
232     EXPECT_EQ((vector<int64_t>{4, 4, 4}), read_vector<int64_t>(result));
233 }
234
235 NGRAPH_TEST(${BACKEND_NAME}, broadcast_scalar_to_matrix_int32)
236 {
237     Shape shape_a{1};
238     auto A = make_shared<op::Parameter>(element::i32, shape_a);
239     Shape shape_r{3, 1};
240     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
241                                    ParameterVector{A});
242
243     auto backend = runtime::Backend::create("${BACKEND_NAME}");
244
245     // Create some tensors for input/output
246     auto a = backend->create_tensor(element::i32, shape_a);
247     copy_data(a, vector<int32_t>{4});
248     auto result = backend->create_tensor(element::i32, shape_r);
249
250     auto handle = backend->compile(f);
251     handle->call_with_validate({result}, {a});
252     EXPECT_EQ((vector<int32_t>{4, 4, 4}), read_vector<int32_t>(result));
253 }
254
255 static void broadcast_test_helper(const Shape& shape_a, const Shape& shape_r, const AxisSet& axis)
256 {
257     auto A = make_shared<op::Parameter>(element::f32, shape_a);
258
259     vector<float> inp_data(shape_size<const Shape>(shape_a));
260     iota(inp_data.begin(), inp_data.end(), 1.f);
261
262     auto f =
263         make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, axis), ParameterVector{A});
264
265     auto ref_backend = runtime::Backend::create("INTERPRETER");
266     auto wrk_backend = runtime::Backend::create("${BACKEND_NAME}");
267
268     auto wrk_a = wrk_backend->create_tensor(element::f32, shape_a);
269     copy_data(wrk_a, inp_data);
270
271     auto ref_a = ref_backend->create_tensor(element::f32, shape_a);
272     copy_data(ref_a, inp_data);
273
274     auto wrk_result = wrk_backend->create_tensor(element::f32, shape_r);
275     auto ref_result = ref_backend->create_tensor(element::f32, shape_r);
276
277     auto wrk_handle = wrk_backend->compile(f);
278     auto ref_handle = ref_backend->compile(f);
279     wrk_handle->call_with_validate({wrk_result}, {wrk_a});
280     ref_handle->call_with_validate({ref_result}, {ref_a});
281     EXPECT_TRUE(test::all_close_f(
282         read_vector<float>(ref_result), read_vector<float>(wrk_result), MIN_FLOAT_TOLERANCE_BITS));
283 }
284
285 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_middle)
286 {
287     Shape shape_a{2};
288     Shape shape_r{3, 2, 4};
289     AxisSet axis{0, 2};
290     broadcast_test_helper(shape_a, shape_r, axis);
291 }
292
293 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_forward_2)
294 {
295     Shape shape_a{2};
296     Shape shape_r{3, 2};
297     AxisSet axis{0};
298     broadcast_test_helper(shape_a, shape_r, axis);
299 }
300
301 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_forward_3)
302 {
303     Shape shape_a{2};
304     Shape shape_r{4, 3, 2};
305     AxisSet axis{0, 1};
306     broadcast_test_helper(shape_a, shape_r, axis);
307 }
308 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_forward_4)
309 {
310     Shape shape_a{2};
311     Shape shape_r{5, 4, 3, 2};
312     AxisSet axis{0, 1, 2};
313     broadcast_test_helper(shape_a, shape_r, axis);
314 }
315
316 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_scalar)
317 {
318     Shape shape_a{};
319     Shape shape_r{5, 4, 3, 2};
320     AxisSet axis{0, 1, 2, 3};
321     broadcast_test_helper(shape_a, shape_r, axis);
322 }
323
324 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_backward_2)
325 {
326     Shape shape_a{2};
327     Shape shape_r{2, 3};
328     AxisSet axis{1};
329     broadcast_test_helper(shape_a, shape_r, axis);
330 }
331
332 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_backward_3)
333 {
334     Shape shape_a{2};
335     Shape shape_r{2, 3, 4};
336     AxisSet axis{1, 2};
337     broadcast_test_helper(shape_a, shape_r, axis);
338 }
339
340 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_backward_4)
341 {
342     Shape shape_a{2};
343     Shape shape_r{2, 3, 4, 5};
344     AxisSet axis{1, 2, 3};
345     broadcast_test_helper(shape_a, shape_r, axis);
346 }
347
348 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_matrix_backward_4)
349 {
350     Shape shape_a{4, 5};
351     Shape shape_r{2, 3, 4, 5};
352     AxisSet axis{0, 1};
353     broadcast_test_helper(shape_a, shape_r, axis);
354 }
355
356 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_matrix_stride_1)
357 {
358     Shape shape_a{3, 5};
359     Shape shape_r{2, 3, 4, 5};
360     AxisSet axis{0, 2};
361     broadcast_test_helper(shape_a, shape_r, axis);
362 }
363
364 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_matrix_stride_2)
365 {
366     Shape shape_a{3, 4};
367     Shape shape_r{2, 3, 4, 5};
368     AxisSet axis{0, 3};
369     broadcast_test_helper(shape_a, shape_r, axis);
370 }
371
372 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_matrix_stride_3)
373 {
374     Shape shape_a{2, 4};
375     Shape shape_r{2, 3, 4, 5};
376     AxisSet axis{1, 3};
377     broadcast_test_helper(shape_a, shape_r, axis);
378 }
379
380 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_3d_backward)
381 {
382     Shape shape_a{2, 3, 4};
383     Shape shape_r{5, 2, 3, 4};
384     AxisSet axis{0};
385     broadcast_test_helper(shape_a, shape_r, axis);
386 }
387
388 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_3d_stride_1)
389 {
390     Shape shape_a{2, 3, 4};
391     Shape shape_r{2, 5, 3, 4};
392     AxisSet axis{1};
393     broadcast_test_helper(shape_a, shape_r, axis);
394 }
395
396 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_3d_stride_2)
397 {
398     Shape shape_a{2, 3, 4};
399     Shape shape_r{2, 3, 5, 4};
400     AxisSet axis{2};
401     broadcast_test_helper(shape_a, shape_r, axis);
402 }
403
404 NGRAPH_TEST(${BACKEND_NAME}, broadcast_matrix_0)
405 {
406     Shape shape_a{2, 2};
407     auto A = make_shared<op::Parameter>(element::f32, shape_a);
408     Shape shape_r{2, 2, 2};
409     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
410                                    ParameterVector{A});
411
412     auto backend = runtime::Backend::create("${BACKEND_NAME}");
413
414     // Create some tensors for input/output
415     auto a = backend->create_tensor(element::f32, shape_a);
416     copy_data(a, vector<float>{1, 2, 3, 4});
417     auto result = backend->create_tensor(element::f32, shape_r);
418
419     auto handle = backend->compile(f);
420     handle->call_with_validate({result}, {a});
421     EXPECT_TRUE(test::all_close_f((vector<float>{1, 2, 3, 4, 1, 2, 3, 4}),
422                                   read_vector<float>(result),
423                                   MIN_FLOAT_TOLERANCE_BITS));
424 }
425
426 NGRAPH_TEST(${BACKEND_NAME}, broadcast_matrix_1)
427 {
428     Shape shape_a{2, 2};
429     auto A = make_shared<op::Parameter>(element::f32, shape_a);
430     Shape shape_r{2, 2, 2};
431     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{1}),
432                                    ParameterVector{A});
433
434     auto backend = runtime::Backend::create("${BACKEND_NAME}");
435
436     // Create some tensors for input/output
437     auto a = backend->create_tensor(element::f32, shape_a);
438     copy_data(a, vector<float>{1, 2, 3, 4});
439     auto result = backend->create_tensor(element::f32, shape_r);
440
441     auto handle = backend->compile(f);
442     handle->call_with_validate({result}, {a});
443     EXPECT_TRUE(test::all_close_f((vector<float>{1, 2, 1, 2, 3, 4, 3, 4}),
444                                   read_vector<float>(result),
445                                   MIN_FLOAT_TOLERANCE_BITS));
446 }
447
448 NGRAPH_TEST(${BACKEND_NAME}, broadcast_matrix_2)
449 {
450     Shape shape_a{2, 2};
451     auto A = make_shared<op::Parameter>(element::f32, shape_a);
452     Shape shape_r{2, 2, 2};
453     auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{2}),
454                                    ParameterVector{A});
455
456     auto backend = runtime::Backend::create("${BACKEND_NAME}");
457
458     // Create some tensors for input/output
459     auto a = backend->create_tensor(element::f32, shape_a);
460     copy_data(a, vector<float>{1, 2, 3, 4});
461     auto result = backend->create_tensor(element::f32, shape_r);
462
463     auto handle = backend->compile(f);
464     handle->call_with_validate({result}, {a});
465     EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 2, 2, 3, 3, 4, 4}),
466                                   read_vector<float>(result),
467                                   MIN_FLOAT_TOLERANCE_BITS));
468 }