1 // Copyright (c) 2018 Intel Corporation
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 ///////////////////////////////////////////////////////////////////////////////////////////////////
16 #include <gtest/gtest.h>
18 #include <api/CPP/engine.hpp>
19 #include <api/CPP/input_layout.hpp>
20 #include <api/CPP/memory.hpp>
21 #include <api/CPP/concatenation.hpp>
22 #include <api/CPP/topology.hpp>
23 #include <api/CPP/network.hpp>
24 #include <api/CPP/pooling.hpp>
25 #include <api/CPP/condition.hpp>
26 #include <api/CPP/softmax.hpp>
27 #include <api/CPP/scale.hpp>
28 #include <api/CPP/data.hpp>
29 #include "test_utils/test_utils.h"
34 using namespace cldnn;
35 using namespace ::tests;
38 bool is_output_equal(const cldnn::memory& mem, const std::vector<float>& ref)
40 auto ptr = mem.pointer<float>();
41 for (size_t i = 0; i < mem.get_layout().count(); i++)
43 if (!are_equal(ptr[i], ref[i])) return false;
48 topology generate_simple_branch (bool branch_true_false, const primitive_id& input_id)
51 if (branch_true_false)
54 pooling(input_id + "_when_true", input_id, cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
60 pooling(input_id + "_when_false", input_id, cldnn::pooling_mode::average, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
67 TEST(condition_gpu, basic_equal_comp) {
68 const auto& engine = get_test_engine();
70 bs.set_option(build_option::optimize_data(true));
71 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 4, 1 } });
72 auto compare = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
73 auto scale_mem = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
75 topology branch_true = generate_simple_branch(true, "condi");
76 topology branch_false = generate_simple_branch(false, "condi");
80 input_layout("input", input.get_layout())
83 input_layout("compare", compare.get_layout())
86 input_layout("scale_data", scale_mem.get_layout())
89 condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL)
92 scale("output", "condi", "scale_data")
95 network net(engine, topology, bs);
96 set_values(input, { 1.0f, 2.0f, 3.0f, 4.0f });
97 set_values(scale_mem, { 10.0f });
98 net.set_input_data("input", input);
99 net.set_input_data("scale_data", scale_mem);
101 decltype(net.execute()) out;
104 set_values(compare, { 1.0f });
105 net.set_input_data("compare", compare);
107 auto out_data_true = out.at("output").get_memory();
108 EXPECT_TRUE(is_output_equal(out_data_true, {20.0f, 40.0f}));
111 set_values(compare, { 4.0f });
112 net.set_input_data("compare", compare);
114 auto out_data_false = out.at("output").get_memory();
115 EXPECT_TRUE(is_output_equal(out_data_false, { 15.0f, 35.0f }));
119 TEST(condition_gpu, basic_range_equal_comp) {
121 const auto& engine = get_test_engine();
123 bs.set_option(build_option::optimize_data(true));
124 auto input0 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 4, 1 } });
125 auto input1 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 4, 1 } });
127 auto compare = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 3, 1 } });
129 topology branch_true = generate_simple_branch(true, "condi");
130 topology branch_false = generate_simple_branch(false, "condi");
134 input_layout("input0", input0.get_layout())
137 input_layout("input1", input1.get_layout())
140 input_layout("compare", compare.get_layout())
143 concatenation("concat", { "input0", "input1" }, concatenation::along_x)
146 condition("condi", "concat", branch_true, branch_false, "compare", cond_functions::EQUAL)
149 std::vector<float> input0_data = {
152 std::vector<float> input1_data = {
155 std::vector<float> compare_data_true = {
158 std::vector<float> pooling_when_true_data = {
161 std::vector<float> compare_data_false = {
164 std::vector<float> pooling_when_false_data = {
168 set_values(input0, input0_data);
169 set_values(input1, input1_data);
170 network net(engine, topology, bs);
171 net.set_input_data("input0", input0);
172 net.set_input_data("input1", input1);
174 decltype(net.execute()) outputs;
177 set_values(compare, compare_data_true);
178 net.set_input_data("compare", compare);
179 outputs = net.execute();
181 auto out_data_true = outputs.at("condi").get_memory();
182 EXPECT_TRUE(is_output_equal(out_data_true, pooling_when_true_data));
185 set_values(compare, compare_data_false);
186 net.set_input_data("compare", compare);
187 outputs = net.execute();
189 auto out_data_false = outputs.at("condi").get_memory();
190 EXPECT_TRUE(is_output_equal(out_data_false, pooling_when_false_data));
193 std::pair<std::vector<float>, std::vector<float>> get_values_to_compare(const cldnn::tensor& offset, const cldnn::tensor& range, const std::vector<float>& values, const cldnn::layout& input_lay, const cond_functions& func)
195 std::vector<float> ret_true;
196 std::vector<float> ret_false;
197 auto mem_desc = generic_test::get_linear_memory_desc(input_lay);
198 for (int32_t b = 0; b < range.batch[0]; b++)
200 for (int32_t f = 0; f < range.feature[0]; f++)
202 for (int32_t y = 0; y < range.spatial[1]; y++)
204 for (int32_t x = 0; x < range.spatial[0]; x++)
206 auto linear_idx = generic_test::get_linear_index(
209 offset.feature[0] + f,
210 offset.spatial[1] + y,
211 offset.spatial[0] + x,
216 case cond_functions::EQUAL:
217 ret_true.push_back(values.at(linear_idx));
218 ret_false.push_back(-1.0f);
220 case cond_functions::GREATER:
221 ret_true.push_back(values.at(linear_idx) - 1.0f);
222 ret_false.push_back(99.0f);
224 case cond_functions::LESS:
225 ret_true.push_back(values.at(linear_idx) + 1.0f);
226 ret_false.push_back(-1.0f);
233 return { ret_true, ret_false };
236 TEST(DISABLED_condition_gpu, generic_test_true_false) {
238 const auto& engine = get_test_engine();
240 bs.set_option(build_option::optimize_data(true));
241 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 5, 2, 5, 1 } });
242 std::vector<float> input_data(50);
243 std::iota(input_data.begin(), input_data.end(), 0.0f);
245 std::vector<cond_functions> functions = {
246 cond_functions::EQUAL,
247 cond_functions::GREATER,
248 cond_functions::LESS,
251 // ranges, with data when condition is true or false
252 std::vector<cldnn::tensor> ranges = {
259 std::vector<cldnn::tensor> offsets = {
267 std::vector<float> pooling_when_true_data = {
268 2, 4, 7, 9, 12, 14, 17,
269 19, 22, 24, 27, 29, 32,
270 34, 37, 39, 42, 44, 47, 49
273 std::vector<float> pooling_when_false_data = {
274 1, 3, 6, 8, 11, 13, 16,
275 18, 21, 23, 26, 28, 31,
276 33, 36, 38, 41, 43, 46, 48
279 for (auto const& func : functions)
281 for (auto const& range : ranges)
283 for (auto const& offset : offsets)
285 auto comp_values = get_values_to_compare(offset, range, input_data, input.get_layout(), func);
286 auto comp_values_true = comp_values.first;
287 auto comp_values_false = comp_values.second;
289 auto compare = memory::allocate(engine, { data_types::f32, format::bfyx, range });
291 topology branch_true;
292 topology branch_false;
294 pooling("pooling_when_true", "condi", cldnn::pooling_mode::max, { 1, 1, 3, 1 }, { 1, 1, 2, 1 })
297 pooling("pooling_when_false", "condi", cldnn::pooling_mode::average, { 1, 1, 3, 1 }, { 1, 1, 2, 1 })
302 input_layout("input", input.get_layout())
305 input_layout("compare", compare.get_layout())
308 condition("condi", "input", branch_true, branch_false, "compare", func, offset)
311 set_values(input, input_data);
312 network net(engine, topology, bs);
313 net.set_input_data("input", input);
315 decltype(net.execute()) outputs;
318 set_values(compare, comp_values_true);
319 net.set_input_data("compare", compare);
320 outputs = net.execute();
322 auto out_data_true = outputs.at("condi").get_memory();
323 EXPECT_TRUE(is_output_equal(out_data_true, pooling_when_true_data));
326 set_values(compare, comp_values_false);
327 net.set_input_data("compare", compare);
328 outputs = net.execute();
330 auto out_data_false = outputs.at("condi").get_memory();
331 EXPECT_TRUE(is_output_equal(out_data_false, pooling_when_false_data));
338 TEST(condition_gpu, basic_stacked_ifs) {
351 const auto& engine = get_test_engine();
353 bs.set_option(build_option::optimize_data(true));
354 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 4, 1 } });
355 auto compare = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
356 auto compare2 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 2, 1 } });
359 topology condi_1_true = generate_simple_branch(true, "condi");
360 topology condi_1_false = generate_simple_branch(false, "condi");
361 topology condi_2_true;
363 activation("activ_when_true", "condi2", cldnn_activation_func::activation_log2)
365 topology condi_2_false;
367 activation("activ_when_false", "condi2", cldnn_activation_func::activation_relu)
372 input_layout("input", input.get_layout())
375 input_layout("compare", compare.get_layout())
378 condition("condi", "input", condi_1_true, condi_1_false, "compare", cond_functions::EQUAL)
381 input_layout("compare2", compare2.get_layout())
384 condition("condi2", "condi", condi_2_true, condi_2_false, "compare2", cond_functions::GREATER)
387 std::vector<float> input_data = {
390 std::vector<float> compare_data = {
393 std::vector<float> compare_2_data = {
396 set_values(input, input_data);
397 set_values(compare, compare_data);
398 set_values(compare2, compare_2_data);
400 network net(engine, topology, bs);
401 net.set_input_data("input", input);
402 net.set_input_data("compare", compare);
403 net.set_input_data("compare2", compare2);
404 auto outputs = net.execute();
406 auto out_data = outputs.at("condi2").get_memory();
407 EXPECT_TRUE(is_output_equal(out_data, {1.0f, 2.0f}));
410 TEST(condition_gpu, basic_nested_ifs) {
423 const auto& engine = get_test_engine();
425 bs.set_option(build_option::optimize_data(true));
426 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 4, 1 } });
427 auto compare = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
428 auto compare2 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 2, 1 } });
429 auto scale_5_mem = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
430 set_values(scale_5_mem, { 5.0f });
431 auto scale_10_mem = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
432 set_values(scale_10_mem, { 10.0f });
435 topology nested_true;
437 nested_true.add(scale("scale_5", "condi_nested", "scale_5_data"),
438 data("scale_5_data", scale_5_mem));
440 topology nested_false;
442 nested_false.add(scale("scale_10", "condi_nested", "scale_10_data"),
443 data("scale_10_data", scale_10_mem));
446 topology branch_true;
448 pooling("pooling_when_true", "condi", cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
451 input_layout("compare2", compare2.get_layout())
461 cond_functions::EQUAL)
464 topology branch_false;
466 pooling("pooling_when_false", "condi", cldnn::pooling_mode::average, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
471 input_layout("input", input.get_layout())
475 input_layout("compare", compare.get_layout())
479 condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL)
482 std::vector<float> input_data = {
483 1.0f, 2.0f, 3.0f, 4.0f
485 std::vector<float> compare_data = {
488 std::vector<float> compare_2_data = {
491 set_values(input, input_data);
492 set_values(compare, compare_data);
493 set_values(compare2, compare_2_data);
495 network net(engine, topology, bs);
496 net.set_input_data("input", input);
497 net.set_input_data("compare", compare);
498 net.set_input_data("compare2", compare2);
499 auto outputs = net.execute();
501 auto out_data = outputs.at("condi").get_memory();
502 EXPECT_TRUE(is_output_equal(out_data, { 10.0f, 20.0f }));
506 TEST(condition_gpu, negative_compare_wrong_layout) {
507 const auto& engine = get_test_engine();
509 bs.set_option(build_option::optimize_data(true));
510 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 4, 1 } });
511 auto compare = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 5, 1 } });
513 topology branch_true = generate_simple_branch(true, "condi");
514 topology branch_false = generate_simple_branch(false, "condi");
518 input_layout("input", input.get_layout())
521 input_layout("compare", compare.get_layout())
524 condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL)
527 EXPECT_ANY_THROW(network net(engine, topology, bs););
530 TEST(condition_gpu, negative_too_big_offset) {
531 const auto& engine = get_test_engine();
533 bs.set_option(build_option::optimize_data(true));
534 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 4, 1 } });
535 auto compare = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 3, 1 } });
537 topology branch_true = generate_simple_branch(true, "condi");
538 topology branch_false = generate_simple_branch(false, "condi");
542 input_layout("input", input.get_layout())
545 input_layout("compare", compare.get_layout())
548 condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL, {1, 1, 2, 1})
551 EXPECT_ANY_THROW(network net(engine, topology, bs););
554 TEST(condition_gpu, negative_not_same_layouts) {
555 const auto& engine = get_test_engine();
557 bs.set_option(build_option::optimize_data(true));
558 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 4, 1 } });
559 auto compare = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
561 topology branch_true;
563 pooling("pooling_when_true", "condi", cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
566 topology branch_false;
568 pooling("pooling_when_false", "condi", cldnn::pooling_mode::max, { 0, 0, 4, 1 }, { 0, 0, 4, 1 })
573 input_layout("input", input.get_layout())
576 input_layout("compare", compare.get_layout())
579 condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL)
582 EXPECT_ANY_THROW(network net(engine, topology, bs););
585 TEST(condition_gpu, negative_same_names_within_different_networks) {
586 const auto& engine = get_test_engine();
588 bs.set_option(build_option::optimize_data(true));
589 auto input = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 4, 1 } });
590 auto compare = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
592 topology branch_true;
594 pooling("pooling_check_name", "condi", cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
597 topology branch_false;
599 pooling("pooling_when_false", "condi", cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
604 input_layout("input", input.get_layout())
607 input_layout("compare", compare.get_layout())
610 condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL)
613 pooling("pooling_check_name", "condi", cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
616 EXPECT_ANY_THROW(network net(engine, topology, bs););