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