diff options
Diffstat (limited to 'src/backends')
16 files changed, 1535 insertions, 8 deletions
diff --git a/src/backends/backendsCommon/test/CommonTestUtils.cpp b/src/backends/backendsCommon/test/CommonTestUtils.cpp index 950b939d71..80512e290a 100644 --- a/src/backends/backendsCommon/test/CommonTestUtils.cpp +++ b/src/backends/backendsCommon/test/CommonTestUtils.cpp @@ -50,3 +50,21 @@ armnn::IBackendInternalUniquePtr CreateBackendObject(const armnn::BackendId& bac return backendObjPtr; } + +armnn::TensorShape MakeTensorShape(unsigned int batches, + unsigned int channels, + unsigned int height, + unsigned int width, + armnn::DataLayout layout) +{ + using namespace armnn; + switch (layout) + { + case DataLayout::NCHW: + return TensorShape{ batches, channels, height, width }; + case DataLayout::NHWC: + return TensorShape{ batches, height, width, channels }; + default: + throw InvalidArgumentException(std::string("Unsupported data layout: ") + GetDataLayoutName(layout)); + } +} diff --git a/src/backends/backendsCommon/test/CommonTestUtils.hpp b/src/backends/backendsCommon/test/CommonTestUtils.hpp index 03c975540a..58bd6b197f 100644 --- a/src/backends/backendsCommon/test/CommonTestUtils.hpp +++ b/src/backends/backendsCommon/test/CommonTestUtils.hpp @@ -68,3 +68,9 @@ armnn::SubgraphView::SubgraphViewPtr CreateSubgraphViewFrom(armnn::SubgraphView: armnn::SubgraphView::Layers&& layers); armnn::IBackendInternalUniquePtr CreateBackendObject(const armnn::BackendId& backendId); + +armnn::TensorShape MakeTensorShape(unsigned int batches, + unsigned int channels, + unsigned int height, + unsigned int width, + armnn::DataLayout layout);
\ No newline at end of file diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp index a625097fdb..ca39438fbf 100644 --- a/src/backends/backendsCommon/test/LayerTests.cpp +++ b/src/backends/backendsCommon/test/LayerTests.cpp @@ -45,6 +45,7 @@ #include "DebugTestImpl.hpp" #include "DequantizeTestImpl.hpp" #include "QuantizeTestImpl.hpp" +#include "TransposeConvolution2dTestImpl.hpp" // 3-channel 16x8 image used as common input data for a number of Conv2d tests. static std::vector<float> ConvInput3x8x16({ @@ -9643,3 +9644,409 @@ LayerTestResult<int16_t, 4> QuantizeClampInt16Test( { return QuantizeClampTest<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager); } + +// +// TransposeConvolution2d +// + +// Simple biased +LayerTestResult<float, 4> SimpleTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NCHW); +} + +LayerTestResult<float, 4> SimpleTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NHWC); +} + +LayerTestResult<uint8_t, 4> SimpleTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NCHW); +} + +LayerTestResult<uint8_t, 4> SimpleTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NHWC); +} + +LayerTestResult<int16_t, 4> SimpleTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NCHW); +} + +LayerTestResult<int16_t, 4> SimpleTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NHWC); +} + +// Simple unbiased +LayerTestResult<float, 4> UnbiasedSimpleTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NCHW); +} + +LayerTestResult<float, 4> UnbiasedSimpleTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NHWC); +} + +LayerTestResult<uint8_t, 4> UnbiasedSimpleTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NCHW); +} + +LayerTestResult<uint8_t, 4> UnbiasedSimpleTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NHWC); +} + +LayerTestResult<int16_t, 4> UnbiasedSimpleTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NCHW); +} + +LayerTestResult<int16_t, 4> UnbiasedSimpleTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return SimpleTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NHWC); +} + +// Padded biased +LayerTestResult<float, 4> PaddedTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NCHW); +} + +LayerTestResult<float, 4> PaddedTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NHWC); +} + +LayerTestResult<uint8_t, 4> PaddedTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NCHW); +} + +LayerTestResult<uint8_t, 4> PaddedTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NHWC); +} + +LayerTestResult<int16_t, 4> PaddedTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NCHW); +} + +LayerTestResult<int16_t, 4> PaddedTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NHWC); +} + +// Padded unbiased +LayerTestResult<float, 4> UnbiasedPaddedTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NCHW); +} + +LayerTestResult<float, 4> UnbiasedPaddedTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NHWC); +} + +LayerTestResult<uint8_t, 4> UnbiasedPaddedTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NCHW); +} + +LayerTestResult<uint8_t, 4> UnbiasedPaddedTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NHWC); +} + +LayerTestResult<int16_t, 4> UnbiasedPaddedTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NCHW); +} + +LayerTestResult<int16_t, 4> UnbiasedPaddedTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return PaddedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NHWC); +} + +// Strided biased +LayerTestResult<float, 4> StridedTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NCHW); +} + +LayerTestResult<float, 4> StridedTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NHWC); +} + +LayerTestResult<uint8_t, 4> StridedTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NCHW); +} + +LayerTestResult<uint8_t, 4> StridedTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NHWC); +} + +LayerTestResult<int16_t, 4> StridedTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NCHW); +} + +LayerTestResult<int16_t, 4> StridedTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + true, + armnn::DataLayout::NHWC); +} + +// Strided unbiased +LayerTestResult<float, 4> UnbiasedStridedTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NCHW); +} + +LayerTestResult<float, 4> UnbiasedStridedTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NHWC); +} + +LayerTestResult<uint8_t, 4> UnbiasedStridedTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NCHW); +} + +LayerTestResult<uint8_t, 4> UnbiasedStridedTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedAsymm8, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NHWC); +} + +LayerTestResult<int16_t, 4> UnbiasedStridedTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NCHW); +} + +LayerTestResult<int16_t, 4> UnbiasedStridedTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + return StridedTransposeConvolution2dTestImpl<armnn::DataType::QuantisedSymm16, armnn::DataType::Signed32>( + workloadFactory, + memoryManager, + false, + armnn::DataLayout::NHWC); +}
\ No newline at end of file diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp index 10bc00f83b..b225e4d655 100644 --- a/src/backends/backendsCommon/test/LayerTests.hpp +++ b/src/backends/backendsCommon/test/LayerTests.hpp @@ -3760,3 +3760,157 @@ template LayerTestResult<typename armnn::ResolveType<armnn::DataType::QuantisedS PreluTest<armnn::DataType::QuantisedSymm16>( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +// +// TransposeConvolution2d +// + +// Simple biased +LayerTestResult<float, 4> SimpleTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<float, 4> SimpleTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> SimpleTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> SimpleTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> SimpleTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> SimpleTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +// Simple unbiased +LayerTestResult<float, 4> UnbiasedSimpleTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<float, 4> UnbiasedSimpleTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> UnbiasedSimpleTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> UnbiasedSimpleTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> UnbiasedSimpleTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> UnbiasedSimpleTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +// Padded biased +LayerTestResult<float, 4> PaddedTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<float, 4> PaddedTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> PaddedTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> PaddedTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> PaddedTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> PaddedTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +// Padded unbiased +LayerTestResult<float, 4> UnbiasedPaddedTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<float, 4> UnbiasedPaddedTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> UnbiasedPaddedTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> UnbiasedPaddedTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> UnbiasedPaddedTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> UnbiasedPaddedTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +// Strided biased +LayerTestResult<float, 4> StridedTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<float, 4> StridedTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> StridedTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> StridedTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> StridedTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> StridedTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +// Strided unbiased +LayerTestResult<float, 4> UnbiasedStridedTransposeConvolution2dFloatNchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<float, 4> UnbiasedStridedTransposeConvolution2dFloatNhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> UnbiasedStridedTransposeConvolution2dUint8NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<uint8_t, 4> UnbiasedStridedTransposeConvolution2dUint8NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> UnbiasedStridedTransposeConvolution2dInt16NchwTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + +LayerTestResult<int16_t, 4> UnbiasedStridedTransposeConvolution2dInt16NhwcTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
\ No newline at end of file diff --git a/src/backends/backendsCommon/test/TransposeConvolution2dTestImpl.hpp b/src/backends/backendsCommon/test/TransposeConvolution2dTestImpl.hpp new file mode 100644 index 0000000000..3bbd5d6770 --- /dev/null +++ b/src/backends/backendsCommon/test/TransposeConvolution2dTestImpl.hpp @@ -0,0 +1,498 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// +#pragma once + +#include "QuantizeHelper.hpp" + +#include <armnn/ArmNN.hpp> + +#include <ResolveType.hpp> + +#include <backendsCommon/CpuTensorHandle.hpp> +#include <backendsCommon/test/CommonTestUtils.hpp> +#include <backendsCommon/test/TensorCopyUtils.hpp> +#include <backendsCommon/test/WorkloadTestUtils.hpp> + +#include <reference/RefWorkloadFactory.hpp> + +#include <boost/test/unit_test.hpp> + +#include <string> +#include <utility> +#include <vector> + +namespace +{ + +template<typename T> +using TensorData = std::pair<armnn::TensorInfo, std::vector<T>>; + +template<typename T> +void VerifyInputTensorData(const TensorData<T>& data, const std::string& tensorName) +{ + if (data.first.GetNumElements() > data.second.size()) + { + throw armnn::InvalidArgumentException("Size of data too small for " + tensorName + ": expected " + + std::to_string(data.first.GetNumElements()) + "but got " + std::to_string(data.second.size())); + } +} + +template<typename T, typename BT> +void TransposeConvolution2dTestImpl(armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::TransposeConvolution2dDescriptor& descriptor, + const TensorData<T>& input, + TensorData<T>& output, + const TensorData<T>& weights, + const armnn::Optional<TensorData<BT>>& biases) +{ + using namespace armnn; + + VerifyInputTensorData(input, "input"); + VerifyInputTensorData(weights, "biases"); + + if (descriptor.m_BiasEnabled) + { + if (!biases.has_value()) + { + throw InvalidArgumentException("Bias enabled but no bias data provided"); + } + VerifyInputTensorData(biases.value(), "biases"); + } + + // set up weights + ScopedCpuTensorHandle weightsTensor(weights.first); + + TransposeConvolution2dQueueDescriptor queueDescriptor; + queueDescriptor.m_Parameters = descriptor; + queueDescriptor.m_Weight = &weightsTensor; + + AllocateAndCopyDataToITensorHandle(&weightsTensor, weights.second.data()); + + std::unique_ptr<ScopedCpuTensorHandle> biasesTensor; + if (descriptor.m_BiasEnabled) + { + // set up biases + biasesTensor = std::make_unique<ScopedCpuTensorHandle>(biases.value().first); + queueDescriptor.m_Bias = biasesTensor.get(); + + AllocateAndCopyDataToITensorHandle(biasesTensor.get(), biases.value().second.data()); + } + + // set up input and output handles + std::unique_ptr<ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(input.first); + std::unique_ptr<ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(output.first); + + // set up workload + armnn::WorkloadInfo workloadInfo; + AddInputToWorkload(queueDescriptor, workloadInfo, input.first, inputHandle.get()); + AddOutputToWorkload(queueDescriptor, workloadInfo, output.first, outputHandle.get()); + + std::unique_ptr<armnn::IWorkload> workload = + workloadFactory.CreateTransposeConvolution2d(queueDescriptor, workloadInfo); + + inputHandle->Allocate(); + outputHandle->Allocate(); + + CopyDataToITensorHandle(inputHandle.get(), input.second.data()); + + ExecuteWorkload(*workload, nullptr); + + // copy output + output.second = std::vector<T>(output.first.GetNumElements(), 0.0f); + CopyDataFromITensorHandle(output.second.data(), outputHandle.get()); +} + +template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>> +LayerTestResult<T, 4> TransposeConvolution2dTestImpl( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::TransposeConvolution2dDescriptor& descriptor, + armnn::TensorInfo& inputInfo, + const std::vector<float>& inputData, + armnn::TensorInfo& outputInfo, + const std::vector<float>& expectedOutputData, + armnn::TensorInfo& weightsInfo, + const std::vector<float>& weightsData, + armnn::TensorInfo& biasesInfo, + const std::vector<float>& biasesData) +{ + using namespace armnn; + + // set up quantization parameters + if (armnn::IsQuantizedType<T>()) + { + constexpr float qScale = 0.25f; + constexpr int32_t qOffset = 50; + + inputInfo.SetQuantizationScale(qScale); + inputInfo.SetQuantizationOffset(qOffset); + + outputInfo.SetQuantizationScale(qScale); + outputInfo.SetQuantizationOffset(qOffset); + + weightsInfo.SetQuantizationScale(qScale); + weightsInfo.SetQuantizationOffset(qOffset); + + biasesInfo.SetQuantizationScale(qScale * qScale); + biasesInfo.SetQuantizationOffset(0); + } + + // set up input + TensorData<T> input = + { + inputInfo, + QuantizedVector<T>(inputInfo.GetQuantizationScale(), inputInfo.GetQuantizationOffset(), inputData) + }; + + // set up weights + TensorData<T> weights = + { + weightsInfo, + QuantizedVector<T>(weightsInfo.GetQuantizationScale(), weightsInfo.GetQuantizationOffset(), weightsData) + }; + + // set up biases + using BT = armnn::ResolveType<ArmnnBType>; + Optional<TensorData<BT>> optionalBiases; + if (descriptor.m_BiasEnabled) + { + TensorData<BT> biases = + { + biasesInfo, + QuantizedVector<BT>(biasesInfo.GetQuantizationScale(), biasesInfo.GetQuantizationOffset(), biasesData) + }; + + optionalBiases = Optional<TensorData<BT>>(biases); + } + + // set up output + TensorData<T> output = { outputInfo, {} }; + + // execute test + TransposeConvolution2dTestImpl(workloadFactory, + memoryManager, + descriptor, + input, + output, + weights, + optionalBiases); + + // construct result object + LayerTestResult<T, 4> testResult(outputInfo); + testResult.output = MakeTensor<T, 4>(outputInfo, output.second); + testResult.outputExpected = MakeTensor<T, 4>(outputInfo, + QuantizedVector<T>(outputInfo.GetQuantizationScale(), + outputInfo.GetQuantizationOffset(), + expectedOutputData)); + + return testResult; +} + +} // anonymous namespace + +template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>> +LayerTestResult<T, 4> SimpleTransposeConvolution2dTestImpl( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + bool biasEnabled, + const armnn::DataLayout layout) +{ + using namespace armnn; + + constexpr unsigned int batches = 1u; + constexpr unsigned int channels = 1u; + + constexpr unsigned int wInput = 3u; + constexpr unsigned int hInput = wInput; + + constexpr unsigned int wOutput = 5u; + constexpr unsigned int hOutput = wOutput; + + constexpr unsigned int wWeights = 3u; + constexpr unsigned int hWeights = wWeights; + + TensorShape inputShape = MakeTensorShape(batches, channels, hInput, wInput, layout); + TensorShape outputShape = MakeTensorShape(batches, channels, hOutput, wOutput, layout); + TensorShape weightsShape = MakeTensorShape(batches, channels, hWeights, wWeights, layout); + + TensorInfo inputInfo(inputShape, ArmnnType); + TensorInfo outputInfo(outputShape, ArmnnType); + TensorInfo weightsInfo(weightsShape, ArmnnType); + TensorInfo biasesInfo({ channels }, ArmnnBType); + + std::vector<float> inputData = + { + 1.f, 1.f, 1.f, + 1.f, 1.f, 1.f, + 1.f, 1.f, 1.f + }; + + std::vector<float> weightsData = + { + 1.f, 2.f, 3.f, + 4.f, 5.f, 6.f, + 7.f, 8.f, 9.f + }; + + std::vector<float> biasesData = { 1.f }; + + std::vector<float> expectedOutputData = + { + 1.f, 3.f, 6.f, 5.f, 3.f, + 5.f, 12.f, 21.f, 16.f, 9.f, + 12.f, 27.f, 45.f, 33.f, 18.f, + 11.f, 24.f, 39.f, 28.f, 15.f, + 7.f, 15.f, 24.f, 17.f, 9.f + }; + + if (biasEnabled) + { + // apply bias to expected output data + std::transform(expectedOutputData.begin(), expectedOutputData.end(), expectedOutputData.begin(), + [&](float f) -> float { return f + biasesData[0]; }); + } + + TransposeConvolution2dDescriptor descriptor; + descriptor.m_StrideX = 1; + descriptor.m_StrideY = 1; + descriptor.m_BiasEnabled = biasEnabled; + descriptor.m_DataLayout = layout; + + // swizzle data if needed + if (layout == armnn::DataLayout::NHWC) + { + constexpr size_t dataTypeSize = sizeof(float); + const armnn::PermutationVector nchwToNhwc = { 0, 3, 1, 2 }; + + std::vector<float> tmp(inputData.size()); + armnnUtils::Permute(inputInfo.GetShape(), nchwToNhwc, inputData.data(), tmp.data(), dataTypeSize); + inputData = tmp; + + tmp.resize(weightsData.size()); + armnnUtils::Permute(weightsInfo.GetShape(), nchwToNhwc, weightsData.data(), tmp.data(), dataTypeSize); + weightsData = tmp; + + tmp.resize(expectedOutputData.size()); + armnnUtils::Permute(outputInfo.GetShape(), nchwToNhwc, expectedOutputData.data(), tmp.data(), dataTypeSize); + expectedOutputData = tmp; + } + + return TransposeConvolution2dTestImpl<ArmnnType, ArmnnBType>(workloadFactory, + memoryManager, + descriptor, + inputInfo, + inputData, + outputInfo, + expectedOutputData, + weightsInfo, + weightsData, + biasesInfo, + biasesData); +} + +template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>> +LayerTestResult<T, 4> PaddedTransposeConvolution2dTestImpl( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + bool biasEnabled, + const armnn::DataLayout layout) +{ + using namespace armnn; + + constexpr unsigned int batches = 1u; + constexpr unsigned int channels = 1u; + + constexpr unsigned int wInput = 4u; + constexpr unsigned int hInput = wInput; + + constexpr unsigned int wOutput = 2u; + constexpr unsigned int hOutput = wOutput; + + constexpr unsigned int wWeights = 3u; + constexpr unsigned int hWeights = wWeights; + + TensorShape inputShape = MakeTensorShape(batches, channels, hInput, wInput, layout); + TensorShape outputShape = MakeTensorShape(batches, channels, hOutput, wOutput, layout); + TensorShape weightsShape = MakeTensorShape(batches, channels, hWeights, wWeights, layout); + + TensorInfo inputInfo(inputShape, ArmnnType); + TensorInfo outputInfo(outputShape, ArmnnType); + TensorInfo weightsInfo(weightsShape, ArmnnType); + TensorInfo biasesInfo({ channels }, ArmnnBType); + + std::vector<float> inputData = + { + 1.f, 3.f, 2.f, 1.f, + 1.f, 3.f, 3.f, 1.f, + 2.f, 1.f, 1.f, 3.f, + 3.f, 2.f, 3.f, 3.f + }; + + std::vector<float> weightsData = + { + 1.f, 2.f, 3.f, + 0.f, 1.f, 0.f, + 2.f, 1.f, 2.f + }; + + std::vector<float> biasesData = { 1.f }; + + std::vector<float> expectedOutputData = + { + 21.f, 21.f, + 28.f, 27.f + }; + + if (biasEnabled) + { + // apply bias to expected output data + std::transform(expectedOutputData.begin(), expectedOutputData.end(), expectedOutputData.begin(), + [&](float f) -> float { return f + biasesData[0]; }); + } + + TransposeConvolution2dDescriptor descriptor; + descriptor.m_PadLeft = 2; + descriptor.m_PadRight = 2; + descriptor.m_PadTop = 2; + descriptor.m_PadBottom = 2; + descriptor.m_StrideX = 1; + descriptor.m_StrideY = 1; + descriptor.m_BiasEnabled = biasEnabled; + descriptor.m_DataLayout = layout; + + // swizzle data if needed + if (layout == armnn::DataLayout::NHWC) + { + constexpr size_t dataTypeSize = sizeof(float); + const armnn::PermutationVector nchwToNhwc = { 0, 3, 1, 2 }; + + std::vector<float> tmp(inputData.size()); + armnnUtils::Permute(inputInfo.GetShape(), nchwToNhwc, inputData.data(), tmp.data(), dataTypeSize); + inputData = tmp; + + tmp.resize(weightsData.size()); + armnnUtils::Permute(weightsInfo.GetShape(), nchwToNhwc, weightsData.data(), tmp.data(), dataTypeSize); + weightsData = tmp; + + tmp.resize(expectedOutputData.size()); + armnnUtils::Permute(outputInfo.GetShape(), nchwToNhwc, expectedOutputData.data(), tmp.data(), dataTypeSize); + expectedOutputData = tmp; + } + + return TransposeConvolution2dTestImpl<ArmnnType, ArmnnBType>(workloadFactory, + memoryManager, + descriptor, + inputInfo, + inputData, + outputInfo, + expectedOutputData, + weightsInfo, + weightsData, + biasesInfo, + biasesData); +} + + template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>> + LayerTestResult<T, 4> StridedTransposeConvolution2dTestImpl( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + bool biasEnabled, + const armnn::DataLayout layout) +{ + using namespace armnn; + + constexpr unsigned int batches = 1u; + constexpr unsigned int channels = 1u; + + constexpr unsigned int wInput = 3u; + constexpr unsigned int hInput = wInput; + + constexpr unsigned int wOutput = 7u; + constexpr unsigned int hOutput = wOutput; + + constexpr unsigned int wWeights = 3u; + constexpr unsigned int hWeights = wWeights; + + TensorShape inputShape = MakeTensorShape(batches, channels, hInput, wInput, layout); + TensorShape outputShape = MakeTensorShape(batches, channels, hOutput, wOutput, layout); + TensorShape weightsShape = MakeTensorShape(batches, channels, hWeights, wWeights, layout); + + TensorInfo inputInfo(inputShape, ArmnnType); + TensorInfo outputInfo(outputShape, ArmnnType); + TensorInfo weightsInfo(weightsShape, ArmnnType); + TensorInfo biasesInfo({ channels }, ArmnnBType); + + std::vector<float> inputData = + { + 1.f, 1.f, 1.f, + 1.f, 1.f, 1.f, + 1.f, 1.f, 1.f + }; + + std::vector<float> weightsData = + { + 1.f, 2.f, 3.f, + 4.f, 5.f, 6.f, + 7.f, 8.f, 9.f + }; + + std::vector<float> biasesData = { 1.f }; + + std::vector<float> expectedOutputData = + { + 1.f, 2.f, 4.f, 2.f, 4.f, 2.f, 3.f, + 4.f, 5.f, 10.f, 5.f, 10.f, 5.f, 6.f, + 8.f, 10.f, 20.f, 10.f, 20.f, 10.f, 12.f, + 4.f, 5.f, 10.f, 5.f, 10.f, 5.f, 6.f, + 8.f, 10.f, 20.f, 10.f, 20.f, 10.f, 12.f, + 4.f, 5.f, 10.f, 5.f, 10.f, 5.f, 6.f, + 7.f, 8.f, 16.f, 8.f, 16.f, 8.f, 9.f + }; + + if (biasEnabled) + { + // apply bias to expected output data + std::transform(expectedOutputData.begin(), expectedOutputData.end(), expectedOutputData.begin(), + [&](float f) -> float { return f + biasesData[0]; }); + } + + TransposeConvolution2dDescriptor descriptor; + descriptor.m_StrideX = 2; + descriptor.m_StrideY = 2; + descriptor.m_BiasEnabled = biasEnabled; + descriptor.m_DataLayout = layout; + + // swizzle data if needed + if (layout == armnn::DataLayout::NHWC) + { + constexpr size_t dataTypeSize = sizeof(float); + const armnn::PermutationVector nchwToNhwc = { 0, 3, 1, 2 }; + + std::vector<float> tmp(inputData.size()); + armnnUtils::Permute(inputInfo.GetShape(), nchwToNhwc, inputData.data(), tmp.data(), dataTypeSize); + inputData = tmp; + + tmp.resize(weightsData.size()); + armnnUtils::Permute(weightsInfo.GetShape(), nchwToNhwc, weightsData.data(), tmp.data(), dataTypeSize); + weightsData = tmp; + + tmp.resize(expectedOutputData.size()); + armnnUtils::Permute(outputInfo.GetShape(), nchwToNhwc, expectedOutputData.data(), tmp.data(), dataTypeSize); + expectedOutputData = tmp; + } + + return TransposeConvolution2dTestImpl<ArmnnType, ArmnnBType>(workloadFactory, + memoryManager, + descriptor, + inputInfo, + inputData, + outputInfo, + expectedOutputData, + weightsInfo, + weightsData, + biasesInfo, + biasesData); +}
\ No newline at end of file diff --git a/src/backends/reference/CMakeLists.txt b/src/backends/reference/CMakeLists.txt index 82880cf524..ff16f185b4 100644 --- a/src/backends/reference/CMakeLists.txt +++ b/src/backends/reference/CMakeLists.txt @@ -11,7 +11,6 @@ list(APPEND armnnRefBackend_sources RefLayerSupport.hpp RefWorkloadFactory.cpp RefWorkloadFactory.hpp - ) add_library(armnnRefBackend OBJECT ${armnnRefBackend_sources}) diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp index 035a28b71a..5ede8b3f02 100644 --- a/src/backends/reference/RefWorkloadFactory.cpp +++ b/src/backends/reference/RefWorkloadFactory.cpp @@ -464,4 +464,11 @@ std::unique_ptr<IWorkload> RefWorkloadFactory::CreatePrelu(const PreluQueueDescr return std::make_unique<RefPreluWorkload>(descriptor, info); } +std::unique_ptr<IWorkload> RefWorkloadFactory::CreateTransposeConvolution2d( + const TransposeConvolution2dQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return std::make_unique<RefTransposeConvolution2dWorkload>(descriptor, info); +} + } // namespace armnn diff --git a/src/backends/reference/RefWorkloadFactory.hpp b/src/backends/reference/RefWorkloadFactory.hpp index ed513e1e3b..44cb079ea7 100644 --- a/src/backends/reference/RefWorkloadFactory.hpp +++ b/src/backends/reference/RefWorkloadFactory.hpp @@ -193,6 +193,9 @@ public: std::unique_ptr<IWorkload> CreatePrelu(const PreluQueueDescriptor& descriptor, const WorkloadInfo& info) const override; + std::unique_ptr<IWorkload> CreateTransposeConvolution2d(const TransposeConvolution2dQueueDescriptor& descriptor, + const WorkloadInfo& info) const override; + private: template <typename F32Workload, typename U8Workload, typename QueueDescriptorType> diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk index 849d87c4ca..6fb17b563f 100644 --- a/src/backends/reference/backend.mk +++ b/src/backends/reference/backend.mk @@ -60,6 +60,7 @@ BACKEND_SOURCES := \ workloads/RefSpaceToDepthWorkload.cpp \ workloads/RefStridedSliceWorkload.cpp \ workloads/RefSplitterWorkload.cpp \ + workloads/RefTransposeConvolution2dWorkload.cpp \ workloads/ResizeBilinear.cpp \ workloads/Rsqrt.cpp \ workloads/SpaceToBatchNd.cpp \ @@ -67,7 +68,8 @@ BACKEND_SOURCES := \ workloads/StridedSlice.cpp \ workloads/StringMapping.cpp \ workloads/Softmax.cpp \ - workloads/Splitter.cpp + workloads/Splitter.cpp \ + workloads/TransposeConvolution2d.cpp # BACKEND_TEST_SOURCES contains the list of files to be included # in the Android unit test build (armnn-tests) and it is picked diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp index b997a14e9d..3556df18b1 100644 --- a/src/backends/reference/test/RefLayerTests.cpp +++ b/src/backends/reference/test/RefLayerTests.cpp @@ -10,6 +10,7 @@ #include <reference/RefWorkloadFactory.hpp> #include <backendsCommon/test/DetectionPostProcessLayerTestImpl.hpp> +#include <backendsCommon/test/TransposeConvolution2dTestImpl.hpp> #include <backendsCommon/test/LayerTests.hpp> #include <boost/test/unit_test.hpp> @@ -966,4 +967,47 @@ ARMNN_AUTO_TEST_CASE(PreluFloat32, PreluTest<armnn::DataType::Float32>) ARMNN_AUTO_TEST_CASE(PreluUint8, PreluTest<armnn::DataType::QuantisedAsymm8>) ARMNN_AUTO_TEST_CASE(PreluInt16, PreluTest<armnn::DataType::QuantisedSymm16>) +// TransposeConvolution2d +ARMNN_AUTO_TEST_CASE(SimpleTransposeConvolution2dFloatNchw, SimpleTransposeConvolution2dFloatNchwTest) +ARMNN_AUTO_TEST_CASE(SimpleTransposeConvolution2dFloatNhwc, SimpleTransposeConvolution2dFloatNhwcTest) +ARMNN_AUTO_TEST_CASE(SimpleTransposeConvolution2dUint8Nchw, SimpleTransposeConvolution2dUint8NchwTest) +ARMNN_AUTO_TEST_CASE(SimpleTransposeConvolution2dUint8Nhwc, SimpleTransposeConvolution2dUint8NhwcTest) +ARMNN_AUTO_TEST_CASE(SimpleTransposeConvolution2dInt16Nchw, SimpleTransposeConvolution2dInt16NchwTest) +ARMNN_AUTO_TEST_CASE(SimpleTransposeConvolution2dInt16Nhwc, SimpleTransposeConvolution2dInt16NhwcTest) + +ARMNN_AUTO_TEST_CASE(UnbiasedSimpleTransposeConvolution2dFloatNchw, UnbiasedSimpleTransposeConvolution2dFloatNchwTest) +ARMNN_AUTO_TEST_CASE(UnbiasedSimpleTransposeConvolution2dFloatNhwc, UnbiasedSimpleTransposeConvolution2dFloatNhwcTest) +ARMNN_AUTO_TEST_CASE(UnbiasedSimpleTransposeConvolution2dUint8Nchw, UnbiasedSimpleTransposeConvolution2dUint8NchwTest) +ARMNN_AUTO_TEST_CASE(UnbiasedSimpleTransposeConvolution2dUint8Nhwc, UnbiasedSimpleTransposeConvolution2dUint8NhwcTest) +ARMNN_AUTO_TEST_CASE(UnbiasedSimpleTransposeConvolution2dInt16Nchw, UnbiasedSimpleTransposeConvolution2dInt16NchwTest) +ARMNN_AUTO_TEST_CASE(UnbiasedSimpleTransposeConvolution2dInt16Nhwc, UnbiasedSimpleTransposeConvolution2dInt16NhwcTest) + +ARMNN_AUTO_TEST_CASE(PaddedTransposeConvolution2dFloatNchw, PaddedTransposeConvolution2dFloatNchwTest) +ARMNN_AUTO_TEST_CASE(PaddedTransposeConvolution2dFloatNhwc, PaddedTransposeConvolution2dFloatNhwcTest) +ARMNN_AUTO_TEST_CASE(PaddedTransposeConvolution2dUint8Nchw, PaddedTransposeConvolution2dUint8NchwTest) +ARMNN_AUTO_TEST_CASE(PaddedTransposeConvolution2dUint8Nhwc, PaddedTransposeConvolution2dUint8NhwcTest) +ARMNN_AUTO_TEST_CASE(PaddedTransposeConvolution2dInt16Nchw, PaddedTransposeConvolution2dInt16NchwTest) +ARMNN_AUTO_TEST_CASE(PaddedTransposeConvolution2dInt16Nhwc, PaddedTransposeConvolution2dInt16NhwcTest) + +ARMNN_AUTO_TEST_CASE(UnbiasedPaddedTransposeConvolution2dFloatNchw, UnbiasedPaddedTransposeConvolution2dFloatNchwTest) +ARMNN_AUTO_TEST_CASE(UnbiasedPaddedTransposeConvolution2dFloatNhwc, UnbiasedPaddedTransposeConvolution2dFloatNhwcTest) +ARMNN_AUTO_TEST_CASE(UnbiasedPaddedTransposeConvolution2dUint8Nchw, UnbiasedPaddedTransposeConvolution2dUint8NchwTest) +ARMNN_AUTO_TEST_CASE(UnbiasedPaddedTransposeConvolution2dUint8Nhwc, UnbiasedPaddedTransposeConvolution2dUint8NhwcTest) +ARMNN_AUTO_TEST_CASE(UnbiasedPaddedTransposeConvolution2dInt16Nchw, UnbiasedPaddedTransposeConvolution2dInt16NchwTest) +ARMNN_AUTO_TEST_CASE(UnbiasedPaddedTransposeConvolution2dInt16Nhwc, UnbiasedPaddedTransposeConvolution2dInt16NhwcTest) + +ARMNN_AUTO_TEST_CASE(StridedTransposeConvolution2dFloatNhwc, StridedTransposeConvolution2dFloatNhwcTest) +ARMNN_AUTO_TEST_CASE(StridedTransposeConvolution2dFloatNchw, StridedTransposeConvolution2dFloatNchwTest) +ARMNN_AUTO_TEST_CASE(StridedTransposeConvolution2dUint8Nhwc, StridedTransposeConvolution2dUint8NhwcTest) +ARMNN_AUTO_TEST_CASE(StridedTransposeConvolution2dUint8Nchw, StridedTransposeConvolution2dUint8NchwTest) +ARMNN_AUTO_TEST_CASE(StridedTransposeConvolution2dInt16Nhwc, StridedTransposeConvolution2dInt16NhwcTest) +ARMNN_AUTO_TEST_CASE(StridedTransposeConvolution2dInt16Nchw, StridedTransposeConvolution2dInt16NchwTest) + +ARMNN_AUTO_TEST_CASE(UnbiasedStridedTransposeConvolution2dFloatNhwc, UnbiasedStridedTransposeConvolution2dFloatNhwcTest) +ARMNN_AUTO_TEST_CASE(UnbiasedStridedTransposeConvolution2dFloatNchw, UnbiasedStridedTransposeConvolution2dFloatNchwTest) +ARMNN_AUTO_TEST_CASE(UnbiasedStridedTransposeConvolution2dUint8Nhwc, UnbiasedStridedTransposeConvolution2dUint8NhwcTest) +ARMNN_AUTO_TEST_CASE(UnbiasedStridedTransposeConvolution2dUint8Nchw, UnbiasedStridedTransposeConvolution2dUint8NchwTest) +ARMNN_AUTO_TEST_CASE(UnbiasedStridedTransposeConvolution2dInt16Nhwc, UnbiasedStridedTransposeConvolution2dInt16NhwcTest) +ARMNN_AUTO_TEST_CASE(UnbiasedStridedTransposeConvolution2dInt16Nchw, UnbiasedStridedTransposeConvolution2dInt16NchwTest) + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index daa004345c..9be245b1a7 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -29,6 +29,8 @@ list(APPEND armnnRefBackendWorkloads_sources Gather.hpp LstmUtils.hpp Maximum.hpp + Mean.cpp + Mean.hpp Concatenate.hpp Concatenate.cpp Minimum.hpp @@ -44,6 +46,8 @@ list(APPEND armnnRefBackendWorkloads_sources RefBatchNormalizationWorkload.hpp RefBatchToSpaceNdWorkload.cpp RefBatchToSpaceNdWorkload.hpp + RefConcatWorkload.cpp + RefConcatWorkload.hpp RefConstantWorkload.cpp RefConstantWorkload.hpp RefConvertFp16ToFp32Workload.cpp @@ -74,8 +78,8 @@ list(APPEND armnnRefBackendWorkloads_sources RefL2NormalizationWorkload.hpp RefLstmWorkload.cpp RefLstmWorkload.hpp - RefConcatWorkload.cpp - RefConcatWorkload.hpp + RefMeanWorkload.cpp + RefMeanWorkload.hpp RefNormalizationWorkload.cpp RefNormalizationWorkload.hpp RefPadWorkload.cpp @@ -104,6 +108,8 @@ list(APPEND armnnRefBackendWorkloads_sources RefSplitterWorkload.hpp RefStridedSliceWorkload.cpp RefStridedSliceWorkload.hpp + RefTransposeConvolution2dWorkload.cpp + RefTransposeConvolution2dWorkload.hpp RefWorkloads.hpp RefWorkloadUtils.hpp ResizeBilinear.cpp @@ -123,10 +129,8 @@ list(APPEND armnnRefBackendWorkloads_sources StringMapping.cpp StringMapping.hpp TensorBufferArrayView.hpp - Mean.cpp - Mean.hpp - RefMeanWorkload.cpp - RefMeanWorkload.hpp + TransposeConvolution2d.cpp + TransposeConvolution2d.hpp ) add_library(armnnRefBackendWorkloads OBJECT ${armnnRefBackendWorkloads_sources}) diff --git a/src/backends/reference/workloads/RefTransposeConvolution2dWorkload.cpp b/src/backends/reference/workloads/RefTransposeConvolution2dWorkload.cpp new file mode 100644 index 0000000000..50dafcac3c --- /dev/null +++ b/src/backends/reference/workloads/RefTransposeConvolution2dWorkload.cpp @@ -0,0 +1,67 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RefTransposeConvolution2dWorkload.hpp" + +#include "RefWorkloadUtils.hpp" +#include "TransposeConvolution2d.hpp" + +#include <Profiling.hpp> + +namespace armnn +{ + +RefTransposeConvolution2dWorkload::RefTransposeConvolution2dWorkload( + const TransposeConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) : + BaseWorkload<TransposeConvolution2dQueueDescriptor>(descriptor, info) +{ + // set up weights decoder + m_Weights = std::make_unique<ScopedCpuTensorHandle>(*(descriptor.m_Weight)); + const TensorInfo& weightsInfo = GetTensorInfo(m_Weights.get()); + + m_WeightsDecoder = MakeDecoder<float>(weightsInfo, m_Weights.get()->Map(true)); + m_WeightsShape = weightsInfo.GetShape(); + + // set up biases decoder + if (descriptor.m_Parameters.m_BiasEnabled) + { + m_Biases = std::make_unique<ScopedCpuTensorHandle>(*(descriptor.m_Bias)); + const TensorInfo& biasesInfo = GetTensorInfo(m_Biases.get()); + m_BiasesDecoder = MakeDecoder<float>(biasesInfo, m_Biases.get()->Map(true)); + } +} + +void RefTransposeConvolution2dWorkload::PostAllocationConfigure() +{ + // set up input decoder + const ITensorHandle* input = m_Data.m_Inputs[0]; + const TensorInfo& inputInfo = GetTensorInfo(input); + + m_InputShape = inputInfo.GetShape(); + m_InputDecoder = MakeDecoder<float>(inputInfo, input->Map()); + + // set up output encoder + ITensorHandle* output = m_Data.m_Outputs[0]; + const TensorInfo& outputInfo = GetTensorInfo(output); + + m_OutputShape = outputInfo.GetShape(); + m_OutputEncoder = MakeEncoder<float>(outputInfo, output->Map()); +} + +void RefTransposeConvolution2dWorkload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefTransposeConvolution2dWorkload_Execute"); + + TransposeConvolution2dImpl(m_Data.m_Parameters, + m_InputShape, + *m_InputDecoder, + m_OutputShape, + *m_OutputEncoder, + m_WeightsShape, + *m_WeightsDecoder, + m_BiasesDecoder.get()); +} + +} // namespace armnn
\ No newline at end of file diff --git a/src/backends/reference/workloads/RefTransposeConvolution2dWorkload.hpp b/src/backends/reference/workloads/RefTransposeConvolution2dWorkload.hpp new file mode 100644 index 0000000000..9ded8c971f --- /dev/null +++ b/src/backends/reference/workloads/RefTransposeConvolution2dWorkload.hpp @@ -0,0 +1,43 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "Decoders.hpp" +#include "Encoders.hpp" + +#include <backendsCommon/CpuTensorHandle.hpp> +#include <backendsCommon/Workload.hpp> + +namespace armnn +{ + +class RefTransposeConvolution2dWorkload : public BaseWorkload<TransposeConvolution2dQueueDescriptor> +{ +public: + RefTransposeConvolution2dWorkload(const TransposeConvolution2dQueueDescriptor& descriptor, + const WorkloadInfo& info); + ~RefTransposeConvolution2dWorkload() = default; + + void PostAllocationConfigure() override; + + void Execute() const override; + +private: + std::unique_ptr<ScopedCpuTensorHandle> m_Weights; + std::unique_ptr<ScopedCpuTensorHandle> m_Biases; + + std::unique_ptr<Decoder<float>> m_InputDecoder; + std::unique_ptr<Encoder<float>> m_OutputEncoder; + + std::unique_ptr<Decoder<float>> m_WeightsDecoder; + std::unique_ptr<Decoder<float>> m_BiasesDecoder; + + TensorShape m_InputShape; + TensorShape m_OutputShape; + TensorShape m_WeightsShape; +}; + +} // 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 90582812e7..3a094c8a32 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -47,6 +47,7 @@ #include "RefSpaceToBatchNdWorkload.hpp" #include "RefStridedSliceWorkload.hpp" #include "RefSpaceToDepthWorkload.hpp" +#include "RefTransposeConvolution2dWorkload.hpp" #include "RefWorkloadUtils.hpp" #include "ResizeBilinear.hpp" #include "Softmax.hpp" diff --git a/src/backends/reference/workloads/TransposeConvolution2d.cpp b/src/backends/reference/workloads/TransposeConvolution2d.cpp new file mode 100644 index 0000000000..db15cefe10 --- /dev/null +++ b/src/backends/reference/workloads/TransposeConvolution2d.cpp @@ -0,0 +1,248 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TransposeConvolution2d.hpp" + +#include <DataLayoutIndexed.hpp> + +namespace armnn +{ + +using namespace armnnUtils; + +struct TensorData +{ + TensorShape shape; + std::vector<float> data; +}; + +TensorData SetUpStridedInput(const TensorShape& inputShape, + Decoder<float>& inputDecoder, + const TransposeConvolution2dDescriptor& descriptor, + const DataLayoutIndexed& dataLayoutIndexed) +{ + const unsigned int cIndex = dataLayoutIndexed.GetChannelsIndex(); + const unsigned int hIndex = dataLayoutIndexed.GetHeightIndex(); + const unsigned int wIndex = dataLayoutIndexed.GetWidthIndex(); + + const unsigned int batches = inputShape[0]; + const unsigned int channels = inputShape[cIndex]; + + const unsigned int wInput = inputShape[wIndex]; + const unsigned int hInput = inputShape[hIndex]; + + const unsigned int wStridedInput = 1u + descriptor.m_StrideX * (wInput - 1); + const unsigned int hStridedInput = 1u + descriptor.m_StrideY * (hInput - 1); + + TensorData stridedInput; + stridedInput.data = std::vector<float>(batches * channels * wStridedInput * hStridedInput, 0.0f); + stridedInput.shape = TensorShape(4); + + stridedInput.shape[0] = batches; + stridedInput.shape[cIndex] = channels; + stridedInput.shape[hIndex] = hStridedInput; + stridedInput.shape[wIndex] = wStridedInput; + + // expand input data with strides + for (unsigned int batchIdx = 0u; batchIdx < batches; ++batchIdx) + { + for (unsigned int cInput = 0u; cInput < channels; ++cInput) + { + for (unsigned int yInput = 0u, yStrided = 0u; + yInput < hInput && yStrided < hStridedInput; + ++yInput, yStrided += descriptor.m_StrideY) + { + for (unsigned int xInput = 0u, xStrided = 0u; + xInput < wInput && xStrided < wStridedInput; + ++xInput, xStrided += descriptor.m_StrideX) + { + unsigned int inputIdx = + dataLayoutIndexed.GetIndex(inputShape, batchIdx, cInput, yInput, xInput); + unsigned int stridedInputIdx = + dataLayoutIndexed.GetIndex(stridedInput.shape, batchIdx, cInput, yStrided, xStrided); + + inputDecoder[inputIdx]; + stridedInput.data[stridedInputIdx] = inputDecoder.Get(); + } + } + } + } + + return stridedInput; +} + +TensorData SetUpEmptyPaddedOutput(const TensorShape& outputShape, + const TransposeConvolution2dDescriptor& descriptor, + const DataLayoutIndexed& dataLayoutIndexed) +{ + const unsigned int cIndex = dataLayoutIndexed.GetChannelsIndex(); + const unsigned int hIndex = dataLayoutIndexed.GetHeightIndex(); + const unsigned int wIndex = dataLayoutIndexed.GetWidthIndex(); + + const unsigned int batches = outputShape[0]; + const unsigned int channels = outputShape[cIndex]; + + const unsigned int wOutput = outputShape[wIndex]; + const unsigned int hOutput = outputShape[hIndex]; + + const unsigned int wPaddedOutput = wOutput + descriptor.m_PadLeft + descriptor.m_PadRight; + const unsigned int hPaddedOutput = hOutput + descriptor.m_PadTop + descriptor.m_PadBottom; + + TensorData paddedOutput; + paddedOutput.data = std::vector<float>(batches * channels * wPaddedOutput * hPaddedOutput, 0.0f); + paddedOutput.shape = TensorShape(4); + + paddedOutput.shape[0] = batches; + paddedOutput.shape[cIndex] = channels; + paddedOutput.shape[hIndex] = hPaddedOutput; + paddedOutput.shape[wIndex] = wPaddedOutput; + + return paddedOutput; +} + +void Deconvolve(const TensorData& stridedInput, + TensorData& paddedOutput, + const TensorShape& weightsShape, + Decoder<float>& weightsDecoder, + const DataLayoutIndexed& dataLayoutIndexed) +{ + const unsigned int cIndex = dataLayoutIndexed.GetChannelsIndex(); + const unsigned int hIndex = dataLayoutIndexed.GetHeightIndex(); + const unsigned int wIndex = dataLayoutIndexed.GetWidthIndex(); + + const unsigned int batches = stridedInput.shape[0]; + const unsigned int channels = stridedInput.shape[cIndex]; + + const unsigned int wKernel = weightsShape[wIndex]; + const unsigned int hKernel = weightsShape[hIndex]; + + const unsigned int wStridedInput = stridedInput.shape[wIndex]; + const unsigned int hStridedInput = stridedInput.shape[hIndex]; + + // loop through all input elements + for (unsigned int batchIdx = 0u; batchIdx < batches; ++batchIdx) + { + for (unsigned int cInput = 0u; cInput < channels; ++cInput) + { + for (unsigned int yInput = 0u; yInput < hStridedInput; ++yInput) + { + for (unsigned int xInput = 0u; xInput < wStridedInput; ++xInput) + { + // obtain input value + unsigned int inputIdx = + dataLayoutIndexed.GetIndex(stridedInput.shape, batchIdx, cInput, yInput, xInput); + float inputValue = stridedInput.data[inputIdx]; + + // loop through kernel + for (unsigned int yKernel = 0u; yKernel < hKernel; ++yKernel) + { + for (unsigned int xKernel = 0; xKernel < wKernel; ++xKernel) + { + unsigned int kernelIdx = + dataLayoutIndexed.GetIndex(weightsShape, batchIdx, cInput, yKernel, xKernel); + + weightsDecoder[kernelIdx]; + float kernelValue = weightsDecoder.Get(); + + unsigned int xOutput = xInput + xKernel; + unsigned int yOutput = yInput + yKernel; + + // compute output increment + float outputValue = inputValue * kernelValue; + + unsigned int outputIdx = dataLayoutIndexed.GetIndex(paddedOutput.shape, + batchIdx, + cInput, + yOutput, + xOutput); + + // set output value + paddedOutput.data[outputIdx] += outputValue; + } + } + } + } + } + } +} + +void TransposeConvolution2dImpl(const TransposeConvolution2dDescriptor& descriptor, + const TensorShape& inputShape, + Decoder<float>& inputDecoder, + const TensorShape& outputShape, + Encoder<float>& outputEncoder, + const TensorShape& weightsShape, + Decoder<float>& weightsDecoder, + Decoder<float>* biasesDecoder) +{ + if (descriptor.m_BiasEnabled && !biasesDecoder) + { + throw InvalidArgumentException("Biases enabled but no bias data provided"); + } + + const DataLayoutIndexed dataLayoutIndexed(descriptor.m_DataLayout); + + const unsigned int cIndex = dataLayoutIndexed.GetChannelsIndex(); + const unsigned int hIndex = dataLayoutIndexed.GetHeightIndex(); + const unsigned int wIndex = dataLayoutIndexed.GetWidthIndex(); + + const unsigned int numBatches = inputShape[0]; + const unsigned int numChannels = inputShape[cIndex]; + + // set up temporary strided input + TensorData stridedInput = SetUpStridedInput(inputShape, inputDecoder, descriptor, dataLayoutIndexed); + + // set up temporary (empty) padded output + TensorData paddedOutput = SetUpEmptyPaddedOutput(outputShape, descriptor, dataLayoutIndexed); + + // run deconvolution (without biases) on strided input to produce padded output + Deconvolve(stridedInput, paddedOutput, weightsShape, weightsDecoder, dataLayoutIndexed); + + const unsigned int wPaddedOutput = paddedOutput.shape[wIndex]; + const unsigned int hPaddedOutput = paddedOutput.shape[hIndex]; + + // remove padding and apply bias (if enabled) + for (unsigned int batchIdx = 0u; batchIdx < numBatches; ++batchIdx) + { + for (unsigned int cOutput = 0u; cOutput < numChannels; ++cOutput) + { + // update bias decoder iterator + if (descriptor.m_BiasEnabled) + { + (*biasesDecoder)[cOutput]; + } + + for (unsigned int yPaddedOutput = descriptor.m_PadTop; + yPaddedOutput < (hPaddedOutput - descriptor.m_PadBottom); + ++yPaddedOutput) + { + for (unsigned int xPaddedOutput = descriptor.m_PadLeft; + xPaddedOutput < (wPaddedOutput - descriptor.m_PadRight); + ++xPaddedOutput) + { + unsigned int xOutput = xPaddedOutput - descriptor.m_PadLeft; + unsigned int yOutput = yPaddedOutput - descriptor.m_PadTop; + + unsigned int outputIdx = + dataLayoutIndexed.GetIndex(outputShape, batchIdx, cOutput, yOutput, xOutput); + unsigned int paddedOutputIdx = + dataLayoutIndexed.GetIndex(paddedOutput.shape, batchIdx, cOutput, yPaddedOutput, xPaddedOutput); + + // encode (copy) output data + outputEncoder[outputIdx]; + outputEncoder.Set(paddedOutput.data[paddedOutputIdx]); + + // apply bias (if enabled) + if (descriptor.m_BiasEnabled) + { + outputEncoder.Set(outputEncoder.Get() + biasesDecoder->Get()); + } + } + } + } + } +} + +} // namespace armnn
\ No newline at end of file diff --git a/src/backends/reference/workloads/TransposeConvolution2d.hpp b/src/backends/reference/workloads/TransposeConvolution2d.hpp new file mode 100644 index 0000000000..f20f327b38 --- /dev/null +++ b/src/backends/reference/workloads/TransposeConvolution2d.hpp @@ -0,0 +1,26 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "Decoders.hpp" +#include "Encoders.hpp" + +#include <armnn/Descriptors.hpp> +#include <armnn/Tensor.hpp> + +namespace armnn +{ + +void TransposeConvolution2dImpl(const TransposeConvolution2dDescriptor& descriptor, + const TensorShape& inputShape, + Decoder<float>& inputDecoder, + const TensorShape& outputShape, + Encoder<float>& outputEncoder, + const TensorShape& weightsShape, + Decoder<float>& weightsDecoder, + Decoder<float>* biasesDecoder); + +} // namespace armnn
\ No newline at end of file |