Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / tests / test_cases / trim_to_outputs_gpu_test.cpp
1 /*
2 // Copyright (c) 2018 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 ///////////////////////////////////////////////////////////////////////////////////////////////////
18
19 #include <gtest/gtest.h>
20 #include "api/CPP/memory.hpp"
21 #include <api/CPP/input_layout.hpp>
22 #include "api/CPP/concatenation.hpp"
23 #include <api/CPP/topology.hpp>
24 #include <api/CPP/network.hpp>
25 #include <api/CPP/engine.hpp>
26 #include <api/CPP/data.hpp>
27 #include "test_utils/test_utils.h"
28
29 using namespace cldnn;
30 using namespace tests;
31
32 /*
33     This set of tests has been designed to check the correctness of trim_to_outputs optimization pass
34 */
35
36
37 /*
38    In this test we check if the convolution conv2 will be eliminated from the network. This is expected to be done in trim_to_outputs optimization pass
39
40    Network structure:  input  -> conv1 (output)
41                            \
42                             ---> conv2 (to be eliminated)
43 */
44 TEST(trim_to_outputs, one_node_to_eliminate_case1) {
45     const auto& engine = get_test_engine();
46     build_options build_opt;
47     build_opt.set_option(cldnn::build_option::outputs({ "conv1" }));
48     build_opt.set_option(build_option::optimize_data(false));             // to avoid adding reorders
49
50     auto input = memory::allocate(engine, { data_types::f32, format::yxfb, { 1, 1, 1, 1 } });
51     auto weights = memory::allocate(engine, { data_types::f32, format::bfyx, { 1, 1, 1, 1 } });
52     auto bias = memory::allocate(engine, { data_types::f32, format::bfyx, { 1, 1, 1, 1 } });
53
54     set_values(input, { 1.1f });
55     set_values(weights, { 2.1f });
56     set_values(bias, { 1.6f });
57
58     std::vector<float> out_data = { 3.91f };
59
60     topology topology;
61     topology.add(input_layout("input", input.get_layout()));
62     topology.add(data("weights", weights));
63     topology.add(data("bias", bias));
64     topology.add(cldnn::convolution("conv1", { "input" }, { "weights" }, { "bias" }));
65     topology.add(cldnn::convolution("conv2", { "input" }, { "weights" }, { "bias" }));
66
67     network network(engine, topology, build_opt);
68     network.set_input_data("input", input);
69     auto outputs = network.execute();
70
71     EXPECT_EQ(outputs.size(), (size_t)1); // there is only one output
72     EXPECT_EQ(network.get_executed_primitives().size(), (size_t)2);   // input and conv1 where executed
73     EXPECT_EQ(network.get_all_primitive_ids().size(), (size_t)4);     // also bias and weights still exist
74
75     for (auto& it : outputs)
76     {
77         auto output_ptr = it.second.get_memory().pointer<float>();
78         for (size_t cntr = 0; cntr < out_data.size(); cntr++)
79         {
80             EXPECT_NEAR(output_ptr[cntr], out_data[cntr], 1e-4);
81         }
82         EXPECT_EQ(it.first, "conv1");
83     }
84 }
85
86 /*
87 in this test we check if the convolution conv2 will be eliminated from the network. This is expected to be done in trim_to_outputs optimization pass
88
89 Network structure:  input  -> conv1 (output)
90                         \
91                          ---> conv2 (to be eliminated along with its weights and bias)
92 */
93 TEST(trim_to_outputs, one_node_to_eliminate_case2) {
94     const auto& engine = get_test_engine();
95     build_options build_opt;
96     build_opt.set_option(cldnn::build_option::outputs({ "conv1" }));
97     build_opt.set_option(build_option::optimize_data(false));             // to avoid adding reorders
98
99     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 1, 1 } });
100     auto weights1 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
101     auto weights2 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
102     auto bias1 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
103     auto bias2 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
104
105     set_values(input, { 1.1f });
106     set_values(weights1, { 2.1f });
107     set_values(bias1, { 1.6f });
108     set_values(weights2, { 0.3f });
109     set_values(bias2, { 0.2f });
110
111     std::vector<float> out_data = { 3.91f };
112
113     topology topology;
114     topology.add(input_layout("input", input.get_layout()));
115     topology.add(data("weights1", weights1));
116     topology.add(data("bias1", bias1));
117     topology.add(cldnn::convolution("conv1", { "input" }, { "weights1" }, { "bias1" }));
118     topology.add(data("weights2", weights2));
119     topology.add(data("bias2", bias2));
120     topology.add(cldnn::convolution("conv2", { "input" }, { "weights2" }, { "bias2" }));
121
122     network network(engine, topology, build_opt);
123     network.set_input_data("input", input);
124     auto outputs = network.execute();
125
126     EXPECT_EQ(outputs.size(), (size_t)1); // there is only one output
127     EXPECT_EQ(network.get_executed_primitives().size(), (size_t)2);   // input and conv1 where executed
128     EXPECT_EQ(network.get_all_primitive_ids().size(), (size_t)4);     // also bias1 and weights1 still exist
129
130     for (auto& it : outputs)
131     {
132         auto output_ptr = it.second.get_memory().pointer<float>();
133
134         for (size_t cntr = 0; cntr < out_data.size(); cntr++)
135         {
136             EXPECT_NEAR(output_ptr[cntr], out_data[cntr], 1e-4);
137         }
138         EXPECT_EQ(it.first, "conv1");
139     }
140 }
141
142 /*
143 in this test we check if the convolution conv2 will be eliminated from the network. This is expected to be done in trim_to_outputs optimization pass
144
145 Network structure:  input ---> conv1 --- ---> conv4 (output)
146                         \
147                          --->  conv2  ---> conv3
148 Convolutions conv2, conv3 should be optimized out along with weights23 shered by conv2 and conv3.
149 */
150 TEST(trim_to_outputs, two_nodes_to_eliminate_case1) {
151     const auto& engine = get_test_engine();
152     build_options build_opt;
153     build_opt.set_option(cldnn::build_option::outputs({ "conv4" }));
154     build_opt.set_option(build_option::optimize_data(false));             // to avoid adding reorders
155
156     auto input = memory::allocate(engine, { data_types::f32, format::yxfb,{ 1, 1, 1, 1 } });
157     auto weights1 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
158     auto weights23 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
159     auto weights4 = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
160     auto bias = memory::allocate(engine, { data_types::f32, format::bfyx,{ 1, 1, 1, 1 } });
161
162     set_values(input, { 1.1f });
163     set_values(weights1, { 2.1f });
164     set_values(weights23, { 3.0f });
165     set_values(weights4, { 2.0f });
166     set_values(bias, { 1.6f });
167
168     std::vector<float> out_data = { 9.42f };
169
170     topology topology;
171     topology.add(input_layout("input", input.get_layout()));
172     topology.add(data("weights1", weights1));
173     topology.add(data("bias", bias));
174     topology.add(cldnn::convolution("conv1", { "input" }, { "weights1" }, { "bias" }));
175     topology.add(data("weights23", weights23));
176     topology.add(cldnn::convolution("conv2", { "input" }, { "weights23" }, { "bias" }));
177     topology.add(cldnn::convolution("conv3", { "conv2" }, { "weights23" }, { "bias" }));
178     topology.add(data("weights4", weights4));
179     topology.add(cldnn::convolution("conv4", { "conv1" }, { "weights4" }, { "bias" }));
180
181     network network(engine, topology, build_opt);
182     network.set_input_data("input", input);
183     auto outputs = network.execute();
184
185     EXPECT_EQ(outputs.size(), (size_t)1); // there is only one output
186     EXPECT_EQ(network.get_executed_primitives().size(), (size_t)3);   // input, conv1 and conv4  where executed
187     EXPECT_EQ(network.get_all_primitive_ids().size(), (size_t)6);     // also bias weights1 and weights4 still exist
188
189     for (auto& it : outputs)
190     {
191         auto output_ptr = it.second.get_memory().pointer<float>();
192
193         for (size_t cntr = 0; cntr < out_data.size(); cntr++)
194         {
195             EXPECT_NEAR(output_ptr[cntr], out_data[cntr], 1e-4);
196         }
197         EXPECT_EQ(it.first, "conv4");
198     }
199 }
200