ArmNN
 22.05.01
RuntimeTests.cpp File Reference
#include <ArmNNProfilingServiceInitialiser.hpp>
#include <ProfilingOptionsConverter.hpp>
#include <Runtime.hpp>
#include <armnn/Descriptors.hpp>
#include <armnn/IRuntime.hpp>
#include <armnn/INetwork.hpp>
#include <armnn/TypesUtils.hpp>
#include <armnn/profiling/ArmNNProfiling.hpp>
#include <common/include/LabelsAndEventClasses.hpp>
#include <common/include/Processes.hpp>
#include <test/ProfilingTestUtils.hpp>
#include <HeapProfiling.hpp>
#include <LeakChecking.hpp>
#include <doctest/doctest.h>
#include "RuntimeTests.hpp"
#include <TestUtils.hpp>

Go to the source code of this file.

Namespaces

 armnn
 Copyright (c) 2021 ARM Limited and Contributors.
 

Functions

void RuntimeLoadedNetworksReserve (armnn::RuntimeImpl *runtime)
 
 TEST_SUITE ("Runtime")
 

Function Documentation

◆ TEST_SUITE()

TEST_SUITE ( "Runtime"  )

Definition at line 43 of file RuntimeTests.cpp.

References BackendOptions::AddOption(), ARMNN_BYTES_LEAKED_IN_SCOPE, ARMNN_LEAK_CHECKER_IS_ACTIVE, ARMNN_LOCAL_LEAK_CHECKING_ONLY, ARMNN_NO_LEAKS_IN_SCOPE, ARMNN_OBJECTS_LEAKED_IN_SCOPE, ARMNN_SCOPED_LEAK_CHECKER, armnn::BoundedReLu, IOutputSlot::Connect(), arm::pipe::ConvertExternalProfilingOptions(), armnn::CpuAcc, armnn::CpuRef, IRuntime::Create(), INetwork::Create(), RuntimeImpl::EnqueueWorkload(), armnn::Failure, armnn::Float32, ProfilingServiceRuntimeHelper::ForceTransitionToState(), GetBackendId(), RuntimeImpl::GetDeviceSpec(), IConnectableLayer::GetGuid(), IConnectableLayer::GetInputSlot(), RuntimeImpl::GetInputTensorInfo(), IConnectableLayer::GetOutputSlot(), RuntimeImpl::GetOutputTensorInfo(), ProfilingServiceRuntimeHelper::GetProfilingBufferManager(), armnn::GetProfilingService(), armnn::IgnoreUnused(), RuntimeImpl::LoadNetwork(), ActivationDescriptor::m_A, ActivationDescriptor::m_B, IRuntime::CreationOptions::m_BackendOptions, IRuntime::CreationOptions::ExternalProfilingOptions::m_EnableProfiling, ActivationDescriptor::m_Function, IRuntime::CreationOptions::m_ProfilingOptions, IRuntime::CreationOptions::ExternalProfilingOptions::m_TimelineEnabled, armnn::Malloc, armnn::Optimize(), armnn::QAsymmU8, armnn::RuntimeLoadedNetworksReserve(), TensorInfo::SetConstant(), IOutputSlot::SetTensorInfo(), armnn::Signed32, armnn::Success, TEST_CASE_FIXTURE(), armnn::Undefined, RuntimeImpl::UnloadNetwork(), VerifyPostOptimisationStructureTestImpl(), VerifyTimelineEntityBinaryPacketData(), VerifyTimelineEventBinaryPacket(), VerifyTimelineHeaderBinary(), VerifyTimelineLabelBinaryPacketData(), and VerifyTimelineRelationshipBinaryPacketData().

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;
96  armnn::INetworkProperties networkProperties(true, MemorySource::Malloc, MemorySource::Undefined);
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}});
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}});
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}});
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 TEST_CASE("RuntimePreImportOutputs")
179 {
182 
183  armnn::NetworkId networkId = 1;
184 
186  TensorInfo tensorInfo{{4}, armnn::DataType::Float32, 0.0f, 0, true};
187 
188  auto inputLayer1 = testNetwork->AddInputLayer(0, "input 1 layer");
189  inputLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
190 
191  ActivationDescriptor activationDescriptor;
192  activationDescriptor.m_Function = ActivationFunction::BoundedReLu;
193  activationDescriptor.m_A = 2.0f;
194  activationDescriptor.m_B = 0.0f;
195  auto activationLayer1 = testNetwork->AddActivationLayer(activationDescriptor, "add layer");
196  auto outputLayer1 = testNetwork->AddOutputLayer(2, "output layer");
197 
198  inputLayer1->GetOutputSlot(0).Connect(activationLayer1->GetInputSlot(0));
199 
200  activationLayer1->GetOutputSlot(0).Connect(outputLayer1->GetInputSlot(0));
201  activationLayer1->GetOutputSlot(0).SetTensorInfo(tensorInfo);
202 
203  auto inputLayer2 = testNetwork->AddInputLayer(1, "input 1 layer");
204 
205  activationDescriptor.m_A = 4.0f;
206  activationDescriptor.m_B = 2.0f;
207  auto activationLayer2 = testNetwork->AddActivationLayer(activationDescriptor, "add layer");
208  auto outputLayer2 = testNetwork->AddOutputLayer(3, "output layer");
209 
210  inputLayer2->GetOutputSlot(0).Connect(activationLayer2->GetInputSlot(0));
211  inputLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo);
212 
213  activationLayer2->GetOutputSlot(0).Connect(outputLayer2->GetInputSlot(0));
214  activationLayer2->GetOutputSlot(0).SetTensorInfo(tensorInfo);
215 
216  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
217 
218  std::string er;
219  armnn::INetworkProperties networkProperties(true, MemorySource::Malloc, MemorySource::Malloc);
220  runtime->LoadNetwork(networkId,
221  Optimize(*testNetwork, backends, runtime->GetDeviceSpec()),
222  er,
223  networkProperties);
224 
225  std::vector<float> inputData1(4, 1.0f);
226  std::vector<float> inputData2(4, 3.0f);
227 
228  std::vector<float> outputData1(4);
229  std::vector<float> outputData2(4);
230 
231  ConstTensor inputTensor1(tensorInfo, inputData1.data());
232  ConstTensor inputTensor2(tensorInfo, inputData2.data());
233 
234  Tensor outputTensor1{tensorInfo, outputData1.data()};
235  Tensor outputTensor2{tensorInfo, outputData2.data()};
236 
237  InputTensors inputTensors = {{0, inputTensor1}, {1, inputTensor2}};
238 
239  std::pair<LayerBindingId, class Tensor> output1{2, outputTensor1};
240  std::pair<LayerBindingId, class Tensor> output2{3, outputTensor2};
241 
242  auto testOutputs = [&]()
243  {
244  for (auto val : outputData1)
245  {
246  CHECK(val == 1.0f);
247  }
248 
249  for (auto val : outputData2)
250  {
251  CHECK(val == 3.0f);
252  }
253  };
254 
255  auto memHandle = runtime->CreateWorkingMemHandle(networkId);
256 
257  runtime->Execute(*memHandle.get(),inputTensors, {output1, output2});
258  testOutputs();
259 
260  auto importedOutputVec = runtime->ImportOutputs(networkId, {output1, output2 });
261  CHECK(importedOutputVec.size() == 2);
262  CHECK(importedOutputVec[0] == 0);
263  CHECK(importedOutputVec[1] == 1);
264 
265  runtime->Execute(*memHandle.get(), inputTensors, {}, {}, importedOutputVec);
266  testOutputs();
267 
268  runtime->Execute(*memHandle.get(), inputTensors, {output1}, {}, {1});
269  testOutputs();
270 
271  runtime->Execute(*memHandle.get(), inputTensors, {output2}, {}, {0});
272  testOutputs();
273 
274  auto importedInputVec = runtime->ImportInputs(networkId, inputTensors);
275  CHECK(importedInputVec.size() == 2);
276  CHECK(importedInputVec[0] == 0);
277  CHECK(importedInputVec[1] == 1);
278 
279  runtime->Execute(*memHandle.get(), {}, {}, importedInputVec, importedOutputVec);
280  testOutputs();
281 
282  runtime->Execute(*memHandle.get(), {{0, inputTensor1}}, {output2}, {1}, {0});
283  testOutputs();
284 
285  // Too many ids
286  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {output1, output2}, {}, {0, 1});,
288 
289  // Duplicate ids
290  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {output2}, {}, {1});,
292 
293  // Duplicate ids
294  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {output1, output1}, {}, {});,
296 
297  // Duplicate ids
298  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {}, {}, {0, 0}),
300 
301  // Unknown id
302  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {output1}, {}, {3});,
304 
305  // Unknown id
306  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {{4, outputTensor2}}, {}, {1});,
308 
309  // Input id for output
310  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {{0, outputTensor2}}, {}, {1});,
312 
313  // Input id for output
314  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {{0, outputTensor2}}, {}, {1});,
316 
317  // Output id for input
318  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), {{2, inputTensor1}}, {{0, outputTensor2}}, {1}, {1, 0});,
320 
321  runtime->ClearImportedOutputs(networkId, {1});
322 
323  runtime->Execute(*memHandle.get(), inputTensors, {output2}, {}, {0});
324  testOutputs();
325 
326  // Trying to use deleted pre-imported tensor
327  CHECK_THROWS_AS(runtime->Execute(*memHandle.get(), inputTensors, {}, {}, importedOutputVec),
329 
330  // Trying to delete deleted pre-imported tensor
331  CHECK_THROWS_AS(runtime->ClearImportedOutputs(networkId, {1});, armnn::InvalidArgumentException);
332 
333  // Trying to delete unknown pre-imported tensor
334  CHECK_THROWS_AS(runtime->ClearImportedOutputs(networkId, {10});, armnn::InvalidArgumentException);
335 }
336 
337 // Note: the current builds we don't do valgrind and gperftools based leak checking at the same
338 // time, so in practice WITH_VALGRIND and ARMNN_LEAK_CHECKING_ENABLED are exclusive. The
339 // valgrind tests can stay for x86 builds, but on hikey Valgrind is just way too slow
340 // to be integrated into the CI system.
341 
342 #ifdef ARMNN_LEAK_CHECKING_ENABLED
343 
344 struct DisableGlobalLeakChecking
345 {
346  DisableGlobalLeakChecking()
347  {
349  }
350 };
351 
352 TEST_CASE_FIXTURE(DisableGlobalLeakChecking, "RuntimeHeapMemoryUsageSanityChecks")
353 {
355  {
356  ARMNN_SCOPED_LEAK_CHECKER("Sanity_Check_Outer");
357  {
358  ARMNN_SCOPED_LEAK_CHECKER("Sanity_Check_Inner");
359  CHECK(ARMNN_NO_LEAKS_IN_SCOPE() == true);
360  std::unique_ptr<char[]> dummyAllocation(new char[1000]);
361  // "A leak of 1000 bytes is expected here. "
362  // "Please make sure environment variable: HEAPCHECK=draconian is set!"
363  CHECK((ARMNN_NO_LEAKS_IN_SCOPE() == false));
364  CHECK(ARMNN_BYTES_LEAKED_IN_SCOPE() == 1000);
365  CHECK(ARMNN_OBJECTS_LEAKED_IN_SCOPE() == 1);
366  }
367  CHECK(ARMNN_NO_LEAKS_IN_SCOPE());
368  CHECK(ARMNN_BYTES_LEAKED_IN_SCOPE() == 0);
369  CHECK(ARMNN_OBJECTS_LEAKED_IN_SCOPE() == 0);
370  }
371 }
372 
373 #endif // ARMNN_LEAK_CHECKING_ENABLED
374 
375 // Note: this part of the code is due to be removed when we fully trust the gperftools based results.
376 #ifdef WITH_VALGRIND
377 // Run with the following command to get all the amazing output (in the devenv/build folder) :)
378 // valgrind --leak-check=full --show-leak-kinds=all --log-file=Valgrind_Memcheck_Leak_Report.txt armnn/test/UnitTests
379 TEST_CASE("RuntimeMemoryLeak")
380 {
381  // From documentation:
382 
383  // This means that no pointer to the block can be found. The block is classified as "lost",
384  // because the programmer could not possibly have freed it at program exit, since no pointer to it exists.
385  unsigned long leakedBefore = 0;
386  unsigned long leakedAfter = 0;
387 
388  // A start-pointer or chain of start-pointers to the block is found. Since the block is still pointed at,
389  // the programmer could, at least in principle, have freed it before program exit.
390  // We want to test this in case memory is not freed as early as it could have been.
391  unsigned long reachableBefore = 0;
392  unsigned long reachableAfter = 0;
393 
394  // Needed as out params but we don't test them.
395  unsigned long dubious = 0;
396  unsigned long suppressed = 0;
397 
398  armnn::NetworkId networkIdentifier1 = 1;
399 
400  // ensure that runtime is large enough before checking for memory leaks
401  // otherwise when loading the network it will automatically reserve memory that won't be released until destruction
403  armnn::RuntimeImpl runtime(options);
405 
406  {
407  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
408 
410  mockNetwork1->AddInputLayer(0, "test layer");
411 
412  // Warm-up load/unload pair to put the runtime in a stable state (memory-wise).
413  runtime.LoadNetwork(networkIdentifier1, Optimize(*mockNetwork1, backends, runtime.GetDeviceSpec()));
414  runtime.UnloadNetwork(networkIdentifier1);
415 
416  // Checks for leaks before we load the network and record them so that we can see the delta after unloading.
417  VALGRIND_DO_QUICK_LEAK_CHECK;
418  VALGRIND_COUNT_LEAKS(leakedBefore, dubious, reachableBefore, suppressed);
419 
420  // The actual test.
421  runtime.LoadNetwork(networkIdentifier1, Optimize(*mockNetwork1, backends, runtime.GetDeviceSpec()));
422  runtime.UnloadNetwork(networkIdentifier1);
423 
424  VALGRIND_DO_ADDED_LEAK_CHECK;
425  VALGRIND_COUNT_LEAKS(leakedAfter, dubious, reachableAfter, suppressed);
426  }
427 
428  // If we're not running under Valgrind, these vars will have been initialised to 0, so this will always pass.
429  CHECK(leakedBefore == leakedAfter);
430  CHECK(reachableBefore == reachableAfter);
431 
432  // These are needed because VALGRIND_COUNT_LEAKS is a macro that assigns to the parameters
433  // so they are assigned to, but still considered unused, causing a warning.
434  armnn::IgnoreUnused(dubious);
435  armnn::IgnoreUnused(suppressed);
436 }
437 #endif // WITH_VALGRIND
438 
439 TEST_CASE("RuntimeCpuRef")
440 {
441  using namespace armnn;
442 
443  // Create runtime in which test will run
446 
447  // build up the structure of the network
448  INetworkPtr net(INetwork::Create());
449 
450  IConnectableLayer* input = net->AddInputLayer(0);
451 
452  // This layer configuration isn't supported by CpuAcc, should be fall back to CpuRef.
453  NormalizationDescriptor descriptor;
454  IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
455 
456  IConnectableLayer* output = net->AddOutputLayer(0);
457 
458  input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
459  normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
460 
461  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
462  normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
463 
464  // optimize the network
465  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
466  IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec());
467 
468  // Load it into the runtime. It should success.
469  armnn::NetworkId netId;
470  CHECK(runtime->LoadNetwork(netId, std::move(optNet)) == Status::Success);
471 }
472 
473 TEST_CASE("RuntimeFallbackToCpuRef")
474 {
475  using namespace armnn;
476 
477  // Create runtime in which test will run
480 
481  // build up the structure of the network
482  INetworkPtr net(INetwork::Create());
483 
484  IConnectableLayer* input = net->AddInputLayer(0);
485 
486  // This layer configuration isn't supported by CpuAcc, should be fall back to CpuRef.
487  NormalizationDescriptor descriptor;
488  IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
489 
490  IConnectableLayer* output = net->AddOutputLayer(0);
491 
492  input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
493  normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
494 
495  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
496  normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
497 
498  // Allow fallback to CpuRef.
499  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc, armnn::Compute::CpuRef };
500  // optimize the network
501  IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec());
502 
503  // Load it into the runtime. It should succeed.
504  armnn::NetworkId netId;
505  CHECK(runtime->LoadNetwork(netId, std::move(optNet)) == Status::Success);
506 }
507 
508 TEST_CASE("IVGCVSW_1929_QuantizedSoftmaxIssue")
509 {
510  // Test for issue reported by Chris Nix in https://jira.arm.com/browse/IVGCVSW-1929
511  using namespace armnn;
512 
513  // Create runtime in which test will run
516 
517  // build up the structure of the network
518  INetworkPtr net(INetwork::Create());
519  armnn::IConnectableLayer* input = net->AddInputLayer(0,"input");
520  armnn::IConnectableLayer* softmax = net->AddSoftmaxLayer(armnn::SoftmaxDescriptor(), "softmax");
521  armnn::IConnectableLayer* output = net->AddOutputLayer(0, "output");
522 
523  input->GetOutputSlot(0).Connect(softmax->GetInputSlot(0));
524  softmax->GetOutputSlot(0).Connect(output->GetInputSlot(0));
525 
528  1.0f / 255,
529  0));
530 
533 
534  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
535  std::vector<std::string> errMessages;
536 
537  try
538  {
540  backends,
541  runtime->GetDeviceSpec(),
543  errMessages);
544  FAIL("An exception should have been thrown");
545  }
546  catch (const armnn::InvalidArgumentException&)
547  {
548  // Different exceptions are thrown on different backends
549  }
550  CHECK(errMessages.size() > 0);
551 }
552 
553 TEST_CASE("RuntimeBackendOptions")
554 {
555  using namespace armnn;
556 
557  IRuntime::CreationOptions creationOptions;
558  auto& backendOptions = creationOptions.m_BackendOptions;
559 
560 
561  // Define Options on explicit construction
562  BackendOptions options1("FakeBackend1",
563  {
564  { "Option1", 1.3f },
565  { "Option2", true }
566  });
567 
568  // Add an option after construction
569  options1.AddOption({ "Option3", "some_value" });
570 
571  // Add the options to CreationOptions struct
572  backendOptions.push_back(options1);
573 
574  // Add more Options via inplace explicit construction
575  backendOptions.emplace_back(BackendOptions{ "FakeBackend1",
576  {{ "Option4", 42 }}
577  });
578 
579 
580  // First group
581  CHECK(backendOptions[0].GetBackendId().Get() == "FakeBackend1");
582  CHECK(backendOptions[0].GetOption(0).GetName() == "Option1");
583  CHECK(backendOptions[0].GetOption(0).GetValue().IsFloat() == true);
584  CHECK(backendOptions[0].GetOption(0).GetValue().AsFloat() == 1.3f);
585 
586  CHECK(backendOptions[0].GetOption(1).GetName() == "Option2");
587  CHECK(backendOptions[0].GetOption(1).GetValue().IsBool() == true);
588  CHECK(backendOptions[0].GetOption(1).GetValue().AsBool() == true);
589 
590  CHECK(backendOptions[0].GetOption(2).GetName() == "Option3");
591  CHECK(backendOptions[0].GetOption(2).GetValue().IsString() == true);
592  CHECK(backendOptions[0].GetOption(2).GetValue().AsString() == "some_value");
593 
594  // Second group
595  CHECK(backendOptions[1].GetBackendId().Get() == "FakeBackend1");
596  CHECK(backendOptions[1].GetOption(0).GetName() == "Option4");
597  CHECK(backendOptions[1].GetOption(0).GetValue().IsInt() == true);
598  CHECK(backendOptions[1].GetOption(0).GetValue().AsInt() == 42);
599 }
600 
601 TEST_CASE("ProfilingDisable")
602 {
603  using namespace armnn;
604 
605  LogLevelSwapper logLevelSwapper(arm::pipe::LogSeverity::Fatal);
606 
607  // Create runtime in which the test will run
609  armnn::RuntimeImpl runtime(options);
610 
611  // build up the structure of the network
612  INetworkPtr net(INetwork::Create());
613 
614  IConnectableLayer* input = net->AddInputLayer(0);
615 
616  // This layer configuration isn't supported by CpuAcc, should fall back to CpuRef.
617  NormalizationDescriptor descriptor;
618  IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor);
619 
620  IConnectableLayer* output = net->AddOutputLayer(0);
621 
622  input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
623  normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
624 
625  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
626  normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
627 
628  // optimize the network
629  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
630  IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime.GetDeviceSpec());
631 
632  // Load it into the runtime. It should succeed.
633  armnn::NetworkId netId;
634  CHECK(runtime.LoadNetwork(netId, std::move(optNet)) == Status::Success);
635 
637  ProfilingServiceRuntimeHelper profilingServiceHelper(
638  arm::pipe::MAX_ARMNN_COUNTER, initialiser, GetProfilingService(&runtime));
639  BufferManager& bufferManager = profilingServiceHelper.GetProfilingBufferManager();
640  auto readableBuffer = bufferManager.GetReadableBuffer();
641 
642  // Profiling is not enabled, the post-optimisation structure should not be created
643  CHECK(!readableBuffer);
644 }
645 
646 TEST_CASE("ProfilingEnableCpuRef")
647 {
648  using namespace armnn;
649  using namespace arm::pipe;
650 
651  // Create runtime in which the test will run
653  options.m_ProfilingOptions.m_EnableProfiling = true;
654  options.m_ProfilingOptions.m_TimelineEnabled = true;
655 
656  armnn::RuntimeImpl runtime(options);
657  GetProfilingService(&runtime).ResetExternalProfilingOptions(
659 
661  ProfilingServiceRuntimeHelper profilingServiceHelper(
662  arm::pipe::MAX_ARMNN_COUNTER, initialiser, GetProfilingService(&runtime));
663  profilingServiceHelper.ForceTransitionToState(ProfilingState::NotConnected);
664  profilingServiceHelper.ForceTransitionToState(ProfilingState::WaitingForAck);
665  profilingServiceHelper.ForceTransitionToState(ProfilingState::Active);
666 
667  // build up the structure of the network
668  INetworkPtr net(INetwork::Create());
669 
670  IConnectableLayer* input = net->AddInputLayer(0, "input");
671 
672  NormalizationDescriptor descriptor;
673  IConnectableLayer* normalize = net->AddNormalizationLayer(descriptor, "normalization");
674 
675  IConnectableLayer* output = net->AddOutputLayer(0, "output");
676 
677  input->GetOutputSlot(0).Connect(normalize->GetInputSlot(0));
678  normalize->GetOutputSlot(0).Connect(output->GetInputSlot(0));
679 
680  input->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
681  normalize->GetOutputSlot(0).SetTensorInfo(TensorInfo({ 1, 1, 4, 4 }, DataType::Float32));
682 
683  // optimize the network
684  std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
685  IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime.GetDeviceSpec());
686 
687  ProfilingGuid optNetGuid = optNet->GetGuid();
688 
689  // Load it into the runtime. It should succeed.
690  armnn::NetworkId netId;
691  CHECK(runtime.LoadNetwork(netId, std::move(optNet)) == Status::Success);
692 
693  BufferManager& bufferManager = profilingServiceHelper.GetProfilingBufferManager();
694  auto readableBuffer = bufferManager.GetReadableBuffer();
695 
696  // Profiling is enabled, the post-optimisation structure should be created
697  CHECK(readableBuffer != nullptr);
698 
699  unsigned int size = readableBuffer->GetSize();
700 
701  const unsigned char* readableData = readableBuffer->GetReadableData();
702  CHECK(readableData != nullptr);
703 
704  unsigned int offset = 0;
705 
706  // Verify Header
707  VerifyTimelineHeaderBinary(readableData, offset, size - 8);
708 
709  // Post-optimisation network
710  // Network entity
711  VerifyTimelineEntityBinaryPacketData(optNetGuid, readableData, offset);
712 
713  // Entity - Type relationship
714  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
715  arm::pipe::EmptyOptional(),
716  optNetGuid,
717  LabelsAndEventClasses::NETWORK_GUID,
718  LabelsAndEventClasses::TYPE_GUID,
719  readableData,
720  offset);
721 
722  // Network - START OF LIFE
723  ProfilingGuid networkSolEventGuid = VerifyTimelineEventBinaryPacket(arm::pipe::EmptyOptional(),
724  arm::pipe::EmptyOptional(),
725  arm::pipe::EmptyOptional(),
726  readableData,
727  offset);
728 
729  // Network - START OF LIFE event relationship
730  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
731  arm::pipe::EmptyOptional(),
732  optNetGuid,
733  networkSolEventGuid,
734  LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
735  readableData,
736  offset);
737 
738  // Process ID Label
739  int processID = arm::pipe::GetCurrentProcessId();
740  std::stringstream ss;
741  ss << processID;
742  std::string processIdLabel = ss.str();
743  VerifyTimelineLabelBinaryPacketData(arm::pipe::EmptyOptional(), processIdLabel, readableData, offset);
744 
745  // Entity - Process ID relationship
746  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
747  arm::pipe::EmptyOptional(),
748  optNetGuid,
749  arm::pipe::EmptyOptional(),
750  LabelsAndEventClasses::PROCESS_ID_GUID,
751  readableData,
752  offset);
753 
754  // Input layer
755  // Input layer entity
756  VerifyTimelineEntityBinaryPacketData(input->GetGuid(), readableData, offset);
757 
758  // Name Entity
759  ProfilingGuid inputLabelGuid = VerifyTimelineLabelBinaryPacketData(
760  arm::pipe::EmptyOptional(), "input", readableData, offset);
761 
762  // Entity - Name relationship
763  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
764  arm::pipe::EmptyOptional(),
765  input->GetGuid(),
766  inputLabelGuid,
767  LabelsAndEventClasses::NAME_GUID,
768  readableData,
769  offset);
770 
771  // Entity - Type relationship
772  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
773  arm::pipe::EmptyOptional(),
774  input->GetGuid(),
775  LabelsAndEventClasses::LAYER_GUID,
776  LabelsAndEventClasses::TYPE_GUID,
777  readableData,
778  offset);
779 
780  // Network - Input layer relationship
781  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
782  arm::pipe::EmptyOptional(),
783  optNetGuid,
784  input->GetGuid(),
785  LabelsAndEventClasses::CHILD_GUID,
786  readableData,
787  offset);
788 
789  // Normalization layer
790  // Normalization layer entity
791  VerifyTimelineEntityBinaryPacketData(normalize->GetGuid(), readableData, offset);
792 
793  // Name entity
794  ProfilingGuid normalizationLayerNameGuid = VerifyTimelineLabelBinaryPacketData(
795  arm::pipe::EmptyOptional(), "normalization", readableData, offset);
796 
797  // Entity - Name relationship
798  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
799  arm::pipe::EmptyOptional(),
800  normalize->GetGuid(),
801  normalizationLayerNameGuid,
802  LabelsAndEventClasses::NAME_GUID,
803  readableData,
804  offset);
805 
806  // Entity - Type relationship
807  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
808  arm::pipe::EmptyOptional(),
809  normalize->GetGuid(),
810  LabelsAndEventClasses::LAYER_GUID,
811  LabelsAndEventClasses::TYPE_GUID,
812  readableData,
813  offset);
814 
815  // Network - Normalize layer relationship
816  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
817  arm::pipe::EmptyOptional(),
818  optNetGuid,
819  normalize->GetGuid(),
820  LabelsAndEventClasses::CHILD_GUID,
821  readableData,
822  offset);
823 
824  // Input layer - Normalize layer relationship
825  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
826  arm::pipe::EmptyOptional(),
827  input->GetGuid(),
828  normalize->GetGuid(),
829  LabelsAndEventClasses::CONNECTION_GUID,
830  readableData,
831  offset);
832 
833  // Normalization workload
834  // Normalization workload entity
835  ProfilingGuid normalizationWorkloadGuid = VerifyTimelineEntityBinaryPacketData(
836  arm::pipe::EmptyOptional(), readableData, offset);
837 
838  // Entity - Type relationship
839  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
840  arm::pipe::EmptyOptional(),
841  normalizationWorkloadGuid,
842  LabelsAndEventClasses::WORKLOAD_GUID,
843  LabelsAndEventClasses::TYPE_GUID,
844  readableData,
845  offset);
846 
847  // BackendId entity
848  ProfilingGuid cpuRefLabelGuid = VerifyTimelineLabelBinaryPacketData(
849  arm::pipe::EmptyOptional(), "CpuRef", readableData, offset);
850 
851  // Entity - BackendId relationship
852  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
853  arm::pipe::EmptyOptional(),
854  normalizationWorkloadGuid,
855  cpuRefLabelGuid,
856  LabelsAndEventClasses::BACKENDID_GUID,
857  readableData,
858  offset);
859 
860  // Normalize layer - Normalize workload relationship
861  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
862  arm::pipe::EmptyOptional(),
863  normalize->GetGuid(),
864  normalizationWorkloadGuid,
865  LabelsAndEventClasses::CHILD_GUID,
866  readableData,
867  offset);
868 
869  // Output layer
870  // Output layer entity
871  VerifyTimelineEntityBinaryPacketData(output->GetGuid(), readableData, offset);
872 
873  // Name entity
874  ProfilingGuid outputLabelGuid = VerifyTimelineLabelBinaryPacketData(
875  arm::pipe::EmptyOptional(), "output", readableData, offset);
876 
877  // Entity - Name relationship
878  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
879  arm::pipe::EmptyOptional(),
880  output->GetGuid(),
881  outputLabelGuid,
882  LabelsAndEventClasses::NAME_GUID,
883  readableData,
884  offset);
885 
886  // Entity - Type relationship
887  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
888  arm::pipe::EmptyOptional(),
889  output->GetGuid(),
890  LabelsAndEventClasses::LAYER_GUID,
891  LabelsAndEventClasses::TYPE_GUID,
892  readableData,
893  offset);
894 
895  // Network - Output layer relationship
896  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
897  arm::pipe::EmptyOptional(),
898  optNetGuid,
899  output->GetGuid(),
900  LabelsAndEventClasses::CHILD_GUID,
901  readableData,
902  offset);
903 
904  // Normalize layer - Output layer relationship
905  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
906  arm::pipe::EmptyOptional(),
907  normalize->GetGuid(),
908  output->GetGuid(),
909  LabelsAndEventClasses::CONNECTION_GUID,
910  readableData,
911  offset);
912 
913  bufferManager.MarkRead(readableBuffer);
914 
915  // Creates structures for input & output.
916  std::vector<float> inputData(16);
917  std::vector<float> outputData(16);
918 
919  TensorInfo inputTensorInfo = runtime.GetInputTensorInfo(netId, 0);
920  inputTensorInfo.SetConstant(true);
921  InputTensors inputTensors
922  {
923  {0, ConstTensor(inputTensorInfo, inputData.data())}
924  };
925  OutputTensors outputTensors
926  {
927  {0, Tensor(runtime.GetOutputTensorInfo(netId, 0), outputData.data())}
928  };
929 
930  // Does the inference.
931  runtime.EnqueueWorkload(netId, inputTensors, outputTensors);
932 
933  // Get readable buffer for input workload
934  auto inputReadableBuffer = bufferManager.GetReadableBuffer();
935  CHECK(inputReadableBuffer != nullptr);
936 
937  // Get readable buffer for output workload
938  auto outputReadableBuffer = bufferManager.GetReadableBuffer();
939  CHECK(outputReadableBuffer != nullptr);
940 
941  // Get readable buffer for inference timeline
942  auto inferenceReadableBuffer = bufferManager.GetReadableBuffer();
943  CHECK(inferenceReadableBuffer != nullptr);
944 
945  // Validate input workload data
946  size = inputReadableBuffer->GetSize();
947  CHECK(size == 164);
948 
949  readableData = inputReadableBuffer->GetReadableData();
950  CHECK(readableData != nullptr);
951 
952  offset = 0;
953 
954  // Verify Header
955  VerifyTimelineHeaderBinary(readableData, offset, 156);
956 
957  // Input workload
958  // Input workload entity
959  ProfilingGuid inputWorkloadGuid = VerifyTimelineEntityBinaryPacketData(
960  arm::pipe::EmptyOptional(), readableData, offset);
961 
962  // Entity - Type relationship
963  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
964  arm::pipe::EmptyOptional(),
965  inputWorkloadGuid,
966  LabelsAndEventClasses::WORKLOAD_GUID,
967  LabelsAndEventClasses::TYPE_GUID,
968  readableData,
969  offset);
970 
971  // BackendId entity
972  ProfilingGuid CpuRefLabelGuid = VerifyTimelineLabelBinaryPacketData(
973  arm::pipe::EmptyOptional(), "CpuRef", readableData, offset);
974 
975  // Entity - BackendId relationship
976  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
977  arm::pipe::EmptyOptional(),
978  inputWorkloadGuid,
979  CpuRefLabelGuid,
980  LabelsAndEventClasses::BACKENDID_GUID,
981  readableData,
982  offset);
983 
984  // Input layer - Input workload relationship
985  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
986  arm::pipe::EmptyOptional(),
987  input->GetGuid(),
988  inputWorkloadGuid,
989  LabelsAndEventClasses::CHILD_GUID,
990  readableData,
991  offset);
992 
993  bufferManager.MarkRead(inputReadableBuffer);
994 
995  // Validate output workload data
996  size = outputReadableBuffer->GetSize();
997  CHECK(size == 164);
998 
999  readableData = outputReadableBuffer->GetReadableData();
1000  CHECK(readableData != nullptr);
1001 
1002  offset = 0;
1003 
1004  // Verify Header
1005  VerifyTimelineHeaderBinary(readableData, offset, 156);
1006 
1007  // Output workload
1008  // Output workload entity
1009  ProfilingGuid outputWorkloadGuid = VerifyTimelineEntityBinaryPacketData(
1010  arm::pipe::EmptyOptional(), readableData, offset);
1011 
1012  // Entity - Type relationship
1013  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1014  arm::pipe::EmptyOptional(),
1015  outputWorkloadGuid,
1016  LabelsAndEventClasses::WORKLOAD_GUID,
1017  LabelsAndEventClasses::TYPE_GUID,
1018  readableData,
1019  offset);
1020 
1021  // BackendId entity
1022  VerifyTimelineLabelBinaryPacketData(arm::pipe::EmptyOptional(), "CpuRef", readableData, offset);
1023 
1024  // Entity - BackendId relationship
1025  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1026  arm::pipe::EmptyOptional(),
1027  outputWorkloadGuid,
1028  CpuRefLabelGuid,
1029  LabelsAndEventClasses::BACKENDID_GUID,
1030  readableData,
1031  offset);
1032 
1033  // Output layer - Output workload relationship
1034  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1035  arm::pipe::EmptyOptional(),
1036  output->GetGuid(),
1037  outputWorkloadGuid,
1038  LabelsAndEventClasses::CHILD_GUID,
1039  readableData,
1040  offset);
1041 
1042  bufferManager.MarkRead(outputReadableBuffer);
1043 
1044  // Validate inference data
1045  size = inferenceReadableBuffer->GetSize();
1046  CHECK(size == 976 + 8 * ThreadIdSize);
1047 
1048  readableData = inferenceReadableBuffer->GetReadableData();
1049  CHECK(readableData != nullptr);
1050 
1051  offset = 0;
1052 
1053  // Verify Header
1054  VerifyTimelineHeaderBinary(readableData, offset, 968 + 8 * ThreadIdSize);
1055 
1056  // Inference timeline trace
1057  // Inference entity
1058  ProfilingGuid inferenceGuid = VerifyTimelineEntityBinaryPacketData(
1059  arm::pipe::EmptyOptional(), readableData, offset);
1060 
1061  // Entity - Type relationship
1062  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1063  arm::pipe::EmptyOptional(),
1064  inferenceGuid,
1065  LabelsAndEventClasses::INFERENCE_GUID,
1066  LabelsAndEventClasses::TYPE_GUID,
1067  readableData,
1068  offset);
1069 
1070  // Network - Inference relationship
1071  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1072  arm::pipe::EmptyOptional(),
1073  optNetGuid,
1074  inferenceGuid,
1075  LabelsAndEventClasses::EXECUTION_OF_GUID,
1076  readableData,
1077  offset);
1078 
1079  // Start Inference life
1080  // Event packet - timeline, threadId, eventGuid
1081  ProfilingGuid inferenceEventGuid = VerifyTimelineEventBinaryPacket(
1082  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1083 
1084  // Inference - event relationship
1085  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1086  arm::pipe::EmptyOptional(),
1087  inferenceGuid,
1088  inferenceEventGuid,
1089  LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
1090  readableData,
1091  offset);
1092 
1093  // Execution
1094  // Input workload execution
1095  // Input workload execution entity
1096  ProfilingGuid inputWorkloadExecutionGuid = VerifyTimelineEntityBinaryPacketData(
1097  arm::pipe::EmptyOptional(), readableData, offset);
1098 
1099  // Entity - Type relationship
1100  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1101  arm::pipe::EmptyOptional(),
1102  inputWorkloadExecutionGuid,
1103  LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID,
1104  LabelsAndEventClasses::TYPE_GUID,
1105  readableData,
1106  offset);
1107 
1108  // Inference - Workload execution relationship
1109  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1110  arm::pipe::EmptyOptional(),
1111  inferenceGuid,
1112  inputWorkloadExecutionGuid,
1113  LabelsAndEventClasses::CHILD_GUID,
1114  readableData,
1115  offset);
1116 
1117  // Workload - Workload execution relationship
1118  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1119  arm::pipe::EmptyOptional(),
1120  inputWorkloadGuid,
1121  inputWorkloadExecutionGuid,
1122  LabelsAndEventClasses::EXECUTION_OF_GUID,
1123  readableData,
1124  offset);
1125 
1126  // Start Input workload execution life
1127  // Event packet - timeline, threadId, eventGuid
1128  ProfilingGuid inputWorkloadExecutionSOLEventId = VerifyTimelineEventBinaryPacket(
1129  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1130 
1131  // Input workload execution - event relationship
1132  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1133  arm::pipe::EmptyOptional(),
1134  inputWorkloadExecutionGuid,
1135  inputWorkloadExecutionSOLEventId,
1136  LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
1137  readableData,
1138  offset);
1139 
1140  // End of Input workload execution life
1141  // Event packet - timeline, threadId, eventGuid
1142  ProfilingGuid inputWorkloadExecutionEOLEventId = VerifyTimelineEventBinaryPacket(
1143  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1144 
1145  // Input workload execution - event relationship
1146  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1147  arm::pipe::EmptyOptional(),
1148  inputWorkloadExecutionGuid,
1149  inputWorkloadExecutionEOLEventId,
1150  LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS,
1151  readableData,
1152  offset);
1153 
1154  // Normalize workload execution
1155  // Normalize workload execution entity
1156  ProfilingGuid normalizeWorkloadExecutionGuid = VerifyTimelineEntityBinaryPacketData(
1157  arm::pipe::EmptyOptional(), readableData, offset);
1158 
1159  // Entity - Type relationship
1160  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1161  arm::pipe::EmptyOptional(),
1162  normalizeWorkloadExecutionGuid,
1163  LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID,
1164  LabelsAndEventClasses::TYPE_GUID,
1165  readableData,
1166  offset);
1167 
1168  // Inference - Workload execution relationship
1169  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1170  arm::pipe::EmptyOptional(),
1171  inferenceGuid,
1172  normalizeWorkloadExecutionGuid,
1173  LabelsAndEventClasses::CHILD_GUID,
1174  readableData,
1175  offset);
1176 
1177  // Workload - Workload execution relationship
1178  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1179  arm::pipe::EmptyOptional(),
1180  normalizationWorkloadGuid,
1181  normalizeWorkloadExecutionGuid,
1182  LabelsAndEventClasses::EXECUTION_OF_GUID,
1183  readableData,
1184  offset);
1185 
1186  // Start Normalize workload execution life
1187  // Event packet - timeline, threadId, eventGuid
1188  ProfilingGuid normalizationWorkloadExecutionSOLEventGuid = VerifyTimelineEventBinaryPacket(
1189  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1190 
1191  // Normalize workload execution - event relationship
1192  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1193  arm::pipe::EmptyOptional(),
1194  normalizeWorkloadExecutionGuid,
1195  normalizationWorkloadExecutionSOLEventGuid,
1196  LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
1197  readableData,
1198  offset);
1199 
1200  // End of Normalize workload execution life
1201  // Event packet - timeline, threadId, eventGuid
1202  ProfilingGuid normalizationWorkloadExecutionEOLEventGuid = VerifyTimelineEventBinaryPacket(
1203  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1204 
1205  // Normalize workload execution - event relationship
1206  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1207  arm::pipe::EmptyOptional(),
1208  normalizeWorkloadExecutionGuid,
1209  normalizationWorkloadExecutionEOLEventGuid,
1210  LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS,
1211  readableData,
1212  offset);
1213 
1214  // Output workload execution
1215  // Output workload execution entity
1216  ProfilingGuid outputWorkloadExecutionGuid = VerifyTimelineEntityBinaryPacketData(
1217  arm::pipe::EmptyOptional(), readableData, offset);
1218 
1219  // Entity - Type relationship
1220  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::LabelLink,
1221  arm::pipe::EmptyOptional(),
1222  outputWorkloadExecutionGuid,
1223  LabelsAndEventClasses::WORKLOAD_EXECUTION_GUID,
1224  LabelsAndEventClasses::TYPE_GUID,
1225  readableData,
1226  offset);
1227 
1228  // Inference - Workload execution relationship
1229  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1230  arm::pipe::EmptyOptional(),
1231  inferenceGuid,
1232  outputWorkloadExecutionGuid,
1233  LabelsAndEventClasses::CHILD_GUID,
1234  readableData,
1235  offset);
1236 
1237  // Workload - Workload execution relationship
1238  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::RetentionLink,
1239  arm::pipe::EmptyOptional(),
1240  outputWorkloadGuid,
1241  outputWorkloadExecutionGuid,
1242  LabelsAndEventClasses::EXECUTION_OF_GUID,
1243  readableData,
1244  offset);
1245 
1246  // Start Output workload execution life
1247  // Event packet - timeline, threadId, eventGuid
1248  ProfilingGuid outputWorkloadExecutionSOLEventGuid = VerifyTimelineEventBinaryPacket(
1249  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1250 
1251  // Output workload execution - event relationship
1252  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1253  arm::pipe::EmptyOptional(),
1254  outputWorkloadExecutionGuid,
1255  outputWorkloadExecutionSOLEventGuid,
1256  LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS,
1257  readableData,
1258  offset);
1259 
1260  // End of Normalize workload execution life
1261  // Event packet - timeline, threadId, eventGuid
1262  ProfilingGuid outputWorkloadExecutionEOLEventGuid = VerifyTimelineEventBinaryPacket(
1263  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1264 
1265  // Output workload execution - event relationship
1266  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1267  arm::pipe::EmptyOptional(),
1268  outputWorkloadExecutionGuid,
1269  outputWorkloadExecutionEOLEventGuid,
1270  LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS,
1271  readableData,
1272  offset);
1273 
1274  // End of Inference life
1275  // Event packet - timeline, threadId, eventGuid
1276  ProfilingGuid inferenceEOLEventGuid = VerifyTimelineEventBinaryPacket(
1277  arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), arm::pipe::EmptyOptional(), readableData, offset);
1278 
1279  // Inference - event relationship
1280  VerifyTimelineRelationshipBinaryPacketData(ProfilingRelationshipType::ExecutionLink,
1281  arm::pipe::EmptyOptional(),
1282  inferenceGuid,
1283  inferenceEOLEventGuid,
1284  LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS,
1285  readableData,
1286  offset);
1287 
1288  bufferManager.MarkRead(inferenceReadableBuffer);
1289 }
1290 
1291 TEST_CASE("ProfilingPostOptimisationStructureCpuRef")
1292 {
1293  VerifyPostOptimisationStructureTestImpl(armnn::Compute::CpuRef);
1294 }
1295 
1296 }
#define ARMNN_SCOPED_LEAK_CHECKER(TAG)
#define ARMNN_LOCAL_LEAK_CHECKING_ONLY()
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:66
void VerifyPostOptimisationStructureTestImpl(armnn::BackendId backendId)
CPU Execution: Reference C++ kernels.
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
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Definition: Tensor.hpp:392
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:1847
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:242
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:137
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:36
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
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:241
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:476
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