From 639fb0437d1a5a8a6ea737fed5a16b554dfffead Mon Sep 17 00:00:00 2001 From: Aron Virginas-Tar Date: Thu, 20 Jun 2019 14:28:19 +0100 Subject: IVGCVSW-3319 Add frontend support for TransposeConvolution2d Layer Signed-off-by: Aron Virginas-Tar Change-Id: Ic06f63f1eff255e697facf319e2ac4c83d782e7c --- src/backends/backendsCommon/LayerSupportBase.cpp | 10 ++++++ src/backends/backendsCommon/LayerSupportBase.hpp | 8 +++++ src/backends/backendsCommon/WorkloadData.cpp | 41 ++++++++++++++++++++++ src/backends/backendsCommon/WorkloadData.hpp | 13 +++++++ src/backends/backendsCommon/WorkloadFactory.cpp | 37 +++++++++++++++++++ src/backends/backendsCommon/WorkloadFactory.hpp | 6 +++- .../test/IsLayerSupportedTestImpl.hpp | 8 +++++ 7 files changed, 122 insertions(+), 1 deletion(-) (limited to 'src/backends') diff --git a/src/backends/backendsCommon/LayerSupportBase.cpp b/src/backends/backendsCommon/LayerSupportBase.cpp index 12e4ee81ae..2eb0e4161e 100644 --- a/src/backends/backendsCommon/LayerSupportBase.cpp +++ b/src/backends/backendsCommon/LayerSupportBase.cpp @@ -448,4 +448,14 @@ bool LayerSupportBase::IsSwitchSupported(const TensorInfo& input0, return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); } +bool LayerSupportBase::IsTransposeConvolution2dSupported(const TensorInfo& input, + const TensorInfo& output, + const TransposeConvolution2dDescriptor& descriptor, + const TensorInfo& weights, + const Optional& biases, + 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 index d035dfcd62..52ba5b216f 100644 --- a/src/backends/backendsCommon/LayerSupportBase.hpp +++ b/src/backends/backendsCommon/LayerSupportBase.hpp @@ -282,6 +282,14 @@ public: const TensorInfo& output0, const TensorInfo& output1, Optional reasonIfUnsupported = EmptyOptional()) const override; + + bool IsTransposeConvolution2dSupported( + const TensorInfo& input, + const TensorInfo& output, + const TransposeConvolution2dDescriptor& descriptor, + const TensorInfo& weights, + const Optional& biases, + Optional reasonIfUnsupported = EmptyOptional()) const override; }; } // namespace armnn diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index adba86c79a..5ca492888f 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -1800,4 +1800,45 @@ void PreluQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const "alpha"); } +void TransposeConvolution2dQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const +{ + const std::string descriptorName{"TransposeConvolution2dQueueDescriptor"}; + + ValidateNumInputs(workloadInfo, descriptorName, 1); + ValidateNumOutputs(workloadInfo, descriptorName, 1); + + ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], descriptorName, 4, "input"); + ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], descriptorName, 4, "output"); + + ValidatePointer(m_Weight, descriptorName, "weight"); + ValidateTensorNumDimensions(m_Weight->GetTensorInfo(), descriptorName, 4, "weight"); + + ValidateTensorDataType(m_Weight->GetTensorInfo(), + workloadInfo.m_InputTensorInfos[0].GetDataType(), + descriptorName, + "weight"); + + if (m_Parameters.m_BiasEnabled) + { + ValidateTensorNumDimensions(m_Bias->GetTensorInfo(), descriptorName, 1, "bias"); + + ValidateTensorDataType(m_Bias->GetTensorInfo(), + GetBiasDataType(workloadInfo.m_InputTensorInfos[0].GetDataType()), + descriptorName, "bias"); + + ValidateBiasTensorQuantization(m_Bias->GetTensorInfo(), + workloadInfo.m_InputTensorInfos[0], + m_Weight->GetTensorInfo(), + descriptorName); + } + + ValidateTensorQuantizationMultiplier(workloadInfo.m_InputTensorInfos[0], + m_Weight->GetTensorInfo(), + workloadInfo.m_OutputTensorInfos[0], + descriptorName, + "input", + "weights", + "output"); +} + } //namespace armnn diff --git a/src/backends/backendsCommon/WorkloadData.hpp b/src/backends/backendsCommon/WorkloadData.hpp index 6a51bc3144..744758385b 100644 --- a/src/backends/backendsCommon/WorkloadData.hpp +++ b/src/backends/backendsCommon/WorkloadData.hpp @@ -445,4 +445,17 @@ struct PreluQueueDescriptor : QueueDescriptor void Validate(const WorkloadInfo& workloadInfo) const; }; +struct TransposeConvolution2dQueueDescriptor : QueueDescriptorWithParameters +{ + TransposeConvolution2dQueueDescriptor() : + m_Weight(nullptr), + m_Bias(nullptr) + {} + + const ConstCpuTensorHandle* m_Weight; + const ConstCpuTensorHandle* m_Bias; + + void Validate(const WorkloadInfo& workloadInfo) const; +}; + } //namespace armnn diff --git a/src/backends/backendsCommon/WorkloadFactory.cpp b/src/backends/backendsCommon/WorkloadFactory.cpp index cca39198e1..2fba3b7059 100644 --- a/src/backends/backendsCommon/WorkloadFactory.cpp +++ b/src/backends/backendsCommon/WorkloadFactory.cpp @@ -796,6 +796,36 @@ bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId, reason); break; } + case LayerType::TransposeConvolution2d: + { + auto cLayer = boost::polymorphic_downcast(&layer); + + const TensorInfo input = OverrideDataType(layer.GetInputSlot(0).GetConnection()->GetTensorInfo(), + dataType); + const TensorInfo output = OverrideDataType(layer.GetOutputSlot(0).GetTensorInfo(), dataType); + + const TransposeConvolution2dDescriptor& descriptor = cLayer->GetParameters(); + + Optional biases; + if (descriptor.m_BiasEnabled) + { + BOOST_ASSERT(cLayer->m_Bias.get() != nullptr); + biases = OverrideDataType(cLayer->m_Bias->GetTensorInfo(), + GetBiasTypeFromWeightsType(dataType)); + } + + BOOST_ASSERT(cLayer->m_Weight.get() != nullptr); + const TensorInfo weights = OverrideDataType(cLayer->m_Weight->GetTensorInfo(), dataType); + + result = layerSupportObject->IsTransposeConvolution2dSupported(input, + output, + descriptor, + weights, + biases, + reason); + + break; + } default: { BOOST_ASSERT_MSG(false, "WorkloadFactory did not recognise type of layer."); @@ -1098,4 +1128,11 @@ std::unique_ptr IWorkloadFactory::CreateSwitch(const SwitchQueueDescr return std::unique_ptr(); } +std::unique_ptr IWorkloadFactory::CreateTransposeConvolution2d( + const TransposeConvolution2dQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return std::unique_ptr(); } + +} // namepsace armnn \ No newline at end of file diff --git a/src/backends/backendsCommon/WorkloadFactory.hpp b/src/backends/backendsCommon/WorkloadFactory.hpp index c9fbe71f96..978d3a3a98 100644 --- a/src/backends/backendsCommon/WorkloadFactory.hpp +++ b/src/backends/backendsCommon/WorkloadFactory.hpp @@ -190,6 +190,10 @@ public: virtual std::unique_ptr CreateSwitch(const SwitchQueueDescriptor& descriptor, const WorkloadInfo& Info) const; + + virtual std::unique_ptr CreateTransposeConvolution2d( + const TransposeConvolution2dQueueDescriptor& descriptor, + const WorkloadInfo& info) const; }; -} //namespace armnn +} // namespace armnn diff --git a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp index 111cf8f3e3..7c9d0f52c3 100644 --- a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp +++ b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp @@ -212,6 +212,12 @@ struct DummyLayer { }; +template<> +struct DummyLayer + : public DummyConvolutionLayer +{ +}; + template struct DummyLstmLayer { @@ -408,6 +414,8 @@ DECLARE_LAYER_POLICY_1_PARAM(Subtraction) DECLARE_LAYER_POLICY_1_PARAM(Switch) +DECLARE_LAYER_POLICY_2_PARAM(TransposeConvolution2d) + // Generic implementation to get the number of input slots for a given layer type; template -- cgit v1.2.1