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 + src/backends/cl/ClWorkloadFactory.cpp | 12 ++ src/backends/cl/ClWorkloadFactory.hpp | 3 + src/backends/neon/NeonWorkloadFactory.cpp | 12 ++ src/backends/neon/NeonWorkloadFactory.hpp | 3 + src/backends/reference/RefLayerSupport.cpp | 16 ++ src/backends/reference/RefLayerSupport.hpp | 5 + src/backends/reference/RefWorkloadFactory.cpp | 5 + src/backends/reference/RefWorkloadFactory.hpp | 3 + src/backends/reference/backend.mk | 3 + src/backends/reference/test/RefLayerTests.cpp | 6 + .../reference/workloads/BatchToSpaceNd.cpp | 100 ++++++++++++ .../reference/workloads/BatchToSpaceNd.hpp | 22 +++ src/backends/reference/workloads/CMakeLists.txt | 6 + .../workloads/RefBatchToSpaceNdFloat32Workload.cpp | 28 ++++ .../workloads/RefBatchToSpaceNdFloat32Workload.hpp | 22 +++ .../workloads/RefBatchToSpaceNdUint8Workload.cpp | 30 ++++ .../workloads/RefBatchToSpaceNdUint8Workload.hpp | 23 +++ src/backends/reference/workloads/RefWorkloads.hpp | 4 +- 26 files changed, 525 insertions(+), 2 deletions(-) create mode 100644 src/backends/reference/workloads/BatchToSpaceNd.cpp create mode 100644 src/backends/reference/workloads/BatchToSpaceNd.hpp create mode 100644 src/backends/reference/workloads/RefBatchToSpaceNdFloat32Workload.cpp create mode 100644 src/backends/reference/workloads/RefBatchToSpaceNdFloat32Workload.hpp create mode 100644 src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.cpp create mode 100644 src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.hpp (limited to 'src/backends') 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); diff --git a/src/backends/cl/ClWorkloadFactory.cpp b/src/backends/cl/ClWorkloadFactory.cpp index eece934ea3..0862ea163e 100644 --- a/src/backends/cl/ClWorkloadFactory.cpp +++ b/src/backends/cl/ClWorkloadFactory.cpp @@ -314,6 +314,12 @@ std::unique_ptr ClWorkloadFactory::CreatePad(const PadQueueDescriptor return MakeWorkload(descriptor, info); } +std::unique_ptr ClWorkloadFactory::CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return MakeWorkload(descriptor, info); +} + void ClWorkloadFactory::Release() { m_MemoryManager.Release(); @@ -530,6 +536,12 @@ std::unique_ptr ClWorkloadFactory::CreatePad(const PadQueueDescriptor return nullptr; } +std::unique_ptr ClWorkloadFactory::CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return nullptr; +} + void ClWorkloadFactory::Release() { } diff --git a/src/backends/cl/ClWorkloadFactory.hpp b/src/backends/cl/ClWorkloadFactory.hpp index c45bc15839..6a928dbbfc 100644 --- a/src/backends/cl/ClWorkloadFactory.hpp +++ b/src/backends/cl/ClWorkloadFactory.hpp @@ -126,6 +126,9 @@ public: virtual std::unique_ptr CreatePad(const PadQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + virtual std::unique_ptr CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; + virtual void Release() override; virtual void Acquire() override; diff --git a/src/backends/neon/NeonWorkloadFactory.cpp b/src/backends/neon/NeonWorkloadFactory.cpp index 11b5634a79..f0d916b63b 100644 --- a/src/backends/neon/NeonWorkloadFactory.cpp +++ b/src/backends/neon/NeonWorkloadFactory.cpp @@ -279,6 +279,12 @@ std::unique_ptr NeonWorkloadFactory::CreatePad(const PadQueueDescript return MakeWorkloadHelper(descriptor, info); } +std::unique_ptr NeonWorkloadFactory::CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return MakeWorkloadHelper(descriptor, info); +} + void NeonWorkloadFactory::Release() { m_MemoryManager.Release(); @@ -495,6 +501,12 @@ std::unique_ptr NeonWorkloadFactory::CreatePad(const PadQueueDescript return nullptr; } +std::unique_ptr NeonWorkloadFactory::CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return nullptr; +} + void NeonWorkloadFactory::Release() {} diff --git a/src/backends/neon/NeonWorkloadFactory.hpp b/src/backends/neon/NeonWorkloadFactory.hpp index 9b574f6a14..98f323afdf 100644 --- a/src/backends/neon/NeonWorkloadFactory.hpp +++ b/src/backends/neon/NeonWorkloadFactory.hpp @@ -128,6 +128,9 @@ public: virtual std::unique_ptr CreatePad(const PadQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + virtual std::unique_ptr CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor, + const WorkloadInfo& Info) const override; + virtual void Release() override; virtual void Acquire() override; diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp index 0902b0fd17..b057370459 100644 --- a/src/backends/reference/RefLayerSupport.cpp +++ b/src/backends/reference/RefLayerSupport.cpp @@ -101,6 +101,22 @@ bool RefLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input, &TrueFunc<>); } +bool RefLayerSupport::IsBatchToSpaceNdSupported(const TensorInfo& input, + const TensorInfo& output, + const BatchToSpaceNdDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + ignore_unused(descriptor); + return (IsSupportedForDataTypeRef(reasonIfUnsupported, + input.GetDataType(), + &TrueFunc<>, + &TrueFunc<>) && + IsSupportedForDataTypeRef(reasonIfUnsupported, + output.GetDataType(), + &TrueFunc<>, + &TrueFunc<>)); +} + bool RefLayerSupport::IsConstantSupported(const TensorInfo& output, Optional reasonIfUnsupported) const { diff --git a/src/backends/reference/RefLayerSupport.hpp b/src/backends/reference/RefLayerSupport.hpp index b161f5c7cf..2e86ecee29 100644 --- a/src/backends/reference/RefLayerSupport.hpp +++ b/src/backends/reference/RefLayerSupport.hpp @@ -31,6 +31,11 @@ public: 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; diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp index a238d5f545..afffd65285 100644 --- a/src/backends/reference/RefWorkloadFactory.cpp +++ b/src/backends/reference/RefWorkloadFactory.cpp @@ -270,5 +270,10 @@ std::unique_ptr RefWorkloadFactory::CreatePad(const PadQueueDescripto return MakeWorkload(descriptor, info); } +std::unique_ptr RefWorkloadFactory::CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return MakeWorkload(descriptor, info); +} } // namespace armnn diff --git a/src/backends/reference/RefWorkloadFactory.hpp b/src/backends/reference/RefWorkloadFactory.hpp index e9b298d376..91bba84038 100644 --- a/src/backends/reference/RefWorkloadFactory.hpp +++ b/src/backends/reference/RefWorkloadFactory.hpp @@ -143,6 +143,9 @@ public: virtual std::unique_ptr CreatePad(const PadQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + + virtual std::unique_ptr CreateBatchToSpaceNd(const BatchToSpaceNdQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; private: template diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk index cc8c24f394..7d56144f18 100644 --- a/src/backends/reference/backend.mk +++ b/src/backends/reference/backend.mk @@ -13,6 +13,7 @@ BACKEND_SOURCES := \ RefWorkloadFactory.cpp \ workloads/Activation.cpp \ workloads/ArithmeticFunction.cpp \ + workloads/BatchToSpaceNd.cpp \ workloads/Broadcast.cpp \ workloads/ConvImpl.cpp \ workloads/FullyConnected.cpp \ @@ -25,6 +26,8 @@ BACKEND_SOURCES := \ workloads/RefBaseConstantWorkload.cpp \ workloads/RefBatchNormalizationFloat32Workload.cpp \ workloads/RefBatchNormalizationUint8Workload.cpp \ + workloads/RefBatchToSpaceNdFloat32Workload.cpp \ + workloads/RefBatchToSpaceNdUint8Workload.cpp \ workloads/RefConstantFloat32Workload.cpp \ workloads/RefConstantUint8Workload.cpp \ workloads/RefConvertFp16ToFp32Workload.cpp \ diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp index df0e37866d..703ec58208 100644 --- a/src/backends/reference/test/RefLayerTests.cpp +++ b/src/backends/reference/test/RefLayerTests.cpp @@ -376,4 +376,10 @@ ARMNN_AUTO_TEST_CASE(SpaceToBatchNdMultiChannelsNHWCUint8, SpaceToBatchNdMultiCh ARMNN_AUTO_TEST_CASE(SpaceToBatchNdMultiBlockNHWCUint8, SpaceToBatchNdMultiBlockNHWCUint8Test) ARMNN_AUTO_TEST_CASE(SpaceToBatchNdPaddingNHWCUint8, SpaceToBatchNdPaddingNHWCUint8Test) +ARMNN_AUTO_TEST_CASE(BatchToSpaceNdNhwcFloat321, BatchToSpaceNdNhwcFloat32Test1) +ARMNN_AUTO_TEST_CASE(BatchToSpaceNdNhwcFloat322, BatchToSpaceNdNhwcFloat32Test2) +ARMNN_AUTO_TEST_CASE(BatchToSpaceNdNhwcFloat323, BatchToSpaceNdNhwcFloat32Test3) + +ARMNN_AUTO_TEST_CASE(BatchToSpaceNdNchwFloat321, BatchToSpaceNdNchwFloat32Test1) + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/backends/reference/workloads/BatchToSpaceNd.cpp b/src/backends/reference/workloads/BatchToSpaceNd.cpp new file mode 100644 index 0000000000..bedf8418ef --- /dev/null +++ b/src/backends/reference/workloads/BatchToSpaceNd.cpp @@ -0,0 +1,100 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "BatchToSpaceNd.hpp" + +#include "RefWorkloadUtils.hpp" + +#include + +#include + +namespace armnn +{ + +inline unsigned int Offset(const TensorShape& shape, unsigned int batch, unsigned int height, unsigned int width, + unsigned int channels, const DataLayoutIndexed& dataLayout) +{ + if (dataLayout.GetDataLayout() == DataLayout::NHWC) + { + return ((batch * shape[dataLayout.GetHeightIndex()] + height) * shape[dataLayout.GetWidthIndex()] + width) * + shape[dataLayout.GetChannelsIndex()] + channels; + } + else + { + return ((batch * shape[dataLayout.GetChannelsIndex()] + channels) * + shape[dataLayout.GetHeightIndex()] + height) * + shape[dataLayout.GetWidthIndex()] + width; + } +} + +void BatchToSpaceNd(const DataLayoutIndexed& dataLayout, + const TensorInfo& inputTensorInfo, + const TensorInfo& outputTensorInfo, + const std::vector& blockShape, + const std::vector>& cropsData, + const float* inputData, + float* outputData) +{ + TensorShape inputShape = inputTensorInfo.GetShape(); + unsigned int inputNumDims = inputShape.GetNumDimensions(); + if (inputNumDims != 4) + { + throw armnn::InvalidArgumentException("Expected Input with 4 Dimensions"); + } + + TensorShape outputShape = outputTensorInfo.GetShape(); + unsigned int outputNumDims = outputShape.GetNumDimensions(); + if (outputNumDims != 4) + { + throw armnn::InvalidArgumentException("Expected Output with 4 Dimensions"); + } + + const unsigned int inputBatchSize = inputShape[0]; + const unsigned int channels = inputShape[dataLayout.GetChannelsIndex()]; + + const unsigned int outputBatchSize = outputShape[0]; + const unsigned int outputHeight = outputShape[dataLayout.GetHeightIndex()]; + const unsigned int outputWidth = outputShape[dataLayout.GetWidthIndex()]; + + const unsigned int blockShapeHeight = blockShape[0]; + const unsigned int blockShapeWidth = blockShape[1]; + + const unsigned int cropsTop = cropsData[0][0]; + const unsigned int cropsLeft = cropsData[1][0]; + + for (unsigned int inBatch = 0; inBatch < inputBatchSize; ++inBatch) + { + const unsigned int outBatch = inBatch % outputBatchSize; + const unsigned int spatialOffset = inBatch / outputBatchSize; + + for (unsigned int inH = 0; inH < inputTensorInfo.GetShape()[dataLayout.GetHeightIndex()]; ++inH) { + const unsigned int outH = inH * blockShapeHeight + spatialOffset / blockShapeWidth - cropsTop; + + if (outH >= outputHeight) + { + continue; + } + + for (unsigned int inW = 0; inW < inputTensorInfo.GetShape()[dataLayout.GetWidthIndex()]; ++inW) { + const unsigned int outW = inW * blockShapeWidth + spatialOffset % blockShapeWidth - cropsLeft; + + if (outW >= outputWidth) + { + continue; + } + + for (unsigned int c = 0; c < channels; c++) + { + unsigned int outOffset = Offset(outputShape, outBatch, outH, outW, c, dataLayout); + unsigned int inOffset = Offset(inputShape, inBatch, inH, inW, c, dataLayout); + outputData[outOffset] = inputData[inOffset]; + } + } + } + } +} + +} //namespace armnn diff --git a/src/backends/reference/workloads/BatchToSpaceNd.hpp b/src/backends/reference/workloads/BatchToSpaceNd.hpp new file mode 100644 index 0000000000..7923ceadd0 --- /dev/null +++ b/src/backends/reference/workloads/BatchToSpaceNd.hpp @@ -0,0 +1,22 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include +#include + +namespace armnn +{ + +void BatchToSpaceNd(const DataLayoutIndexed& dataLayout, + const TensorInfo& inputTensorInfo, + const TensorInfo& outputTensorInfo, + const std::vector& blockShape, + const std::vector>& cropsData, + const float* inputData, + float* outputData); +} // namespace armnn \ No newline at end of file diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index 4cef2d0771..1c38509ca0 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -9,6 +9,8 @@ list(APPEND armnnRefBackendWorkloads_sources ArithmeticFunction.cpp ArithmeticFunction.hpp BatchNormImpl.hpp + BatchToSpaceNd.cpp + BatchToSpaceNd.hpp Broadcast.cpp Broadcast.hpp ConvImpl.cpp @@ -32,6 +34,10 @@ list(APPEND armnnRefBackendWorkloads_sources RefBatchNormalizationFloat32Workload.hpp RefBatchNormalizationUint8Workload.cpp RefBatchNormalizationUint8Workload.hpp + RefBatchToSpaceNdFloat32Workload.cpp + RefBatchToSpaceNdFloat32Workload.hpp + RefBatchToSpaceNdUint8Workload.cpp + RefBatchToSpaceNdUint8Workload.hpp RefConstantFloat32Workload.cpp RefConstantFloat32Workload.hpp RefConstantUint8Workload.cpp diff --git a/src/backends/reference/workloads/RefBatchToSpaceNdFloat32Workload.cpp b/src/backends/reference/workloads/RefBatchToSpaceNdFloat32Workload.cpp new file mode 100644 index 0000000000..bf246c272f --- /dev/null +++ b/src/backends/reference/workloads/RefBatchToSpaceNdFloat32Workload.cpp @@ -0,0 +1,28 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "BatchToSpaceNd.hpp" +#include "Profiling.hpp" +#include "RefBatchToSpaceNdFloat32Workload.hpp" +#include "RefWorkloadUtils.hpp" + +namespace armnn +{ + +void RefBatchToSpaceNdFloat32Workload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefBatchToSpaceNdFloat32Workload_Execute"); + + const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); + const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]); + const float* inputData = GetInputTensorDataFloat(0, m_Data); + float* outputData = GetOutputTensorDataFloat(0, m_Data); + + BatchToSpaceNd(m_Data.m_Parameters.m_DataLayout, inputInfo, outputInfo, m_Data.m_Parameters.m_BlockShape, + m_Data.m_Parameters.m_Crops, inputData, outputData); +} + + +} //namespace armnn \ No newline at end of file diff --git a/src/backends/reference/workloads/RefBatchToSpaceNdFloat32Workload.hpp b/src/backends/reference/workloads/RefBatchToSpaceNdFloat32Workload.hpp new file mode 100644 index 0000000000..4977772c82 --- /dev/null +++ b/src/backends/reference/workloads/RefBatchToSpaceNdFloat32Workload.hpp @@ -0,0 +1,22 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include + +namespace armnn { + +class RefBatchToSpaceNdFloat32Workload : public Float32Workload +{ + +public: + using Float32Workload::Float32Workload; + + virtual void Execute() const override; +}; + +} // namespace armnn \ No newline at end of file diff --git a/src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.cpp b/src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.cpp new file mode 100644 index 0000000000..a66bcd42de --- /dev/null +++ b/src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.cpp @@ -0,0 +1,30 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "BatchToSpaceNd.hpp" +#include "Profiling.hpp" +#include "RefBatchToSpaceNdUint8Workload.hpp" +#include "RefWorkloadUtils.hpp" + +namespace armnn +{ + +void RefBatchToSpaceNdUint8Workload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefBatchToSpaceNdUint8Workload_Execute"); + + const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); + const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]); + auto dequantizedInputData = Dequantize(GetInputTensorDataU8(0, m_Data), inputInfo); + float* outputData = GetOutputTensorDataFloat(0, m_Data); + + std::vector results(outputInfo.GetNumElements()); + BatchToSpaceNd(m_Data.m_Parameters.m_DataLayout, inputInfo, outputInfo, m_Data.m_Parameters.m_BlockShape, + m_Data.m_Parameters.m_Crops, dequantizedInputData.data(), outputData); + + Quantize(GetOutputTensorDataU8(0, m_Data), results.data(), outputInfo); +} + +} //namespace armnn \ No newline at end of file diff --git a/src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.hpp b/src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.hpp new file mode 100644 index 0000000000..1f221c2f47 --- /dev/null +++ b/src/backends/reference/workloads/RefBatchToSpaceNdUint8Workload.hpp @@ -0,0 +1,23 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include + +namespace armnn +{ + +class RefBatchToSpaceNdUint8Workload : public Uint8Workload +{ + +public: + using Uint8Workload::Uint8Workload; + + virtual void Execute() const override; +}; + +} // namespace armnn \ No newline at end of file diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp index 03907a6b91..5ea7fe4b58 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -54,4 +54,6 @@ #include "RefConvertFp32ToFp16Workload.hpp" #include "RefMeanUint8Workload.hpp" #include "RefMeanFloat32Workload.hpp" -#include "RefPadWorkload.hpp" \ No newline at end of file +#include "RefPadWorkload.hpp" +#include "RefBatchToSpaceNdUint8Workload.hpp" +#include "RefBatchToSpaceNdFloat32Workload.hpp" -- cgit v1.2.1