blob: f5e3386fed7a7640e5f8815d01c73cbdb3bfcebd [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
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00007#include "WorkloadTestUtils.hpp"
Nina Drozdd41b2592018-11-19 13:03:36 +00008#include "TensorUtils.hpp"
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00009
telsoa014fcda012018-03-09 14:13:49 +000010#include "QuantizeHelper.hpp"
11
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000012#include <armnn/ArmNN.hpp>
13
14#include <Permute.hpp>
15
16#include <backendsCommon/CpuTensorHandle.hpp>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000017#include <backendsCommon/IBackendInternal.hpp>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000018#include <backendsCommon/WorkloadFactory.hpp>
19#include <backendsCommon/WorkloadInfo.hpp>
20
21#include <test/TensorHelpers.hpp>
22
Matteo Martincigh21350152018-11-28 16:22:22 +000023#include <DataLayoutIndexed.hpp>
24
James Conroy45a9b772018-10-31 11:47:53 +000025#include <boost/numeric/conversion/cast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000026
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000027#include <algorithm>
28#include <string>
29
telsoa014fcda012018-03-09 14:13:49 +000030template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000031LayerTestResult<T, 4> SimplePooling2dTestImpl(
32 armnn::IWorkloadFactory& workloadFactory,
33 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
34 armnn::Pooling2dDescriptor descriptor,
35 float qScale,
36 int32_t qOffset,
37 const boost::multi_array<T, 4>& input,
38 const boost::multi_array<T, 4>& outputExpected)
telsoa014fcda012018-03-09 14:13:49 +000039{
Matthew Bentham8800c002018-11-19 13:19:28 +000040 const armnn::DataLayout dataLayout = descriptor.m_DataLayout;
Matteo Martincigh21350152018-11-28 16:22:22 +000041 const armnnUtils::DataLayoutIndexed dimensionIndices = dataLayout;
Matthew Bentham8800c002018-11-19 13:19:28 +000042 auto heightIndex = dimensionIndices.GetHeightIndex();
43 auto widthIndex = dimensionIndices.GetWidthIndex();
44 auto channelsIndex = dimensionIndices.GetChannelsIndex();
telsoa014fcda012018-03-09 14:13:49 +000045
James Conroy69482272018-10-19 10:41:35 +010046 unsigned int inputHeight = boost::numeric_cast<unsigned int>(input.shape()[heightIndex]);
47 unsigned int inputWidth = boost::numeric_cast<unsigned int>(input.shape()[widthIndex]);
48 unsigned int inputChannels = boost::numeric_cast<unsigned int>(input.shape()[channelsIndex]);
49 unsigned int inputBatchSize = boost::numeric_cast<unsigned int>(input.shape()[0]);
50
51 unsigned int outputHeight = boost::numeric_cast<unsigned int>(outputExpected.shape()[heightIndex]);
52 unsigned int outputWidth = boost::numeric_cast<unsigned int>(outputExpected.shape()[widthIndex]);
53 unsigned int outputChannels = boost::numeric_cast<unsigned int>(outputExpected.shape()[channelsIndex]);
telsoa014fcda012018-03-09 14:13:49 +000054 unsigned int outputBatchSize = boost::numeric_cast<unsigned int>(outputExpected.shape()[0]);
55
Nina Drozdd41b2592018-11-19 13:03:36 +000056 armnn::TensorInfo inputTensorInfo = armnnUtils::GetTensorInfo<T>(inputBatchSize, inputChannels, inputHeight,
57 inputWidth, dataLayout);
58 armnn::TensorInfo outputTensorInfo = armnnUtils::GetTensorInfo<T>(outputBatchSize, outputChannels, outputHeight,
59 outputWidth, dataLayout);
telsoa014fcda012018-03-09 14:13:49 +000060
61 // Set quantization parameters if the requested type is a quantized type.
62 if(armnn::IsQuantizedType<T>())
63 {
64 inputTensorInfo.SetQuantizationScale(qScale);
65 inputTensorInfo.SetQuantizationOffset(qOffset);
66 outputTensorInfo.SetQuantizationScale(qScale);
67 outputTensorInfo.SetQuantizationOffset(qOffset);
68 }
69
70 LayerTestResult<T, 4> result(outputTensorInfo);
71
72 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
73 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
74
75 armnn::Pooling2dQueueDescriptor queueDescriptor;
76 queueDescriptor.m_Parameters = descriptor;
James Conroy45a9b772018-10-31 11:47:53 +000077 queueDescriptor.m_Parameters.m_DataLayout = dataLayout;
Francis Murtagh043d0d02018-10-05 14:08:48 +010078
79 armnn::WorkloadInfo workloadInfo;
80 AddInputToWorkload(queueDescriptor, workloadInfo, inputTensorInfo, inputHandle.get());
81 AddOutputToWorkload(queueDescriptor, workloadInfo, outputTensorInfo, outputHandle.get());
82
83 // Don't execute if Pooling is not supported, as an exception will be raised.
David Beck79141b92018-10-23 16:09:36 +010084 armnn::BackendId backend = workloadFactory.GetBackendId();
Francis Murtagh043d0d02018-10-05 14:08:48 +010085 const size_t reasonIfUnsupportedMaxLen = 255;
86 char reasonIfUnsupported[reasonIfUnsupportedMaxLen+1];
David Beck79141b92018-10-23 16:09:36 +010087 result.supported = armnn::IsPooling2dSupported(backend, inputTensorInfo, outputTensorInfo,
Francis Murtagh043d0d02018-10-05 14:08:48 +010088 queueDescriptor.m_Parameters,
89 reasonIfUnsupported, reasonIfUnsupportedMaxLen);
90 if (!result.supported)
91 {
92 return result;
93 }
94
95 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePooling2d(queueDescriptor, workloadInfo);
96
97 inputHandle->Allocate();
98 outputHandle->Allocate();
99
100 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
101
102 workload->Execute();
103
104 CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
105
106 result.outputExpected = outputExpected;
107
108 return result;
109}
110
telsoa014fcda012018-03-09 14:13:49 +0000111//
112// Tests max pooling with the following parameters:
113//
114// Pooling size: 3x3
115// Stride: (2,4)
116// input size: 8x13
117// channels: 2
118// batch size: 2
119//
120template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000121LayerTestResult<T, 4> SimpleMaxPooling2dSize3x3Stride2x4TestCommon(
122 armnn::IWorkloadFactory& workloadFactory,
123 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
124 bool forceNoPadding,
125 float qScale = 1.0f,
126 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000127{
128 armnn::Pooling2dDescriptor descriptor;
129 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
130 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
131 descriptor.m_StrideX = 2;
132 descriptor.m_StrideY = 4;
133 // forceNoPadding is mainly used for compatibility with ARM Compute.
134 // As of 16/05/2017, it errors if padX or padY are equal to or greater than the pool size.
135 descriptor.m_PadLeft = descriptor.m_PadRight = forceNoPadding ? 0 : 3;
136 descriptor.m_PadTop = descriptor.m_PadBottom = 0;
137 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
138 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
139
140 unsigned int inputWidth = 8;
141 unsigned int inputHeight = 13;
142 unsigned int outputWidth =
143 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
144 descriptor.m_StrideX;
145 unsigned int outputHeight =
146 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
147 descriptor.m_StrideY;
148 unsigned int channels = 2;
149 unsigned int batchSize = 2;
150
151 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
152 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
153
154 // Set quantization parameters if the requested type is a quantized type.
155 if(armnn::IsQuantizedType<T>())
156 {
157 inputTensorInfo.SetQuantizationScale(qScale);
158 inputTensorInfo.SetQuantizationOffset(qOffset);
159 outputTensorInfo.SetQuantizationScale(qScale);
160 outputTensorInfo.SetQuantizationOffset(qOffset);
161 }
162
163 std::vector<float> singleChannelData({
164 0.0f, 4.0f, 8.0f, 1.0f, 6.0f, 4.0f, 5.0f, 8.0f,
165 1.0f, 1.0f, 6.0f, 0.0f, 3.0f, 7.0f, 4.0f, 7.0f,
166 8.0f, 5.0f, 0.0f, 0.0f, 8.0f, 3.0f, 4.0f, 3.0f,
167 8.0f, 2.0f, 5.0f, 4.0f, 1.0f, 9.0f, 2.0f, 0.0f,
168 5.0f, 4.0f, 5.0f, 0.0f, 0.0f, 0.0f, 7.0f, 2.0f,
169 1.0f, 2.0f, 6.0f, 2.0f, 7.0f, 9.0f, 5.0f, 2.0f,
170 9.0f, 7.0f, 3.0f, 1.0f, 3.0f, 4.0f, 8.0f, 3.0f,
171 1.0f, 0.0f, 0.0f, 5.0f, 5.0f, 4.0f, 2.0f, 0.0f,
172 6.0f, 4.0f, 3.0f, 6.0f, 9.0f, 5.0f, 5.0f, 6.0f,
173 8.0f, 7.0f, 9.0f, 6.0f, 1.0f, 4.0f, 1.0f, 9.0f,
174 7.0f, 1.0f, 9.0f, 2.0f, 9.0f, 9.0f, 8.0f, 1.0f,
175 4.0f, 4.0f, 5.0f, 9.0f, 2.0f, 6.0f, 6.0f, 4.0f,
176 3.0f, 5.0f, 4.0f, 0.0f, 1.0f, 5.0f, 9.0f, 7.0f,
177 });
178
telsoa01c577f2c2018-08-31 09:22:23 +0100179 // Constructs input data.
telsoa014fcda012018-03-09 14:13:49 +0000180 std::vector<float> inputData;
181 auto negator = [](float f) { return -f; };
182
telsoa01c577f2c2018-08-31 09:22:23 +0100183 // First image (two channels where the second channel is the negative of the first one).
telsoa014fcda012018-03-09 14:13:49 +0000184 inputData.insert(inputData.end(), singleChannelData.begin(), singleChannelData.end());
185 std::transform(singleChannelData.begin(), singleChannelData.end(), std::back_inserter(inputData), negator);
186
telsoa01c577f2c2018-08-31 09:22:23 +0100187 // Second image (same as first image).
telsoa014fcda012018-03-09 14:13:49 +0000188 inputData.insert(inputData.end(), singleChannelData.begin(), singleChannelData.end());
189 std::transform(singleChannelData.begin(), singleChannelData.end(), std::back_inserter(inputData), negator);
190
191 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
192
telsoa01c577f2c2018-08-31 09:22:23 +0100193 // These were calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000194 auto shape(GetTensorShapeAsArray<4>(outputTensorInfo));
195 boost::multi_array<T, 4> outputExpected(shape);
196 if (forceNoPadding)
197 {
198 outputExpected = MakeTensor<T, 4>(outputTensorInfo,
199 QuantizedVector<T>(qScale, qOffset, {
200 8.0f, 8.0f, 8.0f,
201 9.0f, 7.0f, 9.0f,
202 9.0f, 9.0f, 9.0f,
203
204 0.0f, 0.0f, -3.0f,
205 -1.0f, 0.0f, 0.0f,
206 -1.0f, -1.0f, -1.0f,
207
208 8.0f, 8.0f, 8.0f,
209 9.0f, 7.0f, 9.0f,
210 9.0f, 9.0f, 9.0f,
211
212 0.0f, 0.0f, -3.0f,
213 -1.0f, 0.0f, 0.0f,
214 -1.0f, -1.0f, -1.0f
215 }));
216 }
217 else
218 {
219 outputExpected = MakeTensor<T, 4>(outputTensorInfo,
220 QuantizedVector<T>(qScale, qOffset, {
221 0.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f,
222 0.0f, 9.0f, 7.0f, 9.0f, 9.0f, 3.0f,
223 0.0f, 8.0f, 9.0f, 9.0f, 9.0f, 9.0f,
224
225 0.0f, 0.0f, 0.0f, 0.0f,-3.0f, 0.0f,
226 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
227 0.0f,-1.0f,-1.0f,-1.0f,-1.0f, 0.0f,
228
229 0.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f,
230 0.0f, 9.0f, 7.0f, 9.0f, 9.0f, 3.0f,
231 0.0f, 8.0f, 9.0f, 9.0f, 9.0f, 9.0f,
232
233 0.0f, 0.0f, 0.0f, 0.0f,-3.0f, 0.0f,
234 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
235 0.0f,-1.0f,-1.0f,-1.0f,-1.0f, 0.0f
236 }));
237 }
238
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000239 return SimplePooling2dTestImpl<T>(
240 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000241}
242
243template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000244LayerTestResult<T, 4> SimpleMaxPooling2dTestCommon(
245 armnn::IWorkloadFactory& workloadFactory,
246 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Matthew Bentham8800c002018-11-19 13:19:28 +0000247 const armnn::DataLayout dataLayout = armnn::DataLayout::NCHW,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000248 float qScale = 1.0f,
249 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000250{
251 armnn::Pooling2dDescriptor descriptor;
James Conroy45a9b772018-10-31 11:47:53 +0000252 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
telsoa014fcda012018-03-09 14:13:49 +0000253 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
254 descriptor.m_StrideX = descriptor.m_StrideY = 2;
telsoa014fcda012018-03-09 14:13:49 +0000255 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
James Conroy69482272018-10-19 10:41:35 +0100256 descriptor.m_DataLayout = dataLayout;
telsoa014fcda012018-03-09 14:13:49 +0000257
Nina Drozdd41b2592018-11-19 13:03:36 +0000258 armnn::TensorInfo inputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 4, 4, dataLayout);
259 armnn::TensorInfo outputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 2, 2, dataLayout);
telsoa014fcda012018-03-09 14:13:49 +0000260
261 // Set quantization parameters if the requested type is a quantized type.
262 if(armnn::IsQuantizedType<T>())
263 {
264 inputTensorInfo.SetQuantizationScale(qScale);
265 inputTensorInfo.SetQuantizationOffset(qOffset);
266 outputTensorInfo.SetQuantizationScale(qScale);
267 outputTensorInfo.SetQuantizationOffset(qOffset);
268 }
269
James Conroy45a9b772018-10-31 11:47:53 +0000270 std::vector<T> inputData(
telsoa014fcda012018-03-09 14:13:49 +0000271 QuantizedVector<T>(qScale, qOffset, {
James Conroy45a9b772018-10-31 11:47:53 +0000272 1.0f, 2.0f, 5.0f, 6.0f,
273 3.0f, 4.0f, 7.0f, 8.0f,
274 9.0f, 10.0f, 13.0f, 14.0f,
275 11.0f, 12.0f, 15.0f, 16.0f,
276
277 17.0f, 18.0f, 21.0f, 22.0f,
278 19.0f, 20.0f, 23.0f, 24.0f,
279 25.0f, 26.0f, 29.0f, 30.0f,
280 27.0f, 28.0f, 31.0f, 32.0f,
telsoa014fcda012018-03-09 14:13:49 +0000281 }));
282
James Conroy45a9b772018-10-31 11:47:53 +0000283 std::vector<T> outputData(
telsoa014fcda012018-03-09 14:13:49 +0000284 QuantizedVector<T>(qScale, qOffset, {
James Conroy45a9b772018-10-31 11:47:53 +0000285 4.0f, 8.0f,
286 12.0f, 16.0f,
287
288 20.0f, 24.0f,
289 28.0f, 32.0f,
telsoa014fcda012018-03-09 14:13:49 +0000290 }));
291
James Conroy45a9b772018-10-31 11:47:53 +0000292 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
Matthew Bentham8800c002018-11-19 13:19:28 +0000293 if (dataLayout == armnn::DataLayout::NHWC)
James Conroy45a9b772018-10-31 11:47:53 +0000294 {
295 std::vector<T> tmp(inputData.size());
296 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data());
297 inputData = tmp;
298
299 std::vector<T> tmp1(outputData.size());
300 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data());
301 outputData = tmp1;
302 }
303
304 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
305
306 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
307
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000308 return SimplePooling2dTestImpl<T>(
309 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000310}
311
312template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000313LayerTestResult<T, 4> SimpleAveragePooling2dTestCommon(
314 armnn::IWorkloadFactory& workloadFactory,
315 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Matthew Bentham8800c002018-11-19 13:19:28 +0000316 armnn::DataLayout dataLayout = armnn::DataLayout::NCHW,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000317 float qScale = 1.0f,
318 int32_t qOffset = 0)
Francis Murtagh043d0d02018-10-05 14:08:48 +0100319{
James Conroy45a9b772018-10-31 11:47:53 +0000320 armnn::Pooling2dDescriptor descriptor;
321 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
322 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
323 descriptor.m_StrideX = descriptor.m_StrideY = 2;
324 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
325 descriptor.m_DataLayout = dataLayout;
Francis Murtagh043d0d02018-10-05 14:08:48 +0100326
Nina Drozdd41b2592018-11-19 13:03:36 +0000327 armnn::TensorInfo inputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 4, 4, dataLayout);
328 armnn::TensorInfo outputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 2, 2, dataLayout);
Francis Murtagh043d0d02018-10-05 14:08:48 +0100329
James Conroy45a9b772018-10-31 11:47:53 +0000330 // Set quantization parameters if the requested type is a quantized type.
331 if(armnn::IsQuantizedType<T>())
332 {
333 inputTensorInfo.SetQuantizationScale(qScale);
334 inputTensorInfo.SetQuantizationOffset(qOffset);
335 outputTensorInfo.SetQuantizationScale(qScale);
336 outputTensorInfo.SetQuantizationOffset(qOffset);
337 }
Francis Murtagh043d0d02018-10-05 14:08:48 +0100338
James Conroy45a9b772018-10-31 11:47:53 +0000339 std::vector<T> inputData(
340 QuantizedVector<T>(qScale, qOffset, {
341 2.0f, 2.0f, 6.0f, 6.0f,
342 4.0f, 4.0f, 8.0f, 8.0f,
343 10.0f, 12.0f, 14.0f, 16.0f,
344 10.0f, 12.0f, 16.0f, 14.0f,
345
346 18.0f, 20.0f, 24.0f, 22.0f,
347 20.0f, 18.0f, 22.0f, 24.0f,
348 26.0f, 28.0f, 0.0f, 0.0f,
349 26.0f, 28.0f, 0.0f, 0.0f,
350 }));
351
352 std::vector<T> outputData(
353 QuantizedVector<T>(qScale, qOffset, {
354 3.0f, 7.0f,
355 11.0f, 15.0f,
356
357 19.0f, 23.0f,
358 27.0f, 0.0f,
359 }));
360
361 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
Matthew Bentham8800c002018-11-19 13:19:28 +0000362 if (dataLayout == armnn::DataLayout::NHWC)
James Conroy45a9b772018-10-31 11:47:53 +0000363 {
364 std::vector<T> tmp(inputData.size());
365 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data());
366 inputData = tmp;
367
368 std::vector<T> tmp1(outputData.size());
369 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data());
370 outputData = tmp1;
371 }
372
373 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
374
375 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
376
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000377 return SimplePooling2dTestImpl<T>(
378 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
Francis Murtagh043d0d02018-10-05 14:08:48 +0100379}
380
381template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000382LayerTestResult<T, 4> LargeTensorsAveragePooling2dTestCommon(
383 armnn::IWorkloadFactory& workloadFactory,
384 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
385 float qScale = 1.0f,
386 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000387{
388 armnn::Pooling2dDescriptor descriptor;
389 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
390 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 100;
391 descriptor.m_StrideX = descriptor.m_StrideY = 5;
392 descriptor.m_PadLeft = 50;
393 descriptor.m_PadRight = 50;
394 descriptor.m_PadTop = 50;
395 descriptor.m_PadBottom = 50;
396 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
397
398 armnn::TensorInfo inputTensorInfo({ 5, 3, 52, 60 }, armnn::GetDataType<T>());
399 armnn::TensorInfo outputTensorInfo({ 5, 3, 11, 13 }, armnn::GetDataType<T>());
400
401 // Set quantization parameters if the requested type is a quantized type.
402 if(armnn::IsQuantizedType<T>())
403 {
404 inputTensorInfo.SetQuantizationScale(qScale);
405 inputTensorInfo.SetQuantizationOffset(qOffset);
406 outputTensorInfo.SetQuantizationScale(qScale);
407 outputTensorInfo.SetQuantizationOffset(qOffset);
408 }
409
410 std::vector<T> inputVec;
411
412 for (unsigned int i = 0 ; i < inputTensorInfo.GetShape().GetNumElements(); ++i)
413 {
414 inputVec.push_back(1);
415 }
416
417 auto input = MakeTensor<T, 4>(inputTensorInfo, inputVec);
418
419 std::vector<T> outputVec;
420
421 for (unsigned int i = 0 ; i < outputTensorInfo.GetShape().GetNumElements(); ++i)
422 {
423 outputVec.push_back(1);
424 }
425
426 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputVec);
427
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000428 return SimplePooling2dTestImpl<T>(
429 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000430}
431
432template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000433LayerTestResult<T, 4> SimpleL2Pooling2dTestCommon(
434 armnn::IWorkloadFactory& workloadFactory,
435 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Matthew Bentham8800c002018-11-19 13:19:28 +0000436 armnn::DataLayout dataLayout = armnn::DataLayout::NCHW,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000437 float qScale = 1.0f,
438 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000439{
440 armnn::Pooling2dDescriptor descriptor;
441 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
442 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
443 descriptor.m_StrideX = descriptor.m_StrideY = 2;
444 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
James Conroy45a9b772018-10-31 11:47:53 +0000445 descriptor.m_DataLayout = dataLayout;
telsoa014fcda012018-03-09 14:13:49 +0000446
Nina Drozdd41b2592018-11-19 13:03:36 +0000447 armnn::TensorInfo inputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 4, 4, dataLayout);
448 armnn::TensorInfo outputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 2, 2, dataLayout);
James Conroy45a9b772018-10-31 11:47:53 +0000449
450 std::vector<T> inputData(
telsoa014fcda012018-03-09 14:13:49 +0000451 QuantizedVector<T>(qScale, qOffset, {
James Conroy45a9b772018-10-31 11:47:53 +0000452 1.0f, 7.0f, 5.0f, 5.0f,
453 1.0f, 7.0f, 5.0f, 5.0f,
454 3.0f, 3.0f, 1.0f, 1.0f,
455 3.0f, 3.0f, 1.0f, 1.0f,
456
457 1.0f, 7.0f, 0.0f, 0.0f,
458 1.0f, 7.0f, 2.0f, 0.0f,
459 0.0f, 2.0f, 1.0f, 1.0f,
460 0.0f, 0.0f, 1.0f, 1.0f,
telsoa014fcda012018-03-09 14:13:49 +0000461 }));
462
James Conroy45a9b772018-10-31 11:47:53 +0000463 std::vector<T> outputData(
telsoa014fcda012018-03-09 14:13:49 +0000464 QuantizedVector<T>(qScale, qOffset, {
465 5.0f, 5.0f,
James Conroy45a9b772018-10-31 11:47:53 +0000466 3.0f, 1.0f,
467
468 5.0f, 1.0f,
469 1.0f, 1.0f,
telsoa014fcda012018-03-09 14:13:49 +0000470 }));
471
James Conroy45a9b772018-10-31 11:47:53 +0000472 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
Matthew Bentham8800c002018-11-19 13:19:28 +0000473 if (dataLayout == armnn::DataLayout::NHWC)
James Conroy45a9b772018-10-31 11:47:53 +0000474 {
475 std::vector<T> tmp(inputData.size());
476 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data());
477 inputData = tmp;
478
479 std::vector<T> tmp1(outputData.size());
480 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data());
481 outputData = tmp1;
482 }
483
484 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
485
486 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
487
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000488 return SimplePooling2dTestImpl<T>(
489 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000490}
491
492template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000493LayerTestResult<T, 4> L2Pooling2dSize3Stride1TestCommon(
494 armnn::IWorkloadFactory& workloadFactory,
495 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
496 float qScale = 1.0f,
497 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000498{
499 armnn::Pooling2dDescriptor descriptor;
500 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
501 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
502 descriptor.m_StrideX = descriptor.m_StrideY = 1;
503 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
504
505 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
506 auto input = MakeTensor<T, 4>(inputTensorInfo,
507 QuantizedVector<T>(qScale, qOffset, {
508 2.0f, 1.0f, 5.0f, 2.0f,
509 1.0f, 2.0f, 2.0f, 1.0f,
510 5.0f, 4.0f, 1.0f, 5.0f,
511 2.0f, 1.0f, 5.0f, 2.0f,
512 }));
513
514 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
515 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
516 QuantizedVector<T>(qScale, qOffset, {
517 3.0f, 3.0f,
518 3.0f, 3.0f,
519 }));
520
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000521 return SimplePooling2dTestImpl<T>(
522 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000523}
524
525template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000526LayerTestResult<T, 4> L2Pooling2dSize3Stride3TestCommon(
527 armnn::IWorkloadFactory& workloadFactory,
528 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
529 float qScale = 1.0f,
530 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000531{
532 armnn::Pooling2dDescriptor descriptor;
533 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
534 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
535 descriptor.m_StrideX = descriptor.m_StrideY = 3;
536 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
537
538 armnn::TensorInfo inputTensorInfo({ 1, 1, 9, 9 }, armnn::GetDataType<T>());
539 auto input = MakeTensor<T, 4>(inputTensorInfo,
540 QuantizedVector<T>(qScale, qOffset, {
541 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
542 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
543 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
544 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
545 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
546 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
547 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
548 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
549 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
550 }));
551
552 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
553 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
554 QuantizedVector<T>(qScale, qOffset, {
555 3.0f, 3.0f, 3.0f,
556 3.0f, 3.0f, 3.0f,
557 3.0f, 3.0f, 3.0f,
558 }));
559
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000560 return SimplePooling2dTestImpl<T>(
561 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000562}
563
564template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000565LayerTestResult<T, 4> L2Pooling2dSize3Stride4TestCommon(
566 armnn::IWorkloadFactory& workloadFactory,
567 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
568 float qScale = 1.0f,
569 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000570{
571 armnn::Pooling2dDescriptor descriptor;
572 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
573 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
574 descriptor.m_StrideX = descriptor.m_StrideY = 4;
575 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
576
577 armnn::TensorInfo inputTensorInfo({ 1, 1, 7, 7 }, armnn::GetDataType<T>());
578 auto input = MakeTensor<T, 4>(inputTensorInfo,
579 QuantizedVector<T>(qScale, qOffset, {
580 2.0f, 1.0f, 5.0f, 0.0f, 2.0f, 1.0f, 5.0f,
581 1.0f, 2.0f, 2.0f, 0.0f, 1.0f, 2.0f, 2.0f,
582 5.0f, 4.0f, 1.0f, 0.0f, 5.0f, 4.0f, 1.0f,
583 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
584 2.0f, 1.0f, 5.0f, 0.0f, 2.0f, 1.0f, 5.0f,
585 1.0f, 2.0f, 2.0f, 0.0f, 1.0f, 2.0f, 2.0f,
586 5.0f, 4.0f, 1.0f, 0.0f, 5.0f, 4.0f, 1.0f,
587 }));
588
589 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
590 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
591 QuantizedVector<T>(qScale, qOffset, {
592 3.0f, 3.0f,
593 3.0f, 3.0f,
594 }));
595
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000596 return SimplePooling2dTestImpl<T>(
597 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000598}
599
600template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000601LayerTestResult<T, 4> L2Pooling2dSize7TestCommon(
602 armnn::IWorkloadFactory& workloadFactory,
603 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
604 float qScale = 1.0f,
605 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000606{
607 armnn::Pooling2dDescriptor descriptor;
608 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
609 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 7;
610 descriptor.m_StrideX = descriptor.m_StrideY = 7;
611 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
612
613 armnn::TensorInfo inputTensorInfo({ 1, 1, 7, 7 }, armnn::GetDataType<T>());
614 auto input = MakeTensor<T, 4>(inputTensorInfo,
615 QuantizedVector<T>(qScale, qOffset, {
616 1.0f, 0.0f, 2.0f, 0.0f, 3.0f, 0.0f, 4.0f,
617 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
618 0.0f, 5.0f, 0.0f, 6.0f, 0.0f, 7.0f, 0.0f,
619 8.0f, 0.0f, 9.0f, 0.0f, 10.0f, 0.0f, 5.0f,
620 0.0f, 5.0f, 0.0f, 2.0f, 0.0f, 1.0f, 1.0f,
621 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
622 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
623 }));
624
625 armnn::TensorInfo outputTensorInfo({ 1, 1, 1, 1 }, armnn::GetDataType<T>());
626 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
627 QuantizedVector<T>(qScale, qOffset, {
628 3.0f,
629 }));
630
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000631 return SimplePooling2dTestImpl<T>(
632 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000633}
634
635template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000636LayerTestResult<T, 4> L2Pooling2dSize9TestCommon(
637 armnn::IWorkloadFactory& workloadFactory,
638 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
639 float qScale = 1.0f,
640 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000641{
642 armnn::Pooling2dDescriptor descriptor;
643 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
644 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 9;
645 descriptor.m_StrideX = descriptor.m_StrideY = 9;
646 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
647
648 armnn::TensorInfo inputTensorInfo({ 1, 1, 9, 9 }, armnn::GetDataType<T>());
649 auto input = MakeTensor<T, 4>(inputTensorInfo,
650 QuantizedVector<T>(qScale, qOffset, {
651 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
652 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
653 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
654 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
655 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
656 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
657 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
658 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
659 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
660 }));
661
662 armnn::TensorInfo outputTensorInfo({ 1, 1, 1, 1 }, armnn::GetDataType<T>());
663 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
664 QuantizedVector<T>(qScale, qOffset, {
665 3.0f,
666 }));
667
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000668 return SimplePooling2dTestImpl<T>(
669 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000670}
671
672template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000673LayerTestResult<T, 4> AsymmetricNonSquarePooling2dTestCommon(
674 armnn::IWorkloadFactory& workloadFactory,
675 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
676 float qScale = 1.0f,
677 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000678{
679 armnn::TensorInfo inputTensorInfo({ 1, 1, 1, 3 }, armnn::GetDataType<T>());
680 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
681
682 armnn::Pooling2dDescriptor descriptor;
683 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
684 descriptor.m_PoolWidth = 2;
685 descriptor.m_PoolHeight = 3;
686 descriptor.m_StrideX = 2;
687 descriptor.m_StrideY = 1;
688 descriptor.m_PadLeft = 2;
689 descriptor.m_PadRight = 0;
690 descriptor.m_PadTop = 1;
691 descriptor.m_PadBottom = 2;
692 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
693 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
694
telsoa01c577f2c2018-08-31 09:22:23 +0100695 // Construct input data.
telsoa014fcda012018-03-09 14:13:49 +0000696 auto input = MakeTensor<T, 4>(inputTensorInfo,
697 QuantizedVector<T>(qScale, qOffset, {
698 1.0f, 3.0f, 4.0f,
699 }));
700
telsoa01c577f2c2018-08-31 09:22:23 +0100701 // These were calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000702 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
703 QuantizedVector<T>(qScale, qOffset, {
704 0.0f, 3.0f, 0.0f, 3.0f,
705 }));
706
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000707 return SimplePooling2dTestImpl<T>(
708 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000709}
710
711template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000712LayerTestResult<T, 4> ComparePooling2dTestCommon(
713 armnn::IWorkloadFactory& workloadFactory,
714 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
715 armnn::IWorkloadFactory& refWorkloadFactory,
716 armnn::PoolingAlgorithm poolingType,
717 float qScale = 1.0f,
718 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000719{
720 const unsigned int inputWidth = 16;
721 const unsigned int inputHeight = 32;
722 const unsigned int channelCount = 2;
723 const unsigned int batchSize = 5;
724
725 const unsigned int poolSize = 3;
726 const unsigned int strideX = 2;
727 const unsigned int strideY = 4;
728 const unsigned int padX = 0;
729 const unsigned int padY = 0;
730
731 const unsigned int outputWidth = (inputWidth + 2 * padX + strideX - poolSize) / strideX;
732 const unsigned int outputHeight = (inputHeight + 2 * padY + strideY - poolSize) / strideY;
733
734 armnn::TensorInfo inputTensorInfo;
735 armnn::TensorInfo outputTensorInfo;
736
737 unsigned int inputShape[] = { batchSize, channelCount, inputHeight, inputWidth };
738 unsigned int outputShape[] = { batchSize, channelCount, outputHeight, outputWidth };
739
740 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::GetDataType<T>());
741 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::GetDataType<T>());
742
743 // Set quantization parameters if the requested type is a quantized type.
744 if(armnn::IsQuantizedType<T>())
745 {
746 inputTensorInfo.SetQuantizationScale(qScale);
747 inputTensorInfo.SetQuantizationOffset(qOffset);
748 outputTensorInfo.SetQuantizationScale(qScale);
749 outputTensorInfo.SetQuantizationOffset(qOffset);
750 }
751
752 boost::multi_array<T, 4> input = MakeRandomTensor<T, 4>(inputTensorInfo, 81715);
753
754 LayerTestResult<T, 4> comparisonResult(outputTensorInfo);
755
756 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
757 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
758
759 armnn::Pooling2dQueueDescriptor data;
760 armnn::WorkloadInfo info;
761 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
762 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
763 data.m_Parameters.m_PoolType = poolingType;
764 data.m_Parameters.m_PoolWidth = poolSize;
765 data.m_Parameters.m_PoolHeight = poolSize;
766 data.m_Parameters.m_StrideX = strideX;
767 data.m_Parameters.m_StrideY = strideY;
768 data.m_Parameters.m_PadLeft = padX;
769 data.m_Parameters.m_PadRight = padX;
770 data.m_Parameters.m_PadTop = padY;
771 data.m_Parameters.m_PadBottom = padY;
772 data.m_Parameters.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
773
774 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
775 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refWorkloadFactory.CreateTensorHandle(inputTensorInfo);
776
777 // Don't execute if Pooling is not supported, as an exception will be raised.
David Beck79141b92018-10-23 16:09:36 +0100778 armnn::BackendId backend = workloadFactory.GetBackendId();
telsoa014fcda012018-03-09 14:13:49 +0000779 const size_t reasonIfUnsupportedMaxLen = 255;
780 char reasonIfUnsupported[reasonIfUnsupportedMaxLen+1];
David Beck79141b92018-10-23 16:09:36 +0100781 comparisonResult.supported = armnn::IsPooling2dSupported(backend, inputTensorInfo, outputTensorInfo,
telsoa014fcda012018-03-09 14:13:49 +0000782 data.m_Parameters,
783 reasonIfUnsupported, reasonIfUnsupportedMaxLen);
784 if (!comparisonResult.supported)
785 {
786 return comparisonResult;
787 }
788
789 armnn::Pooling2dQueueDescriptor refData = data;
790 armnn::WorkloadInfo refInfo = info;
791 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
792 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
793
794 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePooling2d(data, info);
795 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreatePooling2d(refData, refInfo);
796
797 outputHandleRef->Allocate();
798 inputHandleRef->Allocate();
799 inputHandle->Allocate();
800 outputHandle->Allocate();
801
802 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
803 CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0][0][0]);
804
805 workload->Execute();
806 workloadRef->Execute();
807
808 CopyDataFromITensorHandle(&comparisonResult.output[0][0][0][0], outputHandle.get());
809 CopyDataFromITensorHandle(&comparisonResult.outputExpected[0][0][0][0], outputHandleRef.get());
810
811 return comparisonResult;
812}
813
814//
815// Tests max pooling with the following parameters:
816//
817// Pooling size: 2x2
818// Stride: (2,2)
819// input size: 4x4
820// channels: 1
821// batch size: 1
822//
823template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000824LayerTestResult<T, 4> SimpleMaxPooling2dSize2x2Stride2x2TestCommon(
825 armnn::IWorkloadFactory& workloadFactory,
826 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
827 bool forceNoPadding,
828 float qScale = 1.0f,
829 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000830{
831 armnn::Pooling2dDescriptor descriptor;
832 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
833 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
834 descriptor.m_StrideX = 2;
835 descriptor.m_StrideY = 2;
836 descriptor.m_PadLeft = descriptor.m_PadRight = forceNoPadding ? 0 : 3;
837 descriptor.m_PadTop = descriptor.m_PadBottom = 0;
838 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
839 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
840
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000841
telsoa014fcda012018-03-09 14:13:49 +0000842 unsigned int inputWidth = 4;
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000843
telsoa014fcda012018-03-09 14:13:49 +0000844 unsigned int inputHeight = 4;
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000845
telsoa014fcda012018-03-09 14:13:49 +0000846 unsigned int outputWidth =
847 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
848 descriptor.m_StrideX;
849 unsigned int outputHeight =
850 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
851 descriptor.m_StrideY;
852 unsigned int channels = 1;
853 unsigned int batchSize = 1;
854
855 std::vector<float> inputData = {
856 510.0f, 222.0f, 780.0f, 654.0f,
857 141.0f, 276.0f, 15.0f, 546.0f,
858 303.0f, 618.0f, 582.0f, 339.0f,
859 438.0f, 564.0f, 573.0f, 402.0f
860 };
861
telsoa01c577f2c2018-08-31 09:22:23 +0100862 // 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 +0000863 std::vector<float> expectedOutputDataWithPadding = {
864 0.0f, 510.0f, 780.0f, 654.0f, 0.0f,
865 0.0f, 438.0f, 618.0f, 402.0f, 0.0f
866 };
867
868 std::vector<float> expectedOutputDataNoPadding = {
869 510.0f, 780.0f,
870 618.0f, 582.0f
871 };
872
873 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
874
875 // Scale and offset should match input - we're just calculating maximum values.
876 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
877
878 // Set quantization parameters if the requested type is a quantized type.
879 if(armnn::IsQuantizedType<T>())
880 {
881 inputTensorInfo.SetQuantizationScale(qScale);
882 inputTensorInfo.SetQuantizationOffset(qOffset);
883 outputTensorInfo.SetQuantizationScale(qScale);
884 outputTensorInfo.SetQuantizationOffset(qOffset);
885 }
886
887 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
888
889 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
890 forceNoPadding ? QuantizedVector<T>(qScale, qOffset, expectedOutputDataNoPadding) :
891 QuantizedVector<T>(qScale, qOffset, expectedOutputDataWithPadding));
892
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000893 return SimplePooling2dTestImpl<T>(
894 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000895}
896
surmeh01bceff2f2018-03-29 16:29:27 +0100897//
898// Tests max pooling with the following parameters:
899//
900// Pooling size: 3x2
901// Stride: (2,2)
902// input size: 3x2
903// channels: 1
904// batch size: 1
905//
906template<typename T>
907LayerTestResult<T, 4> IgnorePaddingAveragePooling2dSize3x2Stride2x2TestCommon(
908 armnn::IWorkloadFactory& workloadFactory,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000909 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
surmeh01bceff2f2018-03-29 16:29:27 +0100910 bool forceNoPadding,
911 float qScale = 1.0f,
912 int32_t qOffset = 0)
913{
914 armnn::Pooling2dDescriptor descriptor;
915 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
916 descriptor.m_PoolWidth = 3;
917 descriptor.m_PoolHeight = 2;
918 descriptor.m_StrideX = 2;
919 descriptor.m_StrideY = 2;
920 descriptor.m_PadLeft = (forceNoPadding) ? 0 : 1;
921 descriptor.m_PadRight = descriptor.m_PadLeft;
922 descriptor.m_PadTop = 0;
923 descriptor.m_PadBottom = 0;
924 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
925 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
926
927 unsigned int inputWidth = 3;
928 unsigned int inputHeight = 2;
929 unsigned int outputWidth =
930 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
931 descriptor.m_StrideX;
932 unsigned int outputHeight =
933 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
934 descriptor.m_StrideY;
935 unsigned int channels = 1;
936 unsigned int batchSize = 1;
937
938 std::vector<float> inputData = {
939 3.0f, 6.0f, 9.0f,
940 12.0f, 15.0f, 18.0f,
941 };
942
943 std::vector<float> expectedOutputDataWithPadding = {
944 6.0f, 8.0f,
945 };
946
947 std::vector<float> expectedOutputDataNoPadding = {
948 10.5f,
949 };
950
951 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
952
953 // Scale and offset should match input - we're just calculating average values.
954 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
955
956 // Set quantization parameters if the requested type is a quantized type.
957 if(armnn::IsQuantizedType<T>())
958 {
959 inputTensorInfo.SetQuantizationScale(qScale);
960 inputTensorInfo.SetQuantizationOffset(qOffset);
961 outputTensorInfo.SetQuantizationScale(qScale);
962 outputTensorInfo.SetQuantizationOffset(qOffset);
963 }
964
965 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
966
967 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
968 forceNoPadding ? QuantizedVector<T>(qScale, qOffset, expectedOutputDataNoPadding) :
969 QuantizedVector<T>(qScale, qOffset, expectedOutputDataWithPadding));
970
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000971 return SimplePooling2dTestImpl<T>(
972 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
surmeh01bceff2f2018-03-29 16:29:27 +0100973}
974
975
telsoa014fcda012018-03-09 14:13:49 +0000976template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000977LayerTestResult<T, 4> IgnorePaddingSimpleMaxPooling2dTestCommon(
978 armnn::IWorkloadFactory& workloadFactory,
979 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
980 float qScale = 1.0f,
981 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000982{
983 armnn::Pooling2dDescriptor descriptor;
984 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
985 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
986 descriptor.m_StrideX = descriptor.m_StrideY = 2;
987 descriptor.m_PadLeft = 1;
988 descriptor.m_PadRight = 1;
989 descriptor.m_PadTop = 1;
990 descriptor.m_PadBottom = 1;
991 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
992
993 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
994 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
995
996 // Set quantization parameters if the requested type is a quantized type.
997 if(armnn::IsQuantizedType<T>())
998 {
999 inputTensorInfo.SetQuantizationScale(qScale);
1000 inputTensorInfo.SetQuantizationOffset(qOffset);
1001 outputTensorInfo.SetQuantizationScale(qScale);
1002 outputTensorInfo.SetQuantizationOffset(qOffset);
1003 }
1004
1005 auto input = MakeTensor<T, 4>(inputTensorInfo,
1006 QuantizedVector<T>(qScale, qOffset, {
1007 -1.0f, -2.0f, 3.0f, 4.0f,
1008 -1.0f, -2.0f, 3.0f, 4.0f,
1009 1.0f, 2.0f, -3.0f, -4.0f,
1010 1.0f, 2.0f, -3.0f, -4.0f,
1011 }));
1012
1013 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1014 QuantizedVector<T>(qScale, qOffset, {
1015 -1.0f, 3.0f, 4.0f,
1016 1.0f, 3.0f, 4.0f,
1017 1.0f, 2.0f, -4.0f,
1018 }));
1019
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001020 return SimplePooling2dTestImpl<T>(
1021 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001022}
1023
1024template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001025LayerTestResult<T, 4> IgnorePaddingMaxPooling2dSize3TestCommon(
1026 armnn::IWorkloadFactory& workloadFactory,
1027 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1028 float qScale = 1.0f,
1029 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001030{
1031 armnn::Pooling2dDescriptor descriptor;
1032 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
1033 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1034 descriptor.m_StrideX = descriptor.m_StrideY = 1;
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, 4, 4 }, 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 -1.0f, -2.0f, 3.0f, 4.0f,
1056 -1.0f, -2.0f, 3.0f, 4.0f,
1057 1.0f, 2.0f, -3.0f, -4.0f,
1058 1.0f, 2.0f, -3.0f, -4.0f,
1059 }));
1060
1061 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1062 QuantizedVector<T>(qScale, qOffset, {
1063 -1.0f, 3.0f, 4.0f, 4.0f,
1064 2.0f, 3.0f, 4.0f, 4.0f,
1065 2.0f, 3.0f, 4.0f, 4.0f,
1066 2.0f, 2.0f, 2.0f, -3.0f,
1067 }));
1068
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001069 return SimplePooling2dTestImpl<T>(
1070 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001071}
1072
1073template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001074LayerTestResult<T, 4> IgnorePaddingSimpleAveragePooling2dTestCommon(
1075 armnn::IWorkloadFactory& workloadFactory,
1076 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1077 float qScale = 1.0f,
1078 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001079{
1080 armnn::Pooling2dDescriptor descriptor;
1081 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
1082 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
1083 descriptor.m_StrideX = descriptor.m_StrideY = 2;
1084 descriptor.m_PadLeft = 1;
1085 descriptor.m_PadRight = 1;
1086 descriptor.m_PadTop = 1;
1087 descriptor.m_PadBottom = 1;
1088 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1089
1090 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1091 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
1092
1093 // Set quantization parameters if the requested type is a quantized type.
1094 if(armnn::IsQuantizedType<T>())
1095 {
1096 inputTensorInfo.SetQuantizationScale(qScale);
1097 inputTensorInfo.SetQuantizationOffset(qOffset);
1098 outputTensorInfo.SetQuantizationScale(qScale);
1099 outputTensorInfo.SetQuantizationOffset(qOffset);
1100 }
1101
1102 auto input = MakeTensor<T, 4>(inputTensorInfo,
1103 QuantizedVector<T>(qScale, qOffset, {
1104 12.0f, 20.0f, 32.0f, 40.0f,
1105 12.0f, 20.0f, 32.0f, 40.0f,
1106 12.0f, 20.0f, 32.0f, 40.0f,
1107 12.0f, 20.0f, 32.0f, 40.0f,
1108 }));
1109
1110 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1111 QuantizedVector<T>(qScale, qOffset, {
1112 3.0f, 13.0f, 10.0f,
1113 6.0f, 26.0f, 20.0f,
1114 3.0f, 13.0f, 10.0f,
1115 }));
1116
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001117 return SimplePooling2dTestImpl<T>(
1118 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001119}
1120
1121template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001122LayerTestResult<T, 4> IgnorePaddingSimpleAveragePooling2dNoPaddingTestCommon(
1123 armnn::IWorkloadFactory& workloadFactory,
1124 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1125 float qScale = 1.0f,
1126 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001127{
1128 armnn::Pooling2dDescriptor descriptor;
1129 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
1130 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1131 descriptor.m_StrideX = descriptor.m_StrideY = 2;
1132 descriptor.m_PadLeft = 0;
1133 descriptor.m_PadRight = 0;
1134 descriptor.m_PadTop = 0;
1135 descriptor.m_PadBottom = 0;
1136 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1137 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
1138
1139 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4}, armnn::GetDataType<T>());
1140 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
1141
1142 // Set quantization parameters if the requested type is a quantized type.
1143 if(armnn::IsQuantizedType<T>())
1144 {
1145 inputTensorInfo.SetQuantizationScale(qScale);
1146 inputTensorInfo.SetQuantizationOffset(qOffset);
1147 outputTensorInfo.SetQuantizationScale(qScale);
1148 outputTensorInfo.SetQuantizationOffset(qOffset);
1149 }
1150
1151 auto input = MakeTensor<T, 4>(inputTensorInfo,
1152 QuantizedVector<T>(qScale, qOffset, {
1153 1.0f, 2.0f, 3.0f, 4.0f,
1154 1.0f, 2.0f, 3.0f, 4.0f,
1155 1.0f, 2.0f, 3.0f, 4.0f,
1156 1.0f, 2.0f, 3.0f, 4.0f,
1157 }));
1158
1159 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1160 QuantizedVector<T>(qScale, qOffset, {
1161 2.0f, 3.5f,
1162 2.0f, 3.5f
1163 }));
1164
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001165 return SimplePooling2dTestImpl<T>(
1166 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001167}
1168
1169template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001170LayerTestResult<T, 4> IgnorePaddingAveragePooling2dSize3TestCommon(
1171 armnn::IWorkloadFactory& workloadFactory,
1172 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1173 float qScale = 1.0f,
1174 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001175{
1176 armnn::Pooling2dDescriptor descriptor;
1177 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
1178 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1179 descriptor.m_StrideX = descriptor.m_StrideY = 1;
1180 descriptor.m_PadLeft = 1;
1181 descriptor.m_PadRight = 1;
1182 descriptor.m_PadTop = 1;
1183 descriptor.m_PadBottom = 1;
1184 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1185
1186 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1187 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1188
1189 // Set quantization parameters if the requested type is a quantized type.
1190 if(armnn::IsQuantizedType<T>())
1191 {
1192 inputTensorInfo.SetQuantizationScale(qScale);
1193 inputTensorInfo.SetQuantizationOffset(qOffset);
1194 outputTensorInfo.SetQuantizationScale(qScale);
1195 outputTensorInfo.SetQuantizationOffset(qOffset);
1196 }
1197
1198 auto input = MakeTensor<T, 4>(inputTensorInfo,
1199 QuantizedVector<T>(qScale, qOffset, {
1200 9.0f, 27.0f, 18.0f, 36.0f,
1201 18.0f, 9.0f, 18.0f, 9.0f,
1202 27.0f, 18.0f, 9.0f, 27.0f,
1203 9.0f, 27.0f, 9.0f, 18.0f,
1204 }));
1205
1206 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1207 QuantizedVector<T>(qScale, qOffset, {
1208 7.0f, 11.0f, 13.0f, 9.0f,
1209 12.0f, 17.0f, 19.0f, 13.0f,
1210 12.0f, 16.0f, 16.0f, 10.0f,
1211 9.0f, 11.0f, 12.0f, 7.0f,
1212 }));
1213
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001214 return SimplePooling2dTestImpl<T>(
1215 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001216}
1217
1218template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001219LayerTestResult<T, 4> IgnorePaddingSimpleL2Pooling2dTestCommon(
1220 armnn::IWorkloadFactory& workloadFactory,
1221 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1222 float qScale = 1.0f,
1223 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001224{
1225 armnn::Pooling2dDescriptor descriptor;
1226 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
1227 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
1228 descriptor.m_StrideX = descriptor.m_StrideY = 2;
1229 descriptor.m_PadLeft = 1;
1230 descriptor.m_PadRight = 1;
1231 descriptor.m_PadTop = 1;
1232 descriptor.m_PadBottom = 1;
1233 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1234
1235 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1236 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
1237
1238 // Set quantization parameters if the requested type is a quantized type.
1239 if(armnn::IsQuantizedType<T>())
1240 {
1241 inputTensorInfo.SetQuantizationScale(qScale);
1242 inputTensorInfo.SetQuantizationOffset(qOffset);
1243 outputTensorInfo.SetQuantizationScale(qScale);
1244 outputTensorInfo.SetQuantizationOffset(qOffset);
1245 }
1246
1247 auto input = MakeTensor<T, 4>(inputTensorInfo,
1248 QuantizedVector<T>(qScale, qOffset, {
1249 2.0f, 4.0f, 8.0f, 16.0f,
1250 4.0f, 2.0f, 2.0f, 4.0f,
1251 8.0f, 2.0f, 4.0f, 2.0f,
1252 16.0f, 2.0f, 2.0f, 8.0f,
1253 }));
1254
1255 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1256 QuantizedVector<T>(qScale, qOffset, {
1257 1.0f, 4.4721f, 8.0f,
1258 4.4721f, 2.6457f, 2.236f,
1259 8.0f, 1.4142f, 4.0f,
1260 }));
1261
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001262 return SimplePooling2dTestImpl<T>(
1263 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001264}
1265
1266template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001267LayerTestResult<T, 4> IgnorePaddingL2Pooling2dSize3TestCommon(
1268 armnn::IWorkloadFactory& workloadFactory,
1269 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1270 float qScale = 1.0f,
1271 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001272{
1273 armnn::Pooling2dDescriptor descriptor;
1274 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
1275 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1276 descriptor.m_StrideX = descriptor.m_StrideY = 1;
1277 descriptor.m_PadLeft = 1;
1278 descriptor.m_PadRight = 1;
1279 descriptor.m_PadTop = 1;
1280 descriptor.m_PadBottom = 1;
1281 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1282
1283 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1284 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1285
1286 // Set quantization parameters if the requested type is a quantized type.
1287 if(armnn::IsQuantizedType<T>())
1288 {
1289 inputTensorInfo.SetQuantizationScale(qScale);
1290 inputTensorInfo.SetQuantizationOffset(qOffset);
1291 outputTensorInfo.SetQuantizationScale(qScale);
1292 outputTensorInfo.SetQuantizationOffset(qOffset);
1293 }
1294
1295 auto input = MakeTensor<T, 4>(inputTensorInfo,
1296 QuantizedVector<T>(qScale, qOffset, {
1297 1.0f, 2.0f, 3.0f, 4.0f,
1298 1.0f, 2.0f, 3.0f, 4.0f,
1299 1.0f, 2.0f, 3.0f, 4.0f,
1300 1.0f, 2.0f, 3.0f, 4.0f,
1301 }));
1302
1303 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1304 QuantizedVector<T>(qScale, qOffset, {
1305 1.0540f, 1.7638f, 2.5385f, 2.3570f,
1306 1.2909f, 2.1602f, 3.1091f, 2.8867f,
1307 1.2909f, 2.1602f, 3.1091f, 2.8867f,
1308 1.0540f, 1.7638f, 2.5385f, 2.3570f,
1309 }));
1310
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001311 return SimplePooling2dTestImpl<T>(
1312 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001313}