ArmNN
 21.08
LoadedNetwork Class Reference

#include <LoadedNetwork.hpp>

Public Types

using WorkloadQueue = std::vector< std::unique_ptr< IWorkload > >
 

Public Member Functions

 ~LoadedNetwork ()
 
std::unique_ptr< IWorkingMemHandleCreateWorkingMemHandle (NetworkId networkId)
 Create a new unique WorkingMemHandle object. More...
 
TensorInfo GetInputTensorInfo (LayerBindingId layerId) const
 
TensorInfo GetOutputTensorInfo (LayerBindingId layerId) const
 
Status EnqueueWorkload (const InputTensors &inputTensors, const OutputTensors &outputTensors)
 Single thread execution of the loaded network. More...
 
Status Execute (const InputTensors &inputTensors, const OutputTensors &outputTensors, IWorkingMemHandle &workingMemHandle)
 Thread safe execution of the loaded network. More...
 
const std::shared_ptr< IProfiler > & GetProfiler () const
 
void FreeWorkingMemory ()
 
void RegisterDebugCallback (const DebugCallbackFunction &func)
 
void SendNetworkStructure ()
 
bool IsAsyncEnabled ()
 
profiling::ProfilingGuid GetNetworkGuid ()
 

Static Public Member Functions

static std::unique_ptr< LoadedNetworkMakeLoadedNetwork (std::unique_ptr< IOptimizedNetwork > net, std::string &errorMessage, const INetworkProperties &networkProperties, profiling::ProfilingService &profilingService)
 

Detailed Description

Definition at line 35 of file LoadedNetwork.hpp.

Member Typedef Documentation

◆ WorkloadQueue

using WorkloadQueue = std::vector<std::unique_ptr<IWorkload> >

Definition at line 38 of file LoadedNetwork.hpp.

Constructor & Destructor Documentation

◆ ~LoadedNetwork()

~LoadedNetwork ( )
inline

Definition at line 40 of file LoadedNetwork.hpp.

41  {
43  }

Member Function Documentation

◆ CreateWorkingMemHandle()

std::unique_ptr< IWorkingMemHandle > CreateWorkingMemHandle ( NetworkId  networkId)

Create a new unique WorkingMemHandle object.

Create multiple handles if you wish to have overlapped Execution by calling this function from different threads.

Definition at line 1107 of file LoadedNetwork.cpp.

References ITensorHandle::Allocate(), ARMNN_ASSERT, ARMNN_NO_DEPRECATE_WARN_BEGIN, ARMNN_NO_DEPRECATE_WARN_END, armnn::Constant, ITensorHandleFactory::CreateTensorHandle(), Layer::GetBackendId(), TensorHandleFactoryRegistry::GetFactory(), Layer::GetGuid(), Layer::GetInputSlots(), TensorHandleFactoryRegistry::GetMemoryManagers(), Layer::GetNumOutputSlots(), Layer::GetOutputSlots(), Layer::GetType(), armnn::Input, ITensorHandleFactory::LegacyFactoryId, WorkingMemDescriptor::m_Inputs, WorkingMemDescriptor::m_Outputs, ITensorHandle::Manage(), armnn::MemImport, and armnn::Output.

Referenced by RuntimeImpl::CreateWorkingMemHandle().

