ArmNN
 25.02
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Network.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017-2024 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"
15 #include "armnn/utility/Timer.hpp"
16 
21 
22 #include <armnn/Exceptions.hpp>
23 #include <armnn/TypesUtils.hpp>
25 #include <armnn/Logging.hpp>
26 #include <armnn/utility/Assert.hpp>
29 
30 #include <client/include/IProfilingService.hpp>
31 
32 #include <common/include/ProfilingGuid.hpp>
33 
34 #include <fmt/format.h>
35 
36 #include <fcntl.h>
37 #include <algorithm>
38 #include <memory>
39 #include <vector>
40 #include <armnn/ArmNN.hpp>
41 
42 namespace armnn
43 {
44 
45 INetwork::INetwork(NetworkOptions networkOptions) : pNetworkImpl(new NetworkImpl(networkOptions)) {}
46 
47 INetwork::~INetwork() = default;
48 
50  : p_OptimizerOptionsImpl(std::make_unique<OptimizerOptionsOpaqueImpl>())
51 {
52 }
53 
55  : p_OptimizerOptionsImpl(std::make_unique<OptimizerOptionsOpaqueImpl>(*other.p_OptimizerOptionsImpl))
56 {
57 }
58 
60 
61 OptimizerOptionsOpaque::OptimizerOptionsOpaque(bool reduceFp32ToFp16, bool debug, bool reduceFp32ToBf16,
62  bool importEnabled, ModelOptions modelOptions, bool exportEnabled,
63  bool debugToFile)
64  : p_OptimizerOptionsImpl(std::make_unique<OptimizerOptionsOpaqueImpl>(reduceFp32ToFp16, debug, reduceFp32ToBf16,
65  importEnabled, modelOptions,
66  exportEnabled, debugToFile))
67 {
68 }
69 
70 OptimizerOptionsOpaque::OptimizerOptionsOpaque(bool reduceFp32ToFp16, bool debug, bool reduceFp32ToBf16,
71  ShapeInferenceMethod shapeInferenceMethod,
72  bool importEnabled, ModelOptions modelOptions, bool exportEnabled,
73  bool debugToFile, bool allowExpandedDims)
74  : p_OptimizerOptionsImpl(std::make_unique<OptimizerOptionsOpaqueImpl>(reduceFp32ToFp16, debug, reduceFp32ToBf16,
75  shapeInferenceMethod, importEnabled,
76  modelOptions, exportEnabled,
77  debugToFile, allowExpandedDims))
78 {
79 }
80 
82  : p_OptimizerOptionsImpl(std::make_unique<OptimizerOptionsOpaqueImpl>())
83 {
84  p_OptimizerOptionsImpl->m_ImportEnabled = OptimizerStruct.m_ImportEnabled;
85  p_OptimizerOptionsImpl->m_shapeInferenceMethod = OptimizerStruct.m_shapeInferenceMethod;
86  p_OptimizerOptionsImpl->m_ModelOptions = OptimizerStruct.m_ModelOptions;
87  p_OptimizerOptionsImpl->m_ProfilingEnabled = OptimizerStruct.m_ProfilingEnabled;
88  p_OptimizerOptionsImpl->m_DebugToFile = OptimizerStruct.m_DebugToFile;
89  p_OptimizerOptionsImpl->m_Debug = OptimizerStruct.m_Debug;
90  p_OptimizerOptionsImpl->m_ReduceFp32ToFp16 = OptimizerStruct.m_ReduceFp32ToFp16;
91  p_OptimizerOptionsImpl->m_ExportEnabled = OptimizerStruct.m_ExportEnabled;
92  p_OptimizerOptionsImpl->m_AllowExpandedDims = OptimizerStruct.m_AllowExpandedDims;
93  p_OptimizerOptionsImpl->m_ReduceFp32ToBf16 = OptimizerStruct.m_ReduceFp32ToBf16;
94 }
95 
97 {
98  p_OptimizerOptionsImpl->m_ImportEnabled = other.GetImportEnabled();
99  p_OptimizerOptionsImpl->m_shapeInferenceMethod = other.GetShapeInferenceMethod();
100  p_OptimizerOptionsImpl->m_ModelOptions = other.GetModelOptions();
101  p_OptimizerOptionsImpl->m_ProfilingEnabled = other.GetProfilingEnabled();
102  p_OptimizerOptionsImpl->m_DebugToFile = other.GetDebugToFileEnabled();
103  p_OptimizerOptionsImpl->m_Debug = other.GetDebugEnabled();
104  p_OptimizerOptionsImpl->m_ReduceFp32ToFp16 = other.GetReduceFp32ToFp16();
105  p_OptimizerOptionsImpl->m_ExportEnabled = other.GetExportEnabled();
106  p_OptimizerOptionsImpl->m_AllowExpandedDims = other.GetAllowExpandedDims();
107  p_OptimizerOptionsImpl->m_ReduceFp32ToBf16 = other.GetReduceFp32ToBf16();
108  return *this;
109 }
110 
112 {
113  p_OptimizerOptionsImpl->m_ImportEnabled = ImportState;
114 }
115 
117 {
118  p_OptimizerOptionsImpl->m_ExportEnabled = ExportState;
119 }
120 
122 {
123  p_OptimizerOptionsImpl->m_ProfilingEnabled = ProfilingState;
124 }
125 
127 {
128  p_OptimizerOptionsImpl->m_Debug = DebugState;
129 }
130 
132 {
133  p_OptimizerOptionsImpl->m_DebugToFile = DebugFileState;
134 }
135 
136 void OptimizerOptionsOpaque::SetReduceFp32ToFp16(bool ReduceFp32ToFp16State)
137 {
138  p_OptimizerOptionsImpl->m_ReduceFp32ToFp16 = ReduceFp32ToFp16State;
139 }
140 
142 {
143  p_OptimizerOptionsImpl->m_shapeInferenceMethod = ShapeInferenceMethodType;
144 }
145 
146 void OptimizerOptionsOpaque::SetAllowExpandedDims(bool ExpandedDimsAllowed)
147 {
148  p_OptimizerOptionsImpl->m_AllowExpandedDims = ExpandedDimsAllowed;
149 }
150 
152 {
153  p_OptimizerOptionsImpl->m_ModelOptions.push_back(NewModelOption);
154 }
155 
157 {
158  return p_OptimizerOptionsImpl->m_ProfilingEnabled;
159 };
160 
162 {
163  return p_OptimizerOptionsImpl->m_ImportEnabled;
164 };
165 
167 {
168  return p_OptimizerOptionsImpl->m_ExportEnabled;
169 };
170 
172 {
173  return p_OptimizerOptionsImpl->m_ReduceFp32ToFp16;
174 };
175 
177 {
178  return p_OptimizerOptionsImpl->m_ReduceFp32ToBf16;
179 }
180 
182 {
183  return p_OptimizerOptionsImpl->m_Debug;
184 }
185 
187 {
188  return p_OptimizerOptionsImpl->m_DebugToFile;
189 }
190 
192 {
193  return p_OptimizerOptionsImpl->m_AllowExpandedDims;
194 }
195 
197 {
198  return p_OptimizerOptionsImpl->m_ModelOptions;
199 }
200 
202 {
203  return p_OptimizerOptionsImpl->m_shapeInferenceMethod;
204 }
205 
206 const std::string OptimizerOptionsOpaque::ToString() const
207 {
208  std::stringstream stream;
209  stream << "OptimizerOptions: \n";
210  stream << "\tReduceFp32ToFp16: " << p_OptimizerOptionsImpl->m_ReduceFp32ToFp16 << "\n";
211  stream << "\tReduceFp32ToBf16: " << p_OptimizerOptionsImpl->m_ReduceFp32ToBf16 << "\n";
212  stream << "\tDebug: " << p_OptimizerOptionsImpl->m_Debug << "\n";
213  stream << "\tDebug to file: " << p_OptimizerOptionsImpl->m_DebugToFile << "\n";
214  stream << "\tShapeInferenceMethod: " <<
215  (p_OptimizerOptionsImpl->m_shapeInferenceMethod == ShapeInferenceMethod::ValidateOnly ?
216  "ValidateOnly" : "InferAndValidate") << "\n";
217  stream << "\tImportEnabled: " << p_OptimizerOptionsImpl->m_ImportEnabled << "\n";
218  stream << "\tExportEnabled: " << p_OptimizerOptionsImpl->m_ExportEnabled << "\n";
219  stream << "\tProfilingEnabled: " << p_OptimizerOptionsImpl->m_ProfilingEnabled << "\n";
220  stream << "\tAllowExpandedDims: " << p_OptimizerOptionsImpl->m_AllowExpandedDims << "\n";
221 
222  stream << "\tModelOptions: \n";
223  for (auto optionsGroup : p_OptimizerOptionsImpl->m_ModelOptions)
224  {
225  for (size_t i=0; i < optionsGroup.GetOptionCount(); i++)
226  {
227  const armnn::BackendOptions::BackendOption option = optionsGroup.GetOption(i);
228  stream << "\t\tBackend: " << optionsGroup.GetBackendId() << "\n"
229  << "\t\t\tOption: " << option.GetName() << "\n"
230  << "\t\t\tValue: " << std::string(option.GetValue().ToString()) << "\n";
231  }
232  }
233 
234  return stream.str();
235 }
236 
238 {
239  return pNetworkImpl->PrintGraph();
240 }
241 
243 {
244  return pNetworkImpl->AddInputLayer(id, name);
245 }
246 
248  const char* name)
249 {
250  return pNetworkImpl->AddArgMinMaxLayer(desc, name);
251 }
252 
254 {
255  return pNetworkImpl->AddCastLayer(name);
256 }
257 
259  const char* name)
260 {
261  return pNetworkImpl->AddComparisonLayer(comparisonDescriptor, name);
262 }
263 
264 
266  const char* name)
267 {
268  return pNetworkImpl->AddConcatLayer(concatDescriptor, name);
269 }
270 
271 
273  const char* name)
274 {
275  return pNetworkImpl->AddConvolution2dLayer(convolution2dDescriptor, name);
276 }
277 
279  const char* name)
280 {
281  return pNetworkImpl->AddConvolution3dLayer(convolution3dDescriptor, name);
282 }
283 
284 
286  const char* name)
287 {
288  return pNetworkImpl->AddDepthToSpaceLayer(depthToSpaceDescriptor, name);
289 }
290 
291 
293  const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
294  const char* name)
295 {
296  return pNetworkImpl->AddDepthwiseConvolution2dLayer(convolution2dDescriptor, name);
297 }
298 
299 
301 {
302  return pNetworkImpl->AddDequantizeLayer(name);
303 }
304 
305 
307  const DetectionPostProcessDescriptor& descriptor,
308  const ConstTensor& anchors,
309  const char* name)
310 {
311  return pNetworkImpl->AddDetectionPostProcessLayer(descriptor, anchors, name);
312 }
313 
315  const char* name)
316 {
317  return pNetworkImpl->AddElementwiseBinaryLayer(elementwiseBinaryDescriptor, name);
318 }
319 
321  const char* name)
322 {
323  return pNetworkImpl->AddElementwiseUnaryLayer(elementwiseUnaryDescriptor, name);
324 }
325 
327  const char* name)
328 {
329  return pNetworkImpl->AddFillLayer(fillDescriptor, name);
330 }
331 
333  const char* name)
334 {
335  return pNetworkImpl->AddFullyConnectedLayer(fullyConnectedDescriptor, name);
336 }
337 
339  const char* name)
340 {
341  return pNetworkImpl->AddFusedLayer(fusedDescriptor, name);
342 }
343 
345  const char* name)
346 {
347  return pNetworkImpl->AddPermuteLayer(permuteDescriptor, name);
348 }
349 
351  const char* name)
352 {
353  return pNetworkImpl->AddBatchToSpaceNdLayer(batchToSpaceNdDescriptor, name);
354 }
355 
357  const char* name)
358 {
359  return pNetworkImpl->AddPooling2dLayer(pooling2dDescriptor, name);
360 }
361 
363  const char* name)
364 {
365  return pNetworkImpl->AddPooling3dLayer(pooling3dDescriptor, name);
366 }
367 
369  CompiledBlobPtr compiledBlobPtr,
370  const Optional<BackendId>& backend,
371  const char* name)
372 {
373  return pNetworkImpl->AddPrecompiledLayer(preCompiledDescriptor, std::move(compiledBlobPtr), backend, name);
374 }
375 
377  const char* name)
378 {
379  return pNetworkImpl->AddActivationLayer(activationDescriptor, name);
380 }
381 
383  const char* name)
384 {
385  return pNetworkImpl->AddNormalizationLayer(normalizationDescriptor, name);
386 }
387 
388 IConnectableLayer* INetwork::AddSliceLayer(const SliceDescriptor& sliceDescriptor, const char* name)
389 {
390  return pNetworkImpl->AddSliceLayer(sliceDescriptor, name);
391 }
393  const char* name)
394 {
395  return pNetworkImpl->AddSoftmaxLayer(softmaxDescriptor, name);
396 }
397 
399  const char* name)
400 {
401  return pNetworkImpl->AddSplitterLayer(splitterDescriptor, name);
402 }
403 
405 {
406  return pNetworkImpl->AddMergeLayer(name);
407 }
408 
410 {
412  return pNetworkImpl->AddAdditionLayer(name);
414 }
415 
417 {
419  return pNetworkImpl->AddMultiplicationLayer(name);
421 }
422 
424  const ConstTensor& mean,
425  const ConstTensor& variance,
426  const ConstTensor& beta,
427  const ConstTensor& gamma,
428  const char* name)
429 {
430  return pNetworkImpl->AddBatchNormalizationLayer(desc, mean, variance, beta, gamma, name);
431 }
432 
434 {
435  return pNetworkImpl->AddRankLayer(name);
436 }
437 
439  const char* name)
440 {
441  return pNetworkImpl->AddResizeLayer(resizeDescriptor, name);
442 }
443 
445  const char* name)
446 {
447  return pNetworkImpl->AddReduceLayer(reduceDescriptor, name);
448 }
449 
451  const char* name)
452 {
453  return pNetworkImpl->AddInstanceNormalizationLayer(desc, name);
454 }
455 
457  const char* name)
458 {
459  return pNetworkImpl->AddL2NormalizationLayer(desc, name);
460 }
461 
463  const char* name)
464 {
465  return pNetworkImpl->AddLogSoftmaxLayer(logSoftmaxDescriptor, name);
466 }
467 
469  const char* name)
470 {
471  return pNetworkImpl->AddConstantLayer(input, name);
472 }
473 
475  const char* name)
476 {
477  return pNetworkImpl->AddReshapeLayer(reshapeDescriptor, name);
478 }
479 
481  const char* name)
482 {
483  return pNetworkImpl->AddSpaceToBatchNdLayer(spaceToBatchNdDescriptor, name);
484 }
485 
487  const char* name)
488 {
489  return pNetworkImpl->AddSpaceToDepthLayer(spaceToDepthDescriptor, name);
490 }
491 
493 {
494  return pNetworkImpl->AddFloorLayer(name);
495 }
497 {
498  return pNetworkImpl->AddOutputLayer(id, name);
499 }
500 
502  const LstmInputParams& params,
503  const char* name)
504 {
505  return pNetworkImpl->AddLstmLayer(descriptor, params, name);
506 }
507 
509 {
511  return pNetworkImpl->AddDivisionLayer(name);
513 }
514 
516 {
518  return pNetworkImpl->AddSubtractionLayer(name);
520 }
521 
523 {
525  return pNetworkImpl->AddMaximumLayer(name);
527 }
528 
529 IConnectableLayer* INetwork::AddMeanLayer(const MeanDescriptor& meanDescriptor, const char* name)
530 {
531  return pNetworkImpl->AddMeanLayer(meanDescriptor, name);
532 }
533 
535  const char* name)
536 {
537  return pNetworkImpl->AddPadLayer(padDescriptor, name);
538 }
539 
541 {
542  return pNetworkImpl->AddQuantizeLayer(name);
543 }
544 
546  const char* name)
547 {
548  return pNetworkImpl->AddStridedSliceLayer(stridedSliceDescriptor, name);
549 }
550 
552 {
554  return pNetworkImpl->AddMinimumLayer(name);
556 }
557 
559  const char* name)
560 {
561  return pNetworkImpl->AddGatherLayer(descriptor, name);
562 }
563 
565 {
566  return pNetworkImpl->AddGatherNdLayer(name);
567 }
568 
570 {
571  return pNetworkImpl->AddSwitchLayer(name);
572 }
573 
575 {
576  return pNetworkImpl->AddPreluLayer(name);
577 }
578 
580  const ConstTensor& weights,
581  const Optional<ConstTensor>& biases,
582  const char* name)
583 {
584  return pNetworkImpl->AddTransposeConvolution2dLayer(descriptor, weights, biases, name);
585 }
586 
588  const char* name)
589 {
590  return pNetworkImpl->AddTransposeLayer(transposeDescriptor, name);
591 }
592 
594 {
595  return pNetworkImpl->AddShapeLayer(name);
596 }
597 
599  const char* name)
600 {
601  return pNetworkImpl->AddStackLayer(descriptor, name);
602 }
603 
605  const char* name)
606 {
607  return pNetworkImpl->AddStandInLayer(descriptor, name);
608 }
609 
611  const char* name)
612 {
613  return pNetworkImpl->AddQuantizedLstmLayer(params, name);
614 }
615 
617  const LstmInputParams& params,
618  const char* name)
619 {
620  return pNetworkImpl->AddQLstmLayer(descriptor, params, name);
621 }
622 
624  const char* name)
625 {
626  return pNetworkImpl->AddLogicalBinaryLayer(descriptor, name);
627 }
628 
630  const UnidirectionalSequenceLstmDescriptor& descriptor,
631  const LstmInputParams& params,
632  const char* name)
633 {
634  return pNetworkImpl->AddUnidirectionalSequenceLstmLayer(descriptor, params, name);
635 }
636 
638  const char* name)
639 {
640  return pNetworkImpl->AddChannelShuffleLayer(descriptor, name);
641 }
642 
644  const char* name)
645 {
646  return pNetworkImpl->AddBatchMatMulLayer(descriptor, name);
647 }
648 
650 {
651  return pNetworkImpl->AddReverseV2Layer(name);
652 }
653 
655  const char *name)
656 {
657  return pNetworkImpl->AddTileLayer(descriptor, name);
658 }
659 
661  const char* name)
662 {
663  return pNetworkImpl->AddBroadcastToLayer(descriptor, name);
664 }
665 
667  const char *name)
668 {
669  return pNetworkImpl->AddScatterNdLayer(descriptor, name);
670 }
671 
673 {
674  return pNetworkImpl->ExecuteStrategy(strategy);
675 }
676 
678 {
679  return new INetwork(networkOptions);
680 }
681 
683 {
684  return INetworkPtr(CreateRaw(networkOptions), &INetwork::Destroy);
685 }
686 
688 {
689  delete network;
690 }
691 
693  : pOptimizedNetworkImpl(new OptimizedNetworkImpl(*other.pOptimizedNetworkImpl.get(), modelOptions)) {}
694 
695 IOptimizedNetwork::IOptimizedNetwork(std::unique_ptr<Graph> graph)
696  : pOptimizedNetworkImpl(new OptimizedNetworkImpl(std::move(graph))) {}
697 
698 IOptimizedNetwork::IOptimizedNetwork(std::unique_ptr<OptimizedNetworkImpl> impl)
699  : pOptimizedNetworkImpl(std::move(impl)) {}
700 
701 IOptimizedNetwork::IOptimizedNetwork(std::unique_ptr<Graph> graph, const ModelOptions& modelOptions)
702  : pOptimizedNetworkImpl(new OptimizedNetworkImpl(std::move(graph), modelOptions)) {}
703 
705 
707 {
708  delete network;
709 }
710 
712 {
713  return pOptimizedNetworkImpl->PrintGraph();
714 }
715 
716 Status IOptimizedNetwork::SerializeToDot(std::ostream& stream) const
717 {
718  return pOptimizedNetworkImpl->SerializeToDot(stream);
719 }
720 
721 const std::shared_ptr<IProfiler>& IOptimizedNetwork::GetProfiler() const
722 {
723  return pOptimizedNetworkImpl->GetGraph().GetProfiler();
724 }
725 
726 arm::pipe::ProfilingGuid IOptimizedNetwork::GetGuid() const
727 {
728  return pOptimizedNetworkImpl->GetGuid();
729 }
730 
732 {
733  return pOptimizedNetworkImpl->GetNumInputs();
734 }
735 
737 {
738  return pOptimizedNetworkImpl->GetNumOutputs();
739 }
740 
742 {
743  m_Graph->Print();
744  return Status::Success;
745 }
746 
747 Status OptimizedNetworkImpl::SerializeToDot(std::ostream& stream) const
748 {
749  return m_Graph->SerializeToDot(stream);
750 }
751 
753 {
754  return m_Graph->GetNumInputs();
755 }
756 
758 {
759  return m_Graph->GetNumOutputs();
760 }
761 
762 void ReportError(const std::string& errorMessage,
763  Optional<std::vector<std::string>&> errorMessages)
764 {
765  std::stringstream fullErrorMessage;
766  fullErrorMessage << "ERROR: " << errorMessage;
767  ARMNN_LOG(warning) << fullErrorMessage.str();
768  if (errorMessages)
769  {
770  errorMessages.value().push_back(fullErrorMessage.str());
771  }
772 }
773 
774 void ReportWarning(const std::string& warningMessage,
775  Optional<std::vector<std::string>&> warningMessages)
776 {
777  std::stringstream fullWarningMessage;
778  fullWarningMessage << "WARNING: " << warningMessage;
779  ARMNN_LOG(warning) << fullWarningMessage.str();
780  if (warningMessages)
781  {
782  warningMessages.value().push_back(fullWarningMessage.str());
783  }
784 }
785 
786 // Given an OptimizationResult, build and add an error message to the errMessages vector. Then return the result.
788  const Layer* layer,
789  const BackendSettings& backendSettings,
790  Optional<std::vector<std::string>&> errMessages)
791 {
792  std::stringstream failureMsg;
793  failureMsg << "Layer of type " << GetLayerTypeAsCString(layer->GetType())
794  << " is not supported on any preferred backend " << backendSettings.m_PreferredBackends;
795  ReportError(failureMsg.str(), errMessages);
796 
797  res.m_Error = true;
798  return res;
799 }
800 
801 bool CheckScaleSetOnQuantizedType(Layer* layer, Optional<std::vector<std::string>&> errMessages)
802 {
803  bool noErrors = true;
804  unsigned int numOutputs = layer->GetNumOutputSlots();
805  for (unsigned int i = 0; i < numOutputs; i++) {
806  OutputSlot& outputSlot = layer->GetOutputSlot(i);
807  TensorInfo info = outputSlot.GetTensorInfo();
808  auto quantizationDataType = info.GetDataType();
809  auto quantizationScales = info.GetQuantizationScales();
810  // For any Quantized Tensor ensure scale(s) are set
811  switch(quantizationDataType) {
812  case DataType::QAsymmU8:
813  case DataType::QSymmS16:
814  case DataType::QSymmS8:
815  case DataType::QAsymmS8:
816  if ((quantizationDataType == DataType::QAsymmU8 || quantizationDataType == DataType::QAsymmS8)
817  && info.HasPerAxisQuantization()) {
818  throw InvalidArgumentException("Per Axis Quantization is not supported in "
819  "Asymmetric Quantization Datatype.");
820  }
821  // Softmax under QuantisedAsymm8 must always be scale (1.0f/256.0f) and offset 0
822  if (!info.HasPerAxisQuantization() && quantizationDataType == DataType::QAsymmU8 &&
823  (info.GetQuantizationScale() != (1.0f / 256.0f) ||
824  info.GetQuantizationOffset() != 0) &&
825  layer->GetType() == armnn::LayerType::Softmax) {
826  std::stringstream ss;
827  ss << "Quantization parameters for Softmax layer (Scale: " <<
828  info.GetQuantizationScale() << " and Offset: " << info.GetQuantizationOffset() <<
829  ") are incorrect and have been updated to Scale: 0.00390625 and Offset: 0";
830  ARMNN_LOG(warning) << ss.str();
831  info.SetQuantizationScale((1.0f / 256.0f));
832  info.SetQuantizationOffset(0);
833  outputSlot.SetTensorInfo(info);
834  ReportError(ss.str(), errMessages);
835  }
836  break;
837  default:
838  break;
839  }
840  }
841  return noErrors;
842 }
843 
845  Graph& graph,
846  Layer* layer,
847  BackendId backend,
848  DataType dataTypeIn,
849  DataType dataTypeOut,
850  const std::vector<BackendId>& availablePreferredBackends,
851  std::string& reasonIfUnsupported,
852  Optional<std::vector<std::string>&> messages)
853 {
854  OptimizationResult result;
855 
856  // Helper lambda to compose meaningful error message before returning with error
857  auto ReturnError = [&](const Layer* layer)
858  {
859  return ReturnWithError(result, layer, backendSettings, messages);
860  };
861 
862  // need to set the compute device on the layer
863  // before we can check if it is supported
864  layer->SetBackendId(backend);
865  std::string currentReasonIfUnsupported;
866 
867  // To run FP16 operations on CpuAcc we need at least v8.2 architecture. If the available architecture
868  // is older than v8.2, we can check if the operator is supported by changing operator inputs & outputs
869  // to be FP32 and inserting convert layers around the FP32 operator.
870  bool isLayerSupported = IWorkloadFactory::IsLayerSupported(*layer, EmptyOptional(), currentReasonIfUnsupported);
871  reasonIfUnsupported += currentReasonIfUnsupported;
872  if (!isLayerSupported && HasCapability("AllOrNothing", backend))
873  {
874  // It has the capability but is it set to true?
875  if (GetCapability("AllOrNothing", backend).value().GetValue().AsBool())
876  {
877  // This is when a backend says it must execute all layers in a model. We'll report a message to say the
878  // backend will be ignored for the rest of this subgraph.
879  std::stringstream fullWarningMessage;
880  fullWarningMessage << "Backend: " << backend
881  << " has \"AllOrNothing\" enabled. A layer of type "
882  << GetLayerTypeAsCString(layer->GetType()) << " reports that it is not supported. "
883  << "This backend will not be considered to execute this subgraph.";
884  reasonIfUnsupported.append(fullWarningMessage.str());
885  // Also add it to the messages if they exist.
886  ReportWarning(fullWarningMessage.str(), messages);
887  result.m_Warning = true;
888  return result;
889  }
890  }
891  // This string matches the error message that is produced by acl when attempting to run FP16 kernels on
892  // a cpu or build that does not have fp16 support. We use this to check if we should add
893  // conversion layers or not.
894  std::string checkStr = "This CPU architecture does not support F16 data type, you need v8.2 or above";
895  if (!isLayerSupported || currentReasonIfUnsupported.find(checkStr) != std::string::npos)
896  {
897  if (dataTypeIn == DataType::Float16 || dataTypeOut == DataType::Float16)
898  {
899  if (IWorkloadFactory::IsLayerSupported(*layer, DataType::Float32, reasonIfUnsupported)
901  && layer->GetType() != LayerType::ConvertFp16ToFp32)
902  {
903  auto ConstantLayerFromFp16ToFp32 = [](Layer& layer)
904  {
905  if (layer.GetType() == LayerType::Constant)
906  {
907  ConstantLayer* constantLayer = PolymorphicDowncast<ConstantLayer*>(&layer);
908 
909  auto& info = constantLayer->m_LayerOutput->GetTensorInfo();
910 
911  if (info.GetDataType() == DataType::Float16)
912  {
913  std::vector<float> newValues(info.GetNumElements());
914 
916  constantLayer->m_LayerOutput->GetConstTensor<Half>(),
917  info.GetNumElements(),
918  newValues.data());
919 
920  TensorInfo newInfo(info);
922  ConstTensor newInput(newInfo, newValues);
923  constantLayer->m_LayerOutput.reset(new ScopedTensorHandle(newInput));
924 
925  layer.GetOutputSlot(0).SetTensorInfo(newInfo);
926  }
927  }
928  };
929 
930  bool checkType = false;
931 
932  for (auto inputSlot : layer->GetInputSlots())
933  {
934  auto connectedOutputSlot = inputSlot.GetConnectedOutputSlot();
935  if (connectedOutputSlot->GetOwningLayer().GetType() == LayerType::Constant)
936  {
937  if (connectedOutputSlot->GetNumConnections() == 1)
938  {
939  checkType = true;
940  ConstantLayerFromFp16ToFp32(connectedOutputSlot->GetOwningLayer());
941  }
942  }
943  }
944 
945  // Insert FP16 -> FP32 conversion layer before current layer
946  std::vector<ConvertFp16ToFp32Layer*> convertFp16ToFp32Layers;
947  if (dataTypeIn == DataType::Float16)
948  {
949  convertFp16ToFp32Layers =
950  InsertConvertFp16ToFp32LayersBefore(graph, *layer, checkType);
951  }
952 
953  // Insert FP32 -> FP16 conversion layer after current layer
954  std::vector<ConvertFp32ToFp16Layer*> convertFp32ToFp16Layers;
955  if (dataTypeOut == DataType::Float16)
956  {
957  convertFp32ToFp16Layers =
958  InsertConvertFp32ToFp16LayersAfter(graph, *layer);
959  }
960 
961  // Assign a supported backend to the newly introduced conversion layers
962  auto AssignFirstSupportedBackend = [&](Layer* layer, BackendId preferredBackend)
963  {
964  bool supportedBackendFound = false;
965  std::string reasonIfUnsupported;
966 
967  // Try preferred backend first
968  layer->SetBackendId(preferredBackend);
970  EmptyOptional(),
971  reasonIfUnsupported))
972  {
973  supportedBackendFound = true;
974  }
975  else
976  {
977  for (const auto& backend : availablePreferredBackends)
978  {
979  // Skip preferred backend (we already determined that it is not supported)
980  if (backend == preferredBackend)
981  {
982  continue;
983  }
984 
985  layer->SetBackendId(backend);
987  EmptyOptional(),
988  reasonIfUnsupported))
989  {
990  supportedBackendFound = true;
991  break;
992  }
993  }
994  }
995 
996  return supportedBackendFound;
997  };
998 
999  for (ConvertFp16ToFp32Layer* convertLayer : convertFp16ToFp32Layers)
1000  {
1001  if (!AssignFirstSupportedBackend(convertLayer, backend))
1002  {
1003  return ReturnError(convertLayer);
1004  }
1005  }
1006 
1007  for (ConvertFp32ToFp16Layer* convertLayer : convertFp32ToFp16Layers)
1008  {
1009  if (!AssignFirstSupportedBackend(convertLayer, backend))
1010  {
1011  return ReturnError(convertLayer);
1012  }
1013  }
1014 
1015  return result;
1016  }
1017  }
1018 
1019  std::stringstream warningMsg;
1020  warningMsg << "Layer of type " << GetLayerTypeAsCString(layer->GetType())
1021  << " is not supported on requested backend " << layer->GetBackendId().Get()
1022  << " for input data type " << GetDataTypeName(dataTypeIn)
1023  << " and output data type " << GetDataTypeName(dataTypeOut)
1024  << " (reason: " << reasonIfUnsupported
1025  << "), falling back to the next backend.";
1026  ReportWarning(warningMsg.str(), messages);
1027 
1028  return OptimizationResult(true, false);
1029  }
1030  else
1031  {
1032  return result;
1033  }
1034 }
1035 
1036 inline std::vector<DataType> GetLayerInOutDatatype(const Layer* layer)
1037 {
1038  DataType dataTypeIn = layer->GetNumInputSlots() == 0 ? DataType::Float32 :
1040  DataType dataTypeOut = layer->GetNumOutputSlots() == 0 ? DataType::Float32 :
1041  layer->GetOutputSlot(0).GetTensorInfo().GetDataType();
1042  return {dataTypeIn, dataTypeOut};
1043 }
1044 
1046  const std::vector<BackendId>& availablePreferredBackends)
1047 {
1048  bool hasFp16 = false;
1049  // Check if the first preferred backend has FP16 support
1050  auto firstBackend = availablePreferredBackends[0];
1051  auto backendObjPtr = backends.find(firstBackend)->second.get();
1052 
1053  auto hasFp16Capability = BackendOptions::BackendOption{"HasFp16", true};
1054  auto backendCapabilities = backendObjPtr->GetCapabilities();
1055 
1056  if (HasMatchingCapability(hasFp16Capability, backendCapabilities))
1057  {
1058  // First preferred backend has FP16 support. Enable reduce FP32 to FP16 when fp16-turbo-mode is enabled.
1059  hasFp16 = true;
1060  ARMNN_LOG(debug) << "The first available preferred backend: " << firstBackend
1061  << ", has FP16 support.";
1062  }
1063  else
1064  {
1065  ARMNN_LOG(debug) << "The first available preferred backend: " << firstBackend
1066  << ", does not have FP16 support. "
1067  << "The FP16 turbo mode option will be disable. It will run using FP32.";
1068  }
1069 
1070  // Check if the rest of the available preferred backends have FP16 support
1071  for (size_t i = 1; i < availablePreferredBackends.size(); ++i)
1072  {
1073  auto backend = availablePreferredBackends[i];
1074  backendObjPtr = backends.find(backend)->second.get();
1075  backendCapabilities = backendObjPtr->GetCapabilities();
1076  if (!HasMatchingCapability(hasFp16Capability, backendCapabilities))
1077  {
1078  ARMNN_LOG(debug) << "Next preferred backend: " << backend << ", does not have FP16 support. "
1079  << "It will run using FP32 when falling back to this backend.";
1080  }
1081  else
1082  {
1083  ARMNN_LOG(debug) << "Next preferred backend: " << backend << ", has FP16 support.";
1084  }
1085  }
1086 
1087  return hasFp16;
1088 }
1089 
1090 // Refactor to allow passing the IConnectableLayer* rather than Layer Iterator
1091 // on Graph and SubgraphView which are different types.
1093  IConnectableLayer* it,
1094  Optional<std::vector<std::string>&> errMessages,
1095  OptimizationResult& result,
1096  BackendSettings& backendSettings,
1097  std::vector<BackendId>& availablePreferredBackends,
1098  bool& restart)
1099 {
1100  auto ReturnError = [&](const Layer* layer)
1101  {
1102  return ReturnWithError(result, layer, backendSettings, errMessages);
1103  };
1104 
1105  auto layer = PolymorphicDowncast<Layer*>(it);
1106 
1107  if (layer->GetType() == LayerType::Input)
1108  {
1109  return;
1110  }
1111 
1112  std::vector<DataType> inOutDataType = GetLayerInOutDatatype(layer);
1113 
1114  std::string reasonIfUnsupported;
1115  bool found = false;
1116  if (!CheckScaleSetOnQuantizedType(layer, errMessages))
1117  {
1118  // don't bomb immediately, find all the quantized outputs
1119  // which haven't had a scale set and report them all back.
1120  result.m_Error = true;
1121  }
1122 
1123  // First try assign layer to hint backend
1124  if (layer->GetBackendHint().has_value() &&
1125  backendSettings.IsBackendSupported(layer->GetBackendHint().value()) &&
1126  AttemptBackendAssignment(backendSettings,
1127  optNetObjPtr->GetGraph(),
1128  layer,
1129  layer->GetBackendHint().value(),
1130  inOutDataType[0],
1131  inOutDataType[1],
1132  availablePreferredBackends,
1133  reasonIfUnsupported,
1134  errMessages).IsOk())
1135  {
1136  found = true;
1137  backendSettings.m_SelectedBackends.insert(layer->GetBackendHint().value());
1138  }
1139  else
1140  {
1141  // Try assign layer to preferred list of backends
1142  for (const auto& backend : availablePreferredBackends)
1143  {
1144  if (layer->GetBackendHint().has_value() &&
1145  layer->GetBackendHint().value() == backend)
1146  {
1147  continue; //Don't re-test the backend hint
1148  }
1149 
1150  OptimizationResult res = AttemptBackendAssignment(backendSettings,
1151  optNetObjPtr->GetGraph(),
1152  layer,
1153  backend,
1154  inOutDataType[0],
1155  inOutDataType[1],
1156  availablePreferredBackends,
1157  reasonIfUnsupported,
1158  errMessages);
1159 
1160  if (res.IsOk())
1161  {
1162  found = true;
1163  backendSettings.m_SelectedBackends.insert(backend);
1164  break;
1165  }
1166  else if (res.IsError())
1167  {
1168  result = res; // Cannot continue.
1169  // Note: we don't need to log the error as it would already
1170  // be logged in AttemptBackendAssignment().
1171  }
1172  else if (res.IsWarningOnly())
1173  {
1174  // Does the warning message relate to an AllOrNothing backend saying it rejects the subgraph?
1175  if (reasonIfUnsupported.find("AllOrNothing") != std::string::npos)
1176  {
1177  // Layer not supported by all or nothing backend. Add this backend to the ignore list and
1178  // indicate that the backend search should restart.
1179  backendSettings.m_IgnoredBackends.insert(backend);
1180  restart = true;
1181  return;
1182  }
1183  }
1184  }
1185  }
1186 
1187  // If the layer is unsupported by any devices, log and return a null network.
1188  if (!found)
1189  {
1190  // NOTE: if the layer is not an operation queue type AND we have not got CpuRef as a
1191  // fallback we should set the compute device on the layer to CpuRef (these are not
1192  // available as accelerated operations, or are only available under certain
1193  // conditions, currently they comprise MemCopy, Constant, Permute)
1194  armnn::LayerType layerType = layer->GetType();
1195  if (!backendSettings.IsCpuRefUsed() && (layerType == armnn::LayerType::MemCopy ||
1196  layerType == armnn::LayerType::Constant ||
1197  layerType == armnn::LayerType::Permute))
1198  {
1199  BackendId cpuBackendId(armnn::Compute::CpuRef);
1200  layer->SetBackendId(cpuBackendId);
1201  backendSettings.m_SelectedBackends.insert(cpuBackendId);
1202  }
1203  else
1204  {
1205  result = ReturnError(layer);
1206  }
1207  }
1208 
1209 }
1210 
1212  BackendSettings& backendSettings,
1213  Graph::Iterator& firstLayer,
1214  Graph::Iterator& lastLayer,
1215  Optional<std::vector<std::string>&> errMessages)
1216 {
1217  ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Optimizer_AssignBackends");
1218  OptimizationResult result;
1219 
1220  bool restart = false;
1221  BackendIdVector availablePreferredBackends;
1222  for (auto it = firstLayer; it != lastLayer; it = (restart ? firstLayer : ++it))
1223  {
1224  if (it == firstLayer)
1225  {
1226  availablePreferredBackends = backendSettings.GetAvailablePreferredBackends();
1227  if (availablePreferredBackends.empty())
1228  {
1229  ReportError("No preferred backends are available", errMessages);
1230  result.m_Error = true;
1231  return result;
1232  }
1233  }
1234  // In the case where we've set restart it must be reset before we continue looking at backends.
1235  if (restart)
1236  {
1237  restart = false;
1238  }
1239  AssignBackendsIConnectable(optNetObjPtr,
1240  *it,
1241  errMessages,
1242  result,
1243  backendSettings,
1244  availablePreferredBackends,
1245  restart);
1246  }
1247 
1248  for (auto it = firstLayer; it != lastLayer; ++it)
1249  {
1250  auto layer = PolymorphicDowncast<Layer*>(*it);
1251  std::vector<DataType> inOutDataType = GetLayerInOutDatatype(layer);
1252 
1253  // In AttemptBackendAssignment() we check:
1254  // - if input/output datatypes of the layer are float16
1255  // - if the layer is supported with these datatypes
1256  // If the layer is not supported (failing on ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED() in clframework),
1257  // we attempt to insert convertion layers either side of the new fp32 layer.
1258  bool isFloat16 = false;
1259  for (auto type : inOutDataType)
1260  {
1261  if (type == DataType::Float16)
1262  {
1263  isFloat16 = true;
1264  break;
1265  }
1266  }
1267 
1268  if (layer->GetBackendId() == "Unknown" || isFloat16)
1269  {
1270  AssignBackendsIConnectable(optNetObjPtr,
1271  *it,
1272  errMessages,
1273  result,
1274  backendSettings,
1275  availablePreferredBackends,
1276  restart);
1277  }
1278  }
1279 
1280  for (auto it = firstLayer; it != lastLayer; ++it)
1281  {
1282  auto layer = PolymorphicDowncast<Layer*>(*it);
1283 
1284  if(layer->GetType() == LayerType::Input)
1285  {
1286  BackendId connectedBackendId = layer->GetOutputSlot(0).GetConnection(0)->GetOwningLayer().GetBackendId();
1287  layer->SetBackendId(connectedBackendId);
1288  }
1289  }
1290 
1291  return result;
1292 }
1293 
1295  BackendSettings& backendSettings,
1298  Optional<std::vector<std::string>&> errMessages)
1299 {
1300  ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Optimizer_AssignBackends");
1301  OptimizationResult result;
1302 
1303  auto availablePreferredBackends = backendSettings.GetAvailablePreferredBackends();
1304  if (availablePreferredBackends.empty())
1305  {
1306  std::stringstream failureMsg;
1307  failureMsg << "No preferred backends are available";
1308  ReportError(failureMsg.str(), errMessages);
1309 
1310  result.m_Error = true;
1311  return result;
1312  }
1313 
1314  bool restart = false;
1315  for (auto it = firstLayer; it != lastLayer; ++it)
1316  {
1317  AssignBackendsIConnectable(optNetObjPtr,
1318  *it,
1319  errMessages,
1320  result,
1321  backendSettings,
1322  availablePreferredBackends,
1323  restart);
1324  }
1325 
1326  for (auto it = firstLayer; it != lastLayer; ++it)
1327  {
1328  auto layer = PolymorphicDowncast<Layer*>(*it);
1329 
1330  if(layer->GetType() == LayerType::Input)
1331  {
1332  BackendId connectedBackendId = layer->GetOutputSlot(0).GetConnection(0)->GetOwningLayer().GetBackendId();
1333  layer->SetBackendId(connectedBackendId);
1334  }
1335  }
1336 
1337  return result;
1338 }
1339 
1341  BackendSettings& backendSettings,
1342  SubgraphView& subgraph,
1343  Optional<std::vector<std::string>&> errMessages)
1344 {
1345  SubgraphView::IConnectableLayerIterator firstLayer = subgraph.begin();
1346  SubgraphView::IConnectableLayerIterator lastLayer = subgraph.end();
1347  return AssignBackends(optNetObjPtr,
1348  backendSettings,
1349  firstLayer,
1350  lastLayer,
1351  errMessages);
1352 }
1353 
1355  BackendSettings& backendSettings)
1356 {
1357  BackendsMap backends;
1358  auto const& backendRegistry = BackendRegistryInstance();
1359  for (auto&& selectedBackend : backendSettings.m_SupportedBackends)
1360  {
1361  auto backendFactory = backendRegistry.GetFactory(selectedBackend);
1362  auto backendObjPtr = backendFactory();
1363 
1364  backendObjPtr->RegisterTensorHandleFactories(handleFactoryRegistry);
1365 
1366  backends[backendObjPtr->GetId()] = std::move(backendObjPtr);
1367  }
1368 
1369  return backends;
1370 }
1371 
1373  BackendSettings& backendSettings,
1374  BackendsMap& backends,
1375  const ModelOptions& modelOptions,
1376  Optional<std::vector<std::string>&> errMessages)
1377 {
1378  ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Optimizer_ApplyBackendOptimizations")
1379  OptimizationResult result;
1380 
1381  // Get the optimized graph
1382  Graph& optGraph = optNetObjPtr->GetGraph();
1383 
1384  // Run backend specific optimizations
1385  for (auto&& selectedBackend : backendSettings.m_SelectedBackends)
1386  {
1387  auto backendObjPtr = backends.find(selectedBackend)->second.get();
1388  if (!backendObjPtr)
1389  {
1390  throw armnn::NullPointerException("backendObjPtr must not be null.");
1391  }
1392 
1393  if (selectedBackend == armnn::Compute::GpuAcc || selectedBackend == armnn::Compute::CpuAcc)
1394  {
1397  }
1398 
1399  // Select sub-graphs based on backend
1402  // Select layers assigned to the requested backend
1403  [&backendObjPtr](const Layer& layer)
1404  {
1405 
1406  return layer.GetType() != LayerType::Input &&
1407  layer.GetType() != LayerType::Output &&
1408  layer.GetBackendId() == backendObjPtr->GetId();
1409  });
1410  if (subgraphs.empty())
1411  {
1412  // No sub-graphs found, try with next selected backend
1413  continue;
1414  }
1415 
1416  // Try to optimize each sub-graph
1417  for (auto& subgraph : subgraphs)
1418  {
1419  // Try to optimize the current sub-graph
1420  ARMNN_SCOPED_PROFILING_EVENT(backendObjPtr->GetId(), "Optimizer_OptimizeSubgraph");
1421  OptimizationViews optimizationViews = backendObjPtr->OptimizeSubgraphView(*subgraph, modelOptions);
1422  if (!optimizationViews.Validate(*subgraph))
1423  {
1424  throw armnn::Exception("optimizationViews must have a valid subgraph.");
1425  }
1426 
1427  // Optimization attempted, check the resulting optimized sub-graph
1428  for (auto& substitution : optimizationViews.GetSubstitutions())
1429  {
1430  // Sub-graph optimized, substitute the sub-graph with the new optimized one in the main optimized graph
1431  SubgraphView& replacementSubgraph = substitution.m_ReplacementSubgraph;
1432  SubgraphView& substitutableSubgraph = substitution.m_SubstitutableSubgraph;
1433  optGraph.SubstituteSubgraph(substitutableSubgraph, replacementSubgraph);
1434 
1435  // Assign the current backend to the optimized sub-graph
1436  const SubgraphView::IConnectableLayers& subgraphLayers = replacementSubgraph.GetIConnectableLayers();
1437  std::for_each(subgraphLayers.begin(), subgraphLayers.end(), [&selectedBackend](IConnectableLayer* l)
1438  {
1439  PolymorphicDowncast<Layer*>(l)->SetBackendId(selectedBackend);
1440  });
1441  }
1442 
1443  // Remove deleted sub-graphs
1444  for (auto& deletedSubgraph : optimizationViews.GetDeletedSubgraphs())
1445  {
1446  for (auto& l : deletedSubgraph.GetIConnectableLayers())
1447  {
1448  Layer* deletedLayer = PolymorphicDowncast<Layer*>(l);
1449  for (unsigned int in = deletedLayer->GetNumInputSlots(); in > 0; --in)
1450  {
1451  auto inputSlot = deletedLayer->GetInputSlot(in -1);
1452  OutputSlot* parentOut = inputSlot.GetConnectedOutputSlot();
1453  parentOut->Disconnect(inputSlot);
1454  for (unsigned int out = deletedLayer->GetOutputSlot(in -1).GetNumConnections(); out > 0; --out)
1455  {
1456  InputSlot* childIn = deletedLayer->GetOutputSlot(in - 1).GetConnection(out -1);
1457  deletedLayer->GetOutputSlot(in - 1).Disconnect(*childIn);
1458  parentOut->Connect(*childIn);
1459  }
1460  }
1461  optGraph.EraseLayer(deletedLayer);
1462  }
1463  }
1464 
1465  if (!optimizationViews.GetFailedSubgraphs().empty())
1466  {
1467  std::stringstream warningMsg;
1468  warningMsg << "Some sub-graph(s) failed to optimized on " << backendObjPtr->GetId() << " backend.";
1469  ReportWarning(warningMsg.str(), errMessages);
1470 
1471  // Failed to optimize the given sub-graph, re-assign the sub-graph layers to other available backends
1472  BackendSettings settingsCopy(backendSettings);
1473  if (!backendObjPtr->GetId().IsCpuRef())
1474  {
1475  // Add the current backend to the list of backends to ignore
1476  settingsCopy.m_IgnoredBackends.insert(backendObjPtr->GetId());
1477  }
1478 
1479  int count=0;
1480  for (auto& failedSubgraph : optimizationViews.GetFailedSubgraphs())
1481  {
1482  // An error occurred: the optimization was attempted but not performed, try different backends
1483  std::stringstream subgraphMsg;
1484  subgraphMsg << "Re-assigning backends to " << failedSubgraph.GetIConnectableLayers().size()
1485  << " layers inside sub-graph " << count++;
1486  ReportWarning(subgraphMsg.str(), errMessages);
1487 
1488  OptimizationResult reassignmentResult = AssignBackends(optNetObjPtr,
1489  settingsCopy,
1490  *subgraph,
1491  errMessages);
1492  if (reassignmentResult.m_Error)
1493  {
1494  // Failed to re-assign one of the remaining backends to each layer of the sub-graph
1495  result.m_Error = true;
1496  return result;
1497  }
1498  }
1499  }
1500  }
1501  }
1502 
1503  return result;
1504 }
1505 
1508  TensorHandleFactoryRegistry& registry)
1509 {
1510  if (src != dst)
1511  {
1512  ITensorHandleFactory* srcFactory = registry.GetFactory(src);
1513  ITensorHandleFactory* dstFactory = registry.GetFactory(dst);
1514 
1515  if (srcFactory && dstFactory &&
1516  (srcFactory->GetExportFlags() & dstFactory->GetImportFlags()) != 0)
1517  {
1518  return false;
1519  }
1520  return true;
1521  }
1522  return false;
1523 }
1524 
1525 // Find the handle factory for the input layer which results in fewest required copies.
1527  OutputSlot& slot,
1528  TensorHandleFactoryRegistry& registry,
1529  bool importEnabled)
1530 {
1531  Layer& layer = slot.GetOwningLayer();
1532 
1533  if (layer.GetType() != LayerType::Input)
1534  {
1535  throw armnn::Exception("layer must be of type \"Input\".");
1536  }
1537 
1538  // Explicitly select the tensorhandle factory for InputLayer because the rules for it are slightly different. It
1539  // doesn't matter which backend it is assigned to because they all use the same implementation, which
1540  // requires Map/Unmap support. This means that, so long as the handle type supports map/unmap semantics, we can
1541  // select a factory with maximum compatibility with the layers connected to the InputLayer.
1542 
1543  // First ensure the from backends can support the TensorHandeAPI
1544  auto frmBackend = backends.find(layer.GetBackendId());
1545  if (frmBackend == backends.end() ||
1546  !frmBackend->second->SupportsTensorAllocatorAPI())
1547  {
1549  }
1550 
1551  // Go through all connections to the output slot and determine the TensorHandleFactory which results in the
1552  // fewest copies.
1553  std::map<ITensorHandleFactory::FactoryId, int> factoryScores;
1554  int topScore = 0;
1556 
1557  for (auto&& connection : slot.GetConnections())
1558  {
1559 
1560  const Layer& connectedLayer = connection->GetOwningLayer();
1561 
1562  auto toBackend = backends.find(connectedLayer.GetBackendId());
1563  if (toBackend == backends.end())
1564  {
1565  throw armnn::Exception("Backend id not found for the connected layer");
1566  }
1567 
1568  if (!toBackend->second.get()->SupportsTensorAllocatorAPI())
1569  {
1570  // The destination backend does not support the tensor allocator API, move to the next one
1571  continue;
1572  }
1573 
1574  auto dstPrefs = toBackend->second.get()->GetHandleFactoryPreferences();
1575  for (auto&& dst : dstPrefs)
1576  {
1577  // Input layers use the mem copy workload or import, so the selected factory must
1578  // support either the map/unmap API or Import API
1579  ITensorHandleFactory* factory = registry.GetFactory(dst);
1580  if (importEnabled && factory->GetImportFlags() == 0)
1581  {
1582  continue;
1583  }
1584  else if (!importEnabled && !factory->SupportsMapUnmap())
1585  {
1586  continue;
1587  }
1588 
1589  auto it = factoryScores.find(dst);
1590  if (it == factoryScores.end())
1591  {
1592  // Add new score to the table
1593  factoryScores[dst] = 0;
1594  if (topChoice == ITensorHandleFactory::LegacyFactoryId)
1595  {
1596  topChoice = dst;
1597  }
1598  }
1599  else
1600  {
1601  // Increase the score
1602  factoryScores[dst]++;
1603 
1604  // Track the best option
1605  if (factoryScores[dst] > topScore)
1606  {
1607  topScore = factoryScores[dst];
1608  topChoice = dst;
1609  }
1610  }
1611  }
1612  }
1613 
1614  return topChoice;
1615 }
1616 
1617 // Find the handle factory for the output layer which results in fewest required copies.
1619  OutputSlot& slot,
1620  TensorHandleFactoryRegistry& registry)
1621 {
1622  IgnoreUnused(backends, slot, registry);
1624 }
1625 
1626 // For all handle factories supported on the source backend, we wish to find the one which requires the fewest copies
1627 // when considering all connections.
1629  OutputSlot& outputSlot,
1630  TensorHandleFactoryRegistry& registry,
1631  bool exportEnabled)
1632 {
1633  // First ensure the from backends can support the TensorHandeAPI
1634  Layer& layer = outputSlot.GetOwningLayer();
1635  auto frmBackend = backends.find(layer.GetBackendId());
1636  if (frmBackend == backends.end() ||
1637  !frmBackend->second->SupportsTensorAllocatorAPI())
1638  {
1640  }
1641 
1642  bool outputConnection = false;
1643  for (auto&& connection : outputSlot.GetConnections())
1644  {
1645  const Layer& connectedLayer = connection->GetOwningLayer();
1646  if (connectedLayer.GetType() == LayerType::Output)
1647  {
1648  outputConnection = true;
1649  }
1650  }
1651 
1652  IBackendInternal* srcBackend = frmBackend->second.get();
1653  auto srcPrefs = srcBackend->GetHandleFactoryPreferences();
1654 
1655  // Initialize the scores
1656  std::map<ITensorHandleFactory::FactoryId, int> factoryScores;
1657  for (auto&& pref : srcPrefs)
1658  {
1659  if (exportEnabled)
1660  {
1661  ITensorHandleFactory* factory = registry.GetFactory(pref);
1662  if (outputConnection)
1663  {
1664  // Check if this is fallback case
1665  bool fallbackConnection = false;
1666  for (auto&& inputSlot : layer.GetInputSlots())
1667  {
1668  if (inputSlot.GetConnectedOutputSlot()->GetOwningLayer().GetBackendId() != layer.GetBackendId())
1669  {
1670  fallbackConnection = true;
1671  }
1672  }
1673  if (fallbackConnection)
1674  {
1675  auto factoryCap = factory->GetCapabilities(&layer, &layer, CapabilityClass::FallbackImportDisabled);
1676  // Cannot use factory import if fallback import is not supported.
1677  if (!factoryCap.empty())
1678  {
1679  continue;
1680  }
1681  }
1682  else if (factory->GetExportFlags() == 0)
1683  {
1684  continue;
1685  }
1686  }
1687  if (!outputConnection)
1688  {
1689  auto factoryCap = factory->GetCapabilities(&layer, &layer, CapabilityClass::FallbackImportDisabled);
1690  // Cannot use factory import if fallback import is not supported.
1691  if (!factoryCap.empty())
1692  {
1693  continue;
1694  }
1695  }
1696 
1697  }
1698  else
1699  {
1700  // Only consider factories that support map/unmap
1701  ITensorHandleFactory* factory = registry.GetFactory(pref);
1702  if (!factory->SupportsMapUnmap())
1703  {
1704  // The current tensor handle factory does not support the map/unmap strategy, move to the next one
1705  continue;
1706  }
1707  }
1708 
1709 
1710  auto it = factoryScores.find(pref);
1711  if (it == factoryScores.end())
1712  {
1713  // Add new score to the table
1714  factoryScores[pref] = 0;
1715  }
1716  }
1717 
1718  // Score each handle factory based on how many times it requires copies on the slot connections
1719  for (auto&& connection : outputSlot.GetConnections())
1720  {
1721  const Layer& connectedLayer = connection->GetOwningLayer();
1722 
1723  auto toBackend = backends.find(connectedLayer.GetBackendId());
1724  if (toBackend == backends.end())
1725  {
1726  throw armnn::Exception("Backend id not found for the connected layer");
1727  }
1728 
1729  auto dstPrefs = toBackend->second.get()->GetHandleFactoryPreferences();
1730  for (auto&& src : srcPrefs)
1731  {
1732  if (factoryScores.find(src) == factoryScores.end()) // Don't consider excluded factories
1733  {
1734  continue;
1735  }
1736 
1737  for (auto&& dst : dstPrefs)
1738  {
1739  if (RequiresCopy(src, dst, registry))
1740  {
1741  // Copy avoided, increase the score
1742  factoryScores[src]++;
1743  break;
1744  }
1745  }
1746  }
1747  }
1748 
1749  // Find the lowest score
1750  int minScore = std::numeric_limits<int>::max();
1751  for (auto it : factoryScores)
1752  {
1753  minScore = std::min(minScore, it.second);
1754  }
1755 
1756  // Collect factories matching the best(lowest) score
1757  std::vector<ITensorHandleFactory::FactoryId> optimalFactories;
1758  for (auto it : factoryScores)
1759  {
1760  if (it.second == minScore)
1761  {
1762  optimalFactories.push_back(it.first);
1763  }
1764  }
1765 
1766  // For all compatible Factories matching the best score, find the preferred one for the current layer.
1767  for (auto&& srcPref : srcPrefs)
1768  {
1769  for (auto&& comp : optimalFactories)
1770  {
1771  if (comp == srcPref)
1772  {
1773  return comp;
1774  }
1775  }
1776  }
1777 
1779 }
1780 
1782  ITensorHandleFactory::FactoryId srcFactoryId,
1783  const Layer& layer,
1784  const Layer& connectedLayer,
1785  TensorHandleFactoryRegistry& registry,
1786  bool importEnabled)
1787 {
1788  auto toBackend = backends.find(connectedLayer.GetBackendId());
1789  if (toBackend == backends.end())
1790  {
1791  throw armnn::Exception("Backend id not found for the connected layer");
1792  }
1793 
1794  auto dstPrefs = toBackend->second.get()->GetHandleFactoryPreferences();
1795 
1796  // Legacy API check for backward compatibility
1797  if (srcFactoryId == ITensorHandleFactory::LegacyFactoryId || dstPrefs.empty())
1798  {
1799  if (layer.GetBackendId() != connectedLayer.GetBackendId())
1800  {
1802  }
1803  else
1804  {
1806  }
1807  }
1808 
1809  // TensorHandleFactory API present, so perform more sophisticated strategies.
1810  // Dst Output layers don't require copy because they use import or map/unmap
1811  if (connectedLayer.GetType() == LayerType::Output)
1812  {
1814  }
1815 
1816  // Search for direct match in prefs
1817  for (auto&& pref : dstPrefs)
1818  {
1819  if (pref == srcFactoryId)
1820  {
1822  }
1823  }
1824 
1825  // Search for export/import options
1826  ITensorHandleFactory* srcFactory = registry.GetFactory(srcFactoryId);
1827  if (srcFactory->GetExportFlags() != 0 && importEnabled)
1828  {
1829  for (auto&& pref : dstPrefs)
1830  {
1831  ITensorHandleFactory* dstFactory = registry.GetFactory(pref);
1832 
1833  // Handles cases when a destPref is not listed in TensorHandleFactoryRegistry
1834  if (!dstFactory) {
1835  continue;
1836  }
1837  if ((dstFactory->GetImportFlags() & srcFactory->GetExportFlags()) != 0)
1838  {
1839  auto srcCapability = srcFactory->GetCapabilities(&layer, &layer, CapabilityClass::PaddingRequired);
1840  auto dstCapability = dstFactory->GetCapabilities(&connectedLayer,
1841  &connectedLayer,
1843  auto srcFallback = srcFactory->GetCapabilities(&layer, &layer, CapabilityClass::FallbackImportDisabled);
1844  auto dstFallback = dstFactory->GetCapabilities(&connectedLayer,
1845  &connectedLayer,
1847  // Do not require memory copy if the source and destination do not require padding.
1848  if (srcCapability.empty() && dstCapability.empty() && srcFallback.empty() && dstFallback.empty())
1849  {
1851  }
1852  }
1853  }
1854  }
1855 
1856  // Search for copy options via map/unmap
1857  if (srcFactory->SupportsMapUnmap())
1858  {
1859  for (auto&& pref : dstPrefs)
1860  {
1861  ITensorHandleFactory* dstFactory = registry.GetFactory(pref);
1862  if (dstFactory && dstFactory->SupportsMapUnmap())
1863  {
1865  }
1866  }
1867  }
1868 
1869  return EdgeStrategy::Undefined;
1870 }
1871 
1872 // Select the TensorHandleFactories and the corresponding memory strategy
1874  BackendsMap& backends,
1875  TensorHandleFactoryRegistry& registry,
1876  bool importEnabled,
1877  bool exportEnabled,
1878  Optional<std::vector<std::string>&> errMessages)
1879 {
1880  ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Optimizer_SelectTensorHandleStrategy");
1881  OptimizationResult result;
1882 
1883  optGraph.ForEachLayer([&backends, &registry, &result, &errMessages, importEnabled, exportEnabled](Layer* layer)
1884  {
1885  // Lets make sure the backend is in our list of supported backends. Something went wrong during backend
1886  // assignment if this check fails
1887  if (backends.find(layer->GetBackendId()) == backends.end())
1888  {
1889  throw armnn::Exception("Backend id not found for the layer");
1890  }
1891 
1892  // Check each output separately
1893  for (unsigned int slotIdx = 0; slotIdx < layer->GetNumOutputSlots(); slotIdx++)
1894  {
1895  OutputSlot& outputSlot = layer->GetOutputSlot(slotIdx);
1896 
1898 
1899  // Calculate the factory to use which results in the fewest copies being made.
1900  switch(layer->GetType())
1901  {
1902  case LayerType::Input:
1903  slotOption = CalculateSlotOptionForInput(backends, outputSlot, registry, importEnabled);
1904  break;
1905  case LayerType::Output:
1906  slotOption = CalculateSlotOptionForOutput(backends, outputSlot, registry);
1907  break;
1908  default:
1909  slotOption = CalculateSlotOption(backends, outputSlot, registry, exportEnabled);
1910  break;
1911  }
1912  outputSlot.SetTensorHandleFactory(slotOption);
1913 
1914  // Now determine the "best" edge strategy for each connection given the slotOption.
1915  unsigned int connectionIdx = 0;
1916  for (auto&& connection : outputSlot.GetConnections())
1917  {
1918  const Layer& connectedLayer = connection->GetOwningLayer();
1919 
1920  EdgeStrategy strategy = CalculateEdgeStrategy(backends, slotOption, *layer, connectedLayer,
1921  registry, importEnabled);
1922 
1923  if (strategy == EdgeStrategy::Undefined)
1924  {
1925  result.m_Error = true;
1926  if (errMessages)
1927  {
1928  errMessages.value().emplace_back("Could not find valid strategy required for compatibility"
1929  " between backends.");
1930  }
1931  return;
1932  }
1933 
1934  outputSlot.SetEdgeStrategy(connectionIdx, strategy);
1935 
1936  connectionIdx++;
1937  }
1938  }
1939  });
1940 
1941  return result;
1942 }
1943 
1944 bool CheckFastMathSupport(const std::vector<BackendId>& availablePreferredBackends,
1945  const ModelOptions& modelOptions)
1946 {
1947  bool hasFastMath = false;
1948  // Check if the first preferred backend has Fastmath support
1949  auto firstBackend = availablePreferredBackends[0];
1950  if (!modelOptions.empty())
1951  {
1952  ParseOptions(modelOptions, firstBackend, [&](std::string name, const BackendOptions::Var& value)
1953  {
1954  if (name == "FastMathEnabled")
1955  {
1956  hasFastMath = value.AsBool();
1957  ARMNN_LOG(debug) << "The first available preferred backend: " << firstBackend
1958  << ", has FastMath support.";
1959  }
1960  });
1961  }
1962  else
1963  {
1964  ARMNN_LOG(warning) << "The first available preferred backend: " << firstBackend
1965  << ", does not have FastMath support. "
1966  << "Support for Turbo mode for TfLite post quantized FP16 models wil be disabled.";
1967  }
1968 
1969  return hasFastMath;
1970 }
1971 
1972 bool IsTfLiteTurboModel(const Graph& optGraph)
1973 {
1974  // We will define a TfLiteTurboModel as follows:
1975  // All constant layers which are followed by a dequantize layer convert from Fp16 to FP32
1976  Graph::ConstIterator firstLayer = optGraph.begin();
1977  Graph::ConstIterator lastLayer = optGraph.end();
1978  // There must be at least one constant layer to dequantize layer converting from FP16 to Fp32
1979  bool atLeastOneDequantizeEncountered = false;
1980  for (auto it = firstLayer; it != lastLayer; ++it)
1981  {
1982  auto layer = *it;
1983  if (layer->GetType() == LayerType::Constant)
1984  {
1985  auto& connectedLayer = layer->GetOutputSlot(0).GetConnection(0)->GetOwningLayer();
1986  if (connectedLayer.GetType() == LayerType::Dequantize)
1987  {
1988  if(!(connectedLayer.GetInputSlot(0).GetTensorInfo().GetDataType() == DataType::Float16 &&
1989  connectedLayer.GetOutputSlot(0).GetTensorInfo().GetDataType() == DataType::Float32))
1990  {
1991  return false;
1992  }
1993  else
1994  {
1995  atLeastOneDequantizeEncountered = true;
1996  }
1997  }
1998  }
1999  }
2000  if (!atLeastOneDequantizeEncountered)
2001  {
2002  return false;
2003  }
2004  return true;
2005 }
2006 
2007 
2008 // Forwarding function to remain backward compatible with legacy OptimizerOptions
2010  const std::vector<BackendId>& backendPreferences,
2011  const IDeviceSpec& deviceSpec,
2012  const OptimizerOptions& options,
2013  Optional<std::vector<std::string>&> messages)
2014 {
2015  return Optimize(inGraph,
2016  backendPreferences,
2017  deviceSpec,
2018  OptimizerOptionsOpaque(options),
2019  messages);
2020 }
2021 
2023  const std::vector<BackendId>& backendPreferences,
2024  const IDeviceSpec& deviceSpec,
2025  const OptimizerOptionsOpaque& options,
2026  Optional<std::vector<std::string>&> messages)
2027 {
2028  ARMNN_LOG(debug) << options.ToString();
2029 
2030  // Enable profiling
2031  auto profiler = inGraph.GetProfiler();
2032  ProfilerManager::GetInstance().RegisterProfiler(profiler.get());
2033  profiler->EnableProfiling(options.GetProfilingEnabled());
2034 
2035  ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Optimizer");
2036  if (backendPreferences.empty())
2037  {
2038  throw InvalidArgumentException("Invoked Optimize with no backends specified");
2039  }
2040 
2041  if (options.GetReduceFp32ToBf16())
2042  {
2043  throw InvalidArgumentException("BFloat16 optimization is currently ignored. In order to use Bf16 optimization "
2044  "Please use the FastMathEnabled backend option for CpuAcc or GpuAcc.");
2045  }
2046 
2047  if (options.GetReduceFp32ToFp16() && options.GetReduceFp32ToBf16())
2048  {
2049  throw InvalidArgumentException("BFloat16 and Float16 optimization cannot be enabled at the same time.");
2050  }
2051 
2052  // Ensure TensorInfo is set on all output slots of ConstantLayers in the graph
2054 
2055  std::unique_ptr<Graph> graph = std::make_unique<Graph>(inGraph);
2056 
2057  // We need to pass on the information about whether import and export is enabled to the LoadNetwork phase.
2058  // The mechanism to do that is to add model options to the optimized network.
2059  armnn::BackendOptions importExport("Global",
2060  {{"ImportEnabled", options.GetImportEnabled()},
2061  {"ExportEnabled", options.GetExportEnabled()}});
2062  ModelOptions optimizedOptions(options.GetModelOptions());
2063  optimizedOptions.push_back(importExport);
2064 
2065  auto optNet = IOptimizedNetworkPtr(new IOptimizedNetwork(std::move(graph), optimizedOptions),
2066  &IOptimizedNetwork::Destroy);
2067 
2068  IOptimizedNetwork* optNetObjPtr = optNet.get();
2069 
2070  // Get the optimized graph
2071  Graph& optGraph = optNetObjPtr->pOptimizedNetworkImpl->GetGraph();
2072 
2073  if(options.GetShapeInferenceMethod() == ShapeInferenceMethod::InferAndValidate)
2074  {
2075  // Infer the tensor infos for all output slots. Throws an exception on failure
2076  optGraph.InferTensorInfos();
2077  }
2078 
2079  using namespace optimizations;
2080  // Substitute Max + Min with Bounded Relu before AddBroadcastReshapeLayer optimisation,
2081  // as Bounded ReLu needs the constants to be 1D size 1
2082  Optimizer::Pass(optGraph, MakeOptimizations(MaxMinIntoBoundedRelu()));
2083 
2084  // Perform BroadcastToOptimizationLayer before AddBroadcastReshapeLayer optimisation
2085  Optimizer::Pass(optGraph, MakeOptimizations(BroadcastToOptimizationLayer()));
2086 
2087  Optimizer::Pass(optGraph, MakeOptimizations(AddBroadcastReshapeLayer()));
2088 
2089  if(options.GetShapeInferenceMethod() == ShapeInferenceMethod::ValidateOnly)
2090  {
2091  // Validate the tensor infos for all output slots. Throws an exception on failure
2092  optGraph.InferTensorInfos();
2093  }
2094 
2095  // Initialize backend settings
2096  BackendSettings backendSettings(backendPreferences, deviceSpec);
2097  auto availablePreferredBackends = backendSettings.GetAvailablePreferredBackends();
2098  if (availablePreferredBackends.empty())
2099  {
2100  std::stringstream failureMsg;
2101  failureMsg << "None of the preferred backends " << backendPreferences
2102  << " are supported. Current platform provides " << backendSettings.m_SupportedBackends;
2103  ReportError(failureMsg.str(), messages);
2104  throw InvalidArgumentException(failureMsg.str());
2105  }
2106 
2107  // Create a map to temporarily hold initialized backend objects
2108  TensorHandleFactoryRegistry tensorHandleFactoryRegistry;
2109  BackendsMap backends = CreateSupportedBackends(tensorHandleFactoryRegistry, backendSettings);
2110  bool hasFp16 = CheckFp16Support(backends, availablePreferredBackends);
2111 
2112  bool reduceFp32ToFp16 = options.GetReduceFp32ToFp16();
2113  // If fp16 is supported on the backend and fastmath has been enabled and the model is a TfLite converted Fp16
2114  // model: enable turbo mode optimizations
2115  if (hasFp16 && CheckFastMathSupport(availablePreferredBackends, optimizedOptions) && IsTfLiteTurboModel(optGraph))
2116  {
2118  reduceFp32ToFp16 = true;
2119  }
2120  else
2121  {
2123  }
2124 
2125  // Group Constant Layer optimizations together where possible.
2126  // This is important as:
2127  // FusePermuteIntoConstantLayer must happen before FoldPadIntoDepthwiseConvolution2d and
2128  // FuseBatchNormIntoDepthwiseConvolution2D.
2129  Optimizer::Pass(optGraph, MakeOptimizations(FusePermuteIntoConstLayer()));
2130  // Perform optimisation passes
2131  Optimizer::Pass(optGraph, MakeOptimizations(SquashEqualPermuteSiblings(),
2136  MovePermuteUp(),
2137  MoveTransposeUp(),
2138  PermuteAsReshape(),
2151 
2152  const std::vector<BackendId> mappedGpuBackends = BackendRegistryInstance().GetMappedGpuBackends();
2153 
2154  // All or nothing Gpu backends cannot be used as fallback
2155  for (auto backend : mappedGpuBackends)
2156  {
2157  if (std::count(backendPreferences.begin(), backendPreferences.end(), backend)
2158  && (backendPreferences[0] != backend) &&
2159  (backendPreferences[0] != armnn::BackendId("GpuAcc")))
2160  {
2161  std::stringstream failureMsg;
2162  failureMsg << backend << " backend cannot be specified as fallback.";
2163  ReportError(failureMsg.str(), messages);
2164  throw InvalidArgumentException(failureMsg.str());
2165  }
2166  }
2167 
2168  std::vector<BackendId> amendedBackendPreferences = backendPreferences;
2169  std::unordered_set<BackendId> supportedBackends = armnn::BackendRegistryInstance().GetBackendIds();
2170  if (amendedBackendPreferences[0] == armnn::BackendId("GpuAcc"))
2171  {
2172  // Add mapped Gpu backends if not already there and GpuAcc is first backend requested
2173  for (auto backend : mappedGpuBackends)
2174  {
2175  if (!std::count(amendedBackendPreferences.begin(), amendedBackendPreferences.end(), backend))
2176  {
2177  amendedBackendPreferences.insert(amendedBackendPreferences.begin(), backend);
2178  }
2179  }
2180  }
2181 
2182  if (reduceFp32ToFp16 && hasFp16)
2183  {
2184  ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Optimizer_ReduceFp32ToFp16");
2185  Optimizer::Pass(optGraph, MakeOptimizations(Fp32NetworkToFp16Converter()));
2186  Optimizer::Pass(optGraph, MakeOptimizations(ConvertConstantsFloatToHalf()));
2187  }
2188  // Assign an available backend to each layer
2189  Graph::Iterator firstLayer = optGraph.begin();
2190  Graph::Iterator lastLayer = optGraph.end();
2191  OptimizationResult assignBackendsResult = AssignBackends(optNetObjPtr->pOptimizedNetworkImpl.get(),
2192  backendSettings,
2193  firstLayer,
2194  lastLayer,
2195  messages);
2196  if (assignBackendsResult.m_Error)
2197  {
2198  // Failed to assign a backend to each layer
2199  throw InvalidArgumentException("Failed to assign a backend to each layer");
2200  }
2201 
2202  Optimizer::Pass(optGraph, MakeOptimizations(OptimizeInverseConversionsFp16(),
2204 
2205  // Apply the backend-specific optimizations
2206  OptimizationResult backendOptimizationResult = ApplyBackendOptimizations(optNetObjPtr->pOptimizedNetworkImpl.get(),
2207  backendSettings,
2208  backends,
2209  options.GetModelOptions(),
2210  messages);
2211  if (backendOptimizationResult.m_Error)
2212  {
2213  // Failed to apply the backend-specific optimizations
2214  throw InvalidArgumentException("Failed to apply the backend-specific optimizations");
2215  }
2216 
2217  // Convert constants
2218  {
2219  ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Optimizer_ConvertConstants");
2220  Optimizer::Pass(optGraph, MakeOptimizations(ConvertConstantsFloatToHalf()));
2221  Optimizer::Pass(optGraph, MakeOptimizations(ConvertConstantsHalfToFloat()));
2222  }
2223 
2224  // This must occur after all topological changes to the graph and any redirection of variables
2225  // If the debug flag is set, then insert a DebugLayer after each layer
2226  // Doing this after applying the backend optimizations as they might have changed some layers
2227  if (options.GetDebugEnabled() && !options.GetDebugToFileEnabled())
2228  {
2229  Optimizer::Pass(optGraph, MakeOptimizations(InsertDebugLayer()));
2230  }
2231  else if (options.GetDebugToFileEnabled())
2232  {
2233  // Setup the output file path
2234  try
2235  {
2236 #if !defined(ARMNN_DISABLE_FILESYSTEM)
2237  auto result = armnnUtils::Filesystem::CreateDirectory("/ArmNNIntermediateLayerOutputs");
2238  ARMNN_LOG(info) << "Intermediate tensors will be written to: " << result;
2239 #endif
2240  Optimizer::Pass(optGraph, MakeOptimizations(InsertDebugToFileLayer()));
2241  }
2242  catch (const armnn::RuntimeException& e)
2243  {
2244  // If we cannot create the output directory then we'll issue a warning and continue.
2245  ARMNN_LOG(warning) << "Unable to print intermediate layer outputs : " << e.what();
2246  }
2247  }
2248 
2249  // Calculate the compatibility strategies for tensor handles
2250  OptimizationResult strategyResult = SelectTensorHandleStrategy(optGraph,
2251  backends,
2252  tensorHandleFactoryRegistry,
2253  options.GetImportEnabled(),
2254  options.GetExportEnabled(),
2255  messages);
2256 
2257  if (strategyResult.m_Error)
2258  {
2259  // Failed to apply the backend-specific optimizations
2260  return IOptimizedNetworkPtr(nullptr, &IOptimizedNetwork::Destroy);
2261  }
2262 
2263  // Based on the tensor handle strategy determined above, insert copy layers where required.
2264  {
2265  ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Optimizer_AddCompatibilityLayers");
2266  optGraph.AddCompatibilityLayers(backends, tensorHandleFactoryRegistry);
2267  }
2268 
2269  return optNet;
2270 }
2271 
2272 // Forwarding function to remain backward compatible with legacy OptimizerOptions
2274  const std::vector<BackendId>& backendPreferences,
2275  const IDeviceSpec& deviceSpec,
2276  const OptimizerOptions& options,
2277  Optional<std::vector<std::string>&> messages)
2278 {
2279  return Optimize(inNetwork,
2280  backendPreferences,
2281  deviceSpec,
2282  OptimizerOptionsOpaque(options),
2283  messages);
2284 }
2285 
2287  const std::vector<BackendId>& backendPreferences,
2288  const IDeviceSpec& deviceSpec,
2289  const OptimizerOptionsOpaque& options,
2290  Optional<std::vector<std::string>&> messages)
2291 {
2292  return Optimize(inNetwork.pNetworkImpl->GetGraph(),
2293  backendPreferences,
2294  deviceSpec,
2295  options,
2296  messages);
2297 }
2298 
2299 bool NetworkImpl::GetShapeInferenceMethod()
2300 {
2301  bool shapeInferenceMethod = false;
2302 
2303  ParseOptions(m_NetworkOptions, "ShapeInferenceMethod", [&](std::string name, const BackendOptions::Var& value)
2304  {
2305  if (name == "InferAndValidate")
2306  {
2307  shapeInferenceMethod |= value.AsBool();
2308  }
2309  });
2310  return shapeInferenceMethod;
2311 }
2312 
2313 bool NetworkImpl::GetAllowExpandedDims()
2314 {
2315  bool allowExpandedDims = false;
2316 
2317  ParseOptions(m_NetworkOptions, "AllowExpandedDims", [&](std::string name, const BackendOptions::Var& value)
2318  {
2319  if (name == "AllowExpandedDims")
2320  {
2321  allowExpandedDims |= value.AsBool();
2322  }
2323  });
2324  return allowExpandedDims;
2325 }
2326 
2327 NetworkImpl::NetworkImpl(const NetworkOptions& networkOptions)
2328 : m_NetworkOptions(networkOptions),
2329  m_Graph(std::make_unique<Graph>(GetShapeInferenceMethod(), GetAllowExpandedDims()))
2330 {}
2331 
2333 {
2334 }
2335 
2337 {
2338  m_Graph->Print();
2339  return Status::Success;
2340 }
2341 
2343 {
2344  return m_Graph->AddLayer<InputLayer>(id, name);
2345 }
2346 
2348  const char* name)
2349 {
2350  return m_Graph->AddLayer<BatchToSpaceNdLayer>(batchToSpaceNdDescriptor, name);
2351 }
2352 
2354 {
2355  return m_Graph->AddLayer<CastLayer>(name);
2356 }
2358  const char* name)
2359 {
2360  return m_Graph->AddLayer<ChannelShuffleLayer>(channelShuffleDescriptor, name);
2361 }
2362 
2364  const char* name)
2365 {
2366  return m_Graph->AddLayer<ComparisonLayer>(comparisonDescriptor, name);
2367 }
2368 
2370  const char* name)
2371 {
2372  return m_Graph->AddLayer<ElementwiseBinaryLayer>(elementwiseBinaryDesc, name);
2373 }
2374 
2376  const char* name)
2377 {
2378  return m_Graph->AddLayer<ElementwiseUnaryLayer>(elementwiseUnaryDescriptor, name);
2379 }
2380 
2382  const char* name)
2383 {
2384  return m_Graph->AddLayer<FillLayer>(fillDescriptor, name);
2385 }
2386 
2388  const char* name)
2389 {
2390  return m_Graph->AddLayer<FullyConnectedLayer>(fullyConnectedDescriptor, name);
2391 }
2392 
2394  const char* name)
2395 {
2396  return m_Graph->AddLayer<FusedLayer>(fusedDescriptor, name);
2397 }
2398 
2400  const char* name)
2401 {
2402  return m_Graph->AddLayer<ConcatLayer>(concatDescriptor, name);
2403 }
2404 
2406  const char* name)
2407 {
2408  return m_Graph->AddLayer<Convolution2dLayer>(convolution2dDescriptor, name);
2409 }
2410 
2412 {
2413  return m_Graph->AddLayer<ConvertFp16ToFp32Layer>(name);
2414 }
2415 
2417 {
2418  return m_Graph->AddLayer<ConvertFp32ToFp16Layer>(name);
2419 }
2420 
2422  const char* name)
2423 {
2424  return m_Graph->AddLayer<Convolution3dLayer>(convolution3dDescriptor, name);
2425 }
2426 
2428  const char* name)
2429 {
2430  return m_Graph->AddLayer<DepthToSpaceLayer>(depthToSpaceDescriptor, name);
2431 }
2432 
2434  const DepthwiseConvolution2dDescriptor& convolution2dDescriptor,
2435  const char* name)
2436 {
2437  return m_Graph->AddLayer<DepthwiseConvolution2dLayer>(convolution2dDescriptor, name);
2438 }
2439 
2441  const ConstTensor& anchors, const char* name)
2442 {
2443  const auto layer = m_Graph->AddLayer<DetectionPostProcessLayer>(descriptor, name);
2444 
2445  layer->m_Anchors = std::make_shared<ScopedTensorHandle>(anchors);
2446 
2447  return layer;
2448 }
2449 
2451  const char* name)
2452 {
2453  return m_Graph->AddLayer<PermuteLayer>(permuteDescriptor, name);
2454 }
2455 
2457  const char* name)
2458 {
2459  return m_Graph->AddLayer<Pooling2dLayer>(pooling2dDescriptor, name);
2460 }
2461 
2463  const char* name)
2464 {
2465  return m_Graph->AddLayer<Pooling3dLayer>(pooling3dDescriptor, name);
2466 }
2467 
2469  const char* name)
2470 {
2471  return m_Graph->AddLayer<ActivationLayer>(activationDescriptor, name);
2472 }
2473 
2475  const char* name)
2476 {
2477  return m_Graph->AddLayer<ArgMinMaxLayer>(argMinMaxDescriptor, name);
2478 }
2479 
2481 normalizationDescriptor,
2482  const char* name)
2483 {
2484  return m_Graph->AddLayer<NormalizationLayer>(normalizationDescriptor, name);
2485 }
2486 
2487 IConnectableLayer* NetworkImpl::AddSliceLayer(const SliceDescriptor& sliceDescriptor, const char* name)
2488 {
2489  return m_Graph->AddLayer<SliceLayer>(sliceDescriptor, name);
2490 }
2491 
2493  const char* name)
2494 {
2495  return m_Graph->AddLayer<SoftmaxLayer>(softmaxDescriptor, name);
2496 }
2497 
2499  const char* name)
2500 {
2501  return m_Graph->AddLayer<SplitterLayer>(splitterDescriptor, name);
2502 }
2503 
2505 {
2506  return m_Graph->AddLayer<MaximumLayer>(name);
2507 }
2508 
2510 {
2511  return m_Graph->AddLayer<MinimumLayer>(name);
2512 }
2513 
2515 {
2516  return m_Graph->AddLayer<AdditionLayer>(name);
2517 }
2518 
2520 {
2521  return m_Graph->AddLayer<MultiplicationLayer>(name);
2522 }
2523 
2525 {
2526  return m_Graph->AddLayer<OutputLayer>(id, name);
2527 }
2528 
2530  const ConstTensor& mean,
2531  const ConstTensor& variance,
2532  const ConstTensor& beta,
2533  const ConstTensor& gamma,
2534  const char* name)
2535 {
2536  const auto layer = m_Graph->AddLayer<BatchNormalizationLayer>(desc, name);
2537 
2538  layer->m_Mean = std::make_shared<ScopedTensorHandle>(mean);
2539  layer->m_Variance = std::make_shared<ScopedTensorHandle>(variance);
2540  layer->m_Beta = std::make_shared<ScopedTensorHandle>(beta);
2541  layer->m_Gamma = std::make_shared<ScopedTensorHandle>(gamma);
2542 
2543  return layer;
2544 }
2545 
2547 {
2548  return m_Graph->AddLayer<RankLayer>(name);
2549 }
2550 
2552  const char* name)
2553 {
2554  return m_Graph->AddLayer<ReduceLayer>(reduceDescriptor, name);
2555 }
2556 
2557 IConnectableLayer* NetworkImpl::AddResizeLayer(const ResizeDescriptor& resizeDescriptor, const char* name)
2558 {
2559  return m_Graph->AddLayer<ResizeLayer>(resizeDescriptor, name);
2560 }
2561 
2563 {
2564  return m_Graph->AddLayer<ShapeLayer>(name);
2565 }
2566 
2568  const char* name)
2569 {
2570  return m_Graph->AddLayer<InstanceNormalizationLayer>(desc, name);
2571 }
2572 
2574  const char* name)
2575 {
2576  return m_Graph->AddLayer<L2NormalizationLayer>(desc, name);
2577 }
2578 
2580  const char* name)
2581 {
2582  return m_Graph->AddLayer<LogSoftmaxLayer>(desc, name);
2583 }
2584 
2586 {
2587  auto layer = m_Graph->AddLayer<ConstantLayer>(name);
2588 
2589  layer->m_LayerOutput = std::make_shared<ScopedTensorHandle>(input);
2590 
2591  return layer;
2592 }
2593 
2595  const char* name)
2596 {
2597  return m_Graph->AddLayer<ReshapeLayer>(reshapeDescriptor, name);
2598 }
2599 
2601  const char* name)
2602 {
2603  return m_Graph->AddLayer<SpaceToBatchNdLayer>(spaceToBatchNdDescriptor, name);
2604 }
2605 
2607  const char* name)
2608 {
2609  return m_Graph->AddLayer<SpaceToDepthLayer>(spaceToDepthDescriptor, name);
2610 }
2611 
2613 {
2614  return m_Graph->AddLayer<FloorLayer>(name);
2615 }
2616 
2618  const LstmInputParams& params,
2619  const char* name)
2620 {
2621  const auto layer = m_Graph->AddLayer<LstmLayer>(descriptor, name);
2622 
2623  //Lstm Basic Parameters
2625  std::make_shared<ScopedTensorHandle>(*(params.m_InputToForgetWeights));
2626  layer->m_BasicParameters.m_InputToCellWeights =
2627  std::make_shared<ScopedTensorHandle>(*(params.m_InputToCellWeights));
2628  layer->m_BasicParameters.m_InputToOutputWeights =
2629  std::make_shared<ScopedTensorHandle>(*(params.m_InputToOutputWeights));
2630  layer->m_BasicParameters.m_RecurrentToForgetWeights =
2631  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToForgetWeights));
2632  layer->m_BasicParameters.m_RecurrentToCellWeights =
2633  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToCellWeights));
2634  layer->m_BasicParameters.m_RecurrentToOutputWeights =
2635  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToOutputWeights));
2636  layer->m_BasicParameters.m_ForgetGateBias =
2637  std::make_shared<ScopedTensorHandle>(*(params.m_ForgetGateBias));
2638  layer->m_BasicParameters.m_CellBias =
2639  std::make_shared<ScopedTensorHandle>(*(params.m_CellBias));
2640  layer->m_BasicParameters.m_OutputGateBias =
2641  std::make_shared<ScopedTensorHandle>(*(params.m_OutputGateBias));
2642 
2643  //Lstm Cifg parameters
2644  if(!descriptor.m_CifgEnabled)
2645  {
2646  if(params.m_InputToInputWeights == nullptr)
2647  {
2648  throw InvalidArgumentException("AddLstmLayer: Input To Input Weights cannot be NULL "
2649  "when CIFG is disabled.");
2650  }
2651  if(params.m_RecurrentToInputWeights == nullptr)
2652  {
2654  "AddLstmLayer: Recurrent To Input Weights cannot be NULL "
2655  "when CIFG is disabled.");
2656  }
2657  if(params.m_InputGateBias == nullptr)
2658  {
2659  throw InvalidArgumentException("AddLstmLayer: Input Gate Bias cannot be NULL "
2660  "when CIFG is disabled.");
2661  }
2662  layer->m_CifgParameters.m_InputToInputWeights =
2663  std::make_shared<ScopedTensorHandle>(*(params.m_InputToInputWeights));
2664  layer->m_CifgParameters.m_RecurrentToInputWeights =
2665  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToInputWeights));
2666  layer->m_CifgParameters.m_InputGateBias =
2667  std::make_shared<ScopedTensorHandle>(*(params.m_InputGateBias));
2668  }
2669 
2670  //Lstm projection parameters
2671  if(descriptor.m_ProjectionEnabled)
2672  {
2673  if(params.m_ProjectionWeights == nullptr)
2674  {
2675  throw InvalidArgumentException("AddLstmLayer: Projection Weights cannot be NULL "
2676  "when projection is enabled.");
2677  }
2678  layer->m_ProjectionParameters.m_ProjectionWeights =
2679  std::make_shared<ScopedTensorHandle>(*(params.m_ProjectionWeights));
2680  if(params.m_ProjectionBias != nullptr)
2681  {
2682  layer->m_ProjectionParameters.m_ProjectionBias =
2683  std::make_shared<ScopedTensorHandle>(*(params.m_ProjectionBias));
2684  }
2685  }
2686 
2687  //Lstm Peephole params
2688  if(descriptor.m_PeepholeEnabled)
2689  {
2690  if(!descriptor.m_CifgEnabled)
2691  {
2692  if(params.m_CellToInputWeights == nullptr)
2693  {
2694  throw InvalidArgumentException("AddLstmLayer: Cell To Input Weights cannot be NULL "
2695  "when Peephole is enabled and CIFG disabled.");
2696  }
2697 
2698  layer->m_PeepholeParameters.m_CellToInputWeights =
2699  std::make_shared<ScopedTensorHandle>(*(params.m_CellToInputWeights));
2700  }
2701 
2702  if(params.m_CellToForgetWeights == nullptr)
2703  {
2704  throw InvalidArgumentException("AddLstmLayer: Cell To Forget Weights cannot be NULL "
2705  "when Peephole is enabled.");
2706  }
2707  if(params.m_CellToOutputWeights == nullptr)
2708  {
2709  throw InvalidArgumentException("AddLstmLayer: Cell To Output Weights cannot be NULL "
2710  "when Peephole is enabled.");
2711  }
2712 
2713  layer->m_PeepholeParameters.m_CellToForgetWeights =
2714  std::make_shared<ScopedTensorHandle>(*(params.m_CellToForgetWeights));
2715  layer->m_PeepholeParameters.m_CellToOutputWeights =
2716  std::make_shared<ScopedTensorHandle>(*(params.m_CellToOutputWeights));
2717  }
2718 
2719  //Lstm Layer Normalization params
2720  if(descriptor.m_LayerNormEnabled)
2721  {
2722  if(!descriptor.m_CifgEnabled)
2723  {
2724  if(params.m_InputLayerNormWeights == nullptr)
2725  {
2726  throw InvalidArgumentException("AddLstmLayer: Input layer normalization weights cannot be NULL "
2727  "when layer normalization is enabled and CIFG disabled.");
2728  }
2729  layer->m_LayerNormParameters.m_InputLayerNormWeights =
2730  std::make_shared<ScopedTensorHandle>(*(params.m_InputLayerNormWeights));
2731  }
2732 
2733  if(params.m_ForgetLayerNormWeights == nullptr)
2734  {
2735  throw InvalidArgumentException("AddLstmLayer: Forget layer normalization weights cannot be NULL "
2736  "when layer normalization is enabled.");
2737  }
2738  if(params.m_CellLayerNormWeights == nullptr)
2739  {
2740  throw InvalidArgumentException("AddLstmLayer: Cell layer normalization weights cannot be NULL "
2741  "when layer normalization is enabled.");
2742  }
2743  if(params.m_OutputLayerNormWeights == nullptr)
2744  {
2745  throw InvalidArgumentException("AddLstmLayer: Output layer normalization weights cannot be NULL "
2746  "when layer normalization is enabled.");
2747  }
2748  layer->m_LayerNormParameters.m_ForgetLayerNormWeights =
2749  std::make_shared<ScopedTensorHandle>(*(params.m_ForgetLayerNormWeights));
2750  layer->m_LayerNormParameters.m_CellLayerNormWeights =
2751  std::make_shared<ScopedTensorHandle>(*(params.m_CellLayerNormWeights));
2752  layer->m_LayerNormParameters.m_OutputLayerNormWeights =
2753  std::make_shared<ScopedTensorHandle>(*(params.m_OutputLayerNormWeights));
2754  }
2755  return layer;
2756 }
2757 
2759 {
2760  return m_Graph->AddLayer<DivisionLayer>(name);
2761 }
2762 
2764 {
2765  return m_Graph->AddLayer<SubtractionLayer>(name);
2766 }
2767 
2768 IConnectableLayer* NetworkImpl::AddMeanLayer(const MeanDescriptor& meanDescriptor, const char* name)
2769 {
2770  return m_Graph->AddLayer<MeanLayer>(meanDescriptor,name);
2771 }
2772 
2773 IConnectableLayer* NetworkImpl::AddPadLayer(const PadDescriptor& padDescriptor, const char* name)
2774 {
2775  return m_Graph->AddLayer<PadLayer>(padDescriptor,name);
2776 }
2777 
2779 {
2780  return m_Graph->AddLayer<QuantizeLayer>(name);
2781 }
2782 
2784 {
2785  return m_Graph->AddLayer<DequantizeLayer>(name);
2786 }
2787 
2789  const char* name)
2790 {
2791  return m_Graph->AddLayer<StridedSliceLayer>(stridedSliceDescriptor, name);
2792 }
2793 
2795  const char* name)
2796 {
2797  return m_Graph->AddLayer<GatherLayer>(gatherDescriptor, name);
2798 }
2799 
2801 {
2802  return m_Graph->AddLayer<GatherNdLayer>(name);
2803 }
2804 
2806 {
2807  return m_Graph->AddLayer<MergeLayer>(name);
2808 }
2809 
2811 {
2812  return m_Graph->AddLayer<SwitchLayer>(name);
2813 }
2814 
2816 {
2817  return m_Graph->AddLayer<PreluLayer>(name);
2818 }
2819 
2821  const ConstTensor& weights,
2822  const Optional<ConstTensor>& biases,
2823  const char* name)
2824 {
2825  if (descriptor.m_BiasEnabled && !biases.has_value())
2826  {
2827  throw InvalidArgumentException("AddTransposeConvolution2dLayer: Biases cannot be empty");
2828  }
2829 
2830  const auto layer = m_Graph->AddLayer<TransposeConvolution2dLayer>(descriptor, name);
2831 
2832  layer->m_Weight = std::make_shared<ScopedTensorHandle>(weights);
2833 
2834  if (descriptor.m_BiasEnabled)
2835  {
2836  layer->m_Bias = std::make_shared<ScopedTensorHandle>(biases.value());
2837  }
2838 
2839  return layer;
2840 }
2841 
2843  const char* name)
2844 {
2845  return m_Graph->AddLayer<TransposeLayer>(transposeDescriptor, name);
2846 }
2847 
2849  const char* name)
2850 {
2851  return m_Graph->AddLayer<StackLayer>(stackDescriptor, name);
2852 }
2853 
2854 
2856  const char* name)
2857 {
2858  return m_Graph->AddLayer<StandInLayer>(desc, name);
2859 }
2860 
2862  const char* name)
2863 {
2864  const auto layer = m_Graph->AddLayer<QuantizedLstmLayer>(name);
2865 
2866  // InputToX weights
2868  std::make_shared<ScopedTensorHandle>(params.GetInputToInputWeights());
2869  layer->m_QuantizedLstmParameters.m_InputToForgetWeights =
2870  std::make_shared<ScopedTensorHandle>(params.GetInputToForgetWeights());
2871  layer->m_QuantizedLstmParameters.m_InputToCellWeights =
2872  std::make_shared<ScopedTensorHandle>(params.GetInputToCellWeights());
2873  layer->m_QuantizedLstmParameters.m_InputToOutputWeights =
2874  std::make_shared<ScopedTensorHandle>(params.GetInputToOutputWeights());
2875 
2876  // RecurrentToX weights
2877  layer->m_QuantizedLstmParameters.m_RecurrentToInputWeights =
2878  std::make_shared<ScopedTensorHandle>(params.GetRecurrentToInputWeights());
2879  layer->m_QuantizedLstmParameters.m_RecurrentToForgetWeights =
2880  std::make_shared<ScopedTensorHandle>(params.GetRecurrentToForgetWeights());
2881  layer->m_QuantizedLstmParameters.m_RecurrentToCellWeights =
2882  std::make_shared<ScopedTensorHandle>(params.GetRecurrentToCellWeights());
2883  layer->m_QuantizedLstmParameters.m_RecurrentToOutputWeights =
2884  std::make_shared<ScopedTensorHandle>(params.GetRecurrentToOutputWeights());
2885 
2886  // Bias
2887  layer->m_QuantizedLstmParameters.m_InputGateBias =
2888  std::make_shared<ScopedTensorHandle>(params.GetInputGateBias());
2889  layer->m_QuantizedLstmParameters.m_ForgetGateBias =
2890  std::make_shared<ScopedTensorHandle>(params.GetForgetGateBias());
2891  layer->m_QuantizedLstmParameters.m_CellBias =
2892  std::make_shared<ScopedTensorHandle>(params.GetCellBias());
2893  layer->m_QuantizedLstmParameters.m_OutputGateBias =
2894  std::make_shared<ScopedTensorHandle>(params.GetOutputGateBias());
2895 
2896  return layer;
2897 }
2898 
2900  const LstmInputParams& params,
2901  const char* name)
2902 {
2903  const auto layer = m_Graph->AddLayer<QLstmLayer>(descriptor, name);
2904 
2905  // QLstm Basic Parameters
2907  std::make_shared<ScopedTensorHandle>(*(params.m_InputToForgetWeights));
2908  layer->m_BasicParameters.m_InputToCellWeights =
2909  std::make_shared<ScopedTensorHandle>(*(params.m_InputToCellWeights));
2910  layer->m_BasicParameters.m_InputToOutputWeights =
2911  std::make_shared<ScopedTensorHandle>(*(params.m_InputToOutputWeights));
2912  layer->m_BasicParameters.m_RecurrentToForgetWeights =
2913  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToForgetWeights));
2914  layer->m_BasicParameters.m_RecurrentToCellWeights =
2915  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToCellWeights));
2916  layer->m_BasicParameters.m_RecurrentToOutputWeights =
2917  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToOutputWeights));
2918  layer->m_BasicParameters.m_ForgetGateBias =
2919  std::make_shared<ScopedTensorHandle>(*(params.m_ForgetGateBias));
2920  layer->m_BasicParameters.m_CellBias =
2921  std::make_shared<ScopedTensorHandle>(*(params.m_CellBias));
2922  layer->m_BasicParameters.m_OutputGateBias =
2923  std::make_shared<ScopedTensorHandle>(*(params.m_OutputGateBias));
2924 
2925  // QLstm Cifg parameters
2926  if(!descriptor.m_CifgEnabled)
2927  {
2928  if(params.m_InputToInputWeights == nullptr)
2929  {
2930  throw InvalidArgumentException("AddQLstmLayer: Input To Input Weights cannot be NULL");
2931  }
2932 
2933  if(params.m_RecurrentToInputWeights == nullptr)
2934  {
2936  "AddQLstmLayer: Recurrent To Input Weights cannot be NULL");
2937  }
2938 
2939  if(params.m_InputGateBias == nullptr)
2940  {
2941  throw InvalidArgumentException("AddQLstmLayer: Input Gate Bias cannot be NULL");
2942  }
2943 
2944  layer->m_CifgParameters.m_InputToInputWeights =
2945  std::make_shared<ScopedTensorHandle>(*(params.m_InputToInputWeights));
2946  layer->m_CifgParameters.m_RecurrentToInputWeights =
2947  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToInputWeights));
2948  layer->m_CifgParameters.m_InputGateBias =
2949  std::make_shared<ScopedTensorHandle>(*(params.m_InputGateBias));
2950  }
2951 
2952  // QLstm Projection parameters
2953  if(descriptor.m_ProjectionEnabled)
2954  {
2955  if(params.m_ProjectionWeights == nullptr)
2956  {
2957  throw InvalidArgumentException("AddQLstmLayer: Projection Weights cannot be NULL");
2958  }
2959 
2960  layer->m_ProjectionParameters.m_ProjectionWeights =
2961  std::make_shared<ScopedTensorHandle>(*(params.m_ProjectionWeights));
2962 
2963  // Projection bias is optional even if projection is enabled
2964  if(params.m_ProjectionBias != nullptr)
2965  {
2966  layer->m_ProjectionParameters.m_ProjectionBias =
2967  std::make_shared<ScopedTensorHandle>(*(params.m_ProjectionBias));
2968  }
2969 
2970  }
2971 
2972  // QLstm Peephole params
2973  if(descriptor.m_PeepholeEnabled)
2974  {
2975  if(params.m_CellToForgetWeights == nullptr)
2976  {
2977  throw InvalidArgumentException("AddQLstmLayer: Cell To Forget Weights cannot be NULL");
2978  }
2979 
2980  if(params.m_CellToOutputWeights == nullptr)
2981  {
2982  throw InvalidArgumentException("AddQLstmLayer: Cell To Output Weights cannot be NULL");
2983  }
2984 
2985  if(!descriptor.m_CifgEnabled)
2986  {
2987  if(params.m_CellToInputWeights == nullptr)
2988  {
2989  throw InvalidArgumentException("AddQLstmLayer: Cell To Input Weights cannot be NULL");
2990  }
2991 
2992  layer->m_PeepholeParameters.m_CellToInputWeights =
2993  std::make_shared<ScopedTensorHandle>(*(params.m_CellToInputWeights));
2994  }
2995 
2996  layer->m_PeepholeParameters.m_CellToForgetWeights =
2997  std::make_shared<ScopedTensorHandle>(*(params.m_CellToForgetWeights));
2998  layer->m_PeepholeParameters.m_CellToOutputWeights =
2999  std::make_shared<ScopedTensorHandle>(*(params.m_CellToOutputWeights));
3000  }
3001 
3002  // QLstm Layer Normalization params
3003  if(descriptor.m_LayerNormEnabled)
3004  {
3005  if(params.m_ForgetLayerNormWeights == nullptr)
3006  {
3007  throw InvalidArgumentException("AddQLstmLayer: Forget layer normalization weights cannot be NULL");
3008  }
3009 
3010  if(params.m_CellLayerNormWeights == nullptr)
3011  {
3012  throw InvalidArgumentException("AddQLstmLayer: Cell layer normalization weights cannot be NULL");
3013  }
3014 
3015  if(params.m_OutputLayerNormWeights == nullptr)
3016  {
3017  throw InvalidArgumentException("AddQLstmLayer: Output layer normalization weights cannot be NULL");
3018  }
3019 
3020  if(!descriptor.m_CifgEnabled)
3021  {
3022  if(params.m_InputLayerNormWeights == nullptr)
3023  {
3024  throw InvalidArgumentException("AddQLstmLayer: Input layer normalization weights cannot be NULL");
3025  }
3026 
3027  layer->m_LayerNormParameters.m_InputLayerNormWeights =
3028  std::make_shared<ScopedTensorHandle>(*(params.m_InputLayerNormWeights));
3029  }
3030 
3031  layer->m_LayerNormParameters.m_ForgetLayerNormWeights =
3032  std::make_shared<ScopedTensorHandle>(*(params.m_ForgetLayerNormWeights));
3033  layer->m_LayerNormParameters.m_CellLayerNormWeights =
3034  std::make_shared<ScopedTensorHandle>(*(params.m_CellLayerNormWeights));
3035  layer->m_LayerNormParameters.m_OutputLayerNormWeights =
3036  std::make_shared<ScopedTensorHandle>(*(params.m_OutputLayerNormWeights));
3037  }
3038  return layer;
3039 }
3040 
3042  const char* name)
3043 {
3044  return m_Graph->AddLayer<LogicalBinaryLayer>(logicalBinaryDescriptor, name);
3045 }
3046 
3048  const UnidirectionalSequenceLstmDescriptor& descriptor,
3049  const LstmInputParams& params,
3050  const char* name)
3051 {
3052  const auto layer = m_Graph->AddLayer<UnidirectionalSequenceLstmLayer>(descriptor, name);
3053 
3054  //Lstm Basic Parameters
3056  std::make_shared<ScopedTensorHandle>(*(params.m_InputToForgetWeights));
3057  layer->m_BasicParameters.m_InputToCellWeights =
3058  std::make_shared<ScopedTensorHandle>(*(params.m_InputToCellWeights));
3059  layer->m_BasicParameters.m_InputToOutputWeights =
3060  std::make_shared<ScopedTensorHandle>(*(params.m_InputToOutputWeights));
3061  layer->m_BasicParameters.m_RecurrentToForgetWeights =
3062  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToForgetWeights));
3063  layer->m_BasicParameters.m_RecurrentToCellWeights =
3064  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToCellWeights));
3065  layer->m_BasicParameters.m_RecurrentToOutputWeights =
3066  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToOutputWeights));
3067  layer->m_BasicParameters.m_ForgetGateBias =
3068  std::make_shared<ScopedTensorHandle>(*(params.m_ForgetGateBias));
3069  layer->m_BasicParameters.m_CellBias =
3070  std::make_shared<ScopedTensorHandle>(*(params.m_CellBias));
3071  layer->m_BasicParameters.m_OutputGateBias =
3072  std::make_shared<ScopedTensorHandle>(*(params.m_OutputGateBias));
3073 
3074  //Lstm Cifg parameters
3075  if(!descriptor.m_CifgEnabled)
3076  {
3077  if(params.m_InputToInputWeights == nullptr)
3078  {
3079  throw InvalidArgumentException("AddUnidirectionalSequenceLstmLayer: Input To Input Weights cannot be NULL "
3080  "when CIFG is disabled.");
3081  }
3082  if(params.m_RecurrentToInputWeights == nullptr)
3083  {
3085  "AddUnidirectionalSequenceLstmLayer: Recurrent To Input Weights cannot be NULL "
3086  "when CIFG is disabled.");
3087  }
3088  if(params.m_InputGateBias == nullptr)
3089  {
3090  throw InvalidArgumentException("AddUnidirectionalSequenceLstmLayer: Input Gate Bias cannot be NULL "
3091  "when CIFG is disabled.");
3092  }
3093  layer->m_CifgParameters.m_InputToInputWeights =
3094  std::make_shared<ScopedTensorHandle>(*(params.m_InputToInputWeights));
3095  layer->m_CifgParameters.m_RecurrentToInputWeights =
3096  std::make_shared<ScopedTensorHandle>(*(params.m_RecurrentToInputWeights));
3097  layer->m_CifgParameters.m_InputGateBias =
3098  std::make_shared<ScopedTensorHandle>(*(params.m_InputGateBias));
3099  }
3100 
3101  //Lstm projection parameters
3102  if(descriptor.m_ProjectionEnabled)
3103  {
3104  if(params.m_ProjectionWeights == nullptr)
3105  {
3106  throw InvalidArgumentException("AddUnidirectionalSequenceLstmLayer: Projection Weights cannot be NULL "
3107  "when projection is enabled.");
3108  }
3109  layer->m_ProjectionParameters.m_ProjectionWeights =
3110  std::make_shared<ScopedTensorHandle>(*(params.m_ProjectionWeights));
3111  if(params.m_ProjectionBias != nullptr)
3112  {
3113  layer->m_ProjectionParameters.m_ProjectionBias =
3114  std::make_shared<ScopedTensorHandle>(*(params.m_ProjectionBias));
3115  }
3116  }
3117 
3118  //Lstm Peephole params
3119  if(descriptor.m_PeepholeEnabled)
3120  {
3121  if(!descriptor.m_CifgEnabled)
3122  {
3123  if(params.m_CellToInputWeights == nullptr)
3124  {
3125  throw InvalidArgumentException("AddUnidirectionalSequenceLstmLayer: Cell To Input Weights "
3126  "cannot be NULL when Peephole is enabled and CIFG disabled.");
3127  }
3128 
3129  layer->m_PeepholeParameters.m_CellToInputWeights =
3130  std::make_shared<ScopedTensorHandle>(*(params.m_CellToInputWeights));
3131  }
3132 
3133  if(params.m_CellToForgetWeights == nullptr)
3134  {
3135  throw InvalidArgumentException("AddUnidirectionalSequenceLstmLayer: Cell To Forget Weights cannot be NULL "
3136  "when Peephole is enabled.");
3137  }
3138  if(params.m_CellToOutputWeights == nullptr)
3139  {
3140  throw InvalidArgumentException("AddUnidirectionalSequenceLstmLayer: Cell To Output Weights cannot be NULL "
3141  "when Peephole is enabled.");
3142  }
3143 
3144  layer->m_PeepholeParameters.m_CellToForgetWeights =
3145  std::make_shared<ScopedTensorHandle>(*(params.m_CellToForgetWeights));
3146  layer->m_PeepholeParameters.m_CellToOutputWeights =
3147  std::make_shared<ScopedTensorHandle>(*(params.m_CellToOutputWeights));
3148  }
3149 
3150  //Lstm Layer Normalization params
3151  if(descriptor.m_LayerNormEnabled)
3152  {
3153  if(!descriptor.m_CifgEnabled)
3154  {
3155  if(params.m_InputLayerNormWeights == nullptr)
3156  {
3157  throw InvalidArgumentException("AddUnidirectionalSequenceLstmLayer: Input layer normalization weights "
3158  "cannot be NULL when layer normalization is enabled and CIFG disabled.");
3159  }
3160  layer->m_LayerNormParameters.m_InputLayerNormWeights =
3161  std::make_shared<ScopedTensorHandle>(*(params.m_InputLayerNormWeights));
3162  }
3163 
3164  if(params.m_ForgetLayerNormWeights == nullptr)
3165  {
3166  throw InvalidArgumentException("AddUnidirectionalSequenceLstmLayer: Forget layer normalization weights "
3167  "cannot be NULL when layer normalization is enabled.");
3168  }
3169  if(params.m_CellLayerNormWeights == nullptr)
3170  {
3171  throw InvalidArgumentException("AddUnidirectionalSequenceLstmLayer: Cell layer normalization weights "
3172  "cannot be NULL when layer normalization is enabled.");
3173  }
3174  if(params.m_OutputLayerNormWeights == nullptr)
3175  {
3176  throw InvalidArgumentException("AddUnidirectionalSequenceLstmLayer: Output layer normalization weights "
3177  "cannot be NULL when layer normalization is enabled.");
3178  }
3179  layer->m_LayerNormParameters.m_ForgetLayerNormWeights =
3180  std::make_shared<ScopedTensorHandle>(*(params.m_ForgetLayerNormWeights));
3181  layer->m_LayerNormParameters.m_CellLayerNormWeights =
3182  std::make_shared<ScopedTensorHandle>(*(params.m_CellLayerNormWeights));
3183  layer->m_LayerNormParameters.m_OutputLayerNormWeights =
3184  std::make_shared<ScopedTensorHandle>(*(params.m_OutputLayerNormWeights));
3185  }
3186  return layer;
3187 }
3188 
3190 {
3191  return m_Graph->AddLayer<BatchMatMulLayer>(desc, name);
3192 }
3193 
3195 {
3196  return m_Graph->AddLayer<ReverseV2Layer>(name);
3197 }
3198 
3200 {
3201  return m_Graph->AddLayer<TileLayer>(desc, name);
3202 }
3203 
3205  CompiledBlobPtr compiledBlobPtr,
3206  const Optional<BackendId>& backend,
3207  const char* name)
3208 {
3209  // Method use is for backend users.
3210  PreCompiledLayer* layer;
3211  if (name)
3212  {
3213  layer = m_Graph->AddLayer<PreCompiledLayer>(preCompiledDescriptor, name);
3214  }
3215  else
3216  {
3217  layer = m_Graph->AddLayer<PreCompiledLayer>(preCompiledDescriptor, "pre-compiled");
3218  }
3219 
3220  // Assign the pre-compiled object to layer
3221  // Pass only one compiled network, Arm NN does not handle multiple
3222  // pre-compiled objects in a single pre-compiled layer currently
3223  layer->SetPreCompiledObject(std::move(compiledBlobPtr));
3224 
3225  if (backend.has_value())
3226  {
3227  layer->SetBackendId(backend.value());
3228  }
3229  else if (layer->GetBackendHint().has_value())
3230  {
3231  layer->SetBackendId(layer->GetBackendHint().value());
3232  }
3233 
3234  return layer;
3235 }
3236 
3238 {
3239  return m_Graph->AddLayer<BroadcastToLayer>(desc, name);
3240 }
3241 
3243 {
3244  return m_Graph->AddLayer<ScatterNdLayer>(desc, name);
3245 }
3246 
3248 {
3249  for (auto layer : GetGraph())
3250  {
3251  layer->ExecuteStrategy(strategy);
3252  };
3253 }
3254 
3256  : m_Graph(new Graph(*other.m_Graph.get()))
3257  , m_Guid(arm::pipe::IProfilingService::GetNextGuid())
3258  , m_ModelOptions(modelOptions)
3259 {
3260 }
3261 
3262 OptimizedNetworkImpl::OptimizedNetworkImpl(std::unique_ptr<Graph> graph)
3263  : m_Graph(std::move(graph)), m_Guid(arm::pipe::IProfilingService::GetNextGuid())
3264 {
3265 }
3266 
3267 OptimizedNetworkImpl::OptimizedNetworkImpl(std::unique_ptr<Graph> graph, const ModelOptions& modelOptions)
3268  : m_Graph(std::move(graph)), m_Guid(arm::pipe::IProfilingService::GetNextGuid()), m_ModelOptions(modelOptions)
3269 {
3270 }
3271 
3273 {
3274 }
3275 
3277 {
3278  pOptimizedNetworkImpl->ExecuteStrategy(strategy);
3279 }
3280 
3282 {
3283  for (auto layer : GetGraph())
3284  {
3285  layer->ExecuteStrategy(strategy);
3286  };
3287 }
3288 
3289 } // namespace armnn
#define ARMNN_NO_DEPRECATE_WARN_BEGIN
Definition: Deprecated.hpp:33
#define ARMNN_NO_DEPRECATE_WARN_END
Definition: Deprecated.hpp:34
#define ARMNN_LOG(severity)
Definition: Logging.hpp:212
#define ARMNN_SCOPED_PROFILING_EVENT(backendId, name)
Definition: Profiling.hpp:220
This layer represents an activation operation with the specified activation function.
This layer represents an addition operation.
This layer represents a ArgMinMax operation.
const std::string & Get() const
Definition: BackendId.hpp:138
Very basic type safe variant.
bool AsBool() const
Value getters.
BackendIdSet GetBackendIds() const
BackendIdVector GetMappedGpuBackends()
This layer represents a batch normalization operation.
std::shared_ptr< ConstTensorHandle > m_Mean
A unique pointer to store Mean values.
This layer represents a BatchToSpaceNd operation.
This layer represents a cast operation.
Definition: CastLayer.hpp:15
This layer represents a comparison operation.
This layer represents a merge operation.
Definition: ConcatLayer.hpp:14
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:330
A layer that the constant data can be bound to.
std::shared_ptr< ConstTensorHandle > m_LayerOutput
This layer converts data type Float 16 to Float 32.
This layer converts data type Float 32 to Float 16.
This layer represents a convolution 2d operation.
This layer represents a convolution 3d operation.
This layer represents a DepthToSpace operation.
This layer represents a depthwise convolution 2d operation.
This layer dequantizes the input tensor.
This layer represents a detection postprocess operator.
std::shared_ptr< ConstTensorHandle > m_Anchors
A unique pointer to store Anchor values.
This layer represents a division operation.
This layer represents a elementwiseBinary operation.
This layer represents a elementwiseUnary operation.
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:47
virtual const char * what() const noexcept override
Definition: Exceptions.cpp:32
This layer represents a fill operation.
Definition: FillLayer.hpp:14
This layer represents a floor operation.
Definition: FloorLayer.hpp:14
This layer represents a fully connected operation.
This layer represents a Gather operator.
Definition: GatherLayer.hpp:15
This layer represents a GatherNd operator.
Iterator begin()
Returns iterator pointing to the beginning of the list. Lowercase for range-based for loops.
Definition: Graph.hpp:176
void InferTensorInfos()
Definition: Graph.cpp:645
void VerifyConstantLayerSetTensorInfo() const
For each ConstantLayer in Graph, ensures TensorInfo is set on all output slots.
Definition: Graph.cpp:622
const std::shared_ptr< IProfiler > & GetProfiler() const
Definition: Graph.cpp:733
void EraseLayer(Iterator pos)
Deletes the layer at the specified position.
Definition: Graph.hpp:517
void SubstituteSubgraph(SubgraphView &subgraph, IConnectableLayer *substituteLayer)
Substitutes the given sub-graph with either a new layer or a new sub-graph.
Definition: Graph.cpp:475
Iterator end()
Returns iterator pointing to the end of the list. Lowercase for range-based for loops.
Definition: Graph.hpp:178
LayerList::const_iterator Iterator
Definition: Graph.hpp:53
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:330
void ForEachLayer(Func func) const
Definition: Graph.hpp:40
virtual std::vector< ITensorHandleFactory::FactoryId > GetHandleFactoryPreferences() const
(Optional) Returns a vector of supported TensorHandleFactory ids in preference order.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
Definition: INetwork.hpp:81
Device specific knowledge to be passed to the optimizer.
Definition: Types.hpp:302
Main network class which provides the interface for building up a neural network.
Definition: INetwork.hpp:348
IConnectableLayer * AddFusedLayer(const FusedDescriptor &fusedDescriptor, const char *name=nullptr)
Adds a Fused layer to the network.
Definition: Network.cpp:338
IConnectableLayer * AddElementwiseUnaryLayer(const ElementwiseUnaryDescriptor &elementwiseUnaryDescriptor, const char *name=nullptr)
Add an ElementwiseUnary layer to the network.
Definition: Network.cpp:320
IConnectableLayer * AddLstmLayer(const LstmDescriptor &descriptor, const LstmInputParams &params, const char *name=nullptr)
Add a Lstm layer to the network.
Definition: Network.cpp:501
IConnectableLayer * AddDivisionLayer(const char *name=nullptr)
Adds a division layer to the network.
Definition: Network.cpp:508
IConnectableLayer * AddQuantizeLayer(const char *name=nullptr)
Add a quantize layer to the network.
Definition: Network.cpp:540
IConnectableLayer * AddMergeLayer(const char *name=nullptr)
Adds a merge layer to the network.
Definition: Network.cpp:404
IConnectableLayer * AddPermuteLayer(const PermuteDescriptor &permuteDescriptor, const char *name=nullptr)
Adds a permute layer to the network.
Definition: Network.cpp:344
IConnectableLayer * AddSpaceToDepthLayer(const SpaceToDepthDescriptor &spaceToDepthDescriptor, const char *name=nullptr)
Adds a space to depth layer to the network.
Definition: Network.cpp:486
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:468
IConnectableLayer * AddGatherLayer(const GatherDescriptor &descriptor, const char *name=nullptr)
Add Gather layer to the network.
Definition: Network.cpp:558
IConnectableLayer * AddRankLayer(const char *name=nullptr)
Adds a rank layer to the network.
Definition: Network.cpp:433
IConnectableLayer * AddSwitchLayer(const char *name=nullptr)
Adds a switch layer to the network.
Definition: Network.cpp:569
IConnectableLayer * AddQLstmLayer(const QLstmDescriptor &descriptor, const LstmInputParams &params, const char *name=nullptr)
Add a QLstm layer to the network.
Definition: Network.cpp:616
INetwork(NetworkOptions networkOptions={})
Definition: Network.cpp:45
IConnectableLayer * AddSoftmaxLayer(const SoftmaxDescriptor &softmaxDescriptor, const char *name=nullptr)
Adds a softmax layer to the network.
Definition: Network.cpp:392
IConnectableLayer * AddDequantizeLayer(const char *name=nullptr)
Adds a Dequantize layer to the network.
Definition: Network.cpp:300
IConnectableLayer * AddBroadcastToLayer(const BroadcastToDescriptor &descriptor, const char *name=nullptr)
Add a BroadcastTo layer to the network.
Definition: Network.cpp:660
IConnectableLayer * AddConvolution2dLayer(const Convolution2dDescriptor &convolution2dDescriptor, const char *name=nullptr)
Adds a 2D convolution layer to the network.
Definition: Network.cpp:272
IConnectableLayer * AddAdditionLayer(const char *name=nullptr)
Adds an addition layer to the network.
Definition: Network.cpp:409
IConnectableLayer * AddQuantizedLstmLayer(const QuantizedLstmInputParams &params, const char *name=nullptr)
Add a QuantizedLstm layer to the network.
Definition: Network.cpp:610
static INetworkPtr Create(const NetworkOptions &networkOptions={})
Definition: Network.cpp:682
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:579
std::unique_ptr< NetworkImpl > pNetworkImpl
Definition: INetwork.hpp:895
IConnectableLayer * AddFloorLayer(const char *name=nullptr)
Adds a floor layer to the network.
Definition: Network.cpp:492
IConnectableLayer * AddConvolution3dLayer(const Convolution3dDescriptor &convolution3dDescriptor, const char *name=nullptr)
Adds a 3D convolution layer to the network.
Definition: Network.cpp:278
IConnectableLayer * AddFullyConnectedLayer(const FullyConnectedDescriptor &fullyConnectedDescriptor, const char *name=nullptr)
Adds a fully connected layer to the network.
Definition: Network.cpp:332
IConnectableLayer * AddMinimumLayer(const char *name=nullptr)
Add a Minimum layer to the network.
Definition: Network.cpp:551
IConnectableLayer * AddStackLayer(const StackDescriptor &descriptor, const char *name=nullptr)
Adds a stack layer to the network.
Definition: Network.cpp:598
static void Destroy(INetwork *network)
Definition: Network.cpp:687
IConnectableLayer * AddMaximumLayer(const char *name=nullptr)
Add a Maximum layer to the network.
Definition: Network.cpp:522
IConnectableLayer * AddNormalizationLayer(const NormalizationDescriptor &normalizationDescriptor, const char *name=nullptr)
Adds a normalization layer to the network.
Definition: Network.cpp:382
IConnectableLayer * AddPreluLayer(const char *name=nullptr)
Adds a PReLU layer to the network.
Definition: Network.cpp:574
IConnectableLayer * AddPadLayer(const PadDescriptor &padDescriptor, const char *name=nullptr)
Adds a fully pad layer to the network.
Definition: Network.cpp:534
IConnectableLayer * AddSplitterLayer(const ViewsDescriptor &splitterDescriptor, const char *name=nullptr)
Adds a splitter layer to the network.
Definition: Network.cpp:398
void ExecuteStrategy(IStrategy &strategy) const
Definition: Network.cpp:672
IConnectableLayer * AddSpaceToBatchNdLayer(const SpaceToBatchNdDescriptor &spaceToBatchNdDescriptor, const char *name=nullptr)
Adds a space to batch layer to the network.
Definition: Network.cpp:480
IConnectableLayer * AddCastLayer(const char *name=nullptr)
Adds a cast layer to the network.
Definition: Network.cpp:253
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:604
IConnectableLayer * AddChannelShuffleLayer(const ChannelShuffleDescriptor &descriptor, const char *name=nullptr)
Add a ChannelShuffle layer to the network.
Definition: Network.cpp:637
IConnectableLayer * AddLogicalBinaryLayer(const LogicalBinaryDescriptor &descriptor, const char *name=nullptr)
Adds a Logical Binary layer to the network.
Definition: Network.cpp:623
IConnectableLayer * AddLogSoftmaxLayer(const LogSoftmaxDescriptor &logSoftmaxDescriptor, const char *name=nullptr)
Adds a log softmax layer to the network.
Definition: Network.cpp:462
IConnectableLayer * AddReshapeLayer(const ReshapeDescriptor &reshapeDescriptor, const char *name=nullptr)
Adds a reshape layer to the network.
Definition: Network.cpp:474
IConnectableLayer * AddSliceLayer(const SliceDescriptor &sliceDescriptor, const char *name=nullptr)
Adds a slice layer to the network.
Definition: Network.cpp:388
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:423
IConnectableLayer * AddBatchToSpaceNdLayer(const BatchToSpaceNdDescriptor &batchToSpaceNdDescriptor, const char *name=nullptr)
Adds a batch to space ND layer to the network.
Definition: Network.cpp:350
IConnectableLayer * AddActivationLayer(const ActivationDescriptor &activationDescriptor, const char *name=nullptr)
Adds an activation layer to the network.
Definition: Network.cpp:376
IConnectableLayer * AddInputLayer(LayerBindingId id, const char *name=nullptr)
Adds an input layer to the network.
Definition: Network.cpp:242
IConnectableLayer * AddElementwiseBinaryLayer(const ElementwiseBinaryDescriptor &elementwiseBinaryDescriptor, const char *name=nullptr)
Add an ElementwiseBinary layer to the network.
Definition: Network.cpp:314
IConnectableLayer * AddL2NormalizationLayer(const L2NormalizationDescriptor &desc, const char *name=nullptr)
Adds an L2 normalization layer to the network.
Definition: Network.cpp:456
IConnectableLayer * AddTransposeLayer(const TransposeDescriptor &transposeDescriptor, const char *name=nullptr)
Adds a transpose layer to the network.
Definition: Network.cpp:587
static INetwork * CreateRaw(const NetworkOptions &networkOptions={})
Definition: Network.cpp:677
IConnectableLayer * AddUnidirectionalSequenceLstmLayer(const UnidirectionalSequenceLstmDescriptor &descriptor, const LstmInputParams &params, const char *name=nullptr)
Add a UnidirectionalSequenceLstm layer to the network.
Definition: Network.cpp:629
IConnectableLayer * AddMultiplicationLayer(const char *name=nullptr)
Adds a multiplication layer to the network.
Definition: Network.cpp:416
IConnectableLayer * AddInstanceNormalizationLayer(const InstanceNormalizationDescriptor &desc, const char *name=nullptr)
Adds an instance normalization layer to the network.
Definition: Network.cpp:450
IConnectableLayer * AddDetectionPostProcessLayer(const DetectionPostProcessDescriptor &descriptor, const ConstTensor &anchors, const char *name=nullptr)
Adds a Detection PostProcess layer to the network.
Definition: Network.cpp:306
IConnectableLayer * AddStridedSliceLayer(const StridedSliceDescriptor &stridedSliceDescriptor, const char *name=nullptr)
Adds a strided slice layer to the network.
Definition: Network.cpp:545
IConnectableLayer * AddTileLayer(const TileDescriptor &descriptor, const char *name=nullptr)
Add a Tile layer to the network.
Definition: Network.cpp:654
IConnectableLayer * AddDepthwiseConvolution2dLayer(const DepthwiseConvolution2dDescriptor &convolution2dDescriptor, const char *name=nullptr)
Adds a 2D depthwise convolution layer to the network.
Definition: Network.cpp:292
IConnectableLayer * AddComparisonLayer(const ComparisonDescriptor &comparisonDescriptor, const char *name=nullptr)
Add a Comparison layer to the network.
Definition: Network.cpp:258
IConnectableLayer * AddMeanLayer(const MeanDescriptor &meanDescriptor, const char *name=nullptr)
Add a Mean layer to the network.
Definition: Network.cpp:529
IConnectableLayer * AddResizeLayer(const ResizeDescriptor &resizeDescriptor, const char *name=nullptr)
Adds a resize layer to the network.
Definition: Network.cpp:438
IConnectableLayer * AddArgMinMaxLayer(const ArgMinMaxDescriptor &desc, const char *name=nullptr)
Adds an ArgMinMax layer to the network.
Definition: Network.cpp:247
IConnectableLayer * AddReduceLayer(const ReduceDescriptor &reduceDescriptor, const char *name=nullptr)
Adds a reduce layer to the network.
Definition: Network.cpp:444
IConnectableLayer * AddPooling2dLayer(const Pooling2dDescriptor &pooling2dDescriptor, const char *name=nullptr)
Adds a 2D pooling layer to the network.
Definition: Network.cpp:356
IConnectableLayer * AddConcatLayer(const ConcatDescriptor &concatDescriptor, const char *name=nullptr)
Adds a concatenation layer to the network.
Definition: Network.cpp:265
IConnectableLayer * AddBatchMatMulLayer(const BatchMatMulDescriptor &descriptor, const char *name=nullptr)
Add a BatchMatMul layer to the network.
Definition: Network.cpp:643
IConnectableLayer * AddPooling3dLayer(const Pooling3dDescriptor &pooling3dDescriptor, const char *name=nullptr)
Adds a 3D pooling layer to the network.
Definition: Network.cpp:362
IConnectableLayer * AddPrecompiledLayer(const PreCompiledDescriptor &preCompiledDescriptor, CompiledBlobPtr compiledBlobPtr, const Optional< BackendId > &backend, const char *name=nullptr)
Adds a Precompiled layer to the network.
Definition: Network.cpp:368
IConnectableLayer * AddSubtractionLayer(const char *name=nullptr)
Adds a subtraction layer to the network.
Definition: Network.cpp:515
IConnectableLayer * AddDepthToSpaceLayer(const DepthToSpaceDescriptor &depthToSpaceDescriptor, const char *name=nullptr)
Adds a depth to space layer to the network.
Definition: Network.cpp:285
IConnectableLayer * AddOutputLayer(LayerBindingId id, const char *name=nullptr)
Adds an output layer to the network.
Definition: Network.cpp:496
IConnectableLayer * AddReverseV2Layer(const char *name=nullptr)
Add a ReverseV2 layer to the network.
Definition: Network.cpp:649
IConnectableLayer * AddGatherNdLayer(const char *name=nullptr)
Add GatherNd layer to the network.
Definition: Network.cpp:564
IConnectableLayer * AddShapeLayer(const char *name=nullptr)
Adds a shape layer to the network.
Definition: Network.cpp:593
IConnectableLayer * AddFillLayer(const FillDescriptor &fillDescriptor, const char *name=nullptr)
Add an Fill layer to the network.
Definition: Network.cpp:326
IConnectableLayer * AddScatterNdLayer(const ScatterNdDescriptor &descriptor, const char *name=nullptr)
Add a ScatterNd layer to the network.
Definition: Network.cpp:666
Status PrintGraph()
Definition: Network.cpp:237
Status SerializeToDot(std::ostream &stream) const
Definition: Network.cpp:716
IOptimizedNetwork(const IOptimizedNetwork &other, const ModelOptions &modelOptions)
Creates a copy of the IOptimizedNetwork.
Definition: Network.cpp:692
std::unique_ptr< OptimizedNetworkImpl > pOptimizedNetworkImpl
Definition: INetwork.hpp:944
static void Destroy(IOptimizedNetwork *network)
Definition: Network.cpp:706
size_t GetNumOutputs() const
Definition: Network.cpp:736
void ExecuteStrategy(IStrategy &strategy) const
Definition: Network.cpp:3276
const std::shared_ptr< IProfiler > & GetProfiler() const
Definition: Network.cpp:721
size_t GetNumInputs() const
Definition: Network.cpp:731
arm::pipe::ProfilingGuid GetGuid() const
Definition: Network.cpp:726
virtual std::vector< Capability > GetCapabilities(const IConnectableLayer *layer, const IConnectableLayer *connectedLayer, CapabilityClass capabilityClass)
virtual MemorySourceFlags GetExportFlags() const
static const FactoryId LegacyFactoryId
virtual MemorySourceFlags GetImportFlags() const
static const FactoryId DeferredFactoryId
Use the workload factory to create the tensor handle.
virtual bool SupportsMapUnmap() const
static bool IsLayerSupported(const BackendId &backendId, const IConnectableLayer &layer, Optional< DataType > dataType, std::string &outReasonIfUnsupported)
A layer user-provided data can be bound to (e.g. inputs, outputs).
Definition: InputLayer.hpp:14
const OutputSlot * GetConnectedOutputSlot() const
Definition: Layer.hpp:56
This layer represents an instance normalization operation.
This layer represents a L2 normalization operation.
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:339
unsigned int GetNumOutputSlots() const override
Returns the number of connectable output slots.
Definition: Layer.hpp:335
void SetBackendId(const BackendId &id) override
Set the backend of the IConnectableLayer.
Definition: Layer.hpp:291
Optional< BackendId > GetBackendHint() const
Definition: Layer.hpp:355
unsigned int GetNumInputSlots() const override
Returns the number of connectable input slots.
Definition: Layer.hpp:334
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:337
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition: Layer.hpp:286
const std::vector< InputSlot > & GetInputSlots() const
Definition: Layer.hpp:258
const BackendId & GetBackendId() const
Definition: Layer.hpp:290
This layer represents a log softmax operation.
This layer represents a Logical Binary operation.
This layer represents a LSTM operation.
Definition: LstmLayer.hpp:17
LstmBasicParameters m_BasicParameters
Definition: LstmLayer.hpp:20
This layer represents a maximum operation.
This layer represents a mean operation.
Definition: MeanLayer.hpp:15
This layer dequantizes the input tensor.
Definition: MergeLayer.hpp:14
This layer represents a minimum operation.
This layer represents a multiplication operation.
Private implementation of INetwork.
Definition: Network.hpp:33
IConnectableLayer * AddFusedLayer(const FusedDescriptor &fusedDescriptor, const char *name=nullptr)
Definition: Network.cpp:2393
IConnectableLayer * AddElementwiseUnaryLayer(const ElementwiseUnaryDescriptor &elementwiseUnaryDescriptor, const char *name=nullptr)
Definition: Network.cpp:2375
IConnectableLayer * AddLstmLayer(const LstmDescriptor &descriptor, const LstmInputParams &params, const char *name=nullptr)
Definition: Network.cpp:2617
IConnectableLayer * AddDivisionLayer(const char *name=nullptr)
Definition: Network.cpp:2758
IConnectableLayer * AddQuantizeLayer(const char *name=nullptr)
Definition: Network.cpp:2778
IConnectableLayer * AddMergeLayer(const char *name=nullptr)
Definition: Network.cpp:2805
IConnectableLayer * AddPermuteLayer(const PermuteDescriptor &permuteDescriptor, const char *name=nullptr)
Definition: Network.cpp:2450
IConnectableLayer * AddSpaceToDepthLayer(const SpaceToDepthDescriptor &spaceToDepthDescriptor, const char *name=nullptr)
Definition: Network.cpp:2606
IConnectableLayer * AddConstantLayer(const ConstTensor &input, const char *name=nullptr)
Definition: Network.cpp:2585
IConnectableLayer * AddLogicalBinaryLayer(const LogicalBinaryDescriptor &logicalBinaryDescriptor, const char *name=nullptr)
Definition: Network.cpp:3041
IConnectableLayer * AddConvertFp16ToFp32Layer(const char *name=nullptr)
Definition: Network.cpp:2411
IConnectableLayer * AddRankLayer(const char *name=nullptr)
Definition: Network.cpp:2546
IConnectableLayer * AddSwitchLayer(const char *name=nullptr)
Definition: Network.cpp:2810
IConnectableLayer * AddQLstmLayer(const QLstmDescriptor &descriptor, const LstmInputParams &params, const char *name=nullptr)
Definition: Network.cpp:2899
IConnectableLayer * AddSoftmaxLayer(const SoftmaxDescriptor &softmaxDescriptor, const char *name=nullptr)
Definition: Network.cpp:2492
IConnectableLayer * AddDequantizeLayer(const char *name=nullptr)
Definition: Network.cpp:2783
IConnectableLayer * AddBroadcastToLayer(const BroadcastToDescriptor &descriptor, const char *name=nullptr)
Definition: Network.cpp:3237
IConnectableLayer * AddConvolution2dLayer(const Convolution2dDescriptor &convolution2dDescriptor, const char *name=nullptr)
Definition: Network.cpp:2405
IConnectableLayer * AddAdditionLayer(const char *name=nullptr)
Definition: Network.cpp:2514
IConnectableLayer * AddQuantizedLstmLayer(const QuantizedLstmInputParams &params, const char *name=nullptr)
Definition: Network.cpp:2861
IConnectableLayer * AddTransposeConvolution2dLayer(const TransposeConvolution2dDescriptor &descriptor, const ConstTensor &weights, const Optional< ConstTensor > &biases, const char *name=nullptr)
Definition: Network.cpp:2820
IConnectableLayer * AddFloorLayer(const char *name=nullptr)
Definition: Network.cpp:2612
IConnectableLayer * AddConvolution3dLayer(const Convolution3dDescriptor &convolution3dDescriptor, const char *name=nullptr)
Definition: Network.cpp:2421
IConnectableLayer * AddStackLayer(const StackDescriptor &stackDescriptor, const char *name=nullptr)
Definition: Network.cpp:2848
IConnectableLayer * AddFullyConnectedLayer(const FullyConnectedDescriptor &fullyConnectedDescriptor, const char *name=nullptr)
Definition: Network.cpp:2387
IConnectableLayer * AddMinimumLayer(const char *name=nullptr)
Definition: Network.cpp:2509
IConnectableLayer * AddMaximumLayer(const char *name=nullptr)
Definition: Network.cpp:2504
IConnectableLayer * AddChannelShuffleLayer(const ChannelShuffleDescriptor &channelShuffleDescriptor, const char *name=nullptr)
Definition: Network.cpp:2357
IConnectableLayer * AddNormalizationLayer(const NormalizationDescriptor &normalizationDescriptor, const char *name=nullptr)
Definition: Network.cpp:2480
IConnectableLayer * AddPreluLayer(const char *name=nullptr)
Definition: Network.cpp:2815
IConnectableLayer * AddPadLayer(const PadDescriptor &padDescriptor, const char *name=nullptr)
Definition: Network.cpp:2773
IConnectableLayer * AddSplitterLayer(const ViewsDescriptor &splitterDescriptor, const char *name=nullptr)
Definition: Network.cpp:2498
void ExecuteStrategy(IStrategy &strategy) const
Definition: Network.cpp:3247
IConnectableLayer * AddSpaceToBatchNdLayer(const SpaceToBatchNdDescriptor &spaceToBatchNdDescriptor, const char *name=nullptr)
Definition: Network.cpp:2600
IConnectableLayer * AddCastLayer(const char *name=nullptr)
Definition: Network.cpp:2353
IConnectableLayer * AddStandInLayer(const StandInDescriptor &descriptor, const char *name=nullptr)
Definition: Network.cpp:2855
IConnectableLayer * AddScatterNdLayer(const ScatterNdDescriptor &scatterDescriptor, const char *name=nullptr)
Definition: Network.cpp:3242
IConnectableLayer * AddBatchMatMulLayer(const BatchMatMulDescriptor &desc, const char *name=nullptr)
Definition: Network.cpp:3189
IConnectableLayer * AddLogSoftmaxLayer(const LogSoftmaxDescriptor &logSoftmaxDescriptor, const char *name=nullptr)
Definition: Network.cpp:2579
IConnectableLayer * AddReshapeLayer(const ReshapeDescriptor &reshapeDescriptor, const char *name=nullptr)
Definition: Network.cpp:2594
IConnectableLayer * AddSliceLayer(const SliceDescriptor &sliceDescriptor, const char *name=nullptr)
Definition: Network.cpp:2487
IConnectableLayer * AddBatchNormalizationLayer(const BatchNormalizationDescriptor &desc, const ConstTensor &mean, const ConstTensor &variance, const ConstTensor &beta, const ConstTensor &gamma, const char *name=nullptr)
Definition: Network.cpp:2529
IConnectableLayer * AddBatchToSpaceNdLayer(const BatchToSpaceNdDescriptor &batchToSpaceNdDescriptor, const char *name=nullptr)
Definition: Network.cpp:2347
IConnectableLayer * AddActivationLayer(const ActivationDescriptor &activationDescriptor, const char *name=nullptr)
Definition: Network.cpp:2468
IConnectableLayer * AddInputLayer(LayerBindingId id, const char *name=nullptr)
Definition: Network.cpp:2342
IConnectableLayer * AddElementwiseBinaryLayer(const ElementwiseBinaryDescriptor &elementwiseBinaryDescriptor, const char *name=nullptr)
Definition: Network.cpp:2369
IConnectableLayer * AddTileLayer(const TileDescriptor &tileDescriptor, const char *name=nullptr)
Definition: Network.cpp:3199
IConnectableLayer * AddGatherLayer(const GatherDescriptor &gatherDescriptor, const char *name=nullptr)
Definition: Network.cpp:2794
IConnectableLayer * AddL2NormalizationLayer(const L2NormalizationDescriptor &desc, const char *name=nullptr)
Definition: Network.cpp:2573
IConnectableLayer * AddTransposeLayer(const TransposeDescriptor &transposeDescriptor, const char *name=nullptr)
Definition: Network.cpp:2842
IConnectableLayer * AddConvertFp32ToFp16Layer(const char *name=nullptr)
Definition: Network.cpp:2416
IConnectableLayer * AddUnidirectionalSequenceLstmLayer(const UnidirectionalSequenceLstmDescriptor &descriptor, const LstmInputParams &params, const char *name=nullptr)
Definition: Network.cpp:3047
IConnectableLayer * AddMultiplicationLayer(const char *name=nullptr)
Definition: Network.cpp:2519
IConnectableLayer * AddInstanceNormalizationLayer(const InstanceNormalizationDescriptor &desc, const char *name=nullptr)
Definition: Network.cpp:2567
IConnectableLayer * AddDetectionPostProcessLayer(const DetectionPostProcessDescriptor &descriptor, const ConstTensor &anchors, const char *name=nullptr)
Definition: Network.cpp:2440
IConnectableLayer * AddStridedSliceLayer(const StridedSliceDescriptor &stridedSliceDescriptor, const char *name=nullptr)
Definition: Network.cpp:2788
IConnectableLayer * AddDepthwiseConvolution2dLayer(const DepthwiseConvolution2dDescriptor &convolution2dDescriptor, const char *name=nullptr)
Definition: Network.cpp:2433
IConnectableLayer * AddComparisonLayer(const ComparisonDescriptor &comparisonDescriptor, const char *name=nullptr)
Definition: Network.cpp:2363
IConnectableLayer * AddMeanLayer(const MeanDescriptor &meanDescriptor, const char *name=nullptr)
Definition: Network.cpp:2768
IConnectableLayer * AddResizeLayer(const ResizeDescriptor &resizeDescriptor, const char *name=nullptr)
Definition: Network.cpp:2557
IConnectableLayer * AddArgMinMaxLayer(const ArgMinMaxDescriptor &desc, const char *name=nullptr)
Definition: Network.cpp:2474
IConnectableLayer * AddReduceLayer(const ReduceDescriptor &reduceDescriptor, const char *name=nullptr)
Definition: Network.cpp:2551
IConnectableLayer * AddPooling2dLayer(const Pooling2dDescriptor &pooling2dDescriptor, const char *name=nullptr)
Definition: Network.cpp:2456
IConnectableLayer * AddConcatLayer(const ConcatDescriptor &concatDescriptor, const char *name=nullptr)
Definition: Network.cpp:2399
IConnectableLayer * AddPooling3dLayer(const Pooling3dDescriptor &pooling3dDescriptor, const char *name=nullptr)
Definition: Network.cpp:2462
IConnectableLayer * AddPrecompiledLayer(const PreCompiledDescriptor &preCompiledDescriptor, CompiledBlobPtr compiledBlobPtr, const Optional< BackendId > &backend, const char *name=nullptr)
Definition: Network.cpp:3204
IConnectableLayer * AddSubtractionLayer(const char *name=nullptr)
Definition: Network.cpp:2763
IConnectableLayer * AddDepthToSpaceLayer(const DepthToSpaceDescriptor &depthToSpaceDescriptor, const char *name=nullptr)
Definition: Network.cpp:2427
IConnectableLayer * AddOutputLayer(LayerBindingId id, const char *name=nullptr)
Definition: Network.cpp:2524
IConnectableLayer * AddReverseV2Layer(const char *name=nullptr)
Definition: Network.cpp:3194
IConnectableLayer * AddGatherNdLayer(const char *name=nullptr)
Definition: Network.cpp:2800
IConnectableLayer * AddShapeLayer(const char *name=nullptr)
Definition: Network.cpp:2562
IConnectableLayer * AddFillLayer(const FillDescriptor &fillDescriptor, const char *name=nullptr)
Definition: Network.cpp:2381
const Graph & GetGraph() const
Definition: Network.hpp:38
Status PrintGraph()
Definition: Network.cpp:2336
This layer represents a normalization operation.
bool Validate(const SubgraphView &originalSubgraph) const
const Substitutions & GetSubstitutions() const
const Subgraphs & GetDeletedSubgraphs() const
const Subgraphs & GetFailedSubgraphs() const
virtual Status SerializeToDot(std::ostream &stream) const
Definition: Network.cpp:747
virtual size_t GetNumOutputs() const
Definition: Network.cpp:757
void ExecuteStrategy(IStrategy &strategy) const
Definition: Network.cpp:3281
virtual size_t GetNumInputs() const
Definition: Network.cpp:752
OptimizedNetworkImpl(const OptimizedNetworkImpl &other, const ModelOptions &modelOptions)
Definition: Network.cpp:3255
virtual Status PrintGraph()
Definition: Network.cpp:741
static void Pass(Graph &graph, const Optimizations &optimizations)
Definition: Optimizer.cpp:16
void AddModelOption(armnn::BackendOptions)
Definition: Network.cpp:151
void SetDebugEnabled(bool DebugState)
Definition: Network.cpp:126
OptimizerOptionsOpaque & operator=(OptimizerOptionsOpaque other)
Definition: Network.cpp:96
bool GetReduceFp32ToBf16() const
Definition: Network.cpp:176
bool GetProfilingEnabled() const
Definition: Network.cpp:156
void SetReduceFp32ToFp16(bool ReduceFp32ToFp16State)
Definition: Network.cpp:136
armnn::ShapeInferenceMethod GetShapeInferenceMethod() const
Definition: Network.cpp:201
void SetAllowExpandedDims(bool ExpandedDimsAllowed)
Definition: Network.cpp:146
bool GetReduceFp32ToFp16() const
Definition: Network.cpp:171
void SetProfilingEnabled(bool ProfilingState)
Definition: Network.cpp:121
bool GetDebugToFileEnabled() const
Definition: Network.cpp:186
void SetDebugToFileEnabled(bool DebugFileState)
Definition: Network.cpp:131
void SetExportEnabled(bool ExportState)
Definition: Network.cpp:116
const std::string ToString() const
Definition: Network.cpp:206
void SetImportEnabled(bool ImportState)
Definition: Network.cpp:111
armnn::ModelOptions GetModelOptions() const
Definition: Network.cpp:196
void SetShapeInferenceMethod(armnn::ShapeInferenceMethod ShapeInferenceMethodType)
Definition: Network.cpp:141
bool GetAllowExpandedDims() const
Definition: Network.cpp:191
bool has_value() const noexcept
Definition: Optional.hpp:53
A layer user-provided data can be bound to (e.g. inputs, outputs).
Definition: OutputLayer.hpp:14
const InputSlot * GetConnection(unsigned int index) const override
Definition: Layer.cpp:83
unsigned int GetNumConnections() const override
Definition: Layer.hpp:158
void SetEdgeStrategy(unsigned int connectionIndex, EdgeStrategy strategy)
Definition: Layer.cpp:223
const std::vector< InputSlot * > & GetConnections() const
Definition: Layer.hpp:145
Layer & GetOwningLayer() const
Definition: Layer.hpp:132
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition: Layer.cpp:95
void Disconnect(InputSlot &slot)
Definition: Layer.cpp:131
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:100
int Connect(InputSlot &destination)
Definition: Layer.cpp:123
void SetTensorHandleFactory(const ITensorHandleFactory::FactoryId &id)
Definition: Layer.cpp:213
This layer represents a pad operation.
Definition: PadLayer.hpp:15
This layer represents a permutation operation.
This layer represents a pooling 2d operation.
This layer represents a pooling 3d operation.
void SetPreCompiledObject(PreCompiledObjectPtr preCompiledObject)
This layer represents a QLstm operation.
Definition: QLstmLayer.hpp:80
QLstmBasicParameters m_BasicParameters
Definition: QLstmLayer.hpp:83
This layer represents a QuantizedLstm operation.
QuantizedLstmParameters m_QuantizedLstmParameters
This layer represents a reduction operation.
Definition: ReduceLayer.hpp:15
This layer represents a reshape operation.
This layer represents a resize operation.
Definition: ResizeLayer.hpp:14
This layer represents a ReverseV2 operation.
This layer represents a ScatterNd operator.
This layer represents a softmax operation.
This layer represents a SpaceToBatchNd operation.
This layer represents a SpaceToDepth operation.
This layer represents a split operation.
This layer represents a stack operation.
Definition: StackLayer.hpp:14
This layer represents an unknown operation in the input graph.
This layer represents a strided slice operation.
The SubgraphView class represents a subgraph of a Graph.
IConnectableLayers::iterator IConnectableLayerIterator
IConnectableLayerIterator begin()
const IConnectableLayers & GetIConnectableLayers() const
std::list< IConnectableLayer * > IConnectableLayers
IConnectableLayerIterator end()
static Subgraphs SelectSubgraphs(Graph &graph, const LayerSelectorFunction &selector)
Selects subgraphs from a graph based on the selector function and the algorithm.
std::vector< SubgraphView::SubgraphViewPtr > Subgraphs
This layer represents a subtraction operation.
This layer calculates both true and false outputs for input.
Definition: SwitchLayer.hpp:14
ITensorHandleFactory * GetFactory(ITensorHandleFactory::FactoryId id) const
Find a TensorHandleFactory by Id Returns nullptr if not found.
void SetDataType(DataType type)
Definition: Tensor.hpp:201
DataType GetDataType() const
Definition: Tensor.hpp:200
This layer represents a 2D transpose convolution operation.
std::shared_ptr< ConstTensorHandle > m_Weight
A unique pointer to store weight values.
This layer represents a transpose operation.
This layer represents a LSTM operation.
static void ConvertFloat16To32(const void *srcFloat16Buffer, size_t numElements, float *dstFloat32Buffer)
ConvertConstants< Float16ToFloat32, IsFloat32Layer > ConvertConstantsHalfToFloat
OptimizeForConnection< PermuteLayer, BatchToSpaceNdLayer, PermuteAndBatchToSpaceAsDepthToSpaceImpl< PermuteLayer > > PermuteAndBatchToSpaceAsDepthToSpace
OptimizeForConnection< ConvertFp16ToFp32Layer, ConvertFp32ToFp16Layer, OptimizeInverseConversionsImpl > OptimizeInverseConversionsFp16
ConvertConstants< Float32ToFloat16, IsFloat16Layer > ConvertConstantsFloatToHalf
OptimizeForExclusiveConnection< PadLayer, DepthwiseConvolution2dLayer, pad_fold::FoldPadIntoDepthwiseConvolution2dImpl > FoldPadIntoDepthwiseConvolution2d
OptimizeForExclusiveConnection< PadLayer, Pooling2dLayer, pad_fold::FoldPadIntoPooling2dImpl > FoldPadIntoPooling2d
OptimizeForConnection< Layer, ReshapeLayer, SquashEqualSiblingsImpl< ReshapeLayer > > SquashEqualReshapeSiblings
OptimizeForConnection< TransposeLayer, TransposeLayer, OptimizeInversePermutesImpl< TransposeLayer > > OptimizeInverseTransposes
OptimizeForConnection< ConstantLayer, DequantizeLayer, TurboConvertConstDequantisationLayersToConstLayersImpl > TurboConvertConstDequantisationLayersToConstLayers
OptimizeForConnection< ConstantLayer, DequantizeLayer, ConvertConstDequantisationLayersToConstLayersImpl > ConvertConstDequantisationLayersToConstLayers
OptimizeForType< Layer, AddBroadcastReshapeLayerImpl > AddBroadcastReshapeLayer
OptimizeForExclusiveConnection< DepthwiseConvolution2dLayer, BatchNormalizationLayer, FuseBatchNorm< DepthwiseConvolution2dLayer, armnn::DataType::Float32 > > FuseBatchNormIntoDepthwiseConvolution2DFloat32
OptimizeForConnection< Layer, TransposeLayer, MoveTransposeUpImpl > MoveTransposeUp
OptimizeForConnection< Layer, PermuteLayer, SquashEqualSiblingsImpl< PermuteLayer > > SquashEqualPermuteSiblings
OptimizeForConnection< ReshapeLayer, ReshapeLayer, OptimizeConsecutiveReshapesImpl > OptimizeConsecutiveReshapes
OptimizeForType< Layer, ConvertFp32NetworkToFp16Impl > Fp32NetworkToFp16Converter
OptimizeForExclusiveConnection< Convolution2dLayer, BatchNormalizationLayer, FuseBatchNorm< Convolution2dLayer, armnn::DataType::Float16 > > FuseBatchNormIntoConvolution2DFloat16
OptimizeForExclusiveConnection< PadLayer, Convolution2dLayer, pad_fold::FoldPadIntoConvolution2dImpl > FoldPadIntoConvolution2d
OptimizeForConnection< TransposeLayer, BatchToSpaceNdLayer, PermuteAndBatchToSpaceAsDepthToSpaceImpl< TransposeLayer > > TransposeAndBatchToSpaceAsDepthToSpace
OptimizeForType< Layer, AddDebugToFileImpl > InsertDebugToFileLayer
Definition: AddDebug.hpp:54
OptimizeForConnection< PermuteLayer, PermuteLayer, OptimizeInversePermutesImpl< PermuteLayer > > OptimizeInversePermutes
OptimizeForExclusiveConnection< Convolution2dLayer, BatchNormalizationLayer, FuseBatchNorm< Convolution2dLayer, armnn::DataType::Float32 > > FuseBatchNormIntoConvolution2DFloat32
OptimizeForType< Layer, AddDebugImpl > InsertDebugLayer
Definition: AddDebug.hpp:53
OptimizeForConnection< Layer, PermuteLayer, MovePermuteUpImpl > MovePermuteUp
OptimizeForExclusiveConnection< DepthwiseConvolution2dLayer, BatchNormalizationLayer, FuseBatchNorm< DepthwiseConvolution2dLayer, armnn::DataType::Float16 > > FuseBatchNormIntoDepthwiseConvolution2DFloat16
OptimizeForConnection< Layer, TransposeLayer, SquashEqualSiblingsImpl< TransposeLayer > > SquashEqualTransposeSiblings
OptimizeForExclusiveConnection< ElementwiseBinaryLayer, ElementwiseBinaryLayer, MaxMinIntoBoundedReluImpl > MaxMinIntoBoundedRelu
OptimizeForType< BroadcastToLayer, DeleteBroadcastToImpl > BroadcastToOptimizationLayer
OptimizeForType< TransposeLayer, TransposeAsReshapeImpl > TransposeAsReshape
OptimizeForConnection< ConstantLayer, PermuteLayer, ConvertConstPermuteLayersToConstLayers > FusePermuteIntoConstLayer
OptimizeForType< PermuteLayer, PermuteAsReshapeImpl > PermuteAsReshape
OptimizeForConnection< ConvertFp32ToFp16Layer, ConvertFp16ToFp32Layer, OptimizeInverseConversionsImpl > OptimizeInverseConversionsFp32
Copyright (c) 2021 ARM Limited and Contributors.
void ReportWarning(const std::string &warningMessage, Optional< std::vector< std::string > & > warningMessages)
Definition: Network.cpp:774
OptimizationResult AssignBackends(OptimizedNetworkImpl *optNetObjPtr, BackendSettings &backendSettings, SubgraphView &subgraph, Optional< std::vector< std::string > & > errMessages)
Definition: Network.cpp:1340
half_float::half Half
Definition: Half.hpp:22
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 > & > messages)
Definition: Network.cpp:844
BackendsMap CreateSupportedBackends(TensorHandleFactoryRegistry &handleFactoryRegistry, BackendSettings &backendSettings)
Definition: Network.cpp:1354
std::vector< DataType > GetLayerInOutDatatype(const Layer *layer)
Definition: Network.cpp:1036
void AssignBackendsIConnectable(OptimizedNetworkImpl *optNetObjPtr, IConnectableLayer *it, Optional< std::vector< std::string > & > errMessages, OptimizationResult &result, BackendSettings &backendSettings, std::vector< BackendId > &availablePreferredBackends, bool &restart)
Definition: Network.cpp:1092
void ReportError(const std::string &errorMessage, Optional< std::vector< std::string > & > errorMessages)
Definition: Network.cpp:762
bool HasMatchingCapability(const BackendOptions::BackendOption &capability, const BackendCapabilities &capabilities)
Convenience function to check if a given capability matches a capability in a BackendCapabilities str...
void IgnoreUnused(Ts &&...)
bool IsTfLiteTurboModel(const Graph &optGraph)
Definition: Network.cpp:1972
std::vector< BackendOptions > NetworkOptions
LayerType
When adding a new layer, adapt also the LastLayer enum value in the enum class LayerType below.
Definition: Types.hpp:494
std::vector< BackendOptions > ModelOptions
bool RequiresCopy(ITensorHandleFactory::FactoryId src, ITensorHandleFactory::FactoryId dst, TensorHandleFactoryRegistry &registry)
Definition: Network.cpp:1506
ITensorHandleFactory::FactoryId CalculateSlotOptionForInput(BackendsMap &backends, OutputSlot &slot, TensorHandleFactoryRegistry &registry, bool importEnabled)
Definition: Network.cpp:1526
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
Definition: INetwork.hpp:340
Status
enumeration
Definition: Types.hpp:43
Optional< const BackendOptions::BackendOption > GetCapability(const std::string &backendCapabilityName, const BackendCapabilities &capabilities)
Returns a BackendCapability if the backend lists the capability The BackendCapability must then be in...
EdgeStrategy CalculateEdgeStrategy(BackendsMap &backends, ITensorHandleFactory::FactoryId srcFactoryId, const Layer &layer, const Layer &connectedLayer, TensorHandleFactoryRegistry &registry, bool importEnabled)
Definition: Network.cpp:1781
constexpr const char * GetDataTypeName(DataType dataType)
Definition: TypesUtils.hpp:234
OptimizationResult AssignBackends(OptimizedNetworkImpl *optNetObjPtr, BackendSettings &backendSettings, Graph::Iterator &firstLayer, Graph::Iterator &lastLayer, Optional< std::vector< std::string > & > errMessages)
Definition: Network.cpp:1211
float Dequantize(QuantizedType value, float scale, int32_t offset)
Dequantize an 8-bit data type into a floating point data type.
Definition: TypesUtils.cpp:48
bool CheckScaleSetOnQuantizedType(Layer *layer, Optional< std::vector< std::string > & > errMessages)
Definition: Network.cpp:801
bool CheckFastMathSupport(const std::vector< BackendId > &availablePreferredBackends, const ModelOptions &modelOptions)
Definition: Network.cpp:1944
std::map< BackendId, std::unique_ptr< class IBackendInternal > > BackendsMap
Definition: Network.hpp:285
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptionsOpaque &options=OptimizerOptionsOpaque(), Optional< std::vector< std::string > & > messages=EmptyOptional())
Create an optimized version of the network.
Definition: Network.cpp:2286
bool CheckFp16Support(BackendsMap &backends, const std::vector< BackendId > &availablePreferredBackends)
Definition: Network.cpp:1045
Optimizer::Optimizations MakeOptimizations(Args &&... args)
Definition: Optimizer.hpp:43
ITensorHandleFactory::FactoryId CalculateSlotOptionForOutput(BackendsMap &backends, OutputSlot &slot, TensorHandleFactoryRegistry &registry)
Definition: Network.cpp:1618
int LayerBindingId
Type of identifiers for bindable layers (inputs, outputs).
Definition: Types.hpp:311
bool HasCapability(const std::string &name, const BackendCapabilities &capabilities)
Convenience function to check if a capability exists in a BackendCapabilites struct.
std::vector< ConvertFp32ToFp16Layer * > InsertConvertFp32ToFp16LayersAfter(Graph &graph, Layer &layer)
BackendRegistry & BackendRegistryInstance()
OptimizationResult ApplyBackendOptimizations(OptimizedNetworkImpl *optNetObjPtr, BackendSettings &backendSettings, BackendsMap &backends, const ModelOptions &modelOptions, Optional< std::vector< std::string > & > errMessages)
Definition: Network.cpp:1372
std::vector< BackendId > BackendIdVector
Definition: BackendId.hpp:192
OptimizationResult SelectTensorHandleStrategy(Graph &optGraph, BackendsMap &backends, TensorHandleFactoryRegistry &registry, bool importEnabled, bool exportEnabled, Optional< std::vector< std::string > & > errMessages)
Definition: Network.cpp:1873
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:339
std::vector< ConvertFp16ToFp32Layer * > InsertConvertFp16ToFp32LayersBefore(Graph &graph, Layer &layer, bool expectCorrectInputType)
ITensorHandleFactory::FactoryId CalculateSlotOption(BackendsMap &backends, OutputSlot &outputSlot, TensorHandleFactoryRegistry &registry, bool exportEnabled)
Definition: Network.cpp:1628
DataType
Definition: Types.hpp:49
const char * GetLayerTypeAsCString(LayerType type)
ShapeInferenceMethod
The ShapeInferenceMethod modify how the output shapes are treated.
Definition: Types.hpp:237
@ ValidateOnly
Validate all output shapes.
@ CpuAcc
CPU Execution: NEON: ArmCompute.
@ CpuRef
CPU Execution: Reference C++ kernels.
@ GpuAcc
GPU Execution: OpenCL: ArmCompute.
OptimizationResult ReturnWithError(OptimizationResult res, const Layer *layer, const BackendSettings &backendSettings, Optional< std::vector< std::string > & > errMessages)
Definition: Network.cpp:787
std::unique_ptr< void, CompiledBlobDeleter > CompiledBlobPtr
Definition: INetwork.hpp:343
void ParseOptions(const std::vector< BackendOptions > &options, BackendId backend, F f)
@ ExportToTarget
Destination backend can work directly with tensors on source backend.
@ DirectCompatibility
No strategy has been defined. Used internally to verify integrity of optimizations.
@ CopyToTarget
Source backends tensor data can be exported to destination backend tensor without copy.
std::string CreateDirectory(std::string sPath)
Returns full path to temporary folder.
Definition: Filesystem.cpp:47
An ActivationDescriptor for the ActivationLayer.
Definition: Descriptors.hpp:37
An ArgMinMaxDescriptor for ArgMinMaxLayer.
Definition: Descriptors.hpp:68
Struct for the users to pass backend specific options.
BackendIdSet m_SupportedBackends
BackendIdSet m_IgnoredBackends
BackendIdSet m_SelectedBackends
bool IsBackendSupported(const BackendId &backend) const
BackendIdVector GetAvailablePreferredBackends() const
BackendIdVector m_PreferredBackends
A BatchMatMulDescriptor for the BatchMatMul operator.
A BatchNormalizationDescriptor for the BatchNormalizationLayer.
A BatchToSpaceNdDescriptor for the BatchToSpaceNdLayer.
A ChannelShuffleDescriptor for the ChannelShuffle operator.
A ComparisonDescriptor for the ComparisonLayer.
Definition: Descriptors.hpp:90
A Convolution2dDescriptor for the Convolution2dLayer.
A Convolution3dDescriptor for the Convolution3dLayer.
A DepthwiseConvolution2dDescriptor for the DepthwiseConvolution2dLayer.
A ElementwiseBinaryDescriptor for the ElementwiseBinaryLayer.
A ElementwiseUnaryDescriptor for the ElementwiseUnaryLayer.
EmptyOptional is used to initialize the Optional class in case we want to have default value for an O...
Definition: Optional.hpp:32
A FillDescriptor for the FillLayer.
A FullyConnectedDescriptor for the FullyConnectedLayer.
A FusedDescriptor for the FusedLayer.
A GatherDescriptor for the GatherLayer.
An InstanceNormalizationDescriptor for InstanceNormalizationLayer.
A L2NormalizationDescriptor for the L2NormalizationLayer.
A LogicalBinaryDescriptor for the LogicalBinaryLayer.
std::shared_ptr< ConstTensorHandle > m_InputToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
An LstmDescriptor for the LstmLayer.
bool m_PeepholeEnabled
Enable/disable peephole.
bool m_LayerNormEnabled
Enable/disable layer normalization.
bool m_ProjectionEnabled
Enable/disable the projection layer.
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
const ConstTensor * m_InputLayerNormWeights
Definition: LstmParams.hpp:57
const ConstTensor * m_RecurrentToCellWeights
Definition: LstmParams.hpp:46
const ConstTensor * m_InputToForgetWeights
Definition: LstmParams.hpp:41
const ConstTensor * m_CellToForgetWeights
Definition: LstmParams.hpp:49
const ConstTensor * m_RecurrentToInputWeights
Definition: LstmParams.hpp:44
const ConstTensor * m_ProjectionBias
Definition: LstmParams.hpp:56
const ConstTensor * m_CellToInputWeights
Definition: LstmParams.hpp:48
const ConstTensor * m_InputToCellWeights
Definition: LstmParams.hpp:42
const ConstTensor * m_CellBias
Definition: LstmParams.hpp:53
const ConstTensor * m_RecurrentToOutputWeights
Definition: LstmParams.hpp:47
const ConstTensor * m_InputToOutputWeights
Definition: LstmParams.hpp:43
const ConstTensor * m_OutputGateBias
Definition: LstmParams.hpp:54
const ConstTensor * m_OutputLayerNormWeights
Definition: LstmParams.hpp:60
const ConstTensor * m_InputGateBias
Definition: LstmParams.hpp:51
const ConstTensor * m_ProjectionWeights
Definition: LstmParams.hpp:55
const ConstTensor * m_ForgetGateBias
Definition: LstmParams.hpp:52
const ConstTensor * m_CellLayerNormWeights
Definition: LstmParams.hpp:59
const ConstTensor * m_RecurrentToForgetWeights
Definition: LstmParams.hpp:45
const ConstTensor * m_ForgetLayerNormWeights
Definition: LstmParams.hpp:58
const ConstTensor * m_CellToOutputWeights
Definition: LstmParams.hpp:50
const ConstTensor * m_InputToInputWeights
Definition: LstmParams.hpp:40
A MeanDescriptor for the MeanLayer.
A NormalizationDescriptor for the NormalizationLayer.
bool IsWarningOnly() const
Definition: Network.hpp:278
bool m_ExportEnabled
Enable Export.
Definition: INetwork.hpp:262
bool m_ImportEnabled
Enable Import.
Definition: INetwork.hpp:253
bool m_ReduceFp32ToBf16
@Note This feature has been replaced by enabling Fast Math in compute library backend options.
Definition: INetwork.hpp:247
bool m_ProfilingEnabled
Enable profiling dump of the optimizer phase.
Definition: INetwork.hpp:259
bool m_Debug
Add debug data for easier troubleshooting.
Definition: INetwork.hpp:240
bool m_ReduceFp32ToFp16
Reduces all Fp32 operators in the model to Fp16 for faster processing.
Definition: INetwork.hpp:237
ModelOptions m_ModelOptions
Enable Model Options.
Definition: INetwork.hpp:256
ShapeInferenceMethod m_shapeInferenceMethod
Infer output size when not available.
Definition: INetwork.hpp:250
bool m_AllowExpandedDims
When calculating tensor sizes, dimensions of size == 1 will be ignored.
Definition: INetwork.hpp:265
bool m_DebugToFile
Pass debug data to separate output files for easier troubleshooting.
Definition: INetwork.hpp:243
An OriginsDescriptor for the ConcatLayer.
A PadDescriptor for the PadLayer.
A PermuteDescriptor for the PermuteLayer.
A Pooling2dDescriptor for the Pooling2dLayer.
A Pooling3dDescriptor for the Pooling3dLayer.
A PreCompiledDescriptor for the PreCompiledLayer.
std::shared_ptr< ConstTensorHandle > m_InputToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [num_units, inputSize] (QSymmS8).
Definition: QLstmLayer.hpp:17
A QLstmDescriptor for the QLstmLayer.
bool m_PeepholeEnabled
Enable/disable peephole.
bool m_LayerNormEnabled
Enable/disable layer normalization.
bool m_ProjectionEnabled
Enable/disable the projection layer.
bool m_CifgEnabled
Enable/disable CIFG (coupled input & forget gate).
const ConstTensor & GetOutputGateBias() const
const ConstTensor & GetInputToInputWeights() const
const ConstTensor & GetInputToForgetWeights() const
const ConstTensor & GetInputToOutputWeights() const
const ConstTensor & GetRecurrentToCellWeights() const
const ConstTensor & GetForgetGateBias() const
const ConstTensor & GetCellBias() const
const ConstTensor & GetRecurrentToForgetWeights() const
const ConstTensor & GetInputToCellWeights() const
const ConstTensor & GetRecurrentToOutputWeights() const
const ConstTensor & GetInputGateBias() const
const ConstTensor & GetRecurrentToInputWeights() const
std::shared_ptr< ConstTensorHandle > m_InputToInputWeights
A unique pointer to represent 2D weights tensor with dimensions [outputSize, inputSize] (QAsymm8).
A ReduceDescriptor for the REDUCE operators.
A ReshapeDescriptor for the ReshapeLayer.
A ResizeDescriptor for the ResizeLayer.
A ScatterNdDescriptor for the ScatterNdLayer.
A SliceDescriptor for the SliceLayer.
A SoftmaxDescriptor for the SoftmaxLayer.
A SpaceToBatchNdDescriptor for the SpaceToBatchNdLayer.
A SpaceToDepthDescriptor for the SpaceToDepthLayer.
A StackDescriptor for the StackLayer.
A StandInDescriptor for the StandIn layer.
A StridedSliceDescriptor for the StridedSliceLayer.
A TransposeConvolution2dDescriptor for the TransposeConvolution2dLayer.
bool m_BiasEnabled
Enable/disable bias.
A TransposeDescriptor for the TransposeLayer.
A ViewsDescriptor for the SplitterLayer.