ArmNN
 21.11
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
 
std::vector< ImportedInputIdImportInputs (const InputTensors &inputTensors)
 
std::vector< ImportedOutputIdImportOutputs (const OutputTensors &outputTensors)
 
void ClearImportedInputs (const std::vector< ImportedInputId > inputIds)
 
void ClearImportedOutputs (const std::vector< ImportedOutputId > outputIds)
 
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, std::vector< ImportedInputId > preImportedInputs={}, std::vector< ImportedOutputId > preImportedOutputs={})
 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 41 of file LoadedNetwork.hpp.

Member Typedef Documentation

◆ WorkloadQueue

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

Definition at line 44 of file LoadedNetwork.hpp.

Constructor & Destructor Documentation

◆ ~LoadedNetwork()

~LoadedNetwork ( )
inline

Definition at line 46 of file LoadedNetwork.hpp.

47  {
49  }

Member Function Documentation

◆ ClearImportedInputs()

void ClearImportedInputs ( const std::vector< ImportedInputId inputIds)

Definition at line 1241 of file LoadedNetwork.cpp.

Referenced by RuntimeImpl::ClearImportedInputs().

1242 {
1243  for (auto id : inputIds)
1244  {
1245  if (id > m_PreImportedInputHandles.size())
1246  {
1247  throw InvalidArgumentException(fmt::format("ClearImportedInputs::Unknown ImportedInputId: {}", id));
1248  }
1249 
1250  auto& importedTensorHandle = m_PreImportedInputHandles[id].m_TensorHandle;
1251  if (!importedTensorHandle)
1252  {
1253  throw InvalidArgumentException(
1254  fmt::format("ClearImportedInputs::ImportedInput with id: {} has already been deleted", id));
1255  }
1256  // Call Unimport then destroy the tensorHandle
1257  importedTensorHandle->Unimport();
1258  importedTensorHandle = {};
1259  }
1260 }

◆ ClearImportedOutputs()

void ClearImportedOutputs ( const std::vector< ImportedOutputId outputIds)

Definition at line 1262 of file LoadedNetwork.cpp.

Referenced by RuntimeImpl::ClearImportedOutputs().

1263 {
1264  for (auto id : outputIds)
1265  {
1266  if (id > m_PreImportedOutputHandles.size())
1267  {
1268  throw InvalidArgumentException(fmt::format("ClearImportedOutputs::Unknown ImportedOutputId: {}", id));
1269  }
1270 
1271  auto& importedTensorHandle = m_PreImportedOutputHandles[id].m_TensorHandle;
1272  if (!importedTensorHandle)
1273  {
1274  throw InvalidArgumentException(
1275  fmt::format("ClearImportedOutputs::ImportedOutput with id: {} has already been deleted", id));
1276  }
1277  // Call Unimport then destroy the tensorHandle
1278  importedTensorHandle->Unimport();
1279  importedTensorHandle = {};
1280  }
1281 }

◆ 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 1505 of file LoadedNetwork.cpp.

References ARMNN_ASSERT, ARMNN_NO_DEPRECATE_WARN_BEGIN, ARMNN_NO_DEPRECATE_WARN_END, ITensorHandleFactory::CreateTensorHandle(), Layer::GetBackendId(), and ITensorHandleFactory::LegacyFactoryId.

Referenced by RuntimeImpl::CreateWorkingMemHandle().

