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