1108 {
1109  Graph& order = m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph();
1110  std::unordered_map<LayerGuid, std::vector<std::unique_ptr<ITensorHandle> > > tensorHandleMap;
1111  std::vector<WorkingMemDescriptor> workingMemDescriptors;
1112  std::unordered_map<LayerGuid, WorkingMemDescriptor> workingMemDescriptorMap;
1113  TensorHandleFactoryRegistry tensorHandleFactoryRegistry;
1114  WorkloadFactoryMap workloadFactoryMap;
1115 
1116  std::vector<std::shared_ptr<IMemoryManager>> memoryManagers;
1117 
1118  for (auto const& backend : m_Backends)
1119  {
1120  if (backend.second->SupportsTensorAllocatorAPI())
1121  {
1122  backend.second->RegisterTensorHandleFactories(
1123  tensorHandleFactoryRegistry,
1124  static_cast<MemorySourceFlags>(m_NetworkProperties.m_InputSource),
1125  static_cast<MemorySourceFlags>(m_NetworkProperties.m_OutputSource));
1126  memoryManagers.emplace_back(tensorHandleFactoryRegistry.GetMemoryManagers().back());
1127  }
1128  else
1129  {
1130  std::shared_ptr<IMemoryManager> memoryManager = backend.second->CreateMemoryManager();
1131  auto workloadFactory = backend.second->CreateWorkloadFactory(
1132  memoryManager, m_OptimizedNetwork->pOptimizedNetworkImpl->GetModelOptions());
1133 
1134  workloadFactoryMap.emplace(
1135  std::make_pair(backend.first, std::make_pair(std::move(workloadFactory), memoryManager)));
1136  memoryManagers.emplace_back(memoryManager);
1137  }
1138  }
1139 
1140  auto GetTensorHandle = [&](Layer* layer, const OutputSlot& outputSlot, bool isMemoryManaged)
1141  {
1142  ITensorHandleFactory::FactoryId factoryId = outputSlot.GetTensorHandleFactoryId();
1143  const TensorInfo& tensorInfo = outputSlot.GetTensorInfo();
1144 
1145  if (factoryId == ITensorHandleFactory::LegacyFactoryId)
1146  {
1147  BackendId id = layer->GetBackendId();
1149  return workloadFactoryMap.at(id).first->CreateTensorHandle(tensorInfo, isMemoryManaged);
1151  }
1152  else
1153  {
1154  ITensorHandleFactory* handleFactory = tensorHandleFactoryRegistry.GetFactory(factoryId);
1155  ARMNN_ASSERT(handleFactory);
1156  return handleFactory->CreateTensorHandle(tensorInfo, isMemoryManaged);
1157  }
1158  };
1159 
1160  std::unordered_map<const ITensorHandle*, unsigned int> handleReferenceCounts;
1161  for (auto&& layer : order)
1162  {
1163  WorkingMemDescriptor workingMemDescriptor;
1164 
1165  // Constant layers execution and management is handled during loaded network construction
1166  if (layer->GetType() == LayerType::Constant)
1167  {
1168  continue;
1169  }
1170  bool isMemoryManaged = true;
1171  bool isInputLayer = true;
1172  // Look for the layer with 1 OutputSlot which has 1 connection and that connection is an Output Layer
1173  // If Export is enabled disable memory management so we can export, otherwise we do a copy
1174  if ((layer->GetNumOutputSlots() == 1) &&
1175  (layer->GetOutputSlots()[0].GetNumConnections() == 1) &&
1176  (layer->GetOutputSlots()[0].GetConnection(0)->GetOwningLayer().GetType() == LayerType::Output))
1177  {
1178  isMemoryManaged = !m_NetworkProperties.m_ExportEnabled;
1179  }
1180  else if (layer->GetType() == LayerType::Input || layer->GetType() == LayerType::MemImport)
1181  {
1182  // Input layers/workloads will not be executed so the descriptor is not added to workingMemDescriptors
1183  // However we will still need to manage the tensorHandle
1184  isInputLayer = false;
1185  isMemoryManaged = !m_NetworkProperties.m_ExportEnabled;
1186  }
1187 
1188  // Create a tensor handle for each output slot of a layer
1189  // Once we create it, we start managing its lifetime
1190  for (auto& slot : layer->GetOutputSlots())
1191  {
1192  tensorHandleMap[layer->GetGuid()].emplace_back(GetTensorHandle(layer, slot, isMemoryManaged));
1193  ITensorHandle* tensorHandle = tensorHandleMap[layer->GetGuid()].back().get();
1194 
1195  workingMemDescriptor.m_Outputs.push_back(tensorHandle);
1196  tensorHandle->Manage();
1197  unsigned int numConnections = slot.GetNumConnections();
1198  ARMNN_ASSERT(numConnections != 0);
1199 
1200  handleReferenceCounts[tensorHandle] = numConnections;
1201  }
1202  // Loop through the input slots in the same layer and decrement the reference counter associated
1203  // to each tensor handle we encounter.
1204  // Once it reaches zero, the lifetime of the tensor handle has ended, and we mark it's memory as available
1205  // so that the next tensor handle with a non overlapping lifetime can share it's memory.
1206  for (auto& slot : layer->GetInputSlots())
1207  {
1208  ARMNN_ASSERT(slot.GetConnection());
1209  auto outputSlot = slot.GetConnectedOutputSlot();
1210  auto key = outputSlot->GetOwningLayer().GetGuid();
1211 
1212  // Constant layers execution and management is handled during loaded network construction
1213  auto found = m_ConstantTensorHandles.find(key);
1214  if (found != m_ConstantTensorHandles.end())
1215  {
1216  workingMemDescriptor.m_Inputs.push_back(found->second);
1217  continue;
1218  }
1219 
1220  auto search = tensorHandleMap.find(key);
1221  unsigned int index = outputSlot->CalculateIndexOnOwner();
1222  ITensorHandle* inputTensorHandle = search->second[index].get();
1223  workingMemDescriptor.m_Inputs.push_back(inputTensorHandle);
1224  --handleReferenceCounts.at(inputTensorHandle);
1225  if (handleReferenceCounts.at(inputTensorHandle) == 0u)
1226  {
1227  // Stop managing lifetime of tensor handle
1228  inputTensorHandle->Allocate();
1229  handleReferenceCounts.erase(inputTensorHandle);
1230  }
1231  }
1232  workingMemDescriptorMap.insert({layer->GetGuid(), workingMemDescriptor});
1233 
1234  // Input layers/workloads will not be executed, so the descriptor is not added to workingMemDescriptors
1235  // However we will still need to manage the tensorHandle
1236  if (isInputLayer)
1237  {
1238  workingMemDescriptors.push_back(workingMemDescriptor);
1239  }
1240  }
1241 
1242  return std::make_unique<WorkingMemHandle>(networkId,
1243  workingMemDescriptors,
1244  workingMemDescriptorMap,
1245  memoryManagers,
1246  std::move(tensorHandleMap));
1247 }
const MemorySource m_InputSource
Definition: IRuntime.hpp:90
#define ARMNN_NO_DEPRECATE_WARN_BEGIN
Definition: Deprecated.hpp:33
#define ARMNN_NO_DEPRECATE_WARN_END
Definition: Deprecated.hpp:34
const bool m_ExportEnabled
Deprecated and will be removed in future release.
Definition: IRuntime.hpp:82
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
const MemorySource m_OutputSource
Definition: IRuntime.hpp:91
static const FactoryId LegacyFactoryId