1506 {
1507  Graph& order = m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph();
1508 
1509  // Tensors that will need to be allocated internally within armnn
1510  std::vector<std::unique_ptr<ITensorHandle>> managedTensorHandles;
1511  // Tensors that will be allocated externally by the user
1512  std::vector<std::unique_ptr<ITensorHandle>> unmanagedTensorHandles;
1513 
1514  std::vector<WorkingMemDescriptor> workingMemDescriptors;
1515  std::unordered_map<LayerGuid, WorkingMemDescriptor> workingMemDescriptorMap;
1516 
1517  auto GetTensorHandle = [&](Layer* layer, const OutputSlot& outputSlot)
1518  {
1519  ITensorHandleFactory::FactoryId factoryId = outputSlot.GetTensorHandleFactoryId();
1520  const TensorInfo& tensorInfo = outputSlot.GetTensorInfo();
1521 
1522  if (factoryId == ITensorHandleFactory::LegacyFactoryId)
1523  {
1524  BackendId id = layer->GetBackendId();
1526  return m_WorkloadFactories.at(id)->CreateTensorHandle(tensorInfo, false);
1528  }
1529  else
1530  {
1531  ITensorHandleFactory* handleFactory = m_TensorHandleFactoryRegistry.GetFactory(factoryId);
1532  ARMNN_ASSERT(handleFactory);
1533  return handleFactory->CreateTensorHandle(tensorInfo, false);
1534  }
1535  };
1536 
1537  struct HandleInfo
1538  {
1539  ITensorHandle* m_TensorHandle;
1540 
1541  bool m_IsInputLayerHandle = false;
1542  bool m_IsOutputLayerHandle = false;
1543 
1544  WorkingMemHandle::InputMemDescriptorCoords m_InputMemDescriptorCoords;
1545  WorkingMemHandle::OutputMemDescriptorCoords m_OutputMemDescriptorCoords;
1546  };
1547 
1548  std::unordered_map<const OutputSlot*, HandleInfo> outputToHandleInfoMap;
1549 
1550  unsigned int layerIndex = 0;
1551  for (auto&& layer : order)
1552  {
1553  // Constant layers execution and management is handled during loaded network construction
1554  if (layer->GetType() == LayerType::Constant)
1555  {
1556  continue;
1557  }
1558 
1559  WorkingMemDescriptor workingMemDescriptor;
1560 
1561  bool isMemoryManaged = true;
1562  bool isInputLayer = false;
1563  bool isOutputLayer = false;
1564  bool isConnectedToOutputLayer = false;
1565 
1566  if (layer->GetType() == LayerType::Input || layer->GetType() == LayerType::MemImport)
1567  {
1568  // Input layers/workloads will not be executed so the descriptor is not added to workingMemDescriptors
1569  // However we will still need to manage the tensorHandle
1570  isInputLayer = true;
1571  isMemoryManaged = !m_NetworkProperties.m_ImportEnabled;
1572  }
1573  else if (layer->GetType() == LayerType::Output)
1574  {
1575  isOutputLayer = true;
1576  }
1577 
1578  unsigned int slotIndex = 0;
1579  // Create a tensor handle for each output slot of a layer
1580  // Once we create it, we start managing its lifetime
1581  for (auto& slot : layer->GetOutputSlots())
1582  {
1583  for (unsigned int i = 0; i < slot.GetNumConnections(); ++i)
1584  {
1585  if ((slot.GetConnection(i)->GetOwningLayer().GetType() == LayerType::Output))
1586  {
1587  if (!isConnectedToOutputLayer)
1588  {
1589  isConnectedToOutputLayer = true;
1590  // If Export is enabled disable memory management, so we can export, otherwise we do a copy
1591  isMemoryManaged = !m_NetworkProperties.m_ExportEnabled;
1592  }
1593  else
1594  {
1595  // Importing in this case would likely cause unexpected behaviour, so we disallow it.
1596  ARMNN_LOG(warning) <<
1597  fmt::format("Layer name: '{0}' guid: '{1}' has two or more OutputLayers connected to it. "
1598  "This will prevent importing on the connected OutputLayers.",
1599  layer->GetName(), layer->GetGuid());
1600  isMemoryManaged = true;
1601  }
1602  }
1603  }
1604 
1605  ITensorHandle* tensorHandle;
1606  if (isMemoryManaged)
1607  {
1608  managedTensorHandles.emplace_back(GetTensorHandle(layer, slot));
1609  tensorHandle = managedTensorHandles.back().get();
1610  }
1611  else
1612  {
1613  unmanagedTensorHandles.emplace_back(GetTensorHandle(layer, slot));
1614  tensorHandle = unmanagedTensorHandles.back().get();
1615  }
1616 
1617  workingMemDescriptor.m_Outputs.push_back(tensorHandle);
1618 
1619  HandleInfo& handleInfo = outputToHandleInfoMap[&slot];
1620  handleInfo.m_TensorHandle = tensorHandle;
1621 
1622  // Store the coordinates of the current layer's OutputSlot that is connected to the OutputLayer
1623  if (isConnectedToOutputLayer)
1624  {
1625  handleInfo.m_IsOutputLayerHandle = true;
1626  handleInfo.m_OutputMemDescriptorCoords.m_OutputSlotCoords = {layerIndex, slotIndex};
1627  }
1628  // Store the LayerBindingId of the InputLayer
1629  if (isInputLayer)
1630  {
1631  handleInfo.m_IsInputLayerHandle = true;
1632  LayerBindingId bindingId = static_cast<BindableLayer*>(layer)->GetBindingId();
1633  handleInfo.m_InputMemDescriptorCoords.m_LayerBindingId = bindingId;
1634  }
1635  slotIndex++;
1636  }
1637  // Loop through the input slots in the same layer and decrement the reference counter associated
1638  // to each tensor handle we encounter.
1639  // Once it reaches zero, the lifetime of the tensor handle has ended, and we mark its memory as available
1640  // so that the next tensor handle with a non overlapping lifetime can share its memory.
1641  for (auto& slot : layer->GetInputSlots())
1642  {
1643  ARMNN_ASSERT(slot.GetConnection());
1644  auto outputSlot = slot.GetConnectedOutputSlot();
1645  auto key = outputSlot->GetOwningLayer().GetGuid();
1646 
1647  // Constant layers execution and management is handled during loaded network construction
1648  auto found = m_ConstantTensorHandles.find(key);
1649  if (found != m_ConstantTensorHandles.end())
1650  {
1651  ITensorHandle* tensorHandle = found->second;
1652  workingMemDescriptor.m_Inputs.push_back(tensorHandle);
1653 
1654  // Odd case where a constant layer is connected to an output layer
1655  // We will need to create a HandleInfo to track it
1656  if (isOutputLayer)
1657  {
1658  LayerBindingId bindingId = static_cast<BindableLayer*>(layer)->GetBindingId();
1659 
1660  HandleInfo& handleInfo = outputToHandleInfoMap[outputSlot];
1661  handleInfo.m_TensorHandle = tensorHandle;
1662  handleInfo.m_IsOutputLayerHandle = true;
1663  handleInfo.m_OutputMemDescriptorCoords.m_LayerBindingIds.push_back(bindingId);
1664  handleInfo.m_OutputMemDescriptorCoords.m_InputSlotCoords.push_back({layerIndex, 0});
1665  }
1666  continue;
1667  }
1668 
1669  HandleInfo& handleInfo = outputToHandleInfoMap.at(outputSlot);
1670 
1671  ITensorHandle* inputTensorHandle = handleInfo.m_TensorHandle;
1672  workingMemDescriptor.m_Inputs.push_back(inputTensorHandle);
1673 
1674  // Store the LayerBindingId of the OutputLayer
1675  if (isOutputLayer)
1676  {
1677  LayerBindingId bindingId = static_cast<BindableLayer*>(layer)->GetBindingId();
1678  handleInfo.m_OutputMemDescriptorCoords.m_LayerBindingIds.push_back(bindingId);
1679  handleInfo.m_OutputMemDescriptorCoords.m_InputSlotCoords.push_back({layerIndex, 0});
1680  }
1681  // In this case the layer is not an Output Layer but shares its input tensorhandle with an OutputLayer
1682  // It will need to be updated as well, if we swap out the tensorhandle
1683  else if (handleInfo.m_IsOutputLayerHandle)
1684  {
1685  handleInfo.m_OutputMemDescriptorCoords.m_InputSlotCoords.push_back({layerIndex, slot.GetSlotIndex()});
1686  }
1687 
1688  // Store the coordinates of the InputSlots connected to the InputLayer
1689  // There can be more than one InputSlot connected to an InputLayer, so we use a vector
1690  if (handleInfo.m_IsInputLayerHandle)
1691  {
1692  std::pair<LayerGuid, unsigned int> connectionLocation{layerIndex, slot.GetSlotIndex()};
1693  handleInfo.m_InputMemDescriptorCoords.m_InputSlotCoords.emplace_back(connectionLocation);
1694  }
1695  }
1696  workingMemDescriptorMap.insert({layer->GetGuid(), workingMemDescriptor});
1697 
1698  // Input/Output layers/workloads will not be executed, so the descriptor is not added to workingMemDescriptors
1699  // However we will still need to manage the tensorHandle
1700  if (!isInputLayer)
1701  {
1702  workingMemDescriptors.push_back(workingMemDescriptor);
1703  layerIndex++;
1704  }
1705  }
1706 
1707  std::vector<std::pair<std::shared_ptr<TensorMemory>, MemorySource>> tensorMemory;
1708 
1709  auto externalMemoryManager = CreateExternalMemoryManger(tensorMemory);
1710 
1711  // Sort m_TensorMemory, so it's order matches the outputSlot order
1712  std::sort(tensorMemory.begin(), tensorMemory.end(),
1713  [](const std::pair<std::shared_ptr<TensorMemory>, MemorySource>& lhs,
1714  const std::pair<std::shared_ptr<TensorMemory>, MemorySource>& rhs)
1715  {
1716  return lhs.first->m_OutputSlotId < rhs.first->m_OutputSlotId;
1717  });
1718 
1719  std::vector<WorkingMemHandle::InputMemDescriptorCoords> inputConnectionsInfo;
1720  std::vector<WorkingMemHandle::OutputMemDescriptorCoords> outputConnectionsInfo;
1721 
1722  for (const auto& handleInfo: outputToHandleInfoMap)
1723  {
1724  if (handleInfo.second.m_IsOutputLayerHandle)
1725  {
1726  outputConnectionsInfo.emplace_back(handleInfo.second.m_OutputMemDescriptorCoords);
1727  }
1728 
1729  if (handleInfo.second.m_IsInputLayerHandle)
1730  {
1731  inputConnectionsInfo.emplace_back(handleInfo.second.m_InputMemDescriptorCoords);
1732  }
1733  }
1734 
1735  return std::make_unique<WorkingMemHandle>(networkId,
1736  inputConnectionsInfo,
1737  outputConnectionsInfo,
1738  workingMemDescriptors,
1739  workingMemDescriptorMap,
1740  std::move(externalMemoryManager),
1741  std::move(tensorMemory),
1742  std::move(managedTensorHandles),
1743  std::move(unmanagedTensorHandles));
1744 }
#define ARMNN_NO_DEPRECATE_WARN_BEGIN
Definition: Deprecated.hpp:33
#define ARMNN_LOG(severity)
Definition: Logging.hpp:202
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
Definition: Types.hpp:277
#define ARMNN_NO_DEPRECATE_WARN_END
Definition: Deprecated.hpp:34
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
MemorySource
Define the Memory Source to reduce copies.
Definition: Types.hpp:217
ITensorHandleFactory * GetFactory(ITensorHandleFactory::FactoryId id) const
Find a TensorHandleFactory by Id Returns nullptr if not found.
static const FactoryId LegacyFactoryId

