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