blob: c87548cd5b0b1efa9bb3465755d0ac5b263fbc3c [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5#pragma once
6
7#include <armnn/ArmNN.hpp>
8#include <armnn/Tensor.hpp>
9#include <armnn/TypesUtils.hpp>
telsoa014fcda012018-03-09 14:13:49 +000010
David Beckac42efd2018-09-26 17:41:13 +010011#include <test/TensorHelpers.hpp>
telsoa014fcda012018-03-09 14:13:49 +000012#include "QuantizeHelper.hpp"
13
David Beckac42efd2018-09-26 17:41:13 +010014#include <backends/CpuTensorHandle.hpp>
15#include <backends/WorkloadFactory.hpp>
telsoa014fcda012018-03-09 14:13:49 +000016
17#include <algorithm>
18
19template<typename T>
20LayerTestResult<T, 4> SimplePooling2dTestImpl(
21 armnn::IWorkloadFactory& workloadFactory,
22 armnn::Pooling2dDescriptor descriptor,
23 float qScale,
24 int32_t qOffset,
25 const boost::multi_array<T, 4>& input,
26 const boost::multi_array<T, 4>& outputExpected)
27{
28 unsigned int inputHeight = boost::numeric_cast<unsigned int>(input.shape()[2]);
29 unsigned int inputWidth = boost::numeric_cast<unsigned int>(input.shape()[3]);
30 unsigned int inputChannels = boost::numeric_cast<unsigned int>(input.shape()[1]);
31 unsigned int inputBatchSize = boost::numeric_cast<unsigned int>(input.shape()[0]);
32
33 unsigned int outputHeight = boost::numeric_cast<unsigned int>(outputExpected.shape()[2]);
34 unsigned int outputWidth = boost::numeric_cast<unsigned int>(outputExpected.shape()[3]);
35 unsigned int outputChannels = boost::numeric_cast<unsigned int>(outputExpected.shape()[1]);
36 unsigned int outputBatchSize = boost::numeric_cast<unsigned int>(outputExpected.shape()[0]);
37
38 armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
39 armnn::GetDataType<T>());
40 armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
41 armnn::GetDataType<T>());
42
43 // Set quantization parameters if the requested type is a quantized type.
44 if(armnn::IsQuantizedType<T>())
45 {
46 inputTensorInfo.SetQuantizationScale(qScale);
47 inputTensorInfo.SetQuantizationOffset(qOffset);
48 outputTensorInfo.SetQuantizationScale(qScale);
49 outputTensorInfo.SetQuantizationOffset(qOffset);
50 }
51
52 LayerTestResult<T, 4> result(outputTensorInfo);
53
54 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
55 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
56
57 armnn::Pooling2dQueueDescriptor queueDescriptor;
58 queueDescriptor.m_Parameters = descriptor;
59 armnn::WorkloadInfo workloadInfo;
60 AddInputToWorkload(queueDescriptor, workloadInfo, inputTensorInfo, inputHandle.get());
61 AddOutputToWorkload(queueDescriptor, workloadInfo, outputTensorInfo, outputHandle.get());
62
63 // Don't execute if Pooling is not supported, as an exception will be raised.
64 armnn::Compute compute = workloadFactory.GetCompute();
65 const size_t reasonIfUnsupportedMaxLen = 255;
66 char reasonIfUnsupported[reasonIfUnsupportedMaxLen+1];
67 result.supported = armnn::IsPooling2dSupported(compute, inputTensorInfo, outputTensorInfo,
68 queueDescriptor.m_Parameters,
69 reasonIfUnsupported, reasonIfUnsupportedMaxLen);
70 if (!result.supported)
71 {
72 return result;
73 }
74
75 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePooling2d(queueDescriptor, workloadInfo);
76
77 inputHandle->Allocate();
78 outputHandle->Allocate();
79
80 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
81
82 workload->Execute();
83
84 CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
85
86 result.outputExpected = outputExpected;
87
88 return result;
89}
90
91//
92// Tests max pooling with the following parameters:
93//
94// Pooling size: 3x3
95// Stride: (2,4)
96// input size: 8x13
97// channels: 2
98// batch size: 2
99//
100template<typename T>
101LayerTestResult<T, 4> SimpleMaxPooling2dSize3x3Stride2x4TestCommon(armnn::IWorkloadFactory& workloadFactory,
102 bool forceNoPadding,
103 float qScale = 1.0f,
104 int32_t qOffset = 0)
105{
106 armnn::Pooling2dDescriptor descriptor;
107 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
108 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
109 descriptor.m_StrideX = 2;
110 descriptor.m_StrideY = 4;
111 // forceNoPadding is mainly used for compatibility with ARM Compute.
112 // As of 16/05/2017, it errors if padX or padY are equal to or greater than the pool size.
113 descriptor.m_PadLeft = descriptor.m_PadRight = forceNoPadding ? 0 : 3;
114 descriptor.m_PadTop = descriptor.m_PadBottom = 0;
115 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
116 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
117
118 unsigned int inputWidth = 8;
119 unsigned int inputHeight = 13;
120 unsigned int outputWidth =
121 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
122 descriptor.m_StrideX;
123 unsigned int outputHeight =
124 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
125 descriptor.m_StrideY;
126 unsigned int channels = 2;
127 unsigned int batchSize = 2;
128
129 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
130 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
131
132 // Set quantization parameters if the requested type is a quantized type.
133 if(armnn::IsQuantizedType<T>())
134 {
135 inputTensorInfo.SetQuantizationScale(qScale);
136 inputTensorInfo.SetQuantizationOffset(qOffset);
137 outputTensorInfo.SetQuantizationScale(qScale);
138 outputTensorInfo.SetQuantizationOffset(qOffset);
139 }
140
141 std::vector<float> singleChannelData({
142 0.0f, 4.0f, 8.0f, 1.0f, 6.0f, 4.0f, 5.0f, 8.0f,
143 1.0f, 1.0f, 6.0f, 0.0f, 3.0f, 7.0f, 4.0f, 7.0f,
144 8.0f, 5.0f, 0.0f, 0.0f, 8.0f, 3.0f, 4.0f, 3.0f,
145 8.0f, 2.0f, 5.0f, 4.0f, 1.0f, 9.0f, 2.0f, 0.0f,
146 5.0f, 4.0f, 5.0f, 0.0f, 0.0f, 0.0f, 7.0f, 2.0f,
147 1.0f, 2.0f, 6.0f, 2.0f, 7.0f, 9.0f, 5.0f, 2.0f,
148 9.0f, 7.0f, 3.0f, 1.0f, 3.0f, 4.0f, 8.0f, 3.0f,
149 1.0f, 0.0f, 0.0f, 5.0f, 5.0f, 4.0f, 2.0f, 0.0f,
150 6.0f, 4.0f, 3.0f, 6.0f, 9.0f, 5.0f, 5.0f, 6.0f,
151 8.0f, 7.0f, 9.0f, 6.0f, 1.0f, 4.0f, 1.0f, 9.0f,
152 7.0f, 1.0f, 9.0f, 2.0f, 9.0f, 9.0f, 8.0f, 1.0f,
153 4.0f, 4.0f, 5.0f, 9.0f, 2.0f, 6.0f, 6.0f, 4.0f,
154 3.0f, 5.0f, 4.0f, 0.0f, 1.0f, 5.0f, 9.0f, 7.0f,
155 });
156
telsoa01c577f2c2018-08-31 09:22:23 +0100157 // Constructs input data.
telsoa014fcda012018-03-09 14:13:49 +0000158 std::vector<float> inputData;
159 auto negator = [](float f) { return -f; };
160
telsoa01c577f2c2018-08-31 09:22:23 +0100161 // First image (two channels where the second channel is the negative of the first one).
telsoa014fcda012018-03-09 14:13:49 +0000162 inputData.insert(inputData.end(), singleChannelData.begin(), singleChannelData.end());
163 std::transform(singleChannelData.begin(), singleChannelData.end(), std::back_inserter(inputData), negator);
164
telsoa01c577f2c2018-08-31 09:22:23 +0100165 // Second image (same as first image).
telsoa014fcda012018-03-09 14:13:49 +0000166 inputData.insert(inputData.end(), singleChannelData.begin(), singleChannelData.end());
167 std::transform(singleChannelData.begin(), singleChannelData.end(), std::back_inserter(inputData), negator);
168
169 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
170
telsoa01c577f2c2018-08-31 09:22:23 +0100171 // These were calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000172 auto shape(GetTensorShapeAsArray<4>(outputTensorInfo));
173 boost::multi_array<T, 4> outputExpected(shape);
174 if (forceNoPadding)
175 {
176 outputExpected = MakeTensor<T, 4>(outputTensorInfo,
177 QuantizedVector<T>(qScale, qOffset, {
178 8.0f, 8.0f, 8.0f,
179 9.0f, 7.0f, 9.0f,
180 9.0f, 9.0f, 9.0f,
181
182 0.0f, 0.0f, -3.0f,
183 -1.0f, 0.0f, 0.0f,
184 -1.0f, -1.0f, -1.0f,
185
186 8.0f, 8.0f, 8.0f,
187 9.0f, 7.0f, 9.0f,
188 9.0f, 9.0f, 9.0f,
189
190 0.0f, 0.0f, -3.0f,
191 -1.0f, 0.0f, 0.0f,
192 -1.0f, -1.0f, -1.0f
193 }));
194 }
195 else
196 {
197 outputExpected = MakeTensor<T, 4>(outputTensorInfo,
198 QuantizedVector<T>(qScale, qOffset, {
199 0.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f,
200 0.0f, 9.0f, 7.0f, 9.0f, 9.0f, 3.0f,
201 0.0f, 8.0f, 9.0f, 9.0f, 9.0f, 9.0f,
202
203 0.0f, 0.0f, 0.0f, 0.0f,-3.0f, 0.0f,
204 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
205 0.0f,-1.0f,-1.0f,-1.0f,-1.0f, 0.0f,
206
207 0.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f,
208 0.0f, 9.0f, 7.0f, 9.0f, 9.0f, 3.0f,
209 0.0f, 8.0f, 9.0f, 9.0f, 9.0f, 9.0f,
210
211 0.0f, 0.0f, 0.0f, 0.0f,-3.0f, 0.0f,
212 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
213 0.0f,-1.0f,-1.0f,-1.0f,-1.0f, 0.0f
214 }));
215 }
216
217 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
218}
219
220template<typename T>
221LayerTestResult<T, 4> SimpleAveragePooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
222 float qScale = 1.0f,
223 int32_t qOffset = 0)
224{
225 armnn::Pooling2dDescriptor descriptor;
226 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
227 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
228 descriptor.m_StrideX = descriptor.m_StrideY = 2;
229 descriptor.m_PadLeft = 1;
230 descriptor.m_PadRight = 1;
231 descriptor.m_PadTop = 1;
232 descriptor.m_PadBottom = 1;
233 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
234
235 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
236 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
237
238 // Set quantization parameters if the requested type is a quantized type.
239 if(armnn::IsQuantizedType<T>())
240 {
241 inputTensorInfo.SetQuantizationScale(qScale);
242 inputTensorInfo.SetQuantizationOffset(qOffset);
243 outputTensorInfo.SetQuantizationScale(qScale);
244 outputTensorInfo.SetQuantizationOffset(qOffset);
245 }
246
247 auto input = MakeTensor<T, 4>(inputTensorInfo,
248 QuantizedVector<T>(qScale, qOffset, {
249 1.0f, 2.0f, 3.0f, 4.0f,
250 1.0f, 2.0f, 3.0f, 4.0f,
251 1.0f, 2.0f, 3.0f, 4.0f,
252 1.0f, 2.0f, 3.0f, 4.0f,
253 }));
254
255 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
256 QuantizedVector<T>(qScale, qOffset, {
257 1.0f, 2.5f, 4.0f,
258 1.0f, 2.5f, 4.0f,
259 1.0f, 2.5f, 4.0f,
260 }));
261
262 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
263}
264
265template<typename T>
266LayerTestResult<T, 4> LargeTensorsAveragePooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
267 float qScale = 1.0f,
268 int32_t qOffset = 0)
269{
270 armnn::Pooling2dDescriptor descriptor;
271 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
272 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 100;
273 descriptor.m_StrideX = descriptor.m_StrideY = 5;
274 descriptor.m_PadLeft = 50;
275 descriptor.m_PadRight = 50;
276 descriptor.m_PadTop = 50;
277 descriptor.m_PadBottom = 50;
278 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
279
280 armnn::TensorInfo inputTensorInfo({ 5, 3, 52, 60 }, armnn::GetDataType<T>());
281 armnn::TensorInfo outputTensorInfo({ 5, 3, 11, 13 }, armnn::GetDataType<T>());
282
283 // Set quantization parameters if the requested type is a quantized type.
284 if(armnn::IsQuantizedType<T>())
285 {
286 inputTensorInfo.SetQuantizationScale(qScale);
287 inputTensorInfo.SetQuantizationOffset(qOffset);
288 outputTensorInfo.SetQuantizationScale(qScale);
289 outputTensorInfo.SetQuantizationOffset(qOffset);
290 }
291
292 std::vector<T> inputVec;
293
294 for (unsigned int i = 0 ; i < inputTensorInfo.GetShape().GetNumElements(); ++i)
295 {
296 inputVec.push_back(1);
297 }
298
299 auto input = MakeTensor<T, 4>(inputTensorInfo, inputVec);
300
301 std::vector<T> outputVec;
302
303 for (unsigned int i = 0 ; i < outputTensorInfo.GetShape().GetNumElements(); ++i)
304 {
305 outputVec.push_back(1);
306 }
307
308 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputVec);
309
310 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
311}
312
313template<typename T>
314LayerTestResult<T, 4> SimpleL2Pooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
315 float qScale = 1.0f,
316 int32_t qOffset = 0)
317{
318 armnn::Pooling2dDescriptor descriptor;
319 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
320 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
321 descriptor.m_StrideX = descriptor.m_StrideY = 2;
322 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
323
324 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
325 auto input = MakeTensor<T, 4>(inputTensorInfo,
326 QuantizedVector<T>(qScale, qOffset, {
327 1.0f, 7.0f, 1.0f, 7.0f,
328 1.0f, 7.0f, 1.0f, 7.0f,
329 1.0f, 7.0f, 1.0f, 7.0f,
330 1.0f, 7.0f, 1.0f, 7.0f,
331 }));
332
333 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
334 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
335 QuantizedVector<T>(qScale, qOffset, {
336 5.0f, 5.0f,
337 5.0f, 5.0f,
338 }));
339
340 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
341}
342
343template<typename T>
344LayerTestResult<T, 4> L2Pooling2dSize3Stride1TestCommon(armnn::IWorkloadFactory& workloadFactory,
345 float qScale = 1.0f,
346 int32_t qOffset = 0)
347{
348 armnn::Pooling2dDescriptor descriptor;
349 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
350 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
351 descriptor.m_StrideX = descriptor.m_StrideY = 1;
352 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
353
354 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
355 auto input = MakeTensor<T, 4>(inputTensorInfo,
356 QuantizedVector<T>(qScale, qOffset, {
357 2.0f, 1.0f, 5.0f, 2.0f,
358 1.0f, 2.0f, 2.0f, 1.0f,
359 5.0f, 4.0f, 1.0f, 5.0f,
360 2.0f, 1.0f, 5.0f, 2.0f,
361 }));
362
363 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
364 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
365 QuantizedVector<T>(qScale, qOffset, {
366 3.0f, 3.0f,
367 3.0f, 3.0f,
368 }));
369
370 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
371}
372
373template<typename T>
374LayerTestResult<T, 4> L2Pooling2dSize3Stride3TestCommon(armnn::IWorkloadFactory& workloadFactory,
375 float qScale = 1.0f,
376 int32_t qOffset = 0)
377{
378 armnn::Pooling2dDescriptor descriptor;
379 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
380 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
381 descriptor.m_StrideX = descriptor.m_StrideY = 3;
382 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
383
384 armnn::TensorInfo inputTensorInfo({ 1, 1, 9, 9 }, armnn::GetDataType<T>());
385 auto input = MakeTensor<T, 4>(inputTensorInfo,
386 QuantizedVector<T>(qScale, qOffset, {
387 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
388 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
389 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
390 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
391 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
392 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
393 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
394 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
395 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
396 }));
397
398 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
399 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
400 QuantizedVector<T>(qScale, qOffset, {
401 3.0f, 3.0f, 3.0f,
402 3.0f, 3.0f, 3.0f,
403 3.0f, 3.0f, 3.0f,
404 }));
405
406 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
407}
408
409template<typename T>
410LayerTestResult<T, 4> L2Pooling2dSize3Stride4TestCommon(armnn::IWorkloadFactory& workloadFactory,
411 float qScale = 1.0f,
412 int32_t qOffset = 0)
413{
414 armnn::Pooling2dDescriptor descriptor;
415 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
416 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
417 descriptor.m_StrideX = descriptor.m_StrideY = 4;
418 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
419
420 armnn::TensorInfo inputTensorInfo({ 1, 1, 7, 7 }, armnn::GetDataType<T>());
421 auto input = MakeTensor<T, 4>(inputTensorInfo,
422 QuantizedVector<T>(qScale, qOffset, {
423 2.0f, 1.0f, 5.0f, 0.0f, 2.0f, 1.0f, 5.0f,
424 1.0f, 2.0f, 2.0f, 0.0f, 1.0f, 2.0f, 2.0f,
425 5.0f, 4.0f, 1.0f, 0.0f, 5.0f, 4.0f, 1.0f,
426 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
427 2.0f, 1.0f, 5.0f, 0.0f, 2.0f, 1.0f, 5.0f,
428 1.0f, 2.0f, 2.0f, 0.0f, 1.0f, 2.0f, 2.0f,
429 5.0f, 4.0f, 1.0f, 0.0f, 5.0f, 4.0f, 1.0f,
430 }));
431
432 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
433 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
434 QuantizedVector<T>(qScale, qOffset, {
435 3.0f, 3.0f,
436 3.0f, 3.0f,
437 }));
438
439 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
440}
441
442template<typename T>
443LayerTestResult<T, 4> L2Pooling2dSize7TestCommon(armnn::IWorkloadFactory& workloadFactory,
444 float qScale = 1.0f,
445 int32_t qOffset = 0)
446{
447 armnn::Pooling2dDescriptor descriptor;
448 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
449 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 7;
450 descriptor.m_StrideX = descriptor.m_StrideY = 7;
451 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
452
453 armnn::TensorInfo inputTensorInfo({ 1, 1, 7, 7 }, armnn::GetDataType<T>());
454 auto input = MakeTensor<T, 4>(inputTensorInfo,
455 QuantizedVector<T>(qScale, qOffset, {
456 1.0f, 0.0f, 2.0f, 0.0f, 3.0f, 0.0f, 4.0f,
457 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
458 0.0f, 5.0f, 0.0f, 6.0f, 0.0f, 7.0f, 0.0f,
459 8.0f, 0.0f, 9.0f, 0.0f, 10.0f, 0.0f, 5.0f,
460 0.0f, 5.0f, 0.0f, 2.0f, 0.0f, 1.0f, 1.0f,
461 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
462 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
463 }));
464
465 armnn::TensorInfo outputTensorInfo({ 1, 1, 1, 1 }, armnn::GetDataType<T>());
466 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
467 QuantizedVector<T>(qScale, qOffset, {
468 3.0f,
469 }));
470
471 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
472}
473
474template<typename T>
475LayerTestResult<T, 4> L2Pooling2dSize9TestCommon(armnn::IWorkloadFactory& workloadFactory,
476 float qScale = 1.0f,
477 int32_t qOffset = 0)
478{
479 armnn::Pooling2dDescriptor descriptor;
480 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
481 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 9;
482 descriptor.m_StrideX = descriptor.m_StrideY = 9;
483 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
484
485 armnn::TensorInfo inputTensorInfo({ 1, 1, 9, 9 }, armnn::GetDataType<T>());
486 auto input = MakeTensor<T, 4>(inputTensorInfo,
487 QuantizedVector<T>(qScale, qOffset, {
488 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
489 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
490 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
491 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
492 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
493 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
494 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
495 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
496 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
497 }));
498
499 armnn::TensorInfo outputTensorInfo({ 1, 1, 1, 1 }, armnn::GetDataType<T>());
500 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
501 QuantizedVector<T>(qScale, qOffset, {
502 3.0f,
503 }));
504
505 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
506}
507
508template<typename T>
509LayerTestResult<T, 4> AsymmetricNonSquarePooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
510 float qScale = 1.0f,
511 int32_t qOffset = 0)
512{
513 armnn::TensorInfo inputTensorInfo({ 1, 1, 1, 3 }, armnn::GetDataType<T>());
514 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
515
516 armnn::Pooling2dDescriptor descriptor;
517 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
518 descriptor.m_PoolWidth = 2;
519 descriptor.m_PoolHeight = 3;
520 descriptor.m_StrideX = 2;
521 descriptor.m_StrideY = 1;
522 descriptor.m_PadLeft = 2;
523 descriptor.m_PadRight = 0;
524 descriptor.m_PadTop = 1;
525 descriptor.m_PadBottom = 2;
526 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
527 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
528
telsoa01c577f2c2018-08-31 09:22:23 +0100529 // Construct input data.
telsoa014fcda012018-03-09 14:13:49 +0000530 auto input = MakeTensor<T, 4>(inputTensorInfo,
531 QuantizedVector<T>(qScale, qOffset, {
532 1.0f, 3.0f, 4.0f,
533 }));
534
telsoa01c577f2c2018-08-31 09:22:23 +0100535 // These were calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000536 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
537 QuantizedVector<T>(qScale, qOffset, {
538 0.0f, 3.0f, 0.0f, 3.0f,
539 }));
540
541 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
542}
543
544template<typename T>
545LayerTestResult<T, 4> ComparePooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
546 armnn::IWorkloadFactory& refWorkloadFactory,
547 armnn::PoolingAlgorithm poolingType,
548 float qScale = 1.0f,
549 int32_t qOffset = 0)
550{
551 const unsigned int inputWidth = 16;
552 const unsigned int inputHeight = 32;
553 const unsigned int channelCount = 2;
554 const unsigned int batchSize = 5;
555
556 const unsigned int poolSize = 3;
557 const unsigned int strideX = 2;
558 const unsigned int strideY = 4;
559 const unsigned int padX = 0;
560 const unsigned int padY = 0;
561
562 const unsigned int outputWidth = (inputWidth + 2 * padX + strideX - poolSize) / strideX;
563 const unsigned int outputHeight = (inputHeight + 2 * padY + strideY - poolSize) / strideY;
564
565 armnn::TensorInfo inputTensorInfo;
566 armnn::TensorInfo outputTensorInfo;
567
568 unsigned int inputShape[] = { batchSize, channelCount, inputHeight, inputWidth };
569 unsigned int outputShape[] = { batchSize, channelCount, outputHeight, outputWidth };
570
571 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::GetDataType<T>());
572 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::GetDataType<T>());
573
574 // Set quantization parameters if the requested type is a quantized type.
575 if(armnn::IsQuantizedType<T>())
576 {
577 inputTensorInfo.SetQuantizationScale(qScale);
578 inputTensorInfo.SetQuantizationOffset(qOffset);
579 outputTensorInfo.SetQuantizationScale(qScale);
580 outputTensorInfo.SetQuantizationOffset(qOffset);
581 }
582
583 boost::multi_array<T, 4> input = MakeRandomTensor<T, 4>(inputTensorInfo, 81715);
584
585 LayerTestResult<T, 4> comparisonResult(outputTensorInfo);
586
587 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
588 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
589
590 armnn::Pooling2dQueueDescriptor data;
591 armnn::WorkloadInfo info;
592 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
593 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
594 data.m_Parameters.m_PoolType = poolingType;
595 data.m_Parameters.m_PoolWidth = poolSize;
596 data.m_Parameters.m_PoolHeight = poolSize;
597 data.m_Parameters.m_StrideX = strideX;
598 data.m_Parameters.m_StrideY = strideY;
599 data.m_Parameters.m_PadLeft = padX;
600 data.m_Parameters.m_PadRight = padX;
601 data.m_Parameters.m_PadTop = padY;
602 data.m_Parameters.m_PadBottom = padY;
603 data.m_Parameters.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
604
605 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
606 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refWorkloadFactory.CreateTensorHandle(inputTensorInfo);
607
608 // Don't execute if Pooling is not supported, as an exception will be raised.
609 armnn::Compute compute = workloadFactory.GetCompute();
610 const size_t reasonIfUnsupportedMaxLen = 255;
611 char reasonIfUnsupported[reasonIfUnsupportedMaxLen+1];
612 comparisonResult.supported = armnn::IsPooling2dSupported(compute, inputTensorInfo, outputTensorInfo,
613 data.m_Parameters,
614 reasonIfUnsupported, reasonIfUnsupportedMaxLen);
615 if (!comparisonResult.supported)
616 {
617 return comparisonResult;
618 }
619
620 armnn::Pooling2dQueueDescriptor refData = data;
621 armnn::WorkloadInfo refInfo = info;
622 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
623 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
624
625 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePooling2d(data, info);
626 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreatePooling2d(refData, refInfo);
627
628 outputHandleRef->Allocate();
629 inputHandleRef->Allocate();
630 inputHandle->Allocate();
631 outputHandle->Allocate();
632
633 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
634 CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0][0][0]);
635
636 workload->Execute();
637 workloadRef->Execute();
638
639 CopyDataFromITensorHandle(&comparisonResult.output[0][0][0][0], outputHandle.get());
640 CopyDataFromITensorHandle(&comparisonResult.outputExpected[0][0][0][0], outputHandleRef.get());
641
642 return comparisonResult;
643}
644
645//
646// Tests max pooling with the following parameters:
647//
648// Pooling size: 2x2
649// Stride: (2,2)
650// input size: 4x4
651// channels: 1
652// batch size: 1
653//
654template<typename T>
655LayerTestResult<T, 4> SimpleMaxPooling2dSize2x2Stride2x2TestCommon(armnn::IWorkloadFactory& workloadFactory,
656 bool forceNoPadding,
657 float qScale = 1.0f,
658 int32_t qOffset = 0)
659{
660 armnn::Pooling2dDescriptor descriptor;
661 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
662 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
663 descriptor.m_StrideX = 2;
664 descriptor.m_StrideY = 2;
665 descriptor.m_PadLeft = descriptor.m_PadRight = forceNoPadding ? 0 : 3;
666 descriptor.m_PadTop = descriptor.m_PadBottom = 0;
667 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
668 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
669
670 unsigned int inputWidth = 4;
671 unsigned int inputHeight = 4;
672 unsigned int outputWidth =
673 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
674 descriptor.m_StrideX;
675 unsigned int outputHeight =
676 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
677 descriptor.m_StrideY;
678 unsigned int channels = 1;
679 unsigned int batchSize = 1;
680
681 std::vector<float> inputData = {
682 510.0f, 222.0f, 780.0f, 654.0f,
683 141.0f, 276.0f, 15.0f, 546.0f,
684 303.0f, 618.0f, 582.0f, 339.0f,
685 438.0f, 564.0f, 573.0f, 402.0f
686 };
687
telsoa01c577f2c2018-08-31 09:22:23 +0100688 // Note that left and right edges will be 0.f, due to the 2x2 max pooling only accessing zeros here.
telsoa014fcda012018-03-09 14:13:49 +0000689 std::vector<float> expectedOutputDataWithPadding = {
690 0.0f, 510.0f, 780.0f, 654.0f, 0.0f,
691 0.0f, 438.0f, 618.0f, 402.0f, 0.0f
692 };
693
694 std::vector<float> expectedOutputDataNoPadding = {
695 510.0f, 780.0f,
696 618.0f, 582.0f
697 };
698
699 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
700
701 // Scale and offset should match input - we're just calculating maximum values.
702 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
703
704 // Set quantization parameters if the requested type is a quantized type.
705 if(armnn::IsQuantizedType<T>())
706 {
707 inputTensorInfo.SetQuantizationScale(qScale);
708 inputTensorInfo.SetQuantizationOffset(qOffset);
709 outputTensorInfo.SetQuantizationScale(qScale);
710 outputTensorInfo.SetQuantizationOffset(qOffset);
711 }
712
713 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
714
715 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
716 forceNoPadding ? QuantizedVector<T>(qScale, qOffset, expectedOutputDataNoPadding) :
717 QuantizedVector<T>(qScale, qOffset, expectedOutputDataWithPadding));
718
719 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
720}
721
surmeh01bceff2f2018-03-29 16:29:27 +0100722//
723// Tests max pooling with the following parameters:
724//
725// Pooling size: 3x2
726// Stride: (2,2)
727// input size: 3x2
728// channels: 1
729// batch size: 1
730//
731template<typename T>
732LayerTestResult<T, 4> IgnorePaddingAveragePooling2dSize3x2Stride2x2TestCommon(
733 armnn::IWorkloadFactory& workloadFactory,
734 bool forceNoPadding,
735 float qScale = 1.0f,
736 int32_t qOffset = 0)
737{
738 armnn::Pooling2dDescriptor descriptor;
739 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
740 descriptor.m_PoolWidth = 3;
741 descriptor.m_PoolHeight = 2;
742 descriptor.m_StrideX = 2;
743 descriptor.m_StrideY = 2;
744 descriptor.m_PadLeft = (forceNoPadding) ? 0 : 1;
745 descriptor.m_PadRight = descriptor.m_PadLeft;
746 descriptor.m_PadTop = 0;
747 descriptor.m_PadBottom = 0;
748 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
749 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
750
751 unsigned int inputWidth = 3;
752 unsigned int inputHeight = 2;
753 unsigned int outputWidth =
754 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
755 descriptor.m_StrideX;
756 unsigned int outputHeight =
757 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
758 descriptor.m_StrideY;
759 unsigned int channels = 1;
760 unsigned int batchSize = 1;
761
762 std::vector<float> inputData = {
763 3.0f, 6.0f, 9.0f,
764 12.0f, 15.0f, 18.0f,
765 };
766
767 std::vector<float> expectedOutputDataWithPadding = {
768 6.0f, 8.0f,
769 };
770
771 std::vector<float> expectedOutputDataNoPadding = {
772 10.5f,
773 };
774
775 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
776
777 // Scale and offset should match input - we're just calculating average values.
778 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
779
780 // Set quantization parameters if the requested type is a quantized type.
781 if(armnn::IsQuantizedType<T>())
782 {
783 inputTensorInfo.SetQuantizationScale(qScale);
784 inputTensorInfo.SetQuantizationOffset(qOffset);
785 outputTensorInfo.SetQuantizationScale(qScale);
786 outputTensorInfo.SetQuantizationOffset(qOffset);
787 }
788
789 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
790
791 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
792 forceNoPadding ? QuantizedVector<T>(qScale, qOffset, expectedOutputDataNoPadding) :
793 QuantizedVector<T>(qScale, qOffset, expectedOutputDataWithPadding));
794
795 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
796}
797
798
telsoa014fcda012018-03-09 14:13:49 +0000799template<typename T>
800LayerTestResult<T, 4> IgnorePaddingSimpleMaxPooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
801 float qScale = 1.0f,
802 int32_t qOffset = 0)
803{
804 armnn::Pooling2dDescriptor descriptor;
805 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
806 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
807 descriptor.m_StrideX = descriptor.m_StrideY = 2;
808 descriptor.m_PadLeft = 1;
809 descriptor.m_PadRight = 1;
810 descriptor.m_PadTop = 1;
811 descriptor.m_PadBottom = 1;
812 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
813
814 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
815 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
816
817 // Set quantization parameters if the requested type is a quantized type.
818 if(armnn::IsQuantizedType<T>())
819 {
820 inputTensorInfo.SetQuantizationScale(qScale);
821 inputTensorInfo.SetQuantizationOffset(qOffset);
822 outputTensorInfo.SetQuantizationScale(qScale);
823 outputTensorInfo.SetQuantizationOffset(qOffset);
824 }
825
826 auto input = MakeTensor<T, 4>(inputTensorInfo,
827 QuantizedVector<T>(qScale, qOffset, {
828 -1.0f, -2.0f, 3.0f, 4.0f,
829 -1.0f, -2.0f, 3.0f, 4.0f,
830 1.0f, 2.0f, -3.0f, -4.0f,
831 1.0f, 2.0f, -3.0f, -4.0f,
832 }));
833
834 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
835 QuantizedVector<T>(qScale, qOffset, {
836 -1.0f, 3.0f, 4.0f,
837 1.0f, 3.0f, 4.0f,
838 1.0f, 2.0f, -4.0f,
839 }));
840
841 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
842}
843
844template<typename T>
845LayerTestResult<T, 4> IgnorePaddingMaxPooling2dSize3TestCommon(armnn::IWorkloadFactory& workloadFactory,
846 float qScale = 1.0f,
847 int32_t qOffset = 0)
848{
849 armnn::Pooling2dDescriptor descriptor;
850 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
851 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
852 descriptor.m_StrideX = descriptor.m_StrideY = 1;
853 descriptor.m_PadLeft = 1;
854 descriptor.m_PadRight = 1;
855 descriptor.m_PadTop = 1;
856 descriptor.m_PadBottom = 1;
857 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
858
859 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
860 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
861
862 // Set quantization parameters if the requested type is a quantized type.
863 if(armnn::IsQuantizedType<T>())
864 {
865 inputTensorInfo.SetQuantizationScale(qScale);
866 inputTensorInfo.SetQuantizationOffset(qOffset);
867 outputTensorInfo.SetQuantizationScale(qScale);
868 outputTensorInfo.SetQuantizationOffset(qOffset);
869 }
870
871 auto input = MakeTensor<T, 4>(inputTensorInfo,
872 QuantizedVector<T>(qScale, qOffset, {
873 -1.0f, -2.0f, 3.0f, 4.0f,
874 -1.0f, -2.0f, 3.0f, 4.0f,
875 1.0f, 2.0f, -3.0f, -4.0f,
876 1.0f, 2.0f, -3.0f, -4.0f,
877 }));
878
879 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
880 QuantizedVector<T>(qScale, qOffset, {
881 -1.0f, 3.0f, 4.0f, 4.0f,
882 2.0f, 3.0f, 4.0f, 4.0f,
883 2.0f, 3.0f, 4.0f, 4.0f,
884 2.0f, 2.0f, 2.0f, -3.0f,
885 }));
886
887 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
888}
889
890template<typename T>
891LayerTestResult<T, 4> IgnorePaddingSimpleAveragePooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
892 float qScale = 1.0f,
893 int32_t qOffset = 0)
894{
895 armnn::Pooling2dDescriptor descriptor;
896 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
897 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
898 descriptor.m_StrideX = descriptor.m_StrideY = 2;
899 descriptor.m_PadLeft = 1;
900 descriptor.m_PadRight = 1;
901 descriptor.m_PadTop = 1;
902 descriptor.m_PadBottom = 1;
903 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
904
905 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
906 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
907
908 // Set quantization parameters if the requested type is a quantized type.
909 if(armnn::IsQuantizedType<T>())
910 {
911 inputTensorInfo.SetQuantizationScale(qScale);
912 inputTensorInfo.SetQuantizationOffset(qOffset);
913 outputTensorInfo.SetQuantizationScale(qScale);
914 outputTensorInfo.SetQuantizationOffset(qOffset);
915 }
916
917 auto input = MakeTensor<T, 4>(inputTensorInfo,
918 QuantizedVector<T>(qScale, qOffset, {
919 12.0f, 20.0f, 32.0f, 40.0f,
920 12.0f, 20.0f, 32.0f, 40.0f,
921 12.0f, 20.0f, 32.0f, 40.0f,
922 12.0f, 20.0f, 32.0f, 40.0f,
923 }));
924
925 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
926 QuantizedVector<T>(qScale, qOffset, {
927 3.0f, 13.0f, 10.0f,
928 6.0f, 26.0f, 20.0f,
929 3.0f, 13.0f, 10.0f,
930 }));
931
932 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
933}
934
935template<typename T>
936LayerTestResult<T, 4> IgnorePaddingSimpleAveragePooling2dNoPaddingTestCommon(armnn::IWorkloadFactory& workloadFactory,
937 float qScale = 1.0f,
938 int32_t qOffset = 0)
939{
940 armnn::Pooling2dDescriptor descriptor;
941 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
942 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
943 descriptor.m_StrideX = descriptor.m_StrideY = 2;
944 descriptor.m_PadLeft = 0;
945 descriptor.m_PadRight = 0;
946 descriptor.m_PadTop = 0;
947 descriptor.m_PadBottom = 0;
948 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
949 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
950
951 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4}, armnn::GetDataType<T>());
952 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
953
954 // Set quantization parameters if the requested type is a quantized type.
955 if(armnn::IsQuantizedType<T>())
956 {
957 inputTensorInfo.SetQuantizationScale(qScale);
958 inputTensorInfo.SetQuantizationOffset(qOffset);
959 outputTensorInfo.SetQuantizationScale(qScale);
960 outputTensorInfo.SetQuantizationOffset(qOffset);
961 }
962
963 auto input = MakeTensor<T, 4>(inputTensorInfo,
964 QuantizedVector<T>(qScale, qOffset, {
965 1.0f, 2.0f, 3.0f, 4.0f,
966 1.0f, 2.0f, 3.0f, 4.0f,
967 1.0f, 2.0f, 3.0f, 4.0f,
968 1.0f, 2.0f, 3.0f, 4.0f,
969 }));
970
971 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
972 QuantizedVector<T>(qScale, qOffset, {
973 2.0f, 3.5f,
974 2.0f, 3.5f
975 }));
976
977 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
978}
979
980template<typename T>
981LayerTestResult<T, 4> IgnorePaddingAveragePooling2dSize3TestCommon(armnn::IWorkloadFactory& workloadFactory,
982 float qScale = 1.0f,
983 int32_t qOffset = 0)
984{
985 armnn::Pooling2dDescriptor descriptor;
986 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
987 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
988 descriptor.m_StrideX = descriptor.m_StrideY = 1;
989 descriptor.m_PadLeft = 1;
990 descriptor.m_PadRight = 1;
991 descriptor.m_PadTop = 1;
992 descriptor.m_PadBottom = 1;
993 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
994
995 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
996 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
997
998 // Set quantization parameters if the requested type is a quantized type.
999 if(armnn::IsQuantizedType<T>())
1000 {
1001 inputTensorInfo.SetQuantizationScale(qScale);
1002 inputTensorInfo.SetQuantizationOffset(qOffset);
1003 outputTensorInfo.SetQuantizationScale(qScale);
1004 outputTensorInfo.SetQuantizationOffset(qOffset);
1005 }
1006
1007 auto input = MakeTensor<T, 4>(inputTensorInfo,
1008 QuantizedVector<T>(qScale, qOffset, {
1009 9.0f, 27.0f, 18.0f, 36.0f,
1010 18.0f, 9.0f, 18.0f, 9.0f,
1011 27.0f, 18.0f, 9.0f, 27.0f,
1012 9.0f, 27.0f, 9.0f, 18.0f,
1013 }));
1014
1015 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1016 QuantizedVector<T>(qScale, qOffset, {
1017 7.0f, 11.0f, 13.0f, 9.0f,
1018 12.0f, 17.0f, 19.0f, 13.0f,
1019 12.0f, 16.0f, 16.0f, 10.0f,
1020 9.0f, 11.0f, 12.0f, 7.0f,
1021 }));
1022
1023 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
1024}
1025
1026template<typename T>
1027LayerTestResult<T, 4> IgnorePaddingSimpleL2Pooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
1028 float qScale = 1.0f,
1029 int32_t qOffset = 0)
1030{
1031 armnn::Pooling2dDescriptor descriptor;
1032 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
1033 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
1034 descriptor.m_StrideX = descriptor.m_StrideY = 2;
1035 descriptor.m_PadLeft = 1;
1036 descriptor.m_PadRight = 1;
1037 descriptor.m_PadTop = 1;
1038 descriptor.m_PadBottom = 1;
1039 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1040
1041 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1042 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
1043
1044 // Set quantization parameters if the requested type is a quantized type.
1045 if(armnn::IsQuantizedType<T>())
1046 {
1047 inputTensorInfo.SetQuantizationScale(qScale);
1048 inputTensorInfo.SetQuantizationOffset(qOffset);
1049 outputTensorInfo.SetQuantizationScale(qScale);
1050 outputTensorInfo.SetQuantizationOffset(qOffset);
1051 }
1052
1053 auto input = MakeTensor<T, 4>(inputTensorInfo,
1054 QuantizedVector<T>(qScale, qOffset, {
1055 2.0f, 4.0f, 8.0f, 16.0f,
1056 4.0f, 2.0f, 2.0f, 4.0f,
1057 8.0f, 2.0f, 4.0f, 2.0f,
1058 16.0f, 2.0f, 2.0f, 8.0f,
1059 }));
1060
1061 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1062 QuantizedVector<T>(qScale, qOffset, {
1063 1.0f, 4.4721f, 8.0f,
1064 4.4721f, 2.6457f, 2.236f,
1065 8.0f, 1.4142f, 4.0f,
1066 }));
1067
1068 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
1069}
1070
1071template<typename T>
1072LayerTestResult<T, 4> IgnorePaddingL2Pooling2dSize3TestCommon(armnn::IWorkloadFactory& workloadFactory,
1073 float qScale = 1.0f,
1074 int32_t qOffset = 0)
1075{
1076 armnn::Pooling2dDescriptor descriptor;
1077 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
1078 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1079 descriptor.m_StrideX = descriptor.m_StrideY = 1;
1080 descriptor.m_PadLeft = 1;
1081 descriptor.m_PadRight = 1;
1082 descriptor.m_PadTop = 1;
1083 descriptor.m_PadBottom = 1;
1084 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1085
1086 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1087 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1088
1089 // Set quantization parameters if the requested type is a quantized type.
1090 if(armnn::IsQuantizedType<T>())
1091 {
1092 inputTensorInfo.SetQuantizationScale(qScale);
1093 inputTensorInfo.SetQuantizationOffset(qOffset);
1094 outputTensorInfo.SetQuantizationScale(qScale);
1095 outputTensorInfo.SetQuantizationOffset(qOffset);
1096 }
1097
1098 auto input = MakeTensor<T, 4>(inputTensorInfo,
1099 QuantizedVector<T>(qScale, qOffset, {
1100 1.0f, 2.0f, 3.0f, 4.0f,
1101 1.0f, 2.0f, 3.0f, 4.0f,
1102 1.0f, 2.0f, 3.0f, 4.0f,
1103 1.0f, 2.0f, 3.0f, 4.0f,
1104 }));
1105
1106 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1107 QuantizedVector<T>(qScale, qOffset, {
1108 1.0540f, 1.7638f, 2.5385f, 2.3570f,
1109 1.2909f, 2.1602f, 3.1091f, 2.8867f,
1110 1.2909f, 2.1602f, 3.1091f, 2.8867f,
1111 1.0540f, 1.7638f, 2.5385f, 2.3570f,
1112 }));
1113
1114 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
1115}