◆ EnqueueWorkload()

Status EnqueueWorkload ( const InputTensors inputTensors,
const OutputTensors outputTensors 
)

Single thread execution of the loaded network.

Definition at line 636 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().

638 {
639  const Graph& graph = m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph();
640 
641  // Walk graph to determine the order of execution.
642  if (graph.GetNumLayers() < 2)
643  {
644  ARMNN_LOG(warning) << "IRuntime::EnqueueWorkload()::Less than two nodes in graph";
645  return Status::Failure;
646  }
647 
648  // Data that must be kept alive for the entire execution of the workload.
649  WorkloadData workloadData(inputTensors, outputTensors);
650 
651  if (graph.GetNumInputs() != inputTensors.size())
652  {
653  throw InvalidArgumentException("Number of inputs provided does not match network.");
654  }
655 
656  // For each input to the network, call EnqueueInput with the data passed by the user.
657  {
659  m_InputQueue.clear();
660  m_InputQueue.reserve(graph.GetNumInputs());
661  for (const BindableLayer* inputLayer : graph.GetInputLayers())
662  {
663  const TensorPin& pin = workloadData.GetInputTensorPin(inputLayer->GetBindingId());
664  EnqueueInput(*inputLayer, pin.GetTensorHandle(), pin.GetTensorInfo());
665  }
666  }
667 
668  // For each output to the network, call EnqueueOutput with the data passed by the user.
669  {
671  m_OutputQueue.clear();
672  m_OutputQueue.reserve(graph.GetNumOutputs());
673  for (const BindableLayer* outputLayer : graph.GetOutputLayers())
674  {
675  const TensorPin& pin = workloadData.GetOutputTensorPin(outputLayer->GetBindingId());
676  EnqueueOutput(*outputLayer, pin.GetTensorHandle(), pin.GetTensorInfo());
677  }
678  }
679 
680  std::unique_ptr<TimelineUtilityMethods> timelineUtils =
681  TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService);
682  ProfilingGuid inferenceGuid = m_ProfilingService.GetNextGuid();
683  if (timelineUtils)
684  {
685  // Add inference timeline trace if profiling is enabled.
686  ProfilingGuid networkGuid = m_OptimizedNetwork->GetGuid();
687  timelineUtils->CreateTypedEntity(inferenceGuid, LabelsAndEventClasses::INFERENCE_GUID);
688  timelineUtils->CreateRelationship(ProfilingRelationshipType::RetentionLink,
689  networkGuid,
690  inferenceGuid,
691  LabelsAndEventClasses::EXECUTION_OF_GUID);
692  timelineUtils->RecordEvent(inferenceGuid, LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS);
693  }
694 
695  bool executionSucceeded = true;
696 
697  {
698  if (m_ProfilingService.IsProfilingEnabled())
699  {
700  m_ProfilingService.IncrementCounterValue(armnn::profiling::INFERENCES_RUN);
701  }
703  ARMNN_SCOPED_HEAP_PROFILING("Executing");
704  executionSucceeded = Execute(timelineUtils, inferenceGuid);
705  }
706 
707  if (timelineUtils)
708  {
709  // Add end of life of the inference timeline if profiling is enabled.
710  timelineUtils->RecordEvent(inferenceGuid, LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
711  timelineUtils->Commit();
712  }
713  return executionSucceeded ? Status::Success : Status::Failure;
714 }
Status Execute(const InputTensors &inputTensors, const OutputTensors &outputTensors, IWorkingMemHandle &workingMemHandle, std::vector< ImportedInputId > preImportedInputs={}, std::vector< ImportedOutputId > preImportedOutputs={})
Thread safe execution of the loaded network.
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:220
#define ARMNN_SCOPED_HEAP_PROFILING(TAG)
bool IsProfilingEnabled() const override
static ProfilingDynamicGuid GetNextGuid()

