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