blob: 90bc8d76c1f88da6938e01536c03e5e2db2c6828 [file] [log] [blame]
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001//
Teresa Charlinfbf0e5b2020-08-17 01:01:06 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003// SPDX-License-Identifier: MIT
4//
5
6#include "BatchNormalizationTestImpl.hpp"
7
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01008#include <QuantizeHelper.hpp>
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01009#include <ResolveType.hpp>
10
Jan Eilers8eb25602020-03-09 12:13:48 +000011#include <armnn/utility/IgnoreUnused.hpp>
Matteo Martincighe011d202019-11-28 11:35:47 +000012#include <armnnUtils/DataLayoutIndexed.hpp>
13
James Conroy1f58f032021-04-27 17:13:27 +010014#include <backendsCommon/TensorHandle.hpp>
Matteo Martincighe5b8eb92019-11-28 15:45:42 +000015#include <armnn/backends/IBackendInternal.hpp>
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010016#include <backendsCommon/WorkloadFactory.hpp>
Keith Davis33a626f2020-08-27 15:38:12 +010017#include <reference/test/RefWorkloadFactoryHelper.hpp>
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010018
Sadik Armagana097d2a2021-11-24 15:47:28 +000019#include <armnnTestUtils/TensorCopyUtils.hpp>
20#include <WorkloadTestUtils.hpp>
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010021
Sadik Armagana097d2a2021-11-24 15:47:28 +000022#include <TensorHelpers.hpp>
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010023
24namespace
25{
26
Aron Virginas-Tar48623a02019-10-22 10:00:28 +010027using namespace armnnUtils;
28
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010029template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
30LayerTestResult<T, 4> BatchNormTestImpl(
31 armnn::IWorkloadFactory& workloadFactory,
32 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +010033 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010034 const armnn::TensorShape& inputOutputTensorShape,
35 const std::vector<float>& inputValues,
36 const std::vector<float>& expectedOutputValues,
37 float qScale,
38 int32_t qOffset,
39 armnn::DataLayout dataLayout)
40{
Jan Eilers8eb25602020-03-09 12:13:48 +000041 IgnoreUnused(memoryManager);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010042 armnn::TensorInfo inputTensorInfo(inputOutputTensorShape, ArmnnType);
43 armnn::TensorInfo outputTensorInfo(inputOutputTensorShape, ArmnnType);
44
45 armnnUtils::DataLayoutIndexed dataLayoutIndexed(dataLayout);
46
47 armnn::TensorInfo tensorInfo({ inputOutputTensorShape[dataLayoutIndexed.GetChannelsIndex()] },
48 ArmnnType);
49
50 // Set quantization parameters if the requested type is a quantized type.
51 if (armnn::IsQuantizedType<T>())
52 {
53 inputTensorInfo.SetQuantizationScale(qScale);
54 inputTensorInfo.SetQuantizationOffset(qOffset);
55 outputTensorInfo.SetQuantizationScale(qScale);
56 outputTensorInfo.SetQuantizationOffset(qOffset);
57 tensorInfo.SetQuantizationScale(qScale);
58 tensorInfo.SetQuantizationOffset(qOffset);
59 }
60
Sadik Armagan483c8112021-06-01 09:24:52 +010061 auto inputTensor = QuantizedVector<T>(inputValues, qScale, qOffset);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010062
63 // These values are per-channel of the input.
Sadik Armagan483c8112021-06-01 09:24:52 +010064 auto mean = QuantizedVector<T>({ 3, -2 }, qScale, qOffset);
65 auto variance = QuantizedVector<T>({ 4, 9 }, qScale, qOffset);
66 auto beta = QuantizedVector<T>({ 3, 2 }, qScale, qOffset);
67 auto gamma = QuantizedVector<T>({ 2, 1 }, qScale, qOffset);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010068
Sadik Armagan483c8112021-06-01 09:24:52 +010069 std::vector<T> actualOutput(outputTensorInfo.GetNumElements());
70 std::vector<T> expectedOutput = QuantizedVector<T>(expectedOutputValues, qScale, qOffset);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010071
Keith Davis33a626f2020-08-27 15:38:12 +010072 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
73 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010074
James Conroy1f58f032021-04-27 17:13:27 +010075 armnn::ScopedTensorHandle meanTensor(tensorInfo);
76 armnn::ScopedTensorHandle varianceTensor(tensorInfo);
77 armnn::ScopedTensorHandle betaTensor(tensorInfo);
78 armnn::ScopedTensorHandle gammaTensor(tensorInfo);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010079
80 armnn::BatchNormalizationQueueDescriptor descriptor;
81 descriptor.m_Mean = &meanTensor;
82 descriptor.m_Variance = &varianceTensor;
83 descriptor.m_Beta = &betaTensor;
84 descriptor.m_Gamma = &gammaTensor;
85 descriptor.m_Parameters.m_Eps = 0.0f;
86 descriptor.m_Parameters.m_DataLayout = dataLayout;
87 armnn::WorkloadInfo info;
88
Sadik Armagan483c8112021-06-01 09:24:52 +010089 AllocateAndCopyDataToITensorHandle(&meanTensor, mean.data());
90 AllocateAndCopyDataToITensorHandle(&varianceTensor, variance.data());
91 AllocateAndCopyDataToITensorHandle(&betaTensor, beta.data());
92 AllocateAndCopyDataToITensorHandle(&gammaTensor, gamma.data());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010093
94 AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
95 AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
96
97 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateBatchNormalization(descriptor, info);
98
99 inputHandle->Allocate();
100 outputHandle->Allocate();
101
Sadik Armagan483c8112021-06-01 09:24:52 +0100102 CopyDataToITensorHandle(inputHandle.get(), inputTensor.data());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100103
104 workload->Execute();
105
Sadik Armagan483c8112021-06-01 09:24:52 +0100106 CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100107
Sadik Armagan483c8112021-06-01 09:24:52 +0100108 return LayerTestResult<T, 4>(actualOutput,
109 expectedOutput,
110 outputHandle->GetShape(),
111 outputTensorInfo.GetShape());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100112}
113
114template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
115LayerTestResult<T,4> BatchNormTestNhwcImpl(
116 armnn::IWorkloadFactory& workloadFactory,
117 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +0100118 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100119 float qScale,
120 int32_t qOffset)
121{
Jan Eilers8eb25602020-03-09 12:13:48 +0000122 IgnoreUnused(memoryManager);
Derek Lambertic374ff02019-12-10 21:57:35 +0000123
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100124 const unsigned int width = 2;
125 const unsigned int height = 3;
126 const unsigned int channels = 2;
127 const unsigned int num = 1;
128
129 armnn::TensorInfo inputTensorInfo({num, height, width, channels}, ArmnnType);
130 armnn::TensorInfo outputTensorInfo({num, height, width, channels}, ArmnnType);
131 armnn::TensorInfo tensorInfo({channels}, ArmnnType);
132
133 // Set quantization parameters if the requested type is a quantized type.
134 if(armnn::IsQuantizedType<T>())
135 {
136 inputTensorInfo.SetQuantizationScale(qScale);
137 inputTensorInfo.SetQuantizationOffset(qOffset);
138 outputTensorInfo.SetQuantizationScale(qScale);
139 outputTensorInfo.SetQuantizationOffset(qOffset);
140 tensorInfo.SetQuantizationScale(qScale);
141 tensorInfo.SetQuantizationOffset(qOffset);
142 }
143
Sadik Armagan483c8112021-06-01 09:24:52 +0100144 auto input = QuantizedVector<T>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100145 {
146 1.f, 1.f, 4.f, 1.f,
147 4.f, 4.f, 2.f, 1.f,
148 1.f, -2.f, 6.f, 4.f
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100149 },
Sadik Armagan483c8112021-06-01 09:24:52 +0100150 qScale, qOffset);
151
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100152 // These values are per-channel of the input.
Sadik Armagan483c8112021-06-01 09:24:52 +0100153 auto mean = QuantizedVector<T>({ 3, -2 }, qScale, qOffset);
154 auto variance = QuantizedVector<T>({ 4, 9 }, qScale, qOffset);
155 auto beta = QuantizedVector<T>({ 3, 2 }, qScale, qOffset);
156 auto gamma = QuantizedVector<T>({ 2, 1 }, qScale, qOffset);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100157
Keith Davis33a626f2020-08-27 15:38:12 +0100158 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
159 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100160
161 armnn::BatchNormalizationQueueDescriptor data;
162 armnn::WorkloadInfo info;
James Conroy1f58f032021-04-27 17:13:27 +0100163 armnn::ScopedTensorHandle meanTensor(tensorInfo);
164 armnn::ScopedTensorHandle varianceTensor(tensorInfo);
165 armnn::ScopedTensorHandle betaTensor(tensorInfo);
166 armnn::ScopedTensorHandle gammaTensor(tensorInfo);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100167
168 AllocateAndCopyDataToITensorHandle(&meanTensor, &mean[0]);
169 AllocateAndCopyDataToITensorHandle(&varianceTensor, &variance[0]);
170 AllocateAndCopyDataToITensorHandle(&betaTensor, &beta[0]);
171 AllocateAndCopyDataToITensorHandle(&gammaTensor, &gamma[0]);
172
173 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
174 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
175 data.m_Mean = &meanTensor;
176 data.m_Variance = &varianceTensor;
177 data.m_Beta = &betaTensor;
178 data.m_Gamma = &gammaTensor;
179 data.m_Parameters.m_Eps = 0.0f;
180 data.m_Parameters.m_DataLayout = armnn::DataLayout::NHWC;
181
Sadik Armagan483c8112021-06-01 09:24:52 +0100182 std::vector<T> actualOutput(outputTensorInfo.GetNumElements());
183
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100184 // For each channel:
185 // substract mean, divide by standard deviation (with an epsilon to avoid div by 0),
186 // multiply by gamma and add beta
Sadik Armagan483c8112021-06-01 09:24:52 +0100187 std::vector<T> expectedOutput = QuantizedVector<T>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100188 {
189 1.f, 3.f, 4.f, 3.f,
190 4.f, 4.f, 2.f, 3.f,
191 1.f, 2.f, 6.f, 4.f
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100192 },
Sadik Armagan483c8112021-06-01 09:24:52 +0100193 qScale, qOffset);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100194
195 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateBatchNormalization(data, info);
196
197 inputHandle->Allocate();
198 outputHandle->Allocate();
199
Sadik Armagan483c8112021-06-01 09:24:52 +0100200 CopyDataToITensorHandle(inputHandle.get(), input.data());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100201
202 workload->Execute();
203
Sadik Armagan483c8112021-06-01 09:24:52 +0100204 CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100205
Sadik Armagan483c8112021-06-01 09:24:52 +0100206 return LayerTestResult<T, 4>(actualOutput,
207 expectedOutput,
208 outputHandle->GetShape(),
209 outputTensorInfo.GetShape());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100210}
211
212} // anonymous namespace
213
Matthew Jackson9bff1442019-09-12 09:08:23 +0100214LayerTestResult<float, 4> BatchNormFloat32Test(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100215 armnn::IWorkloadFactory& workloadFactory,
Keith Davis33a626f2020-08-27 15:38:12 +0100216 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
217 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100218{
219 // BatchSize: 1
220 // Channels: 2
221 // Height: 3
222 // Width: 2
223
224 const armnn::TensorShape inputOutputShape{ 1, 2, 3, 2 };
225 std::vector<float> inputValues
226 {
227 // Batch 0, Channel 0, Height (3) x Width (2)
228 1.f, 4.f,
229 4.f, 2.f,
230 1.f, 6.f,
231
232 // Batch 0, Channel 1, Height (3) x Width (2)
233 1.f, 1.f,
234 4.f, 1.f,
235 -2.f, 4.f
236 };
237 std::vector<float> expectedOutputValues
238 {
239 // Batch 0, Channel 0, Height (3) x Width (2)
240 1.f, 4.f,
241 4.f, 2.f,
242 1.f, 6.f,
243
244 // Batch 0, Channel 1, Height (3) x Width (2)
245 3.f, 3.f,
246 4.f, 3.f,
247 2.f, 4.f
248 };
249
250 return BatchNormTestImpl<armnn::DataType::Float32>(
251 workloadFactory,
252 memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +0100253 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100254 inputOutputShape,
255 inputValues,
256 expectedOutputValues,
257 0.f,
258 0,
259 armnn::DataLayout::NCHW);
260}
261
Matthew Jackson9bff1442019-09-12 09:08:23 +0100262LayerTestResult<float, 4> BatchNormFloat32NhwcTest(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100263 armnn::IWorkloadFactory& workloadFactory,
Keith Davis33a626f2020-08-27 15:38:12 +0100264 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
265 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100266{
267 // BatchSize: 1
268 // Height: 3
269 // Width: 2
270 // Channels: 2
271
272 const armnn::TensorShape inputOutputShape{ 1, 3, 2, 2 };
273 std::vector<float> inputValues
274 {
275 // Batch 0, Height 0, Width (2) x Channel (2)
276 1.f, 1.f,
277 4.f, 1.f,
278
279 // Batch 0, Height 1, Width (2) x Channel (2)
280 4.f, 4.f,
281 2.f, 1.f,
282
283 // Batch 0, Height 2, Width (2) x Channel (2)
284 1.f, -2.f,
285 6.f, 4.f
286 };
287 std::vector<float> expectedOutputValues
288 {
289 // Batch 0, Height 0, Width (2) x Channel (2)
290 1.f, 3.f,
291 4.f, 3.f,
292
293 // Batch 0, Height 1, Width (2) x Channel (2)
294 4.f, 4.f,
295 2.f, 3.f,
296
297 // Batch 0, Height 2, Width (2) x Channel (2)
298 1.f, 2.f,
299 6.f, 4.f
300 };
301
302 return BatchNormTestImpl<armnn::DataType::Float32>(
303 workloadFactory,
304 memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +0100305 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100306 inputOutputShape,
307 inputValues,
308 expectedOutputValues,
309 0.f,
310 0,
311 armnn::DataLayout::NHWC);
312}
313
Matthew Jackson9bff1442019-09-12 09:08:23 +0100314LayerTestResult<armnn::Half, 4> BatchNormFloat16Test(
315 armnn::IWorkloadFactory& workloadFactory,
Keith Davis33a626f2020-08-27 15:38:12 +0100316 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
317 const armnn::ITensorHandleFactory& tensorHandleFactory)
Matthew Jackson9bff1442019-09-12 09:08:23 +0100318{
319 // BatchSize: 1
320 // Channels: 2
321 // Height: 3
322 // Width: 2
323
324 const armnn::TensorShape inputOutputShape{ 1, 2, 3, 2 };
325 std::vector<float> inputValues
326 {
327 // Batch 0, Channel 0, Height (3) x Width (2)
328 1.f, 4.f,
329 4.f, 2.f,
330 1.f, 6.f,
331
332 // Batch 0, Channel 1, Height (3) x Width (2)
333 1.f, 1.f,
334 4.f, 1.f,
335 -2.f, 4.f
336 };
337 std::vector<float> expectedOutputValues
338 {
339 // Batch 0, Channel 0, Height (3) x Width (2)
340 1.f, 4.f,
341 4.f, 2.f,
342 1.f, 6.f,
343
344 // Batch 0, Channel 1, Height (3) x Width (2)
345 3.f, 3.f,
346 4.f, 3.f,
347 2.f, 4.f
348 };
349
350 return BatchNormTestImpl<armnn::DataType::Float16>(
351 workloadFactory,
352 memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +0100353 tensorHandleFactory,
Matthew Jackson9bff1442019-09-12 09:08:23 +0100354 inputOutputShape,
355 inputValues,
356 expectedOutputValues,
357 0.f,
358 0,
359 armnn::DataLayout::NCHW);
360}
361
362LayerTestResult<armnn::Half, 4> BatchNormFloat16NhwcTest(
363 armnn::IWorkloadFactory& workloadFactory,
Keith Davis33a626f2020-08-27 15:38:12 +0100364 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
365 const armnn::ITensorHandleFactory& tensorHandleFactory)
Matthew Jackson9bff1442019-09-12 09:08:23 +0100366{
367 // BatchSize: 1
368 // Height: 3
369 // Width: 2
370 // Channels: 2
371
372 const armnn::TensorShape inputOutputShape{ 1, 3, 2, 2 };
373 std::vector<float> inputValues
374 {
375 // Batch 0, Height 0, Width (2) x Channel (2)
376 1.f, 1.f,
377 4.f, 1.f,
378
379 // Batch 0, Height 1, Width (2) x Channel (2)
380 4.f, 4.f,
381 2.f, 1.f,
382
383 // Batch 0, Height 2, Width (2) x Channel (2)
384 1.f, -2.f,
385 6.f, 4.f
386 };
387 std::vector<float> expectedOutputValues
388 {
389 // Batch 0, Height 0, Width (2) x Channel (2)
390 1.f, 3.f,
391 4.f, 3.f,
392
393 // Batch 0, Height 1, Width (2) x Channel (2)
394 4.f, 4.f,
395 2.f, 3.f,
396
397 // Batch 0, Height 2, Width (2) x Channel (2)
398 1.f, 2.f,
399 6.f, 4.f
400 };
401
402 return BatchNormTestImpl<armnn::DataType::Float16>(
403 workloadFactory,
404 memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +0100405 tensorHandleFactory,
Matthew Jackson9bff1442019-09-12 09:08:23 +0100406 inputOutputShape,
407 inputValues,
408 expectedOutputValues,
409 0.f,
410 0,
411 armnn::DataLayout::NHWC);
412}
413
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100414LayerTestResult<uint8_t, 4> BatchNormUint8Test(
415 armnn::IWorkloadFactory& workloadFactory,
Keith Davis33a626f2020-08-27 15:38:12 +0100416 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
417 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100418{
419 // BatchSize: 1
420 // Channels: 2
421 // Height: 3
422 // Width: 2
423
424 const armnn::TensorShape inputOutputShape{ 1, 2, 3, 2 };
425 std::vector<float> inputValues
426 {
427 // Batch 0, Channel 0, Height (3) x Width (2)
428 1.f, 4.f,
429 4.f, 2.f,
430 1.f, 6.f,
431
432 // Batch 0, Channel 1, Height (3) x Width (2)
433 1.f, 1.f,
434 4.f, 1.f,
435 -2.f, 4.f
436 };
437 std::vector<float> expectedOutputValues
438 {
439 // Batch 0, Channel 0, Height (3) x Width (2)
440 1.f, 4.f,
441 4.f, 2.f,
442 1.f, 6.f,
443
444 // Batch 0, Channel 1, Height (3) x Width (2)
445 3.f, 3.f,
446 4.f, 3.f,
447 2.f, 4.f
448 };
449
Derek Lambertif90c56d2020-01-10 17:14:08 +0000450 return BatchNormTestImpl<armnn::DataType::QAsymmU8>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100451 workloadFactory,
452 memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +0100453 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100454 inputOutputShape,
455 inputValues,
456 expectedOutputValues,
457 1.f / 20.f,
458 50,
459 armnn::DataLayout::NCHW);
460}
461
462LayerTestResult<uint8_t, 4> BatchNormUint8NhwcTest(
463 armnn::IWorkloadFactory& workloadFactory,
Keith Davis33a626f2020-08-27 15:38:12 +0100464 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
465 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100466{
467 // BatchSize: 1
468 // Height: 3
469 // Width: 2
470 // Channels: 2
471
472 const armnn::TensorShape inputOutputShape{ 1, 3, 2, 2 };
473 std::vector<float> inputValues
474 {
475 // Batch 0, Height 0, Width (2) x Channel (2)
476 1.f, 1.f,
477 4.f, 1.f,
478
479 // Batch 0, Height 1, Width (2) x Channel (2)
480 4.f, 4.f,
481 2.f, 1.f,
482
483 // Batch 0, Height 2, Width (2) x Channel (2)
484 1.f, -2.f,
485 6.f, 4.f
486 };
487 std::vector<float> expectedOutputValues
488 {
489 // Batch 0, Height 0, Width (2) x Channel (2)
490 1.f, 3.f,
491 4.f, 3.f,
492
493 // Batch 0, Height 1, Width (2) x Channel (2)
494 4.f, 4.f,
495 2.f, 3.f,
496
497 // Batch 0, Height 2, Width (2) x Channel (2)
498 1.f, 2.f,
499 6.f, 4.f
500 };
501
Derek Lambertif90c56d2020-01-10 17:14:08 +0000502 return BatchNormTestImpl<armnn::DataType::QAsymmU8>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100503 workloadFactory,
504 memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +0100505 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100506 inputOutputShape, inputValues, expectedOutputValues,
507 1.f/20.f, 50, armnn::DataLayout::NHWC);
508}
509
510LayerTestResult<int16_t, 4> BatchNormInt16Test(
511 armnn::IWorkloadFactory& workloadFactory,
Keith Davis33a626f2020-08-27 15:38:12 +0100512 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
513 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100514{
515 // BatchSize: 1
516 // Channels: 2
517 // Height: 3
518 // Width: 2
519
520 const armnn::TensorShape inputOutputShape{ 1, 2, 3, 2 };
521 std::vector<float> inputValues
522 {
523 // Batch 0, Channel 0, Height (3) x Width (2)
524 1.f, 4.f,
525 4.f, 2.f,
526 1.f, 6.f,
527
528 // Batch 0, Channel 1, Height (3) x Width (2)
529 1.f, 1.f,
530 4.f, 1.f,
531 -2.f, 4.f
532 };
533 std::vector<float> expectedOutputValues
534 {
535 // Batch 0, Channel 0, Height (3) x Width (2)
536 1.f, 4.f,
537 4.f, 2.f,
538 1.f, 6.f,
539
540 // Batch 0, Channel 1, Height (3) x Width (2)
541 3.f, 3.f,
542 4.f, 3.f,
543 2.f, 4.f
544 };
545
Derek Lambertif90c56d2020-01-10 17:14:08 +0000546 return BatchNormTestImpl<armnn::DataType::QSymmS16>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100547 workloadFactory,
548 memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +0100549 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100550 inputOutputShape,
551 inputValues,
552 expectedOutputValues,
553 1.f / 20.f,
554 50,
555 armnn::DataLayout::NCHW);
556}
557
558LayerTestResult<int16_t, 4> BatchNormInt16NhwcTest(
559 armnn::IWorkloadFactory& workloadFactory,
Keith Davis33a626f2020-08-27 15:38:12 +0100560 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
561 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100562{
563 // BatchSize: 1
564 // Height: 3
565 // Width: 2
566 // Channels: 2
567
568 const armnn::TensorShape inputOutputShape{ 1, 3, 2, 2 };
569 std::vector<float> inputValues
570 {
571 // Batch 0, Height 0, Width (2) x Channel (2)
572 1.f, 1.f,
573 4.f, 1.f,
574
575 // Batch 0, Height 1, Width (2) x Channel (2)
576 4.f, 4.f,
577 2.f, 1.f,
578
579 // Batch 0, Height 2, Width (2) x Channel (2)
580 1.f, -2.f,
581 6.f, 4.f
582 };
583 std::vector<float> expectedOutputValues
584 {
585 // Batch 0, Height 0, Width (2) x Channel (2)
586 1.f, 3.f,
587 4.f, 3.f,
588
589 // Batch 0, Height 1, Width (2) x Channel (2)
590 4.f, 4.f,
591 2.f, 3.f,
592
593 // Batch 0, Height 2, Width (2) x Channel (2)
594 1.f, 2.f,
595 6.f, 4.f
596 };
597
Derek Lambertif90c56d2020-01-10 17:14:08 +0000598 return BatchNormTestImpl<armnn::DataType::QSymmS16>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100599 workloadFactory,
600 memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +0100601 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100602 inputOutputShape,
603 inputValues,
604 expectedOutputValues,
605 1.f / 20.f,
606 50,
607 armnn::DataLayout::NHWC);
608}
609
610LayerTestResult<float,4> CompareBatchNormTest(
611 armnn::IWorkloadFactory& workloadFactory,
612 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davis33a626f2020-08-27 15:38:12 +0100613 armnn::IWorkloadFactory& refWorkloadFactory,
614 const armnn::ITensorHandleFactory& tensorHandleFactory,
615 const armnn::ITensorHandleFactory& refTensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100616{
Jan Eilers8eb25602020-03-09 12:13:48 +0000617 IgnoreUnused(memoryManager);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100618 const unsigned int width = 2;
619 const unsigned int height = 3;
620 const unsigned int channels = 5;
621 const unsigned int batchSize = 3;
622
623 armnn::TensorInfo inputTensorInfo;
624 armnn::TensorInfo outputTensorInfo;
625 armnn::TensorInfo tensorInfo;
626
627 constexpr unsigned int shape[] = {batchSize, channels, height, width};
628 constexpr unsigned int tensorShape[] = {channels};
629
630 inputTensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
631 outputTensorInfo = armnn::TensorInfo(4, shape, armnn::DataType::Float32);
632 tensorInfo = armnn::TensorInfo(1, tensorShape, armnn::DataType::Float32);
633
Sadik Armagan483c8112021-06-01 09:24:52 +0100634 auto input = MakeRandomTensor<float>(inputTensorInfo, 21312);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100635
Sadik Armagan483c8112021-06-01 09:24:52 +0100636 auto mean = MakeRandomTensor<float>(tensorInfo, 123);
637 auto variance = MakeRandomTensor<float>(tensorInfo, 234, 0.0f);
638 auto beta = MakeRandomTensor<float>(tensorInfo, 123);
639 auto gamma = MakeRandomTensor<float>(tensorInfo, 345);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100640
Sadik Armagan483c8112021-06-01 09:24:52 +0100641 std::vector<float> actualOutput(outputTensorInfo.GetNumElements());
642 std::vector<float> expectedOutput(outputTensorInfo.GetNumElements());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100643
Keith Davis33a626f2020-08-27 15:38:12 +0100644 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
645 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100646
Keith Davis33a626f2020-08-27 15:38:12 +0100647 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refTensorHandleFactory.CreateTensorHandle(inputTensorInfo);
648 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refTensorHandleFactory.CreateTensorHandle(outputTensorInfo);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100649
650 armnn::BatchNormalizationQueueDescriptor data;
651 armnn::WorkloadInfo info;
James Conroy1f58f032021-04-27 17:13:27 +0100652 armnn::ScopedTensorHandle meanTensor(tensorInfo);
653 armnn::ScopedTensorHandle varianceTensor(tensorInfo);
654 armnn::ScopedTensorHandle betaTensor(tensorInfo);
655 armnn::ScopedTensorHandle gammaTensor(tensorInfo);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100656
657 AllocateAndCopyDataToITensorHandle(&meanTensor, &mean[0]);
658 AllocateAndCopyDataToITensorHandle(&varianceTensor, &variance[0]);
659 AllocateAndCopyDataToITensorHandle(&betaTensor, &beta[0]);
660 AllocateAndCopyDataToITensorHandle(&gammaTensor, &gamma[0]);
661
662 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
663 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
664 data.m_Mean = &meanTensor;
665 data.m_Variance = &varianceTensor;
666 data.m_Beta = &betaTensor;
667 data.m_Gamma = &gammaTensor;
668 data.m_Parameters.m_Eps = 0.01f;
669
670 armnn::BatchNormalizationQueueDescriptor refData = data;
671 armnn::WorkloadInfo refInfo = info;
672 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
673 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
674
675 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateBatchNormalization(data, info);
676 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateBatchNormalization(refData, refInfo);
677
678 inputHandle->Allocate();
679 outputHandle->Allocate();
680 inputHandleRef->Allocate();
681 outputHandleRef->Allocate();
682
Sadik Armagan483c8112021-06-01 09:24:52 +0100683 CopyDataToITensorHandle(inputHandle.get(), input.data());
684 CopyDataToITensorHandle(inputHandleRef.get(), input.data());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100685
686 workload->PostAllocationConfigure();
687 workload->Execute();
688 workloadRef->PostAllocationConfigure();
689 workloadRef->Execute();
690
Sadik Armagan483c8112021-06-01 09:24:52 +0100691 CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
692 CopyDataFromITensorHandle(expectedOutput.data(), outputHandleRef.get());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100693
Sadik Armagan483c8112021-06-01 09:24:52 +0100694 return LayerTestResult<float, 4>(actualOutput,
695 expectedOutput,
696 outputHandle->GetShape(),
697 outputTensorInfo.GetShape());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100698}