2 // Copyright (c) 2018 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.
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
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"
29 using namespace cldnn;
30 using namespace tests;
33 This set of tests has been designed to check the correctness of trim_to_outputs optimization pass
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
40 Network structure: input -> conv1 (output)
42 ---> conv2 (to be eliminated)
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
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 } });
54 set_values(input, { 1.1f });
55 set_values(weights, { 2.1f });
56 set_values(bias, { 1.6f });
58 std::vector<float> out_data = { 3.91f };
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" }));
67 network network(engine, topology, build_opt);
68 network.set_input_data("input", input);
69 auto outputs = network.execute();
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
75 for (auto& it : outputs)
77 auto output_ptr = it.second.get_memory().pointer<float>();
78 for (size_t cntr = 0; cntr < out_data.size(); cntr++)
80 EXPECT_NEAR(output_ptr[cntr], out_data[cntr], 1e-4);
82 EXPECT_EQ(it.first, "conv1");
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
89 Network structure: input -> conv1 (output)
91 ---> conv2 (to be eliminated along with its weights and bias)
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
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 } });
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 });
111 std::vector<float> out_data = { 3.91f };
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" }));
122 network network(engine, topology, build_opt);
123 network.set_input_data("input", input);
124 auto outputs = network.execute();
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
130 for (auto& it : outputs)
132 auto output_ptr = it.second.get_memory().pointer<float>();
134 for (size_t cntr = 0; cntr < out_data.size(); cntr++)
136 EXPECT_NEAR(output_ptr[cntr], out_data[cntr], 1e-4);
138 EXPECT_EQ(it.first, "conv1");
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
145 Network structure: input ---> conv1 --- ---> conv4 (output)
147 ---> conv2 ---> conv3
148 Convolutions conv2, conv3 should be optimized out along with weights23 shered by conv2 and conv3.
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
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 } });
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 });
168 std::vector<float> out_data = { 9.42f };
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" }));
181 network network(engine, topology, build_opt);
182 network.set_input_data("input", input);
183 auto outputs = network.execute();
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
189 for (auto& it : outputs)
191 auto output_ptr = it.second.get_memory().pointer<float>();
193 for (size_t cntr = 0; cntr < out_data.size(); cntr++)
195 EXPECT_NEAR(output_ptr[cntr], out_data[cntr], 1e-4);
197 EXPECT_EQ(it.first, "conv4");