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