blob: 1219ac5a33bd2b37baeb66e25ae8291f18681f99 [file] [log] [blame]
David Monahan005288d2019-05-14 10:42:38 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
David Monahan005288d2019-05-14 10:42:38 +01006
Sadik Armagana097d2a2021-11-24 15:47:28 +00007#include <CommonTestUtils.hpp>
David Monahan005288d2019-05-14 10:42:38 +01008
Jan Eilersbb446e52020-04-02 13:56:54 +01009#include <Graph.hpp>
10#include <Network.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010011#include <SubgraphViewSelector.hpp>
12
Francis Murtagha49ff082022-01-17 17:08:01 +000013#include <armnn/backends/OptimizationViews.hpp>
14#include <armnn/backends/SubgraphView.hpp>
15#include <armnn/utility/PolymorphicDowncast.hpp>
Cathal Corbett3464ba12022-03-04 11:36:39 +000016#include <armnnTestUtils/MockBackend.hpp>
Francis Murtagha49ff082022-01-17 17:08:01 +000017
Sadik Armagan1625efc2021-06-10 18:24:34 +010018#include <doctest/doctest.h>
Jan Eilersbb446e52020-04-02 13:56:54 +010019
David Monahan005288d2019-05-14 10:42:38 +010020using namespace armnn;
21
David Monahan41f00f12019-05-27 09:44:52 +010022void CheckLayers(Graph& graph)
23{
24 unsigned int m_inputLayerCount = 0, m_outputLayerCount = 0, m_addLayerCount = 0;
25 for(auto layer : graph)
26 {
27 switch(layer->GetType())
28 {
29 case LayerType::Input:
30 ++m_inputLayerCount;
Sadik Armagan1625efc2021-06-10 18:24:34 +010031 CHECK((layer->GetName() == std::string("inLayer0") ||
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +000032 layer->GetName() == std::string("inLayer1")));
David Monahan41f00f12019-05-27 09:44:52 +010033 break;
34 // The Addition layer should become a PreCompiled Layer after Optimisation
35 case LayerType::PreCompiled:
36 ++m_addLayerCount;
Sadik Armagan1625efc2021-06-10 18:24:34 +010037 CHECK(std::string(layer->GetName()) == "pre-compiled");
David Monahan41f00f12019-05-27 09:44:52 +010038 break;
39 case LayerType::Output:
40 ++m_outputLayerCount;
Sadik Armagan1625efc2021-06-10 18:24:34 +010041 CHECK(std::string(layer->GetName()) == "outLayer");
David Monahan41f00f12019-05-27 09:44:52 +010042 break;
43 default:
44 //Fail for anything else
Sadik Armagan1625efc2021-06-10 18:24:34 +010045 CHECK(false);
David Monahan41f00f12019-05-27 09:44:52 +010046 }
47 }
Sadik Armagan1625efc2021-06-10 18:24:34 +010048 CHECK(m_inputLayerCount == 2);
49 CHECK(m_outputLayerCount == 1);
50 CHECK(m_addLayerCount == 1);
David Monahan41f00f12019-05-27 09:44:52 +010051}
52
Sadik Armagan1625efc2021-06-10 18:24:34 +010053TEST_SUITE("OptimizationViewsTestSuite")
54{
55TEST_CASE("OptimizedViewsSubgraphLayerCount")
David Monahan005288d2019-05-14 10:42:38 +010056{
57 OptimizationViews view;
58 // Construct a graph with 3 layers
Cathal Corbettcbfd7182021-12-15 17:12:59 +000059 Graph baseGraph;
David Monahan005288d2019-05-14 10:42:38 +010060
61 Layer* const inputLayer = baseGraph.AddLayer<InputLayer>(0, "input");
62
63 Convolution2dDescriptor convDescriptor;
64 PreCompiledDescriptor substitutionLayerDescriptor(1, 1);
65 Layer* const convLayer1 = baseGraph.AddLayer<Convolution2dLayer>(convDescriptor, "conv1");
66 Layer* const convLayer2 = baseGraph.AddLayer<Convolution2dLayer>(convDescriptor, "conv2");
67 Layer* const substitutableCompiledLayer =
68 baseGraph.AddLayer<PreCompiledLayer>(substitutionLayerDescriptor, "pre-compiled");
69
70 Layer* const outputLayer = baseGraph.AddLayer<OutputLayer>(0, "output");
71
72 inputLayer->GetOutputSlot(0).Connect(convLayer1->GetInputSlot(0));
73 convLayer1->GetOutputSlot(0).Connect(convLayer2->GetInputSlot(0));
74 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
75
76 // Subgraph for a failed layer
77 SubgraphViewSelector::SubgraphViewPtr failedSubgraph =
78 CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
79 CreateOutputsFrom({convLayer1}),
80 {convLayer1});
81 // Subgraph for an untouched layer
82 SubgraphViewSelector::SubgraphViewPtr untouchedSubgraph =
83 CreateSubgraphViewFrom(CreateInputsFrom({convLayer2}),
84 CreateOutputsFrom({convLayer2}),
85 {convLayer2});
86 // Subgraph for a substitutable layer
87 SubgraphViewSelector::SubgraphViewPtr substitutableSubgraph =
88 CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
89 CreateOutputsFrom({convLayer2}),
90 {substitutableCompiledLayer});
91 // Create a Graph containing a layer to substitute in
92 Graph substitutableGraph;
93 Layer* const substitutionpreCompiledLayer =
94 substitutableGraph.AddLayer<PreCompiledLayer>(substitutionLayerDescriptor, "pre-compiled");
95
96 // Subgraph for a substitution layer
97 SubgraphViewSelector::SubgraphViewPtr substitutionSubgraph =
98 CreateSubgraphViewFrom(CreateInputsFrom({substitutionpreCompiledLayer}),
99 CreateOutputsFrom({substitutionpreCompiledLayer}),
100 {substitutionpreCompiledLayer});
101
102 // Sub in the graph
103 baseGraph.SubstituteSubgraph(*substitutableSubgraph, *substitutionSubgraph);
104
105 view.AddFailedSubgraph(SubgraphView(*failedSubgraph));
106 view.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
107
108 SubgraphViewSelector::SubgraphViewPtr baseSubgraph =
109 CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
110 CreateOutputsFrom({convLayer2}),
111 {substitutionpreCompiledLayer});
112 view.AddSubstitution({*baseSubgraph, *substitutionSubgraph});
113
114 // Construct original subgraph to compare against
115 SubgraphViewSelector::SubgraphViewPtr originalSubgraph =
116 CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
117 CreateOutputsFrom({convLayer2}),
118 {convLayer1, convLayer2, substitutionpreCompiledLayer});
119
Sadik Armagan1625efc2021-06-10 18:24:34 +0100120 CHECK(view.Validate(*originalSubgraph));
David Monahan005288d2019-05-14 10:42:38 +0100121}
122
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000123
124TEST_CASE("OptimizedViewsSubgraphLayerCountUsingGetINetwork")
125{
126 OptimizationViews view;
127
128 IConnectableLayer* const inputLayer = view.GetINetwork()->AddInputLayer(0, "input");
129
130 DepthwiseConvolution2dDescriptor convDescriptor;
Cathal Corbett06902652022-04-14 17:55:11 +0100131 PreCompiledDescriptor substitutionLayerDescriptor(2, 1);
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000132 CompiledBlobPtr blobPtr;
133 BackendId backend = Compute::CpuRef;
134
135 Layer* convLayer1 = PolymorphicDowncast<Layer*>(
136 view.GetINetwork()->AddDepthwiseConvolution2dLayer(convDescriptor,
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000137 "conv1"));
138
139 Layer* convLayer2 = PolymorphicDowncast<Layer*>(
140 view.GetINetwork()->AddDepthwiseConvolution2dLayer(convDescriptor,
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000141 "conv2"));
142
143 IConnectableLayer* const outputLayer = view.GetINetwork()->AddOutputLayer(0, "output");
144
145 inputLayer->GetOutputSlot(0).Connect(convLayer1->GetInputSlot(0));
146 convLayer1->GetOutputSlot(0).Connect(convLayer2->GetInputSlot(0));
147 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
148
149 // Subgraph for a failed layer
150 SubgraphViewSelector::SubgraphViewPtr failedSubgraph = CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
151 CreateOutputsFrom({convLayer1}),
152 {convLayer1});
153 // Subgraph for an untouched layer
154 SubgraphViewSelector::SubgraphViewPtr untouchedSubgraph = CreateSubgraphViewFrom(CreateInputsFrom({convLayer2}),
155 CreateOutputsFrom({convLayer2}),
156 {convLayer2});
157
158 // Create a Network containing a layer to substitute in
159 NetworkImpl net;
160 Layer* substitutionpreCompiledLayer = PolymorphicDowncast<Layer*>(
Cathal Corbett3ea01072022-01-06 10:29:43 +0000161 net.AddPrecompiledLayer(substitutionLayerDescriptor, std::move(blobPtr), backend));
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000162
163 // Subgraph for a substitution layer
164 SubgraphViewSelector::SubgraphViewPtr substitutionSubgraph =
165 CreateSubgraphViewFrom(CreateInputsFrom({substitutionpreCompiledLayer}),
166 CreateOutputsFrom({substitutionpreCompiledLayer}),
167 {substitutionpreCompiledLayer});
168
169 view.AddFailedSubgraph(SubgraphView(*failedSubgraph));
170 view.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
171
172 SubgraphViewSelector::SubgraphViewPtr baseSubgraph = CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
173 CreateOutputsFrom({convLayer2}),
174 {substitutionpreCompiledLayer});
175 view.AddSubstitution({*baseSubgraph, *substitutionSubgraph});
176
177 // Construct original subgraph to compare against
178 SubgraphViewSelector::SubgraphViewPtr originalSubgraph =
179 CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
180 CreateOutputsFrom({convLayer2}),
181 {convLayer1, convLayer2, substitutionpreCompiledLayer});
182
183 CHECK(view.Validate(*originalSubgraph));
184}
185
Sadik Armagan1625efc2021-06-10 18:24:34 +0100186TEST_CASE("OptimizedViewsSubgraphLayerCountFailValidate")
David Monahan005288d2019-05-14 10:42:38 +0100187{
188 OptimizationViews view;
189 // Construct a graph with 3 layers
Cathal Corbettcbfd7182021-12-15 17:12:59 +0000190 Graph baseGraph;
David Monahan005288d2019-05-14 10:42:38 +0100191
192 Layer* const inputLayer = baseGraph.AddLayer<InputLayer>(0, "input");
193
194 Convolution2dDescriptor convDescriptor;
195 PreCompiledDescriptor substitutionLayerDescriptor(1, 1);
196 Layer* const convLayer1 = baseGraph.AddLayer<Convolution2dLayer>(convDescriptor, "conv1");
197 Layer* const convLayer2 = baseGraph.AddLayer<Convolution2dLayer>(convDescriptor, "conv2");
198 Layer* const substitutableCompiledLayer =
199 baseGraph.AddLayer<PreCompiledLayer>(substitutionLayerDescriptor, "pre-compiled");
200
201 Layer* const outputLayer = baseGraph.AddLayer<OutputLayer>(0, "output");
202
203 inputLayer->GetOutputSlot(0).Connect(convLayer1->GetInputSlot(0));
204 convLayer1->GetOutputSlot(0).Connect(convLayer2->GetInputSlot(0));
205 convLayer2->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
206
207 // Subgraph for an untouched layer
208 SubgraphViewSelector::SubgraphViewPtr untouchedSubgraph =
209 CreateSubgraphViewFrom(CreateInputsFrom({convLayer2}),
210 CreateOutputsFrom({convLayer2}),
211 {convLayer2});
212 // Subgraph for a substitutable layer
213 SubgraphViewSelector::SubgraphViewPtr substitutableSubgraph =
214 CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
215 CreateOutputsFrom({convLayer2}),
216 {substitutableCompiledLayer});
217 // Create a Graph containing a layer to substitute in
218 Graph substitutableGraph;
219 Layer* const substitutionpreCompiledLayer =
220 substitutableGraph.AddLayer<PreCompiledLayer>(substitutionLayerDescriptor, "pre-compiled");
221
222 // Subgraph for a substitution layer
223 SubgraphViewSelector::SubgraphViewPtr substitutionSubgraph =
224 CreateSubgraphViewFrom(CreateInputsFrom({substitutionpreCompiledLayer}),
225 CreateOutputsFrom({substitutionpreCompiledLayer}),
226 {substitutionpreCompiledLayer});
227
228 // Sub in the graph
229 baseGraph.SubstituteSubgraph(*substitutableSubgraph, *substitutionSubgraph);
230
231 view.AddUntouchedSubgraph(SubgraphView(*untouchedSubgraph));
232
233 SubgraphViewSelector::SubgraphViewPtr baseSubgraph =
234 CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
235 CreateOutputsFrom({convLayer2}),
236 {substitutionpreCompiledLayer});
237 view.AddSubstitution({*baseSubgraph, *substitutionSubgraph});
238
239 // Construct original subgraph to compare against
240 SubgraphViewSelector::SubgraphViewPtr originalSubgraph =
241 CreateSubgraphViewFrom(CreateInputsFrom({convLayer1}),
242 CreateOutputsFrom({convLayer2}),
243 {convLayer1, convLayer2, substitutionpreCompiledLayer});
244
245 // Validate should fail as convLayer1 is not counted
Sadik Armagan1625efc2021-06-10 18:24:34 +0100246 CHECK(!view.Validate(*originalSubgraph));
David Monahan005288d2019-05-14 10:42:38 +0100247}
248
Sadik Armagan1625efc2021-06-10 18:24:34 +0100249TEST_CASE("OptimizeViewsValidateDeviceMockBackend")
David Monahan41f00f12019-05-27 09:44:52 +0100250{
251 // build up the structure of the network
252 armnn::INetworkPtr net(armnn::INetwork::Create());
253
254 armnn::IConnectableLayer* input = net->AddInputLayer(0, "inLayer0");
255 armnn::IConnectableLayer* input1 = net->AddInputLayer(1, "inLayer1");
256
257 armnn::IConnectableLayer* addition = net->AddAdditionLayer("addLayer");
258
259 armnn::IConnectableLayer* output = net->AddOutputLayer(0, "outLayer");
260
261 input->GetOutputSlot(0).Connect(addition->GetInputSlot(0));
262 input1->GetOutputSlot(0).Connect(addition->GetInputSlot(1));
263 addition->GetOutputSlot(0).Connect(output->GetInputSlot(0));
264
265 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
266 input1->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
267 addition->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
268
David Monahanc1536d62020-02-12 15:52:35 +0000269 armnn::MockBackendInitialiser initialiser;
David Monahan41f00f12019-05-27 09:44:52 +0100270 armnn::IRuntime::CreationOptions options;
271 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
272
273 std::vector<armnn::BackendId> backends = { MockBackend().GetIdStatic() };
274 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec());
Sadik Armagan1625efc2021-06-10 18:24:34 +0100275 CHECK(optNet);
David Monahan41f00f12019-05-27 09:44:52 +0100276
277 // Check the optimised graph
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000278 armnn::Graph& graph = GetGraphForTesting(optNet.get());
279 CheckLayers(graph);
David Monahan41f00f12019-05-27 09:44:52 +0100280}
281
Sadik Armagan1625efc2021-06-10 18:24:34 +0100282}