blob: 6ba3e6b94a675ca59ad51c564dfff97ba064076f [file] [log] [blame]
Laurent Carlier749294b2020-06-01 09:03:17 +01001//
Teresa Charlinfbf0e5b2020-08-17 01:01:06 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01006#include "NormalizationTestImpl.hpp"
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00007
David Beckac42efd2018-09-26 17:41:13 +01008#include <armnn/Exceptions.hpp>
telsoa014fcda012018-03-09 14:13:49 +00009
Matthew Sloyan171214c2020-09-09 09:07:37 +010010#include <armnn/utility/NumericCast.hpp>
11
Colm Donelan0c479742021-12-10 12:43:54 +000012#include <armnn/backends/TensorHandle.hpp>
Francis Murtaghb28e5252022-02-09 14:36:04 +000013#include <armnn/backends/ILayerSupport.hpp>
14#include <armnn/BackendHelper.hpp>
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010015
Sadik Armagana097d2a2021-11-24 15:47:28 +000016#include <armnnTestUtils/TensorCopyUtils.hpp>
Colm Donelan0c479742021-12-10 12:43:54 +000017#include <armnnTestUtils/WorkloadTestUtils.hpp>
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010018
Colm Donelanc42a9872022-02-02 16:35:09 +000019#include <armnnTestUtils/TensorHelpers.hpp>
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010020
21namespace
22{
telsoa014fcda012018-03-09 14:13:49 +000023
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000024LayerTestResult<float,4> SimpleNormalizationTestImpl(
25 armnn::IWorkloadFactory& workloadFactory,
26 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Finn Williams826a5432020-08-27 16:15:20 +010027 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000028 armnn::NormalizationAlgorithmChannel normChannel,
29 armnn::NormalizationAlgorithmMethod normMethod)
telsoa014fcda012018-03-09 14:13:49 +000030{
Jan Eilers8eb25602020-03-09 12:13:48 +000031 IgnoreUnused(memoryManager);
telsoa014fcda012018-03-09 14:13:49 +000032 const unsigned int inputHeight = 2;
33 const unsigned int inputWidth = 2;
34 const unsigned int inputChannels = 1;
35 const unsigned int inputNum = 2;
36
37 unsigned int outputHeight = inputHeight;
38 unsigned int outputWidth = inputWidth;
39 unsigned int outputChannels = inputChannels;
40 unsigned int outputNum = inputNum;
41
42 unsigned int inputShape[] = { inputNum, inputChannels, inputHeight, inputWidth };
43 unsigned int outputShape[] = { outputNum, outputChannels, outputHeight, outputWidth };
44
45 auto inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
46 auto outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
47
Sadik Armagan483c8112021-06-01 09:24:52 +010048 std::vector<float> input =
49 {
telsoa014fcda012018-03-09 14:13:49 +000050 // Batch #0
51 1.0f, 2.0f,
52 3.0f, 4.0f,
53 // Batch #1
54 5.0f, 6.0f,
55 7.0f, 8.0f
Sadik Armagan483c8112021-06-01 09:24:52 +010056 };
57
58 std::vector<float> actualOutput(outputTensorInfo.GetNumElements());
59 std::vector<float> expectedOutput(outputTensorInfo.GetNumElements());
telsoa014fcda012018-03-09 14:13:49 +000060
61 float alpha = 1.f;
62 float beta = 1.f;
63 float kappa = 1.f;
64 uint32_t normSize = 3;
65
Finn Williams826a5432020-08-27 16:15:20 +010066 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
67 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
telsoa014fcda012018-03-09 14:13:49 +000068
69 armnn::NormalizationQueueDescriptor data;
70 armnn::WorkloadInfo info;
71 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
72 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
73 data.m_Parameters.m_NormChannelType = normChannel;
74 data.m_Parameters.m_NormMethodType = normMethod;
75 data.m_Parameters.m_NormSize = normSize;
76 data.m_Parameters.m_Alpha = alpha;
77 data.m_Parameters.m_Beta = beta;
78 data.m_Parameters.m_K = kappa;
narpra0155a97bc2018-10-02 14:35:53 +010079 data.m_Parameters.m_DataLayout = armnn::DataLayout::NCHW;
telsoa014fcda012018-03-09 14:13:49 +000080
Sadik Armagan483c8112021-06-01 09:24:52 +010081 armnn::PassthroughTensorHandle refHandle(outputTensorInfo, expectedOutput.data());
telsoa014fcda012018-03-09 14:13:49 +000082 armnn::NormalizationQueueDescriptor refData = data;
83 armnn::WorkloadInfo refInfo = info;
84 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, &refHandle);
85
Teresa Charlin611c7fb2022-01-07 09:47:29 +000086 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Normalization,
87 data,
88 info);
telsoa014fcda012018-03-09 14:13:49 +000089
90 inputHandle->Allocate();
91 outputHandle->Allocate();
92
Sadik Armagan483c8112021-06-01 09:24:52 +010093 CopyDataToITensorHandle(inputHandle.get(), input.data());
telsoa014fcda012018-03-09 14:13:49 +000094
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000095 ExecuteWorkload(*workload, memoryManager);
telsoa014fcda012018-03-09 14:13:49 +000096
Sadik Armagan483c8112021-06-01 09:24:52 +010097 CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
telsoa014fcda012018-03-09 14:13:49 +000098
99 switch (normMethod)
100 {
101 case armnn::NormalizationAlgorithmMethod::LocalBrightness:
102 {
103 switch (normChannel)
104 {
105 case armnn::NormalizationAlgorithmChannel::Within:
106 {
107 // When normalising within channels, the 3x3 kernel covers the entire 2x2 input at every index.
108 // Therefore, all output values should equal the inputs, but divided by:
109 // pow((kappa + (accumulatedScale * alpha)), beta)
telsoa01c577f2c2018-08-31 09:22:23 +0100110 // ...where accumulatedScale is the sum of every element squared.
telsoa014fcda012018-03-09 14:13:49 +0000111 float divisor[inputNum];
Sadik Armagan483c8112021-06-01 09:24:52 +0100112
113 float accumulatedScale1 = 0.0f;
114 for (size_t i = 0; i < input.size()/2; ++i)
telsoa014fcda012018-03-09 14:13:49 +0000115 {
Sadik Armagan483c8112021-06-01 09:24:52 +0100116 accumulatedScale1 += input[i]*input[i];
telsoa014fcda012018-03-09 14:13:49 +0000117 }
Sadik Armagan483c8112021-06-01 09:24:52 +0100118
119 float accumulatedScale2 = 0.0f;
120 for (size_t i = input.size()/2; i < input.size(); ++i)
121 {
122 accumulatedScale2 += input[i]*input[i];
123 }
124
125 divisor[0] = powf((kappa + accumulatedScale1 * alpha), beta);
126 divisor[1] = powf((kappa + accumulatedScale2 * alpha), beta);
127
128 std::vector<float> output;
129 unsigned int divisorIndex = 0;
130 for (size_t i = 0; i < input.size(); ++i)
131 {
132 if (i == input.size()/2)
133 {
134 divisorIndex++;
135 }
136 output.emplace_back(input[i]/divisor[divisorIndex]);
137 }
138
139 expectedOutput = output;
telsoa014fcda012018-03-09 14:13:49 +0000140 break;
141 }
142 case armnn::NormalizationAlgorithmChannel::Across:
143 {
144 // When normalising across channels, all output values should equal the inputs, but multiplied by:
145 // pow((kappa + (accumulatedScale * alpha)), -beta)
146 // ...where accumulatedScale is the sum of the inputs for adjacent channels for this element squared
147 // ...where adjacent channels means within half the normSize for the channel
148 // The test data has only one channel, so this is simplified below.
149 std::vector<float> outputVector;
Sadik Armagan483c8112021-06-01 09:24:52 +0100150
151 for (unsigned int i = 0; i < input.size(); ++i)
telsoa014fcda012018-03-09 14:13:49 +0000152 {
Sadik Armagan483c8112021-06-01 09:24:52 +0100153 float accumulatedScale = input[i]*input[i];
154 float scale = powf((kappa + accumulatedScale * alpha), -beta);
155 outputVector.push_back(input[i] * scale);
telsoa014fcda012018-03-09 14:13:49 +0000156 }
Sadik Armagan483c8112021-06-01 09:24:52 +0100157 expectedOutput = outputVector;
telsoa014fcda012018-03-09 14:13:49 +0000158 break;
159 }
160 default:
161 {
162 throw armnn::UnimplementedException("Unsupported normalisation channel type, "
163 "only Across and Within are supported");
164 }
165 }
166 break;
167 }
telsoa01c577f2c2018-08-31 09:22:23 +0100168 case armnn::NormalizationAlgorithmMethod::LocalContrast: // NOTE: intentional fallthrough.
telsoa014fcda012018-03-09 14:13:49 +0000169 default:
170 {
171 throw armnn::UnimplementedException("Unsupported normalisation method type, "
172 "only LocalBrightness is supported");
173 }
174 }
175
Sadik Armagan483c8112021-06-01 09:24:52 +0100176 return LayerTestResult<float, 4>(actualOutput,
177 expectedOutput,
178 outputHandle->GetShape(),
179 outputTensorInfo.GetShape());
telsoa014fcda012018-03-09 14:13:49 +0000180}
181
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000182LayerTestResult<float,4> SimpleNormalizationNhwcTestImpl(
183 armnn::IWorkloadFactory& workloadFactory,
184 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Finn Williams826a5432020-08-27 16:15:20 +0100185 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000186 armnn::NormalizationAlgorithmChannel normChannel,
187 armnn::NormalizationAlgorithmMethod normMethod)
narpra0155a97bc2018-10-02 14:35:53 +0100188{
189 const unsigned int inputHeight = 2;
190 const unsigned int inputWidth = 2;
191 const unsigned int inputChannels = 1;
192 const unsigned int inputNum = 2;
193
194 unsigned int outputHeight = inputHeight;
195 unsigned int outputWidth = inputWidth;
196 unsigned int outputChannels = inputChannels;
197 unsigned int outputNum = inputNum;
198
199 unsigned int inputShape[] = { inputNum, inputHeight, inputWidth, inputChannels };
200 unsigned int outputShape[] = { outputNum, outputHeight, outputWidth, outputChannels };
201
202 auto inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
203 auto outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
204
Sadik Armagan483c8112021-06-01 09:24:52 +0100205 std::vector<float> input =
206 {
narpra0155a97bc2018-10-02 14:35:53 +0100207 // Batch #0
208 1.0f, 2.0f,
209 3.0f, 4.0f,
210 // Batch #1
211 5.0f, 6.0f,
212 7.0f, 8.0f
Sadik Armagan483c8112021-06-01 09:24:52 +0100213 };
214
215 std::vector<float> actualOutput(outputTensorInfo.GetNumElements());
216 std::vector<float> expectedOutput(outputTensorInfo.GetNumElements());
narpra0155a97bc2018-10-02 14:35:53 +0100217
218 float alpha = 1.f;
219 float beta = 1.f;
220 float kappa = 1.f;
221 uint32_t normSize = 3;
222
Finn Williams826a5432020-08-27 16:15:20 +0100223 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
224 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
narpra0155a97bc2018-10-02 14:35:53 +0100225
226 armnn::NormalizationQueueDescriptor data;
227 armnn::WorkloadInfo info;
228 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
229 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
230 data.m_Parameters.m_NormChannelType = normChannel;
231 data.m_Parameters.m_NormMethodType = normMethod;
232 data.m_Parameters.m_NormSize = normSize;
233 data.m_Parameters.m_Alpha = alpha;
234 data.m_Parameters.m_Beta = beta;
235 data.m_Parameters.m_K = kappa;
236 data.m_Parameters.m_DataLayout = armnn::DataLayout::NHWC;
237
Sadik Armagan483c8112021-06-01 09:24:52 +0100238 armnn::PassthroughTensorHandle refHandle(outputTensorInfo, expectedOutput.data());
narpra0155a97bc2018-10-02 14:35:53 +0100239 armnn::NormalizationQueueDescriptor refData = data;
240 armnn::WorkloadInfo refInfo = info;
241 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, &refHandle);
242
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000243 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Normalization,
244 data,
245 info);
narpra0155a97bc2018-10-02 14:35:53 +0100246
247 inputHandle->Allocate();
248 outputHandle->Allocate();
249
Sadik Armagan483c8112021-06-01 09:24:52 +0100250 CopyDataToITensorHandle(inputHandle.get(), input.data());
narpra0155a97bc2018-10-02 14:35:53 +0100251
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000252 ExecuteWorkload(*workload, memoryManager);
narpra0155a97bc2018-10-02 14:35:53 +0100253
Sadik Armagan483c8112021-06-01 09:24:52 +0100254 CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
narpra0155a97bc2018-10-02 14:35:53 +0100255
256 switch (normMethod)
257 {
258 case armnn::NormalizationAlgorithmMethod::LocalBrightness:
259 {
260 switch (normChannel)
261 {
262 case armnn::NormalizationAlgorithmChannel::Across:
263 {
Sadik Armagan483c8112021-06-01 09:24:52 +0100264 expectedOutput = { 0.5f, 0.400000006f, 0.300000012f, 0.235294119f,
265 0.192307696f, 0.16216217f, 0.140000001f, 0.123076923f };
narpra0155a97bc2018-10-02 14:35:53 +0100266 break;
267 }
268 default:
269 {
270 throw armnn::UnimplementedException("Unsupported normalisation channel type, "
271 "Only Cross-map is supported for NHWC layout");
272 }
273 }
274 break;
275 }
276 case armnn::NormalizationAlgorithmMethod::LocalContrast: // NOTE: intentional fallthrough.
277 default:
278 {
279 throw armnn::UnimplementedException("Unsupported normalisation method type, "
280 "only LocalBrightness is supported");
281 }
282 }
283
Sadik Armagan483c8112021-06-01 09:24:52 +0100284 return LayerTestResult<float, 4>(actualOutput,
285 expectedOutput,
286 outputHandle->GetShape(),
287 outputTensorInfo.GetShape());
narpra0155a97bc2018-10-02 14:35:53 +0100288}
289
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000290LayerTestResult<float,4> CompareNormalizationTestImpl(
291 armnn::IWorkloadFactory& workloadFactory,
292 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
293 armnn::IWorkloadFactory& refWorkloadFactory,
Finn Williams826a5432020-08-27 16:15:20 +0100294 const armnn::ITensorHandleFactory& tensorHandleFactory,
295 const armnn::ITensorHandleFactory& refTensorHandleFactory,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000296 armnn::NormalizationAlgorithmChannel normChannel,
297 armnn::NormalizationAlgorithmMethod normMethod)
telsoa014fcda012018-03-09 14:13:49 +0000298{
299 constexpr unsigned int inputNum = 5;
300 constexpr unsigned int inputChannels = 3;
301 constexpr unsigned int inputHeight = 32;
302 constexpr unsigned int inputWidth = 24;
303
304 constexpr unsigned int outputNum = inputNum;
305 constexpr unsigned int outputChannels = inputChannels;
306 constexpr unsigned int outputHeight = inputHeight;
307 constexpr unsigned int outputWidth = inputWidth;
308
309 armnn::TensorInfo inputTensorInfo;
310 armnn::TensorInfo outputTensorInfo;
311
312 unsigned int inputShape[] = {inputNum, inputChannels, inputHeight, inputWidth};
313 unsigned int outputShape[] = {outputNum, outputChannels, outputHeight, outputWidth};
314
315 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
316 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
317
318 LayerTestResult<float,4> ret(outputTensorInfo);
319
Sadik Armagan483c8112021-06-01 09:24:52 +0100320 auto input = MakeRandomTensor<float>(inputTensorInfo, 111234);
321
322 std::vector<float> actualOutput(outputTensorInfo.GetNumElements());
323 std::vector<float> expectedOutput(outputTensorInfo.GetNumElements());
telsoa014fcda012018-03-09 14:13:49 +0000324
325 constexpr float alpha = 1.f;
326 constexpr float beta = 1.f;
327 constexpr float kappa = 1.f;
328 constexpr uint32_t normSize = 5;
329
Finn Williams826a5432020-08-27 16:15:20 +0100330 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
331 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
telsoa014fcda012018-03-09 14:13:49 +0000332
333 armnn::NormalizationQueueDescriptor data;
334 armnn::WorkloadInfo info;
335 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
336 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
337 data.m_Parameters.m_NormChannelType = normChannel;
338 data.m_Parameters.m_NormMethodType = normMethod;
339 data.m_Parameters.m_NormSize = normSize;
340 data.m_Parameters.m_Alpha = alpha;
341 data.m_Parameters.m_Beta = beta;
342 data.m_Parameters.m_K = kappa;
343
Finn Williams826a5432020-08-27 16:15:20 +0100344 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refTensorHandleFactory.CreateTensorHandle(outputTensorInfo);
345 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refTensorHandleFactory.CreateTensorHandle(inputTensorInfo);
telsoa014fcda012018-03-09 14:13:49 +0000346
347 armnn::NormalizationQueueDescriptor refData = data;
348 armnn::WorkloadInfo refInfo = info;
349 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
350 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
351
352 // Don't execute if Normalization is not supported for the method and channel types, as an exception will be raised.
David Beck79141b92018-10-23 16:09:36 +0100353 armnn::BackendId backend = workloadFactory.GetBackendId();
Francis Murtaghb28e5252022-02-09 14:36:04 +0000354 auto handle = armnn::GetILayerSupportByBackendId(backend);
355 ret.m_Supported = handle.IsNormalizationSupported(inputTensorInfo, outputTensorInfo, data.m_Parameters);
356
Sadik Armagan483c8112021-06-01 09:24:52 +0100357 if (!ret.m_Supported)
telsoa014fcda012018-03-09 14:13:49 +0000358 {
359 return ret;
360 }
361
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000362 std::unique_ptr<armnn::IWorkload> workload
363 = workloadFactory.CreateWorkload(armnn::LayerType::Normalization, data, info);
364 std::unique_ptr<armnn::IWorkload> workloadRef
365 = refWorkloadFactory.CreateWorkload(armnn::LayerType::Normalization, refData, refInfo);
telsoa014fcda012018-03-09 14:13:49 +0000366
367 outputHandleRef->Allocate();
368 inputHandleRef->Allocate();
369
370 inputHandle->Allocate();
371 outputHandle->Allocate();
372
Sadik Armagan483c8112021-06-01 09:24:52 +0100373 CopyDataToITensorHandle(inputHandle.get(), input.data());
374 CopyDataToITensorHandle(inputHandleRef.get(), input.data());
telsoa014fcda012018-03-09 14:13:49 +0000375
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000376 ExecuteWorkload(*workload, memoryManager);
Aron Virginas-Tar60578952018-10-31 11:04:01 +0000377
telsoa014fcda012018-03-09 14:13:49 +0000378 workloadRef->Execute();
379
Sadik Armagan483c8112021-06-01 09:24:52 +0100380 CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
381 CopyDataFromITensorHandle(expectedOutput.data(), outputHandleRef.get());
382 ret.m_ActualData = actualOutput;
383 ret.m_ExpectedData = expectedOutput;
telsoa014fcda012018-03-09 14:13:49 +0000384
385 return ret;
386}
387
Sadik Armagan483c8112021-06-01 09:24:52 +0100388LayerTestResult<float,4> AcrossChannelNormalizationTestImpl(
389 armnn::IWorkloadFactory& workloadFactory,
390 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
391 const armnn::ITensorHandleFactory& tensorHandleFactory,
392 armnn::NormalizationAlgorithmChannel normChannel,
393 armnn::NormalizationAlgorithmMethod normMethod)
394{
395 const unsigned int inputHeight = 1;
396 const unsigned int inputWidth = 2;
397 const unsigned int inputChannels = 3;
398 const unsigned int inputNum = 2;
399
400 unsigned int outputHeight = inputHeight;
401 unsigned int outputWidth = inputWidth;
402 unsigned int outputChannels = inputChannels;
403 unsigned int outputNum = inputNum;
404
405 unsigned int inputShape[] = { inputNum, inputHeight, inputWidth, inputChannels };
406 unsigned int outputShape[] = { outputNum, outputHeight, outputWidth, outputChannels };
407
408 auto inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::DataType::Float32);
409 auto outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::DataType::Float32);
410
411 std::vector<float> input =
412 {
413 // Batch #0
414 -2.1f, 2.6f, 1.7f, 1.2f, -1.0f, 0.7f,
415 // Batch #1
416 -2.1f, 2.6f, 1.7f, 1.2f, -1.0f, 0.7f,
417 };
418
419 std::vector<float> actualOutput(outputTensorInfo.GetNumElements());
420 std::vector<float> expectedOutput(outputTensorInfo.GetNumElements());
421
422 float alpha = 4.f;
423 float beta = 0.5f;
424 float kappa = 9.f;
425 uint32_t normSize = 5;
426
427 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
428 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
429
430 armnn::NormalizationQueueDescriptor data;
431 armnn::WorkloadInfo info;
432 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
433 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
434 data.m_Parameters.m_NormChannelType = normChannel;
435 data.m_Parameters.m_NormMethodType = normMethod;
436 data.m_Parameters.m_NormSize = normSize;
437 data.m_Parameters.m_Alpha = alpha;
438 data.m_Parameters.m_Beta = beta;
439 data.m_Parameters.m_K = kappa;
440 data.m_Parameters.m_DataLayout = armnn::DataLayout::NHWC;
441
442 armnn::PassthroughTensorHandle refHandle(outputTensorInfo, expectedOutput.data());
443 armnn::NormalizationQueueDescriptor refData = data;
444 armnn::WorkloadInfo refInfo = info;
445 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, &refHandle);
446
Teresa Charlin611c7fb2022-01-07 09:47:29 +0000447 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Normalization,
448 data,
449 info);
Sadik Armagan483c8112021-06-01 09:24:52 +0100450
451 inputHandle->Allocate();
452 outputHandle->Allocate();
453
454 CopyDataToITensorHandle(inputHandle.get(), input.data());
455
456 ExecuteWorkload(*workload, memoryManager);
457
458 CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
459
460 switch (normMethod)
461 {
462 case armnn::NormalizationAlgorithmMethod::LocalBrightness:
463 {
464 switch (normChannel)
465 {
466 case armnn::NormalizationAlgorithmChannel::Across:
467 {
468 expectedOutput = { -0.259993f, 0.321897f, 0.210471f, 0.263625f, -0.219687f, 0.153781f,
469 -0.259993f, 0.321897f, 0.210471f, 0.263625f, -0.219687f, 0.153781f, };
470 break;
471 }
472 default:
473 {
474 throw armnn::UnimplementedException("Unsupported normalisation channel type, "
475 "only Across and Within are supported");
476 }
477 }
478 break;
479 }
480 case armnn::NormalizationAlgorithmMethod::LocalContrast: // NOTE: intentional fallthrough.
481 default:
482 {
483 throw armnn::UnimplementedException("Unsupported normalisation method type, "
484 "only LocalBrightness is supported");
485 }
486 }
487
488 return LayerTestResult<float, 4>(actualOutput,
489 expectedOutput,
490 outputHandle->GetShape(),
491 outputTensorInfo.GetShape());
492}
493
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100494} // anonymous namespace
495
496LayerTestResult<float,4> SimpleNormalizationAcrossTest(
497 armnn::IWorkloadFactory& workloadFactory,
Finn Williams826a5432020-08-27 16:15:20 +0100498 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
499 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100500{
501 auto normMethod = armnn::NormalizationAlgorithmMethod::LocalBrightness;
502 auto normChannel = armnn::NormalizationAlgorithmChannel::Across;
Finn Williams826a5432020-08-27 16:15:20 +0100503 return SimpleNormalizationTestImpl(workloadFactory, memoryManager, tensorHandleFactory, normChannel, normMethod);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100504}
505
506LayerTestResult<float,4> SimpleNormalizationWithinTest(
507 armnn::IWorkloadFactory& workloadFactory,
Finn Williams826a5432020-08-27 16:15:20 +0100508 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
509 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100510{
511 auto normMethod = armnn::NormalizationAlgorithmMethod::LocalBrightness;
512 auto normChannel = armnn::NormalizationAlgorithmChannel::Within;
Finn Williams826a5432020-08-27 16:15:20 +0100513 return SimpleNormalizationTestImpl(workloadFactory, memoryManager, tensorHandleFactory, normChannel, normMethod);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100514}
515
516LayerTestResult<float,4> SimpleNormalizationAcrossNhwcTest(
517 armnn::IWorkloadFactory& workloadFactory,
Finn Williams826a5432020-08-27 16:15:20 +0100518 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
519 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100520{
521 auto normMethod = armnn::NormalizationAlgorithmMethod::LocalBrightness;
522 auto normChannel = armnn::NormalizationAlgorithmChannel::Across;
Finn Williams826a5432020-08-27 16:15:20 +0100523 return SimpleNormalizationNhwcTestImpl(
524 workloadFactory, memoryManager, tensorHandleFactory, normChannel, normMethod);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100525}
526
527LayerTestResult<float,4> CompareNormalizationTest(
528 armnn::IWorkloadFactory& workloadFactory,
529 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
530 armnn::IWorkloadFactory& refWorkloadFactory,
Finn Williams826a5432020-08-27 16:15:20 +0100531 const armnn::ITensorHandleFactory& tensorHandleFactory,
532 const armnn::ITensorHandleFactory& refTensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100533 armnn::NormalizationAlgorithmChannel normChannel,
534 armnn::NormalizationAlgorithmMethod normMethod)
535{
Finn Williams826a5432020-08-27 16:15:20 +0100536 return CompareNormalizationTestImpl(
537 workloadFactory, memoryManager, refWorkloadFactory, tensorHandleFactory, refTensorHandleFactory,
538 normChannel, normMethod);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100539}
Sadik Armagan483c8112021-06-01 09:24:52 +0100540
541LayerTestResult<float,4> AcrossChannelNormalizationTest(
542 armnn::IWorkloadFactory& workloadFactory,
543 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
544 const armnn::ITensorHandleFactory& tensorHandleFactory)
545{
546 auto normMethod = armnn::NormalizationAlgorithmMethod::LocalBrightness;
547 auto normChannel = armnn::NormalizationAlgorithmChannel::Across;
548 return AcrossChannelNormalizationTestImpl(workloadFactory,
549 memoryManager,
550 tensorHandleFactory,
551 normChannel,
552 normMethod);
553}