Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / tests / test_cases / condition_gpu_test.cpp
1 // Copyright (c) 2018 Intel Corporation
2 //
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
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14
15 ///////////////////////////////////////////////////////////////////////////////////////////////////
16 #include <gtest/gtest.h>
17
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"
30
31 #include <cstddef>
32
33
34 using namespace cldnn;
35 using namespace ::tests;
36
37
38 bool is_output_equal(const cldnn::memory& mem, const std::vector<float>& ref)
39 {
40     auto ptr = mem.pointer<float>();
41     for (size_t i = 0; i < mem.get_layout().count(); i++)
42     {
43         if (!are_equal(ptr[i], ref[i])) return false;
44     }
45     return true;
46 }
47
48 topology generate_simple_branch (bool branch_true_false, const primitive_id& input_id)
49 {
50     topology branch;
51     if (branch_true_false)
52     {
53         branch.add(
54             pooling(input_id + "_when_true", input_id, cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
55         );
56     }
57     else
58     {
59         branch.add(
60             pooling(input_id + "_when_false", input_id, cldnn::pooling_mode::average, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
61         );
62     }
63     return branch;
64 }
65
66
67 TEST(condition_gpu, basic_equal_comp) {
68     const auto& engine = get_test_engine();
69     build_options bs;
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 } });
74     
75     topology branch_true = generate_simple_branch(true, "condi");
76     topology branch_false = generate_simple_branch(false, "condi");
77
78     topology topology;
79     topology.add(
80         input_layout("input", input.get_layout())
81     );
82     topology.add(
83         input_layout("compare", compare.get_layout())
84     );    
85     topology.add(
86         input_layout("scale_data", scale_mem.get_layout())
87     );
88     topology.add(
89         condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL)
90     );  
91     topology.add(
92         scale("output", "condi", "scale_data")
93     );
94
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);
100
101     decltype(net.execute()) out;
102
103     //WHEN TRUE
104     set_values(compare, { 1.0f });
105     net.set_input_data("compare", compare);
106     out = net.execute();
107     auto out_data_true = out.at("output").get_memory();
108     EXPECT_TRUE(is_output_equal(out_data_true, {20.0f, 40.0f}));
109
110     //WHEN FALSE
111     set_values(compare, { 4.0f });
112     net.set_input_data("compare", compare);
113     out = net.execute();
114     auto out_data_false = out.at("output").get_memory();
115     EXPECT_TRUE(is_output_equal(out_data_false, { 15.0f, 35.0f }));
116
117 }
118
119 TEST(condition_gpu, basic_range_equal_comp) {
120
121     const auto& engine = get_test_engine();
122     build_options bs;
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 } });
126
127     auto compare = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 3, 1 } });
128
129     topology branch_true = generate_simple_branch(true, "condi");
130     topology branch_false = generate_simple_branch(false, "condi");
131
132     topology topology;
133     topology.add(
134         input_layout("input0", input0.get_layout())
135     );
136     topology.add(
137         input_layout("input1", input1.get_layout())
138     );
139     topology.add(
140         input_layout("compare", compare.get_layout())
141     );
142     topology.add(
143         concatenation("concat", { "input0", "input1" }, concatenation::along_x)
144     );
145     topology.add( 
146         condition("condi", "concat", branch_true, branch_false, "compare", cond_functions::EQUAL)
147     );
148
149     std::vector<float> input0_data = {
150         1, 2, 3, 4
151     };
152     std::vector<float> input1_data = {
153         5, 6, 7, 8
154     };
155     std::vector<float> compare_data_true = {
156         1, 2, 3
157     };
158     std::vector<float> pooling_when_true_data = {
159         2, 4, 6, 8
160     };
161     std::vector<float> compare_data_false = {
162         1, 2, 10
163     };
164     std::vector<float> pooling_when_false_data = {
165         1.5, 3.5, 5.5, 7.5
166     };
167
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);
173
174     decltype(net.execute()) outputs;
175
176     //CHECK TRUE
177     set_values(compare, compare_data_true);
178     net.set_input_data("compare", compare);
179     outputs = net.execute();
180
181     auto out_data_true = outputs.at("condi").get_memory();
182     EXPECT_TRUE(is_output_equal(out_data_true, pooling_when_true_data));
183
184     //CHECK FALSE
185     set_values(compare, compare_data_false);
186     net.set_input_data("compare", compare);
187     outputs = net.execute();
188
189     auto out_data_false = outputs.at("condi").get_memory();
190     EXPECT_TRUE(is_output_equal(out_data_false, pooling_when_false_data));
191 }
192
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)
194 {
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++)
199     {
200         for (int32_t f = 0; f < range.feature[0]; f++)
201         {
202             for (int32_t y = 0; y < range.spatial[1]; y++)
203             {
204                 for (int32_t x = 0; x < range.spatial[0]; x++)
205                 {
206                     auto linear_idx = generic_test::get_linear_index(
207                         input_lay,
208                         offset.batch[0] + b,
209                         offset.feature[0] + f,
210                         offset.spatial[1] + y,
211                         offset.spatial[0] + x,
212                         mem_desc);
213
214                     switch (func)
215                     {
216                     case cond_functions::EQUAL:
217                         ret_true.push_back(values.at(linear_idx));
218                         ret_false.push_back(-1.0f);
219                         break;
220                     case cond_functions::GREATER: 
221                         ret_true.push_back(values.at(linear_idx) - 1.0f);
222                         ret_false.push_back(99.0f);
223                         break;
224                     case cond_functions::LESS: 
225                         ret_true.push_back(values.at(linear_idx) + 1.0f);
226                         ret_false.push_back(-1.0f);
227                         break;
228                     }
229                 }
230             }
231         }
232     }
233     return { ret_true, ret_false };
234 }
235
236 TEST(DISABLED_condition_gpu, generic_test_true_false) {
237
238     const auto& engine = get_test_engine();
239     build_options bs;
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);
244
245     std::vector<cond_functions> functions = {
246         cond_functions::EQUAL,
247         cond_functions::GREATER,
248         cond_functions::LESS,
249     };
250
251     // ranges, with data when condition is true or false
252     std::vector<cldnn::tensor> ranges = {
253         {1, 1, 1, 1},
254         {1, 1, 3, 1},
255         {2, 1, 1, 1},
256         {2, 1, 1, 1}
257     };
258
259     std::vector<cldnn::tensor> offsets = {
260         { 0, 0, 0, 0},
261         { 0, 0, 1, 0},
262         { 0, 0, 2, 0},
263         { 2, 0, 0, 0},
264         { 2, 1, 1, 0}
265     };
266
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
271     };
272
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
277     };
278
279     for (auto const& func : functions)
280     {
281         for (auto const& range : ranges)
282         {
283             for (auto const& offset : offsets)
284             {
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;
288
289                 auto compare = memory::allocate(engine, { data_types::f32, format::bfyx, range });
290
291                 topology branch_true;
292                 topology branch_false;
293                 branch_true.add(
294                     pooling("pooling_when_true", "condi", cldnn::pooling_mode::max, { 1, 1, 3, 1 }, { 1, 1, 2, 1 })
295                 );
296                 branch_false.add(
297                     pooling("pooling_when_false", "condi", cldnn::pooling_mode::average, { 1, 1, 3, 1 }, { 1, 1, 2, 1 })
298                 );
299
300                 topology topology;
301                 topology.add(
302                     input_layout("input", input.get_layout())
303                 );
304                 topology.add(
305                     input_layout("compare", compare.get_layout())
306                 );
307                 topology.add(
308                     condition("condi", "input", branch_true, branch_false, "compare", func, offset)
309                 );
310
311                 set_values(input, input_data);
312                 network net(engine, topology, bs);
313                 net.set_input_data("input", input);
314
315                 decltype(net.execute()) outputs;
316
317                 //CHECK TRUE
318                 set_values(compare, comp_values_true);
319                 net.set_input_data("compare", compare);
320                 outputs = net.execute();
321
322                 auto out_data_true = outputs.at("condi").get_memory();
323                 EXPECT_TRUE(is_output_equal(out_data_true, pooling_when_true_data));
324
325                 //CHECK FALSE
326                 set_values(compare, comp_values_false);
327                 net.set_input_data("compare", compare);
328                 outputs = net.execute();
329
330                 auto out_data_false = outputs.at("condi").get_memory();
331                 EXPECT_TRUE(is_output_equal(out_data_false, pooling_when_false_data));
332
333             }
334         }
335     }
336 }
337
338 TEST(condition_gpu, basic_stacked_ifs) {
339
340     /*   
341         <prims...>
342         <if>
343         <...>
344         <end_if>
345         <...>
346         <if>
347         <...>
348         <end_if>
349         <prims...>    
350     */
351     const auto& engine = get_test_engine();
352     build_options bs;
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 } });
357
358
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;
362     condi_2_true.add(
363         activation("activ_when_true", "condi2", cldnn_activation_func::activation_log2)
364     );
365     topology condi_2_false;
366     condi_2_false.add(
367         activation("activ_when_false", "condi2", cldnn_activation_func::activation_relu)
368     );
369
370     topology topology;
371     topology.add(
372         input_layout("input", input.get_layout())
373     );
374     topology.add(
375         input_layout("compare", compare.get_layout())
376     );
377     topology.add(
378         condition("condi", "input", condi_1_true, condi_1_false, "compare", cond_functions::EQUAL)
379     );
380     topology.add(
381         input_layout("compare2", compare2.get_layout())
382     );
383     topology.add(
384         condition("condi2", "condi", condi_2_true, condi_2_false, "compare2", cond_functions::GREATER)
385     );
386
387     std::vector<float> input_data = {
388         1, 2, 3, 4
389     };
390     std::vector<float> compare_data = {
391         1
392     };
393     std::vector<float> compare_2_data = {
394         0.0f, 0.0f
395     };
396     set_values(input, input_data);
397     set_values(compare, compare_data);
398     set_values(compare2, compare_2_data);
399
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();
405
406     auto out_data = outputs.at("condi2").get_memory();
407     EXPECT_TRUE(is_output_equal(out_data, {1.0f, 2.0f}));
408 }
409
410 TEST(condition_gpu, basic_nested_ifs) {
411
412     /*
413     <prims...>
414     <if 0>
415     <...>
416     <if 1>
417     <...>
418     <end_if 1>
419     <...>
420     <end_if 0>
421     <prims...>
422     */
423     const auto& engine = get_test_engine();
424     build_options bs;
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 });
433
434
435     topology nested_true;
436     {
437         nested_true.add(scale("scale_5", "condi_nested", "scale_5_data"),
438             data("scale_5_data", scale_5_mem));
439     }
440     topology nested_false;
441     {
442         nested_false.add(scale("scale_10", "condi_nested", "scale_10_data"),
443             data("scale_10_data", scale_10_mem));
444     }
445
446     topology branch_true;
447     branch_true.add(
448         pooling("pooling_when_true", "condi", cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
449     );
450     branch_true.add(
451         input_layout("compare2", compare2.get_layout())
452     );
453
454     branch_true.add(
455         condition(
456         "condi_nested",
457         "pooling_when_true",
458         nested_true,
459         nested_false,
460         "compare2",
461         cond_functions::EQUAL)
462     );
463
464     topology branch_false;
465     branch_false.add(
466         pooling("pooling_when_false", "condi", cldnn::pooling_mode::average, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
467     );
468
469     topology topology;
470     topology.add(
471         input_layout("input", input.get_layout())
472     );
473
474     topology.add(
475         input_layout("compare", compare.get_layout())
476     );
477
478     topology.add(
479         condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL)
480     );
481
482     std::vector<float> input_data = {
483         1.0f, 2.0f, 3.0f, 4.0f
484     };
485     std::vector<float> compare_data = {
486         1.0f
487     };
488     std::vector<float> compare_2_data = {
489         2.0f, 4.0f
490     };
491     set_values(input, input_data);
492     set_values(compare, compare_data);
493     set_values(compare2, compare_2_data);
494
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();
500
501     auto out_data = outputs.at("condi").get_memory();
502     EXPECT_TRUE(is_output_equal(out_data, { 10.0f, 20.0f }));
503 }
504
505
506 TEST(condition_gpu, negative_compare_wrong_layout) {
507     const auto& engine = get_test_engine();
508     build_options bs;
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 } });
512
513     topology branch_true = generate_simple_branch(true, "condi");
514     topology branch_false = generate_simple_branch(false, "condi");
515
516     topology topology;
517     topology.add(
518         input_layout("input", input.get_layout())
519     );
520     topology.add(
521         input_layout("compare", compare.get_layout())
522     );
523     topology.add(
524         condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL)
525     );
526
527     EXPECT_ANY_THROW(network net(engine, topology, bs););
528 }
529
530 TEST(condition_gpu, negative_too_big_offset) {
531     const auto& engine = get_test_engine();
532     build_options bs;
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 } });
536
537     topology branch_true = generate_simple_branch(true, "condi");
538     topology branch_false = generate_simple_branch(false, "condi");
539
540     topology topology;
541     topology.add(
542         input_layout("input", input.get_layout())
543     );
544     topology.add(
545         input_layout("compare", compare.get_layout())
546     );
547     topology.add(
548         condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL, {1, 1, 2, 1})
549     );
550
551     EXPECT_ANY_THROW(network net(engine, topology, bs););
552 }
553
554 TEST(condition_gpu, negative_not_same_layouts) {
555     const auto& engine = get_test_engine();
556     build_options bs;
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 } });
560     
561     topology branch_true;
562     branch_true.add(
563         pooling("pooling_when_true", "condi", cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
564     );
565
566     topology branch_false;
567     branch_false.add(
568         pooling("pooling_when_false", "condi", cldnn::pooling_mode::max, { 0, 0, 4, 1 }, { 0, 0, 4, 1 })
569     );
570
571     topology topology;
572     topology.add(
573         input_layout("input", input.get_layout())
574     );
575     topology.add(
576         input_layout("compare", compare.get_layout())
577     );
578     topology.add(
579         condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL)
580     );
581
582     EXPECT_ANY_THROW(network net(engine, topology, bs););
583 }
584
585 TEST(condition_gpu, negative_same_names_within_different_networks) {
586     const auto& engine = get_test_engine();
587     build_options bs;
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 } });
591
592     topology branch_true;
593     branch_true.add(
594         pooling("pooling_check_name", "condi", cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
595     );
596
597     topology branch_false;
598     branch_false.add(
599         pooling("pooling_when_false", "condi", cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
600     );
601
602     topology topology;
603     topology.add(
604         input_layout("input", input.get_layout())
605     );
606     topology.add(
607         input_layout("compare", compare.get_layout())
608     );
609     topology.add(
610         condition("condi", "input", branch_true, branch_false, "compare", cond_functions::EQUAL)
611     );
612     topology.add(
613         pooling("pooling_check_name", "condi", cldnn::pooling_mode::max, { 0, 0, 2, 1 }, { 0, 0, 2, 1 })
614     );
615     
616     EXPECT_ANY_THROW(network net(engine, topology, bs););
617 }