ArmNN
 22.02
RuntimeTests.cpp File Reference
#include <armnn/Descriptors.hpp>
#include <armnn/IRuntime.hpp>
#include <armnn/INetwork.hpp>
#include <Processes.hpp>
#include <Runtime.hpp>
#include <armnn/TypesUtils.hpp>
#include <common/include/LabelsAndEventClasses.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 37 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(), armnn::CpuAcc, armnn::CpuRef, IRuntime::Create(), INetwork::Create(), RuntimeImpl::EnqueueWorkload(), armnn::Failure, armnn::Float32, ProfilingServiceRuntimeHelper::ForceTransitionToState(), GetBackendId(), armnnUtils::Processes::GetCurrentId(), RuntimeImpl::GetDeviceSpec(), IConnectableLayer::GetGuid(), IConnectableLayer::GetInputSlot(), RuntimeImpl::GetInputTensorInfo(), IConnectableLayer::GetOutputSlot(), RuntimeImpl::GetOutputTensorInfo(), ProfilingServiceRuntimeHelper::GetProfilingBufferManager(), armnn::GetProfilingService(), BufferManager::GetReadableBuffer(), 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, ProfilingService::ResetExternalProfilingOptions(), armnn::RuntimeLoadedNetworksReserve(), TensorInfo::SetConstant(), IOutputSlot::SetTensorInfo(), armnn::Signed32, armnn::Success, TEST_CASE_FIXTURE(), armnn::profiling::ThreadIdSize, armnn::Undefined, RuntimeImpl::UnloadNetwork(), VerifyPostOptimisationStructureTestImpl(), VerifyTimelineEntityBinaryPacketData(), VerifyTimelineEventBinaryPacket(), VerifyTimelineHeaderBinary(), VerifyTimelineLabelBinaryPacketData(), and VerifyTimelineRelationshipBinaryPacketData().

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