From cbb66aa4b7ec93e9a64a1dec5ebc4158056ec061 Mon Sep 17 00:00:00 2001 From: Jim Flynn Date: Wed, 15 May 2019 13:03:54 +0100 Subject: IVGCVSW-2972 Support QSymm16 for Merger Change-Id: If2289b2d1fc20f4524fcf4620f01ea3a36d727d2 Signed-off-by: Jim Flynn --- src/backends/backendsCommon/WorkloadData.cpp | 21 ++ src/backends/backendsCommon/test/LayerTests.cpp | 216 +++++++++++++++++---- src/backends/backendsCommon/test/LayerTests.hpp | 8 +- .../backendsCommon/test/WorkloadDataValidation.cpp | 6 +- src/backends/reference/RefLayerSupport.cpp | 26 ++- src/backends/reference/RefWorkloadFactory.cpp | 6 +- src/backends/reference/backend.mk | 3 +- .../reference/test/RefCreateWorkloadTests.cpp | 25 ++- src/backends/reference/test/RefLayerTests.cpp | 1 + src/backends/reference/workloads/CMakeLists.txt | 6 +- src/backends/reference/workloads/Merger.cpp | 49 ++--- src/backends/reference/workloads/Merger.hpp | 6 - .../workloads/RefMergerFloat32Workload.cpp | 21 -- .../workloads/RefMergerFloat32Workload.hpp | 21 -- .../reference/workloads/RefMergerUint8Workload.cpp | 21 -- .../reference/workloads/RefMergerUint8Workload.hpp | 21 -- .../reference/workloads/RefMergerWorkload.cpp | 21 ++ .../reference/workloads/RefMergerWorkload.hpp | 21 ++ src/backends/reference/workloads/RefWorkloads.hpp | 3 +- 19 files changed, 303 insertions(+), 199 deletions(-) delete mode 100644 src/backends/reference/workloads/RefMergerFloat32Workload.cpp delete mode 100644 src/backends/reference/workloads/RefMergerFloat32Workload.hpp delete mode 100644 src/backends/reference/workloads/RefMergerUint8Workload.cpp delete mode 100644 src/backends/reference/workloads/RefMergerUint8Workload.hpp create mode 100644 src/backends/reference/workloads/RefMergerWorkload.cpp create mode 100644 src/backends/reference/workloads/RefMergerWorkload.hpp diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index 58f77d55c5..335e7c5fcd 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -445,6 +445,27 @@ void MergerQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const } } } + + // Check the supported data types + std::vector supportedTypes = + { + DataType::Float32, + DataType::Float16, + DataType::Boolean, + DataType::Signed32, + DataType::QuantisedAsymm8, + DataType::QuantisedSymm16 + }; + + for (unsigned long i = 0; i < workloadInfo.m_InputTensorInfos.size(); ++i) + { + ValidateDataTypes(workloadInfo.m_InputTensorInfos[i], + supportedTypes, + "MergerQueueDescriptor"); + } + ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0], + {workloadInfo.m_InputTensorInfos[0].GetDataType()}, + "MergerQueueDescriptor"); } //--------------------------------------------------------------- diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp index da6a2b22ad..980cd84d7c 100644 --- a/src/backends/backendsCommon/test/LayerTests.cpp +++ b/src/backends/backendsCommon/test/LayerTests.cpp @@ -3601,13 +3601,13 @@ LayerTestResult Concatenation1dTestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo inputTensorInfo({ 3 }, ArmnnType); + armnn::TensorInfo inputTensorInfo({ 3 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(inputTensorInfo, QuantizedVector(qScale, qOffset, { 1.0f, 2.0f, 3.0f })); auto input1 = MakeTensor(inputTensorInfo, QuantizedVector(qScale, qOffset, { 4.0f, 5.0f, 6.0f })); auto input2 = MakeTensor(inputTensorInfo, QuantizedVector(qScale, qOffset, { 7.0f, 8.0f, 9.0f })); - armnn::TensorInfo outputTensorInfo({ 9 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 9 }, ArmnnType, qScale, qOffset); LayerTestResult result(outputTensorInfo); @@ -3645,7 +3645,7 @@ LayerTestResult Concatenation2dTestImpl( const float qScale, const int32_t qOffset) { - armnn::TensorInfo inputTensorInfo({ 2, 3 }, ArmnnType); + armnn::TensorInfo inputTensorInfo({ 2, 3 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(inputTensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0 @@ -3694,7 +3694,7 @@ LayerTestResult Concatenation2dDim0TestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo outputTensorInfo({ 6, 3 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 6, 3 }, ArmnnType, qScale, qOffset); LayerTestResult result = Concatenation2dTestImpl( workloadFactory, memoryManager, outputTensorInfo, 0, qScale, qOffset); @@ -3736,7 +3736,7 @@ LayerTestResult Concatenation2dDim1TestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo outputTensorInfo({ 2, 9 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 2, 9 }, ArmnnType, qScale, qOffset); LayerTestResult result = Concatenation2dTestImpl( workloadFactory, memoryManager, outputTensorInfo, 1, qScale, qOffset); @@ -3766,7 +3766,7 @@ LayerTestResult Concatenation2dDim0DiffInputDimsTestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo input0TensorInfo({ 2, 3 }, ArmnnType); + armnn::TensorInfo input0TensorInfo({ 2, 3 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(input0TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0 1.0f, 2.0f, 3.0f, @@ -3775,7 +3775,7 @@ LayerTestResult Concatenation2dDim0DiffInputDimsTestImpl( 10.0f, 11.0f, 12.0f, })); - armnn::TensorInfo input1TensorInfo({ 3, 3 }, ArmnnType); + armnn::TensorInfo input1TensorInfo({ 3, 3 }, ArmnnType, qScale, qOffset); auto input1 = MakeTensor(input1TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0 4.0f, 5.0f, 6.0f, @@ -3787,13 +3787,13 @@ LayerTestResult Concatenation2dDim0DiffInputDimsTestImpl( 7.0f, 8.0f, 9.0f, })); - armnn::TensorInfo input2TensorInfo({ 1, 3 }, ArmnnType); + armnn::TensorInfo input2TensorInfo({ 1, 3 }, ArmnnType, qScale, qOffset); auto input2 = MakeTensor(input2TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 1 16.0f, 17.0f, 18.0f, })); - armnn::TensorInfo outputTensorInfo({ 6, 3 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 6, 3 }, ArmnnType, qScale, qOffset); LayerTestResult result(outputTensorInfo); std::vector output; @@ -3845,7 +3845,7 @@ LayerTestResult Concatenation2dDim1DiffInputDimsTestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo input0TensorInfo({ 2, 3 }, ArmnnType); + armnn::TensorInfo input0TensorInfo({ 2, 3 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(input0TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0 1.0f, 2.0f, 3.0f, @@ -3854,7 +3854,7 @@ LayerTestResult Concatenation2dDim1DiffInputDimsTestImpl( 10.0f, 11.0f, 12.0f, })); - armnn::TensorInfo input1TensorInfo({ 2, 5 }, ArmnnType); + armnn::TensorInfo input1TensorInfo({ 2, 5 }, ArmnnType, qScale, qOffset); auto input1 = MakeTensor(input1TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, @@ -3863,7 +3863,7 @@ LayerTestResult Concatenation2dDim1DiffInputDimsTestImpl( 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, })); - armnn::TensorInfo input2TensorInfo({ 2, 1 }, ArmnnType); + armnn::TensorInfo input2TensorInfo({ 2, 1 }, ArmnnType, qScale, qOffset); auto input2 = MakeTensor(input2TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0 9.0f, @@ -3872,7 +3872,7 @@ LayerTestResult Concatenation2dDim1DiffInputDimsTestImpl( 18.0f })); - armnn::TensorInfo outputTensorInfo({ 2, 9 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 2, 9 }, ArmnnType, qScale, qOffset); LayerTestResult result(outputTensorInfo); std::vector output; @@ -3915,7 +3915,7 @@ LayerTestResult Concatenation3dTestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo inputTensorInfo({ 2, 3, 2 }, ArmnnType); + armnn::TensorInfo inputTensorInfo({ 2, 3, 2 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(inputTensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0, Channel 0 @@ -4000,7 +4000,7 @@ LayerTestResult Concatenation3dDim0TestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo outputTensorInfo({ 6, 3, 2 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 6, 3, 2 }, ArmnnType, qScale, qOffset); LayerTestResult result = Concatenation3dTestImpl( workloadFactory, memoryManager, outputTensorInfo, 0, true, qScale, qOffset); @@ -4078,7 +4078,7 @@ LayerTestResult Concatenation3dDim1TestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo outputTensorInfo({ 2, 9, 2 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 2, 9, 2 }, ArmnnType, qScale, qOffset); LayerTestResult result = Concatenation3dTestImpl( workloadFactory, memoryManager, outputTensorInfo, 1, true, qScale, qOffset); @@ -4157,7 +4157,7 @@ LayerTestResult Concatenation3dDim2TestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo outputTensorInfo({ 2, 3, 6 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 2, 3, 6 }, ArmnnType, qScale, qOffset); LayerTestResult result = Concatenation3dTestImpl( workloadFactory, memoryManager, outputTensorInfo, 2, useSubtensor, qScale, qOffset); @@ -4352,7 +4352,7 @@ LayerTestResult Concatenation3dDim1DiffInputDimsTestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo input0TensorInfo({ 2, 3, 2 }, ArmnnType); + armnn::TensorInfo input0TensorInfo({ 2, 3, 2 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(input0TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0, Channel 0 1.0f, 2.0f, @@ -4373,7 +4373,7 @@ LayerTestResult Concatenation3dDim1DiffInputDimsTestImpl( 23.0f, 24.0f })); - armnn::TensorInfo input1TensorInfo({ 2, 4, 2 }, ArmnnType); + armnn::TensorInfo input1TensorInfo({ 2, 4, 2 }, ArmnnType, qScale, qOffset); auto input1 = MakeTensor(input1TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0, Channel 0 7.0f, 8.0f, @@ -4400,7 +4400,7 @@ LayerTestResult Concatenation3dDim1DiffInputDimsTestImpl( 15.0f, 16.0f, })); - armnn::TensorInfo input2TensorInfo({ 2, 1, 2 }, ArmnnType); + armnn::TensorInfo input2TensorInfo({ 2, 1, 2 }, ArmnnType, qScale, qOffset); auto input2 = MakeTensor(input2TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0, Channel 0 17.0f, 18.0f, @@ -4409,7 +4409,7 @@ LayerTestResult Concatenation3dDim1DiffInputDimsTestImpl( 31.0f, 32.0f, })); - armnn::TensorInfo outputTensorInfo({ 2, 8, 2 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 2, 8, 2 }, ArmnnType, qScale, qOffset); LayerTestResult result(outputTensorInfo); std::vector output; @@ -4492,7 +4492,7 @@ LayerTestResult Concatenation3dDim2DiffInputDimsTestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo input0TensorInfo({ 2, 3, 2 }, ArmnnType); + armnn::TensorInfo input0TensorInfo({ 2, 3, 2 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(input0TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0, Channel 0 1.0f, 2.0f, @@ -4513,7 +4513,7 @@ LayerTestResult Concatenation3dDim2DiffInputDimsTestImpl( 23.0f, 24.0f })); - armnn::TensorInfo input1TensorInfo({ 2, 3, 1 }, ArmnnType); + armnn::TensorInfo input1TensorInfo({ 2, 3, 1 }, ArmnnType, qScale, qOffset); auto input1 = MakeTensor(input1TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0, Channel 0 7.0f, @@ -4534,7 +4534,7 @@ LayerTestResult Concatenation3dDim2DiffInputDimsTestImpl( 29.0f })); - armnn::TensorInfo input2TensorInfo({ 2, 3, 3 }, ArmnnType); + armnn::TensorInfo input2TensorInfo({ 2, 3, 3 }, ArmnnType, qScale, qOffset); auto input2 = MakeTensor(input2TensorInfo, QuantizedVector(qScale, qOffset, { // Batch 0, Channel 0 13.0f, 14.0f, 50.0f, @@ -4555,7 +4555,7 @@ LayerTestResult Concatenation3dDim2DiffInputDimsTestImpl( 35.0f, 36.0f, 55.0f, })); - armnn::TensorInfo outputTensorInfo({ 2, 3, 6 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 2, 3, 6 }, ArmnnType, qScale, qOffset); LayerTestResult result(outputTensorInfo); std::vector output; @@ -4611,7 +4611,7 @@ LayerTestResult Concatenation4dTestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo inputTensorInfo({ 1, 3, 2, 2 }, ArmnnType); + armnn::TensorInfo inputTensorInfo({ 1, 3, 2, 2 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(inputTensorInfo, QuantizedVector(qScale, qOffset, { 1.0f, 2.0f, @@ -4665,7 +4665,7 @@ LayerTestResult Concatenation4dDim0TestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo outputTensorInfo({ 3, 3, 2, 2 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 3, 3, 2, 2 }, ArmnnType, qScale, qOffset); LayerTestResult result = Concatenation4dTestImpl( workloadFactory, memoryManager, outputTensorInfo, 0, true, qScale, qOffset); @@ -4709,7 +4709,7 @@ LayerTestResult Concatenation4dDim1TestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo outputTensorInfo({ 1, 9, 2, 2 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 1, 9, 2, 2 }, ArmnnType, qScale, qOffset); LayerTestResult result = Concatenation4dTestImpl( workloadFactory, memoryManager, outputTensorInfo, 1, true, qScale, qOffset); @@ -4754,7 +4754,7 @@ LayerTestResult Concatenation4dDim2TestImpl( float qScale, int32_t qOffset) { - armnn::TensorInfo outputTensorInfo({ 1, 3, 6, 2 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 1, 3, 6, 2 }, ArmnnType, qScale, qOffset); LayerTestResult result = Concatenation4dTestImpl( workloadFactory, memoryManager, outputTensorInfo, 2, true, qScale, qOffset); @@ -4800,7 +4800,7 @@ LayerTestResult Concatenation4dDim3TestImpl( int32_t qOffset, bool useSubtensor) { - armnn::TensorInfo outputTensorInfo({ 1, 3, 2, 6 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 1, 3, 2, 6 }, ArmnnType, qScale, qOffset); LayerTestResult result = Concatenation4dTestImpl( workloadFactory, memoryManager, outputTensorInfo, 3, useSubtensor, qScale, qOffset); @@ -4848,7 +4848,7 @@ LayerTestResult Concatenation4dDiffShapeDim0TestImpl( int32_t qOffset) { unsigned int dimension = 0; - armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType); + armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(inputTensorInfo0, QuantizedVector(qScale, qOffset, { 1.0f, 2.0f, @@ -4859,7 +4859,7 @@ LayerTestResult Concatenation4dDiffShapeDim0TestImpl( 11.0f, 12.0f })); - armnn::TensorInfo inputTensorInfo1({ 2, 3, 2, 2 }, ArmnnType); + armnn::TensorInfo inputTensorInfo1({ 2, 3, 2, 2 }, ArmnnType, qScale, qOffset); auto input1 = MakeTensor(inputTensorInfo1, QuantizedVector(qScale, qOffset, { 11.0f, 12.0f, @@ -4878,7 +4878,7 @@ LayerTestResult Concatenation4dDiffShapeDim0TestImpl( })); - armnn::TensorInfo outputTensorInfo({ 3, 3, 2, 2 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 3, 3, 2, 2 }, ArmnnType, qScale, qOffset); LayerTestResult result(outputTensorInfo); @@ -4936,7 +4936,7 @@ LayerTestResult Concatenation4dDiffShapeDim1TestImpl( int32_t qOffset) { unsigned int dimension = 1; - armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType); + armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(inputTensorInfo0, QuantizedVector(qScale, qOffset, { 1.0f, 2.0f, @@ -4947,7 +4947,7 @@ LayerTestResult Concatenation4dDiffShapeDim1TestImpl( 11.0f, 12.0f })); - armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, ArmnnType); + armnn::TensorInfo inputTensorInfo1({ 1, 2, 2, 2 }, ArmnnType, qScale, qOffset); auto input1 = MakeTensor(inputTensorInfo1, QuantizedVector(qScale, qOffset, { 11.0f, 12.0f, @@ -4957,7 +4957,7 @@ LayerTestResult Concatenation4dDiffShapeDim1TestImpl( })); - armnn::TensorInfo outputTensorInfo({ 1, 5, 2, 2 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 1, 5, 2, 2 }, ArmnnType, qScale, qOffset); LayerTestResult result(outputTensorInfo); @@ -5005,7 +5005,7 @@ LayerTestResult Concatenation4dDiffShapeDim2TestImpl( int32_t qOffset) { unsigned int dimension = 2; - armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType); + armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(inputTensorInfo0, QuantizedVector(qScale, qOffset, { 1.0f, 2.0f, @@ -5016,7 +5016,7 @@ LayerTestResult Concatenation4dDiffShapeDim2TestImpl( 11.0f, 12.0f })); - armnn::TensorInfo inputTensorInfo1({ 1, 3, 3, 2 }, ArmnnType); + armnn::TensorInfo inputTensorInfo1({ 1, 3, 3, 2 }, ArmnnType, qScale, qOffset); auto input1 = MakeTensor(inputTensorInfo1, QuantizedVector(qScale, qOffset, { 11.0f, 12.0f, @@ -5030,7 +5030,7 @@ LayerTestResult Concatenation4dDiffShapeDim2TestImpl( 27.0f, 28.0f })); - armnn::TensorInfo outputTensorInfo({ 1, 3, 5, 2 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 1, 3, 5, 2 }, ArmnnType, qScale, qOffset); LayerTestResult result(outputTensorInfo); @@ -5086,7 +5086,7 @@ LayerTestResult Concatenation4dDiffShapeDim3TestImpl( bool useSubtensor) { unsigned int dimension = 3; - armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType); + armnn::TensorInfo inputTensorInfo0({ 1, 3, 2, 2 }, ArmnnType, qScale, qOffset); auto input0 = MakeTensor(inputTensorInfo0, QuantizedVector(qScale, qOffset, { 1.0f, 2.0f, @@ -5097,7 +5097,7 @@ LayerTestResult Concatenation4dDiffShapeDim3TestImpl( 11.0f, 12.0f })); - armnn::TensorInfo inputTensorInfo1({ 1, 3, 2, 3 }, ArmnnType); + armnn::TensorInfo inputTensorInfo1({ 1, 3, 2, 3 }, ArmnnType, qScale, qOffset); auto input1 = MakeTensor(inputTensorInfo1, QuantizedVector(qScale, qOffset, { 11.0f, 12.0f, 13.0f, @@ -5110,7 +5110,7 @@ LayerTestResult Concatenation4dDiffShapeDim3TestImpl( 26.0f, 27.0f, 28.0f })); - armnn::TensorInfo outputTensorInfo({ 1, 3, 2, 5 }, ArmnnType); + armnn::TensorInfo outputTensorInfo({ 1, 3, 2, 5 }, ArmnnType, qScale, qOffset); LayerTestResult result(outputTensorInfo); @@ -6757,6 +6757,138 @@ LayerTestResult MergerUint8Test( return ret; } +LayerTestResult MergerUint16Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager) +{ + unsigned int outputWidth = 3; + unsigned int outputHeight = 6; + unsigned int outputChannels = 3; + + unsigned int inputWidth1 = 3; + unsigned int inputHeight1 = 6; + unsigned int inputChannels1 = 2; + + unsigned int inputWidth2 = 3; + unsigned int inputHeight2 = 6; + unsigned int inputChannels2 = 1; + + // Defines the tensor descriptors. + armnn::TensorInfo outputTensorInfo({ outputChannels, outputHeight, outputWidth }, armnn::DataType::QuantisedSymm16); + armnn::TensorInfo inputTensorInfo1({ inputChannels1, inputHeight1, inputWidth1 }, armnn::DataType::QuantisedSymm16); + armnn::TensorInfo inputTensorInfo2({ inputChannels2, inputHeight2, inputWidth2 }, armnn::DataType::QuantisedSymm16); + + // Arbitrary scale and offsets. They don't really matter as the merger operator doesn't dequantize/quantize them. + const float scale = 0.13497836f; + const int32_t offset = -7; + + outputTensorInfo.SetQuantizationScale(scale); + outputTensorInfo.SetQuantizationOffset(offset); + inputTensorInfo1.SetQuantizationScale(scale); + inputTensorInfo1.SetQuantizationOffset(offset); + inputTensorInfo2.SetQuantizationScale(scale); + inputTensorInfo2.SetQuantizationOffset(offset); + + LayerTestResult ret(outputTensorInfo); + + ret.outputExpected = MakeTensor(outputTensorInfo, std::vector( + { + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + 13, 14, 15, + 16, 17, 18, + + 19, 20, 21, + 22, 23, 24, + 25, 26, 27, + 28, 29, 30, + 31, 32, 33, + 34, 35, 36, + + 37, 38, 39, + 40, 41, 42, + 43, 44, 45, + 46, 47, 48, + 49, 50, 51, + 52, 53, 54, + })); + + auto input1 = MakeTensor(inputTensorInfo1, std::vector( + { + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + 13, 14, 15, + 16, 17, 18, + + 19, 20, 21, + 22, 23, 24, + 25, 26, 27, + 28, 29, 30, + 31, 32, 33, + 34, 35, 36, + })); + + auto input2 = MakeTensor(inputTensorInfo2, std::vector( + { + 37, 38, 39, + 40, 41, 42, + 43, 44, 45, + 46, 47, 48, + 49, 50, 51, + 52, 53, 54, + })); + + std::vector wOrigin1 = { 0, 0, 0 }; //Extent of the window is defined by size of input[0]. + armnn::MergerQueueDescriptor::ViewOrigin window1(wOrigin1); + + std::vector wOrigin2 = { 2, 0, 0 }; //Extent of the window is defined by size of input[1]. + armnn::MergerQueueDescriptor::ViewOrigin window2(wOrigin2); + + + std::unique_ptr outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo); + + bool subTensorsSupported = workloadFactory.SupportsSubTensors(); + + std::unique_ptr inputHandle1 = + subTensorsSupported ? + workloadFactory.CreateSubTensorHandle(*outputHandle, inputTensorInfo1.GetShape(), wOrigin1.data()) : + workloadFactory.CreateTensorHandle(inputTensorInfo1); + + std::unique_ptr inputHandle2 = + subTensorsSupported ? + workloadFactory.CreateSubTensorHandle(*outputHandle, inputTensorInfo2.GetShape(), wOrigin2.data()) : + workloadFactory.CreateTensorHandle(inputTensorInfo2); + + + armnn::MergerQueueDescriptor data; + armnn::WorkloadInfo info; + AddInputToWorkload(data, info, inputTensorInfo1, inputHandle1.get()); + AddInputToWorkload(data, info, inputTensorInfo2, inputHandle2.get()); + AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get()); + + data.m_ViewOrigins.push_back(window1); + data.m_ViewOrigins.push_back(window2); + + std::unique_ptr workload = workloadFactory.CreateMerger(data, info); + + inputHandle1->Allocate(); + inputHandle2->Allocate(); + outputHandle->Allocate(); + + CopyDataToITensorHandle(inputHandle1.get(), &input1[0][0][0]); + CopyDataToITensorHandle(inputHandle2.get(), &input2[0][0][0]); + + workload->PostAllocationConfigure(); + workload->Execute(); + + CopyDataFromITensorHandle(&ret.output[0][0][0], outputHandle.get()); + + return ret; +} namespace { diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp index 84001aa7ea..60195cd534 100644 --- a/src/backends/backendsCommon/test/LayerTests.hpp +++ b/src/backends/backendsCommon/test/LayerTests.hpp @@ -806,9 +806,13 @@ LayerTestResult MergerUint8Test( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); +LayerTestResult MergerUint16Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + LayerTestResult MergerUint8DifferentQParamsTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); LayerTestResult AdditionUint8Test( armnn::IWorkloadFactory& workloadFactory, diff --git a/src/backends/backendsCommon/test/WorkloadDataValidation.cpp b/src/backends/backendsCommon/test/WorkloadDataValidation.cpp index d37cc74c66..962701f051 100644 --- a/src/backends/backendsCommon/test/WorkloadDataValidation.cpp +++ b/src/backends/backendsCommon/test/WorkloadDataValidation.cpp @@ -269,14 +269,14 @@ BOOST_AUTO_TEST_CASE(MergerQueueDescriptor_Validate_WrongWindow) BOOST_TEST_INFO("Invalid argument exception is expected, because merge window dimensionality does not " "match input."); - BOOST_CHECK_THROW(RefMergerFloat32Workload(invalidData, invalidInfo), armnn::InvalidArgumentException); + BOOST_CHECK_THROW(RefMergerWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException); // Invalid, since window extends past the boundary of output tensor. std::vector wOrigin3 = {0, 0, 15, 0}; armnn::MergerQueueDescriptor::ViewOrigin window3(wOrigin3); invalidData.m_ViewOrigins[0] = window3; BOOST_TEST_INFO("Invalid argument exception is expected (wOrigin3[2]+ inputHeight > outputHeight"); - BOOST_CHECK_THROW(RefMergerFloat32Workload(invalidData, invalidInfo), armnn::InvalidArgumentException); + BOOST_CHECK_THROW(RefMergerWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException); std::vector wOrigin4 = {0, 0, 0, 0}; @@ -288,7 +288,7 @@ BOOST_AUTO_TEST_CASE(MergerQueueDescriptor_Validate_WrongWindow) invalidData.m_ViewOrigins.push_back(window5); BOOST_TEST_INFO("Invalid exception due to number of merge windows not matching number of inputs."); - BOOST_CHECK_THROW(RefMergerFloat32Workload(invalidData, invalidInfo), armnn::InvalidArgumentException); + BOOST_CHECK_THROW(RefMergerWorkload(invalidData, invalidInfo), armnn::InvalidArgumentException); } BOOST_AUTO_TEST_CASE(AdditionQueueDescriptor_Validate_InputNumbers) diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp index f79c152139..858bd878ae 100644 --- a/src/backends/reference/RefLayerSupport.cpp +++ b/src/backends/reference/RefLayerSupport.cpp @@ -729,11 +729,27 @@ bool RefLayerSupport::IsMergerSupported(const std::vector inp Optional reasonIfUnsupported) const { ignore_unused(descriptor); - ignore_unused(output); - return IsSupportedForDataTypeRef(reasonIfUnsupported, - inputs[0]->GetDataType(), - &TrueFunc<>, - &TrueFunc<>); + + bool supported = true; + std::array supportedTypes = + { + DataType::Float32, + DataType::QuantisedAsymm8, + DataType::QuantisedSymm16 + }; + + supported &= CheckSupportRule(TypeAnyOf(output, supportedTypes), reasonIfUnsupported, + "Reference concatenation: output type not supported"); + for (const TensorInfo* input : inputs) + { + supported &= CheckSupportRule(TypeAnyOf(*input, supportedTypes), reasonIfUnsupported, + "Reference concatenation: input type not supported"); + + supported &= CheckSupportRule(TypesAreEqual(*input, output), reasonIfUnsupported, + "Reference concatenation: input and output types mismatched."); + } + + return supported; } bool RefLayerSupport::IsMemCopySupported(const TensorInfo &input, diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp index 6603aaf27b..5c90a43c37 100644 --- a/src/backends/reference/RefWorkloadFactory.cpp +++ b/src/backends/reference/RefWorkloadFactory.cpp @@ -135,7 +135,11 @@ std::unique_ptr RefWorkloadFactory::CreateSplitter(const SplitterQueu std::unique_ptr RefWorkloadFactory::CreateMerger(const MergerQueueDescriptor& descriptor, const WorkloadInfo& info) const { - return MakeWorkload(descriptor, info); + if (IsFloat16(info)) + { + return MakeWorkload(descriptor, info); + } + return std::make_unique(descriptor, info); } std::unique_ptr RefWorkloadFactory::CreateFullyConnected( diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk index 5034c0fe9e..a297529d60 100644 --- a/src/backends/reference/backend.mk +++ b/src/backends/reference/backend.mk @@ -50,8 +50,7 @@ BACKEND_SOURCES := \ workloads/RefLstmWorkload.cpp \ workloads/RefMeanFloat32Workload.cpp \ workloads/RefMeanUint8Workload.cpp \ - workloads/RefMergerFloat32Workload.cpp \ - workloads/RefMergerUint8Workload.cpp \ + workloads/RefMergerWorkload.cpp \ workloads/RefNormalizationFloat32Workload.cpp \ workloads/RefPadWorkload.cpp \ workloads/RefPermuteWorkload.cpp \ diff --git a/src/backends/reference/test/RefCreateWorkloadTests.cpp b/src/backends/reference/test/RefCreateWorkloadTests.cpp index 5da1f94f6e..788b6559f6 100644 --- a/src/backends/reference/test/RefCreateWorkloadTests.cpp +++ b/src/backends/reference/test/RefCreateWorkloadTests.cpp @@ -479,12 +479,12 @@ static void RefCreateSplitterMergerWorkloadTest() BOOST_AUTO_TEST_CASE(CreateSplitterMergerFloat32) { - RefCreateSplitterMergerWorkloadTest(); + RefCreateSplitterMergerWorkloadTest(); } BOOST_AUTO_TEST_CASE(CreateSplitterMergerUint8) { - RefCreateSplitterMergerWorkloadTest(); + RefCreateSplitterMergerWorkloadTest(); } template @@ -658,42 +658,47 @@ static void RefCreateMergerWorkloadTest(const armnn::TensorShape& outputShape, BOOST_AUTO_TEST_CASE(CreateMergerDim0Float32Workload) { - RefCreateMergerWorkloadTest({ 4, 3, 2, 5 }, 0); + RefCreateMergerWorkloadTest({ 4, 3, 2, 5 }, 0); } BOOST_AUTO_TEST_CASE(CreateMergerDim0Uint8Workload) { - RefCreateMergerWorkloadTest({ 4, 3, 2, 5 }, 0); + RefCreateMergerWorkloadTest({ 4, 3, 2, 5 }, 0); +} + +BOOST_AUTO_TEST_CASE(CreateMergerDim0Uint16Workload) +{ + RefCreateMergerWorkloadTest({ 4, 3, 2, 5 }, 0); } BOOST_AUTO_TEST_CASE(CreateMergerDim1Float32Workload) { - RefCreateMergerWorkloadTest({ 2, 6, 2, 5 }, 1); + RefCreateMergerWorkloadTest({ 2, 6, 2, 5 }, 1); } BOOST_AUTO_TEST_CASE(CreateMergerDim1Uint8Workload) { - RefCreateMergerWorkloadTest({ 2, 6, 2, 5 }, 1); + RefCreateMergerWorkloadTest({ 2, 6, 2, 5 }, 1); } BOOST_AUTO_TEST_CASE(CreateMergerDim2Float32Workload) { - RefCreateMergerWorkloadTest({ 2, 3, 4, 5 }, 2); + RefCreateMergerWorkloadTest({ 2, 3, 4, 5 }, 2); } BOOST_AUTO_TEST_CASE(CreateMergerDim2Uint8Workload) { - RefCreateMergerWorkloadTest({ 2, 3, 4, 5 }, 2); + RefCreateMergerWorkloadTest({ 2, 3, 4, 5 }, 2); } BOOST_AUTO_TEST_CASE(CreateMergerDim3Float32Workload) { - RefCreateMergerWorkloadTest({ 2, 3, 2, 10 }, 3); + RefCreateMergerWorkloadTest({ 2, 3, 2, 10 }, 3); } BOOST_AUTO_TEST_CASE(CreateMergerDim3Uint8Workload) { - RefCreateMergerWorkloadTest({ 2, 3, 2, 10 }, 3); + RefCreateMergerWorkloadTest({ 2, 3, 2, 10 }, 3); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp index 01afff8b02..053de9e14f 100644 --- a/src/backends/reference/test/RefLayerTests.cpp +++ b/src/backends/reference/test/RefLayerTests.cpp @@ -246,6 +246,7 @@ ARMNN_AUTO_TEST_CASE(CopyViaSplitterUint8, CopyViaSplitterUint8Test) ARMNN_AUTO_TEST_CASE(SimpleMerger, MergerTest) ARMNN_AUTO_TEST_CASE(MergerUint8, MergerUint8Test) ARMNN_AUTO_TEST_CASE(MergerUint8DifferentQParams, MergerUint8DifferentQParamsTest) +ARMNN_AUTO_TEST_CASE(MergerUint16, MergerUint16Test) // Add ARMNN_AUTO_TEST_CASE(SimpleAdd, AdditionTest) diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index b1cdef9cf1..8c8aa6ffb5 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -83,10 +83,8 @@ list(APPEND armnnRefBackendWorkloads_sources RefL2NormalizationFloat32Workload.hpp RefLstmWorkload.cpp RefLstmWorkload.hpp - RefMergerFloat32Workload.cpp - RefMergerFloat32Workload.hpp - RefMergerUint8Workload.cpp - RefMergerUint8Workload.hpp + RefMergerWorkload.cpp + RefMergerWorkload.hpp RefNormalizationFloat32Workload.cpp RefNormalizationFloat32Workload.hpp RefPadWorkload.cpp diff --git a/src/backends/reference/workloads/Merger.cpp b/src/backends/reference/workloads/Merger.cpp index 8877ee2284..e0b70ee5cb 100644 --- a/src/backends/reference/workloads/Merger.cpp +++ b/src/backends/reference/workloads/Merger.cpp @@ -5,43 +5,19 @@ #include "Merger.hpp" #include "RefWorkloadUtils.hpp" +#include "Decoders.hpp" +#include "Encoders.hpp" namespace armnn { -template <> -void CopyValue(const float& source, const TensorInfo& sourceInfo, float& dest, const TensorInfo& destInfo) -{ - dest = source; -} - -template <> -void CopyValue(const uint8_t& source, const TensorInfo& sourceInfo, uint8_t& dest, const TensorInfo& destInfo) -{ - if (sourceInfo.GetQuantizationScale() != destInfo.GetQuantizationScale() || - sourceInfo.GetQuantizationOffset() != destInfo.GetQuantizationOffset()) - { - // Dequantize value according to sourceInfo params - float dequantizedValue = armnn::Dequantize(source, - sourceInfo.GetQuantizationScale(), - sourceInfo.GetQuantizationOffset()); - - // Quantize again according to destInfo paramns - dest = armnn::Quantize(dequantizedValue, - destInfo.GetQuantizationScale(), - destInfo.GetQuantizationOffset()); - } - else - { - dest = source; - } -} - -template void Merger(const MergerQueueDescriptor& data) { const TensorInfo& outputInfo0 = GetTensorInfo(data.m_Outputs[0]); + std::unique_ptr> encoderPtr = MakeEncoder(outputInfo0, data.m_Outputs[0]->Map()); + Encoder& encoder = *encoderPtr; + for (unsigned int index = 0 ; index < outputInfo0.GetNumElements(); ++index) { unsigned int indices[MaxNumOfTensorDimensions] = { 0 }; @@ -80,6 +56,9 @@ void Merger(const MergerQueueDescriptor& data) if (insideView) { + std::unique_ptr> decoderPtr = + MakeDecoder(inputInfo, data.m_Inputs[viewIdx]->Map()); + Decoder& decoder = *decoderPtr; unsigned int inIndex = 0; unsigned int dimensionStride = 1; @@ -88,11 +67,8 @@ void Merger(const MergerQueueDescriptor& data) inIndex += dimensionStride * (indices[i] - view.m_Origin[i]); dimensionStride *= inputInfo.GetShape()[i]; } - - CopyValue((GetInputTensorData(viewIdx, data))[inIndex], - GetTensorInfo(data.m_Inputs[viewIdx]), - (GetOutputTensorData(0, data))[index], - outputInfo0); + decoder += inIndex; + encoder.Set(decoder.Get()); //What should we do if input views overlap on the output tensor? //We could error, take the average, or shm else... @@ -100,11 +76,8 @@ void Merger(const MergerQueueDescriptor& data) break; } } + ++encoder; } } -template void Merger(const MergerQueueDescriptor& data); - -template void Merger(const MergerQueueDescriptor& data); - } //namespace armnn diff --git a/src/backends/reference/workloads/Merger.hpp b/src/backends/reference/workloads/Merger.hpp index ba3b99b6e2..eaa154d25a 100644 --- a/src/backends/reference/workloads/Merger.hpp +++ b/src/backends/reference/workloads/Merger.hpp @@ -10,11 +10,5 @@ namespace armnn { - -template -void CopyValue(const DataType& source, const TensorInfo& sourceInfo, DataType& dest, const TensorInfo& destInfo); - -template void Merger(const MergerQueueDescriptor& data); - } //namespace armnn diff --git a/src/backends/reference/workloads/RefMergerFloat32Workload.cpp b/src/backends/reference/workloads/RefMergerFloat32Workload.cpp deleted file mode 100644 index b1f8a32ee7..0000000000 --- a/src/backends/reference/workloads/RefMergerFloat32Workload.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#include "RefMergerFloat32Workload.hpp" - -#include "Merger.hpp" - -#include "Profiling.hpp" - -namespace armnn -{ - -void RefMergerFloat32Workload::Execute() const -{ - ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefMergerFloat32Workload_Execute"); - Merger(m_Data); -} - -} //namespace armnn diff --git a/src/backends/reference/workloads/RefMergerFloat32Workload.hpp b/src/backends/reference/workloads/RefMergerFloat32Workload.hpp deleted file mode 100644 index 8d7b2706f3..0000000000 --- a/src/backends/reference/workloads/RefMergerFloat32Workload.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#pragma once - -#include -#include - -namespace armnn -{ - -class RefMergerFloat32Workload : public Float32Workload -{ -public: - using Float32Workload::Float32Workload; - virtual void Execute() const override; -}; - -} //namespace armnn diff --git a/src/backends/reference/workloads/RefMergerUint8Workload.cpp b/src/backends/reference/workloads/RefMergerUint8Workload.cpp deleted file mode 100644 index 47ce1cf731..0000000000 --- a/src/backends/reference/workloads/RefMergerUint8Workload.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#include "RefMergerUint8Workload.hpp" - -#include "Merger.hpp" - -#include "Profiling.hpp" - -namespace armnn -{ - -void RefMergerUint8Workload::Execute() const -{ - ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefMergerUint8Workload_Execute"); - Merger(m_Data); -} - -} //namespace armnn diff --git a/src/backends/reference/workloads/RefMergerUint8Workload.hpp b/src/backends/reference/workloads/RefMergerUint8Workload.hpp deleted file mode 100644 index df23af093f..0000000000 --- a/src/backends/reference/workloads/RefMergerUint8Workload.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#pragma once - -#include -#include - -namespace armnn -{ - -class RefMergerUint8Workload : public Uint8Workload -{ -public: - using Uint8Workload::Uint8Workload; - virtual void Execute() const override; -}; - -} //namespace armnn diff --git a/src/backends/reference/workloads/RefMergerWorkload.cpp b/src/backends/reference/workloads/RefMergerWorkload.cpp new file mode 100644 index 0000000000..5b42e828b9 --- /dev/null +++ b/src/backends/reference/workloads/RefMergerWorkload.cpp @@ -0,0 +1,21 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RefMergerWorkload.hpp" + +#include "Merger.hpp" + +#include "Profiling.hpp" + +namespace armnn +{ + +void RefMergerWorkload::Execute() const +{ + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefMergerWorkload_Execute"); + Merger(m_Data); +} + +} //namespace armnn diff --git a/src/backends/reference/workloads/RefMergerWorkload.hpp b/src/backends/reference/workloads/RefMergerWorkload.hpp new file mode 100644 index 0000000000..138838a1af --- /dev/null +++ b/src/backends/reference/workloads/RefMergerWorkload.hpp @@ -0,0 +1,21 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include + +namespace armnn +{ + +class RefMergerWorkload : 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 8ffd3485ae..9a2eb0a8af 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -16,11 +16,10 @@ #include "RefActivationWorkload.hpp" #include "RefPooling2dFloat32Workload.hpp" #include "RefWorkloadUtils.hpp" -#include "RefMergerUint8Workload.hpp" +#include "RefMergerWorkload.hpp" #include "RefFullyConnectedFloat32Workload.hpp" #include "RefGatherWorkload.hpp" #include "Softmax.hpp" -#include "RefMergerFloat32Workload.hpp" #include "TensorBufferArrayView.hpp" #include "RefBatchNormalizationFloat32Workload.hpp" #include "Splitter.hpp" -- cgit v1.2.1