ArmNN
 20.11
Network.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "Network.hpp"
7 #include "Graph.hpp"
8 #include "Layer.hpp"
9 #include "DeviceSpec.hpp"
10 #include "Optimizer.hpp"
11 #include "SubgraphViewSelector.hpp"
12 #include "BackendSettings.hpp"
13 #include "optimizations/All.hpp"
14 
19 
20 #include <armnn/Exceptions.hpp>
21 #include <armnn/Utils.hpp>
22 #include <armnn/TypesUtils.hpp>
24 #include <armnn/Logging.hpp>
25 #include <armnn/utility/Assert.hpp>
28 
29 #include <ProfilingService.hpp>
30 
31 #include <fcntl.h>
32 #include <algorithm>
33 #include <fstream>
34 #include <memory>
35 #include <vector>
36 #include <algorithm>
37 
38 namespace armnn
39 {
40 
42 {
43  return new Network(networkOptions);
44 }
45 
47 {
48  return INetworkPtr(CreateRaw(networkOptions), &INetwork::Destroy);
49 }
50 
52 {
53  delete PolymorphicDowncast<Network*>(network);
54 }
55 
57 {
58  delete PolymorphicDowncast<OptimizedNetwork*>(network);
59 }
60 
62 {
63  m_Graph->Print();
64  return Status::Success;
65 }
66 
67 Status OptimizedNetwork::SerializeToDot(std::ostream& stream) const
68 {
69  return m_Graph->SerializeToDot(stream);
70 }
71 
72 void ReportError(const std::string& errorMessage,
73  Optional<std::vector<std::string>&> errorMessages)
74 {
75  std::stringstream fullErrorMessage;
76  fullErrorMessage << "ERROR: " << errorMessage;
77  ARMNN_LOG(warning) << fullErrorMessage.str();
78  if (errorMessages)
79  {
80  errorMessages.value().push_back(fullErrorMessage.str());
81  }
82 }
83 
84 void ReportWarning(const std::string& warningMessage,
85  Optional<std::vector<std::string>&> warningMessages)
86 {
87  std::stringstream fullWarningMessage;
88  fullWarningMessage << "WARNING: " << warningMessage;
89  ARMNN_LOG(warning) << fullWarningMessage.str();
90  if (warningMessages)
91  {
92  warningMessages.value().push_back(fullWarningMessage.str());
93  }
94 }
95 
97  const Layer* layer,
98  const BackendSettings& backendSettings,
99  Optional<std::vector<std::string>&> errMessages)
100 {
101  std::stringstream failureMsg;
102  failureMsg << "Layer of type " << GetLayerTypeAsCString(layer->GetType())
103  << " is not supported on any preferred backend " << backendSettings.m_PreferredBackends;
104  ReportError(failureMsg.str(), errMessages);
105 
106  res.m_Error = true;
107  return res;
108 }
109 
110 
111 bool CheckScaleSetOnQuantizedType(Layer* layer, Optional<std::vector<std::string>&> errMessages)
112 {
113  bool noErrors = true;
114  unsigned int numOutputs = layer->GetNumOutputSlots();
115  for (unsigned int i = 0; i < numOutputs; i++) {
116  OutputSlot& outputSlot = layer->GetOutputSlot(i);
117  TensorInfo info = outputSlot.GetTensorInfo();
118  if (DataType::QAsymmU8 == info.GetDataType()) {
119  if (0.f == info.GetQuantizationScale()) {
120  noErrors = false;
121  std::stringstream ss;
122  ss << "output " << i << " of layer " << GetLayerTypeAsCString(layer->GetType())
123  << " (" << layer->GetNameStr() << ") is of type"
124  << " Quantized 8 bit but its scale parameter has not been set";
125  ReportError(ss.str(), errMessages);
126  }
127  // Softmax under QuantisedAsymm8 must always be scale (1.0f/256.0f) and offset 0
128  if ((info.GetQuantizationScale() != (1.0f / 256.0f) ||
129  info.GetQuantizationOffset() != 0) &&
131  {
132  std::stringstream ss;
133  ss << "Quantization parameters for Softmax layer (Scale: " <<
134  info.GetQuantizationScale() << " and Offset: " << info.GetQuantizationOffset() <<
135  ") are incorrect and have been updated to Scale: 0.00390625 and Offset: 0";
136  ARMNN_LOG(warning) << ss.str();
137  info.SetQuantizationScale((1.0f /256.0f));
138  info.SetQuantizationOffset(0);
139  outputSlot.SetTensorInfo(info);
140  }
141  }
142  }
143  return noErrors;
144 }
145 
146 template <typename LayerT>
148 {
149  LayerT* layer = PolymorphicDowncast<LayerT*>(l);
150  if ((layer->GetType() == LayerType::Convolution2d || layer->GetType() == LayerType::FullyConnected)
151  && layer->m_Weight)
152  {
153  const TensorInfo& info = layer->m_Weight->GetTensorInfo();
154 
155  if (info.GetDataType() == DataType::BFloat16)
156  {
157  std::vector<float> newValues(info.GetNumElements());
158 
160  layer->m_Weight->template GetTensor<armnn::BFloat16>(), info.GetNumElements(), newValues.data());
161 
162  TensorInfo newInfo(info.GetShape(), DataType::Float32);
163  ConstTensor newInput(newInfo, newValues);
164  layer->m_Weight.reset(new ScopedCpuTensorHandle(newInput));
165  }
166  }
167  return layer;
168 }
169 
171  Graph& graph,
172  Layer* layer,
173  BackendId backend,
174  DataType dataTypeIn,
175  DataType dataTypeOut,
176  const std::vector<BackendId>& availablePreferredBackends,
177  std::string& reasonIfUnsupported,
178  Optional<std::vector<std::string>&> errMessages)
179 {
180  OptimizationResult result;
181 
182  // Helper lambda to compose meaningful error message before returning with error
183  auto ReturnError = [&](const Layer* layer)
184  {
185  return ReturnWithError(result, layer, backendSettings, errMessages);
186  };
187 
188  // need to set the compute device on the layer
189  // before we can check if it is supported
190  layer->SetBackendId(backend);
191  if (!IWorkloadFactory::IsLayerSupported(*layer, EmptyOptional(), reasonIfUnsupported))
192  {
193  if (dataTypeIn == DataType::Float16 || dataTypeOut == DataType::Float16)
194  {
195  if (IWorkloadFactory::IsLayerSupported(*layer, DataType::Float32, reasonIfUnsupported)
197  && layer->GetType() != LayerType::ConvertFp16ToFp32)
198  {
199  // Insert FP16 -> FP32 conversion layer before current layer
200  std::vector<ConvertFp16ToFp32Layer*> convertFp16ToFp32Layers;
201  if (dataTypeIn == DataType::Float16)
202  {
203  convertFp16ToFp32Layers =
205  }
206 
207  // Insert FP32 -> FP16 conversion layer after current layer
208  std::vector<ConvertFp32ToFp16Layer*> convertFp32ToFp16Layers;
209  if (dataTypeOut == DataType::Float16)
210  {
211  convertFp32ToFp16Layers =
212  InsertConvertFp32ToFp16LayersAfter(graph, *layer);
213  }
214 
215  // Assign a supported backend to the newly introduced conversion layers
216  auto AssignFirstSupportedBackend = [&](Layer* layer, BackendId preferredBackend)
217  {
218  bool supportedBackendFound = false;
219  std::string reasonIfUnsupported;
220 
221  // Try preferred backend first
222  layer->SetBackendId(preferredBackend);
224  EmptyOptional(),
225  reasonIfUnsupported))
226  {
227  supportedBackendFound = true;
228  }
229  else
230  {
231  for (const auto& backend : availablePreferredBackends)
232  {
233  // Skip preferred backend (we already determined that it is not supported)
234  if (backend == preferredBackend)
235  {
236  continue;
237  }
238 
239  layer->SetBackendId(backend);
241  EmptyOptional(),
242  reasonIfUnsupported))
243  {
244  supportedBackendFound = true;
245  break;
246  }
247  }
248  }
249 
250  return supportedBackendFound;
251  };
252 
253  for (ConvertFp16ToFp32Layer* convertLayer : convertFp16ToFp32Layers)
254  {
255  if (!AssignFirstSupportedBackend(convertLayer, backend))
256  {
257  return ReturnError(convertLayer);
258  }
259  }
260 
261  for (ConvertFp32ToFp16Layer* convertLayer : convertFp32ToFp16Layers)
262  {
263  if (!AssignFirstSupportedBackend(convertLayer, backend))
264  {
265  return ReturnError(convertLayer);
266  }
267  }
268 
269  return result;
270  }
271  }
272  else if (dataTypeIn == DataType::BFloat16 || dataTypeOut == DataType::BFloat16)
273  {
274  if (IWorkloadFactory::IsLayerSupported(*layer, DataType::Float32, reasonIfUnsupported)
276  && layer->GetType() != LayerType::ConvertBf16ToFp32)
277  {
278  // Insert BF16 -> FP32 conversion layer before current layer
279  std::vector<ConvertBf16ToFp32Layer*> convertBf16ToFp32Layers;
280  if (dataTypeIn == DataType::BFloat16)
281  {
282  convertBf16ToFp32Layers =
284  if (layer->GetType() == LayerType::Convolution2d)
285  {
286  ConvertBf16ToFp32Weight<Convolution2dLayer>(layer);
287  }
288  else if (layer->GetType() == LayerType::FullyConnected)
289  {
290  ConvertBf16ToFp32Weight<FullyConnectedLayer>(layer);
291  }
292  }
293 
294  // Insert FP32 -> BF16 conversion layer after current layer
295  std::vector<ConvertFp32ToBf16Layer*> convertFp32ToBf16Layers;
296  if (dataTypeOut == DataType::BFloat16)
297  {
298  convertFp32ToBf16Layers =
299  InsertConvertFp32ToBf16LayersAfter(graph, *layer);
300  }
301 
302  // Assign a supported backend to the newly introduced conversion layers
303  auto AssignFirstSupportedBackend = [&](Layer* layer, BackendId preferredBackend)
304  {
305  bool supportedBackendFound = false;
306  std::string reasonIfUnsupported;
307 
308  // Try preferred backend first
309  layer->SetBackendId(preferredBackend);
311  EmptyOptional(),
312  reasonIfUnsupported))
313  {
314  supportedBackendFound = true;
315  }
316  else
317  {
318  for (const auto& backend : availablePreferredBackends)
319  {
320  // Skip preferred backend (we already determined that it is not supported)
321  if (backend == preferredBackend)
322  {
323  continue;
324  }
325 
326  layer->SetBackendId(backend);
328  EmptyOptional(),
329  reasonIfUnsupported))
330  {
331  supportedBackendFound = true;
332  break;
333  }
334  }
335  }
336 
337  return supportedBackendFound;
338  };
339 
340  for (ConvertBf16ToFp32Layer* convertLayer : convertBf16ToFp32Layers)
341  {
342  if (!AssignFirstSupportedBackend(convertLayer, backend))
343  {
344  return ReturnError(convertLayer);
345  }
346  }
347 
348  for (ConvertFp32ToBf16Layer* convertLayer : convertFp32ToBf16Layers)
349  {
350  if (!AssignFirstSupportedBackend(convertLayer, backend))
351  {
352  return ReturnError(convertLayer);
353  }
354  }
355 
356  return result;
357  }
358  }
359 
360  std::stringstream warningMsg;
361  warningMsg << "Layer of type " << GetLayerTypeAsCString(layer->GetType())
362  << " is not supported on requested backend " << layer->GetBackendId().Get()
363  << " for input data type " << GetDataTypeName(dataTypeIn)
364  << " and output data type " << GetDataTypeName(dataTypeOut)
365  << " (reason: " << reasonIfUnsupported
366  << "), falling back to the next backend.";
367  ReportWarning(warningMsg.str(), errMessages);
368 
369  return OptimizationResult(true, false);
370  }
371  else
372  {
373  return result;
374  }
375 }
376 
377 
379  BackendSettings& backendSettings,
380  Graph::Iterator& firstLayer,
381  Graph::Iterator& lastLayer,
382  Optional<std::vector<std::string>&> errMessages)
383 {
384  OptimizationResult result;
385 
386  // Helper lambda to compose meaningful error message before returning with error
387  auto ReturnError = [&](const Layer* layer)
388  {
389  return ReturnWithError(result, layer, backendSettings, errMessages);
390  };
391 
392 
393  auto availablePreferredBackends = backendSettings.GetAvailablePreferredBackends();
394  if (availablePreferredBackends.empty())
395  {
396  std::stringstream failureMsg;
397  failureMsg << "No preferred backends are available";
398  ReportError(failureMsg.str(), errMessages);
399 
400  result.m_Error = true;
401  return result;
402  }
403 
404  for (auto it = firstLayer; it != lastLayer; ++it)
405  {
406  auto layer = *it;
407 
408  DataType dataTypeIn = layer->GetNumInputSlots() == 0 ? DataType::Float32 :
409  layer->GetInputSlot(0).GetConnectedOutputSlot()->GetTensorInfo().GetDataType();
410  DataType dataTypeOut = layer->GetNumOutputSlots() == 0 ? DataType::Float32 :
411  layer->GetOutputSlot(0).GetTensorInfo().GetDataType();
412 
413  std::string reasonIfUnsupported;
414  bool found = false;
415  if (!CheckScaleSetOnQuantizedType(layer, errMessages))
416  {
417  // don't bomb immediately, find all the quantized outputs
418  // which haven't had a scale set and report them all back.
419  result.m_Error = true;
420  }
421 
422  // First try assign layer to hint backend
423  if (layer->GetBackendHint().has_value() &&
424  backendSettings.IsBackendSupported(layer->GetBackendHint().value()) &&
425  AttemptBackendAssignment(backendSettings,
426  optNetObjPtr->GetGraph(),
427  layer,
428  layer->GetBackendHint().value(),
429  dataTypeIn,
430  dataTypeOut,
431  availablePreferredBackends,
432  reasonIfUnsupported,
433  errMessages).IsOk())
434  {
435  found = true;
436  backendSettings.m_SelectedBackends.insert(layer->GetBackendHint().value());
437  }
438  else
439  {
440  // Try assign layer to prefered list of backends
441  for (const auto& backend : availablePreferredBackends)
442  {
443  if (layer->GetBackendHint().has_value() &&
444  layer->GetBackendHint().value() == backend)
445  {
446  continue; //Don't re-test the backend hint
447  }
448 
449  OptimizationResult res = AttemptBackendAssignment(backendSettings,
450  optNetObjPtr->GetGraph(),
451  layer,
452  backend,
453  dataTypeIn,
454  dataTypeOut,
455  availablePreferredBackends,
456  reasonIfUnsupported,
457  errMessages);
458 
459  if (res.IsOk())
460  {
461  found = true;
462  backendSettings.m_SelectedBackends.insert(backend);
463  break;
464  }
465  else if (res.IsError())
466  {
467  return res; // Cannot continue.
468  // Note: we don't need to log the error as it would already
469  // be logged in AttemptBackendAssignment().
470  }
471  else
472  {
473  ARMNN_ASSERT_MSG(res.IsWarningOnly(), "OptimizationResult in unexpected state.");
474  }
475  }
476  }
477 
478  // If the layer is unsupported by any devices, log and return a null network.
479  if (!found)
480  {
481  // NOTE: if the layer is not an operation queue type AND we have not got CpuRef as a
482  // fallback we should set the compute device on the layer to CpuRef (these are not
483  // available as accelerated operations, or are only available under certain
484  // conditions, currently they comprise MemCopy, Constant, Permute)
485  armnn::LayerType layerType = layer->GetType();
486  if (!backendSettings.IsCpuRefUsed() && (layerType == armnn::LayerType::MemCopy ||
487  layerType == armnn::LayerType::Constant ||
488  layerType == armnn::LayerType::Permute))
489  {
490  BackendId cpuBackendId(armnn::Compute::CpuRef);
491  layer->SetBackendId(cpuBackendId);
492  backendSettings.m_SelectedBackends.insert(cpuBackendId);
493  }
494  else
495  {
496  return ReturnError(layer);
497  }
498  }
499  }
500 
501  return result;
502 }
503 
505  BackendSettings& backendSettings,
506  SubgraphView& subgraph,
507  Optional<std::vector<std::string>&> errMessages)
508 {
509  Graph::Iterator firstLayer = subgraph.begin();
510  Graph::Iterator lastLayer = subgraph.end();
511  return AssignBackends(optNetObjPtr,
512  backendSettings,
513  firstLayer,
514  lastLayer,
515  errMessages);
516 }
517 
519  BackendSettings& backendSettings)
520 {
521  BackendsMap backends;
522  auto const& backendRegistry = BackendRegistryInstance();
523  for (auto&& selectedBackend : backendSettings.m_SupportedBackends)
524  {
525  auto backendFactory = backendRegistry.GetFactory(selectedBackend);
526  auto backendObjPtr = backendFactory();
527  ARMNN_ASSERT(backendObjPtr);
528 
529  backendObjPtr->RegisterTensorHandleFactories(handleFactoryRegistry);
530 
531  backends[backendObjPtr->GetId()] = std::move(backendObjPtr);
532  }
533 
534  return backends;
535 }
536 
538  BackendSettings& backendSettings,
539  BackendsMap& backends,
540  const ModelOptions& modelOptions,
541  Optional<std::vector<std::string>&> errMessages)
542 {
543  ARMNN_ASSERT(optNetObjPtr);
544 
545  OptimizationResult result;
546 
547  // Get the optimized graph
548  Graph& optGraph = optNetObjPtr->GetGraph();
549 
550  // Run backend specific optimizations
551  for (auto&& selectedBackend : backendSettings.m_SelectedBackends)
552  {
553  auto backendObjPtr = backends.find(selectedBackend)->second.get();
554  ARMNN_ASSERT(backendObjPtr);
555 
556  // Select sub-graphs based on backend
559  // Select layers assigned to the requested backend
560  [&backendObjPtr](const Layer& layer)
561  {
562  return layer.GetType() != LayerType::Input &&
563  layer.GetType() != LayerType::Output &&
564  layer.GetBackendId() == backendObjPtr->GetId();
565  });
566  if (subgraphs.empty())
567  {
568  // No sub-graphs found, try with next selected backend
569  continue;
570  }
571 
572  // Try to optimize each sub-graph
573  for (auto& subgraph : subgraphs)
574  {
575  // Try to optimize the current sub-graph
576  OptimizationViews optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraph, modelOptions);
577  ARMNN_ASSERT(optimizationViews.Validate(*subgraph));
578 
579  // Optimization attempted, check the resulting optimized sub-graph
580  for (auto& substitution : optimizationViews.GetSubstitutions())
581  {
582  // Sub-graph optimized, substitute the sub-graph with the new optimized one in the main optimized graph
583  SubgraphView& replacementSubgraph = substitution.m_ReplacementSubgraph;
584  SubgraphView& substitutableSubgraph = substitution.m_SubstitutableSubgraph;
585  optGraph.SubstituteSubgraph(substitutableSubgraph, replacementSubgraph);
586 
587  // Assign the current backend to the optimized sub-graph
588  std::for_each(replacementSubgraph.begin(), replacementSubgraph.end(), [&selectedBackend](Layer* l)
589  {
590  ARMNN_ASSERT(l);
591  l->SetBackendId(selectedBackend);
592  });
593  }
594 
595  if (!optimizationViews.GetFailedSubgraphs().empty())
596  {
597  std::stringstream warningMsg;
598  warningMsg << "Some sub-graph(s) failed to optimized on " << backendObjPtr->GetId() << " backend.";
599  ReportWarning(warningMsg.str(), errMessages);
600 
601  // Failed to optimize the given sub-graph, re-assign the sub-graph layers to other available backends
602  BackendSettings settingsCopy(backendSettings);
603  if (!backendObjPtr->GetId().IsCpuRef())
604  {
605  // Add the current backend to the list of backends to ignore
606  settingsCopy.m_IgnoredBackends.insert(backendObjPtr->GetId());
607  }
608 
609  int count=0;
610  for (auto& failedSubgraph : optimizationViews.GetFailedSubgraphs())
611  {
612  // An error occurred: the optimization was attempted but not performed, try different backends
613  std::stringstream subgraphMsg;
614  subgraphMsg << "Re-assigning backends to " << failedSubgraph.GetLayers().size()
615  << " layers inside sub-graph " << count++;
616  ReportWarning(subgraphMsg.str(), errMessages);
617 
618  OptimizationResult reassignmentResult = AssignBackends(optNetObjPtr,
619  settingsCopy,
620  *subgraph,
621  errMessages);
622  if (reassignmentResult.m_Error)
623  {
624  // Failed to re-assign one of the remaining backends to each layer of the sub-graph
625  result.m_Error = true;
626  return result;
627  }
628  }
629  }
630  }
631  }
632 
633  return result;
634 }
635 
638  TensorHandleFactoryRegistry& registry)
639 {
640  if (src != dst)
641  {
642  ITensorHandleFactory* srcFactory = registry.GetFactory(src);
643  ITensorHandleFactory* dstFactory = registry.GetFactory(dst);
644 
645  if (srcFactory && dstFactory &&
646  (srcFactory->GetExportFlags() & dstFactory->GetImportFlags()) != 0)
647  {
648  return false;
649  }
650  return true;
651  }
652  return false;
653 }
654 
655 // Find the handle factory for the input layer which results in fewest required copies.
657  OutputSlot& slot,
658  TensorHandleFactoryRegistry& registry)
659 {
660  Layer& layer = slot.GetOwningLayer();
662 
663  // Explicitly select the tensorhandle factory for InputLayer because the rules for it are slightly different. It
664  // doesn't matter which backend it is assigned to because they all use the same implementation, which
665  // requires Map/Unmap support. This means that, so long as the handle type supports map/unmap semantics, we can
666  // select a factory with maximum compatibility with the layers connected to the InputLayer.
667 
668  // First ensure the from backends can support the TensorHandeAPI
669  auto frmBackend = backends.find(layer.GetBackendId());
670  if (frmBackend == backends.end() ||
671  !frmBackend->second->SupportsTensorAllocatorAPI())
672  {
674  }
675 
676  // Go through all connections to the output slot and determine the TensorHandleFactory which results in the
677  // fewest copies.
678  std::map<ITensorHandleFactory::FactoryId, int> factoryScores;
679  int topScore = 0;
681 
682  for (auto&& connection : slot.GetConnections())
683  {
684  const Layer& connectedLayer = connection->GetOwningLayer();
685 
686  auto toBackend = backends.find(connectedLayer.GetBackendId());
687  ARMNN_ASSERT_MSG(toBackend != backends.end(), "Backend id not found for the connected layer");
688 
689  if (!toBackend->second.get()->SupportsTensorAllocatorAPI())
690  {
691  // The destination backend does not support the tensor allocator API, move to the next one
692  continue;
693  }
694 
695  auto dstPrefs = toBackend->second.get()->GetHandleFactoryPreferences();
696  for (auto&& dst : dstPrefs)
697  {
698  // Input layers use the mem copy workload or import, so the selected factory must
699  // support either the map/unmap API or Import API
700  ITensorHandleFactory* factory = registry.GetFactory(dst);
701  if (!factory->SupportsMapUnmap() &&
702  !CheckFlag(factory->GetImportFlags(), MemorySource::Malloc)) // Just support cpu mem imports for now
703  {
704  // The current tensor handle factory does not support the map/unmap or import
705  // strategy, move to the next one
706  continue;
707  }
708 
709  auto it = factoryScores.find(dst);
710  if (it == factoryScores.end())
711  {
712  // Add new score to the table
713  factoryScores[dst] = 0;
714  if (topChoice == ITensorHandleFactory::LegacyFactoryId)
715  {
716  topChoice = dst;
717  }
718  }
719  else
720  {
721  // Increase the score
722  factoryScores[dst]++;
723 
724  // Track the best option
725  if (factoryScores[dst] > topScore)
726  {
727  topScore = factoryScores[dst];
728  topChoice = dst;
729  }
730  }
731  }
732  }
733 
734  return topChoice;
735 }
736 
737 // Find the handle factory for the output layer which results in fewest required copies.
739  OutputSlot& slot,
740  TensorHandleFactoryRegistry& registry)
741 {
742  IgnoreUnused(backends, slot, registry);
744 }
745 
746 // For all handle factories supported on the source backend, we wish to find the one which requires the fewest copies
747 // when considering all connections.
749  OutputSlot& outputSlot,
750  TensorHandleFactoryRegistry& registry)
751 {
752  // First ensure the from backends can support the TensorHandeAPI
753  Layer& layer = outputSlot.GetOwningLayer();
754  auto frmBackend = backends.find(layer.GetBackendId());
755  if (frmBackend == backends.end() ||
756  !frmBackend->second->SupportsTensorAllocatorAPI())
757  {
759  }
760 
761  // Connections to Output Layers requires support for map/unmap on the TensorHandle.
762  bool requiresMapUnmap = false;
763  for (auto&& connection : outputSlot.GetConnections())
764  {
765  const Layer& connectedLayer = connection->GetOwningLayer();
766  if (connectedLayer.GetType() == LayerType::Output)
767  {
768  requiresMapUnmap = true;
769  }
770  }
771 
772  IBackendInternal* srcBackend = frmBackend->second.get();
773  auto srcPrefs = srcBackend->GetHandleFactoryPreferences();
774 
775  // Initialize the scores
776  std::map<ITensorHandleFactory::FactoryId, int> factoryScores;
777  for (auto&& pref : srcPrefs)
778  {
779  if (requiresMapUnmap) // Only consider factories that support map/unmap if required
780  {
781  ITensorHandleFactory* factory = registry.GetFactory(pref);
782  if (!factory->SupportsMapUnmap())
783  {
784  // The current tensor handle factory does not support the map/unmap strategy, move to the next one
785  continue;
786  }
787  }
788 
789  auto it = factoryScores.find(pref);
790  if (it == factoryScores.end())
791  {
792  // Add new score to the table
793  factoryScores[pref] = 0;
794  }
795  }
796 
797  // Score each handle factory based on how many times it requires copies on the slot connections
798  for (auto&& connection : outputSlot.GetConnections())
799  {
800  const Layer& connectedLayer = connection->GetOwningLayer();
801 
802  auto toBackend = backends.find(connectedLayer.GetBackendId());
803  ARMNN_ASSERT_MSG(toBackend != backends.end(), "Backend id not found for the connected layer");
804 
805  auto dstPrefs = toBackend->second.get()->GetHandleFactoryPreferences();
806  for (auto&& src : srcPrefs)
807  {
808  if (factoryScores.find(src) == factoryScores.end()) // Don't consider excluded factories
809  {
810  continue;
811  }
812 
813  for (auto&& dst : dstPrefs)
814  {
815  if (RequiresCopy(src, dst, registry))
816  {
817  // Copy avoided, increase the score
818  factoryScores[src]++;
819  break;
820  }
821  }
822  }
823  }
824 
825  // Find the lowest score
826  int minScore = std::numeric_limits<int>::max();
827  for (auto it : factoryScores)
828  {
829  minScore = std::min(minScore, it.second);
830  }
831 
832  // Collect factories matching the best(lowest) score
833  std::vector<ITensorHandleFactory::FactoryId> optimalFactories;
834  for (auto it : factoryScores)
835  {
836  if (it.second == minScore)
837  {
838  optimalFactories.push_back(it.first);
839  }
840  }
841 
842  // For all compatible Factories matching the best score, find the preferred one for the current layer.
843  for (auto&& srcPref : srcPrefs)
844  {
845  for (auto&& comp : optimalFactories)
846  {
847  if (comp == srcPref)
848  {
849  return comp;
850  }
851  }
852  }
853 
855 }
856 
858  ITensorHandleFactory::FactoryId srcFactoryId,
859  const Layer& layer,
860  const Layer& connectedLayer,
861  TensorHandleFactoryRegistry& registry,
862  bool importEnabled)
863 {
864  auto toBackend = backends.find(connectedLayer.GetBackendId());
865  ARMNN_ASSERT_MSG(toBackend != backends.end(), "Backend id not found for the connected layer");
866 
867  auto dstPrefs = toBackend->second.get()->GetHandleFactoryPreferences();
868 
869  // Legacy API check for backward compatibility
870  if (srcFactoryId == ITensorHandleFactory::LegacyFactoryId || dstPrefs.empty())
871  {
872  if (layer.GetBackendId() != connectedLayer.GetBackendId())
873  {
875  }
876  else
877  {
879  }
880  }
881 
882  // TensorHandleFactory API present, so perform more sophisticated strategies.
883  // Dst Output layers don't require copy because they use import or map/unmap
884  if (connectedLayer.GetType() == LayerType::Output)
885  {
887  }
888 
889  // Search for direct match in prefs
890  for (auto&& pref : dstPrefs)
891  {
892  if (pref == srcFactoryId)
893  {
895  }
896  }
897 
898  // Search for export/import options
899  ITensorHandleFactory* srcFactory = registry.GetFactory(srcFactoryId);
900  if (srcFactory->GetExportFlags() != 0 && importEnabled)
901  {
902  for (auto&& pref : dstPrefs)
903  {
904  ITensorHandleFactory* dstFactory = registry.GetFactory(pref);
905 
906  // Handles cases when a destPref is not listed in TensorHandleFactoryRegistry
907  if (!dstFactory) {
908  continue;
909  }
910 
911  if ((dstFactory->GetImportFlags() & srcFactory->GetExportFlags()) != 0)
912  {
913  auto srcCapability = srcFactory->GetCapabilities(&layer, &layer, CapabilityClass::PaddingRequired);
914  auto dstCapability = dstFactory->GetCapabilities(&connectedLayer,
915  &connectedLayer,
917  // Do not require memory copy if the source and destination do not require padding.
918  if (srcCapability.empty() && dstCapability.empty())
919  {
921  }
922  }
923  }
924  }
925 
926  // Search for copy options via map/unmap
927  if (srcFactory->SupportsMapUnmap())
928  {
929  for (auto&& pref : dstPrefs)
930  {
931  ITensorHandleFactory* dstFactory = registry.GetFactory(pref);
932  if (dstFactory && dstFactory->SupportsMapUnmap())
933  {
935  }
936  }
937  }
938 
940 }
941 
942 // Select the TensorHandleFactories and the corresponding memory strategy
944  BackendsMap& backends,
945  TensorHandleFactoryRegistry& registry,
946  bool importEnabled,
947  Optional<std::vector<std::string>&> errMessages)
948 {
949  OptimizationResult result;
950 
951  optGraph.ForEachLayer([&backends, &registry, &result, &errMessages, importEnabled](Layer* layer)
952  {
953  ARMNN_ASSERT(layer);
954 
955  // Lets make sure the backend is in our list of supported backends. Something went wrong during backend
956  // assignment if this check fails
957  ARMNN_ASSERT(backends.find(layer->GetBackendId()) != backends.end());
958 
959  // Check each output separately
960  for (unsigned int slotIdx = 0; slotIdx < layer->GetNumOutputSlots(); slotIdx++)
961  {
962  OutputSlot& outputSlot = layer->GetOutputSlot(slotIdx);
963 
965 
966  // Calculate the factory to use which results in the fewest copies being made.
967  switch(layer->GetType())
968  {
969  case LayerType::Input:
970  slotOption = CalculateSlotOptionForInput(backends, outputSlot, registry);
971  break;
972  case LayerType::Output:
973  slotOption = CalculateSlotOptionForOutput(backends, outputSlot, registry);
974  break;
975  default:
976  slotOption = CalculateSlotOption(backends, outputSlot, registry);
977  break;
978  }
979  outputSlot.SetTensorHandleFactory(slotOption);
980 
981  // Now determine the "best" edge strategy for each connection given the slotOption.
982  unsigned int connectionIdx = 0;
983  for (auto&& connection : outputSlot.GetConnections())
984  {
985  const Layer& connectedLayer = connection->GetOwningLayer();
986 
987  EdgeStrategy strategy = CalculateEdgeStrategy(backends, slotOption, *layer, connectedLayer,
988  registry, importEnabled);
989 
990  if (strategy == EdgeStrategy::Undefined)
991  {
992  result.m_Error = true;
993  if (errMessages)
994  {
995  errMessages.value().emplace_back("Could not find valid strategy required for compatibility"
996  " between backends.");
997  }
998  return;
999  }
1000 
1001  outputSlot.SetEdgeStrategy(connectionIdx, strategy);
1002 
1003  connectionIdx++;
1004  }
1005  }
1006  });
1007 
1008  return result;
1009 }
1010 
1012  const std::vector<BackendId>& backendPreferences,
1013  const IDeviceSpec& deviceSpec,
1014  const OptimizerOptions& options,
1015  Optional<std::vector<std::string>&> messages)
1016 {
1017  if (backendPreferences.empty())
1018  {
1019  throw InvalidArgumentException("Invoked Optimize with no backends specified");
1020  }
1021 
1022  if (options.m_ReduceFp32ToFp16 && options.m_ReduceFp32ToBf16)
1023  {
1024  throw InvalidArgumentException("BFloat16 and Float16 optimization cannot be enabled at the same time.");
1025  }
1026 
1027  const Network& network = *PolymorphicDowncast<const Network*>(&inNetwork);
1028  std::unique_ptr<Graph> graph = std::make_unique<Graph>(network.GetGraph());
1029 
1030  auto optNet = IOptimizedNetworkPtr(new OptimizedNetwork(std::move(graph), options.m_ModelOptions),
1032 
1033  OptimizedNetwork* optNetObjPtr = PolymorphicDowncast<OptimizedNetwork*>(optNet.get());
1034 
1035  // Get the optimized graph
1036  Graph& optGraph = optNetObjPtr->GetGraph();
1037 
1038  // Perform AddBroadcastReshapeLayer optimisation
1039  using namespace optimizations;
1041 
1042  // Infer the tensor infos for all output slots. Throws an exception on failure
1043  optGraph.InferTensorInfos();
1044 
1045  // Perform optimisation passes
1051  MovePermuteUp(),
1052  MoveTransposeUp(),
1053  PermuteAsReshape(),
1063 
1064  // If Fp32 to Fp16 optimization is set convert Fp32 network to Fp16
1065  if (options.m_ReduceFp32ToFp16)
1066  {
1069  }
1070 
1071  // If Fp32 to Bf16 optimization is set convert Fp32 network to Bf16
1072  // Convert input of Convolution2d and FullyConnected from Fp32 to Bf16
1073  // Only Constant weight of Convolution2d and FullyConnected are converted from Fp32 to Bf16
1074  if (options.m_ReduceFp32ToBf16)
1075  {
1077  }
1078 
1079  // Initialize backend settings
1080  BackendSettings backendSettings(backendPreferences, deviceSpec);
1081  if (backendSettings.GetAvailablePreferredBackends().empty())
1082  {
1083  std::stringstream failureMsg;
1084  failureMsg << "None of the preferred backends " << backendPreferences
1085  << " are supported. Current platform provides " << backendSettings.m_SupportedBackends;
1086  ReportError(failureMsg.str(), messages);
1087  throw InvalidArgumentException(failureMsg.str());
1088  }
1089 
1090  // Create a map to temporarily hold initialized backend objects
1091  TensorHandleFactoryRegistry tensorHandleFactoryRegistry;
1092  BackendsMap backends = CreateSupportedBackends(tensorHandleFactoryRegistry, backendSettings);
1093 
1094  // Assign an available backend to each layer
1095  Graph::Iterator firstLayer = optGraph.begin();
1096  Graph::Iterator lastLayer = optGraph.end();
1097  OptimizationResult assignBackendsResult = AssignBackends(optNetObjPtr,
1098  backendSettings,
1099  firstLayer,
1100  lastLayer,
1101  messages);
1102  if (assignBackendsResult.m_Error)
1103  {
1104  // Failed to assign a backend to each layer
1105  throw InvalidArgumentException("Failed to assign a backend to each layer");
1106  }
1107 
1110 
1111  // Apply the backend-specific optimizations
1112  OptimizationResult backendOptimizationResult = ApplyBackendOptimizations(optNetObjPtr,
1113  backendSettings,
1114  backends,
1115  options.m_ModelOptions,
1116  messages);
1117  if (backendOptimizationResult.m_Error)
1118  {
1119  // Failed to apply the backend-specific optimizations
1120  throw InvalidArgumentException("Failed to apply the backend-specific optimizations");
1121  }
1122 
1123  // If the debug flag is set, then insert a DebugLayer after each layer
1124  // Doing this after applying the backend optimizations as they might have changed some layers
1125  if (options.m_Debug)
1126  {
1128  }
1129 
1130  // Calculate the compatibility strategies for tensor handles
1131  OptimizationResult strategyResult = SelectTensorHandleStrategy(optGraph,
1132  backends,
1133  tensorHandleFactoryRegistry,
1134  options.m_ImportEnabled,
1135  messages);
1136  if (strategyResult.m_Error)
1137  {
1138  // Failed to apply the backend-specific optimizations
1140  }
1141 
1142  // Based on the tensor handle strategy determined above, insert copy layers where required.
1143  optGraph.AddCompatibilityLayers(backends, tensorHandleFactoryRegistry);
1144 
1145  // Convert constants
1148 
1149  // Run backend specific optimizations (deprecated)
1150  for (auto&& chosenBackend : backendSettings.m_SelectedBackends)
1151  {
1152  auto factoryFun = BackendRegistryInstance().GetFactory(chosenBackend);
1153  auto backendPtr = factoryFun();
1154  ARMNN_ASSERT(backendPtr.get() != nullptr);
1155 
1157  auto backendSpecificOptimizations = backendPtr->GetOptimizations();
1159 
1160  if (!backendSpecificOptimizations.empty())
1161  {
1162  Optimizer::Pass(optNetObjPtr->GetGraph(), backendSpecificOptimizations);
1163  }
1164  }
1165 
1166  return optNet;
1167 }
1168 bool Network::GetShapeInferenceMethod()
1169 {
1170  if (m_NetworkOptions.size() > 0 && m_NetworkOptions[0].GetBackendId().Get() == "ShapeInferenceMethod")
1171  {
1172  return m_NetworkOptions[0].GetOption(0).GetValue().AsBool();
1173  }
1174 
1175  return false;
1176 }
1178 : m_NetworkOptions(networkOptions),
1179  m_Graph(std::make_unique<Graph>(GetShapeInferenceMethod()))
1180 {}
1181 
1183 {
1184 }
1185 
1187 {
1188  m_Graph->Print();
1189  return Status::Success;
1190 }
1191 
1193 {
1194  return m_Graph->AddLayer<InputLayer>(id, name);
1195 }
1196 
1198  const char* name)
1199 {
1200  return m_Graph->AddLayer<BatchToSpaceNdLayer>(batchToSpaceNdDescriptor, name);
1201 }
1202 
1204  const char* name)
1205 {
1206  return m_Graph->AddLayer<ComparisonLayer>(comparisonDescriptor, name);
1207 }
1208 
1210  const char* name)
1211 {
1212  return m_Graph->AddLayer<ElementwiseUnaryLayer>(elementwiseUnaryDescriptor, name);
1213 }
1214 
1216  const char* name)
1217 {
1218  return m_Graph->AddLayer<FillLayer>(fillDescriptor, name);
1219 }
1220 
1221 IConnectableLayer* Network::AddFullyConnectedLayerImpl(const FullyConnectedDescriptor& fullyConnectedDescriptor,
1222  const ConstTensor& weights,
1223  const Optional<ConstTensor>& biases,
1224  const char* name)
1225 {
1226  if (fullyConnectedDescriptor.m_BiasEnabled && !biases.has_value())
1227  {
1228  throw InvalidArgumentException("AddFullyConnectedLayer: biases cannot be empty");
1229  }
1230 
1231  const auto layer = m_Graph->AddLayer<FullyConnectedLayer>(fullyConnectedDescriptor, name);
1232 
1233  layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
1234 
1235  if (fullyConnectedDescriptor.m_BiasEnabled)
1236  {
1237  layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(biases.value());
1238  }
1239 
1240  return layer;
1241 }
1242 
1244  const ConstTensor& weights,
1245  const Optional<ConstTensor>& biases,
1246  const char* name)
1247 {
1248  return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, biases, name);
1249 }
1250 
1252  const ConstTensor& weights,
1253  const char* name)
1254 {
1255  Optional<ConstTensor> biases;
1256  return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, biases, name);
1257 }
1258 
1260  const ConstTensor& weights,
1261  const ConstTensor& biases,
1262  const char* name)
1263 {
1264  Optional<ConstTensor> optionalBiases(biases);
1265  return AddFullyConnectedLayerImpl(fullyConnectedDescriptor, weights, optionalBiases, name);
1266 }
1267 
1269  const char* name)
1270 {
1271  return m_Graph->AddLayer<ConcatLayer>(concatDescriptor, name);
1272 }
1273 
1274 IConnectableLayer* Network::AddConvolution2dLayerImpl(const Convolution2dDescriptor& convolution2dDescriptor,
1275  const ConstTensor& weights,
1276  const Optional<ConstTensor>& biases,
1277  const char* name)
1278 {
1279  if (convolution2dDescriptor.m_BiasEnabled && !biases.has_value())
1280  {
1281  throw InvalidArgumentException("AddConvolution2dLayer: biases cannot be empty");
1282  }
1283 
1284  const auto layer = m_Graph->AddLayer<Convolution2dLayer>(convolution2dDescriptor, name);
1285 
1286  layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
1287 
1288  if (convolution2dDescriptor.m_BiasEnabled)
1289  {
1290  layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(biases.value());
1291  }
1292 
1293  return layer;
1294 }
1295 
1297  const ConstTensor& weights,
1298  const Optional<ConstTensor>& biases,
1299  const char* name)
1300 {
1301  return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, biases, name);
1302 }
1303 
1305  const ConstTensor& weights,
1306  const char* name)
1307 {
1308  Optional<ConstTensor> biases;
1309  return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, biases, name);
1310 }
1311 
1313  const ConstTensor& weights,
1314  const ConstTensor& biases,
1315  const char* name)
1316 {
1317  Optional<ConstTensor> optionalBiases(biases);
1318  return AddConvolution2dLayerImpl(convolution2dDescriptor, weights, optionalBiases, name);
1319 }
1320 
1321 IConnectableLayer* Network::AddDepthwiseConvolution2dLayerImpl(
1322  const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
1323  const ConstTensor& weights,
1324  const Optional<ConstTensor>& biases,
1325  const char* name)
1326 {
1327  if (convolution2dDescriptor.m_BiasEnabled && !biases.has_value())
1328  {
1329  throw InvalidArgumentException("AddDepthwiseConvolution2dLayer: biases cannot be empty");
1330  }
1331 
1332  const auto layer = m_Graph->AddLayer<DepthwiseConvolution2dLayer>(convolution2dDescriptor, name);
1333 
1334  layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
1335 
1336  if (convolution2dDescriptor.m_BiasEnabled)
1337  {
1338  layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(biases.value());
1339  }
1340 
1341  return layer;
1342 }
1343 
1345  const char* name)
1346 {
1347  return m_Graph->AddLayer<DepthToSpaceLayer>(depthToSpaceDescriptor, name);
1348 }
1349 
1351  const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
1352  const ConstTensor& weights,
1353  const Optional<ConstTensor>& biases,
1354  const char* name)
1355 {
1356  return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, biases, name);
1357 }
1358 
1360  const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
1361  const ConstTensor& weights,
1362  const char* name)
1363 {
1364  Optional<ConstTensor> biases;
1365  return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, biases, name);
1366 }
1367 
1369  const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
1370  const ConstTensor& weights,
1371  const ConstTensor& biases,
1372  const char* name)
1373 {
1374  Optional<ConstTensor> optionalBiases(biases);
1375  return AddDepthwiseConvolution2dLayerImpl(convolution2dDescriptor, weights, optionalBiases, name);
1376 }
1377 
1379  const ConstTensor& anchors, const char* name)
1380 {
1381  const auto layer = m_Graph->AddLayer<DetectionPostProcessLayer>(descriptor, name);
1382 
1383  layer->m_Anchors = std::make_unique<ScopedCpuTensorHandle>(anchors);
1384 
1385  return layer;
1386 }
1387 
1389  const char* name)
1390 {
1391  return m_Graph->AddLayer<PermuteLayer>(permuteDescriptor, name);
1392 }
1393 
1395  const char* name)
1396 {
1397  return m_Graph->AddLayer<Pooling2dLayer>(pooling2dDescriptor, name);
1398 }
1399 
1401  const char* name)
1402 {
1403  return m_Graph->AddLayer<ActivationLayer>(activationDescriptor, name);
1404 }
1405 
1407  const char* name)
1408 {
1409  return m_Graph->AddLayer<ArgMinMaxLayer>(argMinMaxDescriptor, name);
1410 }
1411 
1413 normalizationDescriptor,
1414  const char* name)
1415 {
1416  return m_Graph->AddLayer<NormalizationLayer>(normalizationDescriptor, name);
1417 }
1418 
1419 IConnectableLayer* Network::AddSliceLayer(const SliceDescriptor& sliceDescriptor, const char* name)
1420 {
1421  return m_Graph->AddLayer<SliceLayer>(sliceDescriptor, name);
1422 }
1423 
1425  const char* name)
1426 {
1427  return m_Graph->AddLayer<SoftmaxLayer>(softmaxDescriptor, name);
1428 }
1429 
1431  const char* name)
1432 {
1433  return m_Graph->AddLayer<SplitterLayer>(splitterDescriptor, name);
1434 }
1435 
1437 {
1438  return m_Graph->AddLayer<MaximumLayer>(name);
1439 }
1440 
1442 {
1443  return m_Graph->AddLayer<MinimumLayer>(name);
1444 }
1445 
1447  const char* name)
1448 {
1449  return AddConcatLayer(mergerDescriptor, name);
1450 }
1451 
1453 {
1455 }
1456 
1458 {
1459  return m_Graph->AddLayer<AdditionLayer>(name);
1460 }
1461 
1463 {
1464  return m_Graph->AddLayer<MultiplicationLayer>(name);
1465 }
1466 
1468 {
1469  return m_Graph->AddLayer<OutputLayer>(id, name);
1470 }
1471 
1473  const ConstTensor& mean,
1474  const ConstTensor& variance,
1475  const ConstTensor& beta,
1476  const ConstTensor& gamma,
1477  const char* name)
1478 {
1479  const auto layer = m_Graph->AddLayer<BatchNormalizationLayer>(desc, name);
1480 
1481  layer->m_Mean = std::make_unique<ScopedCpuTensorHandle>(mean);
1482  layer->m_Variance = std::make_unique<ScopedCpuTensorHandle>(variance);
1483  layer->m_Beta = std::make_unique<ScopedCpuTensorHandle>(beta);
1484  layer->m_Gamma = std::make_unique<ScopedCpuTensorHandle>(gamma);
1485 
1486  return layer;
1487 }
1488 
1490 {
1491  return m_Graph->AddLayer<RankLayer>(name);
1492 }
1493 
1495  const char* name)
1496 {
1497  ResizeDescriptor resizeDescriptor;
1498  resizeDescriptor.m_Method = ResizeMethod::Bilinear;
1499  resizeDescriptor.m_DataLayout = descriptor.m_DataLayout;
1500  resizeDescriptor.m_TargetWidth = descriptor.m_TargetWidth;
1501  resizeDescriptor.m_TargetHeight = descriptor.m_TargetHeight;
1502  resizeDescriptor.m_AlignCorners = descriptor.m_AlignCorners;
1503  resizeDescriptor.m_HalfPixelCenters = descriptor.m_HalfPixelCenters;
1504 
1505  return m_Graph->AddLayer<ResizeLayer>(resizeDescriptor, name);
1506 }
1507 
1509 resizeDescriptor, const char* name)
1510 {
1511  return m_Graph->AddLayer<ResizeLayer>(resizeDescriptor, name);
1512 }
1513 
1515  const char* name)
1516 {
1517  return m_Graph->AddLayer<InstanceNormalizationLayer>(desc, name);
1518 }
1519 
1521  const char* name)
1522 {
1523  return m_Graph->AddLayer<L2NormalizationLayer>(desc, name);
1524 }
1525 
1527  const char* name)
1528 {
1529  return m_Graph->AddLayer<LogSoftmaxLayer>(desc, name);
1530 }
1531 
1533 {
1534  auto layer = m_Graph->AddLayer<ConstantLayer>(name);
1535 
1536  layer->m_LayerOutput = std::make_unique<ScopedCpuTensorHandle>(input);
1537 
1538  return layer;
1539 }
1540 
1542  const char* name)
1543 {
1544  return m_Graph->AddLayer<ReshapeLayer>(reshapeDescriptor, name);
1545 }
1546 
1548  const char* name)
1549 {
1550  return m_Graph->AddLayer<SpaceToBatchNdLayer>(spaceToBatchNdDescriptor, name);
1551 }
1552 
1554  const char* name)
1555 {
1556  return m_Graph->AddLayer<SpaceToDepthLayer>(spaceToDepthDescriptor, name);
1557 }
1558 
1560 {
1561  return m_Graph->AddLayer<FloorLayer>(name);
1562 }
1563 
1565  const LstmInputParams& params,
1566  const char* name)
1567 {
1568  const auto layer = m_Graph->AddLayer<LstmLayer>(descriptor, name);
1569 
1570  //Lstm Basic Parameters
1572  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputToForgetWeights));
1573  layer->m_BasicParameters.m_InputToCellWeights =
1574  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputToCellWeights));
1575  layer->m_BasicParameters.m_InputToOutputWeights =
1576  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputToOutputWeights));
1577  layer->m_BasicParameters.m_RecurrentToForgetWeights =
1578  std::make_unique<ScopedCpuTensorHandle>(*(params.m_RecurrentToForgetWeights));
1579  layer->m_BasicParameters.m_RecurrentToCellWeights =
1580  std::make_unique<ScopedCpuTensorHandle>(*(params.m_RecurrentToCellWeights));
1581  layer->m_BasicParameters.m_RecurrentToOutputWeights =
1582  std::make_unique<ScopedCpuTensorHandle>(*(params.m_RecurrentToOutputWeights));
1583  layer->m_BasicParameters.m_ForgetGateBias =
1584  std::make_unique<ScopedCpuTensorHandle>(*(params.m_ForgetGateBias));
1585  layer->m_BasicParameters.m_CellBias =
1586  std::make_unique<ScopedCpuTensorHandle>(*(params.m_CellBias));
1587  layer->m_BasicParameters.m_OutputGateBias =
1588  std::make_unique<ScopedCpuTensorHandle>(*(params.m_OutputGateBias));
1589 
1590  //Lstm Cifg parameters
1591  if(!descriptor.m_CifgEnabled)
1592  {
1593  if(params.m_InputToInputWeights == nullptr)
1594  {
1595  throw InvalidArgumentException("AddLstmLayer: Input To Input Weights cannot be NULL "
1596  "when CIFG is disabled.");
1597  }
1598  if(params.m_RecurrentToInputWeights == nullptr)
1599  {
1601  "AddLstmLayer: Recurrent To Input Weights cannot be NULL "
1602  "when CIFG is disabled.");
1603  }
1604  if(params.m_InputGateBias == nullptr)
1605  {
1606  throw InvalidArgumentException("AddLstmLayer: Input Gate Bias cannot be NULL "
1607  "when CIFG is disabled.");
1608  }
1609  layer->m_CifgParameters.m_InputToInputWeights =
1610  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputToInputWeights));
1611  layer->m_CifgParameters.m_RecurrentToInputWeights =
1612  std::make_unique<ScopedCpuTensorHandle>(*(params.m_RecurrentToInputWeights));
1613  layer->m_CifgParameters.m_InputGateBias =
1614  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputGateBias));
1615  }
1616 
1617  //Lstm projection parameters
1618  if(descriptor.m_ProjectionEnabled)
1619  {
1620  if(params.m_ProjectionWeights == nullptr)
1621  {
1622  throw InvalidArgumentException("AddLstmLayer: Projection Weights cannot be NULL "
1623  "when projection is enabled.");
1624  }
1625  layer->m_ProjectionParameters.m_ProjectionWeights =
1626  std::make_unique<ScopedCpuTensorHandle>(*(params.m_ProjectionWeights));
1627  if(params.m_ProjectionBias != nullptr)
1628  {
1629  layer->m_ProjectionParameters.m_ProjectionBias =
1630  std::make_unique<ScopedCpuTensorHandle>(*(params.m_ProjectionBias));
1631  }
1632  }
1633 
1634  //Lstm Peephole params
1635  if(descriptor.m_PeepholeEnabled)
1636  {
1637  if(!descriptor.m_CifgEnabled)
1638  {
1639  if(params.m_CellToInputWeights == nullptr)
1640  {
1641  throw InvalidArgumentException("AddLstmLayer: Cell To Input Weights cannot be NULL "
1642  "when Peephole is enabled and CIFG disabled.");
1643  }
1644 
1645  layer->m_PeepholeParameters.m_CellToInputWeights =
1646  std::make_unique<ScopedCpuTensorHandle>(*(params.m_CellToInputWeights));
1647  }
1648 
1649  if(params.m_CellToForgetWeights == nullptr)
1650  {
1651  throw InvalidArgumentException("AddLstmLayer: Cell To Forget Weights cannot be NULL "
1652  "when Peephole is enabled.");
1653  }
1654  if(params.m_CellToOutputWeights == nullptr)
1655  {
1656  throw InvalidArgumentException("AddLstmLayer: Cell To Output Weights cannot be NULL "
1657  "when Peephole is enabled.");
1658  }
1659 
1660  layer->m_PeepholeParameters.m_CellToForgetWeights =
1661  std::make_unique<ScopedCpuTensorHandle>(*(params.m_CellToForgetWeights));
1662  layer->m_PeepholeParameters.m_CellToOutputWeights =
1663  std::make_unique<ScopedCpuTensorHandle>(*(params.m_CellToOutputWeights));
1664  }
1665 
1666  //Lstm Layer Normalization params
1667  if(descriptor.m_LayerNormEnabled)
1668  {
1669  if(!descriptor.m_CifgEnabled)
1670  {
1671  if(params.m_InputLayerNormWeights == nullptr)
1672  {
1673  throw InvalidArgumentException("AddLstmLayer: Input layer normalization weights cannot be NULL "
1674  "when layer normalization is enabled and CIFG disabled.");
1675  }
1676  layer->m_LayerNormParameters.m_InputLayerNormWeights =
1677  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputLayerNormWeights));
1678  }
1679 
1680  if(params.m_ForgetLayerNormWeights == nullptr)
1681  {
1682  throw InvalidArgumentException("AddLstmLayer: Forget layer normalization weights cannot be NULL "
1683  "when layer normalization is enabled.");
1684  }
1685  if(params.m_CellLayerNormWeights == nullptr)
1686  {
1687  throw InvalidArgumentException("AddLstmLayer: Cell layer normalization weights cannot be NULL "
1688  "when layer normalization is enabled.");
1689  }
1690  if(params.m_OutputLayerNormWeights == nullptr)
1691  {
1692  throw InvalidArgumentException("AddLstmLayer: Output layer normalization weights cannot be NULL "
1693  "when layer normalization is enabled.");
1694  }
1695  layer->m_LayerNormParameters.m_ForgetLayerNormWeights =
1696  std::make_unique<ScopedCpuTensorHandle>(*(params.m_ForgetLayerNormWeights));
1697  layer->m_LayerNormParameters.m_CellLayerNormWeights =
1698  std::make_unique<ScopedCpuTensorHandle>(*(params.m_CellLayerNormWeights));
1699  layer->m_LayerNormParameters.m_OutputLayerNormWeights =
1700  std::make_unique<ScopedCpuTensorHandle>(*(params.m_OutputLayerNormWeights));
1701  }
1702  return layer;
1703 }
1704 
1706 {
1707  return m_Graph->AddLayer<DivisionLayer>(name);
1708 }
1709 
1711 {
1712  return m_Graph->AddLayer<SubtractionLayer>(name);
1713 }
1714 
1715 IConnectableLayer* Network::AddMeanLayer(const MeanDescriptor& meanDescriptor, const char* name)
1716 {
1717  return m_Graph->AddLayer<MeanLayer>(meanDescriptor,name);
1718 }
1719 
1720 IConnectableLayer* Network::AddPadLayer(const PadDescriptor& padDescriptor, const char* name)
1721 {
1722  return m_Graph->AddLayer<PadLayer>(padDescriptor,name);
1723 }
1724 
1726 {
1727  return m_Graph->AddLayer<QuantizeLayer>(name);
1728 }
1729 
1731 {
1732  return m_Graph->AddLayer<DequantizeLayer>(name);
1733 }
1734 
1736  const char* name)
1737 {
1738  return m_Graph->AddLayer<StridedSliceLayer>(stridedSliceDescriptor, name);
1739 }
1740 
1742 {
1744 }
1745 
1747 {
1749 }
1750 
1752 {
1754 }
1755 
1757 {
1758  GatherDescriptor gatherDescriptor{};
1759  return AddGatherLayer(gatherDescriptor, name);
1760 }
1761 
1763  const char* name)
1764 {
1765  return m_Graph->AddLayer<GatherLayer>(gatherDescriptor, name);
1766 }
1767 
1769 {
1770  return m_Graph->AddLayer<MergeLayer>(name);
1771 }
1772 
1774 {
1775  return m_Graph->AddLayer<SwitchLayer>(name);
1776 }
1777 
1779 {
1780  return m_Graph->AddLayer<PreluLayer>(name);
1781 }
1782 
1784  const ConstTensor& weights,
1785  const Optional<ConstTensor>& biases,
1786  const char* name)
1787 {
1788  if (descriptor.m_BiasEnabled && !biases.has_value())
1789  {
1790  throw InvalidArgumentException("AddTransposeConvolution2dLayer: Biases cannot be empty");
1791  }
1792 
1793  const auto layer = m_Graph->AddLayer<TransposeConvolution2dLayer>(descriptor, name);
1794 
1795  layer->m_Weight = std::make_unique<ScopedCpuTensorHandle>(weights);
1796 
1797  if (descriptor.m_BiasEnabled)
1798  {
1799  layer->m_Bias = std::make_unique<ScopedCpuTensorHandle>(biases.value());
1800  }
1801 
1802  return layer;
1803 }
1804 
1806  const char* name)
1807 {
1808  return m_Graph->AddLayer<TransposeLayer>(transposeDescriptor, name);
1809 }
1810 
1812  const char* name)
1813 {
1814  return m_Graph->AddLayer<StackLayer>(stackDescriptor, name);
1815 }
1816 
1817 
1819  const char* name)
1820 {
1821  return m_Graph->AddLayer<StandInLayer>(desc, name);
1822 }
1823 
1825  const char* name)
1826 {
1827  const auto layer = m_Graph->AddLayer<QuantizedLstmLayer>(name);
1828 
1829  // InputToX weights
1831  std::make_unique<ScopedCpuTensorHandle>(params.GetInputToInputWeights());
1832  layer->m_QuantizedLstmParameters.m_InputToForgetWeights =
1833  std::make_unique<ScopedCpuTensorHandle>(params.GetInputToForgetWeights());
1834  layer->m_QuantizedLstmParameters.m_InputToCellWeights =
1835  std::make_unique<ScopedCpuTensorHandle>(params.GetInputToCellWeights());
1836  layer->m_QuantizedLstmParameters.m_InputToOutputWeights =
1837  std::make_unique<ScopedCpuTensorHandle>(params.GetInputToOutputWeights());
1838 
1839  // RecurrentToX weights
1840  layer->m_QuantizedLstmParameters.m_RecurrentToInputWeights =
1841  std::make_unique<ScopedCpuTensorHandle>(params.GetRecurrentToInputWeights());
1842  layer->m_QuantizedLstmParameters.m_RecurrentToForgetWeights =
1843  std::make_unique<ScopedCpuTensorHandle>(params.GetRecurrentToForgetWeights());
1844  layer->m_QuantizedLstmParameters.m_RecurrentToCellWeights =
1845  std::make_unique<ScopedCpuTensorHandle>(params.GetRecurrentToCellWeights());
1846  layer->m_QuantizedLstmParameters.m_RecurrentToOutputWeights =
1847  std::make_unique<ScopedCpuTensorHandle>(params.GetRecurrentToOutputWeights());
1848 
1849  // Bias
1850  layer->m_QuantizedLstmParameters.m_InputGateBias =
1851  std::make_unique<ScopedCpuTensorHandle>(params.GetInputGateBias());
1852  layer->m_QuantizedLstmParameters.m_ForgetGateBias =
1853  std::make_unique<ScopedCpuTensorHandle>(params.GetForgetGateBias());
1854  layer->m_QuantizedLstmParameters.m_CellBias =
1855  std::make_unique<ScopedCpuTensorHandle>(params.GetCellBias());
1856  layer->m_QuantizedLstmParameters.m_OutputGateBias =
1857  std::make_unique<ScopedCpuTensorHandle>(params.GetOutputGateBias());
1858 
1859  return layer;
1860 }
1861 
1863  const LstmInputParams& params,
1864  const char* name)
1865 {
1866  const auto layer = m_Graph->AddLayer<QLstmLayer>(descriptor, name);
1867 
1868  // QLstm Basic Parameters
1870  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputToForgetWeights));
1871  layer->m_BasicParameters.m_InputToCellWeights =
1872  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputToCellWeights));
1873  layer->m_BasicParameters.m_InputToOutputWeights =
1874  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputToOutputWeights));
1875  layer->m_BasicParameters.m_RecurrentToForgetWeights =
1876  std::make_unique<ScopedCpuTensorHandle>(*(params.m_RecurrentToForgetWeights));
1877  layer->m_BasicParameters.m_RecurrentToCellWeights =
1878  std::make_unique<ScopedCpuTensorHandle>(*(params.m_RecurrentToCellWeights));
1879  layer->m_BasicParameters.m_RecurrentToOutputWeights =
1880  std::make_unique<ScopedCpuTensorHandle>(*(params.m_RecurrentToOutputWeights));
1881  layer->m_BasicParameters.m_ForgetGateBias =
1882  std::make_unique<ScopedCpuTensorHandle>(*(params.m_ForgetGateBias));
1883  layer->m_BasicParameters.m_CellBias =
1884  std::make_unique<ScopedCpuTensorHandle>(*(params.m_CellBias));
1885  layer->m_BasicParameters.m_OutputGateBias =
1886  std::make_unique<ScopedCpuTensorHandle>(*(params.m_OutputGateBias));
1887 
1888  // QLstm Cifg parameters
1889  if(!descriptor.m_CifgEnabled)
1890  {
1891  if(params.m_InputToInputWeights == nullptr)
1892  {
1893  throw InvalidArgumentException("AddQLstmLayer: Input To Input Weights cannot be NULL");
1894  }
1895 
1896  if(params.m_RecurrentToInputWeights == nullptr)
1897  {
1899  "AddQLstmLayer: Recurrent To Input Weights cannot be NULL");
1900  }
1901 
1902  if(params.m_InputGateBias == nullptr)
1903  {
1904  throw InvalidArgumentException("AddQLstmLayer: Input Gate Bias cannot be NULL");
1905  }
1906 
1907  layer->m_CifgParameters.m_InputToInputWeights =
1908  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputToInputWeights));
1909  layer->m_CifgParameters.m_RecurrentToInputWeights =
1910  std::make_unique<ScopedCpuTensorHandle>(*(params.m_RecurrentToInputWeights));
1911  layer->m_CifgParameters.m_InputGateBias =
1912  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputGateBias));
1913  }
1914 
1915  // QLstm Projection parameters
1916  if(descriptor.m_ProjectionEnabled)
1917  {
1918  if(params.m_ProjectionWeights == nullptr)
1919  {
1920  throw InvalidArgumentException("AddQLstmLayer: Projection Weights cannot be NULL");
1921  }
1922 
1923  layer->m_ProjectionParameters.m_ProjectionWeights =
1924  std::make_unique<ScopedCpuTensorHandle>(*(params.m_ProjectionWeights));
1925 
1926  // Projection bias is optional even if projection is enabled
1927  if(params.m_ProjectionWeights != nullptr)
1928  {
1929  layer->m_ProjectionParameters.m_ProjectionBias =
1930  std::make_unique<ScopedCpuTensorHandle>(*(params.m_ProjectionBias));
1931  }
1932 
1933  }
1934 
1935  // QLstm Peephole params
1936  if(descriptor.m_PeepholeEnabled)
1937  {
1938  if(params.m_CellToForgetWeights == nullptr)
1939  {
1940  throw InvalidArgumentException("AddQLstmLayer: Cell To Forget Weights cannot be NULL");
1941  }
1942 
1943  if(params.m_CellToOutputWeights == nullptr)
1944  {
1945  throw InvalidArgumentException("AddQLstmLayer: Cell To Output Weights cannot be NULL");
1946  }
1947 
1948  if(!descriptor.m_CifgEnabled)
1949  {
1950  if(params.m_CellToInputWeights == nullptr)
1951  {
1952  throw InvalidArgumentException("AddQLstmLayer: Cell To Input Weights cannot be NULL");
1953  }
1954 
1955  layer->m_PeepholeParameters.m_CellToInputWeights =
1956  std::make_unique<ScopedCpuTensorHandle>(*(params.m_CellToInputWeights));
1957  }
1958 
1959  layer->m_PeepholeParameters.m_CellToForgetWeights =
1960  std::make_unique<ScopedCpuTensorHandle>(*(params.m_CellToForgetWeights));
1961  layer->m_PeepholeParameters.m_CellToOutputWeights =
1962  std::make_unique<ScopedCpuTensorHandle>(*(params.m_CellToOutputWeights));
1963  }
1964 
1965  // QLstm Layer Normalization params
1966  if(descriptor.m_LayerNormEnabled)
1967  {
1968  if(params.m_ForgetLayerNormWeights == nullptr)
1969  {
1970  throw InvalidArgumentException("AddQLstmLayer: Forget layer normalization weights cannot be NULL");
1971  }
1972 
1973  if(params.m_CellLayerNormWeights == nullptr)
1974  {
1975  throw InvalidArgumentException("AddQLstmLayer: Cell layer normalization weights cannot be NULL");
1976  }
1977 
1978  if(params.m_OutputLayerNormWeights == nullptr)
1979  {
1980  throw InvalidArgumentException("AddQLstmLayer: Output layer normalization weights cannot be NULL");
1981  }
1982 
1983  if(!descriptor.m_CifgEnabled)
1984  {
1985  if(params.m_InputLayerNormWeights == nullptr)
1986  {
1987  throw InvalidArgumentException("AddQLstmLayer: Input layer normalization weights cannot be NULL");
1988  }
1989 
1990  layer->m_LayerNormParameters.m_InputLayerNormWeights =
1991  std::make_unique<ScopedCpuTensorHandle>(*(params.m_InputLayerNormWeights));
1992  }
1993 
1994  layer->m_LayerNormParameters.m_ForgetLayerNormWeights =
1995  std::make_unique<ScopedCpuTensorHandle>(*(params.m_ForgetLayerNormWeights));
1996  layer->m_LayerNormParameters.m_CellLayerNormWeights =
1997  std::make_unique<ScopedCpuTensorHandle>(*(params.m_CellLayerNormWeights));
1998  layer->m_LayerNormParameters.m_OutputLayerNormWeights =
1999  std::make_unique<ScopedCpuTensorHandle>(*(params.m_OutputLayerNormWeights));
2000  }
2001  return layer;
2002 }
2003 
2005  const char* name)
2006 {
2007  return m_Graph->AddLayer<LogicalBinaryLayer>(logicalBinaryDescriptor, name);
2008 }
2009 
2010 void Network::Accept(ILayerVisitor& visitor) const
2011 {
2012  for (auto layer : GetGraph())
2013  {
2014  layer->Accept(visitor);
2015  };
2016 }
2017 
2018 OptimizedNetwork::OptimizedNetwork(std::unique_ptr<Graph> graph)
2019  : m_Graph(std::move(graph)), m_Guid(profiling::ProfilingService::GetNextGuid())
2020 {
2021 }
2022 
2023 OptimizedNetwork::OptimizedNetwork(std::unique_ptr<Graph> graph, const ModelOptions& modelOptions)
2024  : m_Graph(std::move(graph)), m_Guid(profiling::ProfilingService::GetNextGuid()), m_ModelOptions(modelOptions)
2025 {
2026 }
2027 
2029 {
2030 }
2031 
2032 } // namespace armnn
A layer that the constant data can be bound to.
OptimizeForConnection< Layer, PermuteLayer, SquashEqualSiblingsImpl< PermuteLayer > > SquashEqualPermuteSiblings
void ReportError(const std::string &errorMessage, Optional< std::vector< std::string > &> errorMessages)
Definition: Network.cpp:72
bool m_BiasEnabled
Enable/disable bias.
ModelOptions m_ModelOptions
Definition: INetwork.hpp:674
bool m_HalfPixelCenters
Half Pixel Centers.
IConnectableLayer * AddPooling2dLayer(const Pooling2dDescriptor &pooling2dDescriptor, const char *name=nullptr) override
Adds a pooling layer to the network.
Definition: Network.cpp:1394
bool m_AlignCorners
Aligned corners.
This layer represents a minimum operation.
static const FactoryId DeferredFactoryId
Use the workload factory to create the tensor handle.
This layer represents a split operation.
LstmBasicParameters m_BasicParameters
Definition: LstmLayer.hpp:81
const ConstTensor * m_ProjectionWeights
Definition: LstmParams.hpp:55
const std::vector< InputSlot * > & GetConnections() const
Definition: Layer.hpp:125
const ConstTensor & GetRecurrentToOutputWeights() const
FactoryFunction GetFactory(const BackendId &id) const
This layer represents a batch normalization operation.
static void Destroy(INetwork *network)
Definition: Network.cpp:51
A ViewsDescriptor for the SplitterLayer.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:61
OptimizeForConnection< PermuteLayer, PermuteLayer, OptimizeInversePermutesImpl< PermuteLayer > > OptimizeInversePermutes
virtual bool SupportsMapUnmap() const final
const ConstTensor * m_CellBias
Definition: LstmParams.hpp:53
std::vector< ConvertFp32ToFp16Layer * > InsertConvertFp32ToFp16LayersAfter(Graph &graph, Layer &layer)
bool m_BiasEnabled
Enable/disable bias.
IConnectableLayer * AddOutputLayer(LayerBindingId id, const char *name=nullptr) override
Adds an output layer to the network.
Definition: Network.cpp:1467
IConnectableLayer * AddRankLayer(const char *name=nullptr) override
Adds a rank layer to the network.
Definition: Network.cpp:1489
void SetEdgeStrategy(unsigned int connectionIndex, EdgeStrategy strategy)
Definition: Layer.cpp:181
QuantizedLstmParameters m_QuantizedLstmParameters
This layer represents a 2D transpose convolution operation.
No strategy has been defined. Used internally to verify integrity of optimizations.
std::vector< ConvertFp16ToFp32Layer * > InsertConvertFp16ToFp32LayersBefore(Graph &graph, Layer &layer, bool expectCorrectInputType)
IConnectableLayer * AddL2NormalizationLayer(const L2NormalizationDescriptor &desc, const char *name=nullptr) override
Adds an L2 normalization layer to the network.
Definition: Network.cpp:1520
A TransposeConvolution2dDescriptor for the TransposeConvolution2dLayer.
const TensorShape & GetShape() const
Definition: Tensor.hpp:187
CPU Execution: Reference C++ kernels.
Optimizer::Optimizations MakeOptimizations(Args &&... args)
Definition: Optimizer.hpp:43
std::unique_ptr< ScopedCpuTensorHandle > m_Weight
A unique pointer to store Weight values.
IConnectableLayer * AddResizeBilinearLayer(const ResizeBilinearDescriptor &resizeDesc, const char *name=nullptr) override
Adds a resize bilinear layer to the network.
Definition: Network.cpp:1494
IConnectableLayer * AddFillLayer(const FillDescriptor &fillDescriptor, const char *name=nullptr) override
Add an Fill layer to the network.
Definition: Network.cpp:1215
IConnectableLayer * AddMeanLayer(const MeanDescriptor &meanDescriptor, const char *name=nullptr) override
Add a Mean layer to the network.
Definition: Network.cpp:1715
A ReshapeDescriptor for the ReshapeLayer.
ITensorHandleFactory::FactoryId CalculateSlotOption(BackendsMap &backends, OutputSlot &outputSlot, TensorHandleFactoryRegistry &registry)
Definition: Network.cpp:748
OptimizeForConnection< TransposeLayer, TransposeLayer, OptimizeInversePermutesImpl< TransposeLayer > > OptimizeInverseTransposes
const ConstTensor & GetRecurrentToForgetWeights() const
OptimizeForConnection< TransposeLayer, BatchToSpaceNdLayer, PermuteAndBatchToSpaceAsDepthToSpaceImpl< TransposeLayer > > TransposeAndBatchToSpaceAsDepthToSpace
const ConstTensor * m_CellToOutputWeights
Definition: LstmParams.hpp:50
OptimizeForExclusiveConnection< DepthwiseConvolution2dLayer, BatchNormalizationLayer, FuseBatchNorm< DepthwiseConvolution2dLayer, armnn::DataType::Float32 > > FuseBatchNormIntoDepthwiseConvolution2DFloat32
#define ARMNN_NO_DEPRECATE_WARN_BEGIN
Definition: Deprecated.hpp:33
ITensorHandleFactory::FactoryId CalculateSlotOptionForOutput(BackendsMap &backends, OutputSlot &slot, TensorHandleFactoryRegistry &registry)
Definition: Network.cpp:738
A ComparisonDescriptor for the ComparisonLayer.
Definition: Descriptors.hpp:73
This layer represents a depthwise convolution 2d operation.
static void ConvertBFloat16ToFloat32(const void *srcBFloat16Buffer, size_t numElements, float *dstFloat32Buffer)
bool RequiresCopy(ITensorHandleFactory::FactoryId src, ITensorHandleFactory::FactoryId dst, TensorHandleFactoryRegistry &registry)
Definition: Network.cpp:636
uint32_t m_TargetWidth
Target width value.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
std::vector< BackendOptions > ModelOptions
IConnectableLayer * AddLogSoftmaxLayer(const LogSoftmaxDescriptor &logSoftmaxDescriptor, const char *name=nullptr) override
Adds a log softmax layer to the network.
Definition: Network.cpp:1526
const ConstTensor & GetCellBias() const
A Convolution2dDescriptor for the Convolution2dLayer.
Layer & GetOwningLayer() const
Definition: Layer.hpp:115
Source backends tensor data can be exported to destination backend tensor without copy...
IConnectableLayer * AddDepthwiseConvolution2dLayer(const DepthwiseConvolution2dDescriptor &convolution2dDescriptor, const ConstTensor &weights, const Optional< ConstTensor > &biases, const char *name=nullptr) override
Adds a 2D depthwise convolution layer to the network.
Definition: Network.cpp:1350
This layer converts data type Float 16 to Float 32.
bool m_BiasEnabled
Enable/disable bias.
const ConstTensor * m_CellToInputWeights
Definition: LstmParams.hpp:48
const Graph & GetGraph() const
Definition: Network.hpp:34
IConnectableLayer * AddSwitchLayer(const char *name=nullptr) override
Adds a switch layer to the network.
Definition: Network.cpp:1773
ResizeMethod m_Method
The Interpolation method to use (Bilinear, NearestNeighbor).
IConnectableLayer * AddFloorLayer(const char *name=nullptr) override
Adds a floor layer to the network.
Definition: Network.cpp:1559
static void Pass(Graph &graph, const Optimizations &optimizations)
Definition: Optimizer.cpp:16
OptimizeForExclusiveConnection< DepthwiseConvolution2dLayer, BatchNormalizationLayer, FuseBatchNorm< DepthwiseConvolution2dLayer, armnn::DataType::Float16 > > FuseBatchNormIntoDepthwiseConvolution2DFloat16
const ConstTensor * m_InputGateBias
Definition: LstmParams.hpp:51
This layer represents a SpaceToDepth operation.
IConnectableLayer * AddInputLayer(LayerBindingId id, const char *name=nullptr) override
Adds an input layer to the network.
Definition: Network.cpp:1192
This layer represents a reshape operation.
std::unique_ptr< ScopedCpuTensorHandle > m_InputToInputWeights
A unique pointer to represent 2D weights tensor with dimensions [outputSize, inputSize] (QAsymm8)...
OptimizeForExclusiveConnection< Convolution2dLayer, BatchNormalizationLayer, FuseBatchNorm< Convolution2dLayer, armnn::DataType::Float16 > > FuseBatchNormIntoConvolution2DFloat16
OptimizeForExclusiveConnection< Convolution2dLayer, BatchNormalizationLayer, FuseBatchNorm< Convolution2dLayer, armnn::DataType::Float32 > > FuseBatchNormIntoConvolution2DFloat32
#define ARMNN_LOG(severity)
Definition: Logging.hpp:163
std::unique_ptr< ScopedCpuTensorHandle > m_InputToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [num_units, inputSize] (QSymmS8)...
Definition: QLstmLayer.hpp:17
Main network class which provides the interface for building up a neural network. ...
Definition: INetwork.hpp:105
This layer represents an activation operation with the specified activation function.
BackendRegistry & BackendRegistryInstance()
This layer converts data type BFloat16 to Float32.
const ConstTensor * m_RecurrentToCellWeights
Definition: LstmParams.hpp:46
LayerT * ConvertBf16ToFp32Weight(Layer *l)
Definition: Network.cpp:147
std::vector< BackendOptions > NetworkOptions
void Accept(ILayerVisitor &visitor) const override
Definition: Network.cpp:2010
A LogicalBinaryDescriptor for the LogicalBinaryLayer.
IConnectableLayer * AddMinimumLayer(const char *name=nullptr) override
Add a Minimum layer to the network.
Definition: Network.cpp:1441
This layer represents an unknown operation in the input graph.
OptimizeForConnection< Layer, ReshapeLayer, SquashEqualSiblingsImpl< ReshapeLayer > > SquashEqualReshapeSiblings
This layer represents a detection postprocess operator.
BackendIdSet m_SupportedBackends
const ConstTensor * m_ForgetLayerNormWeights
Definition: LstmParams.hpp:58
OptimizeForConnection< Layer, TransposeLayer, MoveTransposeUpImpl > MoveTransposeUp
const ConstTensor * m_CellToForgetWeights
Definition: LstmParams.hpp:49
OptimizationResult ReturnWithError(OptimizationResult res, const Layer *layer, const BackendSettings &backendSettings, Optional< std::vector< std::string > &> errMessages)
Definition: Network.cpp:96
std::unique_ptr< ScopedCpuTensorHandle > m_Weight
A unique pointer to store weight values.
Copyright (c) 2020 ARM Limited.
IConnectableLayer * AddQLstmLayer(const QLstmDescriptor &descriptor, const LstmInputParams &params, const char *name=nullptr) override
Add a QLstm layer to the network.
Definition: Network.cpp:1862
This layer represents a pad operation.
Definition: PadLayer.hpp:14
This layer represents a LSTM operation.
Definition: LstmLayer.hpp:77
void IgnoreUnused(Ts &&...)
OptimizeForConnection< PadLayer, Convolution2dLayer, FoldPadIntoConvolution2dImpl > FoldPadIntoConvolution2d
void SetBackendId(const BackendId &id)
Definition: Layer.hpp:267
bool IsBackendSupported(const BackendId &backend) const
LayerList::const_iterator Iterator
Definition: Graph.hpp:50
IConnectableLayer * AddFullyConnectedLayer(const FullyConnectedDescriptor &fullyConnectedDescriptor, const ConstTensor &weights, const Optional< ConstTensor > &biases, const char *name=nullptr) override
Adds a fully connected layer to the network.
Definition: Network.cpp:1243
A SpaceToDepthDescriptor for the SpaceToDepthLayer.
This layer represents a permutation operation.
const ConstTensor & GetInputToOutputWeights() const
unsigned int GetNumOutputSlots() const override
Returns the number of connectable output slots.
Definition: Layer.hpp:311
This layer represents a SpaceToBatchNd operation.
IConnectableLayer * AddRsqrtLayer(const char *name=nullptr) override
Add Reciprocal of square root layer to the network.
Definition: Network.cpp:1751
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
OptimizeForType< Layer, AddDebugImpl > InsertDebugLayer
Definition: AddDebug.hpp:34
OptimizeForConnection< ReshapeLayer, ReshapeLayer, OptimizeConsecutiveReshapesImpl > OptimizeConsecutiveReshapes
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
Definition: Types.hpp:202
const ConstTensor * m_OutputGateBias
Definition: LstmParams.hpp:54
This layer represents a elementwiseUnary operation.
constexpr const char * GetDataTypeName(DataType dataType)
Definition: TypesUtils.hpp:180
A ResizeDescriptor for the ResizeLayer.
IConnectableLayer * AddEqualLayer(const char *name=nullptr) override
Add a Equal layer to the network.
Definition: Network.cpp:1746
IConnectableLayer * AddConvolution2dLayer(const Convolution2dDescriptor &convolution2dDescriptor, const ConstTensor &weights, const Optional< ConstTensor > &biases, const char *name=nullptr) override
Adds a 2D convolution layer to the network.
Definition: Network.cpp:1296
A StackDescriptor for the StackLayer.
IConnectableLayer * AddTransposeConvolution2dLayer(const TransposeConvolution2dDescriptor &descriptor, const ConstTensor &weights, const Optional< ConstTensor > &biases, const char *name=nullptr) override
Adds a 2D transpose convolution layer to the network.
Definition: Network.cpp:1783
Destination backend can work directly with tensors on source backend.
virtual std::vector< ITensorHandleFactory::FactoryId > GetHandleFactoryPreferences() const
(Optional) Returns a vector of supported TensorHandleFactory ids in preference order.
OptimizeForConnection< ConvertFp16ToFp32Layer, ConvertFp32ToFp16Layer, OptimizeInverseConversionsImpl > OptimizeInverseConversionsFp16
The SubgraphView class represents a subgraph of a Graph.
A PadDescriptor for the PadLayer.
This layer represents an instance normalization operation.
OptimizeForConnection< PermuteLayer, BatchToSpaceNdLayer, PermuteAndBatchToSpaceAsDepthToSpaceImpl< PermuteLayer > > PermuteAndBatchToSpaceAsDepthToSpace
const ConstTensor * m_InputLayerNormWeights
Definition: LstmParams.hpp:57
OptimizeForConnection< Layer, PermuteLayer, MovePermuteUpImpl > MovePermuteUp
This layer represents a Logical Binary operation.
std::unique_ptr< ScopedCpuTensorHandle > m_LayerOutput
const ConstTensor & GetInputToCellWeights() const
IConnectableLayer * AddReshapeLayer(const ReshapeDescriptor &reshapeDescriptor, const char *name=nullptr) override
Adds a reshape layer to the network.
Definition: Network.cpp:1541
IConnectableLayer * AddTransposeLayer(const TransposeDescriptor &transposeDescriptor, const char *name=nullptr) override
Adds a transpose layer to the network.
Definition: Network.cpp:1805
A layer user-provided data can be bound to (e.g. inputs, outputs).
Definition: OutputLayer.hpp:13
void ForEachLayer(Func func) const
Definition: Graph.hpp:39
virtual std::vector< Capability > GetCapabilities(const IConnectableLayer *layer, const IConnectableLayer *connectedLayer, CapabilityClass capabilityClass)
Status PrintGraph() override
Definition: Network.cpp:61
IConnectableLayer * AddMergeLayer(const char *name=nullptr) override
Adds a merge layer to the network.
Definition: Network.cpp:1768
This layer dequantizes the input tensor.
ConvertConstants< Float32ToFloat16, IsFloat16Layer > ConvertConstantsFloatToHalf
DataType
Definition: Types.hpp:32
OptimizeForType< TransposeLayer, TransposeAsReshapeImpl > TransposeAsReshape
IConnectableLayer * AddMaximumLayer(const char *name=nullptr) override
Add a Maximum layer to the network.
Definition: Network.cpp:1436
This layer represents a Gather operator.
Definition: GatherLayer.hpp:14
const ConstTensor * m_RecurrentToOutputWeights
Definition: LstmParams.hpp:47
std::unique_ptr< ScopedCpuTensorHandle > m_Anchors
A unique pointer to store Anchor values.
This layer represents a fully connected operation.
An LstmDescriptor for the LstmLayer.
#define ARMNN_NO_DEPRECATE_WARN_END
Definition: Deprecated.hpp:34
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:1011
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
This layer represents a QuantizedLstm operation.
char const * GetLayerTypeAsCString(LayerType type)
This layer represents a log softmax operation.
std::unique_ptr< ScopedCpuTensorHandle > m_Mean
A unique pointer to store Mean values.
A L2NormalizationDescriptor for the L2NormalizationLayer.
const ConstTensor * m_ProjectionBias
Definition: LstmParams.hpp:56
int32_t GetQuantizationOffset() const
Definition: Tensor.cpp:469
An ArgMinMaxDescriptor for ArgMinMaxLayer.
Definition: Descriptors.hpp:51
float GetQuantizationScale() const
Definition: Tensor.cpp:452
DataType GetDataType() const
Definition: Tensor.hpp:194
An OriginsDescriptor for the ConcatLayer.
bool has_value() const noexcept
Definition: Optional.hpp:53
A FullyConnectedDescriptor for the FullyConnectedLayer.
std::unique_ptr< ScopedCpuTensorHandle > m_Weight
A unique pointer to store Weight values.
bool m_BiasEnabled
Enable/disable bias.
This layer represents a stack operation.
Definition: StackLayer.hpp:13
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:314
IConnectableLayer * AddConcatLayer(const ConcatDescriptor &concatDescriptor, const char *name=nullptr) override
Adds a concatenation layer to the network.
Definition: Network.cpp:1268
const Subgraphs & GetFailedSubgraphs() const
This layer represents a merge operation.
Definition: ConcatLayer.hpp:13
This layer represents a softmax operation.
const std::string & GetNameStr() const
Definition: Layer.hpp:217
uint32_t m_TargetWidth
Target width value.
std::vector< ConvertBf16ToFp32Layer * > InsertConvertBf16ToFp32LayersBefore(Graph &graph, Layer &layer, bool expectCorrectInputType)
A GatherDescriptor for the GatherLayer.
const ConstTensor & GetInputToInputWeights() const
Status
enumeration
Definition: Types.hpp:26
This layer represents a BatchToSpaceNd operation.
std::vector< SubgraphViewPtr > Subgraphs
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
Definition: INetwork.hpp:600
bool m_HalfPixelCenters
Half Pixel Centers.
IConnectableLayer * AddPadLayer(const PadDescriptor &padDescriptor, const char *name=nullptr) override
Adds a fully pad layer to the network.
Definition: Network.cpp:1720
IConnectableLayer * AddStandInLayer(const StandInDescriptor &descriptor, const char *name=nullptr) override
Add a stand-in layer for a type unknown to the Arm NN framework.
Definition: Network.cpp:1818
void SetQuantizationScale(float scale)
Definition: Tensor.cpp:464
This layer represents a ArgMinMax operation.
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
A StandInDescriptor for the StandIn layer.
A QLstmDescriptor for the QLstmLayer.
IConnectableLayer * AddActivationLayer(const ActivationDescriptor &activationDescriptor, const char *name=nullptr) override
Adds an activation layer to the network.
Definition: Network.cpp:1400
BackendIdVector GetAvailablePreferredBackends() const
IConnectableLayer * AddSubtractionLayer(const char *name=nullptr) override
Adds a subtraction layer to the network.
Definition: Network.cpp:1710
IConnectableLayer * AddInstanceNormalizationLayer(const InstanceNormalizationDescriptor &desc, const char *name=nullptr) override
Adds an instance normalization layer to the network.
Definition: Network.cpp:1514
Device specific knowledge to be passed to the optimizer.
Definition: Types.hpp:192
static bool IsLayerSupported(const BackendId &backendId, const IConnectableLayer &layer, Optional< DataType > dataType, std::string &outReasonIfUnsupported)
IConnectableLayer * AddDepthToSpaceLayer(const DepthToSpaceDescriptor &depthToSpaceDescriptor, const char *name=nullptr) override
Adds a depth to space layer to the network.
Definition: Network.cpp:1344
bool Validate(const SubgraphView &originalSubgraph) const
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:20
std::vector< ConvertFp32ToBf16Layer * > InsertConvertFp32ToBf16LayersAfter(Graph &graph, Layer &layer)
const BackendId & GetBackendId() const
Definition: Layer.hpp:266
uint32_t m_TargetHeight
Target height value.
IConnectableLayer * AddStackLayer(const StackDescriptor &stackDescriptor, const char *name=nullptr) override
Adds a stack layer to the network.
Definition: Network.cpp:1811
This layer represents a floor operation.
Definition: FloorLayer.hpp:13
uint32_t m_TargetHeight
Target height value.
A SliceDescriptor for the SliceLayer.
This layer represents a normalization operation.
virtual MemorySourceFlags GetExportFlags() const
const ConstTensor & GetForgetGateBias() const
This layer represents a pooling 2d operation.
This layer converts data type Float 32 to Float 16.
OptimizedNetwork(std::unique_ptr< Graph > graph)
Definition: Network.cpp:2018
This layer represents a transpose operation.
IConnectableLayer * AddSplitterLayer(const ViewsDescriptor &splitterDescriptor, const char *name=nullptr) override
Adds a splitter layer to the network.
Definition: Network.cpp:1430
This layer represents an addition operation.
QLstmBasicParameters m_BasicParameters
Definition: QLstmLayer.hpp:83
void SubstituteSubgraph(SubgraphView &subgraph, IConnectableLayer *substituteLayer)
Substitutes the given sub-graph with either a new layer or a new sub-graph.
Definition: Graph.cpp:432
Status PrintGraph() override
Definition: Network.cpp:1186
IConnectableLayer * AddSpaceToDepthLayer(const SpaceToDepthDescriptor &spaceToDepthDescriptor, const char *name=nullptr) override
Adds a space to depth layer to the network.
Definition: Network.cpp:1553
bool CheckScaleSetOnQuantizedType(Layer *layer, Optional< std::vector< std::string > &> errMessages)
Definition: Network.cpp:111
Private implementation of INetwork.
Definition: Network.hpp:28
const ConstTensor * m_CellLayerNormWeights
Definition: LstmParams.hpp:59
void SetTensorHandleFactory(const ITensorHandleFactory::FactoryId &id)
Definition: Layer.cpp:171
const ConstTensor * m_ForgetGateBias
Definition: LstmParams.hpp:52
A SpaceToBatchNdDescriptor for the SpaceToBatchNdLayer.
const ConstTensor * m_InputToCellWeights
Definition: LstmParams.hpp:42
IConnectableLayer * AddPreluLayer(const char *name=nullptr) override
Adds a PReLU layer to the network.
Definition: Network.cpp:1778
OptimizeForType< PermuteLayer, PermuteAsReshapeImpl > PermuteAsReshape
bool IsWarningOnly() const
Definition: Network.hpp:320
const ConstTensor * m_InputToOutputWeights
Definition: LstmParams.hpp:43
OptimizeForConnection< Layer, TransposeLayer, SquashEqualSiblingsImpl< TransposeLayer > > SquashEqualTransposeSiblings
This layer represents a QLstm operation.
Definition: QLstmLayer.hpp:79
IConnectableLayer * AddQuantizeLayer(const char *name=nullptr) override
Add a quantize layer to the network.
Definition: Network.cpp:1725
const ConstTensor & GetInputGateBias() const
const Substitutions & GetSubstitutions() const
IConnectableLayer * AddArgMinMaxLayer(const ArgMinMaxDescriptor &desc, const char *name=nullptr) override
Adds an ArgMinMax layer to the network.
Definition: Network.cpp:1406
BackendIdVector m_PreferredBackends
OptimizationResult AssignBackends(OptimizedNetwork *optNetObjPtr, BackendSettings &backendSettings, Graph::Iterator &firstLayer, Graph::Iterator &lastLayer, Optional< std::vector< std::string > &> errMessages)
Definition: Network.cpp:378
This layer represents a subtraction operation.
This layer calculates both true and false outputs for input.
Definition: SwitchLayer.hpp:13
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
Definition: Optional.hpp:32
ConvertConstants< Float16ToFloat32, IsFloat32Layer > ConvertConstantsHalfToFloat
bool m_AlignCorners
Aligned corners.
A ElementwiseUnaryDescriptor for the ElementwiseUnaryLayer.
Definition: Descriptors.hpp:93
IConnectableLayer * AddBatchNormalizationLayer(const BatchNormalizationDescriptor &desc, const ConstTensor &mean, const ConstTensor &variance, const ConstTensor &beta, const ConstTensor &gamma, const char *name=nullptr) override
Adds a batch normalization layer to the network.
Definition: Network.cpp:1472
const ConstTensor * m_RecurrentToForgetWeights
Definition: LstmParams.hpp:45
static Subgraphs SelectSubgraphs(Graph &graph, const LayerSelectorFunction &selector)
Selects subgraphs from a graph based on the selector function and the algorithm.
IConnectableLayer * AddBatchToSpaceNdLayer(const BatchToSpaceNdDescriptor &batchToSpaceNdDescriptor, const char *name=nullptr) override
Adds a batch to space ND layer to the network.
Definition: Network.cpp:1197
This layer represents a L2 normalization operation.
BackendsMap CreateSupportedBackends(TensorHandleFactoryRegistry &handleFactoryRegistry, BackendSettings &backendSettings)
Definition: Network.cpp:518
OptimizeForConnection< ConvertFp32ToFp16Layer, ConvertFp16ToFp32Layer, OptimizeInverseConversionsImpl > OptimizeInverseConversionsFp32
ITensorHandleFactory::FactoryId CalculateSlotOptionForInput(BackendsMap &backends, OutputSlot &slot, TensorHandleFactoryRegistry &registry)
Definition: Network.cpp:656
const std::string & Get() const
Definition: BackendId.hpp:136
Status SerializeToDot(std::ostream &stream) const override
Definition: Network.cpp:67
IConnectableLayer * AddAdditionLayer(const char *name=nullptr) override
Adds an addition layer to the network.
Definition: Network.cpp:1457
BackendIdSet m_SelectedBackends
IConnectableLayer * AddDequantizeLayer(const char *name=nullptr) override
Adds a Dequantize layer to the network.
Definition: Network.cpp:1730
A layer user-provided data can be bound to (e.g. inputs, outputs).
Definition: InputLayer.hpp:13
const ConstTensor & GetRecurrentToCellWeights() const
IConnectableLayer * AddSpaceToBatchNdLayer(const SpaceToBatchNdDescriptor &spaceToBatchNdDescriptor, const char *name=nullptr) override
Adds a space to batch layer to the network.
Definition: Network.cpp:1547
OptimizationResult AttemptBackendAssignment(BackendSettings &backendSettings, Graph &graph, Layer *layer, BackendId backend, DataType dataTypeIn, DataType dataTypeOut, const std::vector< BackendId > &availablePreferredBackends, std::string &reasonIfUnsupported, Optional< std::vector< std::string > &> errMessages)
Definition: Network.cpp:170
const ConstTensor & GetInputToForgetWeights() const
ITensorHandleFactory * GetFactory(ITensorHandleFactory::FactoryId id) const
Find a TensorHandleFactory by Id Returns nullptr if not found.
IConnectableLayer * AddLogicalBinaryLayer(const LogicalBinaryDescriptor &logicalBinaryDescriptor, const char *name=nullptr) override
Adds a Logical Binary layer to the network.
Definition: Network.cpp:2004
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition: Layer.cpp:58
IConnectableLayer * AddAbsLayer(const char *name=nullptr) override
Add absolute layer to the network.
Definition: Network.cpp:1452
A MeanDescriptor for the MeanLayer.
const ConstTensor * m_RecurrentToInputWeights
Definition: LstmParams.hpp:44
This layer represents a division operation.
IConnectableLayer * AddSliceLayer(const SliceDescriptor &sliceDescriptor, const char *name=nullptr) override
Adds a slice layer to the network.
Definition: Network.cpp:1419
This layer represents a strided slice operation.
LayerType GetType() const
Definition: Layer.hpp:262
IConnectableLayer * AddGreaterLayer(const char *name=nullptr) override
Add a Greater layer to the network.
Definition: Network.cpp:1741
This layer represents a maximum operation.
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:315
const ConstTensor & GetRecurrentToInputWeights() const
IConnectableLayer * AddMergerLayer(const MergerDescriptor &mergerDescriptor, const char *name=nullptr) override
Adds a concat layer to the network.
Definition: Network.cpp:1446
OptimizeForType< Layer, ConvertFp32NetworkToFp16Impl > Fp32NetworkToFp16Converter
IConnectableLayer * AddResizeLayer(const ResizeDescriptor &resizeDescriptor, const char *name=nullptr) override
Adds a resize layer to the network.
Definition: Network.cpp:1508
IConnectableLayer * AddConstantLayer(const ConstTensor &input, const char *name=nullptr) override
Adds a layer with no inputs and a single output, which always corresponds to the passed in constant t...
Definition: Network.cpp:1532
A TransposeDescriptor for the TransposeLayer.
A StridedSliceDescriptor for the StridedSliceLayer.
IConnectableLayer * AddMultiplicationLayer(const char *name=nullptr) override
Adds a multiplication layer to the network.
Definition: Network.cpp:1462
OptimizationResult SelectTensorHandleStrategy(Graph &optGraph, BackendsMap &backends, TensorHandleFactoryRegistry &registry, bool importEnabled, Optional< std::vector< std::string > &> errMessages)
Definition: Network.cpp:943
IConnectableLayer * AddComparisonLayer(const ComparisonDescriptor &comparisonDescriptor, const char *name=nullptr) override
Add a Comparison layer to the network.
Definition: Network.cpp:1203
void ReportWarning(const std::string &warningMessage, Optional< std::vector< std::string > &> warningMessages)
Definition: Network.cpp:84
This layer represents a convolution 2d operation.
This layer converts data type Float32 to BFloat16.
bool CheckFlag(MemorySourceFlags flags, MemorySource source)
void SetQuantizationOffset(int32_t offset)
Definition: Tensor.cpp:480
OptimizationResult ApplyBackendOptimizations(OptimizedNetwork *optNetObjPtr, BackendSettings &backendSettings, BackendsMap &backends, const ModelOptions &modelOptions, Optional< std::vector< std::string > &> errMessages)
Definition: Network.cpp:537
static INetwork * CreateRaw(NetworkOptions networkOptions={})
Definition: Network.cpp:41
This layer represents a mean operation.
Definition: MeanLayer.hpp:14
This layer represents a comparison operation.
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:101
IConnectableLayer * AddNormalizationLayer(const NormalizationDescriptor &normalizationDescriptor, const char *name=nullptr) override
Adds a normalization layer to the network.
Definition: Network.cpp:1412
OptimizeForType< Layer, AddBroadcastReshapeLayerImpl > AddBroadcastReshapeLayer
std::unique_ptr< ScopedCpuTensorHandle > m_Weight
A unique pointer to store Weight values.
A Pooling2dDescriptor for the Pooling2dLayer.
This layer dequantizes the input tensor.
Definition: MergeLayer.hpp:13
const ConstTensor * m_OutputLayerNormWeights
Definition: LstmParams.hpp:60
A NormalizationDescriptor for the NormalizationLayer.
IConnectableLayer * AddPermuteLayer(const PermuteDescriptor &permuteDescriptor, const char *name=nullptr) override
Adds a permute layer to the network.
Definition: Network.cpp:1388
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
An InstanceNormalizationDescriptor for InstanceNormalizationLayer.
This layer represents a multiplication operation.
IConnectableLayer * AddGatherLayer(const char *name=nullptr) override
Add Gather layer to the network.
Definition: Network.cpp:1756
IConnectableLayer * AddSoftmaxLayer(const SoftmaxDescriptor &softmaxDescriptor, const char *name=nullptr) override
Adds a softmax layer to the network.
Definition: Network.cpp:1424
IConnectableLayer * AddLstmLayer(const LstmDescriptor &descriptor, const LstmInputParams &params, const char *name=nullptr) override
Add a Lstm layer to the network.
Definition: Network.cpp:1564
A ResizeBilinearDescriptor for the ResizeBilinearLayer.
IConnectableLayer * AddElementwiseUnaryLayer(const ElementwiseUnaryDescriptor &elementwiseUnaryDescriptor, const char *name=nullptr) override
Add an ElementwiseUnary layer to the network.
Definition: Network.cpp:1209
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:63
static INetworkPtr Create(NetworkOptions networkOptions={})
Definition: Network.cpp:46
IConnectableLayer * AddDivisionLayer(const char *name=nullptr) override
Adds a division layer to the network.
Definition: Network.cpp:1705
EdgeStrategy CalculateEdgeStrategy(BackendsMap &backends, ITensorHandleFactory::FactoryId srcFactoryId, const Layer &layer, const Layer &connectedLayer, TensorHandleFactoryRegistry &registry, bool importEnabled)
Definition: Network.cpp:857
static void Destroy(IOptimizedNetwork *network)
Definition: Network.cpp:56
virtual MemorySourceFlags GetImportFlags() const
std::unique_ptr< ScopedCpuTensorHandle > m_InputToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
Definition: LstmLayer.hpp:57
OptimizeForType< Layer, ConvertFp32NetworkToBf16Impl > Fp32NetworkToBf16Converter
IConnectableLayer * AddStridedSliceLayer(const StridedSliceDescriptor &stridedSliceDescriptor, const char *name=nullptr) override
Adds a strided slice layer to the network.
Definition: Network.cpp:1735
A SoftmaxDescriptor for the SoftmaxLayer.
IConnectableLayer * AddQuantizedLstmLayer(const QuantizedLstmInputParams &params, const char *name=nullptr) override
Add a QuantizedLstm layer to the network.
Definition: Network.cpp:1824
const ConstTensor & GetOutputGateBias() const
static const FactoryId LegacyFactoryId
This layer represents a fill operation.
Definition: FillLayer.hpp:13
IConnectableLayer * AddDetectionPostProcessLayer(const DetectionPostProcessDescriptor &descriptor, const ConstTensor &anchors, const char *name=nullptr) override
Adds a Detection PostProcess layer to the network.
Definition: Network.cpp:1378
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
A FillDescriptor for the FillLayer.
This layer represents a DepthToSpace operation.
A BatchNormalizationDescriptor for the BatchNormalizationLayer.
unsigned int GetNumElements() const
Definition: Tensor.hpp:192
Network(NetworkOptions networkOptions={})
Definition: Network.cpp:1177
const ConstTensor * m_InputToForgetWeights
Definition: LstmParams.hpp:41
std::map< BackendId, std::unique_ptr< class IBackendInternal > > BackendsMap
Definition: Network.hpp:325
This layer represents a resize operation.
Definition: ResizeLayer.hpp:13
A PermuteDescriptor for the PermuteLayer.
const ConstTensor * m_InputToInputWeights
Definition: LstmParams.hpp:40
std::vector< float > anchors({ 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 10.5f, 1.0f, 1.0f, 0.5f, 100.5f, 1.0f, 1.0f })