blob: 0f33ac01a569587908062a15ec7d716a9169bd84 [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
James Conroy45a9b772018-10-31 11:47:53 +000023#include <boost/numeric/conversion/cast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000024
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000025#include <algorithm>
26#include <string>
27
telsoa014fcda012018-03-09 14:13:49 +000028template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000029LayerTestResult<T, 4> SimplePooling2dTestImpl(
30 armnn::IWorkloadFactory& workloadFactory,
31 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
32 armnn::Pooling2dDescriptor descriptor,
33 float qScale,
34 int32_t qOffset,
35 const boost::multi_array<T, 4>& input,
36 const boost::multi_array<T, 4>& outputExpected)
telsoa014fcda012018-03-09 14:13:49 +000037{
Matthew Bentham8800c002018-11-19 13:19:28 +000038 const armnn::DataLayout dataLayout = descriptor.m_DataLayout;
39 const armnn::DataLayoutIndexed dimensionIndices = dataLayout;
40 auto heightIndex = dimensionIndices.GetHeightIndex();
41 auto widthIndex = dimensionIndices.GetWidthIndex();
42 auto channelsIndex = dimensionIndices.GetChannelsIndex();
telsoa014fcda012018-03-09 14:13:49 +000043
James Conroy69482272018-10-19 10:41:35 +010044 unsigned int inputHeight = boost::numeric_cast<unsigned int>(input.shape()[heightIndex]);
45 unsigned int inputWidth = boost::numeric_cast<unsigned int>(input.shape()[widthIndex]);
46 unsigned int inputChannels = boost::numeric_cast<unsigned int>(input.shape()[channelsIndex]);
47 unsigned int inputBatchSize = boost::numeric_cast<unsigned int>(input.shape()[0]);
48
49 unsigned int outputHeight = boost::numeric_cast<unsigned int>(outputExpected.shape()[heightIndex]);
50 unsigned int outputWidth = boost::numeric_cast<unsigned int>(outputExpected.shape()[widthIndex]);
51 unsigned int outputChannels = boost::numeric_cast<unsigned int>(outputExpected.shape()[channelsIndex]);
telsoa014fcda012018-03-09 14:13:49 +000052 unsigned int outputBatchSize = boost::numeric_cast<unsigned int>(outputExpected.shape()[0]);
53
Nina Drozdd41b2592018-11-19 13:03:36 +000054 armnn::TensorInfo inputTensorInfo = armnnUtils::GetTensorInfo<T>(inputBatchSize, inputChannels, inputHeight,
55 inputWidth, dataLayout);
56 armnn::TensorInfo outputTensorInfo = armnnUtils::GetTensorInfo<T>(outputBatchSize, outputChannels, outputHeight,
57 outputWidth, dataLayout);
telsoa014fcda012018-03-09 14:13:49 +000058
59 // Set quantization parameters if the requested type is a quantized type.
60 if(armnn::IsQuantizedType<T>())
61 {
62 inputTensorInfo.SetQuantizationScale(qScale);
63 inputTensorInfo.SetQuantizationOffset(qOffset);
64 outputTensorInfo.SetQuantizationScale(qScale);
65 outputTensorInfo.SetQuantizationOffset(qOffset);
66 }
67
68 LayerTestResult<T, 4> result(outputTensorInfo);
69
70 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
71 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
72
73 armnn::Pooling2dQueueDescriptor queueDescriptor;
74 queueDescriptor.m_Parameters = descriptor;
James Conroy45a9b772018-10-31 11:47:53 +000075 queueDescriptor.m_Parameters.m_DataLayout = dataLayout;
Francis Murtagh043d0d02018-10-05 14:08:48 +010076
77 armnn::WorkloadInfo workloadInfo;
78 AddInputToWorkload(queueDescriptor, workloadInfo, inputTensorInfo, inputHandle.get());
79 AddOutputToWorkload(queueDescriptor, workloadInfo, outputTensorInfo, outputHandle.get());
80
81 // Don't execute if Pooling is not supported, as an exception will be raised.
David Beck79141b92018-10-23 16:09:36 +010082 armnn::BackendId backend = workloadFactory.GetBackendId();
Francis Murtagh043d0d02018-10-05 14:08:48 +010083 const size_t reasonIfUnsupportedMaxLen = 255;
84 char reasonIfUnsupported[reasonIfUnsupportedMaxLen+1];
David Beck79141b92018-10-23 16:09:36 +010085 result.supported = armnn::IsPooling2dSupported(backend, inputTensorInfo, outputTensorInfo,
Francis Murtagh043d0d02018-10-05 14:08:48 +010086 queueDescriptor.m_Parameters,
87 reasonIfUnsupported, reasonIfUnsupportedMaxLen);
88 if (!result.supported)
89 {
90 return result;
91 }
92
93 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePooling2d(queueDescriptor, workloadInfo);
94
95 inputHandle->Allocate();
96 outputHandle->Allocate();
97
98 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
99
100 workload->Execute();
101
102 CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
103
104 result.outputExpected = outputExpected;
105
106 return result;
107}
108
telsoa014fcda012018-03-09 14:13:49 +0000109//
110// Tests max pooling with the following parameters:
111//
112// Pooling size: 3x3
113// Stride: (2,4)
114// input size: 8x13
115// channels: 2
116// batch size: 2
117//
118template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000119LayerTestResult<T, 4> SimpleMaxPooling2dSize3x3Stride2x4TestCommon(
120 armnn::IWorkloadFactory& workloadFactory,
121 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
122 bool forceNoPadding,
123 float qScale = 1.0f,
124 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000125{
126 armnn::Pooling2dDescriptor descriptor;
127 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
128 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
129 descriptor.m_StrideX = 2;
130 descriptor.m_StrideY = 4;
131 // forceNoPadding is mainly used for compatibility with ARM Compute.
132 // As of 16/05/2017, it errors if padX or padY are equal to or greater than the pool size.
133 descriptor.m_PadLeft = descriptor.m_PadRight = forceNoPadding ? 0 : 3;
134 descriptor.m_PadTop = descriptor.m_PadBottom = 0;
135 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
136 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
137
138 unsigned int inputWidth = 8;
139 unsigned int inputHeight = 13;
140 unsigned int outputWidth =
141 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
142 descriptor.m_StrideX;
143 unsigned int outputHeight =
144 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
145 descriptor.m_StrideY;
146 unsigned int channels = 2;
147 unsigned int batchSize = 2;
148
149 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
150 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
151
152 // Set quantization parameters if the requested type is a quantized type.
153 if(armnn::IsQuantizedType<T>())
154 {
155 inputTensorInfo.SetQuantizationScale(qScale);
156 inputTensorInfo.SetQuantizationOffset(qOffset);
157 outputTensorInfo.SetQuantizationScale(qScale);
158 outputTensorInfo.SetQuantizationOffset(qOffset);
159 }
160
161 std::vector<float> singleChannelData({
162 0.0f, 4.0f, 8.0f, 1.0f, 6.0f, 4.0f, 5.0f, 8.0f,
163 1.0f, 1.0f, 6.0f, 0.0f, 3.0f, 7.0f, 4.0f, 7.0f,
164 8.0f, 5.0f, 0.0f, 0.0f, 8.0f, 3.0f, 4.0f, 3.0f,
165 8.0f, 2.0f, 5.0f, 4.0f, 1.0f, 9.0f, 2.0f, 0.0f,
166 5.0f, 4.0f, 5.0f, 0.0f, 0.0f, 0.0f, 7.0f, 2.0f,
167 1.0f, 2.0f, 6.0f, 2.0f, 7.0f, 9.0f, 5.0f, 2.0f,
168 9.0f, 7.0f, 3.0f, 1.0f, 3.0f, 4.0f, 8.0f, 3.0f,
169 1.0f, 0.0f, 0.0f, 5.0f, 5.0f, 4.0f, 2.0f, 0.0f,
170 6.0f, 4.0f, 3.0f, 6.0f, 9.0f, 5.0f, 5.0f, 6.0f,
171 8.0f, 7.0f, 9.0f, 6.0f, 1.0f, 4.0f, 1.0f, 9.0f,
172 7.0f, 1.0f, 9.0f, 2.0f, 9.0f, 9.0f, 8.0f, 1.0f,
173 4.0f, 4.0f, 5.0f, 9.0f, 2.0f, 6.0f, 6.0f, 4.0f,
174 3.0f, 5.0f, 4.0f, 0.0f, 1.0f, 5.0f, 9.0f, 7.0f,
175 });
176
telsoa01c577f2c2018-08-31 09:22:23 +0100177 // Constructs input data.
telsoa014fcda012018-03-09 14:13:49 +0000178 std::vector<float> inputData;
179 auto negator = [](float f) { return -f; };
180
telsoa01c577f2c2018-08-31 09:22:23 +0100181 // First image (two channels where the second channel is the negative of the first one).
telsoa014fcda012018-03-09 14:13:49 +0000182 inputData.insert(inputData.end(), singleChannelData.begin(), singleChannelData.end());
183 std::transform(singleChannelData.begin(), singleChannelData.end(), std::back_inserter(inputData), negator);
184
telsoa01c577f2c2018-08-31 09:22:23 +0100185 // Second image (same as first image).
telsoa014fcda012018-03-09 14:13:49 +0000186 inputData.insert(inputData.end(), singleChannelData.begin(), singleChannelData.end());
187 std::transform(singleChannelData.begin(), singleChannelData.end(), std::back_inserter(inputData), negator);
188
189 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
190
telsoa01c577f2c2018-08-31 09:22:23 +0100191 // These were calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000192 auto shape(GetTensorShapeAsArray<4>(outputTensorInfo));
193 boost::multi_array<T, 4> outputExpected(shape);
194 if (forceNoPadding)
195 {
196 outputExpected = MakeTensor<T, 4>(outputTensorInfo,
197 QuantizedVector<T>(qScale, qOffset, {
198 8.0f, 8.0f, 8.0f,
199 9.0f, 7.0f, 9.0f,
200 9.0f, 9.0f, 9.0f,
201
202 0.0f, 0.0f, -3.0f,
203 -1.0f, 0.0f, 0.0f,
204 -1.0f, -1.0f, -1.0f,
205
206 8.0f, 8.0f, 8.0f,
207 9.0f, 7.0f, 9.0f,
208 9.0f, 9.0f, 9.0f,
209
210 0.0f, 0.0f, -3.0f,
211 -1.0f, 0.0f, 0.0f,
212 -1.0f, -1.0f, -1.0f
213 }));
214 }
215 else
216 {
217 outputExpected = MakeTensor<T, 4>(outputTensorInfo,
218 QuantizedVector<T>(qScale, qOffset, {
219 0.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f,
220 0.0f, 9.0f, 7.0f, 9.0f, 9.0f, 3.0f,
221 0.0f, 8.0f, 9.0f, 9.0f, 9.0f, 9.0f,
222
223 0.0f, 0.0f, 0.0f, 0.0f,-3.0f, 0.0f,
224 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
225 0.0f,-1.0f,-1.0f,-1.0f,-1.0f, 0.0f,
226
227 0.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f,
228 0.0f, 9.0f, 7.0f, 9.0f, 9.0f, 3.0f,
229 0.0f, 8.0f, 9.0f, 9.0f, 9.0f, 9.0f,
230
231 0.0f, 0.0f, 0.0f, 0.0f,-3.0f, 0.0f,
232 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
233 0.0f,-1.0f,-1.0f,-1.0f,-1.0f, 0.0f
234 }));
235 }
236
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000237 return SimplePooling2dTestImpl<T>(
238 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000239}
240
241template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000242LayerTestResult<T, 4> SimpleMaxPooling2dTestCommon(
243 armnn::IWorkloadFactory& workloadFactory,
244 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Matthew Bentham8800c002018-11-19 13:19:28 +0000245 const armnn::DataLayout dataLayout = armnn::DataLayout::NCHW,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000246 float qScale = 1.0f,
247 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000248{
249 armnn::Pooling2dDescriptor descriptor;
James Conroy45a9b772018-10-31 11:47:53 +0000250 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
telsoa014fcda012018-03-09 14:13:49 +0000251 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
252 descriptor.m_StrideX = descriptor.m_StrideY = 2;
telsoa014fcda012018-03-09 14:13:49 +0000253 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
James Conroy69482272018-10-19 10:41:35 +0100254 descriptor.m_DataLayout = dataLayout;
telsoa014fcda012018-03-09 14:13:49 +0000255
Nina Drozdd41b2592018-11-19 13:03:36 +0000256 armnn::TensorInfo inputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 4, 4, dataLayout);
257 armnn::TensorInfo outputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 2, 2, dataLayout);
telsoa014fcda012018-03-09 14:13:49 +0000258
259 // Set quantization parameters if the requested type is a quantized type.
260 if(armnn::IsQuantizedType<T>())
261 {
262 inputTensorInfo.SetQuantizationScale(qScale);
263 inputTensorInfo.SetQuantizationOffset(qOffset);
264 outputTensorInfo.SetQuantizationScale(qScale);
265 outputTensorInfo.SetQuantizationOffset(qOffset);
266 }
267
James Conroy45a9b772018-10-31 11:47:53 +0000268 std::vector<T> inputData(
telsoa014fcda012018-03-09 14:13:49 +0000269 QuantizedVector<T>(qScale, qOffset, {
James Conroy45a9b772018-10-31 11:47:53 +0000270 1.0f, 2.0f, 5.0f, 6.0f,
271 3.0f, 4.0f, 7.0f, 8.0f,
272 9.0f, 10.0f, 13.0f, 14.0f,
273 11.0f, 12.0f, 15.0f, 16.0f,
274
275 17.0f, 18.0f, 21.0f, 22.0f,
276 19.0f, 20.0f, 23.0f, 24.0f,
277 25.0f, 26.0f, 29.0f, 30.0f,
278 27.0f, 28.0f, 31.0f, 32.0f,
telsoa014fcda012018-03-09 14:13:49 +0000279 }));
280
James Conroy45a9b772018-10-31 11:47:53 +0000281 std::vector<T> outputData(
telsoa014fcda012018-03-09 14:13:49 +0000282 QuantizedVector<T>(qScale, qOffset, {
James Conroy45a9b772018-10-31 11:47:53 +0000283 4.0f, 8.0f,
284 12.0f, 16.0f,
285
286 20.0f, 24.0f,
287 28.0f, 32.0f,
telsoa014fcda012018-03-09 14:13:49 +0000288 }));
289
James Conroy45a9b772018-10-31 11:47:53 +0000290 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
Matthew Bentham8800c002018-11-19 13:19:28 +0000291 if (dataLayout == armnn::DataLayout::NHWC)
James Conroy45a9b772018-10-31 11:47:53 +0000292 {
293 std::vector<T> tmp(inputData.size());
294 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data());
295 inputData = tmp;
296
297 std::vector<T> tmp1(outputData.size());
298 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data());
299 outputData = tmp1;
300 }
301
302 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
303
304 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
305
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000306 return SimplePooling2dTestImpl<T>(
307 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000308}
309
310template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000311LayerTestResult<T, 4> SimpleAveragePooling2dTestCommon(
312 armnn::IWorkloadFactory& workloadFactory,
313 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Matthew Bentham8800c002018-11-19 13:19:28 +0000314 armnn::DataLayout dataLayout = armnn::DataLayout::NCHW,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000315 float qScale = 1.0f,
316 int32_t qOffset = 0)
Francis Murtagh043d0d02018-10-05 14:08:48 +0100317{
James Conroy45a9b772018-10-31 11:47:53 +0000318 armnn::Pooling2dDescriptor descriptor;
319 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
320 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
321 descriptor.m_StrideX = descriptor.m_StrideY = 2;
322 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
323 descriptor.m_DataLayout = dataLayout;
Francis Murtagh043d0d02018-10-05 14:08:48 +0100324
Nina Drozdd41b2592018-11-19 13:03:36 +0000325 armnn::TensorInfo inputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 4, 4, dataLayout);
326 armnn::TensorInfo outputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 2, 2, dataLayout);
Francis Murtagh043d0d02018-10-05 14:08:48 +0100327
James Conroy45a9b772018-10-31 11:47:53 +0000328 // Set quantization parameters if the requested type is a quantized type.
329 if(armnn::IsQuantizedType<T>())
330 {
331 inputTensorInfo.SetQuantizationScale(qScale);
332 inputTensorInfo.SetQuantizationOffset(qOffset);
333 outputTensorInfo.SetQuantizationScale(qScale);
334 outputTensorInfo.SetQuantizationOffset(qOffset);
335 }
Francis Murtagh043d0d02018-10-05 14:08:48 +0100336
James Conroy45a9b772018-10-31 11:47:53 +0000337 std::vector<T> inputData(
338 QuantizedVector<T>(qScale, qOffset, {
339 2.0f, 2.0f, 6.0f, 6.0f,
340 4.0f, 4.0f, 8.0f, 8.0f,
341 10.0f, 12.0f, 14.0f, 16.0f,
342 10.0f, 12.0f, 16.0f, 14.0f,
343
344 18.0f, 20.0f, 24.0f, 22.0f,
345 20.0f, 18.0f, 22.0f, 24.0f,
346 26.0f, 28.0f, 0.0f, 0.0f,
347 26.0f, 28.0f, 0.0f, 0.0f,
348 }));
349
350 std::vector<T> outputData(
351 QuantizedVector<T>(qScale, qOffset, {
352 3.0f, 7.0f,
353 11.0f, 15.0f,
354
355 19.0f, 23.0f,
356 27.0f, 0.0f,
357 }));
358
359 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
Matthew Bentham8800c002018-11-19 13:19:28 +0000360 if (dataLayout == armnn::DataLayout::NHWC)
James Conroy45a9b772018-10-31 11:47:53 +0000361 {
362 std::vector<T> tmp(inputData.size());
363 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data());
364 inputData = tmp;
365
366 std::vector<T> tmp1(outputData.size());
367 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data());
368 outputData = tmp1;
369 }
370
371 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
372
373 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
374
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000375 return SimplePooling2dTestImpl<T>(
376 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
Francis Murtagh043d0d02018-10-05 14:08:48 +0100377}
378
379template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000380LayerTestResult<T, 4> LargeTensorsAveragePooling2dTestCommon(
381 armnn::IWorkloadFactory& workloadFactory,
382 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
383 float qScale = 1.0f,
384 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000385{
386 armnn::Pooling2dDescriptor descriptor;
387 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
388 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 100;
389 descriptor.m_StrideX = descriptor.m_StrideY = 5;
390 descriptor.m_PadLeft = 50;
391 descriptor.m_PadRight = 50;
392 descriptor.m_PadTop = 50;
393 descriptor.m_PadBottom = 50;
394 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
395
396 armnn::TensorInfo inputTensorInfo({ 5, 3, 52, 60 }, armnn::GetDataType<T>());
397 armnn::TensorInfo outputTensorInfo({ 5, 3, 11, 13 }, armnn::GetDataType<T>());
398
399 // Set quantization parameters if the requested type is a quantized type.
400 if(armnn::IsQuantizedType<T>())
401 {
402 inputTensorInfo.SetQuantizationScale(qScale);
403 inputTensorInfo.SetQuantizationOffset(qOffset);
404 outputTensorInfo.SetQuantizationScale(qScale);
405 outputTensorInfo.SetQuantizationOffset(qOffset);
406 }
407
408 std::vector<T> inputVec;
409
410 for (unsigned int i = 0 ; i < inputTensorInfo.GetShape().GetNumElements(); ++i)
411 {
412 inputVec.push_back(1);
413 }
414
415 auto input = MakeTensor<T, 4>(inputTensorInfo, inputVec);
416
417 std::vector<T> outputVec;
418
419 for (unsigned int i = 0 ; i < outputTensorInfo.GetShape().GetNumElements(); ++i)
420 {
421 outputVec.push_back(1);
422 }
423
424 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputVec);
425
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000426 return SimplePooling2dTestImpl<T>(
427 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000428}
429
430template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000431LayerTestResult<T, 4> SimpleL2Pooling2dTestCommon(
432 armnn::IWorkloadFactory& workloadFactory,
433 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Matthew Bentham8800c002018-11-19 13:19:28 +0000434 armnn::DataLayout dataLayout = armnn::DataLayout::NCHW,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000435 float qScale = 1.0f,
436 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000437{
438 armnn::Pooling2dDescriptor descriptor;
439 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
440 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
441 descriptor.m_StrideX = descriptor.m_StrideY = 2;
442 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
James Conroy45a9b772018-10-31 11:47:53 +0000443 descriptor.m_DataLayout = dataLayout;
telsoa014fcda012018-03-09 14:13:49 +0000444
Nina Drozdd41b2592018-11-19 13:03:36 +0000445 armnn::TensorInfo inputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 4, 4, dataLayout);
446 armnn::TensorInfo outputTensorInfo = armnnUtils::GetTensorInfo<T>(1, 2, 2, 2, dataLayout);
James Conroy45a9b772018-10-31 11:47:53 +0000447
448 std::vector<T> inputData(
telsoa014fcda012018-03-09 14:13:49 +0000449 QuantizedVector<T>(qScale, qOffset, {
James Conroy45a9b772018-10-31 11:47:53 +0000450 1.0f, 7.0f, 5.0f, 5.0f,
451 1.0f, 7.0f, 5.0f, 5.0f,
452 3.0f, 3.0f, 1.0f, 1.0f,
453 3.0f, 3.0f, 1.0f, 1.0f,
454
455 1.0f, 7.0f, 0.0f, 0.0f,
456 1.0f, 7.0f, 2.0f, 0.0f,
457 0.0f, 2.0f, 1.0f, 1.0f,
458 0.0f, 0.0f, 1.0f, 1.0f,
telsoa014fcda012018-03-09 14:13:49 +0000459 }));
460
James Conroy45a9b772018-10-31 11:47:53 +0000461 std::vector<T> outputData(
telsoa014fcda012018-03-09 14:13:49 +0000462 QuantizedVector<T>(qScale, qOffset, {
463 5.0f, 5.0f,
James Conroy45a9b772018-10-31 11:47:53 +0000464 3.0f, 1.0f,
465
466 5.0f, 1.0f,
467 1.0f, 1.0f,
telsoa014fcda012018-03-09 14:13:49 +0000468 }));
469
James Conroy45a9b772018-10-31 11:47:53 +0000470 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
Matthew Bentham8800c002018-11-19 13:19:28 +0000471 if (dataLayout == armnn::DataLayout::NHWC)
James Conroy45a9b772018-10-31 11:47:53 +0000472 {
473 std::vector<T> tmp(inputData.size());
474 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data());
475 inputData = tmp;
476
477 std::vector<T> tmp1(outputData.size());
478 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data());
479 outputData = tmp1;
480 }
481
482 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
483
484 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
485
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000486 return SimplePooling2dTestImpl<T>(
487 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000488}
489
490template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000491LayerTestResult<T, 4> L2Pooling2dSize3Stride1TestCommon(
492 armnn::IWorkloadFactory& workloadFactory,
493 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
494 float qScale = 1.0f,
495 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000496{
497 armnn::Pooling2dDescriptor descriptor;
498 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
499 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
500 descriptor.m_StrideX = descriptor.m_StrideY = 1;
501 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
502
503 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
504 auto input = MakeTensor<T, 4>(inputTensorInfo,
505 QuantizedVector<T>(qScale, qOffset, {
506 2.0f, 1.0f, 5.0f, 2.0f,
507 1.0f, 2.0f, 2.0f, 1.0f,
508 5.0f, 4.0f, 1.0f, 5.0f,
509 2.0f, 1.0f, 5.0f, 2.0f,
510 }));
511
512 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
513 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
514 QuantizedVector<T>(qScale, qOffset, {
515 3.0f, 3.0f,
516 3.0f, 3.0f,
517 }));
518
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000519 return SimplePooling2dTestImpl<T>(
520 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000521}
522
523template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000524LayerTestResult<T, 4> L2Pooling2dSize3Stride3TestCommon(
525 armnn::IWorkloadFactory& workloadFactory,
526 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
527 float qScale = 1.0f,
528 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000529{
530 armnn::Pooling2dDescriptor descriptor;
531 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
532 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
533 descriptor.m_StrideX = descriptor.m_StrideY = 3;
534 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
535
536 armnn::TensorInfo inputTensorInfo({ 1, 1, 9, 9 }, armnn::GetDataType<T>());
537 auto input = MakeTensor<T, 4>(inputTensorInfo,
538 QuantizedVector<T>(qScale, qOffset, {
539 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
540 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
541 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
542 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
543 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
544 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
545 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
546 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
547 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
548 }));
549
550 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
551 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
552 QuantizedVector<T>(qScale, qOffset, {
553 3.0f, 3.0f, 3.0f,
554 3.0f, 3.0f, 3.0f,
555 3.0f, 3.0f, 3.0f,
556 }));
557
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000558 return SimplePooling2dTestImpl<T>(
559 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000560}
561
562template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000563LayerTestResult<T, 4> L2Pooling2dSize3Stride4TestCommon(
564 armnn::IWorkloadFactory& workloadFactory,
565 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
566 float qScale = 1.0f,
567 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000568{
569 armnn::Pooling2dDescriptor descriptor;
570 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
571 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
572 descriptor.m_StrideX = descriptor.m_StrideY = 4;
573 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
574
575 armnn::TensorInfo inputTensorInfo({ 1, 1, 7, 7 }, armnn::GetDataType<T>());
576 auto input = MakeTensor<T, 4>(inputTensorInfo,
577 QuantizedVector<T>(qScale, qOffset, {
578 2.0f, 1.0f, 5.0f, 0.0f, 2.0f, 1.0f, 5.0f,
579 1.0f, 2.0f, 2.0f, 0.0f, 1.0f, 2.0f, 2.0f,
580 5.0f, 4.0f, 1.0f, 0.0f, 5.0f, 4.0f, 1.0f,
581 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
582 2.0f, 1.0f, 5.0f, 0.0f, 2.0f, 1.0f, 5.0f,
583 1.0f, 2.0f, 2.0f, 0.0f, 1.0f, 2.0f, 2.0f,
584 5.0f, 4.0f, 1.0f, 0.0f, 5.0f, 4.0f, 1.0f,
585 }));
586
587 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
588 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
589 QuantizedVector<T>(qScale, qOffset, {
590 3.0f, 3.0f,
591 3.0f, 3.0f,
592 }));
593
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000594 return SimplePooling2dTestImpl<T>(
595 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000596}
597
598template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000599LayerTestResult<T, 4> L2Pooling2dSize7TestCommon(
600 armnn::IWorkloadFactory& workloadFactory,
601 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
602 float qScale = 1.0f,
603 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000604{
605 armnn::Pooling2dDescriptor descriptor;
606 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
607 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 7;
608 descriptor.m_StrideX = descriptor.m_StrideY = 7;
609 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
610
611 armnn::TensorInfo inputTensorInfo({ 1, 1, 7, 7 }, armnn::GetDataType<T>());
612 auto input = MakeTensor<T, 4>(inputTensorInfo,
613 QuantizedVector<T>(qScale, qOffset, {
614 1.0f, 0.0f, 2.0f, 0.0f, 3.0f, 0.0f, 4.0f,
615 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
616 0.0f, 5.0f, 0.0f, 6.0f, 0.0f, 7.0f, 0.0f,
617 8.0f, 0.0f, 9.0f, 0.0f, 10.0f, 0.0f, 5.0f,
618 0.0f, 5.0f, 0.0f, 2.0f, 0.0f, 1.0f, 1.0f,
619 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
620 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
621 }));
622
623 armnn::TensorInfo outputTensorInfo({ 1, 1, 1, 1 }, armnn::GetDataType<T>());
624 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
625 QuantizedVector<T>(qScale, qOffset, {
626 3.0f,
627 }));
628
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000629 return SimplePooling2dTestImpl<T>(
630 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000631}
632
633template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000634LayerTestResult<T, 4> L2Pooling2dSize9TestCommon(
635 armnn::IWorkloadFactory& workloadFactory,
636 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
637 float qScale = 1.0f,
638 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000639{
640 armnn::Pooling2dDescriptor descriptor;
641 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
642 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 9;
643 descriptor.m_StrideX = descriptor.m_StrideY = 9;
644 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
645
646 armnn::TensorInfo inputTensorInfo({ 1, 1, 9, 9 }, armnn::GetDataType<T>());
647 auto input = MakeTensor<T, 4>(inputTensorInfo,
648 QuantizedVector<T>(qScale, qOffset, {
649 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
650 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
651 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
652 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
653 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
654 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
655 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
656 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
657 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
658 }));
659
660 armnn::TensorInfo outputTensorInfo({ 1, 1, 1, 1 }, armnn::GetDataType<T>());
661 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
662 QuantizedVector<T>(qScale, qOffset, {
663 3.0f,
664 }));
665
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000666 return SimplePooling2dTestImpl<T>(
667 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000668}
669
670template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000671LayerTestResult<T, 4> AsymmetricNonSquarePooling2dTestCommon(
672 armnn::IWorkloadFactory& workloadFactory,
673 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
674 float qScale = 1.0f,
675 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000676{
677 armnn::TensorInfo inputTensorInfo({ 1, 1, 1, 3 }, armnn::GetDataType<T>());
678 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
679
680 armnn::Pooling2dDescriptor descriptor;
681 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
682 descriptor.m_PoolWidth = 2;
683 descriptor.m_PoolHeight = 3;
684 descriptor.m_StrideX = 2;
685 descriptor.m_StrideY = 1;
686 descriptor.m_PadLeft = 2;
687 descriptor.m_PadRight = 0;
688 descriptor.m_PadTop = 1;
689 descriptor.m_PadBottom = 2;
690 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
691 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
692
telsoa01c577f2c2018-08-31 09:22:23 +0100693 // Construct input data.
telsoa014fcda012018-03-09 14:13:49 +0000694 auto input = MakeTensor<T, 4>(inputTensorInfo,
695 QuantizedVector<T>(qScale, qOffset, {
696 1.0f, 3.0f, 4.0f,
697 }));
698
telsoa01c577f2c2018-08-31 09:22:23 +0100699 // These were calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000700 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
701 QuantizedVector<T>(qScale, qOffset, {
702 0.0f, 3.0f, 0.0f, 3.0f,
703 }));
704
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000705 return SimplePooling2dTestImpl<T>(
706 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000707}
708
709template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000710LayerTestResult<T, 4> ComparePooling2dTestCommon(
711 armnn::IWorkloadFactory& workloadFactory,
712 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
713 armnn::IWorkloadFactory& refWorkloadFactory,
714 armnn::PoolingAlgorithm poolingType,
715 float qScale = 1.0f,
716 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000717{
718 const unsigned int inputWidth = 16;
719 const unsigned int inputHeight = 32;
720 const unsigned int channelCount = 2;
721 const unsigned int batchSize = 5;
722
723 const unsigned int poolSize = 3;
724 const unsigned int strideX = 2;
725 const unsigned int strideY = 4;
726 const unsigned int padX = 0;
727 const unsigned int padY = 0;
728
729 const unsigned int outputWidth = (inputWidth + 2 * padX + strideX - poolSize) / strideX;
730 const unsigned int outputHeight = (inputHeight + 2 * padY + strideY - poolSize) / strideY;
731
732 armnn::TensorInfo inputTensorInfo;
733 armnn::TensorInfo outputTensorInfo;
734
735 unsigned int inputShape[] = { batchSize, channelCount, inputHeight, inputWidth };
736 unsigned int outputShape[] = { batchSize, channelCount, outputHeight, outputWidth };
737
738 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::GetDataType<T>());
739 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::GetDataType<T>());
740
741 // Set quantization parameters if the requested type is a quantized type.
742 if(armnn::IsQuantizedType<T>())
743 {
744 inputTensorInfo.SetQuantizationScale(qScale);
745 inputTensorInfo.SetQuantizationOffset(qOffset);
746 outputTensorInfo.SetQuantizationScale(qScale);
747 outputTensorInfo.SetQuantizationOffset(qOffset);
748 }
749
750 boost::multi_array<T, 4> input = MakeRandomTensor<T, 4>(inputTensorInfo, 81715);
751
752 LayerTestResult<T, 4> comparisonResult(outputTensorInfo);
753
754 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
755 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
756
757 armnn::Pooling2dQueueDescriptor data;
758 armnn::WorkloadInfo info;
759 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
760 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
761 data.m_Parameters.m_PoolType = poolingType;
762 data.m_Parameters.m_PoolWidth = poolSize;
763 data.m_Parameters.m_PoolHeight = poolSize;
764 data.m_Parameters.m_StrideX = strideX;
765 data.m_Parameters.m_StrideY = strideY;
766 data.m_Parameters.m_PadLeft = padX;
767 data.m_Parameters.m_PadRight = padX;
768 data.m_Parameters.m_PadTop = padY;
769 data.m_Parameters.m_PadBottom = padY;
770 data.m_Parameters.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
771
772 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
773 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refWorkloadFactory.CreateTensorHandle(inputTensorInfo);
774
775 // Don't execute if Pooling is not supported, as an exception will be raised.
David Beck79141b92018-10-23 16:09:36 +0100776 armnn::BackendId backend = workloadFactory.GetBackendId();
telsoa014fcda012018-03-09 14:13:49 +0000777 const size_t reasonIfUnsupportedMaxLen = 255;
778 char reasonIfUnsupported[reasonIfUnsupportedMaxLen+1];
David Beck79141b92018-10-23 16:09:36 +0100779 comparisonResult.supported = armnn::IsPooling2dSupported(backend, inputTensorInfo, outputTensorInfo,
telsoa014fcda012018-03-09 14:13:49 +0000780 data.m_Parameters,
781 reasonIfUnsupported, reasonIfUnsupportedMaxLen);
782 if (!comparisonResult.supported)
783 {
784 return comparisonResult;
785 }
786
787 armnn::Pooling2dQueueDescriptor refData = data;
788 armnn::WorkloadInfo refInfo = info;
789 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
790 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
791
792 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePooling2d(data, info);
793 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreatePooling2d(refData, refInfo);
794
795 outputHandleRef->Allocate();
796 inputHandleRef->Allocate();
797 inputHandle->Allocate();
798 outputHandle->Allocate();
799
800 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
801 CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0][0][0]);
802
803 workload->Execute();
804 workloadRef->Execute();
805
806 CopyDataFromITensorHandle(&comparisonResult.output[0][0][0][0], outputHandle.get());
807 CopyDataFromITensorHandle(&comparisonResult.outputExpected[0][0][0][0], outputHandleRef.get());
808
809 return comparisonResult;
810}
811
812//
813// Tests max pooling with the following parameters:
814//
815// Pooling size: 2x2
816// Stride: (2,2)
817// input size: 4x4
818// channels: 1
819// batch size: 1
820//
821template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000822LayerTestResult<T, 4> SimpleMaxPooling2dSize2x2Stride2x2TestCommon(
823 armnn::IWorkloadFactory& workloadFactory,
824 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
825 bool forceNoPadding,
826 float qScale = 1.0f,
827 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000828{
829 armnn::Pooling2dDescriptor descriptor;
830 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
831 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
832 descriptor.m_StrideX = 2;
833 descriptor.m_StrideY = 2;
834 descriptor.m_PadLeft = descriptor.m_PadRight = forceNoPadding ? 0 : 3;
835 descriptor.m_PadTop = descriptor.m_PadBottom = 0;
836 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
837 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
838
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000839
telsoa014fcda012018-03-09 14:13:49 +0000840 unsigned int inputWidth = 4;
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000841
telsoa014fcda012018-03-09 14:13:49 +0000842 unsigned int inputHeight = 4;
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000843
telsoa014fcda012018-03-09 14:13:49 +0000844 unsigned int outputWidth =
845 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
846 descriptor.m_StrideX;
847 unsigned int outputHeight =
848 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
849 descriptor.m_StrideY;
850 unsigned int channels = 1;
851 unsigned int batchSize = 1;
852
853 std::vector<float> inputData = {
854 510.0f, 222.0f, 780.0f, 654.0f,
855 141.0f, 276.0f, 15.0f, 546.0f,
856 303.0f, 618.0f, 582.0f, 339.0f,
857 438.0f, 564.0f, 573.0f, 402.0f
858 };
859
telsoa01c577f2c2018-08-31 09:22:23 +0100860 // 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 +0000861 std::vector<float> expectedOutputDataWithPadding = {
862 0.0f, 510.0f, 780.0f, 654.0f, 0.0f,
863 0.0f, 438.0f, 618.0f, 402.0f, 0.0f
864 };
865
866 std::vector<float> expectedOutputDataNoPadding = {
867 510.0f, 780.0f,
868 618.0f, 582.0f
869 };
870
871 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
872
873 // Scale and offset should match input - we're just calculating maximum values.
874 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
875
876 // Set quantization parameters if the requested type is a quantized type.
877 if(armnn::IsQuantizedType<T>())
878 {
879 inputTensorInfo.SetQuantizationScale(qScale);
880 inputTensorInfo.SetQuantizationOffset(qOffset);
881 outputTensorInfo.SetQuantizationScale(qScale);
882 outputTensorInfo.SetQuantizationOffset(qOffset);
883 }
884
885 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
886
887 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
888 forceNoPadding ? QuantizedVector<T>(qScale, qOffset, expectedOutputDataNoPadding) :
889 QuantizedVector<T>(qScale, qOffset, expectedOutputDataWithPadding));
890
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000891 return SimplePooling2dTestImpl<T>(
892 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +0000893}
894
surmeh01bceff2f2018-03-29 16:29:27 +0100895//
896// Tests max pooling with the following parameters:
897//
898// Pooling size: 3x2
899// Stride: (2,2)
900// input size: 3x2
901// channels: 1
902// batch size: 1
903//
904template<typename T>
905LayerTestResult<T, 4> IgnorePaddingAveragePooling2dSize3x2Stride2x2TestCommon(
906 armnn::IWorkloadFactory& workloadFactory,
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000907 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
surmeh01bceff2f2018-03-29 16:29:27 +0100908 bool forceNoPadding,
909 float qScale = 1.0f,
910 int32_t qOffset = 0)
911{
912 armnn::Pooling2dDescriptor descriptor;
913 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
914 descriptor.m_PoolWidth = 3;
915 descriptor.m_PoolHeight = 2;
916 descriptor.m_StrideX = 2;
917 descriptor.m_StrideY = 2;
918 descriptor.m_PadLeft = (forceNoPadding) ? 0 : 1;
919 descriptor.m_PadRight = descriptor.m_PadLeft;
920 descriptor.m_PadTop = 0;
921 descriptor.m_PadBottom = 0;
922 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
923 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
924
925 unsigned int inputWidth = 3;
926 unsigned int inputHeight = 2;
927 unsigned int outputWidth =
928 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
929 descriptor.m_StrideX;
930 unsigned int outputHeight =
931 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
932 descriptor.m_StrideY;
933 unsigned int channels = 1;
934 unsigned int batchSize = 1;
935
936 std::vector<float> inputData = {
937 3.0f, 6.0f, 9.0f,
938 12.0f, 15.0f, 18.0f,
939 };
940
941 std::vector<float> expectedOutputDataWithPadding = {
942 6.0f, 8.0f,
943 };
944
945 std::vector<float> expectedOutputDataNoPadding = {
946 10.5f,
947 };
948
949 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
950
951 // Scale and offset should match input - we're just calculating average values.
952 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, 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, QuantizedVector<T>(qScale, qOffset, inputData));
964
965 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
966 forceNoPadding ? QuantizedVector<T>(qScale, qOffset, expectedOutputDataNoPadding) :
967 QuantizedVector<T>(qScale, qOffset, expectedOutputDataWithPadding));
968
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000969 return SimplePooling2dTestImpl<T>(
970 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
surmeh01bceff2f2018-03-29 16:29:27 +0100971}
972
973
telsoa014fcda012018-03-09 14:13:49 +0000974template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000975LayerTestResult<T, 4> IgnorePaddingSimpleMaxPooling2dTestCommon(
976 armnn::IWorkloadFactory& workloadFactory,
977 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
978 float qScale = 1.0f,
979 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000980{
981 armnn::Pooling2dDescriptor descriptor;
982 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
983 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
984 descriptor.m_StrideX = descriptor.m_StrideY = 2;
985 descriptor.m_PadLeft = 1;
986 descriptor.m_PadRight = 1;
987 descriptor.m_PadTop = 1;
988 descriptor.m_PadBottom = 1;
989 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
990
991 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
992 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
993
994 // Set quantization parameters if the requested type is a quantized type.
995 if(armnn::IsQuantizedType<T>())
996 {
997 inputTensorInfo.SetQuantizationScale(qScale);
998 inputTensorInfo.SetQuantizationOffset(qOffset);
999 outputTensorInfo.SetQuantizationScale(qScale);
1000 outputTensorInfo.SetQuantizationOffset(qOffset);
1001 }
1002
1003 auto input = MakeTensor<T, 4>(inputTensorInfo,
1004 QuantizedVector<T>(qScale, qOffset, {
1005 -1.0f, -2.0f, 3.0f, 4.0f,
1006 -1.0f, -2.0f, 3.0f, 4.0f,
1007 1.0f, 2.0f, -3.0f, -4.0f,
1008 1.0f, 2.0f, -3.0f, -4.0f,
1009 }));
1010
1011 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1012 QuantizedVector<T>(qScale, qOffset, {
1013 -1.0f, 3.0f, 4.0f,
1014 1.0f, 3.0f, 4.0f,
1015 1.0f, 2.0f, -4.0f,
1016 }));
1017
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001018 return SimplePooling2dTestImpl<T>(
1019 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001020}
1021
1022template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001023LayerTestResult<T, 4> IgnorePaddingMaxPooling2dSize3TestCommon(
1024 armnn::IWorkloadFactory& workloadFactory,
1025 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1026 float qScale = 1.0f,
1027 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001028{
1029 armnn::Pooling2dDescriptor descriptor;
1030 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
1031 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1032 descriptor.m_StrideX = descriptor.m_StrideY = 1;
1033 descriptor.m_PadLeft = 1;
1034 descriptor.m_PadRight = 1;
1035 descriptor.m_PadTop = 1;
1036 descriptor.m_PadBottom = 1;
1037 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1038
1039 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1040 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1041
1042 // Set quantization parameters if the requested type is a quantized type.
1043 if(armnn::IsQuantizedType<T>())
1044 {
1045 inputTensorInfo.SetQuantizationScale(qScale);
1046 inputTensorInfo.SetQuantizationOffset(qOffset);
1047 outputTensorInfo.SetQuantizationScale(qScale);
1048 outputTensorInfo.SetQuantizationOffset(qOffset);
1049 }
1050
1051 auto input = MakeTensor<T, 4>(inputTensorInfo,
1052 QuantizedVector<T>(qScale, qOffset, {
1053 -1.0f, -2.0f, 3.0f, 4.0f,
1054 -1.0f, -2.0f, 3.0f, 4.0f,
1055 1.0f, 2.0f, -3.0f, -4.0f,
1056 1.0f, 2.0f, -3.0f, -4.0f,
1057 }));
1058
1059 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1060 QuantizedVector<T>(qScale, qOffset, {
1061 -1.0f, 3.0f, 4.0f, 4.0f,
1062 2.0f, 3.0f, 4.0f, 4.0f,
1063 2.0f, 3.0f, 4.0f, 4.0f,
1064 2.0f, 2.0f, 2.0f, -3.0f,
1065 }));
1066
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001067 return SimplePooling2dTestImpl<T>(
1068 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001069}
1070
1071template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001072LayerTestResult<T, 4> IgnorePaddingSimpleAveragePooling2dTestCommon(
1073 armnn::IWorkloadFactory& workloadFactory,
1074 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1075 float qScale = 1.0f,
1076 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001077{
1078 armnn::Pooling2dDescriptor descriptor;
1079 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
1080 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
1081 descriptor.m_StrideX = descriptor.m_StrideY = 2;
1082 descriptor.m_PadLeft = 1;
1083 descriptor.m_PadRight = 1;
1084 descriptor.m_PadTop = 1;
1085 descriptor.m_PadBottom = 1;
1086 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1087
1088 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1089 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
1090
1091 // Set quantization parameters if the requested type is a quantized type.
1092 if(armnn::IsQuantizedType<T>())
1093 {
1094 inputTensorInfo.SetQuantizationScale(qScale);
1095 inputTensorInfo.SetQuantizationOffset(qOffset);
1096 outputTensorInfo.SetQuantizationScale(qScale);
1097 outputTensorInfo.SetQuantizationOffset(qOffset);
1098 }
1099
1100 auto input = MakeTensor<T, 4>(inputTensorInfo,
1101 QuantizedVector<T>(qScale, qOffset, {
1102 12.0f, 20.0f, 32.0f, 40.0f,
1103 12.0f, 20.0f, 32.0f, 40.0f,
1104 12.0f, 20.0f, 32.0f, 40.0f,
1105 12.0f, 20.0f, 32.0f, 40.0f,
1106 }));
1107
1108 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1109 QuantizedVector<T>(qScale, qOffset, {
1110 3.0f, 13.0f, 10.0f,
1111 6.0f, 26.0f, 20.0f,
1112 3.0f, 13.0f, 10.0f,
1113 }));
1114
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001115 return SimplePooling2dTestImpl<T>(
1116 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001117}
1118
1119template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001120LayerTestResult<T, 4> IgnorePaddingSimpleAveragePooling2dNoPaddingTestCommon(
1121 armnn::IWorkloadFactory& workloadFactory,
1122 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1123 float qScale = 1.0f,
1124 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001125{
1126 armnn::Pooling2dDescriptor descriptor;
1127 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
1128 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1129 descriptor.m_StrideX = descriptor.m_StrideY = 2;
1130 descriptor.m_PadLeft = 0;
1131 descriptor.m_PadRight = 0;
1132 descriptor.m_PadTop = 0;
1133 descriptor.m_PadBottom = 0;
1134 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1135 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
1136
1137 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4}, armnn::GetDataType<T>());
1138 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
1139
1140 // Set quantization parameters if the requested type is a quantized type.
1141 if(armnn::IsQuantizedType<T>())
1142 {
1143 inputTensorInfo.SetQuantizationScale(qScale);
1144 inputTensorInfo.SetQuantizationOffset(qOffset);
1145 outputTensorInfo.SetQuantizationScale(qScale);
1146 outputTensorInfo.SetQuantizationOffset(qOffset);
1147 }
1148
1149 auto input = MakeTensor<T, 4>(inputTensorInfo,
1150 QuantizedVector<T>(qScale, qOffset, {
1151 1.0f, 2.0f, 3.0f, 4.0f,
1152 1.0f, 2.0f, 3.0f, 4.0f,
1153 1.0f, 2.0f, 3.0f, 4.0f,
1154 1.0f, 2.0f, 3.0f, 4.0f,
1155 }));
1156
1157 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1158 QuantizedVector<T>(qScale, qOffset, {
1159 2.0f, 3.5f,
1160 2.0f, 3.5f
1161 }));
1162
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001163 return SimplePooling2dTestImpl<T>(
1164 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001165}
1166
1167template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001168LayerTestResult<T, 4> IgnorePaddingAveragePooling2dSize3TestCommon(
1169 armnn::IWorkloadFactory& workloadFactory,
1170 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1171 float qScale = 1.0f,
1172 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001173{
1174 armnn::Pooling2dDescriptor descriptor;
1175 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
1176 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1177 descriptor.m_StrideX = descriptor.m_StrideY = 1;
1178 descriptor.m_PadLeft = 1;
1179 descriptor.m_PadRight = 1;
1180 descriptor.m_PadTop = 1;
1181 descriptor.m_PadBottom = 1;
1182 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1183
1184 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1185 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1186
1187 // Set quantization parameters if the requested type is a quantized type.
1188 if(armnn::IsQuantizedType<T>())
1189 {
1190 inputTensorInfo.SetQuantizationScale(qScale);
1191 inputTensorInfo.SetQuantizationOffset(qOffset);
1192 outputTensorInfo.SetQuantizationScale(qScale);
1193 outputTensorInfo.SetQuantizationOffset(qOffset);
1194 }
1195
1196 auto input = MakeTensor<T, 4>(inputTensorInfo,
1197 QuantizedVector<T>(qScale, qOffset, {
1198 9.0f, 27.0f, 18.0f, 36.0f,
1199 18.0f, 9.0f, 18.0f, 9.0f,
1200 27.0f, 18.0f, 9.0f, 27.0f,
1201 9.0f, 27.0f, 9.0f, 18.0f,
1202 }));
1203
1204 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1205 QuantizedVector<T>(qScale, qOffset, {
1206 7.0f, 11.0f, 13.0f, 9.0f,
1207 12.0f, 17.0f, 19.0f, 13.0f,
1208 12.0f, 16.0f, 16.0f, 10.0f,
1209 9.0f, 11.0f, 12.0f, 7.0f,
1210 }));
1211
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001212 return SimplePooling2dTestImpl<T>(
1213 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001214}
1215
1216template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001217LayerTestResult<T, 4> IgnorePaddingSimpleL2Pooling2dTestCommon(
1218 armnn::IWorkloadFactory& workloadFactory,
1219 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1220 float qScale = 1.0f,
1221 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001222{
1223 armnn::Pooling2dDescriptor descriptor;
1224 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
1225 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
1226 descriptor.m_StrideX = descriptor.m_StrideY = 2;
1227 descriptor.m_PadLeft = 1;
1228 descriptor.m_PadRight = 1;
1229 descriptor.m_PadTop = 1;
1230 descriptor.m_PadBottom = 1;
1231 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1232
1233 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1234 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
1235
1236 // Set quantization parameters if the requested type is a quantized type.
1237 if(armnn::IsQuantizedType<T>())
1238 {
1239 inputTensorInfo.SetQuantizationScale(qScale);
1240 inputTensorInfo.SetQuantizationOffset(qOffset);
1241 outputTensorInfo.SetQuantizationScale(qScale);
1242 outputTensorInfo.SetQuantizationOffset(qOffset);
1243 }
1244
1245 auto input = MakeTensor<T, 4>(inputTensorInfo,
1246 QuantizedVector<T>(qScale, qOffset, {
1247 2.0f, 4.0f, 8.0f, 16.0f,
1248 4.0f, 2.0f, 2.0f, 4.0f,
1249 8.0f, 2.0f, 4.0f, 2.0f,
1250 16.0f, 2.0f, 2.0f, 8.0f,
1251 }));
1252
1253 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1254 QuantizedVector<T>(qScale, qOffset, {
1255 1.0f, 4.4721f, 8.0f,
1256 4.4721f, 2.6457f, 2.236f,
1257 8.0f, 1.4142f, 4.0f,
1258 }));
1259
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001260 return SimplePooling2dTestImpl<T>(
1261 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001262}
1263
1264template<typename T>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001265LayerTestResult<T, 4> IgnorePaddingL2Pooling2dSize3TestCommon(
1266 armnn::IWorkloadFactory& workloadFactory,
1267 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
1268 float qScale = 1.0f,
1269 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +00001270{
1271 armnn::Pooling2dDescriptor descriptor;
1272 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
1273 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1274 descriptor.m_StrideX = descriptor.m_StrideY = 1;
1275 descriptor.m_PadLeft = 1;
1276 descriptor.m_PadRight = 1;
1277 descriptor.m_PadTop = 1;
1278 descriptor.m_PadBottom = 1;
1279 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1280
1281 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1282 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1283
1284 // Set quantization parameters if the requested type is a quantized type.
1285 if(armnn::IsQuantizedType<T>())
1286 {
1287 inputTensorInfo.SetQuantizationScale(qScale);
1288 inputTensorInfo.SetQuantizationOffset(qOffset);
1289 outputTensorInfo.SetQuantizationScale(qScale);
1290 outputTensorInfo.SetQuantizationOffset(qOffset);
1291 }
1292
1293 auto input = MakeTensor<T, 4>(inputTensorInfo,
1294 QuantizedVector<T>(qScale, qOffset, {
1295 1.0f, 2.0f, 3.0f, 4.0f,
1296 1.0f, 2.0f, 3.0f, 4.0f,
1297 1.0f, 2.0f, 3.0f, 4.0f,
1298 1.0f, 2.0f, 3.0f, 4.0f,
1299 }));
1300
1301 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1302 QuantizedVector<T>(qScale, qOffset, {
1303 1.0540f, 1.7638f, 2.5385f, 2.3570f,
1304 1.2909f, 2.1602f, 3.1091f, 2.8867f,
1305 1.2909f, 2.1602f, 3.1091f, 2.8867f,
1306 1.0540f, 1.7638f, 2.5385f, 2.3570f,
1307 }));
1308
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +00001309 return SimplePooling2dTestImpl<T>(
1310 workloadFactory, memoryManager, descriptor, qScale, qOffset, input, outputExpected);
telsoa014fcda012018-03-09 14:13:49 +00001311}