diff options
author | narpra01 <narumol.prangnawarat@arm.com> | 2018-10-26 16:24:58 +0100 |
---|---|---|
committer | Matteo Martincigh <matteo.martincigh@arm.com> | 2018-10-26 16:23:42 +0000 |
commit | 5f70318b08907eb1612dbe88d53857110909cb42 (patch) | |
tree | b900688ba4d60bc891d47b2c303d33182197ec0c /src/backends/reference | |
parent | 29fe58b6e6f221273b8f5e2af4133f243f7b7787 (diff) | |
download | armnn-5f70318b08907eb1612dbe88d53857110909cb42.tar.gz |
IVGCVSW-2069 - Implement NHWC Convolution2D for CpuRef
* Calculate index for NHWC to compute Convolution
* add more unit test for NHWC
Change-Id: I800d649b9b42be2758c445e3b3e76142888c1377
Diffstat (limited to 'src/backends/reference')
-rw-r--r-- | src/backends/reference/test/RefLayerTests.cpp | 26 | ||||
-rw-r--r-- | src/backends/reference/workloads/ConvImpl.hpp | 75 |
2 files changed, 79 insertions, 22 deletions
diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp index 45239be8c1..cb5a1c4158 100644 --- a/src/backends/reference/test/RefLayerTests.cpp +++ b/src/backends/reference/test/RefLayerTests.cpp @@ -20,21 +20,37 @@ using FactoryType = armnn::RefWorkloadFactory; // Convolution ARMNN_AUTO_TEST_CASE(SimpleConvolution2d3x5, SimpleConvolution2d3x5Test, true, armnn::DataLayout::NCHW) ARMNN_AUTO_TEST_CASE(SimpleConvolution2d3x5Uint8, SimpleConvolution2d3x5Uint8Test, true, armnn::DataLayout::NCHW) +ARMNN_AUTO_TEST_CASE(SimpleConvolution2d3x5Nhwc, SimpleConvolution2d3x5Test, true, armnn::DataLayout::NHWC) +ARMNN_AUTO_TEST_CASE(SimpleConvolution2d3x5Uint8Nhwc, SimpleConvolution2d3x5Uint8Test, true, armnn::DataLayout::NHWC) ARMNN_AUTO_TEST_CASE(UnbiasedConvolution2d, SimpleConvolution2d3x5Test, false, armnn::DataLayout::NCHW) ARMNN_AUTO_TEST_CASE(UnbiasedConvolutionUint8, SimpleConvolution2d3x5Uint8Test, false, armnn::DataLayout::NCHW) +ARMNN_AUTO_TEST_CASE(UnbiasedConvolution2dNhwc, SimpleConvolution2d3x5Test, false, armnn::DataLayout::NHWC) +ARMNN_AUTO_TEST_CASE(UnbiasedConvolutionUint8Nhwc, SimpleConvolution2d3x5Uint8Test, false, armnn::DataLayout::NHWC) ARMNN_AUTO_TEST_CASE(SimpleConvolution1d, Convolution1dTest, true) ARMNN_AUTO_TEST_CASE(SimpleConvolution1dUint8, Convolution1dUint8Test, true) -ARMNN_AUTO_TEST_CASE(SimpleConvolution2d3x3, SimpleConvolution2d3x3Test, true) -ARMNN_AUTO_TEST_CASE(SimpleConvolution2d3x3Uint8, SimpleConvolution2d3x3Uint8Test, true) +ARMNN_AUTO_TEST_CASE(SimpleConvolution2d3x3, SimpleConvolution2d3x3Test, true, armnn::DataLayout::NCHW) +ARMNN_AUTO_TEST_CASE(SimpleConvolution2d3x3Uint8, SimpleConvolution2d3x3Uint8Test, true, armnn::DataLayout::NCHW) -ARMNN_AUTO_TEST_CASE(UnbiasedConvolution2dSquare, SimpleConvolution2d3x3Test, false) +ARMNN_AUTO_TEST_CASE(SimpleConvolution2d3x3Nhwc, SimpleConvolution2d3x3Test, true, armnn::DataLayout::NHWC) +ARMNN_AUTO_TEST_CASE(SimpleConvolution2d3x3Uint8Nhwc, SimpleConvolution2d3x3Uint8Test, true, armnn::DataLayout::NHWC) + +ARMNN_AUTO_TEST_CASE(UnbiasedConvolution2dSquare, SimpleConvolution2d3x3Test, false, armnn::DataLayout::NCHW) +ARMNN_AUTO_TEST_CASE(UnbiasedConvolution2dSquareNhwc, SimpleConvolution2d3x3Test, false, armnn::DataLayout::NHWC) ARMNN_AUTO_TEST_CASE(SimpleConvolution2dAsymmetricPaddingLargerThanHalfKernelSize, - Convolution2dAsymmetricPaddingLargerThanHalfKernelSizeTest) -ARMNN_AUTO_TEST_CASE(SimpleConvolution2dAsymmetricPadding, Convolution2dAsymmetricPaddingTest) + Convolution2dAsymmetricPaddingLargerThanHalfKernelSizeTest, + armnn::DataLayout::NCHW) +ARMNN_AUTO_TEST_CASE(SimpleConvolution2dAsymmetricPadding, Convolution2dAsymmetricPaddingTest, armnn::DataLayout::NCHW) + +ARMNN_AUTO_TEST_CASE(SimpleConvolution2dAsymmetricPaddingLargerThanHalfKernelSizeNhwc, + Convolution2dAsymmetricPaddingLargerThanHalfKernelSizeTest, + armnn::DataLayout::NHWC) +ARMNN_AUTO_TEST_CASE(SimpleConvolution2dAsymmetricPaddingNhwc, + Convolution2dAsymmetricPaddingTest, + armnn::DataLayout::NHWC) ARMNN_AUTO_TEST_CASE(SimpleConvolution2dSquareNhwc, SimpleConvolution2d3x3NhwcTest, false) diff --git a/src/backends/reference/workloads/ConvImpl.hpp b/src/backends/reference/workloads/ConvImpl.hpp index 60a3622c55..4b15c1da6d 100644 --- a/src/backends/reference/workloads/ConvImpl.hpp +++ b/src/backends/reference/workloads/ConvImpl.hpp @@ -6,6 +6,7 @@ #pragma once #include "RefWorkloadUtils.hpp" +#include "TensorBufferArrayView.hpp" #include <armnn/Tensor.hpp> @@ -66,6 +67,10 @@ static void ConvImpl(ConvData data, const TensorInfo& inputInfo0 = GetTensorInfo(data.m_Inputs[0]); const TensorInfo& outputInfo0 = GetTensorInfo(data.m_Outputs[0]); + TensorBufferArrayView<InputType> output(outputInfo0.GetShape(), + GetOutputTensorData<InputType>(0, data), + data.m_Parameters.m_DataLayout); + const DataLayoutIndexed dataLayoutIndexed(data.m_Parameters.m_DataLayout); const unsigned int channelsIndex = dataLayoutIndexed.GetChannelsIndex(); const unsigned int heightIndex = dataLayoutIndexed.GetHeightIndex(); @@ -123,18 +128,41 @@ static void ConvImpl(ConvData data, // Since dimensionality of kernel depends on depthwiseness, so does index. if (depthwise) { - filterIndex = depthwiseMultiplierIdx * widthFilter * heightFilter * channelsInput + - cInput * widthFilter * heightFilter + - yFilter * widthFilter + - xFilter; + if (data.m_Parameters.m_DataLayout == DataLayout::NHWC) + { + filterIndex = depthwiseMultiplierIdx * heightFilter * widthFilter + * channelsInput + + yFilter * widthFilter * channelsInput + + xFilter * channelsInput + + cInput; + } + else + { + filterIndex = depthwiseMultiplierIdx * widthFilter * heightFilter + * channelsInput + + cInput * widthFilter * heightFilter + + yFilter * widthFilter + + xFilter; + } } else { - filterIndex = cOutput * widthFilter * heightFilter * channelsInput + - cInput * widthFilter * heightFilter + - yFilter * widthFilter + - xFilter; + if (data.m_Parameters.m_DataLayout == DataLayout::NHWC) + { + filterIndex = cOutput * heightFilter * widthFilter * channelsInput + + yFilter * widthFilter * channelsInput + + xFilter * channelsInput + + cInput; + } + else + { + filterIndex = cOutput * widthFilter * heightFilter * channelsInput + + cInput * widthFilter * heightFilter + + yFilter * widthFilter + + xFilter; + } } + AccumulatorType filterValue = filterData[filterIndex] - boost::numeric_cast<AccumulatorType>(filterOffset); @@ -151,11 +179,27 @@ static void ConvImpl(ConvData data, } else { - inputValue = inputData[batchIdx * widthInput * heightInput * channelsInput + - widthInput * heightInput * cInput + - widthInput * (yInput - paddingTop) + - xInput - paddingLeft] - - boost::numeric_cast<AccumulatorType>(inputOffset); + unsigned int inputIndex; + + if (data.m_Parameters.m_DataLayout == DataLayout::NHWC) + { + inputIndex = batchIdx * heightInput * widthInput * channelsInput + + (yInput - paddingTop) * widthInput * channelsInput + + (xInput - paddingLeft) * channelsInput + + cInput; + + } + else + { + inputIndex = batchIdx * widthInput * heightInput * channelsInput + + widthInput * heightInput * cInput + + widthInput * (yInput - paddingTop) + + xInput - paddingLeft; + } + + inputValue = inputData[inputIndex] - + boost::numeric_cast<AccumulatorType>(inputOffset); + } sum += filterValue * inputValue; } @@ -179,10 +223,7 @@ static void ConvImpl(ConvData data, sum = std::min<AccumulatorType>(std::max<AccumulatorType>(sum, 0), 255); } - outputData[batchIdx * widthOutput * heightOutput * channelsOutput + - widthOutput * heightOutput * cOutput + - widthOutput * yOutput + - xOutput] = boost::numeric_cast<InputType>(sum); + output.Get(batchIdx, cOutput, yOutput, xOutput) = boost::numeric_cast<InputType>(sum); } } } |