◆ EnqueueWorkload()

Status EnqueueWorkload ( const InputTensors inputTensors,
const OutputTensors outputTensors 
)

Single thread execution of the loaded network.

Definition at line 525 of file LoadedNetwork.cpp.

References ARMNN_ASSERT_MSG, ARMNN_LOG, ARMNN_SCOPED_HEAP_PROFILING, ARMNN_SCOPED_PROFILING_EVENT, armnn::CheckFlag(), armnn::Failure, ITensorHandle::GetImportFlags(), Graph::GetInputLayers(), Layer::GetInputSlots(), Graph::GetNumInputs(), Layer::GetNumInputSlots(), Graph::GetNumLayers(), Graph::GetNumOutputs(), Layer::GetNumOutputSlots(), Layer::GetOutputHandler(), Graph::GetOutputLayers(), TimelineUtilityMethods::GetTimelineUtils(), Layer::GetType(), armnn::IgnoreUnused(), ITensorHandle::Import(), armnn::info, armnn::Input, QueueDescriptor::m_Inputs, WorkloadInfo::m_InputTensorInfos, QueueDescriptor::m_Outputs, WorkloadInfo::m_OutputTensorInfos, ITensorHandle::Map(), armnn::Output, armnn::Success, armnn::Undefined, ITensorHandle::Unmap(), and armnn::warning.

Referenced by RuntimeImpl::EnqueueWorkload().

