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