aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFerran Balaguer <ferran.balaguer@arm.com>2019-06-10 10:29:54 +0100
committerMatteo Martincigh <matteo.martincigh@arm.com>2019-06-14 13:03:28 +0000
commitd73d14fd77fe1405a33b3ecf3c56e1ac65647ff7 (patch)
treea8f51e7d7c652653dc13c8c978aca347463c03a0
parent0421e7f22d9ccd5d810b345731b766a96c841492 (diff)
downloadarmnn-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
-rw-r--r--src/backends/backendsCommon/WorkloadData.cpp26
-rw-r--r--src/backends/backendsCommon/test/LayerTests.cpp302
-rw-r--r--src/backends/backendsCommon/test/LayerTests.hpp20
-rw-r--r--src/backends/reference/RefLayerSupport.cpp28
-rw-r--r--src/backends/reference/RefWorkloadFactory.cpp33
-rw-r--r--src/backends/reference/backend.mk2
-rw-r--r--src/backends/reference/test/RefCreateWorkloadTests.cpp14
-rw-r--r--src/backends/reference/test/RefLayerTests.cpp8
-rw-r--r--src/backends/reference/workloads/CMakeLists.txt4
-rw-r--r--src/backends/reference/workloads/RefL2NormalizationFloat32Workload.cpp69
-rw-r--r--src/backends/reference/workloads/RefL2NormalizationWorkload.cpp75
-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.hpp2
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"