From 4e1e136cce3fca73ba49b570cfcb620f4ec574da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89anna=20=C3=93=20Cath=C3=A1in?= Date: Mon, 12 Nov 2018 11:36:34 +0000 Subject: IVGCVSW-2054: BATCH_TO_SPACE_ND Reference implementation and Unit tests. Change-Id: I13c6728dbb60643d0e086d171225c5d802987f92 --- src/backends/backendsCommon/ILayerSupport.cpp | 8 + src/backends/backendsCommon/WorkloadData.cpp | 8 +- src/backends/backendsCommon/WorkloadData.hpp | 4 + src/backends/backendsCommon/WorkloadFactory.cpp | 12 ++ src/backends/backendsCommon/WorkloadFactory.hpp | 3 + .../test/IsLayerSupportedTestImpl.hpp | 16 ++ src/backends/backendsCommon/test/LayerTests.cpp | 167 +++++++++++++++++++++ src/backends/backendsCommon/test/LayerTests.hpp | 6 + 8 files changed, 223 insertions(+), 1 deletion(-) (limited to 'src/backends/backendsCommon') diff --git a/src/backends/backendsCommon/ILayerSupport.cpp b/src/backends/backendsCommon/ILayerSupport.cpp index ebfff5d429..2cd57b7ad7 100644 --- a/src/backends/backendsCommon/ILayerSupport.cpp +++ b/src/backends/backendsCommon/ILayerSupport.cpp @@ -59,6 +59,14 @@ bool ILayerSupport::IsBatchNormalizationSupported(const TensorInfo& input, 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 { diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index 7c02947b32..9fbdfe94c2 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -918,4 +918,10 @@ void PadQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const } } -} //namespace armnn +void BatchToSpaceNdQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const +{ + ValidateSingleInput(workloadInfo, "BatchToSpaceNdQueueDescriptor"); + ValidateSingleOutput(workloadInfo, "BatchToSpaceNdQueueDescriptor"); +} + +} //namespace armnn \ No newline at end of file diff --git a/src/backends/backendsCommon/WorkloadData.hpp b/src/backends/backendsCommon/WorkloadData.hpp index 7fb8855bf6..d54a71aa8c 100644 --- a/src/backends/backendsCommon/WorkloadData.hpp +++ b/src/backends/backendsCommon/WorkloadData.hpp @@ -335,4 +335,8 @@ struct ConvertFp32ToFp16QueueDescriptor : QueueDescriptor void Validate(const WorkloadInfo& workloadInfo) const; }; +struct BatchToSpaceNdQueueDescriptor : QueueDescriptorWithParameters +{ + void Validate(const WorkloadInfo& workloadInfo) const; +}; } //namespace armnn diff --git a/src/backends/backendsCommon/WorkloadFactory.cpp b/src/backends/backendsCommon/WorkloadFactory.cpp index 9f974522aa..ec30f34880 100644 --- a/src/backends/backendsCommon/WorkloadFactory.cpp +++ b/src/backends/backendsCommon/WorkloadFactory.cpp @@ -116,6 +116,18 @@ bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId, reason); break; } + case LayerType::BatchToSpaceNd: + { + const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo(); + const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo(); + auto cLayer = boost::polymorphic_downcast(&layer); + + result = layerSupportObject->IsBatchToSpaceNdSupported(OverrideDataType(input, dataType), + OverrideDataType(output, dataType), + cLayer->GetParameters(), + reason); + break; + } case LayerType::Constant: { const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo(); diff --git a/src/backends/backendsCommon/WorkloadFactory.hpp b/src/backends/backendsCommon/WorkloadFactory.hpp index 67876e13a2..e3be9f501f 100644 --- a/src/backends/backendsCommon/WorkloadFactory.hpp +++ b/src/backends/backendsCommon/WorkloadFactory.hpp @@ -97,6 +97,9 @@ public: virtual std::unique_ptr CreateBatchNormalization(const BatchNormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const = 0; + virtual std::unique_ptr CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor, + const WorkloadInfo& Info) const = 0; + virtual std::unique_ptr CreateMemCopy(const MemCopyQueueDescriptor& descriptor, const WorkloadInfo& info) const = 0; diff --git a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp index 2c992bc10b..25079058f6 100644 --- a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp +++ b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp @@ -91,6 +91,20 @@ struct DummyLayer }; +template<> +struct DummyLayer +{ + DummyLayer() + { + m_Layer = dummyGraph.AddLayer(armnn::BatchToSpaceNdDescriptor(), ""); + } + ~DummyLayer() + { + dummyGraph.EraseLayer(m_Layer); + } + armnn::BatchToSpaceNdLayer* m_Layer; +}; + template<> struct DummyLayer { @@ -306,6 +320,8 @@ DECLARE_LAYER_POLICY_1_PARAM(Addition) DECLARE_LAYER_POLICY_2_PARAM(BatchNormalization) +DECLARE_LAYER_POLICY_2_PARAM(BatchToSpaceNd) + DECLARE_LAYER_POLICY_1_PARAM(Constant) DECLARE_LAYER_POLICY_1_PARAM(ConvertFp16ToFp32) diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp index cdc989fe6d..4a003036ca 100755 --- a/src/backends/backendsCommon/test/LayerTests.cpp +++ b/src/backends/backendsCommon/test/LayerTests.cpp @@ -6169,3 +6169,170 @@ LayerTestResult SpaceToBatchNdPaddingNHWCUint8Test(armnn::IWorkloadF { return SpaceToBatchNdPaddingNHWCTest(workloadFactory); } + +namespace { + +template +LayerTestResult BatchToSpaceNdHelper(armnn::IWorkloadFactory &workloadFactory, + const armnn::DataLayout& dataLayout, + const unsigned int *inputShape, + const std::vector &inputData, + const std::vector &blockShape, + const std::vector> &crops, + const unsigned int *outputShape, + const std::vector &outputData, + float scale = 1.0f, + int32_t offset = 0) + { + auto dataType = (std::is_same::value ? armnn::DataType::QuantisedAsymm8 : armnn::DataType::Float32); + + armnn::TensorInfo inputTensorInfo(InputDim, inputShape, dataType); + armnn::TensorInfo outputTensorInfo(OutputDim, outputShape, dataType); + + inputTensorInfo.SetQuantizationScale(scale); + inputTensorInfo.SetQuantizationOffset(offset); + + outputTensorInfo.SetQuantizationScale(scale); + outputTensorInfo.SetQuantizationOffset(offset); + + auto input = MakeTensor(inputTensorInfo, inputData); + + LayerTestResult result(outputTensorInfo); + result.outputExpected = MakeTensor(outputTensorInfo, outputData); + + std::unique_ptr inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo); + std::unique_ptr outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo); + + armnn::BatchToSpaceNdQueueDescriptor data; + data.m_Parameters.m_DataLayout = dataLayout; + data.m_Parameters.m_BlockShape = blockShape; + data.m_Parameters.m_Crops = crops; + armnn::WorkloadInfo info; + AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); + AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); + + std::unique_ptr workload = workloadFactory.CreateBatchToSpaceNd(data, info); + + inputHandle->Allocate(); + outputHandle->Allocate(); + + CopyDataToITensorHandle(inputHandle.get(), input.origin()); + + workload->Execute(); + + CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get()); + + return result; +} + +} // anonymous namespace + +LayerTestResult BatchToSpaceNdNhwcFloat32Test1(armnn::IWorkloadFactory& workloadFactory) +{ + const unsigned int inputShape[] = {4, 2, 2, 1}; + const unsigned int outputShape[] = {1, 4, 4, 1 }; + + std::vector input + ({ + // Batch 0, Height 0, Width (2) x Channel (1) + 1.0f, 3.0f, + // Batch 0, Height 1, Width (2) x Channel (1) + 9.0f, 11.0f, + + + // Batch 1, Height 0, Width (2) x Channel (1) + 2.0f, 4.0f, + // Batch 1, Height 1, Width (2) x Channel (1) + 10.0f, 12.0f, + + + // Batch 2, Height 0, Width (2) x Channel (1) + 5.0f, 7.0f, + // Batch 2, Height 1, Width (2) x Channel (1) + 13.0f, 15.0f, + + // Batch 3, Height 0, Width (2) x Channel (3) + 6.0f, 8.0f, + // Batch 3, Height 1, Width (2) x Channel (1) + 14.0f, 16.0f + }); + + std::vector expectedOutput + ({ + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f + }); + + std::vector blockShape {2, 2}; + std::vector> crops = {{0, 0}, {0, 0}}; + + return BatchToSpaceNdHelper(workloadFactory, armnn::DataLayout::NHWC, inputShape, input, blockShape, + crops, outputShape, expectedOutput); +} + +LayerTestResult BatchToSpaceNdNhwcFloat32Test2(armnn::IWorkloadFactory& workloadFactory) +{ + const unsigned int inputShape[] = {4, 1, 1, 1}; + const unsigned int outputShape[] = {1, 2, 2, 1}; + + std::vector input + ({ + // Batch 0, Height 0, Width (2) x Channel (1) + 1.0f, 2.0f, 3.0f, 4.0f + }); + + std::vector expectedOutput({1.0f, 2.0f, 3.0f, 4.0f}); + + std::vector blockShape({2, 2}); + std::vector> crops = {{0, 0}, {0, 0}}; + + return BatchToSpaceNdHelper(workloadFactory, armnn::DataLayout::NHWC, inputShape, input, blockShape, + crops, outputShape, expectedOutput); +} + +LayerTestResult BatchToSpaceNdNhwcFloat32Test3(armnn::IWorkloadFactory& workloadFactory) +{ + const unsigned int inputShape[] = {4, 1, 1, 3}; + const unsigned int outputShape[] = {1, 2, 2, 3}; + + std::vector input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f }); + + std::vector expectedOutput({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f }); + + std::vector blockShape({2, 2}); + std::vector> crops = {{0, 0}, {0, 0}}; + + return BatchToSpaceNdHelper(workloadFactory, armnn::DataLayout::NHWC, inputShape, input, blockShape, + crops, outputShape, expectedOutput); +} + +LayerTestResult BatchToSpaceNdNchwFloat32Test1(armnn::IWorkloadFactory &workloadFactory) +{ + const unsigned int inputShape[] = {4, 3, 1, 1}; + const unsigned int outputShape[] = {1, 3, 2, 2}; + + std::vector input({ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f }); + + std::vector expectedOutput + ({ + // Batch 0, Channel 0, Height (2) x Width (2) + 1.0f, 4.0f, + 7.0f, 10.0f, + + // Batch 0, Channel 1, Height (2) x Width (2) + 2.0f, 5.0f, + 8.0f, 11.0f, + + // Batch 0, Channel 2, Height (2) x Width (2) + 3.0f, 6.0f, + 9.0f, 12.0f, + }); + + std::vector blockShape({2, 2}); + std::vector> crops = {{0, 0}, {0, 0}}; + + return BatchToSpaceNdHelper(workloadFactory, armnn::DataLayout::NCHW, inputShape, input, blockShape, + crops, outputShape, expectedOutput); +} diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp index 66032c8f2a..cd8758e477 100644 --- a/src/backends/backendsCommon/test/LayerTests.hpp +++ b/src/backends/backendsCommon/test/LayerTests.hpp @@ -434,3 +434,9 @@ LayerTestResult SpaceToBatchNdSimpleNHWCUint8Test(armnn::IWorkloadFa LayerTestResult SpaceToBatchNdMultiChannelsNHWCUint8Test(armnn::IWorkloadFactory& workloadFactory); LayerTestResult SpaceToBatchNdMultiBlockNHWCUint8Test(armnn::IWorkloadFactory& workloadFactory); LayerTestResult SpaceToBatchNdPaddingNHWCUint8Test(armnn::IWorkloadFactory& workloadFactory); + +LayerTestResult BatchToSpaceNdNhwcFloat32Test1(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult BatchToSpaceNdNhwcFloat32Test2(armnn::IWorkloadFactory& workloadFactory); +LayerTestResult BatchToSpaceNdNhwcFloat32Test3(armnn::IWorkloadFactory& workloadFactory); + +LayerTestResult BatchToSpaceNdNchwFloat32Test1(armnn::IWorkloadFactory &workloadFactory); -- cgit v1.2.1