blob: 2c74690e6e16b4ff1c8a366bb10e17a92895fba9 [file] [log] [blame]
Aron Virginas-Tar70104002018-10-24 15:33:28 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +00006#include <Graph.hpp>
7#include <Network.hpp>
8
9#include <reference/RefWorkloadFactory.hpp>
Aron Virginas-Tar70104002018-10-24 15:33:28 +010010
Sadik Armagan1625efc2021-06-10 18:24:34 +010011#include <doctest/doctest.h>
Aron Virginas-Tar70104002018-10-24 15:33:28 +010012
Sadik Armagan1625efc2021-06-10 18:24:34 +010013TEST_SUITE("OptimizedNetwork")
14{
15TEST_CASE("SerializeToDot")
Aron Virginas-Tar70104002018-10-24 15:33:28 +010016{
Francis Murtagh3d2b4b22021-02-15 18:23:17 +000017 // build up the structure of the network
18 armnn::INetworkPtr net(armnn::INetwork::Create());
Aron Virginas-Tar70104002018-10-24 15:33:28 +010019
20 //Defines layers.
Francis Murtagh3d2b4b22021-02-15 18:23:17 +000021 auto input = net->AddInputLayer(0);
22 auto add = net->AddAdditionLayer();
23 auto output = net->AddOutputLayer(0);
Aron Virginas-Tar70104002018-10-24 15:33:28 +010024
25 // Connects layers.
26 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
27 input->GetOutputSlot(0).Connect(add->GetInputSlot(1));
28 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
29
30 armnn::TensorShape shape({4});
31 armnn::TensorInfo info(shape, armnn::DataType::Float32);
32 input->GetOutputSlot(0).SetTensorInfo(info);
33 add->GetOutputSlot(0).SetTensorInfo(info);
34
35 armnn::IRuntime::CreationOptions options;
36 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
37
38 std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef};
Francis Murtagh3d2b4b22021-02-15 18:23:17 +000039 armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec());
Aron Virginas-Tar70104002018-10-24 15:33:28 +010040
41 std::ostringstream ss;
42 optimizedNet->SerializeToDot(ss);
43
44 auto inputId = input->GetGuid();
45 auto addId = add->GetGuid();
46 auto outputId = output->GetGuid();
47
48 std::stringstream expected;
49 expected <<
50 "digraph Optimized {\n"
51 " node [shape=\"record\"];\n"
52 " edge [fontsize=8 fontcolor=\"blue\" fontname=\"arial-bold\"];\n"
Rob Hughesb17220d2020-08-28 11:48:35 +010053 " " << inputId << " [label=\"{Input|Guid : " << inputId << "\\lLayerType : Input\\l"
54 "BackendID : CpuRef\\l}\"];\n"
55 " " << addId << " [label=\"{Addition|Guid : " << addId << "\\lLayerType : Addition\\l"
56 "BackendID : CpuRef\\l}\"];\n"
57 " " << outputId << " [label=\"{Output|Guid : " << outputId << "\\lLayerType : Output\\l"
58 "BackendID : CpuRef\\l}\"];\n"
Aron Virginas-Tar70104002018-10-24 15:33:28 +010059 " " << inputId << " -> " << addId << " [label=< [4] >];\n"
60 " " << inputId << " -> " << addId << " [label=< [4] >];\n"
61 " " << addId << " -> " << outputId << " [label=< [4] >];\n"
62 "}\n";
63
Sadik Armagan1625efc2021-06-10 18:24:34 +010064 CHECK(ss.str() == expected.str());
Aron Virginas-Tar70104002018-10-24 15:33:28 +010065}
66
Sadik Armagan1625efc2021-06-10 18:24:34 +010067TEST_CASE("OptimizeValidateDeviceNonSupportLayerNoFallback")
Aron Virginas-Tar70104002018-10-24 15:33:28 +010068{
69 // build up the structure of the network
70 armnn::INetworkPtr net(armnn::INetwork::Create());
71
72 armnn::IConnectableLayer* input = net->AddInputLayer(0);
73
74 // This layer configuration isn't supported by CpuAcc and isn't allowed to fall back, so Optimize will return null.
75 armnn::NormalizationDescriptor descriptor;
76 armnn::IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
77
78 armnn::IConnectableLayer* output = net->AddOutputLayer(0);
79
80 input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
81 normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
82
83 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
84 normalize->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
85
86 armnn::IRuntime::CreationOptions options;
87 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
88
89 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc };
Mike Kelly3a613cc2020-09-29 20:50:35 +010090 std::vector<std::string> errMessages;
91
92 try
93 {
94 Optimize(*net, backends, runtime->GetDeviceSpec(), armnn::OptimizerOptions(), errMessages);
Sadik Armagan1625efc2021-06-10 18:24:34 +010095 FAIL("Should have thrown an exception.");
Mike Kelly3a613cc2020-09-29 20:50:35 +010096 }
97 catch (const armnn::InvalidArgumentException& e)
98 {
99 // Different exceptions are thrown on different backends
100 }
Sadik Armagan1625efc2021-06-10 18:24:34 +0100101 CHECK(errMessages.size() > 0);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100102}
103
Sadik Armagan1625efc2021-06-10 18:24:34 +0100104TEST_CASE("OptimizeValidateDeviceNonSupportLayerWithFallback")
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100105{
106 // build up the structure of the network
107 armnn::INetworkPtr net(armnn::INetwork::Create());
108
109 armnn::IConnectableLayer* input = net->AddInputLayer(0);
110
111 // This layer configuration isn't supported by CpuAcc but it allows to fallback to CpuRef.
112 armnn::NormalizationDescriptor descriptor;
113 armnn::IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
114
115 armnn::IConnectableLayer* output = net->AddOutputLayer(0);
116
117 input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
118 normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
119
120 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
121 normalize->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
122
123 armnn::IRuntime::CreationOptions options;
124 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
125
126 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc, armnn::Compute::CpuRef };
127 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec());
Sadik Armagan1625efc2021-06-10 18:24:34 +0100128 REQUIRE(optNet);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100129
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000130 armnn::Graph& graph = GetGraphForTesting(optNet.get());
131 graph.AllocateDynamicBuffers();
132
133 for (auto&& layer : graph)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100134 {
135 // If NEON is enabled, Input and Output layers are supported by CpuAcc,
136 // the other layers are supported by CpuRef.
137 // If NEON is not enabled, all layers are supported by CpuRef.
Matteo Martincighd95e9062019-01-31 15:35:59 +0000138#if defined(ARMCOMPUTENEON_ENABLED)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100139 if (layer->GetType() == armnn::LayerType::Input || layer->GetType() == armnn::LayerType::Output)
140 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100141 CHECK(layer->GetBackendId() == armnn::Compute::CpuAcc);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100142 }
143 else if (layer->GetType() == armnn::LayerType::Normalization)
144 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100145 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100146 }
147#else
Sadik Armagan1625efc2021-06-10 18:24:34 +0100148 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100149#endif
150 }
151}
152
Sadik Armagan1625efc2021-06-10 18:24:34 +0100153TEST_CASE("OptimizeValidateWorkloadsUndefinedComputeDevice")
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100154{
155 const armnn::TensorInfo desc({3, 5}, armnn::DataType::Float32);
156
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000157 // build up the structure of the network
158 armnn::INetworkPtr net(armnn::INetwork::Create());
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100159
160 armnn::NormalizationDescriptor nmDesc;
161 armnn::ActivationDescriptor acDesc;
162
163 // in
164 // |
165 // nm
166 // / |
167 // ac |
168 // \ |
169 // ml
170 // |
171 // sm
172 // |
173 // ot
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000174 armnn::IConnectableLayer* layer = net->AddInputLayer(0, "in");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100175 layer->GetOutputSlot(0).SetTensorInfo(desc);
176
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000177 armnn::IConnectableLayer* const normLayer = net->AddNormalizationLayer(nmDesc, "nm");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100178
179 layer->GetOutputSlot(0).Connect(normLayer->GetInputSlot(0));
180 normLayer->GetOutputSlot(0).SetTensorInfo(desc);
181
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000182 layer = net->AddActivationLayer(acDesc, "ac");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100183
184 normLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
185 layer->GetOutputSlot(0).SetTensorInfo(desc);
186
187 armnn::IConnectableLayer* prevLayer = layer;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000188 layer = net->AddMultiplicationLayer("ml");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100189
190 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
191 normLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(1));
192 layer->GetOutputSlot(0).SetTensorInfo(desc);
193
194 prevLayer = layer;
195 armnn::SoftmaxDescriptor softmaxDescriptor;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000196 layer = net->AddSoftmaxLayer(softmaxDescriptor, "sm");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100197
198 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
199 layer->GetOutputSlot(0).SetTensorInfo(desc);
200
201 prevLayer = layer;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000202 layer = net->AddOutputLayer(0, "ot");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100203
204 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
205
206 armnn::IRuntime::CreationOptions options;
207 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
208
209 std::vector<armnn::BackendId> backends = { armnn::Compute::Undefined };
Mike Kelly3a613cc2020-09-29 20:50:35 +0100210 std::vector<std::string> errMessages;
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100211
Mike Kelly3a613cc2020-09-29 20:50:35 +0100212 try
213 {
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000214 Optimize(*net, backends, runtime->GetDeviceSpec(), armnn::OptimizerOptions(), errMessages);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100215 FAIL("Should have thrown an exception.");
Mike Kelly3a613cc2020-09-29 20:50:35 +0100216 }
217 catch (const armnn::InvalidArgumentException& e)
218 {
219 // Different exceptions are thrown on different backends
220 }
Sadik Armagan1625efc2021-06-10 18:24:34 +0100221 CHECK(errMessages.size() > 0);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100222}
223
Sadik Armagan1625efc2021-06-10 18:24:34 +0100224TEST_CASE("OptimizeValidateWorkloadsUndefinedComputeDeviceWithFallback")
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100225{
226 const armnn::TensorInfo desc({3, 5}, armnn::DataType::Float32);
227
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000228 // build up the structure of the network
229 armnn::INetworkPtr net(armnn::INetwork::Create());
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100230
231 armnn::NormalizationDescriptor nmDesc;
232 armnn::ActivationDescriptor acDesc;
233
234 // in
235 // |
236 // nm
237 // / |
238 // ac |
239 // \ |
240 // ml
241 // |
242 // sm
243 // |
244 // ot
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000245 armnn::IConnectableLayer* layer = net->AddInputLayer(0, "in");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100246 layer->GetOutputSlot(0).SetTensorInfo(desc);
247
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000248 armnn::IConnectableLayer* const normLayer = net->AddNormalizationLayer(nmDesc, "nm");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100249
250 layer->GetOutputSlot(0).Connect(normLayer->GetInputSlot(0));
251 normLayer->GetOutputSlot(0).SetTensorInfo(desc);
252
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000253 layer = net->AddActivationLayer(acDesc, "ac");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100254
255 normLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
256 layer->GetOutputSlot(0).SetTensorInfo(desc);
257
258 armnn::IConnectableLayer* prevLayer = layer;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000259 layer = net->AddMultiplicationLayer("ml");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100260
261 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
262 normLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(1));
263 layer->GetOutputSlot(0).SetTensorInfo(desc);
264
265 prevLayer = layer;
266 armnn::SoftmaxDescriptor softmaxDescriptor;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000267 layer = net->AddSoftmaxLayer(softmaxDescriptor, "sm");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100268
269 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
270 layer->GetOutputSlot(0).SetTensorInfo(desc);
271
272 prevLayer = layer;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000273 layer = net->AddOutputLayer(0, "ot");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100274
275 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
276
277 armnn::IRuntime::CreationOptions options;
278 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
279
280 std::vector<armnn::BackendId> backends = { armnn::Compute::Undefined, armnn::Compute::CpuRef };
281
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000282 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec());
Sadik Armagan1625efc2021-06-10 18:24:34 +0100283 CHECK(optNet);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100284
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000285 armnn::Graph& graph = GetGraphForTesting(optNet.get());
286 graph.AllocateDynamicBuffers();
287
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100288 // validate workloads
289 armnn::RefWorkloadFactory fact;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000290 for (auto&& layer : graph)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100291 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100292 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
293 CHECK_NOTHROW(
Derek Lamberti94a88d22019-12-10 21:12:59 +0000294 layer->CreateWorkload(fact));
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100295 }
296}
297
Sadik Armagan1625efc2021-06-10 18:24:34 +0100298TEST_CASE("OptimizeValidateWorkloadsDuplicateComputeDeviceWithFallback")
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100299{
300 // build up the structure of the network
301 armnn::INetworkPtr net(armnn::INetwork::Create());
302
303 armnn::IConnectableLayer* input = net->AddInputLayer(0);
304
305 // This layer configuration isn't supported by CpuAcc but it allows to fallback to CpuRef.
306 armnn::NormalizationDescriptor descriptor;
307 armnn::IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
308
309 armnn::IConnectableLayer* output = net->AddOutputLayer(0);
310
311 input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
312 normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
313
314 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
315 normalize->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
316
317 armnn::IRuntime::CreationOptions options;
318 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
319
320 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc,
321 armnn::Compute::GpuAcc,
322 armnn::Compute::CpuRef };
323
324 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec());
Sadik Armagan1625efc2021-06-10 18:24:34 +0100325 REQUIRE(optNet);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100326
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000327 armnn::Graph& graph = GetGraphForTesting(optNet.get());
328 graph.AllocateDynamicBuffers();
329
330 for (auto&& layer : graph)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100331 {
332 // If NEON is enabled, Input and Output layers are supported by CpuAcc,
333 // the other layers are supported by CpuRef.
334 // If only CL is enabled, Input and Output layers are supported by GpuAcc,
335 // the other layers are supported by CpuRef.
336 // If neither NEON, nor CL is enabled, all layers are supported by CpuRef.
Matteo Martincighd95e9062019-01-31 15:35:59 +0000337#if defined(ARMCOMPUTENEON_ENABLED)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100338 if (layer->GetType() == armnn::LayerType::Input || layer->GetType() == armnn::LayerType::Output)
339 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100340 CHECK(layer->GetBackendId() == armnn::Compute::CpuAcc);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100341 }
342 else if (layer->GetType() == armnn::LayerType::Normalization)
343 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100344 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100345 }
Matteo Martincighd95e9062019-01-31 15:35:59 +0000346#elif defined(ARMCOMPUTECL_ENABLED)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100347 if (layer->GetType() == armnn::LayerType::Input || layer->GetType() == armnn::LayerType::Output)
348 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100349 CHECK(layer->GetBackendId() == armnn::Compute::GpuAcc);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100350 }
351 else if (layer->GetType() == armnn::LayerType::Normalization)
352 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100353 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100354 }
355#else
Sadik Armagan1625efc2021-06-10 18:24:34 +0100356 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100357#endif
358 }
359}
360
Sadik Armagan1625efc2021-06-10 18:24:34 +0100361}