◆ Execute()

Status Execute ( const InputTensors inputTensors,
const OutputTensors outputTensors,
IWorkingMemHandle workingMemHandle,
std::vector< ImportedInputId preImportedInputs = {},
std::vector< ImportedOutputId preImportedOutputs = {} 
)

Thread safe execution of the loaded network.

Definition at line 1283 of file LoadedNetwork.cpp.

References WorkingMemHandle::Allocate(), ARMNN_LOG, ARMNN_SCOPED_PROFILING_EVENT, armnn::CopyToOutputTensor(), armnn::error, armnn::Failure, WorkingMemHandle::GetBindingIdVector(), WorkingMemHandle::GetInputConnections(), WorkingMemHandle::GetInputHandle(), Graph::GetNumInputs(), Graph::GetNumOutputs(), WorkingMemHandle::GetOutputConnection(), WorkingMemHandle::GetOutputHandle(), TimelineUtilityMethods::GetTimelineUtils(), WorkingMemHandle::GetWorkingMemDescriptorAt(), WorkingMemHandle::IsAllocated(), WorkingMemHandle::MemSyncOutputs(), armnn::profiling::RetentionLink, armnn::Success, armnn::Undefined, and WorkingMemHandle::ValidateBindingIds().

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

1288 {
1289  const Graph& graph = m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph();
1290 
1291  if (inputTensors.size() + preImportedInputs.size() != graph.GetNumInputs())
1292  {
1293  if (preImportedInputs.empty())
1294  {
1295  throw InvalidArgumentException("LoadedNetwork::Execute: Number of inputs provided does not match network.");
1296  }
1297  else
1298  {
1299  throw InvalidArgumentException("LoadedNetwork::Execute: "
1300  "Number of inputs + preImportedInputs provided does not match network.");
1301  }
1302  }
1303 
1304  if (outputTensors.size() + preImportedOutputs.size() != graph.GetNumOutputs())
1305  {
1306  if (preImportedOutputs.empty())
1307  {
1308  throw InvalidArgumentException("LoadedNetwork::Execute: "
1309  "Number of outputs provided does not match network.");
1310  }
1311  else
1312  {
1313  throw InvalidArgumentException("LoadedNetwork::Execute: "
1314  "Number of outputs + preImportedOutputs provided does not match network.");
1315  }
1316  }
1317 
1318  WorkingMemHandle& workingMemHandle = dynamic_cast<WorkingMemHandle&>(iWorkingMemHandle);
1319  // Collect all the given LayerBindingIds and check them for duplicates and unknowns.
1320  std::vector<LayerBindingId>& bindingIds = workingMemHandle.GetBindingIdVector();
1321  unsigned int index = 0;
1322  for (auto pair : inputTensors)
1323  {
1324  bindingIds[index++] = pair.first;
1325  }
1326  for (ImportedInputId id : preImportedInputs)
1327  {
1328  bindingIds[index++] = ValidateImportedInputID(id);
1329  }
1330  for (auto pair : outputTensors)
1331  {
1332  bindingIds[index++] = pair.first;
1333  }
1334  for (ImportedOutputId id : preImportedOutputs)
1335  {
1336  bindingIds[index++] = ValidateImportedOutputID(id);
1337  }
1338 
1339  workingMemHandle.ValidateBindingIds();
1340 
1341  auto resetMemHandle = [&]()
1342  {
1343  for (ImportedInputId id: preImportedInputs)
1344  {
1345  const LayerBindingId layerBindingId = m_PreImportedInputHandles[id].m_LayerBindingId;
1346 
1347  auto inputHandle = workingMemHandle.GetInputHandle(layerBindingId);
1348  auto inputConnections = workingMemHandle.GetInputConnections(layerBindingId);
1349  for (auto it : inputConnections)
1350  {
1351  *it = inputHandle;
1352  }
1353  }
1354 
1355  for (ImportedOutputId id: preImportedOutputs)
1356  {
1357  const LayerBindingId layerBindingId = m_PreImportedOutputHandles[id].m_LayerBindingId;
1358 
1359  auto outputHandle = workingMemHandle.GetOutputHandle(layerBindingId);
1360  auto outputConnections = workingMemHandle.GetOutputConnection(layerBindingId);
1361 
1362  for (auto it : outputConnections)
1363  {
1364  *it = outputHandle;
1365  }
1366  }
1367  };
1368 
1369  std::unique_ptr<profiling::TimelineUtilityMethods> timelineUtils =
1371  profiling::ProfilingGuid inferenceGuid = m_ProfilingService.GetNextGuid();
1372  if (timelineUtils)
1373  {
1374  // Add inference timeline trace if profiling is enabled.
1375  profiling::ProfilingGuid networkGuid = m_OptimizedNetwork->GetGuid();
1376  timelineUtils->CreateTypedEntity(inferenceGuid, profiling::LabelsAndEventClasses::INFERENCE_GUID);
1377  timelineUtils->CreateRelationship(profiling::ProfilingRelationshipType::RetentionLink,
1378  networkGuid,
1379  inferenceGuid,
1380  profiling::LabelsAndEventClasses::EXECUTION_OF_GUID);
1381  timelineUtils->RecordEvent(inferenceGuid, profiling::LabelsAndEventClasses::ARMNN_PROFILING_SOL_EVENT_CLASS);
1382  }
1383 
1384  bool executionSucceeded = true;
1385 
1386  if (timelineUtils)
1387  {
1388  // Add end of life of the inference timeline if profiling is enabled.
1389  timelineUtils->RecordEvent(inferenceGuid, profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
1390  timelineUtils->Commit();
1391  }
1392 
1393  if (!workingMemHandle.IsAllocated())
1394  {
1395  workingMemHandle.Allocate();
1396  }
1397 
1398  {
1400  for (auto pair : inputTensors)
1401  {
1402  EnqueueInput(pair.second, workingMemHandle.GetInputHandle(pair.first));
1403  }
1404 
1405  // Swap in the pre-imported inputs if any
1406  for (ImportedInputId id : preImportedInputs)
1407  {
1408  const ImportedTensorHandlePin& importedInputPin = m_PreImportedInputHandles[id];
1409  const LayerBindingId layerBindingId = m_PreImportedInputHandles[id].m_LayerBindingId;
1410  const auto& preimportedHandle = importedInputPin.m_TensorHandle;
1411 
1412  auto inputConnections = workingMemHandle.GetInputConnections(layerBindingId);
1413  for (auto it : inputConnections)
1414  {
1415  *it = preimportedHandle.get();
1416  }
1417  }
1418  }
1419  {
1421  if (m_NetworkProperties.m_ExportEnabled)
1422  {
1423  for (auto pair: outputTensors)
1424  {
1425  ImportOutputTensor(pair.second, workingMemHandle.GetOutputHandle(pair.first));
1426  }
1427  }
1428 
1429  for (ImportedOutputId id : preImportedOutputs)
1430  {
1431  const ImportedTensorHandlePin& importedOutputPin = m_PreImportedOutputHandles[id];
1432  const LayerBindingId layerBindingId = m_PreImportedOutputHandles[id].m_LayerBindingId;
1433  const auto& preimportedHandle = importedOutputPin.m_TensorHandle;
1434 
1435  auto outputConnections = workingMemHandle.GetOutputConnection(layerBindingId);
1436 
1437  for (auto it : outputConnections)
1438  {
1439  *it = preimportedHandle.get();
1440  }
1441  }
1442  }
1443 
1444  auto Fail = [&](const std::exception& error)
1445  {
1446  ARMNN_LOG(error) << "An error occurred attempting to execute a workload: " << error.what();
1447  executionSucceeded = false;
1448  };
1449  profiling::ProfilingDynamicGuid workloadInferenceID(0);
1450 
1451  try
1452  {
1453  for (unsigned int i = 0; i < m_WorkloadQueue.size(); ++i)
1454  {
1455  auto& workload = m_WorkloadQueue[i];
1456  if (timelineUtils)
1457  {
1458  workloadInferenceID = timelineUtils->RecordWorkloadInferenceAndStartOfLifeEvent(workload->GetGuid(),
1459  inferenceGuid);
1460  }
1461  workload->ExecuteAsync(workingMemHandle.GetWorkingMemDescriptorAt(i));
1462 
1463  if (timelineUtils)
1464  {
1465  timelineUtils->RecordEndOfLifeEvent(workloadInferenceID);
1466  }
1467  }
1468  }
1469  catch (const RuntimeException& error)
1470  {
1471  resetMemHandle();
1472  Fail(error);
1473  }
1474  catch (const std::runtime_error& error)
1475  {
1476  resetMemHandle();
1477  Fail(error);
1478  }
1479  catch (...)
1480  {
1481  resetMemHandle();
1482  throw;
1483  }
1484 
1485  if (!m_NetworkProperties.m_ExportEnabled)
1486  {
1487  for (auto pair: outputTensors)
1488  {
1489  CopyToOutputTensor(pair.second, workingMemHandle.GetOutputHandle(pair.first));
1490  }
1491  }
1492  else
1493  {
1494  ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "SyncMemGeneric_Execute");
1495  workingMemHandle.MemSyncOutputs();
1496  }
1497 
1498  resetMemHandle();
1499 
1500  return executionSucceeded ? Status::Success : Status::Failure;
1501 }
static std::unique_ptr< TimelineUtilityMethods > GetTimelineUtils(ProfilingService &profilingService)
unsigned int ImportedOutputId
Definition: Types.hpp:279
#define ARMNN_LOG(severity)
Definition: Logging.hpp:202
void CopyToOutputTensor(const Tensor &outputTensor, ITensorHandle *outputTensorHandle)
#define ARMNN_SCOPED_PROFILING_EVENT(backendId, name)
Definition: Profiling.hpp:220
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
Definition: Types.hpp:277
const bool m_ExportEnabled
Deprecated and will be removed in future release.
Definition: IRuntime.hpp:87
unsigned int ImportedInputId
Definition: Types.hpp:278
static ProfilingDynamicGuid GetNextGuid()

