blob: eea423275cf30023ed3b98de6e9e155c8c5f0e88 [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
James Conroy45a9b772018-10-31 11:47:53 +00007#include <string>
telsoa014fcda012018-03-09 14:13:49 +00008#include <armnn/ArmNN.hpp>
telsoa014fcda012018-03-09 14:13:49 +00009
David Beckac42efd2018-09-26 17:41:13 +010010#include <test/TensorHelpers.hpp>
telsoa014fcda012018-03-09 14:13:49 +000011#include "QuantizeHelper.hpp"
12
David Beckac42efd2018-09-26 17:41:13 +010013#include <backends/CpuTensorHandle.hpp>
14#include <backends/WorkloadFactory.hpp>
Francis Murtagh043d0d02018-10-05 14:08:48 +010015#include <backends/WorkloadInfo.hpp>
telsoa014fcda012018-03-09 14:13:49 +000016#include <algorithm>
James Conroy45a9b772018-10-31 11:47:53 +000017#include "Permute.hpp"
18#include <boost/numeric/conversion/cast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000019
20template<typename T>
James Conroy69482272018-10-19 10:41:35 +010021LayerTestResult<T, 4> SimplePooling2dTestImpl(armnn::IWorkloadFactory& workloadFactory,
Francis Murtagh043d0d02018-10-05 14:08:48 +010022 armnn::Pooling2dDescriptor descriptor,
23 float qScale,
24 int32_t qOffset,
25 const boost::multi_array<T, 4>& input,
26 const boost::multi_array<T, 4>& outputExpected)
telsoa014fcda012018-03-09 14:13:49 +000027{
James Conroy45a9b772018-10-31 11:47:53 +000028 const armnn::DataLayoutIndexed dataLayout = descriptor.m_DataLayout;
29 auto heightIndex = dataLayout.GetHeightIndex();
30 auto widthIndex = dataLayout.GetWidthIndex();
31 auto channelsIndex = dataLayout.GetChannelsIndex();
telsoa014fcda012018-03-09 14:13:49 +000032
James Conroy69482272018-10-19 10:41:35 +010033 unsigned int inputHeight = boost::numeric_cast<unsigned int>(input.shape()[heightIndex]);
34 unsigned int inputWidth = boost::numeric_cast<unsigned int>(input.shape()[widthIndex]);
35 unsigned int inputChannels = boost::numeric_cast<unsigned int>(input.shape()[channelsIndex]);
36 unsigned int inputBatchSize = boost::numeric_cast<unsigned int>(input.shape()[0]);
37
38 unsigned int outputHeight = boost::numeric_cast<unsigned int>(outputExpected.shape()[heightIndex]);
39 unsigned int outputWidth = boost::numeric_cast<unsigned int>(outputExpected.shape()[widthIndex]);
40 unsigned int outputChannels = boost::numeric_cast<unsigned int>(outputExpected.shape()[channelsIndex]);
telsoa014fcda012018-03-09 14:13:49 +000041 unsigned int outputBatchSize = boost::numeric_cast<unsigned int>(outputExpected.shape()[0]);
42
James Conroy45a9b772018-10-31 11:47:53 +000043 armnn::TensorInfo inputTensorInfo = GetTensorInfo<T>(inputBatchSize, inputChannels, inputHeight,
44 inputWidth, dataLayout);
45 armnn::TensorInfo outputTensorInfo = GetTensorInfo<T>(outputBatchSize, outputChannels, outputHeight,
46 outputWidth, dataLayout);
telsoa014fcda012018-03-09 14:13:49 +000047
48 // Set quantization parameters if the requested type is a quantized type.
49 if(armnn::IsQuantizedType<T>())
50 {
51 inputTensorInfo.SetQuantizationScale(qScale);
52 inputTensorInfo.SetQuantizationOffset(qOffset);
53 outputTensorInfo.SetQuantizationScale(qScale);
54 outputTensorInfo.SetQuantizationOffset(qOffset);
55 }
56
57 LayerTestResult<T, 4> result(outputTensorInfo);
58
59 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
60 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
61
62 armnn::Pooling2dQueueDescriptor queueDescriptor;
63 queueDescriptor.m_Parameters = descriptor;
James Conroy45a9b772018-10-31 11:47:53 +000064 queueDescriptor.m_Parameters.m_DataLayout = dataLayout;
Francis Murtagh043d0d02018-10-05 14:08:48 +010065
66 armnn::WorkloadInfo workloadInfo;
67 AddInputToWorkload(queueDescriptor, workloadInfo, inputTensorInfo, inputHandle.get());
68 AddOutputToWorkload(queueDescriptor, workloadInfo, outputTensorInfo, outputHandle.get());
69
70 // Don't execute if Pooling is not supported, as an exception will be raised.
David Beck79141b92018-10-23 16:09:36 +010071 armnn::BackendId backend = workloadFactory.GetBackendId();
Francis Murtagh043d0d02018-10-05 14:08:48 +010072 const size_t reasonIfUnsupportedMaxLen = 255;
73 char reasonIfUnsupported[reasonIfUnsupportedMaxLen+1];
David Beck79141b92018-10-23 16:09:36 +010074 result.supported = armnn::IsPooling2dSupported(backend, inputTensorInfo, outputTensorInfo,
Francis Murtagh043d0d02018-10-05 14:08:48 +010075 queueDescriptor.m_Parameters,
76 reasonIfUnsupported, reasonIfUnsupportedMaxLen);
77 if (!result.supported)
78 {
79 return result;
80 }
81
82 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePooling2d(queueDescriptor, workloadInfo);
83
84 inputHandle->Allocate();
85 outputHandle->Allocate();
86
87 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
88
89 workload->Execute();
90
91 CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
92
93 result.outputExpected = outputExpected;
94
95 return result;
96}
97
telsoa014fcda012018-03-09 14:13:49 +000098//
99// Tests max pooling with the following parameters:
100//
101// Pooling size: 3x3
102// Stride: (2,4)
103// input size: 8x13
104// channels: 2
105// batch size: 2
106//
107template<typename T>
108LayerTestResult<T, 4> SimpleMaxPooling2dSize3x3Stride2x4TestCommon(armnn::IWorkloadFactory& workloadFactory,
109 bool forceNoPadding,
110 float qScale = 1.0f,
111 int32_t qOffset = 0)
112{
113 armnn::Pooling2dDescriptor descriptor;
114 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
115 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
116 descriptor.m_StrideX = 2;
117 descriptor.m_StrideY = 4;
118 // forceNoPadding is mainly used for compatibility with ARM Compute.
119 // As of 16/05/2017, it errors if padX or padY are equal to or greater than the pool size.
120 descriptor.m_PadLeft = descriptor.m_PadRight = forceNoPadding ? 0 : 3;
121 descriptor.m_PadTop = descriptor.m_PadBottom = 0;
122 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
123 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
124
125 unsigned int inputWidth = 8;
126 unsigned int inputHeight = 13;
127 unsigned int outputWidth =
128 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
129 descriptor.m_StrideX;
130 unsigned int outputHeight =
131 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
132 descriptor.m_StrideY;
133 unsigned int channels = 2;
134 unsigned int batchSize = 2;
135
136 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
137 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
138
139 // Set quantization parameters if the requested type is a quantized type.
140 if(armnn::IsQuantizedType<T>())
141 {
142 inputTensorInfo.SetQuantizationScale(qScale);
143 inputTensorInfo.SetQuantizationOffset(qOffset);
144 outputTensorInfo.SetQuantizationScale(qScale);
145 outputTensorInfo.SetQuantizationOffset(qOffset);
146 }
147
148 std::vector<float> singleChannelData({
149 0.0f, 4.0f, 8.0f, 1.0f, 6.0f, 4.0f, 5.0f, 8.0f,
150 1.0f, 1.0f, 6.0f, 0.0f, 3.0f, 7.0f, 4.0f, 7.0f,
151 8.0f, 5.0f, 0.0f, 0.0f, 8.0f, 3.0f, 4.0f, 3.0f,
152 8.0f, 2.0f, 5.0f, 4.0f, 1.0f, 9.0f, 2.0f, 0.0f,
153 5.0f, 4.0f, 5.0f, 0.0f, 0.0f, 0.0f, 7.0f, 2.0f,
154 1.0f, 2.0f, 6.0f, 2.0f, 7.0f, 9.0f, 5.0f, 2.0f,
155 9.0f, 7.0f, 3.0f, 1.0f, 3.0f, 4.0f, 8.0f, 3.0f,
156 1.0f, 0.0f, 0.0f, 5.0f, 5.0f, 4.0f, 2.0f, 0.0f,
157 6.0f, 4.0f, 3.0f, 6.0f, 9.0f, 5.0f, 5.0f, 6.0f,
158 8.0f, 7.0f, 9.0f, 6.0f, 1.0f, 4.0f, 1.0f, 9.0f,
159 7.0f, 1.0f, 9.0f, 2.0f, 9.0f, 9.0f, 8.0f, 1.0f,
160 4.0f, 4.0f, 5.0f, 9.0f, 2.0f, 6.0f, 6.0f, 4.0f,
161 3.0f, 5.0f, 4.0f, 0.0f, 1.0f, 5.0f, 9.0f, 7.0f,
162 });
163
telsoa01c577f2c2018-08-31 09:22:23 +0100164 // Constructs input data.
telsoa014fcda012018-03-09 14:13:49 +0000165 std::vector<float> inputData;
166 auto negator = [](float f) { return -f; };
167
telsoa01c577f2c2018-08-31 09:22:23 +0100168 // First image (two channels where the second channel is the negative of the first one).
telsoa014fcda012018-03-09 14:13:49 +0000169 inputData.insert(inputData.end(), singleChannelData.begin(), singleChannelData.end());
170 std::transform(singleChannelData.begin(), singleChannelData.end(), std::back_inserter(inputData), negator);
171
telsoa01c577f2c2018-08-31 09:22:23 +0100172 // Second image (same as first image).
telsoa014fcda012018-03-09 14:13:49 +0000173 inputData.insert(inputData.end(), singleChannelData.begin(), singleChannelData.end());
174 std::transform(singleChannelData.begin(), singleChannelData.end(), std::back_inserter(inputData), negator);
175
176 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
177
telsoa01c577f2c2018-08-31 09:22:23 +0100178 // These were calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000179 auto shape(GetTensorShapeAsArray<4>(outputTensorInfo));
180 boost::multi_array<T, 4> outputExpected(shape);
181 if (forceNoPadding)
182 {
183 outputExpected = MakeTensor<T, 4>(outputTensorInfo,
184 QuantizedVector<T>(qScale, qOffset, {
185 8.0f, 8.0f, 8.0f,
186 9.0f, 7.0f, 9.0f,
187 9.0f, 9.0f, 9.0f,
188
189 0.0f, 0.0f, -3.0f,
190 -1.0f, 0.0f, 0.0f,
191 -1.0f, -1.0f, -1.0f,
192
193 8.0f, 8.0f, 8.0f,
194 9.0f, 7.0f, 9.0f,
195 9.0f, 9.0f, 9.0f,
196
197 0.0f, 0.0f, -3.0f,
198 -1.0f, 0.0f, 0.0f,
199 -1.0f, -1.0f, -1.0f
200 }));
201 }
202 else
203 {
204 outputExpected = MakeTensor<T, 4>(outputTensorInfo,
205 QuantizedVector<T>(qScale, qOffset, {
206 0.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f,
207 0.0f, 9.0f, 7.0f, 9.0f, 9.0f, 3.0f,
208 0.0f, 8.0f, 9.0f, 9.0f, 9.0f, 9.0f,
209
210 0.0f, 0.0f, 0.0f, 0.0f,-3.0f, 0.0f,
211 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
212 0.0f,-1.0f,-1.0f,-1.0f,-1.0f, 0.0f,
213
214 0.0f, 8.0f, 8.0f, 8.0f, 8.0f, 8.0f,
215 0.0f, 9.0f, 7.0f, 9.0f, 9.0f, 3.0f,
216 0.0f, 8.0f, 9.0f, 9.0f, 9.0f, 9.0f,
217
218 0.0f, 0.0f, 0.0f, 0.0f,-3.0f, 0.0f,
219 0.0f,-1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
220 0.0f,-1.0f,-1.0f,-1.0f,-1.0f, 0.0f
221 }));
222 }
223
224 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
225}
226
227template<typename T>
James Conroy45a9b772018-10-31 11:47:53 +0000228LayerTestResult<T, 4> SimpleMaxPooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
229 const armnn::DataLayoutIndexed& dataLayout = armnn::DataLayout::NCHW,
230 float qScale = 1.0f,
231 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000232{
233 armnn::Pooling2dDescriptor descriptor;
James Conroy45a9b772018-10-31 11:47:53 +0000234 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
telsoa014fcda012018-03-09 14:13:49 +0000235 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
236 descriptor.m_StrideX = descriptor.m_StrideY = 2;
telsoa014fcda012018-03-09 14:13:49 +0000237 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
James Conroy69482272018-10-19 10:41:35 +0100238 descriptor.m_DataLayout = dataLayout;
telsoa014fcda012018-03-09 14:13:49 +0000239
James Conroy45a9b772018-10-31 11:47:53 +0000240 armnn::TensorInfo inputTensorInfo = GetTensorInfo<T>(1, 2, 4, 4, dataLayout);
241 armnn::TensorInfo outputTensorInfo = GetTensorInfo<T>(1, 2, 2, 2, dataLayout);
telsoa014fcda012018-03-09 14:13:49 +0000242
243 // Set quantization parameters if the requested type is a quantized type.
244 if(armnn::IsQuantizedType<T>())
245 {
246 inputTensorInfo.SetQuantizationScale(qScale);
247 inputTensorInfo.SetQuantizationOffset(qOffset);
248 outputTensorInfo.SetQuantizationScale(qScale);
249 outputTensorInfo.SetQuantizationOffset(qOffset);
250 }
251
James Conroy45a9b772018-10-31 11:47:53 +0000252 std::vector<T> inputData(
telsoa014fcda012018-03-09 14:13:49 +0000253 QuantizedVector<T>(qScale, qOffset, {
James Conroy45a9b772018-10-31 11:47:53 +0000254 1.0f, 2.0f, 5.0f, 6.0f,
255 3.0f, 4.0f, 7.0f, 8.0f,
256 9.0f, 10.0f, 13.0f, 14.0f,
257 11.0f, 12.0f, 15.0f, 16.0f,
258
259 17.0f, 18.0f, 21.0f, 22.0f,
260 19.0f, 20.0f, 23.0f, 24.0f,
261 25.0f, 26.0f, 29.0f, 30.0f,
262 27.0f, 28.0f, 31.0f, 32.0f,
telsoa014fcda012018-03-09 14:13:49 +0000263 }));
264
James Conroy45a9b772018-10-31 11:47:53 +0000265 std::vector<T> outputData(
telsoa014fcda012018-03-09 14:13:49 +0000266 QuantizedVector<T>(qScale, qOffset, {
James Conroy45a9b772018-10-31 11:47:53 +0000267 4.0f, 8.0f,
268 12.0f, 16.0f,
269
270 20.0f, 24.0f,
271 28.0f, 32.0f,
telsoa014fcda012018-03-09 14:13:49 +0000272 }));
273
James Conroy45a9b772018-10-31 11:47:53 +0000274 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
275 if (dataLayout.GetDataLayout() == armnn::DataLayout::NHWC)
276 {
277 std::vector<T> tmp(inputData.size());
278 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data());
279 inputData = tmp;
280
281 std::vector<T> tmp1(outputData.size());
282 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data());
283 outputData = tmp1;
284 }
285
286 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
287
288 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
289
telsoa014fcda012018-03-09 14:13:49 +0000290 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
291}
292
293template<typename T>
James Conroy45a9b772018-10-31 11:47:53 +0000294LayerTestResult<T, 4> SimpleAveragePooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
295 armnn::DataLayoutIndexed dataLayout = armnn::DataLayout::NCHW,
296 float qScale = 1.0f,
297 int32_t qOffset = 0)
Francis Murtagh043d0d02018-10-05 14:08:48 +0100298{
James Conroy45a9b772018-10-31 11:47:53 +0000299 armnn::Pooling2dDescriptor descriptor;
300 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
301 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
302 descriptor.m_StrideX = descriptor.m_StrideY = 2;
303 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
304 descriptor.m_DataLayout = dataLayout;
Francis Murtagh043d0d02018-10-05 14:08:48 +0100305
James Conroy45a9b772018-10-31 11:47:53 +0000306 armnn::TensorInfo inputTensorInfo = GetTensorInfo<T>(1, 2, 4, 4, dataLayout);
307 armnn::TensorInfo outputTensorInfo = GetTensorInfo<T>(1, 2, 2, 2, dataLayout);
Francis Murtagh043d0d02018-10-05 14:08:48 +0100308
James Conroy45a9b772018-10-31 11:47:53 +0000309 // Set quantization parameters if the requested type is a quantized type.
310 if(armnn::IsQuantizedType<T>())
311 {
312 inputTensorInfo.SetQuantizationScale(qScale);
313 inputTensorInfo.SetQuantizationOffset(qOffset);
314 outputTensorInfo.SetQuantizationScale(qScale);
315 outputTensorInfo.SetQuantizationOffset(qOffset);
316 }
Francis Murtagh043d0d02018-10-05 14:08:48 +0100317
James Conroy45a9b772018-10-31 11:47:53 +0000318 std::vector<T> inputData(
319 QuantizedVector<T>(qScale, qOffset, {
320 2.0f, 2.0f, 6.0f, 6.0f,
321 4.0f, 4.0f, 8.0f, 8.0f,
322 10.0f, 12.0f, 14.0f, 16.0f,
323 10.0f, 12.0f, 16.0f, 14.0f,
324
325 18.0f, 20.0f, 24.0f, 22.0f,
326 20.0f, 18.0f, 22.0f, 24.0f,
327 26.0f, 28.0f, 0.0f, 0.0f,
328 26.0f, 28.0f, 0.0f, 0.0f,
329 }));
330
331 std::vector<T> outputData(
332 QuantizedVector<T>(qScale, qOffset, {
333 3.0f, 7.0f,
334 11.0f, 15.0f,
335
336 19.0f, 23.0f,
337 27.0f, 0.0f,
338 }));
339
340 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
341 if (dataLayout.GetDataLayout() == armnn::DataLayout::NHWC)
342 {
343 std::vector<T> tmp(inputData.size());
344 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data());
345 inputData = tmp;
346
347 std::vector<T> tmp1(outputData.size());
348 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data());
349 outputData = tmp1;
350 }
351
352 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
353
354 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
355
356 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
Francis Murtagh043d0d02018-10-05 14:08:48 +0100357}
358
359template<typename T>
telsoa014fcda012018-03-09 14:13:49 +0000360LayerTestResult<T, 4> LargeTensorsAveragePooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
James Conroy69482272018-10-19 10:41:35 +0100361 float qScale = 1.0f,
362 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000363{
364 armnn::Pooling2dDescriptor descriptor;
365 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
366 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 100;
367 descriptor.m_StrideX = descriptor.m_StrideY = 5;
368 descriptor.m_PadLeft = 50;
369 descriptor.m_PadRight = 50;
370 descriptor.m_PadTop = 50;
371 descriptor.m_PadBottom = 50;
372 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
373
374 armnn::TensorInfo inputTensorInfo({ 5, 3, 52, 60 }, armnn::GetDataType<T>());
375 armnn::TensorInfo outputTensorInfo({ 5, 3, 11, 13 }, armnn::GetDataType<T>());
376
377 // Set quantization parameters if the requested type is a quantized type.
378 if(armnn::IsQuantizedType<T>())
379 {
380 inputTensorInfo.SetQuantizationScale(qScale);
381 inputTensorInfo.SetQuantizationOffset(qOffset);
382 outputTensorInfo.SetQuantizationScale(qScale);
383 outputTensorInfo.SetQuantizationOffset(qOffset);
384 }
385
386 std::vector<T> inputVec;
387
388 for (unsigned int i = 0 ; i < inputTensorInfo.GetShape().GetNumElements(); ++i)
389 {
390 inputVec.push_back(1);
391 }
392
393 auto input = MakeTensor<T, 4>(inputTensorInfo, inputVec);
394
395 std::vector<T> outputVec;
396
397 for (unsigned int i = 0 ; i < outputTensorInfo.GetShape().GetNumElements(); ++i)
398 {
399 outputVec.push_back(1);
400 }
401
402 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputVec);
403
404 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
405}
406
407template<typename T>
408LayerTestResult<T, 4> SimpleL2Pooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
James Conroy45a9b772018-10-31 11:47:53 +0000409 armnn::DataLayoutIndexed dataLayout = armnn::DataLayout::NCHW,
telsoa014fcda012018-03-09 14:13:49 +0000410 float qScale = 1.0f,
411 int32_t qOffset = 0)
412{
413 armnn::Pooling2dDescriptor descriptor;
414 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
415 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
416 descriptor.m_StrideX = descriptor.m_StrideY = 2;
417 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
James Conroy45a9b772018-10-31 11:47:53 +0000418 descriptor.m_DataLayout = dataLayout;
telsoa014fcda012018-03-09 14:13:49 +0000419
James Conroy45a9b772018-10-31 11:47:53 +0000420 armnn::TensorInfo inputTensorInfo = GetTensorInfo<T>(1, 2, 4, 4, dataLayout);
421 armnn::TensorInfo outputTensorInfo = GetTensorInfo<T>(1, 2, 2, 2, dataLayout);
422
423 std::vector<T> inputData(
telsoa014fcda012018-03-09 14:13:49 +0000424 QuantizedVector<T>(qScale, qOffset, {
James Conroy45a9b772018-10-31 11:47:53 +0000425 1.0f, 7.0f, 5.0f, 5.0f,
426 1.0f, 7.0f, 5.0f, 5.0f,
427 3.0f, 3.0f, 1.0f, 1.0f,
428 3.0f, 3.0f, 1.0f, 1.0f,
429
430 1.0f, 7.0f, 0.0f, 0.0f,
431 1.0f, 7.0f, 2.0f, 0.0f,
432 0.0f, 2.0f, 1.0f, 1.0f,
433 0.0f, 0.0f, 1.0f, 1.0f,
telsoa014fcda012018-03-09 14:13:49 +0000434 }));
435
James Conroy45a9b772018-10-31 11:47:53 +0000436 std::vector<T> outputData(
telsoa014fcda012018-03-09 14:13:49 +0000437 QuantizedVector<T>(qScale, qOffset, {
438 5.0f, 5.0f,
James Conroy45a9b772018-10-31 11:47:53 +0000439 3.0f, 1.0f,
440
441 5.0f, 1.0f,
442 1.0f, 1.0f,
telsoa014fcda012018-03-09 14:13:49 +0000443 }));
444
James Conroy45a9b772018-10-31 11:47:53 +0000445 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
446 if (dataLayout.GetDataLayout() == armnn::DataLayout::NHWC)
447 {
448 std::vector<T> tmp(inputData.size());
449 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data());
450 inputData = tmp;
451
452 std::vector<T> tmp1(outputData.size());
453 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp1.data());
454 outputData = tmp1;
455 }
456
457 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
458
459 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
460
telsoa014fcda012018-03-09 14:13:49 +0000461 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
462}
463
464template<typename T>
465LayerTestResult<T, 4> L2Pooling2dSize3Stride1TestCommon(armnn::IWorkloadFactory& workloadFactory,
466 float qScale = 1.0f,
467 int32_t qOffset = 0)
468{
469 armnn::Pooling2dDescriptor descriptor;
470 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
471 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
472 descriptor.m_StrideX = descriptor.m_StrideY = 1;
473 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
474
475 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
476 auto input = MakeTensor<T, 4>(inputTensorInfo,
477 QuantizedVector<T>(qScale, qOffset, {
478 2.0f, 1.0f, 5.0f, 2.0f,
479 1.0f, 2.0f, 2.0f, 1.0f,
480 5.0f, 4.0f, 1.0f, 5.0f,
481 2.0f, 1.0f, 5.0f, 2.0f,
482 }));
483
484 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
485 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
486 QuantizedVector<T>(qScale, qOffset, {
487 3.0f, 3.0f,
488 3.0f, 3.0f,
489 }));
490
491 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
492}
493
494template<typename T>
495LayerTestResult<T, 4> L2Pooling2dSize3Stride3TestCommon(armnn::IWorkloadFactory& workloadFactory,
496 float qScale = 1.0f,
497 int32_t qOffset = 0)
498{
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 = 3;
503 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
504
505 armnn::TensorInfo inputTensorInfo({ 1, 1, 9, 9 }, armnn::GetDataType<T>());
506 auto input = MakeTensor<T, 4>(inputTensorInfo,
507 QuantizedVector<T>(qScale, qOffset, {
508 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
509 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
510 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
511 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
512 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
513 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
514 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
515 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
516 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
517 }));
518
519 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
520 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
521 QuantizedVector<T>(qScale, qOffset, {
522 3.0f, 3.0f, 3.0f,
523 3.0f, 3.0f, 3.0f,
524 3.0f, 3.0f, 3.0f,
525 }));
526
527 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
528}
529
530template<typename T>
531LayerTestResult<T, 4> L2Pooling2dSize3Stride4TestCommon(armnn::IWorkloadFactory& workloadFactory,
532 float qScale = 1.0f,
533 int32_t qOffset = 0)
534{
535 armnn::Pooling2dDescriptor descriptor;
536 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
537 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
538 descriptor.m_StrideX = descriptor.m_StrideY = 4;
539 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
540
541 armnn::TensorInfo inputTensorInfo({ 1, 1, 7, 7 }, armnn::GetDataType<T>());
542 auto input = MakeTensor<T, 4>(inputTensorInfo,
543 QuantizedVector<T>(qScale, qOffset, {
544 2.0f, 1.0f, 5.0f, 0.0f, 2.0f, 1.0f, 5.0f,
545 1.0f, 2.0f, 2.0f, 0.0f, 1.0f, 2.0f, 2.0f,
546 5.0f, 4.0f, 1.0f, 0.0f, 5.0f, 4.0f, 1.0f,
547 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
548 2.0f, 1.0f, 5.0f, 0.0f, 2.0f, 1.0f, 5.0f,
549 1.0f, 2.0f, 2.0f, 0.0f, 1.0f, 2.0f, 2.0f,
550 5.0f, 4.0f, 1.0f, 0.0f, 5.0f, 4.0f, 1.0f,
551 }));
552
553 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
554 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
555 QuantizedVector<T>(qScale, qOffset, {
556 3.0f, 3.0f,
557 3.0f, 3.0f,
558 }));
559
560 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
561}
562
563template<typename T>
564LayerTestResult<T, 4> L2Pooling2dSize7TestCommon(armnn::IWorkloadFactory& workloadFactory,
565 float qScale = 1.0f,
566 int32_t qOffset = 0)
567{
568 armnn::Pooling2dDescriptor descriptor;
569 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
570 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 7;
571 descriptor.m_StrideX = descriptor.m_StrideY = 7;
572 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
573
574 armnn::TensorInfo inputTensorInfo({ 1, 1, 7, 7 }, armnn::GetDataType<T>());
575 auto input = MakeTensor<T, 4>(inputTensorInfo,
576 QuantizedVector<T>(qScale, qOffset, {
577 1.0f, 0.0f, 2.0f, 0.0f, 3.0f, 0.0f, 4.0f,
578 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
579 0.0f, 5.0f, 0.0f, 6.0f, 0.0f, 7.0f, 0.0f,
580 8.0f, 0.0f, 9.0f, 0.0f, 10.0f, 0.0f, 5.0f,
581 0.0f, 5.0f, 0.0f, 2.0f, 0.0f, 1.0f, 1.0f,
582 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
583 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
584 }));
585
586 armnn::TensorInfo outputTensorInfo({ 1, 1, 1, 1 }, armnn::GetDataType<T>());
587 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
588 QuantizedVector<T>(qScale, qOffset, {
589 3.0f,
590 }));
591
592 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
593}
594
595template<typename T>
596LayerTestResult<T, 4> L2Pooling2dSize9TestCommon(armnn::IWorkloadFactory& workloadFactory,
597 float qScale = 1.0f,
598 int32_t qOffset = 0)
599{
600 armnn::Pooling2dDescriptor descriptor;
601 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
602 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 9;
603 descriptor.m_StrideX = descriptor.m_StrideY = 9;
604 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
605
606 armnn::TensorInfo inputTensorInfo({ 1, 1, 9, 9 }, armnn::GetDataType<T>());
607 auto input = MakeTensor<T, 4>(inputTensorInfo,
608 QuantizedVector<T>(qScale, qOffset, {
609 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
610 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
611 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
612 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
613 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
614 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
615 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f, 2.0f, 1.0f, 5.0f,
616 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f, 1.0f, 2.0f, 2.0f,
617 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f, 5.0f, 4.0f, 1.0f,
618 }));
619
620 armnn::TensorInfo outputTensorInfo({ 1, 1, 1, 1 }, armnn::GetDataType<T>());
621 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
622 QuantizedVector<T>(qScale, qOffset, {
623 3.0f,
624 }));
625
626 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
627}
628
629template<typename T>
630LayerTestResult<T, 4> AsymmetricNonSquarePooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
631 float qScale = 1.0f,
632 int32_t qOffset = 0)
633{
634 armnn::TensorInfo inputTensorInfo({ 1, 1, 1, 3 }, armnn::GetDataType<T>());
635 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
636
637 armnn::Pooling2dDescriptor descriptor;
638 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
639 descriptor.m_PoolWidth = 2;
640 descriptor.m_PoolHeight = 3;
641 descriptor.m_StrideX = 2;
642 descriptor.m_StrideY = 1;
643 descriptor.m_PadLeft = 2;
644 descriptor.m_PadRight = 0;
645 descriptor.m_PadTop = 1;
646 descriptor.m_PadBottom = 2;
647 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
648 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
649
telsoa01c577f2c2018-08-31 09:22:23 +0100650 // Construct input data.
telsoa014fcda012018-03-09 14:13:49 +0000651 auto input = MakeTensor<T, 4>(inputTensorInfo,
652 QuantizedVector<T>(qScale, qOffset, {
653 1.0f, 3.0f, 4.0f,
654 }));
655
telsoa01c577f2c2018-08-31 09:22:23 +0100656 // These were calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000657 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
658 QuantizedVector<T>(qScale, qOffset, {
659 0.0f, 3.0f, 0.0f, 3.0f,
660 }));
661
662 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
663}
664
665template<typename T>
666LayerTestResult<T, 4> ComparePooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
667 armnn::IWorkloadFactory& refWorkloadFactory,
668 armnn::PoolingAlgorithm poolingType,
669 float qScale = 1.0f,
670 int32_t qOffset = 0)
671{
672 const unsigned int inputWidth = 16;
673 const unsigned int inputHeight = 32;
674 const unsigned int channelCount = 2;
675 const unsigned int batchSize = 5;
676
677 const unsigned int poolSize = 3;
678 const unsigned int strideX = 2;
679 const unsigned int strideY = 4;
680 const unsigned int padX = 0;
681 const unsigned int padY = 0;
682
683 const unsigned int outputWidth = (inputWidth + 2 * padX + strideX - poolSize) / strideX;
684 const unsigned int outputHeight = (inputHeight + 2 * padY + strideY - poolSize) / strideY;
685
686 armnn::TensorInfo inputTensorInfo;
687 armnn::TensorInfo outputTensorInfo;
688
689 unsigned int inputShape[] = { batchSize, channelCount, inputHeight, inputWidth };
690 unsigned int outputShape[] = { batchSize, channelCount, outputHeight, outputWidth };
691
692 inputTensorInfo = armnn::TensorInfo(4, inputShape, armnn::GetDataType<T>());
693 outputTensorInfo = armnn::TensorInfo(4, outputShape, armnn::GetDataType<T>());
694
695 // Set quantization parameters if the requested type is a quantized type.
696 if(armnn::IsQuantizedType<T>())
697 {
698 inputTensorInfo.SetQuantizationScale(qScale);
699 inputTensorInfo.SetQuantizationOffset(qOffset);
700 outputTensorInfo.SetQuantizationScale(qScale);
701 outputTensorInfo.SetQuantizationOffset(qOffset);
702 }
703
704 boost::multi_array<T, 4> input = MakeRandomTensor<T, 4>(inputTensorInfo, 81715);
705
706 LayerTestResult<T, 4> comparisonResult(outputTensorInfo);
707
708 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
709 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
710
711 armnn::Pooling2dQueueDescriptor data;
712 armnn::WorkloadInfo info;
713 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
714 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
715 data.m_Parameters.m_PoolType = poolingType;
716 data.m_Parameters.m_PoolWidth = poolSize;
717 data.m_Parameters.m_PoolHeight = poolSize;
718 data.m_Parameters.m_StrideX = strideX;
719 data.m_Parameters.m_StrideY = strideY;
720 data.m_Parameters.m_PadLeft = padX;
721 data.m_Parameters.m_PadRight = padX;
722 data.m_Parameters.m_PadTop = padY;
723 data.m_Parameters.m_PadBottom = padY;
724 data.m_Parameters.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
725
726 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
727 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refWorkloadFactory.CreateTensorHandle(inputTensorInfo);
728
729 // Don't execute if Pooling is not supported, as an exception will be raised.
David Beck79141b92018-10-23 16:09:36 +0100730 armnn::BackendId backend = workloadFactory.GetBackendId();
telsoa014fcda012018-03-09 14:13:49 +0000731 const size_t reasonIfUnsupportedMaxLen = 255;
732 char reasonIfUnsupported[reasonIfUnsupportedMaxLen+1];
David Beck79141b92018-10-23 16:09:36 +0100733 comparisonResult.supported = armnn::IsPooling2dSupported(backend, inputTensorInfo, outputTensorInfo,
telsoa014fcda012018-03-09 14:13:49 +0000734 data.m_Parameters,
735 reasonIfUnsupported, reasonIfUnsupportedMaxLen);
736 if (!comparisonResult.supported)
737 {
738 return comparisonResult;
739 }
740
741 armnn::Pooling2dQueueDescriptor refData = data;
742 armnn::WorkloadInfo refInfo = info;
743 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
744 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
745
746 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreatePooling2d(data, info);
747 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreatePooling2d(refData, refInfo);
748
749 outputHandleRef->Allocate();
750 inputHandleRef->Allocate();
751 inputHandle->Allocate();
752 outputHandle->Allocate();
753
754 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
755 CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0][0][0]);
756
757 workload->Execute();
758 workloadRef->Execute();
759
760 CopyDataFromITensorHandle(&comparisonResult.output[0][0][0][0], outputHandle.get());
761 CopyDataFromITensorHandle(&comparisonResult.outputExpected[0][0][0][0], outputHandleRef.get());
762
763 return comparisonResult;
764}
765
766//
767// Tests max pooling with the following parameters:
768//
769// Pooling size: 2x2
770// Stride: (2,2)
771// input size: 4x4
772// channels: 1
773// batch size: 1
774//
775template<typename T>
776LayerTestResult<T, 4> SimpleMaxPooling2dSize2x2Stride2x2TestCommon(armnn::IWorkloadFactory& workloadFactory,
777 bool forceNoPadding,
778 float qScale = 1.0f,
779 int32_t qOffset = 0)
780{
781 armnn::Pooling2dDescriptor descriptor;
782 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
783 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
784 descriptor.m_StrideX = 2;
785 descriptor.m_StrideY = 2;
786 descriptor.m_PadLeft = descriptor.m_PadRight = forceNoPadding ? 0 : 3;
787 descriptor.m_PadTop = descriptor.m_PadBottom = 0;
788 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
789 descriptor.m_PaddingMethod = armnn::PaddingMethod::Exclude;
790
791 unsigned int inputWidth = 4;
792 unsigned int inputHeight = 4;
793 unsigned int outputWidth =
794 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
795 descriptor.m_StrideX;
796 unsigned int outputHeight =
797 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
798 descriptor.m_StrideY;
799 unsigned int channels = 1;
800 unsigned int batchSize = 1;
801
802 std::vector<float> inputData = {
803 510.0f, 222.0f, 780.0f, 654.0f,
804 141.0f, 276.0f, 15.0f, 546.0f,
805 303.0f, 618.0f, 582.0f, 339.0f,
806 438.0f, 564.0f, 573.0f, 402.0f
807 };
808
telsoa01c577f2c2018-08-31 09:22:23 +0100809 // 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 +0000810 std::vector<float> expectedOutputDataWithPadding = {
811 0.0f, 510.0f, 780.0f, 654.0f, 0.0f,
812 0.0f, 438.0f, 618.0f, 402.0f, 0.0f
813 };
814
815 std::vector<float> expectedOutputDataNoPadding = {
816 510.0f, 780.0f,
817 618.0f, 582.0f
818 };
819
820 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
821
822 // Scale and offset should match input - we're just calculating maximum values.
823 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
824
825 // Set quantization parameters if the requested type is a quantized type.
826 if(armnn::IsQuantizedType<T>())
827 {
828 inputTensorInfo.SetQuantizationScale(qScale);
829 inputTensorInfo.SetQuantizationOffset(qOffset);
830 outputTensorInfo.SetQuantizationScale(qScale);
831 outputTensorInfo.SetQuantizationOffset(qOffset);
832 }
833
834 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
835
836 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
837 forceNoPadding ? QuantizedVector<T>(qScale, qOffset, expectedOutputDataNoPadding) :
838 QuantizedVector<T>(qScale, qOffset, expectedOutputDataWithPadding));
839
840 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
841}
842
surmeh01bceff2f2018-03-29 16:29:27 +0100843//
844// Tests max pooling with the following parameters:
845//
846// Pooling size: 3x2
847// Stride: (2,2)
848// input size: 3x2
849// channels: 1
850// batch size: 1
851//
852template<typename T>
853LayerTestResult<T, 4> IgnorePaddingAveragePooling2dSize3x2Stride2x2TestCommon(
854 armnn::IWorkloadFactory& workloadFactory,
855 bool forceNoPadding,
856 float qScale = 1.0f,
857 int32_t qOffset = 0)
858{
859 armnn::Pooling2dDescriptor descriptor;
860 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
861 descriptor.m_PoolWidth = 3;
862 descriptor.m_PoolHeight = 2;
863 descriptor.m_StrideX = 2;
864 descriptor.m_StrideY = 2;
865 descriptor.m_PadLeft = (forceNoPadding) ? 0 : 1;
866 descriptor.m_PadRight = descriptor.m_PadLeft;
867 descriptor.m_PadTop = 0;
868 descriptor.m_PadBottom = 0;
869 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
870 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
871
872 unsigned int inputWidth = 3;
873 unsigned int inputHeight = 2;
874 unsigned int outputWidth =
875 (inputWidth + descriptor.m_PadLeft + descriptor.m_PadRight + descriptor.m_StrideX - descriptor.m_PoolWidth) /
876 descriptor.m_StrideX;
877 unsigned int outputHeight =
878 (inputHeight + descriptor.m_PadTop + descriptor.m_PadBottom + descriptor.m_StrideY - descriptor.m_PoolHeight) /
879 descriptor.m_StrideY;
880 unsigned int channels = 1;
881 unsigned int batchSize = 1;
882
883 std::vector<float> inputData = {
884 3.0f, 6.0f, 9.0f,
885 12.0f, 15.0f, 18.0f,
886 };
887
888 std::vector<float> expectedOutputDataWithPadding = {
889 6.0f, 8.0f,
890 };
891
892 std::vector<float> expectedOutputDataNoPadding = {
893 10.5f,
894 };
895
896 armnn::TensorInfo inputTensorInfo({ batchSize, channels, inputHeight, inputWidth }, armnn::GetDataType<T>());
897
898 // Scale and offset should match input - we're just calculating average values.
899 armnn::TensorInfo outputTensorInfo({ batchSize, channels, outputHeight, outputWidth }, armnn::GetDataType<T>());
900
901 // Set quantization parameters if the requested type is a quantized type.
902 if(armnn::IsQuantizedType<T>())
903 {
904 inputTensorInfo.SetQuantizationScale(qScale);
905 inputTensorInfo.SetQuantizationOffset(qOffset);
906 outputTensorInfo.SetQuantizationScale(qScale);
907 outputTensorInfo.SetQuantizationOffset(qOffset);
908 }
909
910 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
911
912 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
913 forceNoPadding ? QuantizedVector<T>(qScale, qOffset, expectedOutputDataNoPadding) :
914 QuantizedVector<T>(qScale, qOffset, expectedOutputDataWithPadding));
915
916 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
917}
918
919
telsoa014fcda012018-03-09 14:13:49 +0000920template<typename T>
921LayerTestResult<T, 4> IgnorePaddingSimpleMaxPooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
922 float qScale = 1.0f,
923 int32_t qOffset = 0)
924{
925 armnn::Pooling2dDescriptor descriptor;
926 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
927 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
928 descriptor.m_StrideX = descriptor.m_StrideY = 2;
929 descriptor.m_PadLeft = 1;
930 descriptor.m_PadRight = 1;
931 descriptor.m_PadTop = 1;
932 descriptor.m_PadBottom = 1;
933 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
934
935 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
936 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
937
938 // Set quantization parameters if the requested type is a quantized type.
939 if(armnn::IsQuantizedType<T>())
940 {
941 inputTensorInfo.SetQuantizationScale(qScale);
942 inputTensorInfo.SetQuantizationOffset(qOffset);
943 outputTensorInfo.SetQuantizationScale(qScale);
944 outputTensorInfo.SetQuantizationOffset(qOffset);
945 }
946
947 auto input = MakeTensor<T, 4>(inputTensorInfo,
948 QuantizedVector<T>(qScale, qOffset, {
949 -1.0f, -2.0f, 3.0f, 4.0f,
950 -1.0f, -2.0f, 3.0f, 4.0f,
951 1.0f, 2.0f, -3.0f, -4.0f,
952 1.0f, 2.0f, -3.0f, -4.0f,
953 }));
954
955 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
956 QuantizedVector<T>(qScale, qOffset, {
957 -1.0f, 3.0f, 4.0f,
958 1.0f, 3.0f, 4.0f,
959 1.0f, 2.0f, -4.0f,
960 }));
961
962 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
963}
964
965template<typename T>
966LayerTestResult<T, 4> IgnorePaddingMaxPooling2dSize3TestCommon(armnn::IWorkloadFactory& workloadFactory,
967 float qScale = 1.0f,
968 int32_t qOffset = 0)
969{
970 armnn::Pooling2dDescriptor descriptor;
971 descriptor.m_PoolType = armnn::PoolingAlgorithm::Max;
972 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
973 descriptor.m_StrideX = descriptor.m_StrideY = 1;
974 descriptor.m_PadLeft = 1;
975 descriptor.m_PadRight = 1;
976 descriptor.m_PadTop = 1;
977 descriptor.m_PadBottom = 1;
978 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
979
980 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
981 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
982
983 // Set quantization parameters if the requested type is a quantized type.
984 if(armnn::IsQuantizedType<T>())
985 {
986 inputTensorInfo.SetQuantizationScale(qScale);
987 inputTensorInfo.SetQuantizationOffset(qOffset);
988 outputTensorInfo.SetQuantizationScale(qScale);
989 outputTensorInfo.SetQuantizationOffset(qOffset);
990 }
991
992 auto input = MakeTensor<T, 4>(inputTensorInfo,
993 QuantizedVector<T>(qScale, qOffset, {
994 -1.0f, -2.0f, 3.0f, 4.0f,
995 -1.0f, -2.0f, 3.0f, 4.0f,
996 1.0f, 2.0f, -3.0f, -4.0f,
997 1.0f, 2.0f, -3.0f, -4.0f,
998 }));
999
1000 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1001 QuantizedVector<T>(qScale, qOffset, {
1002 -1.0f, 3.0f, 4.0f, 4.0f,
1003 2.0f, 3.0f, 4.0f, 4.0f,
1004 2.0f, 3.0f, 4.0f, 4.0f,
1005 2.0f, 2.0f, 2.0f, -3.0f,
1006 }));
1007
1008 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
1009}
1010
1011template<typename T>
1012LayerTestResult<T, 4> IgnorePaddingSimpleAveragePooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
1013 float qScale = 1.0f,
1014 int32_t qOffset = 0)
1015{
1016 armnn::Pooling2dDescriptor descriptor;
1017 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
1018 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
1019 descriptor.m_StrideX = descriptor.m_StrideY = 2;
1020 descriptor.m_PadLeft = 1;
1021 descriptor.m_PadRight = 1;
1022 descriptor.m_PadTop = 1;
1023 descriptor.m_PadBottom = 1;
1024 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1025
1026 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1027 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
1028
1029 // Set quantization parameters if the requested type is a quantized type.
1030 if(armnn::IsQuantizedType<T>())
1031 {
1032 inputTensorInfo.SetQuantizationScale(qScale);
1033 inputTensorInfo.SetQuantizationOffset(qOffset);
1034 outputTensorInfo.SetQuantizationScale(qScale);
1035 outputTensorInfo.SetQuantizationOffset(qOffset);
1036 }
1037
1038 auto input = MakeTensor<T, 4>(inputTensorInfo,
1039 QuantizedVector<T>(qScale, qOffset, {
1040 12.0f, 20.0f, 32.0f, 40.0f,
1041 12.0f, 20.0f, 32.0f, 40.0f,
1042 12.0f, 20.0f, 32.0f, 40.0f,
1043 12.0f, 20.0f, 32.0f, 40.0f,
1044 }));
1045
1046 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1047 QuantizedVector<T>(qScale, qOffset, {
1048 3.0f, 13.0f, 10.0f,
1049 6.0f, 26.0f, 20.0f,
1050 3.0f, 13.0f, 10.0f,
1051 }));
1052
1053 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
1054}
1055
1056template<typename T>
1057LayerTestResult<T, 4> IgnorePaddingSimpleAveragePooling2dNoPaddingTestCommon(armnn::IWorkloadFactory& workloadFactory,
1058 float qScale = 1.0f,
1059 int32_t qOffset = 0)
1060{
1061 armnn::Pooling2dDescriptor descriptor;
1062 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
1063 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1064 descriptor.m_StrideX = descriptor.m_StrideY = 2;
1065 descriptor.m_PadLeft = 0;
1066 descriptor.m_PadRight = 0;
1067 descriptor.m_PadTop = 0;
1068 descriptor.m_PadBottom = 0;
1069 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1070 descriptor.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
1071
1072 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4}, armnn::GetDataType<T>());
1073 armnn::TensorInfo outputTensorInfo({ 1, 1, 2, 2 }, armnn::GetDataType<T>());
1074
1075 // Set quantization parameters if the requested type is a quantized type.
1076 if(armnn::IsQuantizedType<T>())
1077 {
1078 inputTensorInfo.SetQuantizationScale(qScale);
1079 inputTensorInfo.SetQuantizationOffset(qOffset);
1080 outputTensorInfo.SetQuantizationScale(qScale);
1081 outputTensorInfo.SetQuantizationOffset(qOffset);
1082 }
1083
1084 auto input = MakeTensor<T, 4>(inputTensorInfo,
1085 QuantizedVector<T>(qScale, qOffset, {
1086 1.0f, 2.0f, 3.0f, 4.0f,
1087 1.0f, 2.0f, 3.0f, 4.0f,
1088 1.0f, 2.0f, 3.0f, 4.0f,
1089 1.0f, 2.0f, 3.0f, 4.0f,
1090 }));
1091
1092 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1093 QuantizedVector<T>(qScale, qOffset, {
1094 2.0f, 3.5f,
1095 2.0f, 3.5f
1096 }));
1097
1098 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
1099}
1100
1101template<typename T>
1102LayerTestResult<T, 4> IgnorePaddingAveragePooling2dSize3TestCommon(armnn::IWorkloadFactory& workloadFactory,
1103 float qScale = 1.0f,
1104 int32_t qOffset = 0)
1105{
1106 armnn::Pooling2dDescriptor descriptor;
1107 descriptor.m_PoolType = armnn::PoolingAlgorithm::Average;
1108 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1109 descriptor.m_StrideX = descriptor.m_StrideY = 1;
1110 descriptor.m_PadLeft = 1;
1111 descriptor.m_PadRight = 1;
1112 descriptor.m_PadTop = 1;
1113 descriptor.m_PadBottom = 1;
1114 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1115
1116 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1117 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1118
1119 // Set quantization parameters if the requested type is a quantized type.
1120 if(armnn::IsQuantizedType<T>())
1121 {
1122 inputTensorInfo.SetQuantizationScale(qScale);
1123 inputTensorInfo.SetQuantizationOffset(qOffset);
1124 outputTensorInfo.SetQuantizationScale(qScale);
1125 outputTensorInfo.SetQuantizationOffset(qOffset);
1126 }
1127
1128 auto input = MakeTensor<T, 4>(inputTensorInfo,
1129 QuantizedVector<T>(qScale, qOffset, {
1130 9.0f, 27.0f, 18.0f, 36.0f,
1131 18.0f, 9.0f, 18.0f, 9.0f,
1132 27.0f, 18.0f, 9.0f, 27.0f,
1133 9.0f, 27.0f, 9.0f, 18.0f,
1134 }));
1135
1136 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1137 QuantizedVector<T>(qScale, qOffset, {
1138 7.0f, 11.0f, 13.0f, 9.0f,
1139 12.0f, 17.0f, 19.0f, 13.0f,
1140 12.0f, 16.0f, 16.0f, 10.0f,
1141 9.0f, 11.0f, 12.0f, 7.0f,
1142 }));
1143
1144 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
1145}
1146
1147template<typename T>
1148LayerTestResult<T, 4> IgnorePaddingSimpleL2Pooling2dTestCommon(armnn::IWorkloadFactory& workloadFactory,
1149 float qScale = 1.0f,
1150 int32_t qOffset = 0)
1151{
1152 armnn::Pooling2dDescriptor descriptor;
1153 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
1154 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 2;
1155 descriptor.m_StrideX = descriptor.m_StrideY = 2;
1156 descriptor.m_PadLeft = 1;
1157 descriptor.m_PadRight = 1;
1158 descriptor.m_PadTop = 1;
1159 descriptor.m_PadBottom = 1;
1160 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1161
1162 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1163 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3 }, armnn::GetDataType<T>());
1164
1165 // Set quantization parameters if the requested type is a quantized type.
1166 if(armnn::IsQuantizedType<T>())
1167 {
1168 inputTensorInfo.SetQuantizationScale(qScale);
1169 inputTensorInfo.SetQuantizationOffset(qOffset);
1170 outputTensorInfo.SetQuantizationScale(qScale);
1171 outputTensorInfo.SetQuantizationOffset(qOffset);
1172 }
1173
1174 auto input = MakeTensor<T, 4>(inputTensorInfo,
1175 QuantizedVector<T>(qScale, qOffset, {
1176 2.0f, 4.0f, 8.0f, 16.0f,
1177 4.0f, 2.0f, 2.0f, 4.0f,
1178 8.0f, 2.0f, 4.0f, 2.0f,
1179 16.0f, 2.0f, 2.0f, 8.0f,
1180 }));
1181
1182 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1183 QuantizedVector<T>(qScale, qOffset, {
1184 1.0f, 4.4721f, 8.0f,
1185 4.4721f, 2.6457f, 2.236f,
1186 8.0f, 1.4142f, 4.0f,
1187 }));
1188
1189 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
1190}
1191
1192template<typename T>
1193LayerTestResult<T, 4> IgnorePaddingL2Pooling2dSize3TestCommon(armnn::IWorkloadFactory& workloadFactory,
1194 float qScale = 1.0f,
1195 int32_t qOffset = 0)
1196{
1197 armnn::Pooling2dDescriptor descriptor;
1198 descriptor.m_PoolType = armnn::PoolingAlgorithm::L2;
1199 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
1200 descriptor.m_StrideX = descriptor.m_StrideY = 1;
1201 descriptor.m_PadLeft = 1;
1202 descriptor.m_PadRight = 1;
1203 descriptor.m_PadTop = 1;
1204 descriptor.m_PadBottom = 1;
1205 descriptor.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
1206
1207 armnn::TensorInfo inputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1208 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4 }, armnn::GetDataType<T>());
1209
1210 // Set quantization parameters if the requested type is a quantized type.
1211 if(armnn::IsQuantizedType<T>())
1212 {
1213 inputTensorInfo.SetQuantizationScale(qScale);
1214 inputTensorInfo.SetQuantizationOffset(qOffset);
1215 outputTensorInfo.SetQuantizationScale(qScale);
1216 outputTensorInfo.SetQuantizationOffset(qOffset);
1217 }
1218
1219 auto input = MakeTensor<T, 4>(inputTensorInfo,
1220 QuantizedVector<T>(qScale, qOffset, {
1221 1.0f, 2.0f, 3.0f, 4.0f,
1222 1.0f, 2.0f, 3.0f, 4.0f,
1223 1.0f, 2.0f, 3.0f, 4.0f,
1224 1.0f, 2.0f, 3.0f, 4.0f,
1225 }));
1226
1227 auto outputExpected = MakeTensor<T, 4>(outputTensorInfo,
1228 QuantizedVector<T>(qScale, qOffset, {
1229 1.0540f, 1.7638f, 2.5385f, 2.3570f,
1230 1.2909f, 2.1602f, 3.1091f, 2.8867f,
1231 1.2909f, 2.1602f, 3.1091f, 2.8867f,
1232 1.0540f, 1.7638f, 2.5385f, 2.3570f,
1233 }));
1234
1235 return SimplePooling2dTestImpl<T>(workloadFactory, descriptor, qScale, qOffset, input, outputExpected);
1236}