From e52211e1544a30d24b29523c389116a9e4446e8c Mon Sep 17 00:00:00 2001 From: Ferran Balaguer Date: Mon, 17 Jun 2019 12:23:52 +0100 Subject: IVGCVSW-3286 Add epsilon Reference workload support Change-Id: I5cabbf9d1ef3858be68d6820d14845e512128c5b Signed-off-by: Ferran Balaguer --- include/armnn/Descriptors.hpp | 5 +- src/backends/backendsCommon/test/LayerTests.cpp | 75 +++++++++++++++++++++- src/backends/backendsCommon/test/LayerTests.hpp | 10 +++ src/backends/reference/test/RefLayerTests.cpp | 3 + .../workloads/RefL2NormalizationWorkload.cpp | 4 +- 5 files changed, 94 insertions(+), 3 deletions(-) diff --git a/include/armnn/Descriptors.hpp b/include/armnn/Descriptors.hpp index 9479db3571..dd1991d569 100644 --- a/include/armnn/Descriptors.hpp +++ b/include/armnn/Descriptors.hpp @@ -424,9 +424,12 @@ struct NormalizationDescriptor struct L2NormalizationDescriptor { L2NormalizationDescriptor() - : m_DataLayout(DataLayout::NCHW) + : m_Eps(1e-12f) + , m_DataLayout(DataLayout::NCHW) {} + /// Used to avoid dividing by zero. + float m_Eps; /// The data layout to be used (NCHW, NHWC). DataLayout m_DataLayout; }; diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp index 55e799e1be..115b5ecf41 100644 --- a/src/backends/backendsCommon/test/LayerTests.cpp +++ b/src/backends/backendsCommon/test/LayerTests.cpp @@ -5294,7 +5294,8 @@ LayerTestResult L2NormalizationTestImpl( float outScale, int32_t outOffset, const std::vector& expectedOutputValues, - const armnn::DataLayout layout) + const armnn::DataLayout layout, + float epsilon = 1e-12f) { const armnn::TensorInfo inputTensorInfo(inputOutputTensorShape, ArmnnType, scale, offset); const armnn::TensorInfo outputTensorInfo(inputOutputTensorShape, ArmnnType, outScale, outOffset); @@ -5333,6 +5334,7 @@ LayerTestResult L2NormalizationTestImpl( std::unique_ptr outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo); armnn::L2NormalizationQueueDescriptor descriptor; + descriptor.m_Parameters.m_Eps = epsilon; descriptor.m_Parameters.m_DataLayout = layout; armnn::WorkloadInfo info; @@ -5797,6 +5799,57 @@ LayerTestResult PadFloat324dTest( return Pad4dTestCommon(workloadFactory, memoryManager, 0.0f, 0); } +template> +LayerTestResult L2NormalizationEpsilonTestCommon( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + float scale, + int32_t offset, + float outScale, + int32_t outOffset, + const armnn::DataLayout layout, + float epsilon) +{ + // Width: 1 + // Height: 1 + // Channels: 3 + // BatchSize: 1 + unsigned int numberOfBatches = 1; + unsigned int numberOfChannels = 3; + unsigned int height = 1; + unsigned int width = 1; + + const armnn::TensorShape inputOutputShape = armnnUtils::GetTensorShape( + numberOfBatches, numberOfChannels, height, width, layout); + + // 0.0000001^2 + 0.00000002^2 + 0.00000003^2 < 1e-12 + std::vector inputValues + { + // Batch 0, Channel 0, Height (1) x Width (1) + 0.00000001f, + + // Batch 0, Channel 1, Height (1) x Width (1) + 0.00000002f, + + // Batch 0, Channel 2, Height (1) x Width (1) + 0.00000003f, + }; + + const float approxInvL2Norm = 1.f / sqrtf(epsilon); + std::vector expectedOutputValues + { + // Batch 0, Channel 0, Height (1) x Width (1) + 0.00000001f * approxInvL2Norm, + 0.00000002f * approxInvL2Norm, + 0.00000003f * approxInvL2Norm, + }; + + return L2NormalizationTestImpl(workloadFactory, memoryManager, inputOutputShape, scale, offset, + inputValues, outScale, outOffset, expectedOutputValues, layout, + epsilon); +} + + template> LayerTestResult L2Normalization1dTestCommon( armnn::IWorkloadFactory& workloadFactory, @@ -5872,6 +5925,26 @@ LayerTestResult L2Normalization1dTestCommon( inputValues, outScale, outOffset, expectedOutputValues, layout); } +LayerTestResult L2NormalizationDefaultEpsilonTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout) +{ + // Dummy descriptor to get the default value of epsilon. + armnn::L2NormalizationDescriptor descriptor; + + return L2NormalizationEpsilonTestCommon(workloadFactory, memoryManager, 0.f, 0, 0.f, 0, + layout, descriptor.m_Eps); +} + +LayerTestResult L2NormalizationNonDefaultEpsilonTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout) +{ + return L2NormalizationEpsilonTestCommon(workloadFactory, memoryManager, 0.f, 0, 0.f, 0, + layout, 1e-9f); +} LayerTestResult L2Normalization1dTest( armnn::IWorkloadFactory& workloadFactory, diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp index 704e88ef6b..4c340447b9 100644 --- a/src/backends/backendsCommon/test/LayerTests.hpp +++ b/src/backends/backendsCommon/test/LayerTests.hpp @@ -922,6 +922,16 @@ LayerTestResult FakeQuantizationTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager); +LayerTestResult L2NormalizationDefaultEpsilonTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout); + +LayerTestResult L2NormalizationNonDefaultEpsilonTest( + armnn::IWorkloadFactory& workloadFactory, + const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, + const armnn::DataLayout layout); + LayerTestResult L2Normalization1dTest( armnn::IWorkloadFactory& workloadFactory, const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager, diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp index 7540f1d4c1..cf4d9fd6f9 100644 --- a/src/backends/reference/test/RefLayerTests.cpp +++ b/src/backends/reference/test/RefLayerTests.cpp @@ -528,6 +528,9 @@ ARMNN_AUTO_TEST_CASE(L2Normalization2dUint8Nhwc, L2Normalization2dUint8Test, arm ARMNN_AUTO_TEST_CASE(L2Normalization3dUint8Nhwc, L2Normalization3dUint8Test, armnn::DataLayout::NHWC) ARMNN_AUTO_TEST_CASE(L2Normalization4dUint8Nhwc, L2Normalization4dUint8Test, armnn::DataLayout::NHWC) +ARMNN_AUTO_TEST_CASE(L2NormalizationDefaultEpsilon, L2NormalizationDefaultEpsilonTest, armnn::DataLayout::NCHW) +ARMNN_AUTO_TEST_CASE(L2NormalizationNonDefaultEpsilon, L2NormalizationNonDefaultEpsilonTest, armnn::DataLayout::NCHW) + // Pad ARMNN_AUTO_TEST_CASE(PadFloat322d, PadFloat322dTest) ARMNN_AUTO_TEST_CASE(PadFloat323d, PadFloat323dTest) diff --git a/src/backends/reference/workloads/RefL2NormalizationWorkload.cpp b/src/backends/reference/workloads/RefL2NormalizationWorkload.cpp index ce5699ef0b..3b2ab50c8b 100644 --- a/src/backends/reference/workloads/RefL2NormalizationWorkload.cpp +++ b/src/backends/reference/workloads/RefL2NormalizationWorkload.cpp @@ -61,7 +61,9 @@ RefL2NormalizationWorkload::RefL2NormalizationWorkload( unsigned int index = dataLayout.GetIndex(inputInfo.GetShape(), n, c, h, w); - const float scale = 1.0f / sqrtf(reduction); + float maximum = reduction < m_Data.m_Parameters.m_Eps ? m_Data.m_Parameters.m_Eps : reduction; + + const float scale = 1.0f / sqrtf(maximum); (*inputDecoder)[index]; (*outputEncoder)[index]; -- cgit v1.2.1