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