◆ FreeWorkingMemory()

void FreeWorkingMemory ( )

Definition at line 902 of file LoadedNetwork.cpp.

References ARMNN_ASSERT_MSG, ARMNN_LOG, armnn::CheckFlag(), armnn::CopyTensorContentsGeneric(), armnn::error, LoadedNetwork::Execute(), ITensorHandle::GetImportFlags(), BaseTensor< MemoryType >::GetInfo(), BaseTensor< MemoryType >::GetMemoryArea(), ITensorHandle::Import(), and ITensorHandle::Map().

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

903 {
904  std::lock_guard<std::mutex> lockGuard(m_WorkingMemMutex);
905 
906  if (!m_IsWorkingMemAllocated)
907  {
908  return;
909  }
910 
911  if (m_ExternalMemoryManager)
912  {
913  m_ExternalMemoryManager->Deallocate();
914  }
915 
916  // Informs the memory managers to release memory in its respective memory group
917  for (auto&& memoryManager : m_BackendMemoryMangers)
918  {
919  if (memoryManager)
920  {
921  memoryManager->Release();
922  }
923  }
924  m_TensorHandleFactoryRegistry.ReleaseMemory();
925  m_IsWorkingMemAllocated = false;
926 }
void ReleaseMemory()
Release memory required for inference.

