ArmNN
 22.08
RuntimeTests.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
8 #include <Runtime.hpp>
9 
10 #include <armnn/Descriptors.hpp>
11 #include <armnn/IRuntime.hpp>
12 #include <armnn/INetwork.hpp>
13 #include <armnn/TypesUtils.hpp>
14 
16 
17 #include <common/include/LabelsAndEventClasses.hpp>
18 #include <common/include/Processes.hpp>
19 
21 
22 #include <HeapProfiling.hpp>
23 #include <LeakChecking.hpp>
24 
25 #ifdef WITH_VALGRIND
26 #include <valgrind/memcheck.h>
27 #endif
28 
29 #include <doctest/doctest.h>
30 #include "RuntimeTests.hpp"
31 #include <TestUtils.hpp>
32 
33 namespace armnn
34 {
35 
37 {
38  runtime->m_LoadedNetworks.reserve(1);
39 }
40 
41 } // namespace armnn
42 
43 TEST_SUITE("Runtime")
44 {
45 TEST_CASE("RuntimeUnloadNetwork")
46 {
47  // build 2 mock-networks and load them into the runtime
50 
51  // Mock network 1.
52  armnn::NetworkId networkIdentifier1 = 1;
54  mockNetwork1->AddInputLayer(0, "test layer");
55  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
56  runtime->LoadNetwork(networkIdentifier1, Optimize(*mockNetwork1, backends, runtime->GetDeviceSpec()));
57 
58  // Mock network 2.
59  armnn::NetworkId networkIdentifier2 = 2;
61  mockNetwork2->AddInputLayer(0, "test layer");
62  runtime->LoadNetwork(networkIdentifier2, Optimize(*mockNetwork2, backends, runtime->GetDeviceSpec()));
63 
64  // Unloads one by its networkID.
65  CHECK(runtime->UnloadNetwork(networkIdentifier1) == armnn::Status::Success);
66 
67  CHECK(runtime->UnloadNetwork(networkIdentifier1) == armnn::Status::Failure);
68 }
69 
70 TEST_CASE("RuntimePreImportInputs")
71 {
74  armnn::NetworkId networkId = 1;
76 
77  auto inputLayer1 = testNetwork->AddInputLayer(0, "input 1 layer");
78  auto inputLayer2 = testNetwork->AddInputLayer(1, "input 2 layer");
79  auto addLayer = testNetwork->AddAdditionLayer("add layer");
80  auto outputLayer = testNetwork->AddOutputLayer(2, "output layer");
81 
82  TensorInfo tensorInfo{{4}, armnn::DataType::Signed32};
83 
84  inputLayer1->GetOutputSlot(0).Connect(addLayer->GetInputSlot(0));
85  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
86 
87  inputLayer2->GetOutputSlot(0).Connect(addLayer->GetInputSlot(1));
88  inputLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo);
89 
90  addLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
91  addLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
92 
93  std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef};
94 
95  std::string er;
97  runtime->LoadNetwork(networkId,
98  Optimize(*testNetwork, backends, runtime->GetDeviceSpec()),
99  er,
100  networkProperties);
101 
102  std::vector<int> inputData1(4, 10);
103  std::vector<int> inputData2(4, 20);
104  std::vector<int> output(4);
105 
106  ConstTensor inputTensor1({{4}, armnn::DataType::Signed32, 0.0f, 0, true}, inputData1.data());
107  ConstTensor inputTensor2({{4}, armnn::DataType::Signed32, 0.0f, 0, true}, inputData2.data());
108  Tensor outputTensor({{4}, armnn::DataType::Signed32}, output.data());
109 
110  auto importedInputVec1 = runtime->ImportInputs(networkId, {{0, inputTensor1}}, MemorySource::Malloc);
111  CHECK(importedInputVec1.size() == 1);
112  CHECK(importedInputVec1[0] == 0);
113 
114  auto memHandle = runtime->CreateWorkingMemHandle(networkId);
115 
116  runtime->Execute(*memHandle.get(), {{1, inputTensor2}}, {{2, outputTensor}}, {0 /* pre-imported id */});
117  for (auto val: output) {
118  CHECK(val == 30);
119  }
120 
121  auto importedInputVec2 = runtime->ImportInputs(networkId, {{1, inputTensor2}}, MemorySource::Malloc);
122  CHECK(importedInputVec2.size() == 1);
123  CHECK(importedInputVec2[0] == 1);
124 
125  runtime->Execute(*memHandle.get(), {{0, inputTensor1}}, {{2, outputTensor}}, {1 /* pre-imported id */});
126  for (auto val: output) {
127  CHECK(val == 30);
128  }
129 
130  runtime->Execute(*memHandle.get(), {}, {{2, outputTensor}}, {0, 1});
131  for (auto val: output) {
132  CHECK(val == 30);
133  }
134  // Duplicate ImportedInputId and LayerBindingId
135  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), {}, {{2, outputTensor}}, {0, 0});,
137  // Duplicate LayerBindingId
138  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), {{1, inputTensor2}}, {{2, outputTensor}}, {1});,
140  // Incorrect ImportedInputId
141  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), {{1, inputTensor2}}, {{2, outputTensor}}, {10});,
143  // Incorrect LayerBindingId
144  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), {{-2, inputTensor2}}, {{2, outputTensor}}, {1});,
146  // Incorrect layer binding id and ImportedInputId
147  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), {{-2, inputTensor2}}, {{2, outputTensor}}, {10});,
149  auto importedInputVec3 = runtime->ImportInputs(networkId, {{1, inputTensor2}}, MemorySource::Malloc);
150  CHECK(importedInputVec3[0] == 2);
151  // Too many ImportedInputIds
152  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), {}, {{2, outputTensor}}, {0, 1, 2});,
154  // Too many InputTensors
155  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(),
156  {{0, inputTensor2},
157  {1, inputTensor2},
158  {2, inputTensor2}},
159  {{2, outputTensor}});, armnn::InvalidArgumentException);
160  // Too few ImportedInputIds
161  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), {}, {{2, outputTensor}}, {0});,
163  runtime->ClearImportedInputs(networkId, {1});
164  runtime->Execute(*memHandle.get(), {{1, inputTensor2}}, {{2, outputTensor}}, {0}, {});
165  for (auto val: output) {
166  CHECK(val == 30);
167  }
168  // Using deleted pre-imported input
169  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), {}, {{2, outputTensor}}, {0, 1}, {});,
171 
172  // Trying to delete deleted pre-imported tensor
173  CHECK_THROWS_AS(runtime->ClearImportedInputs(networkId, {1});, armnn::InvalidArgumentException);
174 
175  // Trying to delete unknown pre-imported tensor
176  CHECK_THROWS_AS(runtime->ClearImportedInputs(networkId, {10});, armnn::InvalidArgumentException);
177 }
178 
179 TEST_CASE("RuntimePreImportOutputs")
180 {
183 
184  armnn::NetworkId networkId = 1;
185 
187  TensorInfo tensorInfo{{4}, armnn::DataType::Float32, 0.0f, 0, true};
188 
189  auto inputLayer1 = testNetwork->AddInputLayer(0, "input 1 layer");
190  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
191 
192  ActivationDescriptor activationDescriptor;
193  activationDescriptor.m_Function = ActivationFunction::BoundedReLu;
194  activationDescriptor.m_A = 2.0f;
195  activationDescriptor.m_B = 0.0f;
196  auto activationLayer1 = testNetwork->AddActivationLayer(activationDescriptor, "add layer");
197  auto outputLayer1 = testNetwork->AddOutputLayer(2, "output layer");
198 
199  inputLayer1->GetOutputSlot(0).Connect(activationLayer1->GetInputSlot(0));
200 
201  activationLayer1->GetOutputSlot(0).Connect(outputLayer1->GetInputSlot(0));
202  activationLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
203 
204  auto inputLayer2 = testNetwork->AddInputLayer(1, "input 1 layer");
205 
206  activationDescriptor.m_A = 4.0f;
207  activationDescriptor.m_B = 2.0f;
208  auto activationLayer2 = testNetwork->AddActivationLayer(activationDescriptor, "add layer");
209  auto outputLayer2 = testNetwork->AddOutputLayer(3, "output layer");
210 
211  inputLayer2->GetOutputSlot(0).Connect(activationLayer2->GetInputSlot(0));
212  inputLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo);
213 
214  activationLayer2->GetOutputSlot(0).Connect(outputLayer2->GetInputSlot(0));
215  activationLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo);
216 
217  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
218 
219  std::string er;
221  runtime->LoadNetwork(networkId,
222  Optimize(*testNetwork, backends, runtime->GetDeviceSpec()),
223  er,
224  networkProperties);
225 
226  std::vector<float> inputData1(4, 1.0f);
227  std::vector<float> inputData2(4, 3.0f);
228 
229  std::vector<float> outputData1(4);
230  std::vector<float> outputData2(4);
231 
232  ConstTensor inputTensor1(tensorInfo, inputData1.data());
233  ConstTensor inputTensor2(tensorInfo, inputData2.data());
234 
235  Tensor outputTensor1{tensorInfo, outputData1.data()};
236  Tensor outputTensor2{tensorInfo, outputData2.data()};
237 
238  InputTensors inputTensors = {{0, inputTensor1}, {1, inputTensor2}};
239 
240  std::pair<LayerBindingId, class Tensor> output1{2, outputTensor1};
241  std::pair<LayerBindingId, class Tensor> output2{3, outputTensor2};
242 
243  auto testOutputs = [&]()
244  {
245  for (auto val : outputData1)
246  {
247  CHECK(val == 1.0f);
248  }
249 
250  for (auto val : outputData2)
251  {
252  CHECK(val == 3.0f);
253  }
254  };
255 
256  auto memHandle = runtime->CreateWorkingMemHandle(networkId);
257 
258  runtime->Execute(*memHandle.get(),inputTensors, {output1, output2});
259  testOutputs();
260 
261  auto importedOutputVec = runtime->ImportOutputs(networkId, {output1, output2 }, MemorySource::Malloc);
262  CHECK(importedOutputVec.size() == 2);
263  CHECK(importedOutputVec[0] == 0);
264  CHECK(importedOutputVec[1] == 1);
265 
266  runtime->Execute(*memHandle.get(), inputTensors, {}, {}, importedOutputVec);
267  testOutputs();
268 
269  runtime->Execute(*memHandle.get(), inputTensors, {output1}, {}, {1});
270  testOutputs();
271 
272  runtime->Execute(*memHandle.get(), inputTensors, {output2}, {}, {0});
273  testOutputs();
274 
275  auto importedInputVec = runtime->ImportInputs(networkId, inputTensors, MemorySource::Malloc);
276  CHECK(importedInputVec.size() == 2);
277  CHECK(importedInputVec[0] == 0);
278  CHECK(importedInputVec[1] == 1);
279 
280  runtime->Execute(*memHandle.get(), {}, {}, importedInputVec, importedOutputVec);
281  testOutputs();
282 
283  runtime->Execute(*memHandle.get(), {{0, inputTensor1}}, {output2}, {1}, {0});
284  testOutputs();
285 
286  // Too many ids
287  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {output1, output2}, {}, {0, 1});,
289 
290  // Duplicate ids
291  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {output2}, {}, {1});,
293 
294  // Duplicate ids
295  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {output1, output1}, {}, {});,
297 
298  // Duplicate ids
299  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {}, {}, {0, 0}),
301 
302  // Unknown id
303  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {output1}, {}, {3});,
305 
306  // Unknown id
307  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {{4, outputTensor2}}, {}, {1});,
309 
310  // Input id for output
311  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {{0, outputTensor2}}, {}, {1});,
313 
314  // Input id for output
315  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {{0, outputTensor2}}, {}, {1});,
317 
318  // Output id for input
319  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), {{2, inputTensor1}}, {{0, outputTensor2}}, {1}, {1, 0});,
321 
322  runtime->ClearImportedOutputs(networkId, {1});
323 
324  runtime->Execute(*memHandle.get(), inputTensors, {output2}, {}, {0});
325  testOutputs();
326 
327  // Trying to use deleted pre-imported tensor
328  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {}, {}, importedOutputVec),
330 
331  // Trying to delete deleted pre-imported tensor
332  CHECK_THROWS_AS(runtime->ClearImportedOutputs(networkId, {1});, armnn::InvalidArgumentException);
333 
334  // Trying to delete unknown pre-imported tensor
335  CHECK_THROWS_AS(runtime->ClearImportedOutputs(networkId, {10});, armnn::InvalidArgumentException);
336 }
337 
338 // Note: the current builds we don't do valgrind and gperftools based leak checking at the same
339 // time, so in practice WITH_VALGRIND and ARMNN_LEAK_CHECKING_ENABLED are exclusive. The
340 // valgrind tests can stay for x86 builds, but on hikey Valgrind is just way too slow
341 // to be integrated into the CI system.
342 
343 #ifdef ARMNN_LEAK_CHECKING_ENABLED
344 
345 struct DisableGlobalLeakChecking
346 {
347  DisableGlobalLeakChecking()
348  {
350  }
351 };
352 
353 TEST_CASE_FIXTURE(DisableGlobalLeakChecking, "RuntimeHeapMemoryUsageSanityChecks")
354 {
356  {
357  ARMNN_SCOPED_LEAK_CHECKER("Sanity_Check_Outer");
358  {
359  ARMNN_SCOPED_LEAK_CHECKER("Sanity_Check_Inner");
360  CHECK(ARMNN_NO_LEAKS_IN_SCOPE() == true);
361  std::unique_ptr<char[]> dummyAllocation(new char[1000]);
362  // "A leak of 1000 bytes is expected here. "
363  // "Please make sure environment variable: HEAPCHECK=draconian is set!"
364  CHECK((ARMNN_NO_LEAKS_IN_SCOPE() == false));
365  CHECK(ARMNN_BYTES_LEAKED_IN_SCOPE() == 1000);
366  CHECK(ARMNN_OBJECTS_LEAKED_IN_SCOPE() == 1);
367  }
368  CHECK(ARMNN_NO_LEAKS_IN_SCOPE());
369  CHECK(ARMNN_BYTES_LEAKED_IN_SCOPE() == 0);
370  CHECK(ARMNN_OBJECTS_LEAKED_IN_SCOPE() == 0);
371  }
372 }
373 
374 #endif // ARMNN_LEAK_CHECKING_ENABLED
375 
376 // Note: this part of the code is due to be removed when we fully trust the gperftools based results.
377 #ifdef WITH_VALGRIND
378 // Run with the following command to get all the amazing output (in the devenv/build folder) :)
379 // valgrind --leak-check=full --show-leak-kinds=all --log-file=Valgrind_Memcheck_Leak_Report.txt armnn/test/UnitTests
380 TEST_CASE("RuntimeMemoryLeak")
381 {
382  // From documentation:
383 
384  // This means that no pointer to the block can be found. The block is classified as "lost",
385  // because the programmer could not possibly have freed it at program exit, since no pointer to it exists.
386  unsigned long leakedBefore = 0;
387  unsigned long leakedAfter = 0;
388 
389  // A start-pointer or chain of start-pointers to the block is found. Since the block is still pointed at,
390  // the programmer could, at least in principle, have freed it before program exit.
391  // We want to test this in case memory is not freed as early as it could have been.
392  unsigned long reachableBefore = 0;
393  unsigned long reachableAfter = 0;
394 
395  // Needed as out params but we don't test them.
396  unsigned long dubious = 0;
397  unsigned long suppressed = 0;
398 
399  armnn::NetworkId networkIdentifier1 = 1;
400 
401  // ensure that runtime is large enough before checking for memory leaks
402  // otherwise when loading the network it will automatically reserve memory that won't be released until destruction
404  armnn::RuntimeImpl runtime(options);
406 
407  {
408  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
409 
411  mockNetwork1->AddInputLayer(0, "test layer");
412 
413  // Warm-up load/unload pair to put the runtime in a stable state (memory-wise).
414  runtime.LoadNetwork(networkIdentifier1, Optimize(*mockNetwork1, backends, runtime.GetDeviceSpec()));
415  runtime.UnloadNetwork(networkIdentifier1);
416 
417  // Checks for leaks before we load the network and record them so that we can see the delta after unloading.
418  VALGRIND_DO_QUICK_LEAK_CHECK;
419  VALGRIND_COUNT_LEAKS(leakedBefore, dubious, reachableBefore, suppressed);
420 
421  // The actual test.
422  runtime.LoadNetwork(networkIdentifier1, Optimize(*mockNetwork1, backends, runtime.GetDeviceSpec()));
423  runtime.UnloadNetwork(networkIdentifier1);
424 
425  VALGRIND_DO_ADDED_LEAK_CHECK;
426  VALGRIND_COUNT_LEAKS(leakedAfter, dubious, reachableAfter, suppressed);
427  }
428 
429  // If we're not running under Valgrind, these vars will have been initialised to 0, so this will always pass.
430  CHECK(leakedBefore == leakedAfter);
431  CHECK(reachableBefore == reachableAfter);
432 
433  // These are needed because VALGRIND_COUNT_LEAKS is a macro that assigns to the parameters
434  // so they are assigned to, but still considered unused, causing a warning.
435  armnn::IgnoreUnused(dubious);
436  armnn::IgnoreUnused(suppressed);
437 }
438 #endif // WITH_VALGRIND
439 
440 TEST_CASE("RuntimeCpuRef")
441 {
442  using namespace armnn;
443 
444  // Create runtime in which test will run
447 
448  // build up the structure of the network
450 
451  IConnectableLayer* input = net->AddInputLayer(0);
452 
453  // This layer configuration isn't supported by CpuAcc, should be fall back to CpuRef.
454  NormalizationDescriptor descriptor;
455  IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
456 
457  IConnectableLayer* output = net->AddOutputLayer(0);
458 
459  input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
460  normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
461 
462  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
463  normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
464 
465  // optimize the network
466  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
467  IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec());
468 
469  // Load it into the runtime. It should success.
470  armnn::NetworkId netId;
471  CHECK(runtime->LoadNetwork(netId, std::move(optNet)) == Status::Success);
472 }
473 
474 TEST_CASE("RuntimeFallbackToCpuRef")
475 {
476  using namespace armnn;
477 
478  // Create runtime in which test will run
481 
482  // build up the structure of the network
484 
485  IConnectableLayer* input = net->AddInputLayer(0);
486 
487  // This layer configuration isn't supported by CpuAcc, should be fall back to CpuRef.
488  NormalizationDescriptor descriptor;
489  IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
490 
491  IConnectableLayer* output = net->AddOutputLayer(0);
492 
493  input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
494  normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
495 
496  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
497  normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
498 
499  // Allow fallback to CpuRef.
500  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc, armnn::Compute::CpuRef };
501  // optimize the network
502  IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec());
503 
504  // Load it into the runtime. It should succeed.
505  armnn::NetworkId netId;
506  CHECK(runtime->LoadNetwork(netId, std::move(optNet)) == Status::Success);
507 }
508 
509 TEST_CASE("IVGCVSW_1929_QuantizedSoftmaxIssue")
510 {
511  // Test for issue reported by Chris Nix in https://jira.arm.com/browse/IVGCVSW-1929
512  using namespace armnn;
513 
514  // Create runtime in which test will run
517 
518  // build up the structure of the network
520  armnn::IConnectableLayer* input = net->AddInputLayer(0,"input");
521  armnn::IConnectableLayer* softmax = net->AddSoftmaxLayer(armnn::SoftmaxDescriptor(), "softmax");
522  armnn::IConnectableLayer* output = net->AddOutputLayer(0, "output");
523 
524  input->GetOutputSlot(0).Connect(softmax->GetInputSlot(0));
525  softmax->GetOutputSlot(0).Connect(output->GetInputSlot(0));
526 
529  1.0f / 255,
530  0));
531 
534 
535  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
536  std::vector<std::string> errMessages;
537 
538  try
539  {
541  backends,
542  runtime->GetDeviceSpec(),
544  errMessages);
545  FAIL("An exception should have been thrown");
546  }
547  catch (const armnn::InvalidArgumentException&)
548  {
549  // Different exceptions are thrown on different backends
550  }
551  CHECK(errMessages.size() > 0);
552 }
553 
554 TEST_CASE("RuntimeBackendOptions")
555 {
556  using namespace armnn;
557 
558  IRuntime::CreationOptions creationOptions;
559  auto& backendOptions = creationOptions.m_BackendOptions;
560 
561 
562  // Define Options on explicit construction
563  BackendOptions options1("FakeBackend1",
564  {
565  { "Option1", 1.3f },
566  { "Option2", true }
567  });
568 
569  // Add an option after construction
570  options1.AddOption({ "Option3", "some_value" });
571 
572  // Add the options to CreationOptions struct
573  backendOptions.push_back(options1);
574 
575  // Add more Options via inplace explicit construction
576  backendOptions.emplace_back(BackendOptions{ "FakeBackend1",
577  {{ "Option4", 42 }}
578  });
579 
580 
581  // First group
582  CHECK(backendOptions[0].GetBackendId().Get() == "FakeBackend1");
583  CHECK(backendOptions[0].GetOption(0).GetName() == "Option1");
584  CHECK(backendOptions[0].GetOption(0).GetValue().IsFloat() == true);
585  CHECK(backendOptions[0].GetOption(0).GetValue().AsFloat() == 1.3f);
586 
587  CHECK(backendOptions[0].GetOption(1).GetName() == "Option2");
588  CHECK(backendOptions[0].GetOption(1).GetValue().IsBool() == true);
589  CHECK(backendOptions[0].GetOption(1).GetValue().AsBool() == true);
590 
591  CHECK(backendOptions[0].GetOption(2).GetName() == "Option3");
592  CHECK(backendOptions[0].GetOption(2).GetValue().IsString() == true);
593  CHECK(backendOptions[0].GetOption(2).GetValue().AsString() == "some_value");
594 
595  // Second group
596  CHECK(backendOptions[1].GetBackendId().Get() == "FakeBackend1");
597  CHECK(backendOptions[1].GetOption(0).GetName() == "Option4");
598  CHECK(backendOptions[1].GetOption(0).GetValue().IsInt() == true);
599  CHECK(backendOptions[1].GetOption(0).GetValue().AsInt() == 42);
600 }
601 
602 TEST_CASE("ProfilingDisable")
603 {
604  using namespace armnn;
605 
606  LogLevelSwapper logLevelSwapper(arm::pipe::LogSeverity::Fatal);
607 
608  // Create runtime in which the test will run
610  armnn::RuntimeImpl runtime(options);
611 
612  // build up the structure of the network
614 
615  IConnectableLayer* input = net->AddInputLayer(0);
616 
617  // This layer configuration isn't supported by CpuAcc, should fall back to CpuRef.
618  NormalizationDescriptor descriptor;
619  IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
620 
621  IConnectableLayer* output = net->AddOutputLayer(0);
622 
623  input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
624  normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
625 
626  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
627  normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
628 
629  // optimize the network
630  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
631  IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime.GetDeviceSpec());
632 
633  // Load it into the runtime. It should succeed.
634  armnn::NetworkId netId;
635  CHECK(runtime.LoadNetwork(netId, std::move(optNet)) == Status::Success);
636 
638  ProfilingServiceRuntimeHelper profilingServiceHelper(
639  arm::pipe::MAX_ARMNN_COUNTER, initialiser, GetProfilingService(&runtime));
640  BufferManager& bufferManager = profilingServiceHelper.GetProfilingBufferManager();
641  auto readableBuffer = bufferManager.GetReadableBuffer();
642 
643  // Profiling is not enabled, the post-optimisation structure should not be created
644  CHECK(!readableBuffer);
645 }
646 
647 TEST_CASE("ProfilingEnableCpuRef")
648 {
649  using namespace armnn;
650  using namespace arm::pipe;
651 
652  // Create runtime in which the test will run
654  options.m_ProfilingOptions.m_EnableProfiling = true;
655  options.m_ProfilingOptions.m_TimelineEnabled = true;
656 
657  armnn::RuntimeImpl runtime(options);
658  GetProfilingService(&runtime).ResetExternalProfilingOptions(
660 
662  ProfilingServiceRuntimeHelper profilingServiceHelper(
663  arm::pipe::MAX_ARMNN_COUNTER, initialiser, GetProfilingService(&runtime));
664  profilingServiceHelper.ForceTransitionToState(ProfilingState::NotConnected);
665  profilingServiceHelper.ForceTransitionToState(ProfilingState::WaitingForAck);
666  profilingServiceHelper.ForceTransitionToState(ProfilingState::Active);
667 
668  // build up the structure of the network
670 
671  IConnectableLayer* input = net->AddInputLayer(0, "input");
672 
673  NormalizationDescriptor descriptor;
674  IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor, "normalization");
675 
676  IConnectableLayer* output = net->AddOutputLayer(0, "output");
677 
678  input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
679  normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
680 
681  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
682  normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
683 
684  // optimize the network
685  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
686  IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime.GetDeviceSpec());
687 
688  ProfilingGuid optNetGuid = optNet->GetGuid();
689 
690  // Load it into the runtime. It should succeed.
691  armnn::NetworkId netId;
692  CHECK(runtime.LoadNetwork(netId, std::move(optNet)) == Status::Success);
693 
694  BufferManager& bufferManager = profilingServiceHelper.GetProfilingBufferManager();
695  auto readableBuffer = bufferManager.GetReadableBuffer();
696 
697  // Profiling is enabled, the post-optimisation structure should be created
698  CHECK(readableBuffer != nullptr);
699 
700  unsigned int size = readableBuffer->GetSize();
701 
702  const unsigned char* readableData = readableBuffer->GetReadableData();
703  CHECK(readableData != nullptr);
704 
705  unsigned int offset = 0;
706 
707  // Verify Header
708  VerifyTimelineHeaderBinary(readableData, offset, size - 8);
709 
710  // Post-optimisation network
711  // Network entity
712  VerifyTimelineEntityBinaryPacketData(optNetGuid, readableData, offset);
713 
714  // Entity - Type relationship
715  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
716  arm::pipe::EmptyOptional(),
717  optNetGuid,
718  LabelsAndEventClasses::NETWORK_GUID,
719  LabelsAndEventClasses::TYPE_GUID,
720  readableData,
721  offset);
722 
723  // Network - START OF LIFE
724  ProfilingGuid networkSolEventGuid = VerifyTimelineEventBinaryPacket(arm::pipe::EmptyOptional(),
725  arm::pipe::EmptyOptional(),
726  arm::pipe::EmptyOptional(),
727  readableData,
728  offset);
729 
730  // Network - START OF LIFE event relationship
731  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
732  arm::pipe::EmptyOptional(),
733  optNetGuid,
734  networkSolEventGuid,
735  LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
736  readableData,
737  offset);
738 
739  // Process ID Label
740  int processID = arm::pipe::GetCurrentProcessId();
741  std::stringstream ss;
742  ss << processID;
743  std::string processIdLabel = ss.str();
744  VerifyTimelineLabelBinaryPacketData(arm::pipe::EmptyOptional(), processIdLabel, readableData, offset);
745 
746  // Entity - Process ID relationship
747  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
748  arm::pipe::EmptyOptional(),
749  optNetGuid,
750  arm::pipe::EmptyOptional(),
751  LabelsAndEventClasses::PROCESS_ID_GUID,
752  readableData,
753  offset);
754 
755  // Input layer
756  // Input layer entity
757  VerifyTimelineEntityBinaryPacketData(input->GetGuid(), readableData, offset);
758 
759  // Name Entity
760  ProfilingGuid inputLabelGuid = VerifyTimelineLabelBinaryPacketData(
761  arm::pipe::EmptyOptional(), "input", readableData, offset);
762 
763  // Entity - Name relationship
764  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
765  arm::pipe::EmptyOptional(),
766  input->GetGuid(),
767  inputLabelGuid,
768  LabelsAndEventClasses::NAME_GUID,
769  readableData,
770  offset);
771 
772  // Entity - Type relationship
773  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
774  arm::pipe::EmptyOptional(),
775  input->GetGuid(),
776  LabelsAndEventClasses::LAYER_GUID,
777  LabelsAndEventClasses::TYPE_GUID,
778  readableData,
779  offset);
780 
781  // Network - Input layer relationship
782  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
783  arm::pipe::EmptyOptional(),
784  optNetGuid,
785  input->GetGuid(),
786  LabelsAndEventClasses::CHILD_GUID,
787  readableData,
788  offset);
789 
790  // Normalization layer
791  // Normalization layer entity
792  VerifyTimelineEntityBinaryPacketData(normalize->GetGuid(), readableData, offset);
793 
794  // Name entity
795  ProfilingGuid normalizationLayerNameGuid = VerifyTimelineLabelBinaryPacketData(
796  arm::pipe::EmptyOptional(), "normalization", readableData, offset);
797 
798  // Entity - Name relationship
799  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
800  arm::pipe::EmptyOptional(),
801  normalize->GetGuid(),
802  normalizationLayerNameGuid,
803  LabelsAndEventClasses::NAME_GUID,
804  readableData,
805  offset);
806 
807  // Entity - Type relationship
808  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
809  arm::pipe::EmptyOptional(),
810  normalize->GetGuid(),
811  LabelsAndEventClasses::LAYER_GUID,
812  LabelsAndEventClasses::TYPE_GUID,
813  readableData,
814  offset);
815 
816  // Network - Normalize layer relationship
817  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
818  arm::pipe::EmptyOptional(),
819  optNetGuid,
820  normalize->GetGuid(),
821  LabelsAndEventClasses::CHILD_GUID,
822  readableData,
823  offset);
824 
825  // Input layer - Normalize layer relationship
826  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
827  arm::pipe::EmptyOptional(),
828  input->GetGuid(),
829  normalize->GetGuid(),
830  LabelsAndEventClasses::CONNECTION_GUID,
831  readableData,
832  offset);
833 
834  // Normalization workload
835  // Normalization workload entity
836  ProfilingGuid normalizationWorkloadGuid = VerifyTimelineEntityBinaryPacketData(
837  arm::pipe::EmptyOptional(), readableData, offset);
838 
839  // Entity - Type relationship
840  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
841  arm::pipe::EmptyOptional(),
842  normalizationWorkloadGuid,
843  LabelsAndEventClasses::WORKLOAD_GUID,
844  LabelsAndEventClasses::TYPE_GUID,
845  readableData,
846  offset);
847 
848  // BackendId entity
849  ProfilingGuid cpuRefLabelGuid = VerifyTimelineLabelBinaryPacketData(
850  arm::pipe::EmptyOptional(), "CpuRef", readableData, offset);
851 
852  // Entity - BackendId relationship
853  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
854  arm::pipe::EmptyOptional(),
855  normalizationWorkloadGuid,
856  cpuRefLabelGuid,
857  LabelsAndEventClasses::BACKENDID_GUID,
858  readableData,
859  offset);
860 
861  // Normalize layer - Normalize workload relationship
862  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
863  arm::pipe::EmptyOptional(),
864  normalize->GetGuid(),
865  normalizationWorkloadGuid,
866  LabelsAndEventClasses::CHILD_GUID,
867  readableData,
868  offset);
869 
870  // Output layer
871  // Output layer entity
872  VerifyTimelineEntityBinaryPacketData(output->GetGuid(), readableData, offset);
873 
874  // Name entity
875  ProfilingGuid outputLabelGuid = VerifyTimelineLabelBinaryPacketData(
876  arm::pipe::EmptyOptional(), "output", readableData, offset);
877 
878  // Entity - Name relationship
879  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
880  arm::pipe::EmptyOptional(),
881  output->GetGuid(),
882  outputLabelGuid,
883  LabelsAndEventClasses::NAME_GUID,
884  readableData,
885  offset);
886 
887  // Entity - Type relationship
888  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
889  arm::pipe::EmptyOptional(),
890  output->GetGuid(),
891  LabelsAndEventClasses::LAYER_GUID,
892  LabelsAndEventClasses::TYPE_GUID,
893  readableData,
894  offset);
895 
896  // Network - Output layer relationship
897  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
898  arm::pipe::EmptyOptional(),
899  optNetGuid,
900  output->GetGuid(),
901  LabelsAndEventClasses::CHILD_GUID,
902  readableData,
903  offset);
904 
905  // Normalize layer - Output layer relationship
906  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
907  arm::pipe::EmptyOptional(),
908  normalize->GetGuid(),
909  output->GetGuid(),
910  LabelsAndEventClasses::CONNECTION_GUID,
911  readableData,
912  offset);
913 
914  bufferManager.MarkRead(readableBuffer);
915 
916  // Creates structures for input & output.
917  std::vector<float> inputData(16);
918  std::vector<float> outputData(16);
919 
920  TensorInfo inputTensorInfo = runtime.GetInputTensorInfo(netId, 0);
921  inputTensorInfo.SetConstant(true);
922  InputTensors inputTensors
923  {
924  {0, ConstTensor(inputTensorInfo, inputData.data())}
925  };
926  OutputTensors outputTensors
927  {
928  {0, Tensor(runtime.GetOutputTensorInfo(netId, 0), outputData.data())}
929  };
930 
931  // Does the inference.
932  runtime.EnqueueWorkload(netId, inputTensors, outputTensors);
933 
934  // Get readable buffer for input workload
935  auto inputReadableBuffer = bufferManager.GetReadableBuffer();
936  CHECK(inputReadableBuffer != nullptr);
937 
938  // Get readable buffer for output workload
939  auto outputReadableBuffer = bufferManager.GetReadableBuffer();
940  CHECK(outputReadableBuffer != nullptr);
941 
942  // Get readable buffer for inference timeline
943  auto inferenceReadableBuffer = bufferManager.GetReadableBuffer();
944  CHECK(inferenceReadableBuffer != nullptr);
945 
946  // Validate input workload data
947  size = inputReadableBuffer->GetSize();
948  CHECK(size == 164);
949 
950  readableData = inputReadableBuffer->GetReadableData();
951  CHECK(readableData != nullptr);
952 
953  offset = 0;
954 
955  // Verify Header
956  VerifyTimelineHeaderBinary(readableData, offset, 156);
957 
958  // Input workload
959  // Input workload entity
960  ProfilingGuid inputWorkloadGuid = VerifyTimelineEntityBinaryPacketData(
961  arm::pipe::EmptyOptional(), readableData, offset);
962 
963  // Entity - Type relationship
964  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
965  arm::pipe::EmptyOptional(),
966  inputWorkloadGuid,
967  LabelsAndEventClasses::WORKLOAD_GUID,
968  LabelsAndEventClasses::TYPE_GUID,
969  readableData,
970  offset);
971 
972  // BackendId entity
973  ProfilingGuid CpuRefLabelGuid = VerifyTimelineLabelBinaryPacketData(
974  arm::pipe::EmptyOptional(), "CpuRef", readableData, offset);
975 
976  // Entity - BackendId relationship
977  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
978  arm::pipe::EmptyOptional(),
979  inputWorkloadGuid,
980  CpuRefLabelGuid,
981  LabelsAndEventClasses::BACKENDID_GUID,
982  readableData,
983  offset);
984 
985  // Input layer - Input workload relationship
986  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
987  arm::pipe::EmptyOptional(),
988  input->GetGuid(),
989  inputWorkloadGuid,
990  LabelsAndEventClasses::CHILD_GUID,
991  readableData,
992  offset);
993 
994  bufferManager.MarkRead(inputReadableBuffer);
995 
996  // Validate output workload data
997  size = outputReadableBuffer->GetSize();
998  CHECK(size == 164);
999 
1000  readableData = outputReadableBuffer->GetReadableData();
1001  CHECK(readableData != nullptr);
1002 
1003  offset = 0;
1004 
1005  // Verify Header
1006  VerifyTimelineHeaderBinary(readableData, offset, 156);
1007 
1008  // Output workload
1009  // Output workload entity
1010  ProfilingGuid outputWorkloadGuid = VerifyTimelineEntityBinaryPacketData(
1011  arm::pipe::EmptyOptional(), readableData, offset);
1012 
1013  // Entity - Type relationship
1014  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1015  arm::pipe::EmptyOptional(),
1016  outputWorkloadGuid,
1017  LabelsAndEventClasses::WORKLOAD_GUID,
1018  LabelsAndEventClasses::TYPE_GUID,
1019  readableData,
1020  offset);
1021 
1022  // BackendId entity
1023  VerifyTimelineLabelBinaryPacketData(arm::pipe::EmptyOptional(), "CpuRef", readableData, offset);
1024 
1025  // Entity - BackendId relationship
1026  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1027  arm::pipe::EmptyOptional(),
1028  outputWorkloadGuid,
1029  CpuRefLabelGuid,
1030  LabelsAndEventClasses::BACKENDID_GUID,
1031  readableData,
1032  offset);
1033 
1034  // Output layer - Output workload relationship
1035  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1036  arm::pipe::EmptyOptional(),
1037  output->GetGuid(),
1038  outputWorkloadGuid,
1039  LabelsAndEventClasses::CHILD_GUID,
1040  readableData,
1041  offset);
1042 
1043  bufferManager.MarkRead(outputReadableBuffer);
1044 
1045  // Validate inference data
1046  size = inferenceReadableBuffer->GetSize();
1047  CHECK(size == 976 + 8 * ThreadIdSize);
1048 
1049  readableData = inferenceReadableBuffer->GetReadableData();
1050  CHECK(readableData != nullptr);
1051 
1052  offset = 0;
1053 
1054  // Verify Header
1055  VerifyTimelineHeaderBinary(readableData, offset, 968 + 8 * ThreadIdSize);
1056 
1057  // Inference timeline trace
1058  // Inference entity
1059  ProfilingGuid inferenceGuid = VerifyTimelineEntityBinaryPacketData(
1060  arm::pipe::EmptyOptional(), readableData, offset);
1061 
1062  // Entity - Type relationship
1063  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1064  arm::pipe::EmptyOptional(),
1065  inferenceGuid,
1066  LabelsAndEventClasses::INFERENCE_GUID,
1067  LabelsAndEventClasses::TYPE_GUID,
1068  readableData,
1069  offset);
1070 
1071  // Network - Inference relationship
1072  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1073  arm::pipe::EmptyOptional(),
1074  optNetGuid,
1075  inferenceGuid,
1076  LabelsAndEventClasses::EXECUTION_OF_GUID,
1077  readableData,
1078  offset);
1079 
1080  // Start Inference life
1081  // Event packet - timeline, threadId, eventGuid
1082  ProfilingGuid inferenceEventGuid = VerifyTimelineEventBinaryPacket(
1083  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1084 
1085  // Inference - event relationship
1086  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1087  arm::pipe::EmptyOptional(),
1088  inferenceGuid,
1089  inferenceEventGuid,
1090  LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
1091  readableData,
1092  offset);
1093 
1094  // Execution
1095  // Input workload execution
1096  // Input workload execution entity
1097  ProfilingGuid inputWorkloadExecutionGuid = VerifyTimelineEntityBinaryPacketData(
1098  arm::pipe::EmptyOptional(), readableData, offset);
1099 
1100  // Entity - Type relationship
1101  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1102  arm::pipe::EmptyOptional(),
1103  inputWorkloadExecutionGuid,
1104  LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID,
1105  LabelsAndEventClasses::TYPE_GUID,
1106  readableData,
1107  offset);
1108 
1109  // Inference - Workload execution relationship
1110  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1111  arm::pipe::EmptyOptional(),
1112  inferenceGuid,
1113  inputWorkloadExecutionGuid,
1114  LabelsAndEventClasses::CHILD_GUID,
1115  readableData,
1116  offset);
1117 
1118  // Workload - Workload execution relationship
1119  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1120  arm::pipe::EmptyOptional(),
1121  inputWorkloadGuid,
1122  inputWorkloadExecutionGuid,
1123  LabelsAndEventClasses::EXECUTION_OF_GUID,
1124  readableData,
1125  offset);
1126 
1127  // Start Input workload execution life
1128  // Event packet - timeline, threadId, eventGuid
1129  ProfilingGuid inputWorkloadExecutionSOLEventId = VerifyTimelineEventBinaryPacket(
1130  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1131 
1132  // Input workload execution - event relationship
1133  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1134  arm::pipe::EmptyOptional(),
1135  inputWorkloadExecutionGuid,
1136  inputWorkloadExecutionSOLEventId,
1137  LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
1138  readableData,
1139  offset);
1140 
1141  // End of Input workload execution life
1142  // Event packet - timeline, threadId, eventGuid
1143  ProfilingGuid inputWorkloadExecutionEOLEventId = VerifyTimelineEventBinaryPacket(
1144  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1145 
1146  // Input workload execution - event relationship
1147  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1148  arm::pipe::EmptyOptional(),
1149  inputWorkloadExecutionGuid,
1150  inputWorkloadExecutionEOLEventId,
1151  LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS,
1152  readableData,
1153  offset);
1154 
1155  // Normalize workload execution
1156  // Normalize workload execution entity
1157  ProfilingGuid normalizeWorkloadExecutionGuid = VerifyTimelineEntityBinaryPacketData(
1158  arm::pipe::EmptyOptional(), readableData, offset);
1159 
1160  // Entity - Type relationship
1161  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1162  arm::pipe::EmptyOptional(),
1163  normalizeWorkloadExecutionGuid,
1164  LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID,
1165  LabelsAndEventClasses::TYPE_GUID,
1166  readableData,
1167  offset);
1168 
1169  // Inference - Workload execution relationship
1170  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1171  arm::pipe::EmptyOptional(),
1172  inferenceGuid,
1173  normalizeWorkloadExecutionGuid,
1174  LabelsAndEventClasses::CHILD_GUID,
1175  readableData,
1176  offset);
1177 
1178  // Workload - Workload execution relationship
1179  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1180  arm::pipe::EmptyOptional(),
1181  normalizationWorkloadGuid,
1182  normalizeWorkloadExecutionGuid,
1183  LabelsAndEventClasses::EXECUTION_OF_GUID,
1184  readableData,
1185  offset);
1186 
1187  // Start Normalize workload execution life
1188  // Event packet - timeline, threadId, eventGuid
1189  ProfilingGuid normalizationWorkloadExecutionSOLEventGuid = VerifyTimelineEventBinaryPacket(
1190  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1191 
1192  // Normalize workload execution - event relationship
1193  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1194  arm::pipe::EmptyOptional(),
1195  normalizeWorkloadExecutionGuid,
1196  normalizationWorkloadExecutionSOLEventGuid,
1197  LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
1198  readableData,
1199  offset);
1200 
1201  // End of Normalize workload execution life
1202  // Event packet - timeline, threadId, eventGuid
1203  ProfilingGuid normalizationWorkloadExecutionEOLEventGuid = VerifyTimelineEventBinaryPacket(
1204  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1205 
1206  // Normalize workload execution - event relationship
1207  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1208  arm::pipe::EmptyOptional(),
1209  normalizeWorkloadExecutionGuid,
1210  normalizationWorkloadExecutionEOLEventGuid,
1211  LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS,
1212  readableData,
1213  offset);
1214 
1215  // Output workload execution
1216  // Output workload execution entity
1217  ProfilingGuid outputWorkloadExecutionGuid = VerifyTimelineEntityBinaryPacketData(
1218  arm::pipe::EmptyOptional(), readableData, offset);
1219 
1220  // Entity - Type relationship
1221  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1222  arm::pipe::EmptyOptional(),
1223  outputWorkloadExecutionGuid,
1224  LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID,
1225  LabelsAndEventClasses::TYPE_GUID,
1226  readableData,
1227  offset);
1228 
1229  // Inference - Workload execution relationship
1230  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1231  arm::pipe::EmptyOptional(),
1232  inferenceGuid,
1233  outputWorkloadExecutionGuid,
1234  LabelsAndEventClasses::CHILD_GUID,
1235  readableData,
1236  offset);
1237 
1238  // Workload - Workload execution relationship
1239  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1240  arm::pipe::EmptyOptional(),
1241  outputWorkloadGuid,
1242  outputWorkloadExecutionGuid,
1243  LabelsAndEventClasses::EXECUTION_OF_GUID,
1244  readableData,
1245  offset);
1246 
1247  // Start Output workload execution life
1248  // Event packet - timeline, threadId, eventGuid
1249  ProfilingGuid outputWorkloadExecutionSOLEventGuid = VerifyTimelineEventBinaryPacket(
1250  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1251 
1252  // Output workload execution - event relationship
1253  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1254  arm::pipe::EmptyOptional(),
1255  outputWorkloadExecutionGuid,
1256  outputWorkloadExecutionSOLEventGuid,
1257  LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
1258  readableData,
1259  offset);
1260 
1261  // End of Normalize workload execution life
1262  // Event packet - timeline, threadId, eventGuid
1263  ProfilingGuid outputWorkloadExecutionEOLEventGuid = VerifyTimelineEventBinaryPacket(
1264  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1265 
1266  // Output workload execution - event relationship
1267  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1268  arm::pipe::EmptyOptional(),
1269  outputWorkloadExecutionGuid,
1270  outputWorkloadExecutionEOLEventGuid,
1271  LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS,
1272  readableData,
1273  offset);
1274 
1275  // End of Inference life
1276  // Event packet - timeline, threadId, eventGuid
1277  ProfilingGuid inferenceEOLEventGuid = VerifyTimelineEventBinaryPacket(
1278  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1279 
1280  // Inference - event relationship
1281  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1282  arm::pipe::EmptyOptional(),
1283  inferenceGuid,
1284  inferenceEOLEventGuid,
1285  LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS,
1286  readableData,
1287  offset);
1288 
1289  bufferManager.MarkRead(inferenceReadableBuffer);
1290 }
1291 
1292 TEST_CASE("ProfilingPostOptimisationStructureCpuRef")
1293 {
1295 }
1296 
1297 TEST_CASE("RuntimeOptimizeImportOff_LoadNetworkImportOn")
1298 {
1299  // In this test case we'll optimize a network with both import and export disabled. Then we'll attempt to load
1300  // that network but specify that the import memory source is Malloc.
1301 
1303  armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
1304  armnn::NetworkId networkId = 1;
1306 
1307  auto inputLayer1 = testNetwork->AddInputLayer(0, "input 1 layer");
1308  auto inputLayer2 = testNetwork->AddInputLayer(1, "input 2 layer");
1309  auto addLayer = testNetwork->AddAdditionLayer("add layer");
1310  auto outputLayer = testNetwork->AddOutputLayer(2, "output layer");
1311 
1312  TensorInfo tensorInfo{{4}, armnn::DataType::Signed32};
1313 
1314  inputLayer1->GetOutputSlot(0).Connect(addLayer->GetInputSlot(0));
1315  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1316 
1317  inputLayer2->GetOutputSlot(0).Connect(addLayer->GetInputSlot(1));
1318  inputLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1319 
1320  addLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1321  addLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1322 
1323  std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef};
1324 
1325  OptimizerOptions optimizedOptions;
1326  // Hard set import and export to off.
1327  optimizedOptions.m_ImportEnabled = false;
1328  optimizedOptions.m_ExportEnabled = false;
1329  IOptimizedNetworkPtr optNet = Optimize(*testNetwork, backends, runtime->GetDeviceSpec(), optimizedOptions);
1330  CHECK(optNet);
1331 
1332  std::string er;
1333  // Load the network passing an import memory source.
1335  // There should be an InvalidArgumentException.
1336  runtime->LoadNetwork(networkId, std::move(optNet), er, networkProperties1);
1337  CHECK(er.find("However, it was disabled when this network was optimized") != -1);
1338 }
1339 
1340 TEST_CASE("RuntimeOptimizeExportOff_LoadNetworkExportOn")
1341 {
1342  // In this test case we'll optimize a network with both import and export disabled. Then we'll attempt to load
1343  // that network but specify that the export memory source as Malloc.
1344 
1346  armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
1347  armnn::NetworkId networkId = 1;
1349 
1350  auto inputLayer1 = testNetwork->AddInputLayer(0, "input 1 layer");
1351  auto inputLayer2 = testNetwork->AddInputLayer(1, "input 2 layer");
1352  auto addLayer = testNetwork->AddAdditionLayer("add layer");
1353  auto outputLayer = testNetwork->AddOutputLayer(2, "output layer");
1354 
1355  TensorInfo tensorInfo{{4}, armnn::DataType::Signed32};
1356 
1357  inputLayer1->GetOutputSlot(0).Connect(addLayer->GetInputSlot(0));
1358  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1359 
1360  inputLayer2->GetOutputSlot(0).Connect(addLayer->GetInputSlot(1));
1361  inputLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1362 
1363  addLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1364  addLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1365 
1366  std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef};
1367 
1368  OptimizerOptions optimizedOptions;
1369  // Hard set import and export to off.
1370  optimizedOptions.m_ImportEnabled = false;
1371  optimizedOptions.m_ExportEnabled = false;
1372  IOptimizedNetworkPtr optNet = Optimize(*testNetwork, backends, runtime->GetDeviceSpec(), optimizedOptions);
1373  CHECK(optNet);
1374 
1375  std::string er;
1376  // Load the network passing an import memory source.
1378  // There should be an InvalidArgumentException.
1379  runtime->LoadNetwork(networkId, std::move(optNet), er, networkProperties1);
1380  CHECK(er.find("However, it was disabled when this network was optimized") != -1);
1381 }
1382 
1383 TEST_CASE("RuntimeOptimizeImportOn_LoadNetworkImportOff")
1384 {
1385  // In this test case we'll optimize a network with import enabled. Then we'll attempt to load
1386  // that network but specify that the import memory source is Undefined.
1387 
1389  armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
1390  armnn::NetworkId networkId = 1;
1392 
1393  auto inputLayer1 = testNetwork->AddInputLayer(0, "input 1 layer");
1394  auto inputLayer2 = testNetwork->AddInputLayer(1, "input 2 layer");
1395  auto addLayer = testNetwork->AddAdditionLayer("add layer");
1396  auto outputLayer = testNetwork->AddOutputLayer(2, "output layer");
1397 
1398  TensorInfo tensorInfo{{4}, armnn::DataType::Signed32};
1399 
1400  inputLayer1->GetOutputSlot(0).Connect(addLayer->GetInputSlot(0));
1401  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1402 
1403  inputLayer2->GetOutputSlot(0).Connect(addLayer->GetInputSlot(1));
1404  inputLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1405 
1406  addLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1407  addLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1408 
1409  std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef};
1410 
1411  OptimizerOptions optimizedOptions;
1412  // Hard set import and export to off.
1413  optimizedOptions.m_ImportEnabled = true;
1414  optimizedOptions.m_ExportEnabled = false;
1415  IOptimizedNetworkPtr optNet = Optimize(*testNetwork, backends, runtime->GetDeviceSpec(), optimizedOptions);
1416  CHECK(optNet);
1417 
1418  std::string er;
1419  // Load the network passing an import memory source.
1421  // There should be an InvalidArgumentException.
1422  runtime->LoadNetwork(networkId, std::move(optNet), er, networkProperties1);
1423  CHECK(er.find("However, it was enabled when this network was optimized") != -1);
1424 }
1425 
1426 TEST_CASE("RuntimeOptimizeExportOn_LoadNetworkExportOff")
1427 {
1428  // In this test case we'll optimize a network with export enabled. Then we'll attempt to load
1429  // that network but specify that the export memory source is Undefined.
1430 
1432  armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
1433  armnn::NetworkId networkId = 1;
1435 
1436  auto inputLayer1 = testNetwork->AddInputLayer(0, "input 1 layer");
1437  auto inputLayer2 = testNetwork->AddInputLayer(1, "input 2 layer");
1438  auto addLayer = testNetwork->AddAdditionLayer("add layer");
1439  auto outputLayer = testNetwork->AddOutputLayer(2, "output layer");
1440 
1441  TensorInfo tensorInfo{{4}, armnn::DataType::Signed32};
1442 
1443  inputLayer1->GetOutputSlot(0).Connect(addLayer->GetInputSlot(0));
1444  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1445 
1446  inputLayer2->GetOutputSlot(0).Connect(addLayer->GetInputSlot(1));
1447  inputLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1448 
1449  addLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1450  addLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1451 
1452  std::vector<armnn::BackendId> backends = {armnn::Compute::CpuRef};
1453 
1454  OptimizerOptions optimizedOptions;
1455  // Hard set import and export to off.
1456  optimizedOptions.m_ImportEnabled = false;
1457  optimizedOptions.m_ExportEnabled = true;
1458  IOptimizedNetworkPtr optNet = Optimize(*testNetwork, backends, runtime->GetDeviceSpec(), optimizedOptions);
1459  CHECK(optNet);
1460 
1461  std::string er;
1462  // Load the network passing an import memory source.
1464  // There should be an InvalidArgumentException.
1465  runtime->LoadNetwork(networkId, std::move(optNet), er, networkProperties1);
1466  CHECK(er.find("However, it was enabled when this network was optimized") != -1);
1467 }
1468 
1469 TEST_CASE("SyncExecutePreImportInputsHappyPath")
1470 {
1471  // In this test case we'll mix "Pre Import" and pass by reference tensors as input.
1472  //
1473  // * Create a small network that takes two inputs.
1474  // * Optimize it specifying that the inputs and outputs will not be imported or exported.
1475  // * Create some malloc input and output tensors.
1476  // * Use ImportInputs to import only one of the two inputs.
1477  // * Call EnqueueWorkload passing one input tensor and one reference to a pre-imported tensor.
1478 
1480  armnn::IRuntimePtr runtime(armnn::IRuntime::Create(options));
1481  armnn::NetworkId networkId = 1;
1483 
1484  auto inputLayer1 = testNetwork->AddInputLayer(0, "input 1 layer");
1485  auto inputLayer2 = testNetwork->AddInputLayer(1, "input 2 layer");
1486  auto addLayer = testNetwork->AddAdditionLayer("add layer");
1487  auto outputLayer = testNetwork->AddOutputLayer(2, "output layer");
1488 
1489  TensorInfo tensorInfo{ { 4 }, armnn::DataType::Signed32 };
1490 
1491  inputLayer1->GetOutputSlot(0).Connect(addLayer->GetInputSlot(0));
1492  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1493 
1494  inputLayer2->GetOutputSlot(0).Connect(addLayer->GetInputSlot(1));
1495  inputLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1496 
1497  addLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
1498  addLayer->GetOutputSlot(0).SetTensorInfo(tensorInfo);
1499 
1500  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
1501 
1502  std::string er;
1504  runtime->LoadNetwork(networkId, Optimize(*testNetwork, backends, runtime->GetDeviceSpec()), er, networkProperties);
1505 
1506  std::vector<int> inputData1(4, 10);
1507  std::vector<int> inputData2(4, 20);
1508  std::vector<int> output(4);
1509 
1510  ConstTensor inputTensor1({ { 4 }, armnn::DataType::Signed32, 0.0f, 0, true }, inputData1.data());
1511  ConstTensor inputTensor2({ { 4 }, armnn::DataType::Signed32, 0.0f, 0, true }, inputData2.data());
1512  Tensor outputTensor({ { 4 }, armnn::DataType::Signed32 }, output.data());
1513 
1514  // An extra check here: the number of inputs provided to ImportInputs should not exceed the number of inputs
1515  // to the network.
1516  CHECK_THROWS_AS(runtime->ImportInputs(networkId, { { 0, inputTensor1 }, { 0, inputTensor1 }, { 0, inputTensor1 } },
1519 
1520  // Pre Import one of the two input tensors.
1521  std::vector<ImportedOutputId> importedInputVec =
1522  runtime->ImportInputs(networkId, { { 0, inputTensor1 } }, MemorySource::Malloc);
1523  CHECK(importedInputVec.size() == 1);
1524  CHECK(importedInputVec[0] == 0);
1525 
1526  // We've pre-imported tensor 1 and we'll pass tensor 2 by reference.
1527  InputTensors inputTensors{ { 1, inputTensor2 } };
1528  OutputTensors outputTensors{ { 2, outputTensor } };
1529 
1530  // Do the inference
1531  auto ret = runtime->EnqueueWorkload(networkId, inputTensors, outputTensors, importedInputVec,
1532  std::vector<ImportedOutputId>());
1533  REQUIRE(ret == Status::Success);
1534 }
1535 }
TEST_SUITE("TestConstTensorLayerVisitor")
#define ARMNN_SCOPED_LEAK_CHECKER(TAG)
#define ARMNN_LOCAL_LEAK_CHECKING_ONLY()
armnn::TensorInfo GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
Definition: Runtime.cpp:599
static IRuntimePtr Create(const CreationOptions &options)
Definition: Runtime.cpp:49
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:68
void VerifyPostOptimisationStructureTestImpl(armnn::BackendId backendId)
CPU Execution: Reference C++ kernels.
Status UnloadNetwork(NetworkId networkId)
Unloads a network from the Runtime.
Definition: Runtime.cpp:229
ProfilingGuid VerifyTimelineEntityBinaryPacketData(arm::pipe::Optional< ProfilingGuid > guid, const unsigned char *readableData, unsigned int &offset)
std::unique_ptr< IRuntime, void(*)(IRuntime *runtime)> IRuntimePtr
Definition: IRuntime.hpp:33
Status LoadNetwork(NetworkId &networkIdOut, IOptimizedNetworkPtr network)
Loads a complete network into the Runtime.
Definition: Runtime.cpp:163
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Definition: Tensor.hpp:392
armnn::TensorInfo GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
Definition: Runtime.cpp:604
Copyright (c) 2021 ARM Limited and Contributors.
void IgnoreUnused(Ts &&...)
bool m_EnableProfiling
Indicates whether external profiling is enabled or not.
Definition: IRuntime.hpp:138
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
#define ARMNN_LEAK_CHECKER_IS_ACTIVE()
A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
Definition: Tensor.hpp:319
void VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType relationshipType, arm::pipe::Optional< ProfilingGuid > relationshipGuid, arm::pipe::Optional< ProfilingGuid > headGuid, arm::pipe::Optional< ProfilingGuid > tailGuid, arm::pipe::Optional< ProfilingGuid > attributeGuid, const unsigned char *readableData, unsigned int &offset)
#define ARMNN_OBJECTS_LEAKED_IN_SCOPE()
TEST_CASE_FIXTURE(ClContextControlFixture, "CopyBetweenNeonAndGpu")
std::vector< BackendOptions > m_BackendOptions
Pass backend specific options.
Definition: IRuntime.hpp:189
const char * GetBackendId()
void RuntimeLoadedNetworksReserve(armnn::RuntimeImpl *runtime)
void AddOption(BackendOption &&option)
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptions &options=OptimizerOptions(), Optional< std::vector< std::string > &> messages=EmptyOptional())
Create an optimized version of the network.
Definition: Network.cpp:1864
const IDeviceSpec & GetDeviceSpec() const
Definition: Runtime.hpp:90
virtual LayerGuid GetGuid() const =0
Returns the unique id of the layer.
int NetworkId
Definition: IRuntime.hpp:27
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:327
std::vector< std::pair< LayerBindingId, class Tensor > > OutputTensors
Definition: Tensor.hpp:393
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
Definition: INetwork.hpp:239
ProfilingGuid VerifyTimelineLabelBinaryPacketData(arm::pipe::Optional< ProfilingGuid > guid, const std::string &label, const unsigned char *readableData, unsigned int &offset)
ProfilingOptions ConvertExternalProfilingOptions(const armnn::IRuntime::CreationOptions::ExternalProfilingOptions &options)
ArmNN performs an optimization on each model/network before it gets loaded for execution.
Definition: INetwork.hpp:127
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:36
min(a, max(b, input)) ReLu1 & ReLu6.
void VerifyTimelineHeaderBinary(const unsigned char *readableData, unsigned int &offset, uint32_t packetDataLength)
Struct for the users to pass backend specific options.
float m_A
Alpha upper bound value used by the activation functions. (BoundedReLu, Linear, TanH, Elu).
Definition: Descriptors.hpp:61
Status EnqueueWorkload(NetworkId networkId, const InputTensors &inputTensors, const OutputTensors &outputTensors, std::vector< ImportedInputId > preImportedInputIds={}, std::vector< ImportedOutputId > preImportedOutputIds={})
Definition: Runtime.cpp:630
void ForceTransitionToState(ProfilingState newState)
CPU Execution: NEON: ArmCompute.
#define ARMNN_NO_LEAKS_IN_SCOPE()
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
void SetConstant(const bool IsConstant=true)
Marks the data corresponding to this tensor info as constant.
Definition: Tensor.cpp:514
bool m_TimelineEnabled
Indicates whether external timeline profiling is enabled or not.
Definition: IRuntime.hpp:140
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:238
virtual int Connect(IInputSlot &destination)=0
A NormalizationDescriptor for the NormalizationLayer.
ExternalProfilingOptions m_ProfilingOptions
Definition: IRuntime.hpp:153
arm::pipe::IProfilingService & GetProfilingService(armnn::RuntimeImpl *runtime)
Definition: TestUtils.cpp:59
ProfilingGuid VerifyTimelineEventBinaryPacket(arm::pipe::Optional< uint64_t > timestamp, arm::pipe::Optional< int > threadId, arm::pipe::Optional< ProfilingGuid > eventGuid, const unsigned char *readableData, unsigned int &offset)
static INetworkPtr Create(NetworkOptions networkOptions={})
Definition: Network.cpp:475
float m_B
Beta lower bound value used by the activation functions. (BoundedReLu, Linear, TanH).
Definition: Descriptors.hpp:63
A SoftmaxDescriptor for the SoftmaxLayer.
#define ARMNN_BYTES_LEAKED_IN_SCOPE()
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu, LeakyReLu, Abs, Sqrt, Square, Elu).
Definition: Descriptors.hpp:59