blob: eec3afe447bd6b6576fc0056a54a3f8592a486e8 [file] [log] [blame]
Narumol Prangnawarat265e53e2020-10-30 16:06:55 +00001//
2// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include <backendsCommon/test/CommonTestUtils.hpp>
7
8#include <test/GraphUtils.hpp>
9
10#include <boost/test/unit_test.hpp>
11
12BOOST_AUTO_TEST_SUITE(ClFallback)
13
Francis Murtagh73d3e2e2021-04-29 14:23:04 +010014BOOST_AUTO_TEST_CASE(ClImportEnabledFallbackToNeon, * boost::unit_test::disabled())
Narumol Prangnawarat265e53e2020-10-30 16:06:55 +000015{
16 using namespace armnn;
17
18 IRuntime::CreationOptions options;
19 IRuntimePtr runtime(IRuntime::Create(options));
20
21 // Builds up the structure of the network.
22 INetworkPtr net(INetwork::Create());
23
24 IConnectableLayer* input0 = net->AddInputLayer(0, "input0");
25 IConnectableLayer* input1 = net->AddInputLayer(1, "input1");
26 IConnectableLayer* input2 = net->AddInputLayer(2, "input2");
27 IConnectableLayer* add = net->AddAdditionLayer("add");
28 IConnectableLayer* sub = net->AddSubtractionLayer("sub");
29 IConnectableLayer* output = net->AddOutputLayer(0, "output");
30
31 input0->GetOutputSlot(0).Connect(add->GetInputSlot(0));
32 input1->GetOutputSlot(0).Connect(add->GetInputSlot(1));
33 input2->GetOutputSlot(0).Connect(sub->GetInputSlot(0));
34 add->GetOutputSlot(0).Connect(sub->GetInputSlot(1));
35 sub->GetOutputSlot(0).Connect(output->GetInputSlot(0));
36
37 TensorInfo info = TensorInfo({ 1, 2, 3, 2 }, DataType::Float32);
38
39 input0->GetOutputSlot(0).SetTensorInfo(info);
40 input1->GetOutputSlot(0).SetTensorInfo(info);
41 input2->GetOutputSlot(0).SetTensorInfo(info);
42 add->GetOutputSlot(0).SetTensorInfo(info);
43 sub->GetOutputSlot(0).SetTensorInfo(info);
44
45 std::vector<BackendId> backends = { Compute::GpuAcc, Compute::CpuAcc };
46 // Use BackendSelectionHint to specify CpuAcc for Subtraction layer
47 sub->BackendSelectionHint(backends[1]);
48
49 // optimize the network
50 OptimizerOptions optOptions;
51 optOptions.m_ImportEnabled = true;
52 IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec(), optOptions);
53
Francis Murtagh3d2b4b22021-02-15 18:23:17 +000054 Graph& graph = GetGraphForTesting(optNet.get());
Narumol Prangnawarat265e53e2020-10-30 16:06:55 +000055
56 armnn::Layer* const layer0 = GetFirstLayerWithName(graph, "input0");
57 armnn::Layer* const layer1 = GetFirstLayerWithName(graph, "input1");
58 armnn::Layer* const layer2 = GetFirstLayerWithName(graph, "input2");
59 armnn::Layer* const layer3 = GetFirstLayerWithName(graph, "add");
60 armnn::Layer* const layer4 = GetFirstLayerWithName(graph, "[ add (0) -> sub (1) ]");
61 armnn::Layer* const layer5 = GetFirstLayerWithName(graph, "sub");
62 armnn::Layer* const layer6 = GetFirstLayerWithName(graph, "output");
63
64 // Checks order is valid.
65 BOOST_TEST(CheckOrder(graph, layer0, layer1));
66 BOOST_TEST(CheckOrder(graph, layer1, layer2));
67 BOOST_TEST(CheckOrder(graph, layer2, layer3));
68 BOOST_TEST(CheckOrder(graph, layer3, layer4));
69 BOOST_TEST(CheckOrder(graph, layer4, layer5));
70 BOOST_TEST(CheckOrder(graph, layer5, layer6));
71
72 // Use memory import between backends
73 BOOST_TEST((layer4->GetType() == LayerType::MemCopy));
74
75 // Correctly use backend hint
76 BOOST_TEST((layer5->GetBackendId() == Compute::CpuAcc ));
77
78 // Load it into the runtime. It should pass.
79 NetworkId netId;
80 std::string ignoredErrorMessage;
Francis Murtagh73d3e2e2021-04-29 14:23:04 +010081 INetworkProperties networkProperties(false, MemorySource::Malloc, MemorySource::Malloc);
Narumol Prangnawarat265e53e2020-10-30 16:06:55 +000082 runtime->LoadNetwork(netId, std::move(optNet), ignoredErrorMessage, networkProperties);
83
84 // Creates structures for input & output
85 std::vector<float> inputData0
86 {
87 1.0f, 1.0f, 2.0f, 2.0f, 2.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f
88 };
89 std::vector<float> inputData1
90 {
91 0.0f, 1.0f, 1.0f, 2.0f, 3.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f
92 };
93 std::vector<float> inputData2
94 {
95 12.0f, 11.0f, 10.0f, 9.0f, 8.0f, 7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f
96 };
97
98 std::vector<float> outputData(12);
99
100 std::vector<float> expectedOutput
101 {
102 11.0f, 9.0f, 7.0f, 5.0f, 3.0f, 1.0f, -1.0f, -3.0f, -5.0f, -7.0f, -9.0f, -11.0f
103 };
104
105 InputTensors inputTensors
106 {
107 { 0, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), inputData0.data()) },
108 { 1, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 1), inputData1.data()) },
109 { 2, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 2), inputData2.data()) }
110 };
111 OutputTensors outputTensors
112 {
113 { 0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), outputData.data()) }
114 };
115
116 runtime->GetProfiler(netId)->EnableProfiling(true);
117
118 // Do the inference
119 runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
120
121 // Retrieve the Profiler.Print() output to get the workload execution
122 ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance();
123 std::stringstream ss;
124 profilerManager.GetProfiler()->Print(ss);;
125 std::string dump = ss.str();
126
127 // Executed Subtraction using CpuAcc
128 std::size_t found = dump.find("NeonSubtractionWorkload_Execute");
129 BOOST_TEST(found != std::string::npos);
130
131 // Contain CopyMemGeneric
132 found = dump.find("CopyMemGeneric");
133 BOOST_TEST(found != std::string::npos);
134
135 // Check output is as expected
136 BOOST_TEST(outputData == expectedOutput);
137}
138
139BOOST_AUTO_TEST_CASE(ClImportDisabledFallbackToNeon)
140{
141 using namespace armnn;
142
143 IRuntime::CreationOptions options;
144 IRuntimePtr runtime(IRuntime::Create(options));
145
146 // Builds up the structure of the network.
147 INetworkPtr net(INetwork::Create());
148
149 IConnectableLayer* input0 = net->AddInputLayer(0, "input0");
150 IConnectableLayer* input1 = net->AddInputLayer(1, "input1");
151 IConnectableLayer* input2 = net->AddInputLayer(2, "input2");
152 IConnectableLayer* add = net->AddAdditionLayer("add");
153 IConnectableLayer* sub = net->AddSubtractionLayer("sub");
154 IConnectableLayer* output = net->AddOutputLayer(0, "output");
155
156 input0->GetOutputSlot(0).Connect(add->GetInputSlot(0));
157 input1->GetOutputSlot(0).Connect(add->GetInputSlot(1));
158 input2->GetOutputSlot(0).Connect(sub->GetInputSlot(0));
159 add->GetOutputSlot(0).Connect(sub->GetInputSlot(1));
160 sub->GetOutputSlot(0).Connect(output->GetInputSlot(0));
161
162 TensorInfo info = TensorInfo({ 1, 2, 3, 2 }, DataType::Float32);
163
164 input0->GetOutputSlot(0).SetTensorInfo(info);
165 input1->GetOutputSlot(0).SetTensorInfo(info);
166 input2->GetOutputSlot(0).SetTensorInfo(info);
167 add->GetOutputSlot(0).SetTensorInfo(info);
168 sub->GetOutputSlot(0).SetTensorInfo(info);
169
170 std::vector<BackendId> backends = { Compute::GpuAcc, Compute::CpuAcc };
171 // Use BackendSelectionHint to specify CpuAcc for Subtraction layer
172 sub->BackendSelectionHint(backends[1]);
173
174 // optimize the network
175 OptimizerOptions optOptions;
176 IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec(), optOptions);
177
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000178 Graph& graph = GetGraphForTesting(optNet.get());
Narumol Prangnawarat265e53e2020-10-30 16:06:55 +0000179
180 armnn::Layer* const layer0 = GetFirstLayerWithName(graph, "input0");
181 armnn::Layer* const layer1 = GetFirstLayerWithName(graph, "input1");
182 armnn::Layer* const layer2 = GetFirstLayerWithName(graph, "input2");
183 armnn::Layer* const layer3 = GetFirstLayerWithName(graph, "add");
184 armnn::Layer* const layer4 = GetFirstLayerWithName(graph, "[ add (0) -> sub (1) ]");
185 armnn::Layer* const layer5 = GetFirstLayerWithName(graph, "sub");
186 armnn::Layer* const layer6 = GetFirstLayerWithName(graph, "output");
187
188 // Checks order is valid.
189 BOOST_TEST(CheckOrder(graph, layer0, layer1));
190 BOOST_TEST(CheckOrder(graph, layer1, layer2));
191 BOOST_TEST(CheckOrder(graph, layer2, layer3));
192 BOOST_TEST(CheckOrder(graph, layer3, layer4));
193 BOOST_TEST(CheckOrder(graph, layer4, layer5));
194 BOOST_TEST(CheckOrder(graph, layer5, layer6));
195
196 // Use memory import between backends
197 BOOST_TEST((layer4->GetType() == LayerType::MemCopy));
198
199 // Correctly use backend hint
200 BOOST_TEST((layer5->GetBackendId() == Compute::CpuAcc ));
201
202 // Load it into the runtime. It should pass.
203 NetworkId netId;
204 runtime->LoadNetwork(netId, std::move(optNet));
205
206 // Creates structures for input & output
207 std::vector<float> inputData0
208 {
209 1.0f, 1.0f, 2.0f, 2.0f, 2.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f
210 };
211 std::vector<float> inputData1
212 {
213 0.0f, 1.0f, 1.0f, 2.0f, 3.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f
214 };
215 std::vector<float> inputData2
216 {
217 12.0f, 11.0f, 10.0f, 9.0f, 8.0f, 7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f
218 };
219
220 std::vector<float> outputData(12);
221
222 std::vector<float> expectedOutput
223 {
224 11.0f, 9.0f, 7.0f, 5.0f, 3.0f, 1.0f, -1.0f, -3.0f, -5.0f, -7.0f, -9.0f, -11.0f
225 };
226
227 InputTensors inputTensors
228 {
229 { 0, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), inputData0.data()) },
230 { 1, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 1), inputData1.data()) },
231 { 2, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 2), inputData2.data()) }
232 };
233 OutputTensors outputTensors
234 {
235 { 0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), outputData.data()) }
236 };
237
238 runtime->GetProfiler(netId)->EnableProfiling(true);
239
240 // Do the inference
241 runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
242
243 // Retrieve the Profiler.Print() output to get the workload execution
244 ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance();
245 std::stringstream ss;
246 profilerManager.GetProfiler()->Print(ss);;
247 std::string dump = ss.str();
248
249 // Executed Subtraction using CpuAcc
250 std::size_t found = dump.find("NeonSubtractionWorkload_Execute");
251 BOOST_TEST(found != std::string::npos);
252
253 // Contain CopyMemGeneric
254 found = dump.find("CopyMemGeneric");
255 BOOST_TEST(found != std::string::npos);
256
257 // Check output is as expected
258 BOOST_TEST(outputData == expectedOutput);
259}
260
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100261BOOST_AUTO_TEST_CASE(ClImportEnabledFallbackSubgraphToNeon, * boost::unit_test::disabled())
Narumol Prangnawarat265e53e2020-10-30 16:06:55 +0000262{
263 using namespace armnn;
264
265 IRuntime::CreationOptions options;
266 IRuntimePtr runtime(IRuntime::Create(options));
267
268 // Builds up the structure of the network.
269 INetworkPtr net(INetwork::Create());
270
271 Pooling2dDescriptor desc;
272
273 IConnectableLayer* input0 = net->AddInputLayer(0, "input0");
274 IConnectableLayer* input1 = net->AddInputLayer(1, "input1");
275 IConnectableLayer* input2 = net->AddInputLayer(2, "input2");
276 IConnectableLayer* add = net->AddAdditionLayer("add");
277 IConnectableLayer* sub = net->AddSubtractionLayer("sub");
278 IConnectableLayer* pooling = net->AddPooling2dLayer(desc, "pooling");
279 IConnectableLayer* output = net->AddOutputLayer(0, "output");
280
281 input0->GetOutputSlot(0).Connect(add->GetInputSlot(0));
282 input1->GetOutputSlot(0).Connect(add->GetInputSlot(1));
283 input2->GetOutputSlot(0).Connect(sub->GetInputSlot(0));
284 add->GetOutputSlot(0).Connect(sub->GetInputSlot(1));
285 sub->GetOutputSlot(0).Connect(pooling->GetInputSlot(0));
286 pooling->GetOutputSlot(0).Connect(output->GetInputSlot(0));
287
288 TensorInfo info = TensorInfo({ 1, 2, 3, 2 }, DataType::Float32);
289 TensorInfo poolingInfo = TensorInfo({ 1, 2, 1, 1 }, DataType::Float32);
290
291 input0->GetOutputSlot(0).SetTensorInfo(info);
292 input1->GetOutputSlot(0).SetTensorInfo(info);
293 input2->GetOutputSlot(0).SetTensorInfo(info);
294 add->GetOutputSlot(0).SetTensorInfo(info);
295 sub->GetOutputSlot(0).SetTensorInfo(info);
296 pooling->GetOutputSlot(0).SetTensorInfo(poolingInfo);
297
298 std::vector<BackendId> backends = { Compute::GpuAcc, Compute::CpuAcc };
299 // Use BackendSelectionHint to specify CpuAcc for Subtraction layer
300 sub->BackendSelectionHint(backends[1]);
301
302 // optimize the network
303 OptimizerOptions optOptions;
304 optOptions.m_ImportEnabled = true;
305 IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec(), optOptions);
306
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000307 Graph& graph = GetGraphForTesting(optNet.get());
Narumol Prangnawarat265e53e2020-10-30 16:06:55 +0000308
309 armnn::Layer* const layer0 = GetFirstLayerWithName(graph, "input0");
310 armnn::Layer* const layer1 = GetFirstLayerWithName(graph, "input1");
311 armnn::Layer* const layer2 = GetFirstLayerWithName(graph, "input2");
312 armnn::Layer* const layer3 = GetFirstLayerWithName(graph, "add");
313 armnn::Layer* const layer4 = GetFirstLayerWithName(graph, "[ add (0) -> sub (1) ]");
314 armnn::Layer* const layer5 = GetFirstLayerWithName(graph, "sub");
315 armnn::Layer* const layer6 = GetFirstLayerWithName(graph, "[ sub (0) -> pooling (0) ]");
316 armnn::Layer* const layer7 = GetFirstLayerWithName(graph, "pooling");
317 armnn::Layer* const layer8 = GetFirstLayerWithName(graph, "output");
318
319 // Checks order is valid.
320 BOOST_TEST(CheckOrder(graph, layer0, layer1));
321 BOOST_TEST(CheckOrder(graph, layer1, layer2));
322 BOOST_TEST(CheckOrder(graph, layer2, layer3));
323 BOOST_TEST(CheckOrder(graph, layer3, layer4));
324 BOOST_TEST(CheckOrder(graph, layer4, layer5));
325 BOOST_TEST(CheckOrder(graph, layer5, layer6));
326 BOOST_TEST(CheckOrder(graph, layer6, layer7));
327 BOOST_TEST(CheckOrder(graph, layer7, layer8));
328
329 // Use memory import between backends
330 BOOST_TEST((layer4->GetType() == LayerType::MemCopy));
331 BOOST_TEST((layer6->GetType() == LayerType::MemCopy));
332
333 // Correctly use backend hint
334 BOOST_TEST((layer5->GetBackendId() == Compute::CpuAcc ));
335
336 // Load it into the runtime. It should pass.
337 NetworkId netId;
338 std::string ignoredErrorMessage;
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100339 INetworkProperties networkProperties(false, MemorySource::Malloc, MemorySource::Malloc);
Narumol Prangnawarat265e53e2020-10-30 16:06:55 +0000340 runtime->LoadNetwork(netId, std::move(optNet), ignoredErrorMessage, networkProperties);
341
342 // Creates structures for input & output
343 std::vector<float> inputData0
344 {
345 1.0f, 1.0f, 2.0f, 2.0f, 2.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f
346 };
347 std::vector<float> inputData1
348 {
349 0.0f, 1.0f, 1.0f, 2.0f, 3.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f
350 };
351 std::vector<float> inputData2
352 {
353 12.0f, 11.0f, 10.0f, 9.0f, 8.0f, 7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f
354 };
355
356 std::vector<float> outputData(2);
357
358 std::vector<float> expectedOutput{ 11.0f, -1.0f };
359
360 InputTensors inputTensors
361 {
362 { 0, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), inputData0.data()) },
363 { 1, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 1), inputData1.data()) },
364 { 2, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 2), inputData2.data()) }
365 };
366 OutputTensors outputTensors
367 {
368 { 0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), outputData.data()) }
369 };
370
371 runtime->GetProfiler(netId)->EnableProfiling(true);
372
373 // Do the inference
374 runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
375
376 // Retrieve the Profiler.Print() output to get the workload execution
377 ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance();
378 std::stringstream ss;
379 profilerManager.GetProfiler()->Print(ss);;
380 std::string dump = ss.str();
381
382 // Executed Subtraction using CpuAcc
383 std::size_t found = dump.find("NeonSubtractionWorkload_Execute");
384 BOOST_TEST(found != std::string::npos);
385
386 // Correctly switch back to GpuAcc
387 found = dump.find("ClPooling2dWorkload_Execute");
388 BOOST_TEST(found != std::string::npos);
389
390 // Contain CopyMemGeneric
391 found = dump.find("CopyMemGeneric");
392 BOOST_TEST(found != std::string::npos);
393
394 // Check output is as expected
395 BOOST_TEST(outputData == expectedOutput);
396}
397
398BOOST_AUTO_TEST_CASE(ClImportDisableFallbackSubgraphToNeon)
399{
400 using namespace armnn;
401
402 IRuntime::CreationOptions options;
403 IRuntimePtr runtime(IRuntime::Create(options));
404
405 // Builds up the structure of the network.
406 INetworkPtr net(INetwork::Create());
407
408 Pooling2dDescriptor desc;
409
410 IConnectableLayer* input0 = net->AddInputLayer(0, "input0");
411 IConnectableLayer* input1 = net->AddInputLayer(1, "input1");
412 IConnectableLayer* input2 = net->AddInputLayer(2, "input2");
413 IConnectableLayer* add = net->AddAdditionLayer("add");
414 IConnectableLayer* sub = net->AddSubtractionLayer("sub");
415 IConnectableLayer* pooling = net->AddPooling2dLayer(desc, "pooling");
416 IConnectableLayer* output = net->AddOutputLayer(0, "output");
417
418 input0->GetOutputSlot(0).Connect(add->GetInputSlot(0));
419 input1->GetOutputSlot(0).Connect(add->GetInputSlot(1));
420 input2->GetOutputSlot(0).Connect(sub->GetInputSlot(0));
421 add->GetOutputSlot(0).Connect(sub->GetInputSlot(1));
422 sub->GetOutputSlot(0).Connect(pooling->GetInputSlot(0));
423 pooling->GetOutputSlot(0).Connect(output->GetInputSlot(0));
424
425 TensorInfo info = TensorInfo({ 1, 2, 3, 2 }, DataType::Float32);
426 TensorInfo poolingInfo = TensorInfo({ 1, 2, 1, 1 }, DataType::Float32);
427
428 input0->GetOutputSlot(0).SetTensorInfo(info);
429 input1->GetOutputSlot(0).SetTensorInfo(info);
430 input2->GetOutputSlot(0).SetTensorInfo(info);
431 add->GetOutputSlot(0).SetTensorInfo(info);
432 sub->GetOutputSlot(0).SetTensorInfo(info);
433 pooling->GetOutputSlot(0).SetTensorInfo(poolingInfo);
434
435 std::vector<BackendId> backends = { Compute::GpuAcc, Compute::CpuAcc };
436 // Use BackendSelectionHint to specify CpuAcc for Subtraction layer
437 sub->BackendSelectionHint(backends[1]);
438
439 // optimize the network
440 OptimizerOptions optOptions;
441 IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec(), optOptions);
442
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000443 Graph& graph = GetGraphForTesting(optNet.get());
Narumol Prangnawarat265e53e2020-10-30 16:06:55 +0000444
445 armnn::Layer* const layer0 = GetFirstLayerWithName(graph, "input0");
446 armnn::Layer* const layer1 = GetFirstLayerWithName(graph, "input1");
447 armnn::Layer* const layer2 = GetFirstLayerWithName(graph, "input2");
448 armnn::Layer* const layer3 = GetFirstLayerWithName(graph, "add");
449 armnn::Layer* const layer4 = GetFirstLayerWithName(graph, "[ add (0) -> sub (1) ]");
450 armnn::Layer* const layer5 = GetFirstLayerWithName(graph, "sub");
451 armnn::Layer* const layer6 = GetFirstLayerWithName(graph, "[ sub (0) -> pooling (0) ]");
452 armnn::Layer* const layer7 = GetFirstLayerWithName(graph, "pooling");
453 armnn::Layer* const layer8 = GetFirstLayerWithName(graph, "output");
454
455 // Checks order is valid.
456 BOOST_TEST(CheckOrder(graph, layer0, layer1));
457 BOOST_TEST(CheckOrder(graph, layer1, layer2));
458 BOOST_TEST(CheckOrder(graph, layer2, layer3));
459 BOOST_TEST(CheckOrder(graph, layer3, layer4));
460 BOOST_TEST(CheckOrder(graph, layer4, layer5));
461 BOOST_TEST(CheckOrder(graph, layer5, layer6));
462 BOOST_TEST(CheckOrder(graph, layer6, layer7));
463 BOOST_TEST(CheckOrder(graph, layer7, layer8));
464
465 // Use memory import between backends
466 BOOST_TEST((layer4->GetType() == LayerType::MemCopy));
467 BOOST_TEST((layer6->GetType() == LayerType::MemCopy));
468
469 // Correctly use backend hint
470 BOOST_TEST((layer5->GetBackendId() == Compute::CpuAcc ));
471
472 // Load it into the runtime. It should pass.
473 NetworkId netId;
474 runtime->LoadNetwork(netId, std::move(optNet));
475
476 // Creates structures for input & output
477 std::vector<float> inputData0
478 {
479 1.0f, 1.0f, 2.0f, 2.0f, 2.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f
480 };
481 std::vector<float> inputData1
482 {
483 0.0f, 1.0f, 1.0f, 2.0f, 3.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f
484 };
485 std::vector<float> inputData2
486 {
487 12.0f, 11.0f, 10.0f, 9.0f, 8.0f, 7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f
488 };
489
490 std::vector<float> outputData(2);
491
492 std::vector<float> expectedOutput{ 11.0f, -1.0f };
493
494 InputTensors inputTensors
495 {
496 { 0, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 0), inputData0.data()) },
497 { 1, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 1), inputData1.data()) },
498 { 2, armnn::ConstTensor(runtime->GetInputTensorInfo(netId, 2), inputData2.data()) }
499 };
500 OutputTensors outputTensors
501 {
502 { 0,armnn::Tensor(runtime->GetOutputTensorInfo(netId, 0), outputData.data()) }
503 };
504
505 runtime->GetProfiler(netId)->EnableProfiling(true);
506
507 // Do the inference
508 runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
509
510 // Retrieve the Profiler.Print() output to get the workload execution
511 ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance();
512 std::stringstream ss;
513 profilerManager.GetProfiler()->Print(ss);;
514 std::string dump = ss.str();
515
516 // Executed Subtraction using CpuAcc
517 std::size_t found = dump.find("NeonSubtractionWorkload_Execute");
518 BOOST_TEST(found != std::string::npos);
519
520 // Correctly switch back to GpuAcc
521 found = dump.find("ClPooling2dWorkload_Execute");
522 BOOST_TEST(found != std::string::npos);
523
524 // Contain CopyMemGeneric
525 found = dump.find("CopyMemGeneric");
526 BOOST_TEST(found != std::string::npos);
527
528 // Check output is as expected
529 BOOST_TEST(outputData == expectedOutput);
530}
531
532BOOST_AUTO_TEST_SUITE_END()