◆ GetInputTensorInfo()

TensorInfo GetInputTensorInfo ( LayerBindingId  layerId) const

Definition at line 487 of file LoadedNetwork.cpp.

References ARMNN_ASSERT_MSG.

Referenced by RuntimeImpl::GetInputTensorInfo().

488 {
489  for (auto&& inputLayer : m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph().GetInputLayers())
490  {
491  ARMNN_ASSERT_MSG(inputLayer->GetNumOutputSlots() == 1, "Input layer should have exactly 1 output slot");
492  if (inputLayer->GetBindingId() == layerId)
493  {
494  return inputLayer->GetOutputSlot(0).GetTensorInfo();
495  }
496  }
497 
498  throw InvalidArgumentException(fmt::format("No input layer is associated with id {}", layerId));
499 }
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15

◆ GetNetworkGuid()

profiling::ProfilingGuid GetNetworkGuid ( )

Definition at line 482 of file LoadedNetwork.cpp.

483 {
484  return m_OptimizedNetwork->GetGuid();
485 }

◆ GetOutputTensorInfo()

TensorInfo GetOutputTensorInfo ( LayerBindingId  layerId) const

Definition at line 501 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().

502 {
503  for (auto&& outputLayer : m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph().GetOutputLayers())
504  {
505  ARMNN_ASSERT_MSG(outputLayer->GetNumInputSlots() == 1, "Output layer should have exactly 1 input slot");
506  ARMNN_ASSERT_MSG(outputLayer->GetInputSlot(0).GetConnection(), "Input slot on Output layer must be connected");
507  if (outputLayer->GetBindingId() == layerId)
508  {
509  return outputLayer->GetInputSlot(0).GetConnection()->GetTensorInfo();
510  }
511  }
512 
513  throw InvalidArgumentException(fmt::format("No output layer is associated with id {}", layerId));
514 }
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15

◆ GetProfiler()

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

Definition at line 82 of file LoadedNetwork.hpp.

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

82 { return m_OptimizedNetwork->GetProfiler(); }

◆ ImportInputs()

std::vector< ImportedInputId > ImportInputs ( const InputTensors inputTensors)

Definition at line 1090 of file LoadedNetwork.cpp.

References ARMNN_ASSERT, Graph::InputLayersAccessor::begin(), armnn::CheckFlag(), ITensorHandleFactory::CreateTensorHandle(), Graph::InputLayersAccessor::end(), Layer::GetBackendId(), BindableLayer::GetBindingId(), ITensorHandle::GetImportFlags(), BaseTensor< MemoryType >::GetInfo(), Graph::GetInputLayers(), BaseTensor< MemoryType >::GetMemoryArea(), Layer::GetOutputSlots(), OutputSlot::GetTensorHandleFactoryId(), OutputSlot::GetTensorInfo(), Layer::GetType(), armnn::HasCapability(), ITensorHandle::Import(), armnn::Input, and Graph::TopologicalSort().

Referenced by RuntimeImpl::ImportInputs().

