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