diff options
author | Ferran Balaguer <ferran.balaguer@arm.com> | 2019-06-10 10:29:54 +0100 |
---|---|---|
committer | Matteo Martincigh <matteo.martincigh@arm.com> | 2019-06-14 13:03:28 +0000 |
commit | d73d14fd77fe1405a33b3ecf3c56e1ac65647ff7 (patch) | |
tree | a8f51e7d7c652653dc13c8c978aca347463c03a0 /src | |
parent | 0421e7f22d9ccd5d810b345731b766a96c841492 (diff) | |
download | armnn-d73d14fd77fe1405a33b3ecf3c56e1ac65647ff7.tar.gz |
IVGCVSW-3229 Refactor L2Normalization workload to support multiple data types
Signed-off-by: Ferran Balaguer <ferran.balaguer@arm.com>
Change-Id: I848056aad4b172d432664633eea000843d85a85d
Diffstat (limited to 'src')
-rw-r--r-- | src/backends/backendsCommon/WorkloadData.cpp | 26 | ||||
-rw-r--r-- | src/backends/backendsCommon/test/LayerTests.cpp | 302 | ||||
-rw-r--r-- | src/backends/backendsCommon/test/LayerTests.hpp | 20 | ||||
-rw-r--r-- | src/backends/reference/RefLayerSupport.cpp | 28 | ||||
-rw-r--r-- | src/backends/reference/RefWorkloadFactory.cpp | 33 | ||||
-rw-r--r-- | src/backends/reference/backend.mk | 2 | ||||
-rw-r--r-- | src/backends/reference/test/RefCreateWorkloadTests.cpp | 14 | ||||
-rw-r--r-- | src/backends/reference/test/RefLayerTests.cpp | 8 | ||||
-rw-r--r-- | src/backends/reference/workloads/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/backends/reference/workloads/RefL2NormalizationFloat32Workload.cpp | 69 | ||||
-rw-r--r-- | src/backends/reference/workloads/RefL2NormalizationWorkload.cpp | 75 | ||||
-rw-r--r-- | src/backends/reference/workloads/RefL2NormalizationWorkload.hpp (renamed from src/backends/reference/workloads/RefL2NormalizationFloat32Workload.hpp) | 7 | ||||
-rw-r--r-- | src/backends/reference/workloads/RefWorkloads.hpp | 2 |
13 files changed, 379 insertions, 211 deletions
diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index 20e125293a..098e8575b1 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -948,16 +948,32 @@ void FakeQuantizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) void L2NormalizationQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const { - ValidateNumInputs(workloadInfo, "L2NormalizationQueueDescriptor", 1); - ValidateNumOutputs(workloadInfo, "L2NormalizationQueueDescriptor", 1); + const std::string& descriptorName = "L2NormalizationQueueDescriptor"; - ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], "L2NormalizationQueueDescriptor", 4, "input"); - ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], "L2NormalizationQueueDescriptor", 4, "output"); + ValidateNumInputs(workloadInfo, descriptorName, 1); + ValidateNumOutputs(workloadInfo, descriptorName, 1); + + ValidateTensorNumDimensions(workloadInfo.m_InputTensorInfos[0], descriptorName, 4, "input"); + ValidateTensorNumDimensions(workloadInfo.m_OutputTensorInfos[0], descriptorName, 4, "output"); ValidateTensorShapesMatch(workloadInfo.m_InputTensorInfos[0], workloadInfo.m_OutputTensorInfos[0], - "L2NormalizationQueueDescriptor", + descriptorName, "input", "output"); + + // Check the supported data types + std::vector<DataType> supportedTypes = + { + DataType::Float32, + DataType::Float16, + DataType::QuantisedAsymm8, + DataType::QuantisedSymm16 + }; + + ValidateDataTypes(workloadInfo.m_InputTensorInfos[0], supportedTypes, descriptorName); + ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0], supportedTypes, descriptorName); + ValidateDataTypes(workloadInfo.m_OutputTensorInfos[0], + {workloadInfo.m_InputTensorInfos[0].GetDataType()}, descriptorName); } void ConstantQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp index af426a470b..3216ac68ef 100644 --- a/src/backends/backendsCommon/test/LayerTests.cpp +++ b/src/backends/backendsCommon/test/LayerTests.cpp @@ -5283,17 +5283,19 @@ LayerTestResult<float, 2> FakeQuantizationTest( namespace { - -LayerTestResult<float, 4> L2NormalizationTestImpl( +template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>> +LayerTestResult<T, 4> L2NormalizationTestImpl( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + float qScale, + int32_t qOffset, const armnn::TensorShape& inputOutputTensorShape, const std::vector<float>& inputValues, const std::vector<float>& expectedOutputValues, const armnn::DataLayout layout) { - const armnn::TensorInfo inputTensorInfo(inputOutputTensorShape, armnn::DataType::Float32); - const armnn::TensorInfo outputTensorInfo(inputOutputTensorShape, armnn::DataType::Float32); + const armnn::TensorInfo inputTensorInfo(inputOutputTensorShape, ArmnnType, qScale, qOffset); + const armnn::TensorInfo outputTensorInfo(inputOutputTensorShape, ArmnnType, qScale, qOffset); // at this point if we require it permute the input data const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 }; @@ -5305,18 +5307,25 @@ LayerTestResult<float, 4> L2NormalizationTestImpl( inputData = tmp; } - auto inputTensor = MakeTensor<float, 4>(inputTensorInfo, std::vector<float>(inputData)); + auto inputTensor = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>( + inputTensorInfo.GetQuantizationScale(), + inputTensorInfo.GetQuantizationOffset(), + inputData)); - LayerTestResult<float, 4> result(outputTensorInfo); std::vector<float> expectedOutputData = expectedOutputValues; if (layout == armnn::DataLayout::NHWC) { std::vector<float> tmp(expectedOutputData.size()); - armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, - expectedOutputData.data(), tmp.data(), sizeof(float)); + armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, expectedOutputData.data(), tmp.data(), + sizeof(float)); expectedOutputData = tmp; } - result.outputExpected = MakeTensor<float, 4>(inputTensorInfo, std::vector<float>(expectedOutputData)); + + LayerTestResult<T, 4> result(outputTensorInfo); + result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>( + outputTensorInfo.GetQuantizationScale(), + outputTensorInfo.GetQuantizationOffset(), + expectedOutputData)); std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo); std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo); @@ -5786,10 +5795,13 @@ LayerTestResult<float, 4> PadFloat324dTest( return Pad4dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0); } -LayerTestResult<float, 4> L2Normalization1dTest( - armnn::IWorkloadFactory& workloadFactory, - const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, - const armnn::DataLayout layout) +template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>> +LayerTestResult<T, 4> L2Normalization1dTestCommon( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + float qScale, + int32_t qOffset, + const armnn::DataLayout layout) { // Width: 1 // Height: 1 @@ -5806,31 +5818,31 @@ LayerTestResult<float, 4> L2Normalization1dTest( std::vector<float> inputValues { // Batch 0, Channel 0, Height (1) x Width (1) - 1.0f, + 1.0f, // Batch 0, Channel 1, Height (1) x Width (1) - 2.0f, + 2.0f, // Batch 0, Channel 2, Height (1) x Width (1) - 3.0f, + 3.0f, // Batch 0, Channel 3, Height (1) x Width (1) - 4.0f, + 4.0f, // Batch 0, Channel 4, Height (1) x Width (1) - 5.0f, + 5.0f, // Batch 0, Channel 5, Height (1) x Width (1) - 6.0f, + 6.0f, // Batch 0, Channel 6, Height (1) x Width (1) - 7.0f, + 7.0f, // Batch 0, Channel 7, Height (1) x Width (1) - 8.0f, + 8.0f, // Batch 0, Channel 8, Height (1) x Width (1) - 9.0f, + 9.0f, // Batch 0, Channel 9, Height (1) x Width (1) 10.0f @@ -5839,28 +5851,49 @@ LayerTestResult<float, 4> L2Normalization1dTest( std::vector<float> expectedOutputValues { // Batch 0, Channel 0, Height (1) x Width (1) - 1.0f * approxInvL2Norm, - 2.0f * approxInvL2Norm, - 3.0f * approxInvL2Norm, - 4.0f * approxInvL2Norm, - 5.0f * approxInvL2Norm, - 6.0f * approxInvL2Norm, - 7.0f * approxInvL2Norm, - 8.0f * approxInvL2Norm, - 9.0f * approxInvL2Norm, + 1.0f * approxInvL2Norm, + 2.0f * approxInvL2Norm, + 3.0f * approxInvL2Norm, + 4.0f * approxInvL2Norm, + 5.0f * approxInvL2Norm, + 6.0f * approxInvL2Norm, + 7.0f * approxInvL2Norm, + 8.0f * approxInvL2Norm, + 9.0f * approxInvL2Norm, 10.0f * approxInvL2Norm }; - return L2NormalizationTestImpl(workloadFactory, memoryManager, inputOutputShape, - inputValues, expectedOutputValues, layout); + return L2NormalizationTestImpl<ArmnnType>(workloadFactory, memoryManager, qScale, qOffset, inputOutputShape, + inputValues, expectedOutputValues, layout); } -LayerTestResult<float, 4> L2Normalization2dTest( + +LayerTestResult<float, 4> L2Normalization1dTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, const armnn::DataLayout layout) { + return L2Normalization1dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.f, 0, layout); +} + +LayerTestResult<int16_t, 4> L2Normalization1dInt16Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout) +{ + return L2Normalization1dTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 1.f, 0, + layout); +} + +template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>> +LayerTestResult<T, 4> L2Normalization2dTestCommon( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + float qScale, + int32_t qOffset, + const armnn::DataLayout layout) +{ // Width: 5 // Height: 1 // Channels: 2 @@ -5883,29 +5916,49 @@ LayerTestResult<float, 4> L2Normalization2dTest( std::vector<float> expectedOutputValues { // Batch 0, Channel 0, Height (1) x Width (5) - 1.0f * CalcInvL2Norm({ 1.0f, 2.0f }), - 3.0f * CalcInvL2Norm({ 3.0f, 4.0f }), - 5.0f * CalcInvL2Norm({ 5.0f, 6.0f }), - 7.0f * CalcInvL2Norm({ 7.0f, 8.0f }), - 9.0f * CalcInvL2Norm({ 9.0f, 10.0f }), + 1.0f * CalcInvL2Norm({ 1.0f, 2.0f }), + 3.0f * CalcInvL2Norm({ 3.0f, 4.0f }), + 5.0f * CalcInvL2Norm({ 5.0f, 6.0f }), + 7.0f * CalcInvL2Norm({ 7.0f, 8.0f }), + 9.0f * CalcInvL2Norm({ 9.0f, 10.0f }), // Batch 0, Channel 1, Height (1) x Width (5) - 2.0f * CalcInvL2Norm({ 1.0f, 2.0f }), - 4.0f * CalcInvL2Norm({ 3.0f, 4.0f }), - 6.0f * CalcInvL2Norm({ 5.0f, 6.0f }), - 8.0f * CalcInvL2Norm({ 7.0f, 8.0f }), + 2.0f * CalcInvL2Norm({ 1.0f, 2.0f }), + 4.0f * CalcInvL2Norm({ 3.0f, 4.0f }), + 6.0f * CalcInvL2Norm({ 5.0f, 6.0f }), + 8.0f * CalcInvL2Norm({ 7.0f, 8.0f }), 10.0f * CalcInvL2Norm({ 9.0f, 10.0f }) }; - return L2NormalizationTestImpl(workloadFactory, memoryManager, inputOutputShape, - inputValues, expectedOutputValues, layout); + return L2NormalizationTestImpl<ArmnnType>(workloadFactory, memoryManager, qScale, qOffset, inputOutputShape, + inputValues, expectedOutputValues, layout); } -LayerTestResult<float, 4> L2Normalization3dTest( +LayerTestResult<float, 4> L2Normalization2dTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout) +{ + return L2Normalization2dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.f, 0, layout); +} + +LayerTestResult<int16_t, 4> L2Normalization2dInt16Test( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, const armnn::DataLayout layout) { + return L2Normalization1dTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 1.f, 0, + layout); +} + +template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>> +LayerTestResult<T, 4> L2Normalization3dTestCommon( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + float qScale, + int32_t qOffset, + const armnn::DataLayout layout) +{ // Width: 3 // Height: 4 // Channels: 2 @@ -5922,25 +5975,25 @@ LayerTestResult<float, 4> L2Normalization3dTest( // Batch 0, Channel 0, Height (4) x Width (3) 119.0f, 21.0f, 150.0f, 149.0f, 32.0f, 179.0f, - 15.0f, 227.0f, 141.0f, + 15.0f, 227.0f, 141.0f, 147.0f, 199.0f, 220.0f, // Batch 0, Channel 1, Height (4) x Width (3) 110.0f, 140.0f, 73.0f, 211.0f, 212.0f, 89.0f, - 24.0f, 138.0f, 188.0f, + 24.0f, 138.0f, 188.0f, 162.0f, 12.0f, 161.0f }; std::vector<float> expectedOutputValues { // Batch 0, Channel 0, Height (4) x Width (3) 119.0f * CalcInvL2Norm({ 119.0f, 110.0f }), - 21.0f * CalcInvL2Norm({ 21.0f, 140.0f }), + 21.0f * CalcInvL2Norm({ 21.0f, 140.0f }), 150.0f * CalcInvL2Norm({ 150.0f, 73.0f }), 149.0f * CalcInvL2Norm({ 149.0f, 211.0f }), - 32.0f * CalcInvL2Norm({ 32.0f, 212.0f }), + 32.0f * CalcInvL2Norm({ 32.0f, 212.0f }), 179.0f * CalcInvL2Norm({ 179.0f, 89.0f }), - 15.0f * CalcInvL2Norm({ 15.0f, 24.0f }), + 15.0f * CalcInvL2Norm({ 15.0f, 24.0f }), 227.0f * CalcInvL2Norm({ 227.0f, 138.0f }), 141.0f * CalcInvL2Norm({ 141.0f, 188.0f }), 147.0f * CalcInvL2Norm({ 147.0f, 162.0f }), @@ -5950,28 +6003,48 @@ LayerTestResult<float, 4> L2Normalization3dTest( // Batch 0, Channel 1, Height (4) x Width (3) 110.0f * CalcInvL2Norm({ 119.0f, 110.0f }), 140.0f * CalcInvL2Norm({ 21.0f, 140.0f }), - 73.0f * CalcInvL2Norm({ 150.0f, 73.0f }), + 73.0f * CalcInvL2Norm({ 150.0f, 73.0f }), 211.0f * CalcInvL2Norm({ 149.0f, 211.0f }), 212.0f * CalcInvL2Norm({ 32.0f, 212.0f }), - 89.0f * CalcInvL2Norm({ 179.0f, 89.0f }), - 24.0f * CalcInvL2Norm({ 15.0f, 24.0f }), + 89.0f * CalcInvL2Norm({ 179.0f, 89.0f }), + 24.0f * CalcInvL2Norm({ 15.0f, 24.0f }), 138.0f * CalcInvL2Norm({ 227.0f, 138.0f }), 188.0f * CalcInvL2Norm({ 141.0f, 188.0f }), 162.0f * CalcInvL2Norm({ 147.0f, 162.0f }), - 12.0f * CalcInvL2Norm({ 199.0f, 12.0f }), + 12.0f * CalcInvL2Norm({ 199.0f, 12.0f }), 161.0f * CalcInvL2Norm({ 220.0f, 161.0f }) }; - return L2NormalizationTestImpl(workloadFactory, memoryManager, inputOutputShape, - inputValues, expectedOutputValues, layout); + return L2NormalizationTestImpl<ArmnnType>(workloadFactory, memoryManager, qScale, qOffset, inputOutputShape, + inputValues, expectedOutputValues, layout); } -LayerTestResult<float, 4> L2Normalization4dTest( +LayerTestResult<float, 4> L2Normalization3dTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout) +{ + return L2Normalization3dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.f, 0, layout); +} + +LayerTestResult<int16_t, 4> L2Normalization3dInt16Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout) +{ + return L2Normalization1dTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 1.f, 0, + layout); +} + +template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>> +LayerTestResult<T, 4> L2Normalization4dTestCommon( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + float qScale, + int32_t qOffset, const armnn::DataLayout layout) { - // Width: 3 + // Width: 3 // Height: 4 // Channels: 3 // BatchSize: 2 @@ -5988,127 +6061,144 @@ LayerTestResult<float, 4> L2Normalization4dTest( 235.0f, 46.0f, 178.0f, 100.0f, 123.0f, 19.0f, 172.0f, 74.0f, 250.0f, - 6.0f, 195.0f, 80.0f, + 6.0f, 195.0f, 80.0f, // Batch 0, Channel 1, Height (4) x Width (3) 113.0f, 95.0f, 202.0f, - 77.0f, 114.0f, 71.0f, + 77.0f, 114.0f, 71.0f, 122.0f, 246.0f, 166.0f, - 82.0f, 28.0f, 37.0f, + 82.0f, 28.0f, 37.0f, // Batch 0, Channel 2, Height (4) x Width (3) - 56.0f, 170.0f, 162.0f, + 56.0f, 170.0f, 162.0f, 194.0f, 89.0f, 254.0f, - 12.0f, 209.0f, 200.0f, - 1.0f, 64.0f, 54.0f, + 12.0f, 209.0f, 200.0f, + 1.0f, 64.0f, 54.0f, // Batch 1, Channel 0, Height (4) x Width (3) - 67.0f, 90.0f, 49.0f, - 7.0f, 163.0f, 18.0f, - 25.0f, 117.0f, 103.0f, + 67.0f, 90.0f, 49.0f, + 7.0f, 163.0f, 18.0f, + 25.0f, 117.0f, 103.0f, 247.0f, 59.0f, 189.0f, // Batch 1, Channel 1, Height (4) x Width (3) 239.0f, 104.0f, 199.0f, - 17.0f, 124.0f, 153.0f, + 17.0f, 124.0f, 153.0f, 222.0f, 217.0f, 75.0f, - 32.0f, 126.0f, 21.0f, + 32.0f, 126.0f, 21.0f, // Batch 1, Channel 2, Height (4) x Width (3) - 97.0f, 145.0f, 215.0f, + 97.0f, 145.0f, 215.0f, 115.0f, 116.0f, 238.0f, 226.0f, 16.0f, 132.0f, - 92.0f, 125.0f, 88.0f + 92.0f, 125.0f, 88.0f }; std::vector<float> expectedOutputValues { // Batch 0, Channel 0, Height (4) x Width (3) 235.0f * CalcInvL2Norm({ 235.0f, 113.0f, 56.0f }), - 46.0f * CalcInvL2Norm({ 46.0f, 95.0f, 170.0f }), + 46.0f * CalcInvL2Norm({ 46.0f, 95.0f, 170.0f }), 178.0f * CalcInvL2Norm({ 178.0f, 202.0F, 162.0f }), 100.0f * CalcInvL2Norm({ 100.0f, 77.0f, 194.0f }), 123.0f * CalcInvL2Norm({ 123.0f, 114.0f, 89.0f }), - 19.0f * CalcInvL2Norm({ 19.0f, 71.0f, 254.0f }), + 19.0f * CalcInvL2Norm({ 19.0f, 71.0f, 254.0f }), 172.0f * CalcInvL2Norm({ 172.0f, 122.0f, 12.0f }), - 74.0f * CalcInvL2Norm({ 74.0f, 246.0f, 209.0f }), + 74.0f * CalcInvL2Norm({ 74.0f, 246.0f, 209.0f }), 250.0f * CalcInvL2Norm({ 250.0f, 166.0f, 200.0f }), - 6.0f * CalcInvL2Norm({ 6.0f, 82.0f, 1.0f }), + 6.0f * CalcInvL2Norm({ 6.0f, 82.0f, 1.0f }), 195.0f * CalcInvL2Norm({ 195.0f, 28.0f, 64.0f }), - 80.0f * CalcInvL2Norm({ 80.0f, 37.0f, 54.0f }), + 80.0f * CalcInvL2Norm({ 80.0f, 37.0f, 54.0f }), // Batch 0, Channel 1, Height (4) x Width (3) 113.0f * CalcInvL2Norm({ 235.0f, 113.0f, 56.0f }), - 95.0f * CalcInvL2Norm({ 46.0f, 95.0f, 170.0f }), + 95.0f * CalcInvL2Norm({ 46.0f, 95.0f, 170.0f }), 202.0f * CalcInvL2Norm({ 178.0f, 202.0F, 162.0f }), - 77.0f * CalcInvL2Norm({ 100.0f, 77.0f, 194.0f }), + 77.0f * CalcInvL2Norm({ 100.0f, 77.0f, 194.0f }), 114.0f * CalcInvL2Norm({ 123.0f, 114.0f, 89.0f }), - 71.0f * CalcInvL2Norm({ 19.0f, 71.0f, 254.0f }), + 71.0f * CalcInvL2Norm({ 19.0f, 71.0f, 254.0f }), 122.0f * CalcInvL2Norm({ 172.0f, 122.0f, 12.0f }), 246.0f * CalcInvL2Norm({ 74.0f, 246.0f, 209.0f }), 166.0f * CalcInvL2Norm({ 250.0f, 166.0f, 200.0f }), - 82.0f * CalcInvL2Norm({ 6.0f, 82.0f, 1.0f }), - 28.0f * CalcInvL2Norm({ 195.0f, 28.0f, 64.0f }), - 37.0f * CalcInvL2Norm({ 80.0f, 37.0f, 54.0f }), + 82.0f * CalcInvL2Norm({ 6.0f, 82.0f, 1.0f }), + 28.0f * CalcInvL2Norm({ 195.0f, 28.0f, 64.0f }), + 37.0f * CalcInvL2Norm({ 80.0f, 37.0f, 54.0f }), // Batch 0, Channel 2, Height (4) x Width (3) - 56.0f * CalcInvL2Norm({ 235.0f, 113.0f, 56.0f }), + 56.0f * CalcInvL2Norm({ 235.0f, 113.0f, 56.0f }), 170.0f * CalcInvL2Norm({ 46.0f, 95.0f, 170.0f }), 162.0f * CalcInvL2Norm({ 178.0f, 202.0F, 162.0f }), 194.0f * CalcInvL2Norm({ 100.0f, 77.0f, 194.0f }), - 89.0f * CalcInvL2Norm({ 123.0f, 114.0f, 89.0f }), + 89.0f * CalcInvL2Norm({ 123.0f, 114.0f, 89.0f }), 254.0f * CalcInvL2Norm({ 19.0f, 71.0f, 254.0f }), - 12.0f * CalcInvL2Norm({ 172.0f, 122.0f, 12.0f }), + 12.0f * CalcInvL2Norm({ 172.0f, 122.0f, 12.0f }), 209.0f * CalcInvL2Norm({ 74.0f, 246.0f, 209.0f }), 200.0f * CalcInvL2Norm({ 250.0f, 166.0f, 200.0f }), - 1.0f * CalcInvL2Norm({ 6.0f, 82.0f, 1.0f }), - 64.0f * CalcInvL2Norm({ 195.0f, 28.0f, 64.0f }), - 54.0f * CalcInvL2Norm({ 80.0f, 37.0f, 54.0f }), + 1.0f * CalcInvL2Norm({ 6.0f, 82.0f, 1.0f }), + 64.0f * CalcInvL2Norm({ 195.0f, 28.0f, 64.0f }), + 54.0f * CalcInvL2Norm({ 80.0f, 37.0f, 54.0f }), // Batch 1, Channel 0, Height (4) x Width (3) - 67.0f * CalcInvL2Norm({ 67.0f, 239.0f, 97.0f }), - 90.0f * CalcInvL2Norm({ 90.0f, 104.0f, 145.0f }), - 49.0f * CalcInvL2Norm({ 49.0f, 199.0f, 215.0f }), - 7.0f * CalcInvL2Norm({ 7.0f, 17.0f, 115.0f }), + 67.0f * CalcInvL2Norm({ 67.0f, 239.0f, 97.0f }), + 90.0f * CalcInvL2Norm({ 90.0f, 104.0f, 145.0f }), + 49.0f * CalcInvL2Norm({ 49.0f, 199.0f, 215.0f }), + 7.0f * CalcInvL2Norm({ 7.0f, 17.0f, 115.0f }), 163.0f * CalcInvL2Norm({ 163.0f, 124.0f, 116.0f }), - 18.0f * CalcInvL2Norm({ 18.0f, 153.0f, 238.0f }), - 25.0f * CalcInvL2Norm({ 25.0f, 222.0f, 226.0f }), + 18.0f * CalcInvL2Norm({ 18.0f, 153.0f, 238.0f }), + 25.0f * CalcInvL2Norm({ 25.0f, 222.0f, 226.0f }), 117.0f * CalcInvL2Norm({ 117.0f, 217.0f, 16.0f }), 103.0f * CalcInvL2Norm({ 103.0f, 75.0f, 132.0f }), 247.0f * CalcInvL2Norm({ 247.0f, 32.0f, 92.0f }), - 59.0f * CalcInvL2Norm({ 59.0f, 126.0f, 125.0f }), + 59.0f * CalcInvL2Norm({ 59.0f, 126.0f, 125.0f }), 189.0f * CalcInvL2Norm({ 189.0f, 21.0f, 88.0f }), // Batch 1, Channel 1, Height (4) x Width (3) 239.0f * CalcInvL2Norm({ 67.0f, 239.0f, 97.0f }), 104.0f * CalcInvL2Norm({ 90.0f, 104.0f, 145.0f }), 199.0f * CalcInvL2Norm({ 49.0f, 199.0f, 215.0f }), - 17.0f * CalcInvL2Norm({ 7.0f, 17.0f, 115.0f }), + 17.0f * CalcInvL2Norm({ 7.0f, 17.0f, 115.0f }), 124.0f * CalcInvL2Norm({ 163.0f, 124.0f, 116.0f }), 153.0f * CalcInvL2Norm({ 18.0f, 153.0f, 238.0f }), 222.0f * CalcInvL2Norm({ 25.0f, 222.0f, 226.0f }), 217.0f * CalcInvL2Norm({ 117.0f, 217.0f, 16.0f }), - 75.0f * CalcInvL2Norm({ 103.0f, 75.0f, 132.0f }), - 32.0f * CalcInvL2Norm({ 247.0f, 32.0f, 92.0f }), + 75.0f * CalcInvL2Norm({ 103.0f, 75.0f, 132.0f }), + 32.0f * CalcInvL2Norm({ 247.0f, 32.0f, 92.0f }), 126.0f * CalcInvL2Norm({ 59.0f, 126.0f, 125.0f }), - 21.0f * CalcInvL2Norm({ 189.0f, 21.0f, 88.0f }), + 21.0f * CalcInvL2Norm({ 189.0f, 21.0f, 88.0f }), // Batch 1, Channel 2, Height (4) x Width (3) - 97.0f * CalcInvL2Norm({ 67.0f, 239.0f, 97.0f }), + 97.0f * CalcInvL2Norm({ 67.0f, 239.0f, 97.0f }), 145.0f * CalcInvL2Norm({ 90.0f, 104.0f, 145.0f }), 215.0f * CalcInvL2Norm({ 49.0f, 199.0f, 215.0f }), 115.0f * CalcInvL2Norm({ 7.0f, 17.0f, 115.0f }), 116.0f * CalcInvL2Norm({ 163.0f, 124.0f, 116.0f }), 238.0f * CalcInvL2Norm({ 18.0f, 153.0f, 238.0f }), 226.0f * CalcInvL2Norm({ 25.0f, 222.0f, 226.0f }), - 16.0f * CalcInvL2Norm({ 117.0f, 217.0f, 16.0f }), + 16.0f * CalcInvL2Norm({ 117.0f, 217.0f, 16.0f }), 132.0f * CalcInvL2Norm({ 103.0f, 75.0f, 132.0f }), - 92.0f * CalcInvL2Norm({ 247.0f, 32.0f, 92.0f }), + 92.0f * CalcInvL2Norm({ 247.0f, 32.0f, 92.0f }), 125.0f * CalcInvL2Norm({ 59.0f, 126.0f, 125.0f }), - 88.0f * CalcInvL2Norm({ 189.0f, 21.0f, 88.0f }) + 88.0f * CalcInvL2Norm({ 189.0f, 21.0f, 88.0f }) }; - return L2NormalizationTestImpl(workloadFactory, memoryManager, inputOutputShape, - inputValues, expectedOutputValues, layout); + return L2NormalizationTestImpl<ArmnnType>(workloadFactory, memoryManager, qScale, qOffset, inputOutputShape, + inputValues, expectedOutputValues, layout); +} + +LayerTestResult<float, 4> L2Normalization4dTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout) +{ + return L2Normalization4dTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.f, 0, layout); +} + +LayerTestResult<int16_t, 4> L2Normalization4dInt16Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout) +{ + return L2Normalization1dTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 1.f, 0, + layout); } template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>> diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp index 8a5a61145c..853a612b78 100644 --- a/src/backends/backendsCommon/test/LayerTests.hpp +++ b/src/backends/backendsCommon/test/LayerTests.hpp @@ -927,21 +927,41 @@ LayerTestResult<float, 4> L2Normalization1dTest( const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, const armnn::DataLayout layout); +LayerTestResult<int16_t, 4> L2Normalization1dInt16Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout); + LayerTestResult<float, 4> L2Normalization2dTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, const armnn::DataLayout layout); +LayerTestResult<int16_t, 4> L2Normalization2dInt16Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout); + LayerTestResult<float, 4> L2Normalization3dTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, const armnn::DataLayout layout); +LayerTestResult<int16_t, 4> L2Normalization3dInt16Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout); + LayerTestResult<float, 4> L2Normalization4dTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, const armnn::DataLayout layout); +LayerTestResult<int16_t, 4> L2Normalization4dInt16Test( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout); + LayerTestResult<float, 4> ConstantTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp index b508dfd29d..e42e4242e0 100644 --- a/src/backends/reference/RefLayerSupport.cpp +++ b/src/backends/reference/RefLayerSupport.cpp @@ -743,12 +743,30 @@ bool RefLayerSupport::IsL2NormalizationSupported(const TensorInfo& input, const L2NormalizationDescriptor& descriptor, Optional<std::string&> reasonIfUnsupported) const { - ignore_unused(output); ignore_unused(descriptor); - return IsSupportedForDataTypeRef(reasonIfUnsupported, - input.GetDataType(), - &TrueFunc<>, - &FalseFuncU8<>); + // Define supported types + std::array<DataType, 2> supportedTypes = + { + DataType::Float32, + DataType::QuantisedSymm16 + }; + + bool supported = true; + + supported &= CheckSupportRule(TypeAnyOf(input, supportedTypes), reasonIfUnsupported, + "Reference L2normalization: input type not supported."); + + supported &= CheckSupportRule(TypeAnyOf(output, supportedTypes), reasonIfUnsupported, + "Reference L2normalization: output type not supported."); + + supported &= CheckSupportRule(TypesAreEqual(input, output), reasonIfUnsupported, + "Reference L2normalization: input and output types mismatched."); + + supported &= CheckSupportRule(ShapesAreSameTotalSize(input, output), reasonIfUnsupported, + "Reference L2normalization: input and output shapes have different " + "num total elements."); + + return supported; } bool RefLayerSupport::IsLstmSupported(const TensorInfo& input, diff --git a/src/backends/reference/RefWorkloadFactory.cpp b/src/backends/reference/RefWorkloadFactory.cpp index cb26f2642b..72762a48e6 100644 --- a/src/backends/reference/RefWorkloadFactory.cpp +++ b/src/backends/reference/RefWorkloadFactory.cpp @@ -27,15 +27,16 @@ std::unique_ptr<IWorkload> RefWorkloadFactory::MakeWorkload(const QueueDescripto info); } -bool IsFloat16(const WorkloadInfo& info) +template <DataType ArmnnType> +bool IsDataType(const WorkloadInfo& info) { - auto checkFloat16 = [](const TensorInfo& tensorInfo) {return tensorInfo.GetDataType() == DataType::Float16;}; - auto it = std::find_if(std::begin(info.m_InputTensorInfos), std::end(info.m_InputTensorInfos), checkFloat16); + auto checkType = [](const TensorInfo& tensorInfo) {return tensorInfo.GetDataType() == ArmnnType;}; + auto it = std::find_if(std::begin(info.m_InputTensorInfos), std::end(info.m_InputTensorInfos), checkType); if (it != std::end(info.m_InputTensorInfos)) { return true; } - it = std::find_if(std::begin(info.m_OutputTensorInfos), std::end(info.m_OutputTensorInfos), checkFloat16); + it = std::find_if(std::begin(info.m_OutputTensorInfos), std::end(info.m_OutputTensorInfos), checkType); if (it != std::end(info.m_OutputTensorInfos)) { return true; @@ -43,20 +44,14 @@ bool IsFloat16(const WorkloadInfo& info) return false; } +bool IsFloat16(const WorkloadInfo& info) +{ + return IsDataType<DataType::Float16>(info); +} + bool IsUint8(const WorkloadInfo& info) { - auto checkUint8 = [](const TensorInfo& tensorInfo) {return tensorInfo.GetDataType() == DataType::QuantisedAsymm8;}; - auto it = std::find_if(std::begin(info.m_InputTensorInfos), std::end(info.m_InputTensorInfos), checkUint8); - if (it != std::end(info.m_InputTensorInfos)) - { - return true; - } - it = std::find_if(std::begin(info.m_OutputTensorInfos), std::end(info.m_OutputTensorInfos), checkUint8); - if (it != std::end(info.m_OutputTensorInfos)) - { - return true; - } - return false; + return IsDataType<DataType::QuantisedAsymm8>(info); } RefWorkloadFactory::RefWorkloadFactory() @@ -260,7 +255,11 @@ std::unique_ptr<IWorkload> RefWorkloadFactory::CreateFakeQuantization( std::unique_ptr<IWorkload> RefWorkloadFactory::CreateL2Normalization(const L2NormalizationQueueDescriptor& descriptor, const WorkloadInfo& info) const { - return MakeWorkload<RefL2NormalizationFloat32Workload, NullWorkload>(descriptor, info); + if (IsFloat16(info) || IsUint8(info)) + { + return MakeWorkload<NullWorkload, NullWorkload>(descriptor, info); + } + return std::make_unique<RefL2NormalizationWorkload>(descriptor, info); } std::unique_ptr<armnn::IWorkload> RefWorkloadFactory::CreateConcat(const ConcatQueueDescriptor& descriptor, diff --git a/src/backends/reference/backend.mk b/src/backends/reference/backend.mk index 0d2b65d433..189f692033 100644 --- a/src/backends/reference/backend.mk +++ b/src/backends/reference/backend.mk @@ -43,7 +43,7 @@ BACKEND_SOURCES := \ workloads/RefFloorWorkload.cpp \ workloads/RefFullyConnectedWorkload.cpp \ workloads/RefGatherWorkload.cpp \ - workloads/RefL2NormalizationFloat32Workload.cpp \ + workloads/RefL2NormalizationWorkload.cpp \ workloads/RefLstmWorkload.cpp \ workloads/RefMeanFloat32Workload.cpp \ workloads/RefMeanUint8Workload.cpp \ diff --git a/src/backends/reference/test/RefCreateWorkloadTests.cpp b/src/backends/reference/test/RefCreateWorkloadTests.cpp index dbcf20169c..3de47d20e4 100644 --- a/src/backends/reference/test/RefCreateWorkloadTests.cpp +++ b/src/backends/reference/test/RefCreateWorkloadTests.cpp @@ -712,12 +712,22 @@ static void RefCreateL2NormalizationTest(DataLayout dataLayout) BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat32) { - RefCreateL2NormalizationTest<RefL2NormalizationFloat32Workload, armnn::DataType::Float32>(DataLayout::NCHW); + RefCreateL2NormalizationTest<RefL2NormalizationWorkload, armnn::DataType::Float32>(DataLayout::NCHW); } BOOST_AUTO_TEST_CASE(CreateL2NormalizationFloat32Nhwc) { - RefCreateL2NormalizationTest<RefL2NormalizationFloat32Workload, armnn::DataType::Float32>(DataLayout::NHWC); + RefCreateL2NormalizationTest<RefL2NormalizationWorkload, armnn::DataType::Float32>(DataLayout::NHWC); +} + +BOOST_AUTO_TEST_CASE(CreateL2NormalizationInt16) +{ + RefCreateL2NormalizationTest<RefL2NormalizationWorkload, armnn::DataType::QuantisedSymm16>(DataLayout::NCHW); +} + +BOOST_AUTO_TEST_CASE(CreateL2NormalizationInt16Nhwc) +{ + RefCreateL2NormalizationTest<RefL2NormalizationWorkload, armnn::DataType::QuantisedSymm16>(DataLayout::NHWC); } template <typename ReshapeWorkloadType, armnn::DataType DataType> diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp index 8ebb725a6f..30520cbf2e 100644 --- a/src/backends/reference/test/RefLayerTests.cpp +++ b/src/backends/reference/test/RefLayerTests.cpp @@ -472,11 +472,19 @@ ARMNN_AUTO_TEST_CASE(L2Normalization1d, L2Normalization1dTest, armnn::DataLayout ARMNN_AUTO_TEST_CASE(L2Normalization2d, L2Normalization2dTest, armnn::DataLayout::NCHW) ARMNN_AUTO_TEST_CASE(L2Normalization3d, L2Normalization3dTest, armnn::DataLayout::NCHW) ARMNN_AUTO_TEST_CASE(L2Normalization4d, L2Normalization4dTest, armnn::DataLayout::NCHW) +ARMNN_AUTO_TEST_CASE(L2Normalization1dInt16, L2Normalization1dInt16Test, armnn::DataLayout::NCHW) +ARMNN_AUTO_TEST_CASE(L2Normalization2dInt16, L2Normalization2dInt16Test, armnn::DataLayout::NCHW) +ARMNN_AUTO_TEST_CASE(L2Normalization3dInt16, L2Normalization3dInt16Test, armnn::DataLayout::NCHW) +ARMNN_AUTO_TEST_CASE(L2Normalization4dInt16, L2Normalization4dInt16Test, armnn::DataLayout::NCHW) ARMNN_AUTO_TEST_CASE(L2Normalization1dNhwc, L2Normalization1dTest, armnn::DataLayout::NHWC) ARMNN_AUTO_TEST_CASE(L2Normalization2dNhwc, L2Normalization2dTest, armnn::DataLayout::NHWC) ARMNN_AUTO_TEST_CASE(L2Normalization3dNhwc, L2Normalization3dTest, armnn::DataLayout::NHWC) ARMNN_AUTO_TEST_CASE(L2Normalization4dNhwc, L2Normalization4dTest, armnn::DataLayout::NHWC) +ARMNN_AUTO_TEST_CASE(L2Normalization1dInt16Nhwc, L2Normalization1dInt16Test, armnn::DataLayout::NHWC) +ARMNN_AUTO_TEST_CASE(L2Normalization2dInt16Nhwc, L2Normalization2dInt16Test, armnn::DataLayout::NHWC) +ARMNN_AUTO_TEST_CASE(L2Normalization3dInt16Nhwc, L2Normalization3dInt16Test, armnn::DataLayout::NHWC) +ARMNN_AUTO_TEST_CASE(L2Normalization4dInt16Nhwc, L2Normalization4dInt16Test, armnn::DataLayout::NHWC) // Pad ARMNN_AUTO_TEST_CASE(PadFloat322d, PadFloat322dTest) diff --git a/src/backends/reference/workloads/CMakeLists.txt b/src/backends/reference/workloads/CMakeLists.txt index 4d11447280..41a553482d 100644 --- a/src/backends/reference/workloads/CMakeLists.txt +++ b/src/backends/reference/workloads/CMakeLists.txt @@ -70,8 +70,8 @@ list(APPEND armnnRefBackendWorkloads_sources RefFullyConnectedWorkload.hpp RefGatherWorkload.cpp RefGatherWorkload.hpp - RefL2NormalizationFloat32Workload.cpp - RefL2NormalizationFloat32Workload.hpp + RefL2NormalizationWorkload.cpp + RefL2NormalizationWorkload.hpp RefLstmWorkload.cpp RefLstmWorkload.hpp RefConcatWorkload.cpp diff --git a/src/backends/reference/workloads/RefL2NormalizationFloat32Workload.cpp b/src/backends/reference/workloads/RefL2NormalizationFloat32Workload.cpp deleted file mode 100644 index bc82739f6e..0000000000 --- a/src/backends/reference/workloads/RefL2NormalizationFloat32Workload.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright © 2017 Arm Ltd. All rights reserved. -// SPDX-License-Identifier: MIT -// - -#include "RefL2NormalizationFloat32Workload.hpp" - -#include "RefWorkloadUtils.hpp" -#include "TensorBufferArrayView.hpp" - -#include "Profiling.hpp" - -#include <cmath> - -using namespace armnnUtils; - -namespace armnn -{ - -void RefL2NormalizationFloat32Workload::Execute() const -{ - ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefL2NormalizationFloat32Workload_Execute"); - - const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); - const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]); - - TensorBufferArrayView<const float> input(inputInfo.GetShape(), - GetInputTensorDataFloat(0, m_Data), - m_Data.m_Parameters.m_DataLayout); - TensorBufferArrayView<float> output(outputInfo.GetShape(), - GetOutputTensorDataFloat(0, m_Data), - m_Data.m_Parameters.m_DataLayout); - - DataLayoutIndexed dataLayout(m_Data.m_Parameters.m_DataLayout); - - const unsigned int batches = inputInfo.GetShape()[0]; - const unsigned int channels = inputInfo.GetShape()[dataLayout.GetChannelsIndex()]; - const unsigned int height = inputInfo.GetShape()[dataLayout.GetHeightIndex()]; - const unsigned int width = inputInfo.GetShape()[dataLayout.GetWidthIndex()]; - - for (unsigned int n = 0; n < batches; ++n) - { - for (unsigned int c = 0; c < channels; ++c) - { - for (unsigned int h = 0; h < height; ++h) - { - for (unsigned int w = 0; w < width; ++w) - { - float reduction = 0.0; - for (unsigned int d = 0; d < channels; ++d) - { - const float value = input.Get(n, d, h, w); - reduction += value * value; - } - - // Using std::max(reduction, epsilon) below would prevent against division by 0. - // However, at the time of writing: - // - This is not supported by the ACL functions used to implement L2Normalization in the CL - // backend. - // - The reference semantics for this operator do not include this parameter. - const float scale = 1.0f / sqrtf(reduction); - output.Get(n, c, h, w) = input.Get(n, c, h, w) * scale; - } - } - } - } -} - -} //namespace armnn diff --git a/src/backends/reference/workloads/RefL2NormalizationWorkload.cpp b/src/backends/reference/workloads/RefL2NormalizationWorkload.cpp new file mode 100644 index 0000000000..ce5699ef0b --- /dev/null +++ b/src/backends/reference/workloads/RefL2NormalizationWorkload.cpp @@ -0,0 +1,75 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "RefL2NormalizationWorkload.hpp" + +#include "RefWorkloadUtils.hpp" +#include "Decoders.hpp" +#include "Encoders.hpp" +#include "DataLayoutIndexed.hpp" + + +#include "Profiling.hpp" + +#include <cmath> + +using namespace armnnUtils; + +namespace armnn +{ +RefL2NormalizationWorkload::RefL2NormalizationWorkload( + const L2NormalizationQueueDescriptor& descriptor, + const WorkloadInfo& info) + : BaseWorkload<L2NormalizationQueueDescriptor>(descriptor, info) {} + + void RefL2NormalizationWorkload::Execute() const + { + ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefL2NormalizationWorkload_Execute"); + + const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); + const TensorInfo& outputInfo = GetTensorInfo(m_Data.m_Outputs[0]); + + auto inputDecoder = MakeDecoder<float>(inputInfo, m_Data.m_Inputs[0]->Map()); + auto outputEncoder = MakeEncoder<float>(outputInfo, m_Data.m_Outputs[0]->Map()); + + DataLayoutIndexed dataLayout(m_Data.m_Parameters.m_DataLayout); + + const unsigned int batches = inputInfo.GetShape()[0]; + const unsigned int channels = inputInfo.GetShape()[dataLayout.GetChannelsIndex()]; + const unsigned int height = inputInfo.GetShape()[dataLayout.GetHeightIndex()]; + const unsigned int width = inputInfo.GetShape()[dataLayout.GetWidthIndex()]; + + for (unsigned int n = 0; n < batches; ++n) + { + for (unsigned int c = 0; c < channels; ++c) + { + for (unsigned int h = 0; h < height; ++h) + { + for (unsigned int w = 0; w < width; ++w) + { + float reduction = 0.0; + for (unsigned int d = 0; d < channels; ++d) + { + unsigned int inputIndex = dataLayout.GetIndex(inputInfo.GetShape(), n, d, h, w); + + (*inputDecoder)[inputIndex]; + const float value = inputDecoder->Get(); + reduction += value * value; + } + + unsigned int index = dataLayout.GetIndex(inputInfo.GetShape(), n, c, h, w); + + const float scale = 1.0f / sqrtf(reduction); + + (*inputDecoder)[index]; + (*outputEncoder)[index]; + outputEncoder->Set(inputDecoder->Get() * scale); + } + } + } + } + } + +} //namespace armnn diff --git a/src/backends/reference/workloads/RefL2NormalizationFloat32Workload.hpp b/src/backends/reference/workloads/RefL2NormalizationWorkload.hpp index 50ece0e905..4beedc9992 100644 --- a/src/backends/reference/workloads/RefL2NormalizationFloat32Workload.hpp +++ b/src/backends/reference/workloads/RefL2NormalizationWorkload.hpp @@ -1,4 +1,4 @@ -// +// // Copyright © 2017 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // @@ -11,10 +11,11 @@ namespace armnn { -class RefL2NormalizationFloat32Workload : public Float32Workload<L2NormalizationQueueDescriptor> +class RefL2NormalizationWorkload : public BaseWorkload<L2NormalizationQueueDescriptor> { public: - using Float32Workload<L2NormalizationQueueDescriptor>::Float32Workload; + explicit RefL2NormalizationWorkload(const L2NormalizationQueueDescriptor& descriptor, + const WorkloadInfo& info); void Execute() const override; }; diff --git a/src/backends/reference/workloads/RefWorkloads.hpp b/src/backends/reference/workloads/RefWorkloads.hpp index 53f7aa2efb..1a2dec402e 100644 --- a/src/backends/reference/workloads/RefWorkloads.hpp +++ b/src/backends/reference/workloads/RefWorkloads.hpp @@ -12,7 +12,7 @@ #include "RefConvolution2dWorkload.hpp" #include "RefSplitterWorkload.hpp" #include "RefResizeBilinearUint8Workload.hpp" -#include "RefL2NormalizationFloat32Workload.hpp" +#include "RefL2NormalizationWorkload.hpp" #include "RefActivationWorkload.hpp" #include "RefPooling2dWorkload.hpp" #include "RefWorkloadUtils.hpp" |