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