1091 {
1092  if (!m_NetworkProperties.m_ImportEnabled) // Try import the input tensor
1093  {
1094  throw MemoryImportException("ImportInputs: Memory Import failed, NetworkProperties.m_ImportEnabled");
1095  }
1096 
1097  std::vector<ImportedInputId> importedInputs;
1098  Graph& graph = m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph().TopologicalSort();
1099 
1100  for (auto inputTensor : inputTensors)
1101  {
1102  auto layerBindingId = inputTensor.first;
1103  auto it = std::find_if(graph.GetInputLayers().begin(), graph.GetInputLayers().end(), [=](auto* layer)
1104  {
1105  return layer->GetBindingId() == layerBindingId;
1106  });
1107 
1108  if (it == graph.GetInputLayers().end())
1109  {
1110  throw MemoryImportException(fmt::format("ImportInputs: Memory Import failed, unknown LayerBindingId: {}",
1111  layerBindingId));
1112  }
1113 
1114  const Layer* layer = *it;
1115  if (layer->GetType() != LayerType::Input)
1116  {
1117  throw InvalidArgumentException("ImportInputs: given layer not an InputLayer");
1118  }
1119 
1120  auto& backend = m_Backends.at(layer->GetBackendId());
1121  if (!HasCapability(BackendOptions::BackendOption{"PreImportIOTensors", true}, backend->GetCapabilities()))
1122  {
1123  std::string er = backend->GetId();
1124  er += " does not have PreImportIOTensors capability";
1125  throw BackendCapabilityException(er);
1126  }
1127 
1128  const OutputSlot& outputSlot = layer->GetOutputSlots()[0];
1129 
1130  ITensorHandleFactory::FactoryId factoryId = outputSlot.GetTensorHandleFactoryId();
1131  const TensorInfo& tensorInfo = outputSlot.GetTensorInfo();
1132 
1133  ITensorHandleFactory* handleFactory = m_TensorHandleFactoryRegistry.GetFactory(factoryId);
1134  ARMNN_ASSERT(handleFactory);
1135 
1136  ImportedTensorHandlePin importedTensorHandlePin{layerBindingId,
1137  handleFactory->CreateTensorHandle(tensorInfo, false)};
1138 
1139  ITensorHandle* tensorHandle = importedTensorHandlePin.m_TensorHandle.get();
1140 
1141  if (!CheckFlag(tensorHandle->GetImportFlags(), m_NetworkProperties.m_InputSource))
1142  {
1143  throw MemoryImportException(
1144  fmt::format("ImportInputs: Memory Import failed, backend: {} does not support importing from source {}"
1145  , factoryId, m_NetworkProperties.m_InputSource));
1146  }
1147 
1148  std::unique_ptr<ITensorHandle> passThroughTensorHandle =
1149  std::make_unique<ConstPassthroughTensorHandle>(inputTensor.second.GetInfo(),
1150  inputTensor.second.GetMemoryArea());
1151 
1152  if (tensorHandle->Import(passThroughTensorHandle->Map(), m_NetworkProperties.m_InputSource))
1153  {
1154  importedInputs.push_back(m_CurImportedInputId++);
1155  passThroughTensorHandle->Unmap();
1156  }
1157  else
1158  {
1159  passThroughTensorHandle->Unmap();
1160  throw MemoryImportException("ImportInputs: Memory Import failed");
1161  }
1162 
1163  m_PreImportedInputHandles.push_back(std::move(importedTensorHandlePin));
1164  }
1165 
1166  return importedInputs;
1167 }
bool HasCapability(const std::string &name, const BackendCapabilities &capabilities)
Convenience function to check if a capability exists in a BackendCapabilites struct.
const MemorySource m_InputSource
Definition: IRuntime.hpp:95
const bool m_ImportEnabled
Deprecated and will be removed in future release.
Definition: IRuntime.hpp:85
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
ITensorHandleFactory * GetFactory(ITensorHandleFactory::FactoryId id) const
Find a TensorHandleFactory by Id Returns nullptr if not found.
bool CheckFlag(MemorySourceFlags flags, MemorySource source)

◆ ImportOutputs()

std::vector< ImportedOutputId > ImportOutputs ( const OutputTensors outputTensors)

Definition at line 1169 of file LoadedNetwork.cpp.

References ARMNN_ASSERT, Graph::OutputLayersAccessor::begin(), armnn::CheckFlag(), ITensorHandleFactory::CreateTensorHandle(), Graph::OutputLayersAccessor::end(), Layer::GetBackendId(), BindableLayer::GetBindingId(), InputSlot::GetConnectedOutputSlot(), ITensorHandle::GetImportFlags(), Layer::GetInputSlots(), BaseTensor< MemoryType >::GetMemoryArea(), Graph::GetOutputLayers(), OutputSlot::GetTensorHandleFactoryId(), OutputSlot::GetTensorInfo(), Layer::GetType(), armnn::HasCapability(), ITensorHandle::Import(), armnn::Output, and Graph::TopologicalSort().

Referenced by RuntimeImpl::ImportOutputs().

