From 22972f04d6aa5c4d1269ed3be8bc5fb7b508dcda Mon Sep 17 00:00:00 2001 From: Bruno Goncalves Date: Fri, 26 Apr 2019 21:03:24 -0300 Subject: MLCE-101 Add dilation support for DepthWiseConv workload Adds unit tests for dilated depthwise conv Change-Id: Iad0a1b33d07fb0ef8f9f6edf0fd0f83a5800a36d Signed-off-by: Bruno Goncalves Signed-off-by: Matthew Bentham --- include/armnn/Descriptors.hpp | 4 +- src/backends/backendsCommon/WorkloadData.cpp | 8 +++ .../backendsCommon/test/Conv2dTestImpl.hpp | 6 +- src/backends/backendsCommon/test/LayerTests.cpp | 81 ++++++++++++++++++++++ src/backends/backendsCommon/test/LayerTests.hpp | 3 + src/backends/cl/test/ClLayerTests.cpp | 2 + src/backends/neon/test/NeonLayerTests.cpp | 2 + .../workloads/NeonDepthwiseConvolutionWorkload.cpp | 2 +- 8 files changed, 104 insertions(+), 4 deletions(-) diff --git a/include/armnn/Descriptors.hpp b/include/armnn/Descriptors.hpp index cf31599ed1..5be59aaa03 100644 --- a/include/armnn/Descriptors.hpp +++ b/include/armnn/Descriptors.hpp @@ -330,9 +330,9 @@ struct DepthwiseConvolution2dDescriptor uint32_t m_StrideX; /// Stride value when proceeding through input for the height dimension. uint32_t m_StrideY; - /// Dilation along x axis + /// Dilation factor value for width dimension. uint32_t m_DilationX; - /// Dilation along y axis + /// Dilation factor value for height dimension. uint32_t m_DilationY; /// Enable/disable bias. bool m_BiasEnabled; diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index 2cf99371d2..58f77d55c5 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -634,6 +634,14 @@ void DepthwiseConvolution2dQueueDescriptor::Validate(const WorkloadInfo& workloa ValidatePointer(m_Weight, "DepthwiseConvolution2dQueueDescriptor", "weight"); ValidateTensorNumDimensions(m_Weight->GetTensorInfo(), "DepthwiseConvolution2dQueueDescriptor", 4, "weight"); + if (m_Parameters.m_DilationX < 1 || m_Parameters.m_DilationY < 1 ) + { + throw InvalidArgumentException( + boost::str(boost::format("DepthwiseConvolution2dQueueDescriptor: dilationX (provided %1%) " + "and dilationY (provided %2%) cannot be smaller than 1.") + % m_Parameters.m_DilationX % m_Parameters.m_DilationX)); + } + const unsigned int channelIndex = (m_Parameters.m_DataLayout == DataLayout::NCHW) ? 1 : 3; // Expected weight shape: [ M, I, H, W ] - This shape does NOT depend on the data layout diff --git a/src/backends/backendsCommon/test/Conv2dTestImpl.hpp b/src/backends/backendsCommon/test/Conv2dTestImpl.hpp index c2e539b20f..bb5656bd01 100755 --- a/src/backends/backendsCommon/test/Conv2dTestImpl.hpp +++ b/src/backends/backendsCommon/test/Conv2dTestImpl.hpp @@ -827,7 +827,9 @@ LayerTestResult DepthwiseConvolution2dNhwcTestImpl( uint32_t padRight = 0, uint32_t padBottom = 0, uint32_t strideX = 1, - uint32_t strideY = 1) + uint32_t strideY = 1, + uint32_t dilationX = 1, + uint32_t dilationY = 1) { unsigned int inputNum = boost::numeric_cast(input.shape()[0]); unsigned int inputChannels = boost::numeric_cast(input.shape()[3]); @@ -894,6 +896,8 @@ LayerTestResult DepthwiseConvolution2dNhwcTestImpl( data.m_Parameters.m_PadTop = padTop; data.m_Parameters.m_PadBottom = padBottom; data.m_Parameters.m_DataLayout = armnn::DataLayout::NHWC; + data.m_Parameters.m_DilationX = dilationX; + data.m_Parameters.m_DilationY = dilationY; armnn::WorkloadInfo info; AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get()); diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp index e505b56e7e..da6a2b22ad 100644 --- a/src/backends/backendsCommon/test/LayerTests.cpp +++ b/src/backends/backendsCommon/test/LayerTests.cpp @@ -748,6 +748,75 @@ LayerTestResult DepthwiseConvolution2dNhwcTestCommon( 1); // strideY } +template> +LayerTestResult SimpleDepthwiseConvolution2d3x3Dilation3x3NhwcTestCommon( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + float qScale, + int32_t qOffset, + bool biasEnabled) +{ + armnn::TensorInfo inputTensorInfo({ 1, 9, 9, 1}, ArmnnType); + auto input = MakeTensor(inputTensorInfo, std::vector( + QuantizedVector(inputTensorInfo.GetQuantizationScale(), inputTensorInfo.GetQuantizationOffset(), { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0 + }))); + + armnn::TensorInfo kernelTensorInfo({ 1, 1, 3, 3}, ArmnnType); + auto kernel = MakeTensor(kernelTensorInfo, std::vector( + QuantizedVector(kernelTensorInfo.GetQuantizationScale(), kernelTensorInfo.GetQuantizationOffset(), { + 1, 2, 3, + 4, 5, 6, + 7, 8, 9 + }))); + + uint32_t padLeft = 0; + uint32_t padTop = 0; + uint32_t padRight = 0; + uint32_t padBottom = 0; + uint32_t strideX = 1; + uint32_t strideY = 1; + uint32_t dilationX = 3; + uint32_t dilationY = 3; + + // Since the dilation rate is 3 this will reduce the size of the output from 9x9 to 3x3 of all 5s. + armnn::TensorInfo outputTensorInfo({ 1, 3, 3, 1}, ArmnnType); + boost::multi_array expectedOutput = MakeTensor(outputTensorInfo, std::vector( + QuantizedVector(outputTensorInfo.GetQuantizationScale(), outputTensorInfo.GetQuantizationOffset(), { + 5, 5, 5, + 5, 5, 5, + 5, 5, 5 + }))); + + return DepthwiseConvolution2dNhwcTestImpl( + workloadFactory, + memoryManager, + input, + kernel, + GetBias2(biasEnabled, qScale, qOffset), + expectedOutput, + qScale, + qOffset, + padLeft, + padTop, + padRight, + padBottom, + strideX, + strideY, + dilationX, + dilationY); + +} + LayerTestResult Convolution2dAsymmetricPaddingLargerThanHalfKernelSizeTest( armnn::IWorkloadFactory& workloadFactory, @@ -827,6 +896,18 @@ LayerTestResult DepthwiseConvolution2dDepthMul1Uint8Test( workloadFactory, memoryManager, 0.5f, 50, biasEnabled, layout); } +LayerTestResult SimpleDepthwiseConvolution2d3x3Dilation3x3NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleDepthwiseConvolution2d3x3Dilation3x3NhwcTestCommon( + workloadFactory, + memoryManager, + 0.f, + 0, + false); +} + LayerTestResult Convolution1dTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp index 0e8025ee87..84001aa7ea 100644 --- a/src/backends/backendsCommon/test/LayerTests.hpp +++ b/src/backends/backendsCommon/test/LayerTests.hpp @@ -123,6 +123,9 @@ LayerTestResult DepthwiseConvolution2dAsymmetricTest( bool biasEnabled, const armnn::DataLayout layout); +LayerTestResult SimpleDepthwiseConvolution2d3x3Dilation3x3NhwcTest(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + LayerTestResult CompareDepthwiseConvolution2dFloatTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, diff --git a/src/backends/cl/test/ClLayerTests.cpp b/src/backends/cl/test/ClLayerTests.cpp index 58b9ba7f76..0af1d34652 100644 --- a/src/backends/cl/test/ClLayerTests.cpp +++ b/src/backends/cl/test/ClLayerTests.cpp @@ -108,6 +108,8 @@ ARMNN_AUTO_TEST_CASE(DepthwiseConvolution2dDepthMul1Uint8Nhwc, DepthwiseConvolution2dDepthMul1Uint8Test, true, armnn::DataLayout::NHWC) ARMNN_AUTO_TEST_CASE(UnbiasedDepthwiseConvolution2dDepthMul1Uint8Nhwc, DepthwiseConvolution2dDepthMul1Uint8Test, false, armnn::DataLayout::NHWC) +ARMNN_AUTO_TEST_CASE(SimpleDepthwiseConvolution2d3x3Dilation3x3Nhwc, + SimpleDepthwiseConvolution2d3x3Dilation3x3NhwcTest) ARMNN_AUTO_TEST_CASE(DepthwiseConvolution2dDepthNhwc, DepthwiseConvolution2dDepthNhwcTest, false) diff --git a/src/backends/neon/test/NeonLayerTests.cpp b/src/backends/neon/test/NeonLayerTests.cpp index 9454244620..dce369dfa6 100644 --- a/src/backends/neon/test/NeonLayerTests.cpp +++ b/src/backends/neon/test/NeonLayerTests.cpp @@ -68,6 +68,8 @@ ARMNN_AUTO_TEST_CASE(UnbiasedDepthwiseConvolution2dDepthMul1Uint8Nhwc, DepthwiseConvolution2dDepthMul1Uint8Test, false, armnn::DataLayout::NHWC) ARMNN_AUTO_TEST_CASE(DepthwiseConvolution2dDepthNhwc, DepthwiseConvolution2dDepthNhwcTest, false) +ARMNN_AUTO_TEST_CASE(SimpleDepthwiseConvolution2d3x3Dilation3x3Nhwc, + SimpleDepthwiseConvolution2d3x3Dilation3x3NhwcTest) ARMNN_AUTO_TEST_CASE(DepthwiseConvolution2dAsymmetric, diff --git a/src/backends/neon/workloads/NeonDepthwiseConvolutionWorkload.cpp b/src/backends/neon/workloads/NeonDepthwiseConvolutionWorkload.cpp index 0b917fc530..d15b48571a 100644 --- a/src/backends/neon/workloads/NeonDepthwiseConvolutionWorkload.cpp +++ b/src/backends/neon/workloads/NeonDepthwiseConvolutionWorkload.cpp @@ -117,7 +117,7 @@ NeonDepthwiseConvolutionWorkload::NeonDepthwiseConvolutionWorkload( input.info()->set_data_layout(aclDataLayout); output.info()->set_data_layout(aclDataLayout); - // Get the depth multiplier + // Get the depth multiplier const unsigned int depthMultiplier = weightInfo.GetShape()[0]; // Check for optimisation opportunities. -- cgit v1.2.1