From 34b429c2215bab7fd12b761dd5c200414c1b4a5b Mon Sep 17 00:00:00 2001 From: Cathal Corbett Date: Fri, 24 Dec 2021 12:24:40 +0000 Subject: IVGCVSW-6629 Stabilize the ILayerSupport interface with unified strategy. * New Virtual Function Added. * Implemented in Ref Neon CL with switch statement for all layers. * Deprecate original IsXXXLayerSupported functions. * Ensure Npu not broken with change. Change-Id: Icf61b16beec83d6af1cb287e24ab1e98a6138c8c Signed-off-by: Cathal Corbett --- src/backends/neon/NeonLayerSupport.cpp | 421 ++++++++++++++++++++++++++++++++- src/backends/neon/NeonLayerSupport.hpp | 9 +- 2 files changed, 427 insertions(+), 3 deletions(-) (limited to 'src/backends/neon') diff --git a/src/backends/neon/NeonLayerSupport.cpp b/src/backends/neon/NeonLayerSupport.cpp index d5dd238bd8..2b2229a4de 100644 --- a/src/backends/neon/NeonLayerSupport.cpp +++ b/src/backends/neon/NeonLayerSupport.cpp @@ -7,7 +7,6 @@ #include "NeonBackendId.hpp" #include "NeonBackendModelContext.hpp" -#include #include #include #include @@ -146,6 +145,424 @@ NeonLayerSupport::NeonLayerSupport() { } +bool NeonLayerSupport::IsLayerSupported(const LayerType& type, + const std::vector& infos, + const BaseDescriptor& descriptor, + const Optional& lstmParamsInfo, + const Optional& quantizedLstmParamsInfo, + Optional reasonIfUnsupported) const +{ + switch (type) + { + case LayerType::Activation: + return IsActivationSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Addition: + return IsAdditionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported); + case LayerType::ArgMinMax: + return IsArgMinMaxSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::BatchNormalization: + return IsBatchNormalizationSupported(infos[0], + infos[1], + infos[2], + infos[3], + infos[4], + infos[5], + *(PolymorphicDowncast + (&descriptor)), + reasonIfUnsupported); + case LayerType::BatchToSpaceNd: + return IsBatchToSpaceNdSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Comparison: + return IsComparisonSupported(infos[0], + infos[1], + infos[2], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Concat: + { + std::vector inputInfos; + for (uint32_t i = 0; i < (infos.size() - 1); i++) + { + inputInfos.push_back(&infos[i]); + } + return IsConcatSupported(inputInfos, + infos[infos.size() - 1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + } + case LayerType::Constant: + return IsConstantSupported(infos[0], reasonIfUnsupported); + case LayerType::ConvertBf16ToFp32: + return IsConvertBf16ToFp32Supported(infos[0], infos[1], reasonIfUnsupported); + case LayerType::ConvertFp16ToFp32: + return IsConvertFp16ToFp32Supported(infos[0], infos[1], reasonIfUnsupported); + case LayerType::ConvertFp32ToBf16: + return IsConvertFp32ToBf16Supported(infos[0], infos[1], reasonIfUnsupported); + case LayerType::ConvertFp32ToFp16: + return IsConvertFp32ToFp16Supported(infos[0], infos[1], reasonIfUnsupported); + case LayerType::Convolution2d: + { + if (infos.size() != 4) + { + throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. " + "TensorInfos should be of format: {input, output, weights, biases}."); + } + + auto desc = *(PolymorphicDowncast(&descriptor)); + if (infos[3] == TensorInfo()) + { + return IsConvolution2dSupported(infos[0], + infos[1], + desc, + infos[2], + EmptyOptional(), + reasonIfUnsupported); + } + else + { + return IsConvolution2dSupported(infos[0], + infos[1], + desc, + infos[2], + infos[3], + reasonIfUnsupported); + } + } + case LayerType::DepthToSpace: + return IsDepthToSpaceSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::DepthwiseConvolution2d: + { + if (infos.size() != 4) + { + throw InvalidArgumentException("Invalid number of DepthwiseConvolution2d TensorInfos. " + "TensorInfos should be of format: {input, output, weights, biases}."); + } + + auto desc = *(PolymorphicDowncast(&descriptor)); + if (infos[3] == TensorInfo()) + { + return IsDepthwiseConvolutionSupported(infos[0], + infos[1], + desc, + infos[2], + EmptyOptional(), + reasonIfUnsupported); + } + else + { + return IsDepthwiseConvolutionSupported(infos[0], + infos[1], + desc, + infos[2], + infos[3], + reasonIfUnsupported); + } + } + case LayerType::Dequantize: + return IsDequantizeSupported(infos[0], infos[1], reasonIfUnsupported); + case LayerType::Division: + return IsDivisionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported); + case LayerType::ElementwiseUnary: + return IsElementwiseUnarySupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Fill: + return IsFillSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Floor: + return IsFloorSupported(infos[0], infos[1], reasonIfUnsupported); + case LayerType::FullyConnected: + return IsFullyConnectedSupported(infos[0], + infos[1], + infos[2], + infos[3], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Gather: + return IsGatherSupported(infos[0], + infos[1], + infos[2], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Input: + return IsInputSupported(infos[0], reasonIfUnsupported); + case LayerType::InstanceNormalization: + return IsInstanceNormalizationSupported(infos[0], + infos[1], + *(PolymorphicDowncast + (&descriptor)), + reasonIfUnsupported); + case LayerType::L2Normalization: + return IsL2NormalizationSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::LogicalBinary: + return IsLogicalBinarySupported(infos[0], + infos[1], + infos[2], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::LogSoftmax: + return IsLogSoftmaxSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Lstm: + return IsLstmSupported(infos[0], + infos[1], + infos[2], + infos[3], + infos[4], + infos[5], + infos[6], + *(PolymorphicDowncast(&descriptor)), + lstmParamsInfo.value(), + reasonIfUnsupported); + case LayerType::QLstm: + return IsQLstmSupported(infos[0], + infos[1], + infos[2], + infos[3], + infos[4], + infos[5], + *(PolymorphicDowncast(&descriptor)), + lstmParamsInfo.value(), + reasonIfUnsupported); + case LayerType::Maximum: + return IsMaximumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported); + case LayerType::Mean: + return IsMeanSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Minimum: + return IsMinimumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported); + case LayerType::Multiplication: + return IsMultiplicationSupported(infos[0], infos[1], infos[2], reasonIfUnsupported); + case LayerType::Normalization: + return IsNormalizationSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Output: + return IsOutputSupported(infos[0], reasonIfUnsupported); + case LayerType::Pad: + return IsPadSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Permute: + return IsPermuteSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Pooling2d: + return IsPooling2dSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Prelu: + return IsPreluSupported(infos[0], infos[1], infos[2], reasonIfUnsupported); + case LayerType::Quantize: + return IsQuantizeSupported(infos[0], infos[1], reasonIfUnsupported); + case LayerType::QuantizedLstm: + return IsQuantizedLstmSupported(infos[0], + infos[1], + infos[2], + infos[3], + infos[4], + quantizedLstmParamsInfo.value(), + reasonIfUnsupported); + case LayerType::Reshape: + return IsReshapeSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Resize: + return IsResizeSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Reduce: + return IsReduceSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Slice: + return IsSliceSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Softmax: + return IsSoftmaxSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::SpaceToBatchNd: + return IsSpaceToBatchNdSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::SpaceToDepth: + return IsSpaceToDepthSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Splitter: + { + std::vector outputInfos; + for (uint32_t i = 1; i < infos.size(); i++) + { + outputInfos.push_back(infos[i]); + } + return IsSplitterSupported(infos[0], + {outputInfos.begin(), outputInfos.end()}, + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + } + case LayerType::Stack: + { + std::vector inputInfos; + for (uint32_t i = 0; i < infos.size() - 1; i++) + { + inputInfos.push_back(&infos[i]); + } + return IsStackSupported(inputInfos, + infos[infos.size() - 1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + } + case LayerType::StridedSlice: + return IsStridedSliceSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Subtraction: + return IsSubtractionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported); + case LayerType::Transpose: + return IsTransposeSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::TransposeConvolution2d: + { + if (infos.size() != 4) + { + throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. " + "TensorInfos should be of format: {input, output, weights, biases}."); + } + + auto desc = *(PolymorphicDowncast(&descriptor)); + if (infos[3] == TensorInfo()) + { + return IsTransposeConvolution2dSupported(infos[0], + infos[1], + desc, + infos[2], + EmptyOptional(), + reasonIfUnsupported); + } + else + { + return IsTransposeConvolution2dSupported(infos[0], + infos[1], + desc, + infos[2], + infos[3], + reasonIfUnsupported); + } + } + case LayerType::Cast: + return IsCastSupported(infos[0], infos[1], reasonIfUnsupported); + case LayerType::ChannelShuffle: + return IsChannelShuffleSupported(infos[0], + infos[1], + *(PolymorphicDowncast(&descriptor)), + reasonIfUnsupported); + case LayerType::Convolution3d: + { + if (infos.size() != 4) + { + throw InvalidArgumentException("Invalid number of Convolution3d TensorInfos. " + "TensorInfos should be of format: {input, output, weights, biases}."); + } + + auto desc = *(PolymorphicDowncast(&descriptor)); + if (infos[3] == TensorInfo()) + { + return IsConvolution3dSupported(infos[0], + infos[1], + desc, + infos[2], + EmptyOptional(), + reasonIfUnsupported); + } + else + { + return IsConvolution3dSupported(infos[0], + infos[1], + desc, + infos[2], + infos[3], + reasonIfUnsupported); + } + } + case LayerType::MemCopy: + return LayerSupportBase::IsMemCopySupported(infos[0], infos[1], reasonIfUnsupported); + case LayerType::MemImport: + return LayerSupportBase::IsMemImportSupported(infos[0], infos[1], reasonIfUnsupported); + case LayerType::DetectionPostProcess: + { + auto desc = *(PolymorphicDowncast(&descriptor)); + return LayerSupportBase::IsDetectionPostProcessSupported(infos[0], + infos[1], + infos[2], + infos[3], + infos[4], + infos[5], + infos[6], + desc, + reasonIfUnsupported); + } + case LayerType::Map: + return true; + case LayerType::Unmap: + return true; + case LayerType::Merge: + return LayerSupportBase::IsMergeSupported(infos[0], + infos[1], + infos[2], + reasonIfUnsupported); + case LayerType::Rank: + return true; + case LayerType::Shape: + return LayerSupportBase::IsShapeSupported(infos[0], + infos[1], + reasonIfUnsupported); + default: + // layers not supported in neon by default: + // debug, fakequantization, precompiled, standin, + // switch, unidirectionalsequencelstm, pooling3d + return false; + } +} + bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input, const TensorInfo& output, const ActivationDescriptor& descriptor, @@ -256,7 +673,7 @@ bool NeonLayerSupport::IsComparisonSupported(const TensorInfo& input0, bool NeonLayerSupport::IsConcatSupported(const std::vector inputs, const TensorInfo& output, - const ConcatDescriptor& descriptor, + const OriginsDescriptor& descriptor, Optional reasonIfUnsupported) const { if (descriptor.GetNumDimensions() <= descriptor.GetConcatAxis()) diff --git a/src/backends/neon/NeonLayerSupport.hpp b/src/backends/neon/NeonLayerSupport.hpp index 16507c595e..afa9b419e6 100644 --- a/src/backends/neon/NeonLayerSupport.hpp +++ b/src/backends/neon/NeonLayerSupport.hpp @@ -19,6 +19,13 @@ public: ~NeonLayerSupport() {} + bool IsLayerSupported(const LayerType& type, + const std::vector& infos, + const BaseDescriptor& descriptor, + const Optional& lstmParamsInfo, + const Optional& quantizedLstmParamsInfo, + Optional reasonIfUnsupported) const override; + bool IsActivationSupported(const TensorInfo& input, const TensorInfo& output, const ActivationDescriptor& descriptor, @@ -65,7 +72,7 @@ public: bool IsConcatSupported(const std::vector inputs, const TensorInfo& output, - const ConcatDescriptor& descriptor, + const OriginsDescriptor& descriptor, Optional reasonIfUnsupported = EmptyOptional()) const override; bool IsConstantSupported(const TensorInfo& output, -- cgit v1.2.1