From 92b9f87099260178d2a3d61a42af2a86762eaca7 Mon Sep 17 00:00:00 2001 From: Aron Virginas-Tar Date: Tue, 17 Sep 2019 17:27:04 +0100 Subject: IVGCVSW-3878 Add reference workload for SLICE * Added reference workload implementation and layer tests for all supported tensor dimensions (1d, 2d, 3d, 4d) Signed-off-by: Aron Virginas-Tar Change-Id: I40eb300828933e9183027281105d1a7e597d1569 --- src/backends/backendsCommon/WorkloadData.cpp | 2 +- src/backends/backendsCommon/common.mk | 1 + src/backends/backendsCommon/test/CMakeLists.txt | 2 + src/backends/backendsCommon/test/LayerTests.hpp | 1 + .../test/layerTests/SliceTestImpl.cpp | 291 +++++++++++++++++++++ .../test/layerTests/SliceTestImpl.hpp | 50 ++++ src/backends/reference/RefLayerSupport.cpp | 27 ++ src/backends/reference/RefLayerSupport.hpp | 5 + src/backends/reference/RefWorkloadFactory.cpp | 6 + src/backends/reference/RefWorkloadFactory.hpp | 3 + src/backends/reference/backend.mk | 2 + src/backends/reference/test/RefLayerTests.cpp | 16 ++ src/backends/reference/workloads/CMakeLists.txt | 4 + .../reference/workloads/RefSliceWorkload.cpp | 29 ++ .../reference/workloads/RefSliceWorkload.hpp | 22 ++ src/backends/reference/workloads/RefWorkloads.hpp | 5 +- src/backends/reference/workloads/Slice.cpp | 95 +++++++ src/backends/reference/workloads/Slice.hpp | 21 ++ 18 files changed, 579 insertions(+), 3 deletions(-) create mode 100644 src/backends/backendsCommon/test/layerTests/SliceTestImpl.cpp create mode 100644 src/backends/backendsCommon/test/layerTests/SliceTestImpl.hpp create mode 100644 src/backends/reference/workloads/RefSliceWorkload.cpp create mode 100644 src/backends/reference/workloads/RefSliceWorkload.hpp create mode 100644 src/backends/reference/workloads/Slice.cpp create mode 100644 src/backends/reference/workloads/Slice.hpp diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index 2fa0c92daf..136c196e1b 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -2631,7 +2631,7 @@ void SliceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const const TensorShape& inputShape = inputTensorInfo.GetShape(); for(unsigned int i = 0u; i < rank; ++i) { - if (m_Parameters.m_Begin[i] + m_Parameters.m_Size[i] >= inputShape[i]) + if (m_Parameters.m_Begin[i] + m_Parameters.m_Size[i] > inputShape[i]) { throw InvalidArgumentException(descriptorName + ": Sum of begin offset and size for dimension " + std::to_string(i) + " exceeds input size."); diff --git a/src/backends/backendsCommon/common.mk b/src/backends/backendsCommon/common.mk index 14feb347d3..0943a83eb1 100644 --- a/src/backends/backendsCommon/common.mk +++ b/src/backends/backendsCommon/common.mk @@ -62,6 +62,7 @@ COMMON_TEST_SOURCES := \ test/layerTests/Pooling2dTestImpl.cpp \ test/layerTests/ReshapeTestImpl.cpp \ test/layerTests/RsqrtTestImpl.cpp \ + test/layerTests/SliceTestImpl.cpp \ test/layerTests/QuantizeTestImpl.cpp \ test/layerTests/SoftmaxTestImpl.cpp \ test/layerTests/SpaceToBatchNdTestImpl.cpp \ diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt index e3fa431363..ef293d490b 100644 --- a/src/backends/backendsCommon/test/CMakeLists.txt +++ b/src/backends/backendsCommon/test/CMakeLists.txt @@ -106,6 +106,8 @@ list(APPEND armnnBackendsCommonUnitTests_sources layerTests/ResizeTestImpl.hpp layerTests/RsqrtTestImpl.cpp layerTests/RsqrtTestImpl.hpp + layerTests/SliceTestImpl.cpp + layerTests/SliceTestImpl.hpp layerTests/SoftmaxTestImpl.cpp layerTests/SoftmaxTestImpl.hpp layerTests/SpaceToBatchNdTestImpl.cpp diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp index bf2ef6abb6..f48ae436cb 100644 --- a/src/backends/backendsCommon/test/LayerTests.hpp +++ b/src/backends/backendsCommon/test/LayerTests.hpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff --git a/src/backends/backendsCommon/test/layerTests/SliceTestImpl.cpp b/src/backends/backendsCommon/test/layerTests/SliceTestImpl.cpp new file mode 100644 index 0000000000..f0479c8ea9 --- /dev/null +++ b/src/backends/backendsCommon/test/layerTests/SliceTestImpl.cpp @@ -0,0 +1,291 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "SliceTestImpl.hpp" + +#include + +#include + +#include +#include + +#include + +namespace +{ + +template +LayerTestResult SliceTestImpl( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + armnn::TensorInfo& inputInfo, + armnn::TensorInfo& outputInfo, + std::vector& inputData, + std::vector& expectedOutputData, + armnn::SliceQueueDescriptor descriptor, + const float qScale = 1.0f, + const int qOffset = 0) +{ + if(armnn::IsQuantizedType()) + { + inputInfo.SetQuantizationScale(qScale); + inputInfo.SetQuantizationOffset(qOffset); + + outputInfo.SetQuantizationScale(qScale); + outputInfo.SetQuantizationOffset(qOffset); + } + + boost::multi_array input = + MakeTensor(inputInfo, QuantizedVector(qScale, qOffset, inputData)); + + LayerTestResult result(outputInfo); + result.outputExpected = + MakeTensor(outputInfo, QuantizedVector(qScale, qOffset, expectedOutputData)); + + std::unique_ptr inputHandle = workloadFactory.CreateTensorHandle(inputInfo); + std::unique_ptr outputHandle = workloadFactory.CreateTensorHandle(outputInfo); + + armnn::WorkloadInfo info; + AddInputToWorkload(descriptor, info, inputInfo, inputHandle.get()); + AddOutputToWorkload(descriptor, info, outputInfo, outputHandle.get()); + + std::unique_ptr workload = workloadFactory.CreateSlice(descriptor, info); + + inputHandle->Allocate(); + outputHandle->Allocate(); + + CopyDataToITensorHandle(inputHandle.get(), input.data()); + + ExecuteWorkload(*workload, memoryManager); + + CopyDataFromITensorHandle(result.output.data(), outputHandle.get()); + + return result; +} + +template> +LayerTestResult Slice4dTest(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + armnn::TensorShape inputShape = { 3, 2, 3, 5 }; + armnn::TensorShape outputShape = { 2, 1, 2, 3 }; + + armnn::SliceQueueDescriptor desc; + desc.m_Parameters.m_Begin = { 1, 0, 1, 2 }; + desc.m_Parameters.m_Size = { 2, 1, 2, 3 }; + + armnn::TensorInfo inputInfo(inputShape, ArmnnType); + armnn::TensorInfo outputInfo(outputShape, ArmnnType); + + std::vector input = + { + 0.f, 1.f, 2.f, 3.f, 4.f, + 5.f, 6.f, 7.f, 8.f, 9.f, + 10.f, 11.f, 12.f, 13.f, 14.f, + + 15.f, 16.f, 17.f, 18.f, 19.f, + 20.f, 21.f, 22.f, 23.f, 24.f, + 25.f, 26.f, 27.f, 28.f, 29.f, + + + 30.f, 31.f, 32.f, 33.f, 34.f, + 35.f, 36.f, 37.f, 38.f, 39.f, + 40.f, 41.f, 42.f, 43.f, 44.f, + + 45.f, 46.f, 47.f, 48.f, 49.f, + 50.f, 51.f, 52.f, 53.f, 54.f, + 55.f, 56.f, 57.f, 58.f, 59.f, + + + 60.f, 61.f, 62.f, 63.f, 64.f, + 65.f, 66.f, 67.f, 68.f, 69.f, + 70.f, 71.f, 72.f, 73.f, 74.f, + + 75.f, 76.f, 77.f, 78.f, 79.f, + 80.f, 81.f, 82.f, 83.f, 84.f, + 85.f, 86.f, 87.f, 88.f, 89.f + }; + + std::vector expectedOutput = + { + 37.f, 38.f, 39.f, + 42.f, 43.f, 44.f, + + + 67.f, 68.f, 69.f, + 72.f, 73.f, 74.f + }; + + return SliceTestImpl(workloadFactory, memoryManager, inputInfo, outputInfo, input, expectedOutput, desc); +} + +template> +LayerTestResult Slice3dTest(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + armnn::TensorShape inputShape = { 2, 3, 5 }; + armnn::TensorShape outputShape = { 1, 2, 3 }; + + armnn::SliceQueueDescriptor desc; + desc.m_Parameters.m_Begin = { 0, 1, 2 }; + desc.m_Parameters.m_Size = { 1, 2, 3 }; + + armnn::TensorInfo inputInfo(inputShape, ArmnnType); + armnn::TensorInfo outputInfo(outputShape, ArmnnType); + + std::vector input = + { + 0.f, 1.f, 2.f, 3.f, 4.f, + 5.f, 6.f, 7.f, 8.f, 9.f, + 10.f, 11.f, 12.f, 13.f, 14.f, + + 15.f, 16.f, 17.f, 18.f, 19.f, + 20.f, 21.f, 22.f, 23.f, 24.f, + 25.f, 26.f, 27.f, 28.f, 29.f, + }; + + std::vector expectedOutput = + { + 7.f, 8.f, 9.f, + 12.f, 13.f, 14.f + }; + + return SliceTestImpl(workloadFactory, memoryManager, inputInfo, outputInfo, input, expectedOutput, desc); +} + +template> +LayerTestResult Slice2dTest(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + armnn::TensorShape inputShape = { 3, 5 }; + armnn::TensorShape outputShape = { 2, 3 }; + + armnn::SliceQueueDescriptor desc; + desc.m_Parameters.m_Begin = { 1, 2 }; + desc.m_Parameters.m_Size = { 2, 3 }; + + armnn::TensorInfo inputInfo(inputShape, ArmnnType); + armnn::TensorInfo outputInfo(outputShape, ArmnnType); + + std::vector input = + { + 0.f, 1.f, 2.f, 3.f, 4.f, + 5.f, 6.f, 7.f, 8.f, 9.f, + 10.f, 11.f, 12.f, 13.f, 14.f + }; + + std::vector expectedOutput = + { + 7.f, 8.f, 9.f, + 12.f, 13.f, 14.f + }; + + return SliceTestImpl(workloadFactory, memoryManager, inputInfo, outputInfo, input, expectedOutput, desc); +} + +template> +LayerTestResult Slice1dTest(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + armnn::TensorShape inputShape = { 5 }; + armnn::TensorShape outputShape = { 3 }; + + armnn::SliceQueueDescriptor desc; + desc.m_Parameters.m_Begin = { 2 }; + desc.m_Parameters.m_Size = { 3 }; + + armnn::TensorInfo inputInfo(inputShape, ArmnnType); + armnn::TensorInfo outputInfo(outputShape, ArmnnType); + + std::vector input = + { + 0.f, 1.f, 2.f, 3.f, 4.f + }; + + std::vector expectedOutput = + { + 2.f, 3.f, 4.f + }; + + return SliceTestImpl(workloadFactory, memoryManager, inputInfo, outputInfo, input, expectedOutput, desc); +} + +} // anonymous namespace + +// Float32 tests +LayerTestResult Slice4dFloat32Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice4dTest(workloadFactory, memoryManager); +} + +LayerTestResult Slice3dFloat32Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice3dTest(workloadFactory, memoryManager); +} + +LayerTestResult Slice2dFloat32Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice2dTest(workloadFactory, memoryManager); +} + +LayerTestResult Slice1dFloat32Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice1dTest(workloadFactory, memoryManager); +} + +// Uint8 tests +LayerTestResult Slice4dUint8Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice4dTest(workloadFactory, memoryManager); +} + +LayerTestResult Slice3dUint8Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice3dTest(workloadFactory, memoryManager); +} + +LayerTestResult Slice2dUint8Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice2dTest(workloadFactory, memoryManager); +} + +LayerTestResult Slice1dUint8Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice1dTest(workloadFactory, memoryManager); +} + +// Int16 tests +LayerTestResult Slice4dInt16Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice4dTest(workloadFactory, memoryManager); +} + +LayerTestResult Slice3dInt16Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice3dTest(workloadFactory, memoryManager); +} + +LayerTestResult Slice2dInt16Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice2dTest(workloadFactory, memoryManager); +} + +LayerTestResult Slice1dInt16Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return Slice1dTest(workloadFactory, memoryManager); +} diff --git a/src/backends/backendsCommon/test/layerTests/SliceTestImpl.hpp b/src/backends/backendsCommon/test/layerTests/SliceTestImpl.hpp new file mode 100644 index 0000000000..59458edd2f --- /dev/null +++ b/src/backends/backendsCommon/test/layerTests/SliceTestImpl.hpp @@ -0,0 +1,50 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "LayerTestResult.hpp" + +#include +#include + +// Float32 tests +LayerTestResult Slice4dFloat32Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult Slice3dFloat32Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult Slice2dFloat32Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult Slice1dFloat32Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +// Uint8 tests +LayerTestResult Slice4dUint8Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult Slice3dUint8Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult Slice2dUint8Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult Slice1dUint8Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +// Int16 tests +LayerTestResult Slice4dInt16Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult Slice3dInt16Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult Slice2dInt16Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult Slice1dInt16Test(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp index 228f8a8809..572f617636 100644 --- a/src/backends/reference/RefLayerSupport.cpp +++ b/src/backends/reference/RefLayerSupport.cpp @@ -1374,6 +1374,33 @@ bool RefLayerSupport::IsRsqrtSupported(const TensorInfo& input, return supported; } +bool RefLayerSupport::IsSliceSupported(const TensorInfo& input, + const TensorInfo& output, + const SliceDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + ignore_unused(descriptor); + bool supported = true; + + std::array supportedTypes = + { + DataType::Float32, + DataType::QuantisedAsymm8, + DataType::QuantisedSymm16 + }; + + supported &= CheckSupportRule(TypeAnyOf(input, supportedTypes), reasonIfUnsupported, + "Reference Slice: input type not supported"); + + supported &= CheckSupportRule(TypeAnyOf(output, supportedTypes), reasonIfUnsupported, + "Reference Slice: output type not supported"); + + supported &= CheckSupportRule(TypesAreEqual(input, output), reasonIfUnsupported, + "Reference Slice: input and output types are mismatched"); + + return supported; +} + bool RefLayerSupport::IsSoftmaxSupported(const TensorInfo& input, const TensorInfo& output, const SoftmaxDescriptor& descriptor, diff --git a/src/backends/reference/RefLayerSupport.hpp b/src/backends/reference/RefLayerSupport.hpp index 26c60dcf30..8200058633 100644 --- a/src/backends/reference/RefLayerSupport.hpp +++ b/src/backends/reference/RefLayerSupport.hpp @@ -219,6 +219,11 @@ public: const TensorInfo& output, Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsSliceSupported(const TensorInfo& input, + const TensorInfo& output, + const SliceDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsSoftmaxSupported(const TensorInfo& input, const TensorInfo& output, const SoftmaxDescriptor& descriptor, diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp index 52dffcc1f8..055c8da600 100644 --- a/src/backends/reference/RefWorkloadFactory.cpp +++ b/src/backends/reference/RefWorkloadFactory.cpp @@ -457,4 +457,10 @@ std::unique_ptr RefWorkloadFactory::CreateAbs(const AbsQueueDescripto return std::make_unique(descriptor, info); } +std::unique_ptr RefWorkloadFactory::CreateSlice(const SliceQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return std::make_unique(descriptor, info); +} + } // namespace armnn diff --git a/src/backends/reference/RefWorkloadFactory.hpp b/src/backends/reference/RefWorkloadFactory.hpp index 5851528f4a..2c40053f73 100644 --- a/src/backends/reference/RefWorkloadFactory.hpp +++ b/src/backends/reference/RefWorkloadFactory.hpp @@ -212,6 +212,9 @@ public: std::unique_ptr CreateAbs(const AbsQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + std::unique_ptr CreateSlice(const SliceQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; + private: template diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk index b1f0a03782..b2ec7488e2 100644 --- a/src/backends/reference/backend.mk +++ b/src/backends/reference/backend.mk @@ -69,6 +69,7 @@ BACKEND_SOURCES := \ workloads/RefResizeBilinearWorkload.cpp \ workloads/RefResizeWorkload.cpp \ workloads/RefRsqrtWorkload.cpp \ + workloads/RefSliceWorkload.cpp \ workloads/RefSoftmaxWorkload.cpp \ workloads/RefSpaceToBatchNdWorkload.cpp \ workloads/RefSpaceToDepthWorkload.cpp \ @@ -78,6 +79,7 @@ BACKEND_SOURCES := \ workloads/RefTransposeConvolution2dWorkload.cpp \ workloads/Resize.cpp \ workloads/Rsqrt.cpp \ + workloads/Slice.cpp \ workloads/SpaceToBatchNd.cpp \ workloads/SpaceToDepth.cpp \ workloads/Stack.cpp \ diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp index eb56dde884..afeb8a458a 100644 --- a/src/backends/reference/test/RefLayerTests.cpp +++ b/src/backends/reference/test/RefLayerTests.cpp @@ -1252,6 +1252,22 @@ ARMNN_AUTO_TEST_CASE(PreluFloat16, PreluTest) ARMNN_AUTO_TEST_CASE(PreluUint8, PreluTest) ARMNN_AUTO_TEST_CASE(PreluInt16, PreluTest) +// Slice +ARMNN_AUTO_TEST_CASE(Slice4dFloat32, Slice4dFloat32Test) +ARMNN_AUTO_TEST_CASE(Slice3dFloat32, Slice3dFloat32Test) +ARMNN_AUTO_TEST_CASE(Slice2dFloat32, Slice2dFloat32Test) +ARMNN_AUTO_TEST_CASE(Slice1dFloat32, Slice1dFloat32Test) + +ARMNN_AUTO_TEST_CASE(Slice4dUint8, Slice4dUint8Test) +ARMNN_AUTO_TEST_CASE(Slice3dUint8, Slice3dUint8Test) +ARMNN_AUTO_TEST_CASE(Slice2dUint8, Slice2dUint8Test) +ARMNN_AUTO_TEST_CASE(Slice1dUint8, Slice1dUint8Test) + +ARMNN_AUTO_TEST_CASE(Slice4dInt16, Slice4dInt16Test) +ARMNN_AUTO_TEST_CASE(Slice3dInt16, Slice3dInt16Test) +ARMNN_AUTO_TEST_CASE(Slice2dInt16, Slice2dInt16Test) +ARMNN_AUTO_TEST_CASE(Slice1dInt16, Slice1dInt16Test) + // TransposeConvolution2d ARMNN_AUTO_TEST_CASE(SimpleTransposeConvolution2dFloatNchw, SimpleTransposeConvolution2dTest, diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index 23d6024530..30770956ba 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -107,6 +107,8 @@ list(APPEND armnnRefBackendWorkloads_sources RefResizeWorkload.hpp RefRsqrtWorkload.cpp RefRsqrtWorkload.hpp + RefSliceWorkload.cpp + RefSliceWorkload.hpp RefSoftmaxWorkload.cpp RefSoftmaxWorkload.hpp RefSpaceToBatchNdWorkload.cpp @@ -127,6 +129,8 @@ list(APPEND armnnRefBackendWorkloads_sources Resize.hpp Rsqrt.cpp Rsqrt.hpp + Slice.cpp + Slice.hpp Softmax.cpp Softmax.hpp SpaceToBatchNd.hpp diff --git a/src/backends/reference/workloads/RefSliceWorkload.cpp b/src/backends/reference/workloads/RefSliceWorkload.cpp new file mode 100644 index 0000000000..2e448450c1 --- /dev/null +++ b/src/backends/reference/workloads/RefSliceWorkload.cpp @@ -0,0 +1,29 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RefSliceWorkload.hpp" + +#include "RefWorkloadUtils.hpp" +#include "Slice.hpp" + +#include + +namespace armnn +{ + +void RefSliceWorkload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefSliceWorkload_Execute"); + + const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); + + Slice(inputInfo, + m_Data.m_Parameters, + m_Data.m_Inputs[0]->Map(), + m_Data.m_Outputs[0]->Map(), + GetDataTypeSize(inputInfo.GetDataType())); +} + +} // namespace armnn diff --git a/src/backends/reference/workloads/RefSliceWorkload.hpp b/src/backends/reference/workloads/RefSliceWorkload.hpp new file mode 100644 index 0000000000..006c7b775d --- /dev/null +++ b/src/backends/reference/workloads/RefSliceWorkload.hpp @@ -0,0 +1,22 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include + +namespace armnn +{ + +class RefSliceWorkload : public BaseWorkload +{ +public: + using BaseWorkload::BaseWorkload; + + virtual void Execute() const override; +}; + +} // namespace armnn diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp index 1ec349ee22..959226adf6 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -41,10 +41,11 @@ #include "RefPadWorkload.hpp" #include "RefPreluWorkload.hpp" #include "RefQuantizeWorkload.hpp" +#include "RefReshapeWorkload.hpp" #include "RefResizeBilinearWorkload.hpp" #include "RefResizeWorkload.hpp" #include "RefRsqrtWorkload.hpp" -#include "RefReshapeWorkload.hpp" +#include "RefSliceWorkload.hpp" #include "RefSplitterWorkload.hpp" #include "RefSoftmaxWorkload.hpp" #include "RefSpaceToBatchNdWorkload.hpp" @@ -56,4 +57,4 @@ #include "Resize.hpp" #include "Softmax.hpp" #include "Splitter.hpp" -#include "TensorBufferArrayView.hpp" \ No newline at end of file +#include "TensorBufferArrayView.hpp" diff --git a/src/backends/reference/workloads/Slice.cpp b/src/backends/reference/workloads/Slice.cpp new file mode 100644 index 0000000000..c7ca3b156e --- /dev/null +++ b/src/backends/reference/workloads/Slice.cpp @@ -0,0 +1,95 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "Slice.hpp" + +#include +#include +#include + +namespace armnn +{ + +void Slice(const TensorInfo& inputInfo, + const SliceDescriptor& descriptor, + const void* inputData, + void* outputData, + unsigned int dataTypeSize) +{ + const TensorShape& inputShape = inputInfo.GetShape(); + const unsigned int numDims = inputShape.GetNumDimensions(); + + BOOST_ASSERT(descriptor.m_Begin.size() == numDims); + BOOST_ASSERT(descriptor.m_Size.size() == numDims); + + constexpr unsigned int maxNumDims = 4; + BOOST_ASSERT(numDims <= maxNumDims); + + std::vector paddedInput(4); + std::vector paddedBegin(4); + std::vector paddedSize (4); + + const unsigned int numPaddingDims = maxNumDims - numDims; + for (unsigned int i = 0u; i < maxNumDims; ++i) + { + if (i < numPaddingDims) + { + paddedInput[i] = 1u; + paddedBegin[i] = 0u; + paddedSize[i] = 1u; + } + else + { + const unsigned int j = i - numPaddingDims; + paddedInput[i] = inputShape[j]; + paddedBegin[i] = descriptor.m_Begin[j]; + paddedSize[i] = descriptor.m_Size[j]; + } + } + + unsigned int dim0 = paddedInput[0]; + unsigned int dim1 = paddedInput[1]; + unsigned int dim2 = paddedInput[2]; + unsigned int dim3 = paddedInput[3]; + + unsigned int begin0 = paddedBegin[0]; + unsigned int begin1 = paddedBegin[1]; + unsigned int begin2 = paddedBegin[2]; + unsigned int begin3 = paddedBegin[3]; + + unsigned int size0 = paddedSize[0]; + unsigned int size1 = paddedSize[1]; + unsigned int size2 = paddedSize[2]; + unsigned int size3 = paddedSize[3]; + + BOOST_ASSERT(begin0 + size0 <= dim0); + BOOST_ASSERT(begin1 + size1 <= dim1); + BOOST_ASSERT(begin2 + size2 <= dim2); + BOOST_ASSERT(begin3 + size3 <= dim3); + + const unsigned char* input = reinterpret_cast(inputData); + unsigned char* output = reinterpret_cast(outputData); + + boost::ignore_unused(dim0); + for (unsigned int idx0 = begin0; idx0 < begin0 + size0; ++idx0) + { + for (unsigned int idx1 = begin1; idx1 < begin1 + size1; ++idx1) + { + for (unsigned int idx2 = begin2; idx2 < begin2 + size2; ++idx2) + { + for (unsigned int idx3 = begin3; idx3 < begin3 + size3; ++idx3) + { + const unsigned int inputOffset = + (((idx0 * dim1 + idx1) * dim2 + idx2) * dim3 + idx3) * dataTypeSize; + + ::memcpy(output, input + inputOffset, dataTypeSize); + output += dataTypeSize; + } + } + } + } +} + +} // namespace armnn diff --git a/src/backends/reference/workloads/Slice.hpp b/src/backends/reference/workloads/Slice.hpp new file mode 100644 index 0000000000..823f16c052 --- /dev/null +++ b/src/backends/reference/workloads/Slice.hpp @@ -0,0 +1,21 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "BaseIterator.hpp" + +#include + +namespace armnn +{ + +void Slice(const TensorInfo& inputInfo, + const SliceDescriptor& descriptor, + const void* inputData, + void* outputData, + unsigned int dataTypeSize); + +} // namespace armnn -- cgit v1.2.1