527 {
528  const Graph& graph = m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph();
529 
530  // Walk graph to determine the order of execution.
531  if (graph.GetNumLayers() < 2)
532  {
533  ARMNN_LOG(warning) << "IRuntime::EnqueueWorkload()::Less than two nodes in graph";
534  return Status::Failure;
535  }
536 
537  // Data that must be kept alive for the entire execution of the workload.
538  WorkloadData workloadData(inputTensors, outputTensors);
539 
540  if (graph.GetNumInputs() != inputTensors.size())
541  {
542  throw InvalidArgumentException("Number of inputs provided does not match network.");
543  }
544 
545  // For each input to the network, call EnqueueInput with the data passed by the user.
546  {
548  m_InputQueue.clear();
549  m_InputQueue.reserve(graph.GetNumInputs());
550  for (const BindableLayer* inputLayer : graph.GetInputLayers())
551  {
552  const TensorPin& pin = workloadData.GetInputTensorPin(inputLayer->GetBindingId());
553  EnqueueInput(*inputLayer, pin.GetTensorHandle(), pin.GetTensorInfo());
554  }
555  }
556 
557  // For each output to the network, call EnqueueOutput with the data passed by the user.
558  {
560  m_OutputQueue.clear();
561  m_OutputQueue.reserve(graph.GetNumOutputs());
562  for (const BindableLayer* outputLayer : graph.GetOutputLayers())
563  {
564  const TensorPin& pin = workloadData.GetOutputTensorPin(outputLayer->GetBindingId());
565  EnqueueOutput(*outputLayer, pin.GetTensorHandle(), pin.GetTensorInfo());
566  }
567  }
568 
569  std::unique_ptr<TimelineUtilityMethods> timelineUtils =
570  TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService);
571  ProfilingGuid inferenceGuid = m_ProfilingService.GetNextGuid();
572  if (timelineUtils)
573  {
574  // Add inference timeline trace if profiling is enabled.
575  ProfilingGuid networkGuid = m_OptimizedNetwork->GetGuid();
576  timelineUtils->CreateTypedEntity(inferenceGuid, LabelsAndEventClasses::INFERENCE_GUID);
577  timelineUtils->CreateRelationship(ProfilingRelationshipType::RetentionLink,
578  networkGuid,
579  inferenceGuid,
580  LabelsAndEventClasses::EXECUTION_OF_GUID);
581  timelineUtils->RecordEvent(inferenceGuid, LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS);
582  }
583 
584  bool executionSucceeded = true;
585 
586  {
587  if (m_ProfilingService.IsProfilingEnabled())
588  {
589  m_ProfilingService.IncrementCounterValue(armnn::profiling::INFERENCES_RUN);
590  }
592  ARMNN_SCOPED_HEAP_PROFILING("Executing");
593  executionSucceeded = Execute(timelineUtils, inferenceGuid);
594  }
595 
596  if (timelineUtils)
597  {
598  // Add end of life of the inference timeline if profiling is enabled.
599  timelineUtils->RecordEvent(inferenceGuid, LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
600  timelineUtils->Commit();
601  }
602  return executionSucceeded ? Status::Success : Status::Failure;
603 }
static std::unique_ptr< TimelineUtilityMethods > GetTimelineUtils(ProfilingService &profilingService)
#define ARMNN_LOG(severity)
Definition: Logging.hpp:202
uint32_t IncrementCounterValue(uint16_t counterUid) override
#define ARMNN_SCOPED_PROFILING_EVENT(backendId, name)
Definition: Profiling.hpp:219
Status Execute(const InputTensors &inputTensors, const OutputTensors &outputTensors, IWorkingMemHandle &workingMemHandle)
Thread safe execution of the loaded network.
#define ARMNN_SCOPED_HEAP_PROFILING(TAG)
bool IsProfilingEnabled() const override
static ProfilingDynamicGuid GetNextGuid()

◆ Execute()

Status Execute ( const InputTensors inputTensors,
const OutputTensors outputTensors,
IWorkingMemHandle workingMemHandle 
)

Thread safe execution of the loaded network.

Definition at line 1003 of file LoadedNetwork.cpp.

References WorkingMemHandle::Allocate(), ARMNN_LOG, ARMNN_SCOPED_PROFILING_EVENT, armnn::error, armnn::Failure, Graph::GetInputLayers(), armnn::GetInputTensor(), WorkingMemHandle::GetMutex(), Graph::GetNumInputs(), Graph::GetNumLayers(), Graph::GetOutputLayers(), armnn::GetOutputTensor(), TimelineUtilityMethods::GetTimelineUtils(), WorkingMemHandle::GetWorkingMemDescriptorAt(), WorkingMemHandle::IsAllocated(), armnn::profiling::RetentionLink, armnn::Success, armnn::Undefined, and armnn::warning.

Referenced by RuntimeImpl::Execute(), and LoadedNetwork::FreeWorkingMemory().

