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