From 992d6dc57d8463729910b688f0fb5825d0d3ccf2 Mon Sep 17 00:00:00 2001 From: Matteo Martincigh Date: Thu, 10 Jan 2019 17:34:20 +0000 Subject: IVGCVSW-2454 Refactor ArmNN to support pluggable backends from a separate code base * Made the virtual functions in ILayerSupport.hpp pure * Created a LayerSupportBase class with the default implementation of the interface * Made the backend layer support classes inherit from the base class, instead of directly from the interface * Refactored the profiler and the profiling event classes to use the BackendId instead of the Compute * Implemented a proper MemCopy support method * Changed Compute to BackendId in the profiling API and objects * Removed static references to pluggable backends !android-nn-driver:492 Change-Id: Id6332b5f48c980819e0a09adc818d1effd057296 --- src/backends/backendsCommon/CMakeLists.txt | 3 +- src/backends/backendsCommon/ILayerSupport.cpp | 346 ---------------------- src/backends/backendsCommon/LayerSupportBase.cpp | 355 +++++++++++++++++++++++ src/backends/backendsCommon/LayerSupportBase.hpp | 223 ++++++++++++++ src/backends/backendsCommon/WorkloadFactory.cpp | 24 +- src/backends/backendsCommon/common.mk | 2 +- src/backends/cl/ClLayerSupport.cpp | 11 + src/backends/cl/ClLayerSupport.hpp | 9 +- src/backends/neon/NeonLayerSupport.cpp | 19 +- src/backends/neon/NeonLayerSupport.hpp | 12 +- src/backends/reference/RefLayerSupport.cpp | 13 + src/backends/reference/RefLayerSupport.hpp | 11 +- 12 files changed, 652 insertions(+), 376 deletions(-) delete mode 100644 src/backends/backendsCommon/ILayerSupport.cpp create mode 100644 src/backends/backendsCommon/LayerSupportBase.cpp create mode 100644 src/backends/backendsCommon/LayerSupportBase.hpp (limited to 'src/backends') diff --git a/src/backends/backendsCommon/CMakeLists.txt b/src/backends/backendsCommon/CMakeLists.txt index b120f51184..1aa4d99dc3 100644 --- a/src/backends/backendsCommon/CMakeLists.txt +++ b/src/backends/backendsCommon/CMakeLists.txt @@ -11,7 +11,8 @@ list(APPEND armnnBackendsCommon_sources CpuTensorHandle.hpp IBackendInternal.hpp IBackendContext.hpp - ILayerSupport.cpp + LayerSupportBase.cpp + LayerSupportBase.hpp IMemoryManager.hpp ITensorHandle.hpp MakeWorkloadHelper.hpp diff --git a/src/backends/backendsCommon/ILayerSupport.cpp b/src/backends/backendsCommon/ILayerSupport.cpp deleted file mode 100644 index aa1bb5042d..0000000000 --- a/src/backends/backendsCommon/ILayerSupport.cpp +++ /dev/null @@ -1,346 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#include -#include - -namespace armnn -{ - -namespace -{ - -bool DefaultLayerSupport(const char* func, - const char* file, - unsigned int line, - Optional reasonIfUnsupported) -{ - // NOTE: We only need to return the reason if the optional parameter is not empty - if (reasonIfUnsupported) - { - std::stringstream message; - message << func << " is not implemented [" << file << ":" << line << "]"; - - reasonIfUnsupported.value() = message.str(); - } - - return false; -} - -} // anonymous namespace - -bool ILayerSupport::IsActivationSupported(const TensorInfo& input, - const TensorInfo& output, - const ActivationDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsAdditionSupported(const TensorInfo& input0, - const TensorInfo& input1, - const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsBatchNormalizationSupported(const TensorInfo& input, - const TensorInfo& output, - const TensorInfo& mean, - const TensorInfo& var, - const TensorInfo& beta, - const TensorInfo& gamma, - const BatchNormalizationDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsBatchToSpaceNdSupported(const TensorInfo& input, - const TensorInfo& output, - const BatchToSpaceNdDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsConstantSupported(const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input, - const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input, - const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsConvolution2dSupported(const TensorInfo& input, - const TensorInfo& output, - const Convolution2dDescriptor& descriptor, - const TensorInfo& weights, - const Optional& biases, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsDebugSupported(const TensorInfo& input, - const TensorInfo& output, - const DebugDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input, - const TensorInfo& output, - const DepthwiseConvolution2dDescriptor& descriptor, - const TensorInfo& weights, - const Optional& biases, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsDivisionSupported(const TensorInfo& input0, - const TensorInfo& input1, - const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsEqualSupported(const armnn::TensorInfo& input0, - const armnn::TensorInfo& input1, - const armnn::TensorInfo& output, - armnn::Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsFakeQuantizationSupported(const TensorInfo& input, - const FakeQuantizationDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsFloorSupported(const TensorInfo& input, - const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsFullyConnectedSupported(const TensorInfo& input, - const TensorInfo& output, - const TensorInfo& weights, - const TensorInfo& biases, - const FullyConnectedDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsInputSupported(const TensorInfo& input, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsL2NormalizationSupported(const TensorInfo& input, - const TensorInfo& output, - const L2NormalizationDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsLstmSupported(const TensorInfo& input, - const TensorInfo& outputStateIn, - const TensorInfo& cellStateIn, - const TensorInfo& scratchBuffer, - const TensorInfo& outputStateOut, - const TensorInfo& cellStateOut, - const TensorInfo& output, - const LstmDescriptor& descriptor, - const TensorInfo& inputToForgetWeights, - const TensorInfo& inputToCellWeights, - const TensorInfo& inputToOutputWeights, - const TensorInfo& recurrentToForgetWeights, - const TensorInfo& recurrentToCellWeights, - const TensorInfo& recurrentToOutputWeights, - const TensorInfo& forgetGateBias, - const TensorInfo& cellBias, - const TensorInfo& outputGateBias, - const TensorInfo* inputToInputWeights, - const TensorInfo* recurrentToInputWeights, - const TensorInfo* cellToInputWeights, - const TensorInfo* inputGateBias, - const TensorInfo* projectionWeights, - const TensorInfo* projectionBias, - const TensorInfo* cellToForgetWeights, - const TensorInfo* cellToOutputWeights, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsMaximumSupported(const TensorInfo& input0, - const TensorInfo& input1, - const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsMeanSupported(const TensorInfo& input, - const TensorInfo& output, - const MeanDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsMergerSupported(const std::vector inputs, - const TensorInfo& output, - const OriginsDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsMinimumSupported(const TensorInfo& input0, - const TensorInfo& input1, - const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsMultiplicationSupported(const TensorInfo& input0, - const TensorInfo& input1, - const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsNormalizationSupported(const TensorInfo& input, - const TensorInfo& output, - const NormalizationDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsOutputSupported(const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsPadSupported(const TensorInfo& input, - const TensorInfo& output, - const PadDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsPermuteSupported(const TensorInfo& input, - const TensorInfo& output, - const PermuteDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsPooling2dSupported(const TensorInfo& input, - const TensorInfo& output, - const Pooling2dDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsReshapeSupported(const TensorInfo& input, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsResizeBilinearSupported(const TensorInfo& input, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsSoftmaxSupported(const TensorInfo& input, - const TensorInfo& output, - const SoftmaxDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsSpaceToBatchNdSupported(const TensorInfo& input, - const TensorInfo& output, - const SpaceToBatchNdDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsSplitterSupported(const TensorInfo& input, - const ViewsDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsStridedSliceSupported(const TensorInfo& input, - const TensorInfo& output, - const StridedSliceDescriptor& descriptor, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsSubtractionSupported(const TensorInfo& input0, - const TensorInfo& input1, - const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsGreaterSupported(const TensorInfo& input0, - const TensorInfo& input1, - const TensorInfo& output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -bool ILayerSupport::IsRsqrtSupported(const TensorInfo &input, - const TensorInfo &output, - Optional reasonIfUnsupported) const -{ - return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); -} - -} // namespace armnn diff --git a/src/backends/backendsCommon/LayerSupportBase.cpp b/src/backends/backendsCommon/LayerSupportBase.cpp new file mode 100644 index 0000000000..2987e5dd2a --- /dev/null +++ b/src/backends/backendsCommon/LayerSupportBase.cpp @@ -0,0 +1,355 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "LayerSupportBase.hpp" + +#include + +namespace +{ + +bool DefaultLayerSupport(const char* func, + const char* file, + unsigned int line, + armnn::Optional reasonIfUnsupported) +{ + // NOTE: We only need to return the reason if the optional parameter is not empty + if (reasonIfUnsupported) + { + std::stringstream message; + message << func << " is not implemented [" << file << ":" << line << "]"; + + reasonIfUnsupported.value() = message.str(); + } + + return false; +} + +} // anonymous namespace + +namespace armnn +{ + +bool LayerSupportBase::IsActivationSupported(const TensorInfo& input, + const TensorInfo& output, + const ActivationDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsAdditionSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsBatchNormalizationSupported(const TensorInfo& input, + const TensorInfo& output, + const TensorInfo& mean, + const TensorInfo& var, + const TensorInfo& beta, + const TensorInfo& gamma, + const BatchNormalizationDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsBatchToSpaceNdSupported(const TensorInfo& input, + const TensorInfo& output, + const BatchToSpaceNdDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsConstantSupported(const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsConvertFp16ToFp32Supported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsConvertFp32ToFp16Supported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsConvolution2dSupported(const TensorInfo& input, + const TensorInfo& output, + const Convolution2dDescriptor& descriptor, + const TensorInfo& weights, + const Optional& biases, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsDebugSupported(const TensorInfo& input, + const TensorInfo& output, + const DebugDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsDepthwiseConvolutionSupported(const TensorInfo& input, + const TensorInfo& output, + const DepthwiseConvolution2dDescriptor& descriptor, + const TensorInfo& weights, + const Optional& biases, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsDivisionSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsEqualSupported(const armnn::TensorInfo& input0, + const armnn::TensorInfo& input1, + const armnn::TensorInfo& output, + armnn::Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsFakeQuantizationSupported(const TensorInfo& input, + const FakeQuantizationDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsFloorSupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsFullyConnectedSupported(const TensorInfo& input, + const TensorInfo& output, + const TensorInfo& weights, + const TensorInfo& biases, + const FullyConnectedDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsInputSupported(const TensorInfo& input, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsL2NormalizationSupported(const TensorInfo& input, + const TensorInfo& output, + const L2NormalizationDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsLstmSupported(const TensorInfo& input, + const TensorInfo& outputStateIn, + const TensorInfo& cellStateIn, + const TensorInfo& scratchBuffer, + const TensorInfo& outputStateOut, + const TensorInfo& cellStateOut, + const TensorInfo& output, + const LstmDescriptor& descriptor, + const TensorInfo& inputToForgetWeights, + const TensorInfo& inputToCellWeights, + const TensorInfo& inputToOutputWeights, + const TensorInfo& recurrentToForgetWeights, + const TensorInfo& recurrentToCellWeights, + const TensorInfo& recurrentToOutputWeights, + const TensorInfo& forgetGateBias, + const TensorInfo& cellBias, + const TensorInfo& outputGateBias, + const TensorInfo* inputToInputWeights, + const TensorInfo* recurrentToInputWeights, + const TensorInfo* cellToInputWeights, + const TensorInfo* inputGateBias, + const TensorInfo* projectionWeights, + const TensorInfo* projectionBias, + const TensorInfo* cellToForgetWeights, + const TensorInfo* cellToOutputWeights, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsMaximumSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsMeanSupported(const TensorInfo& input, + const TensorInfo& output, + const MeanDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsMemCopySupported(const armnn::TensorInfo& input, + const armnn::TensorInfo& output, + armnn::Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsMergerSupported(const std::vector inputs, + const TensorInfo& output, + const OriginsDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsMinimumSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsMultiplicationSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsNormalizationSupported(const TensorInfo& input, + const TensorInfo& output, + const NormalizationDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsOutputSupported(const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsPadSupported(const TensorInfo& input, + const TensorInfo& output, + const PadDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsPermuteSupported(const TensorInfo& input, + const TensorInfo& output, + const PermuteDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsPooling2dSupported(const TensorInfo& input, + const TensorInfo& output, + const Pooling2dDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsReshapeSupported(const TensorInfo& input, + const ReshapeDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsResizeBilinearSupported(const TensorInfo& input, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsSoftmaxSupported(const TensorInfo& input, + const TensorInfo& output, + const SoftmaxDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsSpaceToBatchNdSupported(const TensorInfo& input, + const TensorInfo& output, + const SpaceToBatchNdDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsSplitterSupported(const TensorInfo& input, + const ViewsDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsStridedSliceSupported(const TensorInfo& input, + const TensorInfo& output, + const StridedSliceDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsSubtractionSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsGreaterSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +bool LayerSupportBase::IsRsqrtSupported(const TensorInfo &input, + const TensorInfo &output, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + +} // namespace armnn diff --git a/src/backends/backendsCommon/LayerSupportBase.hpp b/src/backends/backendsCommon/LayerSupportBase.hpp new file mode 100644 index 0000000000..8c7aa98043 --- /dev/null +++ b/src/backends/backendsCommon/LayerSupportBase.hpp @@ -0,0 +1,223 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include + +namespace armnn +{ + +class LayerSupportBase : public ILayerSupport +{ +public: + bool IsActivationSupported(const TensorInfo& input, + const TensorInfo& output, + const ActivationDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsAdditionSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsBatchNormalizationSupported(const TensorInfo& input, + const TensorInfo& output, + const TensorInfo& mean, + const TensorInfo& var, + const TensorInfo& beta, + const TensorInfo& gamma, + const BatchNormalizationDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsBatchToSpaceNdSupported(const TensorInfo& input, + const TensorInfo& output, + const BatchToSpaceNdDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsConstantSupported(const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsConvertFp16ToFp32Supported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsConvertFp32ToFp16Supported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsConvolution2dSupported(const TensorInfo& input, + const TensorInfo& output, + const Convolution2dDescriptor& descriptor, + const TensorInfo& weights, + const Optional& biases, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsDebugSupported(const TensorInfo& input, + const TensorInfo& output, + const DebugDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsDepthwiseConvolutionSupported(const TensorInfo& input, + const TensorInfo& output, + const DepthwiseConvolution2dDescriptor& descriptor, + const TensorInfo& weights, + const Optional& biases, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsDivisionSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsEqualSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsFakeQuantizationSupported(const TensorInfo& input, + const FakeQuantizationDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsFloorSupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsFullyConnectedSupported(const TensorInfo& input, + const TensorInfo& output, + const TensorInfo& weights, + const TensorInfo& biases, + const FullyConnectedDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsGreaterSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsInputSupported(const TensorInfo& input, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsL2NormalizationSupported(const TensorInfo& input, + const TensorInfo& output, + const L2NormalizationDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsLstmSupported(const TensorInfo& input, + const TensorInfo& outputStateIn, + const TensorInfo& cellStateIn, + const TensorInfo& scratchBuffer, + const TensorInfo& outputStateOut, + const TensorInfo& cellStateOut, + const TensorInfo& output, + const LstmDescriptor& descriptor, + const TensorInfo& inputToForgetWeights, + const TensorInfo& inputToCellWeights, + const TensorInfo& inputToOutputWeights, + const TensorInfo& recurrentToForgetWeights, + const TensorInfo& recurrentToCellWeights, + const TensorInfo& recurrentToOutputWeights, + const TensorInfo& forgetGateBias, + const TensorInfo& cellBias, + const TensorInfo& outputGateBias, + const TensorInfo* inputToInputWeights, + const TensorInfo* recurrentToInputWeights, + const TensorInfo* cellToInputWeights, + const TensorInfo* inputGateBias, + const TensorInfo* projectionWeights, + const TensorInfo* projectionBias, + const TensorInfo* cellToForgetWeights, + const TensorInfo* cellToOutputWeights, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsMaximumSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsMeanSupported(const TensorInfo& input, + const TensorInfo& output, + const MeanDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsMemCopySupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsMergerSupported(const std::vector inputs, + const TensorInfo& output, + const OriginsDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsMinimumSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsMultiplicationSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsNormalizationSupported(const TensorInfo& input, + const TensorInfo& output, + const NormalizationDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsOutputSupported(const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsPadSupported(const TensorInfo& input, + const TensorInfo& output, + const PadDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsPermuteSupported(const TensorInfo& input, + const TensorInfo& output, + const PermuteDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsPooling2dSupported(const TensorInfo& input, + const TensorInfo& output, + const Pooling2dDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsReshapeSupported(const TensorInfo& input, + const ReshapeDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsResizeBilinearSupported(const TensorInfo& input, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsRsqrtSupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsSoftmaxSupported(const TensorInfo& input, + const TensorInfo& output, + const SoftmaxDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsSpaceToBatchNdSupported(const TensorInfo& input, + const TensorInfo& output, + const SpaceToBatchNdDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsSplitterSupported(const TensorInfo& input, + const ViewsDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsStridedSliceSupported(const TensorInfo& input, + const TensorInfo& output, + const StridedSliceDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsSubtractionSupported(const TensorInfo& input0, + const TensorInfo& input1, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; +}; + +} // namespace armnn diff --git a/src/backends/backendsCommon/WorkloadFactory.cpp b/src/backends/backendsCommon/WorkloadFactory.cpp index 1dc96a5ec3..209ba6a4ed 100644 --- a/src/backends/backendsCommon/WorkloadFactory.cpp +++ b/src/backends/backendsCommon/WorkloadFactory.cpp @@ -190,15 +190,6 @@ bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId, reason); break; } - case LayerType::MemCopy: - { - // MemCopy supported for CpuRef, CpuAcc and GpuAcc backends, - // (also treat Undefined as CpuRef to avoid breaking lots of Unit tests). - result = backendId == Compute::CpuRef || backendId == Compute::Undefined - || backendId == Compute::CpuAcc || backendId == Compute::GpuAcc; - reason.value() = "Unsupported backend type"; - break; - } case LayerType::Debug: { auto cLayer = boost::polymorphic_downcast(&layer); @@ -487,6 +478,16 @@ bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId, reason); break; } + case LayerType::MemCopy: + { + const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo(); + const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo(); + + result = layerSupportObject->IsMemCopySupported(OverrideDataType(input, dataType), + OverrideDataType(output, dataType), + reason); + break; + } case LayerType::Merger: { auto cLayer = boost::polymorphic_downcast(&layer); @@ -590,8 +591,11 @@ bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId, } case LayerType::Reshape: { + auto cLayer = boost::polymorphic_downcast(&layer); const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo(); - result = layerSupportObject->IsReshapeSupported(OverrideDataType(input, dataType), reason); + result = layerSupportObject->IsReshapeSupported(OverrideDataType(input, dataType), + cLayer->GetParameters(), + reason); break; } case LayerType::ResizeBilinear: diff --git a/src/backends/backendsCommon/common.mk b/src/backends/backendsCommon/common.mk index 4e79bfcd7e..a1cc0c1b3a 100644 --- a/src/backends/backendsCommon/common.mk +++ b/src/backends/backendsCommon/common.mk @@ -10,7 +10,7 @@ COMMON_SOURCES := \ BackendRegistry.cpp \ CpuTensorHandle.cpp \ - ILayerSupport.cpp \ + LayerSupportBase.cpp \ MemCopyWorkload.cpp \ OutputHandler.cpp \ WorkloadData.cpp \ diff --git a/src/backends/cl/ClLayerSupport.cpp b/src/backends/cl/ClLayerSupport.cpp index c4d45fe8ef..c1139e2e1e 100644 --- a/src/backends/cl/ClLayerSupport.cpp +++ b/src/backends/cl/ClLayerSupport.cpp @@ -385,6 +385,15 @@ bool ClLayerSupport::IsMeanSupported(const TensorInfo& input, descriptor); } +bool ClLayerSupport::IsMemCopySupported(const TensorInfo &input, + const TensorInfo &output, + Optional reasonIfUnsupported) const +{ + ignore_unused(input); + ignore_unused(output); + return true; +} + bool ClLayerSupport::IsMergerSupported(const std::vector inputs, const TensorInfo& output, const OriginsDescriptor& descriptor, @@ -479,9 +488,11 @@ bool ClLayerSupport::IsPooling2dSupported(const TensorInfo& input, } bool ClLayerSupport::IsReshapeSupported(const TensorInfo& input, + const ReshapeDescriptor& descriptor, Optional reasonIfUnsupported) const { ignore_unused(input); + ignore_unused(descriptor); ignore_unused(reasonIfUnsupported); return true; } diff --git a/src/backends/cl/ClLayerSupport.hpp b/src/backends/cl/ClLayerSupport.hpp index 80dd1c85d7..b06e6a9404 100644 --- a/src/backends/cl/ClLayerSupport.hpp +++ b/src/backends/cl/ClLayerSupport.hpp @@ -4,12 +4,12 @@ // #pragma once -#include +#include namespace armnn { -class ClLayerSupport : public ILayerSupport +class ClLayerSupport : public LayerSupportBase { public: bool IsActivationSupported(const TensorInfo& input, @@ -122,6 +122,10 @@ public: const MeanDescriptor& descriptor, Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsMemCopySupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsMergerSupported(const std::vector inputs, const TensorInfo& output, const OriginsDescriptor& descriptor, @@ -161,6 +165,7 @@ public: Optional reasonIfUnsupported = EmptyOptional()) const override; bool IsReshapeSupported(const TensorInfo& input, + const ReshapeDescriptor& descriptor, Optional reasonIfUnsupported = EmptyOptional()) const override; bool IsResizeBilinearSupported(const TensorInfo& input, diff --git a/src/backends/neon/NeonLayerSupport.cpp b/src/backends/neon/NeonLayerSupport.cpp index cc8f973510..1f205ed6d6 100644 --- a/src/backends/neon/NeonLayerSupport.cpp +++ b/src/backends/neon/NeonLayerSupport.cpp @@ -271,6 +271,15 @@ bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input, descriptor); } +bool NeonLayerSupport::IsMemCopySupported(const TensorInfo &input, + const TensorInfo &output, + Optional reasonIfUnsupported) const +{ + ignore_unused(input); + ignore_unused(output); + return true; +} + bool NeonLayerSupport::IsMergerSupported(const std::vector inputs, const TensorInfo& output, const OriginsDescriptor& descriptor, @@ -355,22 +364,16 @@ bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input, } bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input, + const ReshapeDescriptor& descriptor, Optional reasonIfUnsupported) const { + ignore_unused(descriptor); return IsSupportedForDataTypeNeon(reasonIfUnsupported, input.GetDataType(), &TrueFunc<>, &TrueFunc<>); } -bool NeonLayerSupport::IsResizeBilinearSupported(const TensorInfo& input, - Optional reasonIfUnsupported) const -{ - ignore_unused(input); - ignore_unused(reasonIfUnsupported); - return false; -} - bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input, const TensorInfo& output, const SoftmaxDescriptor& descriptor, diff --git a/src/backends/neon/NeonLayerSupport.hpp b/src/backends/neon/NeonLayerSupport.hpp index 73193d34b7..c522c6ee0a 100644 --- a/src/backends/neon/NeonLayerSupport.hpp +++ b/src/backends/neon/NeonLayerSupport.hpp @@ -4,12 +4,12 @@ // #pragma once -#include +#include namespace armnn { -class NeonLayerSupport : public ILayerSupport +class NeonLayerSupport : public LayerSupportBase { public: bool IsActivationSupported(const TensorInfo& input, @@ -85,6 +85,10 @@ public: const MeanDescriptor& descriptor, Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsMemCopySupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsMergerSupported(const std::vector inputs, const TensorInfo& output, const OriginsDescriptor& descriptor, @@ -119,11 +123,9 @@ public: Optional reasonIfUnsupported = EmptyOptional()) const override; bool IsReshapeSupported(const TensorInfo& input, + const ReshapeDescriptor& descriptor, Optional reasonIfUnsupported = EmptyOptional()) const override; - bool IsResizeBilinearSupported(const TensorInfo& input, - Optional reasonIfUnsupported = EmptyOptional()) const override; - bool IsSoftmaxSupported(const TensorInfo& input, const TensorInfo& output, const SoftmaxDescriptor& descriptor, diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp index 56d2e4c659..61a34f957e 100644 --- a/src/backends/reference/RefLayerSupport.cpp +++ b/src/backends/reference/RefLayerSupport.cpp @@ -390,6 +390,17 @@ bool RefLayerSupport::IsMergerSupported(const std::vector inp &TrueFunc<>); } +bool RefLayerSupport::IsMemCopySupported(const TensorInfo &input, + const TensorInfo &output, + Optional reasonIfUnsupported) const +{ + ignore_unused(output); + return IsSupportedForDataTypeRef(reasonIfUnsupported, + input.GetDataType(), + &TrueFunc<>, + &TrueFunc<>); +} + bool RefLayerSupport::IsMinimumSupported(const TensorInfo& input0, const TensorInfo& input1, const TensorInfo& output, @@ -478,8 +489,10 @@ bool RefLayerSupport::IsPooling2dSupported(const TensorInfo& input, } bool RefLayerSupport::IsReshapeSupported(const TensorInfo& input, + const ReshapeDescriptor& descriptor, Optional reasonIfUnsupported) const { + ignore_unused(descriptor); return IsSupportedForDataTypeRef(reasonIfUnsupported, input.GetDataType(), &TrueFunc<>, diff --git a/src/backends/reference/RefLayerSupport.hpp b/src/backends/reference/RefLayerSupport.hpp index 188faa84b6..5778806f00 100644 --- a/src/backends/reference/RefLayerSupport.hpp +++ b/src/backends/reference/RefLayerSupport.hpp @@ -4,12 +4,12 @@ // #pragma once -#include +#include namespace armnn { -class RefLayerSupport : public ILayerSupport +class RefLayerSupport : public LayerSupportBase { public: bool IsActivationSupported(const TensorInfo& input, @@ -93,7 +93,7 @@ public: bool IsGreaterSupported(const TensorInfo& input0, const TensorInfo& input1, - const TensorInfo& ouput, + const TensorInfo& output, Optional reasonIfUnsupported = EmptyOptional()) const override; bool IsInputSupported(const TensorInfo& input, @@ -146,6 +146,10 @@ public: const OriginsDescriptor& descriptor, Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsMemCopySupported(const TensorInfo& input, + const TensorInfo& output, + Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsMinimumSupported(const TensorInfo& input0, const TensorInfo& input1, const TensorInfo& output, @@ -180,6 +184,7 @@ public: Optional reasonIfUnsupported = EmptyOptional()) const override; bool IsReshapeSupported(const TensorInfo& input, + const ReshapeDescriptor& descriptor, Optional reasonIfUnsupported = EmptyOptional()) const override; bool IsResizeBilinearSupported(const TensorInfo& input, -- cgit v1.2.1