1 //*****************************************************************************
2 // Copyright 2017-2020 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.
15 //*****************************************************************************
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"
35 NGRAPH_SUPPRESS_DEPRECATED_START
38 using namespace ngraph;
40 static string s_manifest = "${MANIFEST}";
42 NGRAPH_TEST(${BACKEND_NAME}, broadcast_scalar_vector)
45 auto A = make_shared<op::Parameter>(element::f32, shape_a);
47 auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
50 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
63 NGRAPH_TEST(${BACKEND_NAME}, broadcast_scalar_matrix)
66 auto A = make_shared<op::Parameter>(element::f32, shape_a);
68 auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0, 1}),
71 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
84 NGRAPH_TEST(${BACKEND_NAME}, broadcast_scalar_tensor)
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}),
92 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
106 NGRAPH_TEST(${BACKEND_NAME}, broadcast_trivial)
108 Shape shape{2, 2, 2};
109 auto A = make_shared<op::Parameter>(element::f32, shape);
111 make_shared<Function>(make_shared<op::Broadcast>(A, shape, AxisSet{}), ParameterVector{A});
113 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
127 NGRAPH_TEST(${BACKEND_NAME}, broadcast_vector_colwise)
130 auto A = make_shared<op::Parameter>(element::f32, shape_a);
132 auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{1}),
135 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
149 NGRAPH_TEST(${BACKEND_NAME}, broadcast_vector_rowwise)
152 auto A = make_shared<op::Parameter>(element::f32, shape_a);
154 auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
157 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
171 // Test hybrid mechanism after broadcast
172 NGRAPH_TEST(${BACKEND_NAME}, broadcast_vector_rowwise_reversed)
175 auto A = make_shared<op::Parameter>(element::f32, shape_a);
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});
181 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
195 NGRAPH_TEST(${BACKEND_NAME}, broadcast_vector_rowwise_int64)
198 auto A = make_shared<op::Parameter>(element::i64, shape_a);
200 auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
203 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
215 NGRAPH_TEST(${BACKEND_NAME}, broadcast_scalar_to_matrix_int64)
218 auto A = make_shared<op::Parameter>(element::i64, shape_a);
220 auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
223 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
235 NGRAPH_TEST(${BACKEND_NAME}, broadcast_scalar_to_matrix_int32)
238 auto A = make_shared<op::Parameter>(element::i32, shape_a);
240 auto f = make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, AxisSet{0}),
243 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
255 static void broadcast_test_helper(const Shape& shape_a, const Shape& shape_r, const AxisSet& axis)
257 auto A = make_shared<op::Parameter>(element::f32, shape_a);
259 vector<float> inp_data(shape_size<const Shape>(shape_a));
260 iota(inp_data.begin(), inp_data.end(), 1.f);
263 make_shared<Function>(make_shared<op::Broadcast>(A, shape_r, axis), ParameterVector{A});
265 auto ref_backend = runtime::Backend::create("INTERPRETER");
266 auto wrk_backend = runtime::Backend::create("${BACKEND_NAME}");
268 auto wrk_a = wrk_backend->create_tensor(element::f32, shape_a);
269 copy_data(wrk_a, inp_data);
271 auto ref_a = ref_backend->create_tensor(element::f32, shape_a);
272 copy_data(ref_a, inp_data);
274 auto wrk_result = wrk_backend->create_tensor(element::f32, shape_r);
275 auto ref_result = ref_backend->create_tensor(element::f32, shape_r);
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));
285 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_middle)
288 Shape shape_r{3, 2, 4};
290 broadcast_test_helper(shape_a, shape_r, axis);
293 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_forward_2)
298 broadcast_test_helper(shape_a, shape_r, axis);
301 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_forward_3)
304 Shape shape_r{4, 3, 2};
306 broadcast_test_helper(shape_a, shape_r, axis);
308 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_forward_4)
311 Shape shape_r{5, 4, 3, 2};
312 AxisSet axis{0, 1, 2};
313 broadcast_test_helper(shape_a, shape_r, axis);
316 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_scalar)
319 Shape shape_r{5, 4, 3, 2};
320 AxisSet axis{0, 1, 2, 3};
321 broadcast_test_helper(shape_a, shape_r, axis);
324 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_backward_2)
329 broadcast_test_helper(shape_a, shape_r, axis);
332 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_backward_3)
335 Shape shape_r{2, 3, 4};
337 broadcast_test_helper(shape_a, shape_r, axis);
340 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_vector_backward_4)
343 Shape shape_r{2, 3, 4, 5};
344 AxisSet axis{1, 2, 3};
345 broadcast_test_helper(shape_a, shape_r, axis);
348 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_matrix_backward_4)
351 Shape shape_r{2, 3, 4, 5};
353 broadcast_test_helper(shape_a, shape_r, axis);
356 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_matrix_stride_1)
359 Shape shape_r{2, 3, 4, 5};
361 broadcast_test_helper(shape_a, shape_r, axis);
364 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_matrix_stride_2)
367 Shape shape_r{2, 3, 4, 5};
369 broadcast_test_helper(shape_a, shape_r, axis);
372 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_matrix_stride_3)
375 Shape shape_r{2, 3, 4, 5};
377 broadcast_test_helper(shape_a, shape_r, axis);
380 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_3d_backward)
382 Shape shape_a{2, 3, 4};
383 Shape shape_r{5, 2, 3, 4};
385 broadcast_test_helper(shape_a, shape_r, axis);
388 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_3d_stride_1)
390 Shape shape_a{2, 3, 4};
391 Shape shape_r{2, 5, 3, 4};
393 broadcast_test_helper(shape_a, shape_r, axis);
396 NGRAPH_TEST(${BACKEND_NAME}, broadcast_algo_3d_stride_2)
398 Shape shape_a{2, 3, 4};
399 Shape shape_r{2, 3, 5, 4};
401 broadcast_test_helper(shape_a, shape_r, axis);
404 NGRAPH_TEST(${BACKEND_NAME}, broadcast_matrix_0)
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}),
412 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
426 NGRAPH_TEST(${BACKEND_NAME}, broadcast_matrix_1)
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}),
434 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
448 NGRAPH_TEST(${BACKEND_NAME}, broadcast_matrix_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}),
456 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));