1170 {
1171  if (!m_NetworkProperties.m_ExportEnabled) // Try import the output tensor
1172  {
1173  throw MemoryImportException("ImportOutputs: Memory Import failed, NetworkProperties.m_ImportEnabled");
1174  }
1175 
1176  std::vector<ImportedOutputId> importedOutputs;
1177  Graph& graph = m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph().TopologicalSort();
1178 
1179  for (const auto& outputTensor : outputTensors)
1180  {
1181  auto layerBindingId = outputTensor.first;
1182  auto it = std::find_if(graph.GetOutputLayers().begin(), graph.GetOutputLayers().end(), [=](auto* layer)
1183  {
1184  return layer->GetBindingId() == layerBindingId;
1185  });
1186 
1187  if (it == graph.GetOutputLayers().end())
1188  {
1189  throw MemoryImportException(fmt::format("ImportOutputs: Memory Import failed, unknown LayerBindingId: {}",
1190  layerBindingId));
1191  }
1192 
1193  const Layer* layer = *it;
1194  if (layer->GetType() != LayerType::Output)
1195  {
1196  throw InvalidArgumentException("ImportOutputs: given layer not an OutputLayer");
1197  }
1198 
1199  auto& backend = m_Backends.at(layer->GetBackendId());
1200  if (!HasCapability(BackendOptions::BackendOption{"PreImportIOTensors", true}, backend->GetCapabilities()))
1201  {
1202  std::string er = backend->GetId();
1203  er += " does not have PreImportIOTensors capability";
1204  throw BackendCapabilityException(er);
1205  }
1206 
1207  const InputSlot& inputSlot = layer->GetInputSlots()[0];
1208  ITensorHandleFactory::FactoryId factoryId = inputSlot.GetConnectedOutputSlot()->GetTensorHandleFactoryId();
1209  const TensorInfo& tensorInfo = inputSlot.GetConnectedOutputSlot()->GetTensorInfo();
1210 
1211  ITensorHandleFactory* handleFactory = m_TensorHandleFactoryRegistry.GetFactory(factoryId);
1212  ARMNN_ASSERT(handleFactory);
1213 
1214  ImportedTensorHandlePin importedTensorHandlePin{layerBindingId,
1215  handleFactory->CreateTensorHandle(tensorInfo, false)};
1216 
1217  ITensorHandle* tensorHandle = importedTensorHandlePin.m_TensorHandle.get();
1218 
1219  if (!CheckFlag(tensorHandle->GetImportFlags(), m_NetworkProperties.m_OutputSource))
1220  {
1221  throw MemoryImportException(fmt::format("ImportInputs: Memory Import failed, backend: "
1222  "{} does not support importing from source {}"
1223  , factoryId, m_NetworkProperties.m_OutputSource));
1224  }
1225 
1226  if (tensorHandle->Import(outputTensor.second.GetMemoryArea(), m_NetworkProperties.m_OutputSource))
1227  {
1228  importedOutputs.push_back(m_CurImportedOutputId++);
1229  }
1230  else
1231  {
1232  throw MemoryImportException("ImportInputs: Memory Import failed");
1233  }
1234 
1235  m_PreImportedOutputHandles.push_back(std::move(importedTensorHandlePin));
1236  }
1237 
1238  return importedOutputs;
1239 }
bool HasCapability(const std::string &name, const BackendCapabilities &capabilities)
Convenience function to check if a capability exists in a BackendCapabilites struct.
const bool m_ExportEnabled
Deprecated and will be removed in future release.
Definition: IRuntime.hpp:87
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
ITensorHandleFactory * GetFactory(ITensorHandleFactory::FactoryId id) const
Find a TensorHandleFactory by Id Returns nullptr if not found.
const MemorySource m_OutputSource
Definition: IRuntime.hpp:96
bool CheckFlag(MemorySourceFlags flags, MemorySource source)

◆ IsAsyncEnabled()

bool IsAsyncEnabled ( )
inline

Definition at line 90 of file LoadedNetwork.hpp.

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

91  {
92  return m_NetworkProperties.m_AsyncEnabled;
93  }

◆ MakeLoadedNetwork()

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

Definition at line 82 of file LoadedNetwork.cpp.

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

Referenced by RuntimeImpl::LoadNetwork().

86 {
87  std::unique_ptr<LoadedNetwork> loadedNetwork;
88 
89  auto Fail = [&](const std::exception& error) -> std::unique_ptr<LoadedNetwork>
90  {
91  errorMessage = ToErrorMessage("An error occurred when preparing the network workloads: ", error);
92  ARMNN_LOG(error) << errorMessage;
93 
94  return std::unique_ptr<LoadedNetwork>();
95  };
96 
97  try
98  {
99  loadedNetwork.reset(new LoadedNetwork(std::move(net), networkProperties, profilingService));
100  }
101  catch (const armnn::RuntimeException& error)
102  {
103  return Fail(error);
104  }
105  catch (const armnn::Exception& error)
106  {
107  return Fail(error);
108  }
109  catch (const std::runtime_error& error)
110  {
111  return Fail(error);
112  }
113 
114  return loadedNetwork;
115 }
#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()

◆ SendNetworkStructure()

void SendNetworkStructure ( )

Definition at line 444 of file LoadedNetwork.cpp.

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

445 {
446  ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "LoadNetwork_SendNetworkStructure");
447  Graph& order = m_OptimizedNetwork->pOptimizedNetworkImpl->GetGraph().TopologicalSort();
448  ProfilingGuid networkGuid = m_OptimizedNetwork->GetGuid();
449 
450  std::unique_ptr<TimelineUtilityMethods> timelineUtils =
451  TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService);
452 
453  timelineUtils->CreateTypedEntity(networkGuid, LabelsAndEventClasses::NETWORK_GUID);
454 
455  for (auto&& layer : order)
456  {
457  // Add layer to the post-optimisation network structure
458  AddLayerStructure(timelineUtils, *layer, networkGuid);
459  switch (layer->GetType())
460  {
461  case LayerType::Input:
462  case LayerType::Output:
463  {
464  // Inputs and outputs are treated in a special way - see EnqueueInput() and EnqueueOutput().
465  break;
466  }
467  default:
468  {
469  for (auto& workload : m_WorkloadQueue)
470  {
471  // Add workload to the post-optimisation network structure
472  AddWorkloadStructure(timelineUtils, workload, *layer);
473  }
474  break;
475  }
476  }
477  }
478  // Commit to send the post-optimisation network structure
479  timelineUtils->Commit();
480 }
static std::unique_ptr< TimelineUtilityMethods > GetTimelineUtils(ProfilingService &profilingService)
#define ARMNN_SCOPED_PROFILING_EVENT(backendId, name)
Definition: Profiling.hpp:220

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