blob: d8e8f60cd8a942c5f6ed27aa37af02ed6f685d37 [file] [log] [blame]
Aron Virginas-Tar70104002018-10-24 15:33:28 +01001//
Mike Kelly3ec30772023-03-08 13:47:17 +00002// Copyright © 2017-2023 Arm Ltd and Contributors. All rights reserved.
Aron Virginas-Tar70104002018-10-24 15:33:28 +01003// SPDX-License-Identifier: MIT
4//
5
Sadik Armagana097d2a2021-11-24 15:47:28 +00006#include <CommonTestUtils.hpp>
Mike Kelly0d677db2021-06-27 22:39:21 +01007
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +00008#include <Graph.hpp>
9#include <Network.hpp>
10
11#include <reference/RefWorkloadFactory.hpp>
Aron Virginas-Tar70104002018-10-24 15:33:28 +010012
Sadik Armagan1625efc2021-06-10 18:24:34 +010013#include <doctest/doctest.h>
Aron Virginas-Tar70104002018-10-24 15:33:28 +010014
Sadik Armagan1625efc2021-06-10 18:24:34 +010015TEST_SUITE("OptimizedNetwork")
16{
17TEST_CASE("SerializeToDot")
Aron Virginas-Tar70104002018-10-24 15:33:28 +010018{
Francis Murtagh3d2b4b22021-02-15 18:23:17 +000019 // build up the structure of the network
20 armnn::INetworkPtr net(armnn::INetwork::Create());
Aron Virginas-Tar70104002018-10-24 15:33:28 +010021
22 //Defines layers.
Francis Murtagh3d2b4b22021-02-15 18:23:17 +000023 auto input = net->AddInputLayer(0);
Mike Kelly3ec30772023-03-08 13:47:17 +000024 auto add = net->AddElementwiseBinaryLayer(armnn::BinaryOperation::Add);
Francis Murtagh3d2b4b22021-02-15 18:23:17 +000025 auto output = net->AddOutputLayer(0);
Aron Virginas-Tar70104002018-10-24 15:33:28 +010026
27 // Connects layers.
28 input->GetOutputSlot(0).Connect(add->GetInputSlot(0));
29 input->GetOutputSlot(0).Connect(add->GetInputSlot(1));
30 add->GetOutputSlot(0).Connect(output->GetInputSlot(0));
31
32 armnn::TensorShape shape({4});
33 armnn::TensorInfo info(shape, armnn::DataType::Float32);
34 input->GetOutputSlot(0).SetTensorInfo(info);
35 add->GetOutputSlot(0).SetTensorInfo(info);
36
37 armnn::IRuntime::CreationOptions options;
38 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
39
40 std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef};
Francis Murtagh3d2b4b22021-02-15 18:23:17 +000041 armnn::IOptimizedNetworkPtr optimizedNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec());
Aron Virginas-Tar70104002018-10-24 15:33:28 +010042
43 std::ostringstream ss;
44 optimizedNet->SerializeToDot(ss);
45
46 auto inputId = input->GetGuid();
47 auto addId = add->GetGuid();
48 auto outputId = output->GetGuid();
49
50 std::stringstream expected;
51 expected <<
52 "digraph Optimized {\n"
53 " node [shape=\"record\"];\n"
54 " edge [fontsize=8 fontcolor=\"blue\" fontname=\"arial-bold\"];\n"
Rob Hughesb17220d2020-08-28 11:48:35 +010055 " " << inputId << " [label=\"{Input|Guid : " << inputId << "\\lLayerType : Input\\l"
56 "BackendID : CpuRef\\l}\"];\n"
Mike Kellyb6de7a12023-07-18 12:03:41 +010057 " " << addId << " [label=\"{ElementwiseBinary|BinaryOperation : Add\\lGuid : " << addId <<
58 "\\lLayerType : ElementwiseBinary\\lBackendID : CpuRef\\l}\"];\n"
Rob Hughesb17220d2020-08-28 11:48:35 +010059 " " << outputId << " [label=\"{Output|Guid : " << outputId << "\\lLayerType : Output\\l"
60 "BackendID : CpuRef\\l}\"];\n"
Aron Virginas-Tar70104002018-10-24 15:33:28 +010061 " " << inputId << " -> " << addId << " [label=< [4] >];\n"
62 " " << inputId << " -> " << addId << " [label=< [4] >];\n"
63 " " << addId << " -> " << outputId << " [label=< [4] >];\n"
64 "}\n";
65
Sadik Armagan1625efc2021-06-10 18:24:34 +010066 CHECK(ss.str() == expected.str());
Aron Virginas-Tar70104002018-10-24 15:33:28 +010067}
68
Sadik Armagan1625efc2021-06-10 18:24:34 +010069TEST_CASE("OptimizeValidateDeviceNonSupportLayerNoFallback")
Aron Virginas-Tar70104002018-10-24 15:33:28 +010070{
71 // build up the structure of the network
72 armnn::INetworkPtr net(armnn::INetwork::Create());
73
74 armnn::IConnectableLayer* input = net->AddInputLayer(0);
75
76 // This layer configuration isn't supported by CpuAcc and isn't allowed to fall back, so Optimize will return null.
77 armnn::NormalizationDescriptor descriptor;
78 armnn::IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
79
80 armnn::IConnectableLayer* output = net->AddOutputLayer(0);
81
82 input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
83 normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
84
85 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
86 normalize->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
87
88 armnn::IRuntime::CreationOptions options;
89 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
90
91 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc };
Mike Kelly3a613cc2020-09-29 20:50:35 +010092 std::vector<std::string> errMessages;
93
94 try
95 {
John Mcloughlinc5ee0d72023-03-24 12:07:25 +000096 Optimize(*net, backends, runtime->GetDeviceSpec(), armnn::OptimizerOptionsOpaque(), errMessages);
Sadik Armagan1625efc2021-06-10 18:24:34 +010097 FAIL("Should have thrown an exception.");
Mike Kelly3a613cc2020-09-29 20:50:35 +010098 }
Rob Hughesc013bc82021-07-14 09:31:31 +010099 catch (const armnn::InvalidArgumentException&)
Mike Kelly3a613cc2020-09-29 20:50:35 +0100100 {
101 // Different exceptions are thrown on different backends
102 }
Sadik Armagan1625efc2021-06-10 18:24:34 +0100103 CHECK(errMessages.size() > 0);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100104}
105
Sadik Armagan1625efc2021-06-10 18:24:34 +0100106TEST_CASE("OptimizeValidateDeviceNonSupportLayerWithFallback")
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100107{
108 // build up the structure of the network
109 armnn::INetworkPtr net(armnn::INetwork::Create());
110
111 armnn::IConnectableLayer* input = net->AddInputLayer(0);
112
113 // This layer configuration isn't supported by CpuAcc but it allows to fallback to CpuRef.
114 armnn::NormalizationDescriptor descriptor;
115 armnn::IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
116
117 armnn::IConnectableLayer* output = net->AddOutputLayer(0);
118
119 input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
120 normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
121
122 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
123 normalize->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
124
125 armnn::IRuntime::CreationOptions options;
126 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
127
128 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc, armnn::Compute::CpuRef };
129 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec());
Sadik Armagan1625efc2021-06-10 18:24:34 +0100130 REQUIRE(optNet);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100131
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000132 armnn::Graph& graph = GetGraphForTesting(optNet.get());
133 graph.AllocateDynamicBuffers();
134
135 for (auto&& layer : graph)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100136 {
137 // If NEON is enabled, Input and Output layers are supported by CpuAcc,
138 // the other layers are supported by CpuRef.
139 // If NEON is not enabled, all layers are supported by CpuRef.
Matteo Martincighd95e9062019-01-31 15:35:59 +0000140#if defined(ARMCOMPUTENEON_ENABLED)
Finn Williamsb1aad422021-10-28 19:07:32 +0100141 if (layer->GetType() == armnn::LayerType::Output)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100142 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100143 CHECK(layer->GetBackendId() == armnn::Compute::CpuAcc);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100144 }
145 else if (layer->GetType() == armnn::LayerType::Normalization)
146 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100147 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100148 }
149#else
Sadik Armagan1625efc2021-06-10 18:24:34 +0100150 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100151#endif
152 }
153}
154
Sadik Armagan1625efc2021-06-10 18:24:34 +0100155TEST_CASE("OptimizeValidateWorkloadsUndefinedComputeDevice")
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100156{
157 const armnn::TensorInfo desc({3, 5}, armnn::DataType::Float32);
158
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000159 // build up the structure of the network
160 armnn::INetworkPtr net(armnn::INetwork::Create());
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100161
162 armnn::NormalizationDescriptor nmDesc;
163 armnn::ActivationDescriptor acDesc;
164
165 // in
166 // |
167 // nm
168 // / |
169 // ac |
170 // \ |
171 // ml
172 // |
173 // sm
174 // |
175 // ot
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000176 armnn::IConnectableLayer* layer = net->AddInputLayer(0, "in");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100177 layer->GetOutputSlot(0).SetTensorInfo(desc);
178
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000179 armnn::IConnectableLayer* const normLayer = net->AddNormalizationLayer(nmDesc, "nm");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100180
181 layer->GetOutputSlot(0).Connect(normLayer->GetInputSlot(0));
182 normLayer->GetOutputSlot(0).SetTensorInfo(desc);
183
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000184 layer = net->AddActivationLayer(acDesc, "ac");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100185
186 normLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
187 layer->GetOutputSlot(0).SetTensorInfo(desc);
188
189 armnn::IConnectableLayer* prevLayer = layer;
Mike Kelly3ec30772023-03-08 13:47:17 +0000190 layer = net->AddElementwiseBinaryLayer(armnn::BinaryOperation::Mul, "ml");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100191
192 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
193 normLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(1));
194 layer->GetOutputSlot(0).SetTensorInfo(desc);
195
196 prevLayer = layer;
197 armnn::SoftmaxDescriptor softmaxDescriptor;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000198 layer = net->AddSoftmaxLayer(softmaxDescriptor, "sm");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100199
200 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
201 layer->GetOutputSlot(0).SetTensorInfo(desc);
202
203 prevLayer = layer;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000204 layer = net->AddOutputLayer(0, "ot");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100205
206 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
207
208 armnn::IRuntime::CreationOptions options;
209 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
210
211 std::vector<armnn::BackendId> backends = { armnn::Compute::Undefined };
Mike Kelly3a613cc2020-09-29 20:50:35 +0100212 std::vector<std::string> errMessages;
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100213
Mike Kelly3a613cc2020-09-29 20:50:35 +0100214 try
215 {
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000216 Optimize(*net, backends, runtime->GetDeviceSpec(),
217 armnn::OptimizerOptionsOpaque(), errMessages);
Sadik Armagan1625efc2021-06-10 18:24:34 +0100218 FAIL("Should have thrown an exception.");
Mike Kelly3a613cc2020-09-29 20:50:35 +0100219 }
Rob Hughesc013bc82021-07-14 09:31:31 +0100220 catch (const armnn::InvalidArgumentException&)
Mike Kelly3a613cc2020-09-29 20:50:35 +0100221 {
222 // Different exceptions are thrown on different backends
223 }
Sadik Armagan1625efc2021-06-10 18:24:34 +0100224 CHECK(errMessages.size() > 0);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100225}
226
Sadik Armagan1625efc2021-06-10 18:24:34 +0100227TEST_CASE("OptimizeValidateWorkloadsUndefinedComputeDeviceWithFallback")
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100228{
229 const armnn::TensorInfo desc({3, 5}, armnn::DataType::Float32);
230
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000231 // build up the structure of the network
232 armnn::INetworkPtr net(armnn::INetwork::Create());
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100233
234 armnn::NormalizationDescriptor nmDesc;
235 armnn::ActivationDescriptor acDesc;
236
237 // in
238 // |
239 // nm
240 // / |
241 // ac |
242 // \ |
243 // ml
244 // |
245 // sm
246 // |
247 // ot
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000248 armnn::IConnectableLayer* layer = net->AddInputLayer(0, "in");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100249 layer->GetOutputSlot(0).SetTensorInfo(desc);
250
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000251 armnn::IConnectableLayer* const normLayer = net->AddNormalizationLayer(nmDesc, "nm");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100252
253 layer->GetOutputSlot(0).Connect(normLayer->GetInputSlot(0));
254 normLayer->GetOutputSlot(0).SetTensorInfo(desc);
255
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000256 layer = net->AddActivationLayer(acDesc, "ac");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100257
258 normLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
259 layer->GetOutputSlot(0).SetTensorInfo(desc);
260
261 armnn::IConnectableLayer* prevLayer = layer;
Mike Kelly3ec30772023-03-08 13:47:17 +0000262 layer = net->AddElementwiseBinaryLayer(armnn::BinaryOperation::Mul, "ml");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100263
264 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
265 normLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(1));
266 layer->GetOutputSlot(0).SetTensorInfo(desc);
267
268 prevLayer = layer;
269 armnn::SoftmaxDescriptor softmaxDescriptor;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000270 layer = net->AddSoftmaxLayer(softmaxDescriptor, "sm");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100271
272 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
273 layer->GetOutputSlot(0).SetTensorInfo(desc);
274
275 prevLayer = layer;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000276 layer = net->AddOutputLayer(0, "ot");
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100277
278 prevLayer->GetOutputSlot(0).Connect(layer->GetInputSlot(0));
279
280 armnn::IRuntime::CreationOptions options;
281 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
282
283 std::vector<armnn::BackendId> backends = { armnn::Compute::Undefined, armnn::Compute::CpuRef };
284
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000285 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec());
Sadik Armagan1625efc2021-06-10 18:24:34 +0100286 CHECK(optNet);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100287
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000288 armnn::Graph& graph = GetGraphForTesting(optNet.get());
289 graph.AllocateDynamicBuffers();
290
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100291 // validate workloads
292 armnn::RefWorkloadFactory fact;
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000293 for (auto&& layer : graph)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100294 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100295 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
296 CHECK_NOTHROW(
Derek Lamberti94a88d22019-12-10 21:12:59 +0000297 layer->CreateWorkload(fact));
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100298 }
299}
300
Sadik Armagan1625efc2021-06-10 18:24:34 +0100301TEST_CASE("OptimizeValidateWorkloadsDuplicateComputeDeviceWithFallback")
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100302{
303 // build up the structure of the network
304 armnn::INetworkPtr net(armnn::INetwork::Create());
305
306 armnn::IConnectableLayer* input = net->AddInputLayer(0);
307
308 // This layer configuration isn't supported by CpuAcc but it allows to fallback to CpuRef.
309 armnn::NormalizationDescriptor descriptor;
310 armnn::IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
311
312 armnn::IConnectableLayer* output = net->AddOutputLayer(0);
313
314 input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
315 normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
316
317 input->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
318 normalize->GetOutputSlot(0).SetTensorInfo(armnn::TensorInfo({ 1, 1, 4, 4 }, armnn::DataType::Float32));
319
320 armnn::IRuntime::CreationOptions options;
321 armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
322
323 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc,
324 armnn::Compute::GpuAcc,
325 armnn::Compute::CpuRef };
326
327 armnn::IOptimizedNetworkPtr optNet = armnn::Optimize(*net, backends, runtime->GetDeviceSpec());
Sadik Armagan1625efc2021-06-10 18:24:34 +0100328 REQUIRE(optNet);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100329
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000330 armnn::Graph& graph = GetGraphForTesting(optNet.get());
331 graph.AllocateDynamicBuffers();
332
333 for (auto&& layer : graph)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100334 {
335 // If NEON is enabled, Input and Output layers are supported by CpuAcc,
336 // the other layers are supported by CpuRef.
337 // If only CL is enabled, Input and Output layers are supported by GpuAcc,
338 // the other layers are supported by CpuRef.
339 // If neither NEON, nor CL is enabled, all layers are supported by CpuRef.
Matteo Martincighd95e9062019-01-31 15:35:59 +0000340#if defined(ARMCOMPUTENEON_ENABLED)
David Monahan7f82e082021-11-09 16:25:17 +0000341 if (layer->GetType() == armnn::LayerType::Input)
342 {
343 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
344 }
345 else if (layer->GetType() == armnn::LayerType::Output)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100346 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100347 CHECK(layer->GetBackendId() == armnn::Compute::CpuAcc);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100348 }
349 else if (layer->GetType() == armnn::LayerType::Normalization)
350 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100351 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100352 }
Matteo Martincighd95e9062019-01-31 15:35:59 +0000353#elif defined(ARMCOMPUTECL_ENABLED)
David Monahan7f82e082021-11-09 16:25:17 +0000354 if (layer->GetType() == armnn::LayerType::Input)
355 {
356 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
357 }
358 else if (layer->GetType() == armnn::LayerType::Output)
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100359 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100360 CHECK(layer->GetBackendId() == armnn::Compute::GpuAcc);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100361 }
362 else if (layer->GetType() == armnn::LayerType::Normalization)
363 {
Sadik Armagan1625efc2021-06-10 18:24:34 +0100364 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100365 }
366#else
Sadik Armagan1625efc2021-06-10 18:24:34 +0100367 CHECK(layer->GetBackendId() == armnn::Compute::CpuRef);
Aron Virginas-Tar70104002018-10-24 15:33:28 +0100368#endif
369 }
370}
371
Mike Kelly0d677db2021-06-27 22:39:21 +0100372TEST_CASE("OptimizeNetworkCopy")
373{
374 armnn::IRuntime::CreationOptions options;
375 armnn::IRuntimePtr runtime = armnn::IRuntime::Create(options);
376 std::vector<armnn::NetworkId> networkIds;
377
378 const std::string layerName("convolution2d");
379 const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
380 const armnn::TensorInfo outputInfo({ 1, 2, 2, 1 }, armnn::DataType::Float32);
381
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100382 const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
383 const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
Mike Kelly0d677db2021-06-27 22:39:21 +0100384
385 std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
386 armnn::ConstTensor weights(weightsInfo, weightsData);
387
388 std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
389 armnn::ConstTensor biases(biasesInfo, biasesData);
390
391 armnn::Convolution2dDescriptor descriptor;
392 descriptor.m_PadLeft = 1;
393 descriptor.m_PadRight = 1;
394 descriptor.m_PadTop = 1;
395 descriptor.m_PadBottom = 1;
396 descriptor.m_StrideX = 2;
397 descriptor.m_StrideY = 2;
398 descriptor.m_DilationX = 2;
399 descriptor.m_DilationY = 2;
400 descriptor.m_BiasEnabled = true;
401 descriptor.m_DataLayout = armnn::DataLayout::NHWC;
402
403 armnn::INetworkPtr network = armnn::INetwork::Create();
404 armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
Keith Davisb4dd5cc2022-04-07 11:32:00 +0100405
Keith Davis721e6292022-05-17 10:06:53 +0100406 armnn::IConnectableLayer* const convLayer = network->AddConvolution2dLayer(descriptor, layerName.c_str());
Mike Kelly0d677db2021-06-27 22:39:21 +0100407 armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
Keith Davis721e6292022-05-17 10:06:53 +0100408 armnn::IConnectableLayer* weightsLayer = network->AddConstantLayer(weights);
409 armnn::IConnectableLayer* biasLayer = network->AddConstantLayer(biases);
410
411 weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
412 weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1u));
413
414 biasLayer->GetOutputSlot(0).SetTensorInfo(biasesInfo);
415 biasLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2u));
Mike Kelly0d677db2021-06-27 22:39:21 +0100416
417 inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
418 convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
419
420 inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
421 convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
422
423 std::vector<armnn::BackendId> preferredBackends { "CpuRef" };
424 armnn::ModelOptions modelOptions;
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000425 armnn::OptimizerOptionsOpaque optimizerOptions(false, false, false,
426 false, modelOptions, false);
Mike Kelly0d677db2021-06-27 22:39:21 +0100427 std::vector<std::string> errorMessages;
428
429 // optimize the network.
430 armnn::IOptimizedNetworkPtr optNet = Optimize(*network,
431 preferredBackends,
432 runtime->GetDeviceSpec(),
433 optimizerOptions,
434 armnn::Optional<std::vector<std::string>&>(errorMessages));
435
436 for (unsigned int i = 0; i < 2; ++i)
437 {
438 armnn::ModelOptions optimizedModelOptions;
439 auto copy = armnn::IOptimizedNetworkPtr(new armnn::IOptimizedNetwork(*optNet.get(), optimizedModelOptions),
440 &armnn::IOptimizedNetwork::Destroy);
441
442 CHECK(copy);
443
444 armnn::NetworkId netId;
445 std::string errorMessage;
446
447 CHECK(armnn::Status::Success == runtime->LoadNetwork(netId, std::move(copy), errorMessage));
448
449 // Record the networkID for the loaded network
450 networkIds.emplace_back(netId);
451 }
452 armnn::NetworkId optNetId;
453 std::string errorMessage;
454
455 // Load the original optNet
456 CHECK(armnn::Status::Success == runtime->LoadNetwork(optNetId, std::move(optNet), errorMessage));
457
458 std::vector<float> inputData = GenerateRandomData<float>(runtime->GetInputTensorInfo(optNetId, 0).GetNumElements());
459 std::vector<float> outputData(runtime->GetOutputTensorInfo(optNetId, 0).GetNumElements());
460
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100461 armnn::TensorInfo inputTensorInfo = runtime->GetInputTensorInfo(optNetId, 0);
462 inputTensorInfo.SetConstant(true);
Mike Kelly0d677db2021-06-27 22:39:21 +0100463 armnn::InputTensors inputTensors
464 {
465 {
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100466 0, armnn::ConstTensor(inputTensorInfo, inputData.data())
Mike Kelly0d677db2021-06-27 22:39:21 +0100467 }
468 };
469 armnn::OutputTensors outputTensors
470 {
471 {
472 0, armnn::Tensor(runtime->GetOutputTensorInfo(optNetId, 0), outputData.data())
473 }
474 };
475 runtime->EnqueueWorkload(optNetId, inputTensors, outputTensors);
476 runtime->UnloadNetwork(optNetId);
477
478 // Record the networkID for the loaded network
479 for (unsigned int i = 0; i < networkIds.size(); ++i)
480 {
481 armnn::NetworkId netId = networkIds[i];
482 std::vector<float> copyOutputData(runtime->GetOutputTensorInfo(netId, 0).GetNumElements());
483
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100484 armnn::TensorInfo inputTensorInfo2 = runtime->GetInputTensorInfo(netId, 0);
485 inputTensorInfo2.SetConstant(true);
Mike Kelly0d677db2021-06-27 22:39:21 +0100486 armnn::InputTensors copyInputTensors
487 {
488 {
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100489 0, armnn::ConstTensor(inputTensorInfo2, inputData.data())
Mike Kelly0d677db2021-06-27 22:39:21 +0100490 }
491 };
492 armnn::OutputTensors copyOutputTensors
493 {
494 {
495 0, armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), copyOutputData.data())
496 }
497 };
498 runtime->EnqueueWorkload(netId, copyInputTensors, copyOutputTensors);
499 runtime->UnloadNetwork(netId);
500
501 // Check results are identical to "original" version
502 for (unsigned int j = 0; j < outputData.size(); ++j)
503 {
504 CHECK(outputData[j] == copyOutputData[j]);
505 }
506 }
507}
508
Sadik Armagan1625efc2021-06-10 18:24:34 +0100509}