1006 {
1007  const Graph& graph = m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph();
1008 
1009  // Walk graph to determine the order of execution.
1010  if (graph.GetNumLayers() < 2)
1011  {
1012  ARMNN_LOG(warning) << "IRuntime::EnqueueWorkload()::Less than two nodes in graph";
1013  return Status::Failure;
1014  }
1015 
1016  if (graph.GetNumInputs() != inputTensors.size())
1017  {
1018  throw InvalidArgumentException("Number of inputs provided does not match network.");
1019  }
1020 
1021  std::unique_ptr<profiling::TimelineUtilityMethods> timelineUtils =
1023  profiling::ProfilingGuid inferenceGuid = m_ProfilingService.GetNextGuid();
1024  if (timelineUtils)
1025  {
1026  // Add inference timeline trace if profiling is enabled.
1027  profiling::ProfilingGuid networkGuid = m_OptimizedNetwork->GetGuid();
1028  timelineUtils->CreateTypedEntity(inferenceGuid, profiling::LabelsAndEventClasses::INFERENCE_GUID);
1029  timelineUtils->CreateRelationship(profiling::ProfilingRelationshipType::RetentionLink,
1030  networkGuid,
1031  inferenceGuid,
1032  profiling::LabelsAndEventClasses::EXECUTION_OF_GUID);
1033  timelineUtils->RecordEvent(inferenceGuid, profiling::LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS);
1034  }
1035 
1036  bool executionSucceeded = true;
1037 
1038  if (timelineUtils)
1039  {
1040  // Add end of life of the inference timeline if profiling is enabled.
1041  timelineUtils->RecordEvent(inferenceGuid, profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
1042  timelineUtils->Commit();
1043  }
1044  WorkingMemHandle& workingMemHandle = dynamic_cast<WorkingMemHandle&>(iWorkingMemHandle);
1045  std::lock_guard<std::mutex> lockGuard(workingMemHandle.GetMutex());
1046 
1047  if (!workingMemHandle.IsAllocated())
1048  {
1049  workingMemHandle.Allocate();
1050  }
1051 
1052  {
1054  for (const BindableLayer* inputLayer : graph.GetInputLayers())
1055  {
1056  EnqueueInput(*inputLayer, GetInputTensor(inputLayer->GetBindingId(), inputTensors), workingMemHandle);
1057  }
1058  }
1059 
1060  auto Fail = [&](const std::exception& error)
1061  {
1062  ARMNN_LOG(error) << "An error occurred attempting to execute a workload: " << error.what();
1063  executionSucceeded = false;
1064  };
1065  profiling::ProfilingDynamicGuid workloadInferenceID(0);
1066 
1067  try
1068  {
1069  for (unsigned int i = 0; i < m_WorkloadQueue.size(); ++i)
1070  {
1071  auto& workload = m_WorkloadQueue[i];
1072  if (timelineUtils)
1073  {
1074  workloadInferenceID = timelineUtils->RecordWorkloadInferenceAndStartOfLifeEvent(workload->GetGuid(),
1075  inferenceGuid);
1076  }
1077  workload->ExecuteAsync(workingMemHandle.GetWorkingMemDescriptorAt(i));
1078 
1079  if (timelineUtils)
1080  {
1081  timelineUtils->RecordEndOfLifeEvent(workloadInferenceID);
1082  }
1083  }
1084  }
1085  catch (const RuntimeException& error)
1086  {
1087  Fail(error);
1088  }
1089  catch (const std::runtime_error& error)
1090  {
1091  Fail(error);
1092  }
1093  // For each output to the network, call EnqueueOutput with the data passed by the user.
1094  {
1096  for (const BindableLayer *outputLayer : graph.GetOutputLayers())
1097  {
1098  EnqueueOutput(*outputLayer, GetOutputTensor(outputLayer->GetBindingId(), outputTensors), workingMemHandle);
1099  }
1100  }
1101 
1102  return executionSucceeded ? Status::Success : Status::Failure;
1103 }
static std::unique_ptr< TimelineUtilityMethods > GetTimelineUtils(ProfilingService &profilingService)
const armnn::Tensor GetOutputTensor(const LayerBindingId layerId, const OutputTensors &outputTensors)
#define ARMNN_LOG(severity)
Definition: Logging.hpp:202
#define ARMNN_SCOPED_PROFILING_EVENT(backendId, name)
Definition: Profiling.hpp:219
static ProfilingDynamicGuid GetNextGuid()
const armnn::ConstTensor GetInputTensor(const LayerBindingId layerId, const InputTensors &inputTensors)

◆ FreeWorkingMemory()

void FreeWorkingMemory ( )

Definition at line 781 of file LoadedNetwork.cpp.

References ARMNN_ASSERT_MSG, ARMNN_LOG, ARMNN_SCOPED_PROFILING_EVENT, armnn::CheckFlag(), armnn::CopyTensorContentsGeneric(), armnn::error, LoadedNetwork::Execute(), Layer::GetGuid(), ITensorHandle::GetImportFlags(), BaseTensor< MemoryType >::GetInfo(), Layer::GetInputSlots(), BaseTensor< MemoryType >::GetMemoryArea(), Layer::GetNumInputSlots(), Layer::GetType(), WorkingMemHandle::GetWorkingMemDescriptor(), ITensorHandle::Import(), armnn::Input, WorkingMemDescriptor::m_Inputs, WorkingMemDescriptor::m_Outputs, ITensorHandle::Map(), armnn::Output, armnn::Undefined, and ITensorHandle::Unmap().

Referenced by RuntimeImpl::CreateWorkingMemHandle(), and RuntimeImpl::EnqueueWorkload().

782 {
783  std::lock_guard<std::mutex> lockGuard(m_WorkingMemMutex);
784  if (!m_IsWorkingMemAllocated)
785  {
786  return;
787  }
788  // Informs the memory managers to release memory in it's respective memory group
789  for (auto&& workloadFactory : m_WorkloadFactories)
790  {
791  IBackendInternal::IMemoryManagerSharedPtr memoryManager = workloadFactory.second.second;
792  if (memoryManager)
793  {
794  memoryManager->Release();
795  }
796  }
797  m_TensorHandleFactoryRegistry.ReleaseMemory();
798  m_IsWorkingMemAllocated = false;
799 }
std::shared_ptr< IMemoryManager > IMemoryManagerSharedPtr
void ReleaseMemory()
Release memory required for inference.

◆ GetInputTensorInfo()

TensorInfo GetInputTensorInfo ( LayerBindingId  layerId) const

Definition at line 376 of file LoadedNetwork.cpp.

References ARMNN_ASSERT_MSG.

Referenced by RuntimeImpl::GetInputTensorInfo().

377 {
378  for (auto&& inputLayer : m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph().GetInputLayers())
379  {
380  ARMNN_ASSERT_MSG(inputLayer->GetNumOutputSlots() == 1, "Input layer should have exactly 1 output slot");
381  if (inputLayer->GetBindingId() == layerId)
382  {
383  return inputLayer->GetOutputSlot(0).GetTensorInfo();
384  }
385  }
386 
387  throw InvalidArgumentException(fmt::format("No input layer is associated with id {}", layerId));
388 }
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15

◆ GetNetworkGuid()

profiling::ProfilingGuid GetNetworkGuid ( )

Definition at line 371 of file LoadedNetwork.cpp.

372 {
373  return m_OptimizedNetwork->GetGuid();
374 }

◆ GetOutputTensorInfo()

TensorInfo GetOutputTensorInfo ( LayerBindingId  layerId) const

Definition at line 390 of file LoadedNetwork.cpp.

References ARMNN_ASSERT_MSG, CHECK_LOCATION, BackendId::Get(), Layer::GetBackendId(), Layer::GetNameStr(), armnn::IgnoreUnused(), armnn::info, and IWorkloadFactory::IsLayerSupported().

Referenced by RuntimeImpl::GetOutputTensorInfo().

391 {
392  for (auto&& outputLayer : m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph().GetOutputLayers())
393  {
394  ARMNN_ASSERT_MSG(outputLayer->GetNumInputSlots() == 1, "Output layer should have exactly 1 input slot");
395  ARMNN_ASSERT_MSG(outputLayer->GetInputSlot(0).GetConnection(), "Input slot on Output layer must be connected");
396  if (outputLayer->GetBindingId() == layerId)
397  {
398  return outputLayer->GetInputSlot(0).GetConnection()->GetTensorInfo();
399  }
400  }
401 
402  throw InvalidArgumentException(fmt::format("No output layer is associated with id {}", layerId));
403 }
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15

◆ GetProfiler()

const std::shared_ptr<IProfiler>& GetProfiler ( ) const
inline

Definition at line 68 of file LoadedNetwork.hpp.

Referenced by RuntimeImpl::CreateWorkingMemHandle(), RuntimeImpl::EnqueueWorkload(), and RuntimeImpl::Execute().

68 { return m_Profiler; }

◆ IsAsyncEnabled()

bool IsAsyncEnabled ( )
inline

Definition at line 76 of file LoadedNetwork.hpp.

Referenced by RuntimeImpl::CreateWorkingMemHandle(), RuntimeImpl::EnqueueWorkload(), and RuntimeImpl::Execute().

77  {
78  return m_NetworkProperties.m_AsyncEnabled;
79  }

◆ MakeLoadedNetwork()

std::unique_ptr< LoadedNetwork > MakeLoadedNetwork ( std::unique_ptr< IOptimizedNetwork net,
std::string &  errorMessage,
const INetworkProperties networkProperties,
profiling::ProfilingService profilingService 
)
static

Definition at line 81 of file LoadedNetwork.cpp.

References ITensorHandle::Allocate(), ARMNN_ASSERT, ARMNN_LOG, armnn::BackendRegistryInstance(), armnn::Constant, IBackendInternal::CreateMemoryManager(), IBackendInternal::CreateWorkloadFactory(), armnn::error, armnnUtils::Processes::GetCurrentId(), BackendRegistry::GetFactory(), ProfilerManager::GetInstance(), TimelineUtilityMethods::GetTimelineUtils(), armnn::Input, ITensorHandleFactory::LegacyFactoryId, INetworkProperties::m_AsyncEnabled, INetworkProperties::m_OutputNetworkDetails, WorkingMemDescriptor::m_Outputs, INetworkProperties::m_ProfilingEnabled, armnn::MemImport, armnn::Output, ProfilerManager::RegisterProfiler(), IBackendInternal::SupportsTensorAllocatorAPI(), and Graph::TopologicalSort().

Referenced by RuntimeImpl::LoadNetwork().

85 {
86  std::unique_ptr<LoadedNetwork> loadedNetwork;
87 
88  auto Fail = [&](const std::exception& error) -> std::unique_ptr<LoadedNetwork>
89  {
90  errorMessage = ToErrorMessage("An error occurred when preparing the network workloads: ", error);
91  ARMNN_LOG(error) << errorMessage;
92 
93  return std::unique_ptr<LoadedNetwork>();
94  };
95 
96  try
97  {
98  loadedNetwork.reset(new LoadedNetwork(std::move(net), networkProperties, profilingService));
99  }
100  catch (const armnn::RuntimeException& error)
101  {
102  return Fail(error);
103  }
104  catch (const armnn::Exception& error)
105  {
106  return Fail(error);
107  }
108  catch (const std::runtime_error& error)
109  {
110  return Fail(error);
111  }
112 
113  return loadedNetwork;
114 }
#define ARMNN_LOG(severity)
Definition: Logging.hpp:202
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46

◆ RegisterDebugCallback()

void RegisterDebugCallback ( const DebugCallbackFunction func)

Definition at line 1249 of file LoadedNetwork.cpp.

Referenced by RuntimeImpl::RegisterDebugCallback().

1250 {
1251  for (auto&& workloadPtr: m_WorkloadQueue)
1252  {
1253  workloadPtr.get()->RegisterDebugCallback(func);
1254  }
1255 }

◆ SendNetworkStructure()

void SendNetworkStructure ( )

Definition at line 334 of file LoadedNetwork.cpp.

References TimelineUtilityMethods::GetTimelineUtils(), armnn::Input, armnn::Output, and Graph::TopologicalSort().

335 {
336  Graph& order = m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph().TopologicalSort();
337  ProfilingGuid networkGuid = m_OptimizedNetwork->GetGuid();
338 
339  std::unique_ptr<TimelineUtilityMethods> timelineUtils =
340  TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService);
341 
342  timelineUtils->CreateTypedEntity(networkGuid, LabelsAndEventClasses::NETWORK_GUID);
343 
344  for (auto&& layer : order)
345  {
346  // Add layer to the post-optimisation network structure
347  AddLayerStructure(timelineUtils, *layer, networkGuid);
348  switch (layer->GetType())
349  {
350  case LayerType::Input:
351  case LayerType::Output:
352  {
353  // Inputs and outputs are treated in a special way - see EnqueueInput() and EnqueueOutput().
354  break;
355  }
356  default:
357  {
358  for (auto& workload : m_WorkloadQueue)
359  {
360  // Add workload to the post-optimisation network structure
361  AddWorkloadStructure(timelineUtils, workload, *layer);
362  }
363  break;
364  }
365  }
366  }
367  // Commit to send the post-optimisation network structure
368  timelineUtils->Commit();
369 }
static std::unique_ptr< TimelineUtilityMethods > GetTimelineUtils(ProfilingService &profilingService)

The documentation for this class was generated from the following files: