blob: e99a26e81ec47291924fae5282936bcef0a35ee8 [file] [log] [blame]
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001//
Teresa Charlinfbf0e5b2020-08-17 01:01:06 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003// SPDX-License-Identifier: MIT
4//
5
6#include "Conv2dTestImpl.hpp"
7
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01008#include <QuantizeHelper.hpp>
Matteo Martincighe011d202019-11-28 11:35:47 +00009#include <armnnUtils/TensorUtils.hpp>
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010010
Jan Eilers8eb25602020-03-09 12:13:48 +000011#include <armnn/utility/IgnoreUnused.hpp>
Matteo Martincighe011d202019-11-28 11:35:47 +000012#include <armnnUtils/DataLayoutIndexed.hpp>
13#include <armnnUtils/Permute.hpp>
14
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010015#include <backendsCommon/CpuTensorHandle.hpp>
16
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +000017#include <backendsCommon/test/DataLayoutUtils.hpp>
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010018#include <backendsCommon/test/TensorCopyUtils.hpp>
19#include <backendsCommon/test/WorkloadTestUtils.hpp>
20
21#include <test/TensorHelpers.hpp>
22
23#include <boost/numeric/conversion/cast.hpp>
24
25#include <string>
26
27//
28// Static data
29//
30
31// 2-channel bias used by a number of Conv2d tests.
32static std::vector<float> Bias2({0, 2});
33
34static std::vector<float> Bias4({1, 2, 3, 4});
35
36static std::vector<float> Bias8({1, 2, 3, 4, 1, 2, 3, 4});
37
38// 3-channel 16x8 image used as common input data for a number of Conv2d tests.
39static std::vector<float> ConvInput3x8x16({
40 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
41 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
42 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
43 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
44 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
45 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
46 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
47 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
48 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
57 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
58 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
59 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
60 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
61 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
62 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
63 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
64});
65
Aron Virginas-Tar48623a02019-10-22 10:00:28 +010066using namespace armnnUtils;
67
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010068//
69// Helper templates
70//
71
72// Helper template that returns either Bias2 or an empty vector depending on whether bias is enabled.
73template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
74boost::multi_array<T, 1> GetBias2(bool biasEnabled, float qScale)
75{
76 if(biasEnabled)
77 {
78 armnn::TensorInfo biasDesc({static_cast<unsigned int>(Bias2.size())}, ArmnnType);
Rob Hughesbb46dde2020-05-20 15:27:37 +010079 boost::multi_array<T, 1> bias = MakeTensor<T, 1>(biasDesc, QuantizedVector<T>(Bias2, qScale, 0));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010080 return bias;
81 }
82 else
83 {
84 return boost::multi_array<T, 1>();
85 }
86}
87
88// Helper template that returns either Bias4 or an empty vector depending on whether bias is enabled.
89template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
90boost::multi_array<T, 1> GetBias4(bool biasEnabled, float qScale)
91{
92 if(biasEnabled)
93 {
94 armnn::TensorInfo biasDesc({static_cast<unsigned int>(Bias4.size())}, ArmnnType);
Rob Hughesbb46dde2020-05-20 15:27:37 +010095 boost::multi_array<T, 1> bias = MakeTensor<T, 1>(biasDesc, QuantizedVector<T>(Bias4, qScale, 0));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +010096 return bias;
97 }
98 else
99 {
100 return boost::multi_array<T, 1>();
101 }
102}
103
104// Helper template that returns either Bias8 or an empty vector depending on whether bias is enabled.
105template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
106boost::multi_array<T, 1> GetBias8(bool biasEnabled, float qScale)
107{
108 if(biasEnabled)
109 {
110 armnn::TensorInfo biasDesc({static_cast<unsigned int>(Bias4.size())}, ArmnnType);
Rob Hughesbb46dde2020-05-20 15:27:37 +0100111 boost::multi_array<T, 1> bias = MakeTensor<T, 1>(biasDesc, QuantizedVector<T>(Bias8, qScale, 0));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100112 return bias;
113 }
114 else
115 {
116 return boost::multi_array<T, 1>();
117 }
118}
119
120// Helper template that returns either Bias4 or an empty vector depending on whether bias is enabled.
121template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
122boost::multi_array<T, 1> GetBias(bool biasEnabled, float qScale, armnn::TensorInfo outputInfo, armnn::DataLayout layout)
123{
124 const armnnUtils::DataLayoutIndexed dataLayoutIndexed(layout);
125 const unsigned int channelsIndex = dataLayoutIndexed.GetChannelsIndex();
126 const unsigned int outputChannels = outputInfo.GetShape()[channelsIndex];
127
128 switch (outputChannels)
129 {
130 case 2:
131 default:
132 {
133 return GetBias2<ArmnnType>(biasEnabled, qScale);
134 }
135 case 4:
136 {
137 return GetBias4<ArmnnType>(biasEnabled, qScale);
138 }
139 case 8:
140 {
141 return GetBias8<ArmnnType>(biasEnabled, qScale);
142 }
143 }
144}
145
146//
147// Implementation templates
148//
149
150// Mapping from input type to bias type for fully connected layers.
151// float => float, uint8_t => int32_t
152template<typename T>
153struct FullyConnectedBiasTypeForInputType;
154
155template<>
156struct FullyConnectedBiasTypeForInputType<float>
157{
158 using Type = float;
159};
160
161template<>
162struct FullyConnectedBiasTypeForInputType<uint8_t>
163{
164 using Type = int32_t;
165};
166
167// Modifies a std::vector in-place using a specified bias.
168template<typename T, typename B>
169void ApplyBias(std::vector<T>& v, float vScale, int32_t vOffset,
170 const std::vector<B>& bias, float bScale, int32_t bOffset, uint32_t w, uint32_t h)
171{
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100172 ARMNN_ASSERT_MSG((armnn::IsQuantizedType<T>() && vScale != 0.0f) || (!armnn::IsQuantizedType<T>()),
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100173 "Invalid type and parameter combination.");
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100174 ARMNN_ASSERT_MSG((armnn::IsQuantizedType<B>() && bScale != 0.0f) || (!armnn::IsQuantizedType<B>()),
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100175 "Invalid type and parameter combination.");
176
177 // Note we need to dequantize and re-quantize the image value and the bias.
178 for (uint32_t i = 0; i < bias.size(); ++i)
179 {
180 float dBias = SelectiveDequantize(bias[i], bScale, bOffset);
181 for (uint32_t y = 0; y < h; ++y)
182 {
183 for (uint32_t x = 0; x < w; ++x)
184 {
185 uint32_t offset = (i * h + y) * w + x;
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100186 ARMNN_ASSERT(offset < v.size());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100187 T& outRef = v[offset];
188 float dOutput = SelectiveDequantize(outRef, vScale, vOffset);
189 outRef = SelectiveQuantize<T>(dOutput + dBias, vScale, vOffset);
190 }
191 }
192 }
193}
194
195//
196// Convolution2d implementations
197//
198
199template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
200 typename T = armnn::ResolveType<ArmnnType>, typename B = armnn::ResolveType<ArmnnBType>>
201LayerTestResult<T, 4> SimpleConvolution2dTestImpl(
202 armnn::IWorkloadFactory& workloadFactory,
203 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100204 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100205 const boost::multi_array<T, 4>& originalInput,
206 const boost::multi_array<T, 4>& originalKernel,
207 const boost::multi_array<B, 1>& bias,
208 const boost::multi_array<T, 4>& originalOutputExpected,
209 float qScale,
210 int32_t qOffset,
211 const armnn::DataLayout layout = armnn::DataLayout::NCHW,
212 uint32_t padLeft = 0,
213 uint32_t padTop = 0,
214 uint32_t padRight = 0,
215 uint32_t padBottom = 0,
216 uint32_t strideX = 1,
217 uint32_t strideY = 1,
218 uint32_t dilationX = 1,
219 uint32_t dilationY = 1)
220{
Jan Eilers8eb25602020-03-09 12:13:48 +0000221 armnn::IgnoreUnused(memoryManager);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100222 unsigned int inputHeight = boost::numeric_cast<unsigned int>(originalInput.shape()[2]);
223 unsigned int inputWidth = boost::numeric_cast<unsigned int>(originalInput.shape()[3]);
224 unsigned int inputChannels = boost::numeric_cast<unsigned int>(originalInput.shape()[1]);
225 unsigned int inputNum = boost::numeric_cast<unsigned int>(originalInput.shape()[0]);
226
227 unsigned int outputHeight = boost::numeric_cast<unsigned int>(originalOutputExpected.shape()[2]);
228 unsigned int outputWidth = boost::numeric_cast<unsigned int>(originalOutputExpected.shape()[3]);
229 unsigned int outputChannels = boost::numeric_cast<unsigned int>(originalOutputExpected.shape()[1]);
230 unsigned int outputNum = boost::numeric_cast<unsigned int>(originalOutputExpected.shape()[0]);
231
232 unsigned int kernelHeight = boost::numeric_cast<unsigned int>(originalKernel.shape()[2]);
233 unsigned int kernelWidth = boost::numeric_cast<unsigned int>(originalKernel.shape()[3]);
234 unsigned int kernelChannels = boost::numeric_cast<unsigned int>(originalKernel.shape()[1]);
235 unsigned int kernelDepthMul = boost::numeric_cast<unsigned int>(originalKernel.shape()[0]);
236
237 bool biasEnabled = bias.size() > 0;
238
239 // This function currently assumes 1 batch of input/output (and duplicates this into 2 batches).
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100240 ARMNN_ASSERT(inputNum == 1);
241 ARMNN_ASSERT(outputNum == 1);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100242
243 // If a bias is used, its size must equal the number of output channels.
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100244 ARMNN_ASSERT(!biasEnabled || bias.size() == outputChannels);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100245
246
247 // Note these tensors will use two (identical) batches.
248 armnn::TensorInfo inputTensorInfo =
249 armnnUtils::GetTensorInfo(2*inputNum, inputChannels, inputHeight, inputWidth, layout, ArmnnType);
250 armnn::TensorInfo outputTensorInfo =
251 armnnUtils::GetTensorInfo(2*outputNum, outputChannels, outputHeight, outputWidth, layout, ArmnnType);
252 armnn::TensorInfo kernelDesc =
253 armnnUtils::GetTensorInfo(kernelDepthMul, kernelChannels, kernelHeight, kernelWidth, layout, ArmnnType);
254 armnn::TensorInfo biasDesc({static_cast<unsigned int>(bias.size())}, ArmnnBType);
255
256 // Set quantization parameters if the requested type is a quantized type.
257 if(armnn::IsQuantizedType<T>())
258 {
259 inputTensorInfo.SetQuantizationScale(qScale);
260 inputTensorInfo.SetQuantizationOffset(qOffset);
261 outputTensorInfo.SetQuantizationScale(qScale);
262 outputTensorInfo.SetQuantizationOffset(qOffset);
263 kernelDesc.SetQuantizationScale(qScale);
264 kernelDesc.SetQuantizationOffset(qOffset);
265 biasDesc.SetQuantizationScale(qScale*qScale);
266 biasDesc.SetQuantizationOffset(0);
267 }
268
269 LayerTestResult<T, 4> ret(outputTensorInfo);
270
271 // Construct input data - two batches of the same input image.
272 std::vector<T> inputImage;
273 inputImage.assign(originalInput.data(), originalInput.data() + 1*inputChannels*inputHeight*inputWidth);
274 std::vector<T> inputData;
275 inputData.insert(inputData.end(), inputImage.begin(), inputImage.end());
276 inputData.insert(inputData.end(), inputImage.begin(), inputImage.end());
277
278 // at this point if we require it permute the input data
279 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
280 if (layout == armnn::DataLayout::NHWC)
281 {
282 std::vector<T> tmp(inputData.size());
283 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data(), sizeof(T));
284 inputData = tmp;
285 }
286
287 auto batchedInput = MakeTensor<T, 4>(inputTensorInfo, inputData);
288
289 std::vector<T> outputImage;
290 outputImage.assign(originalOutputExpected.data(),
291 originalOutputExpected.data() + outputChannels*outputHeight*outputWidth);
292
293 // Apply bias to output image if it is enabled.
294 if(biasEnabled)
295 {
296 std::vector<T> biasV;
297 biasV.assign(bias.data(), bias.data() + outputChannels);
298 ApplyBias(outputImage, outputTensorInfo.GetQuantizationScale(), outputTensorInfo.GetQuantizationOffset(),
299 biasV, biasDesc.GetQuantizationScale(), biasDesc.GetQuantizationOffset(),
300 outputWidth, outputHeight);
301 }
302
303 // Construct expected output data - two identical images.
304 std::vector<T> outputData;
305 outputData.insert(outputData.end(), outputImage.begin(), outputImage.end());
306 outputData.insert(outputData.end(), outputImage.begin(), outputImage.end());
307
308 // at this point if we require it permute the expected output
309 if (layout == armnn::DataLayout::NHWC)
310 {
311 std::vector<T> tmp(outputData.size());
312 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp.data(), sizeof(T));
313 outputData = tmp;
314 }
315 ret.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
Keith Davisf500d6c2020-08-31 08:32:55 +0100316
317 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
318 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
319
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100320 armnn::Convolution2dQueueDescriptor data;
321 armnn::WorkloadInfo info;
322 armnn::ScopedCpuTensorHandle weightsTensor(kernelDesc);
323 armnn::ScopedCpuTensorHandle biasTensor(biasDesc);
324 // Permute the kernel if necessary
325 boost::multi_array<T, 4> kernel = boost::multi_array<T, 4>(originalKernel);
326 if (layout == armnn::DataLayout::NHWC)
327 {
328 armnnUtils::Permute(kernelDesc.GetShape(), NCHWToNHWC, originalKernel.data(), kernel.data(), sizeof(T));
329 }
330 AllocateAndCopyDataToITensorHandle(&weightsTensor, &kernel[0][0][0][0]);
331
332 if(biasEnabled)
333 {
334 AllocateAndCopyDataToITensorHandle(&biasTensor, &bias[0]);
335 }
336
337 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
338 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
339
340 data.m_Weight = &weightsTensor;
341 data.m_Bias = &biasTensor; // Still set this whether or not bias is enabled - can be a source of bugs.
342 data.m_Parameters.m_StrideX = strideX;
343 data.m_Parameters.m_StrideY = strideY;
344 data.m_Parameters.m_PadLeft = padLeft;
345 data.m_Parameters.m_PadRight = padRight;
346 data.m_Parameters.m_PadTop = padTop;
347 data.m_Parameters.m_PadBottom = padBottom;
348 data.m_Parameters.m_BiasEnabled = biasEnabled;
349 data.m_Parameters.m_DataLayout = layout;
350 data.m_Parameters.m_DilationX = dilationX;
351 data.m_Parameters.m_DilationY = dilationY;
352
353 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateConvolution2d(data, info);
354 inputHandle->Allocate();
355 outputHandle->Allocate();
356
357 CopyDataToITensorHandle(inputHandle.get(), &batchedInput[0][0][0][0]);
358
359 ExecuteWorkload(*workload, memoryManager);
360
361 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
362
363 return ret;
364}
365
366template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
Narumol Prangnawarate8cddeb2020-04-01 16:51:23 +0100367 typename T = armnn::ResolveType<ArmnnType>, typename B = armnn::ResolveType<ArmnnBType>,
368 armnn::DataType OutType = ArmnnType, typename O = armnn::ResolveType<OutType>>
369LayerTestResult<O, 4> SimpleConvolution2dNhwcTestImpl(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100370 armnn::IWorkloadFactory& workloadFactory,
371 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100372 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100373 const boost::multi_array<T, 4>& input,
374 const boost::multi_array<T, 4>& kernel,
375 const boost::multi_array<B, 1>& bias,
Narumol Prangnawarate8cddeb2020-04-01 16:51:23 +0100376 const boost::multi_array<O, 4>& outputExpected,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100377 const armnn::DataLayout dataLayout,
378 float qScale,
379 int32_t qOffset,
380 uint32_t padLeft = 1,
381 uint32_t padTop = 1,
382 uint32_t padRight = 1,
383 uint32_t padBottom = 1,
384 uint32_t strideX = 1,
385 uint32_t strideY = 1)
386{
Jan Eilers8eb25602020-03-09 12:13:48 +0000387 armnn::IgnoreUnused(qScale, qOffset);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100388 unsigned int inputNum = boost::numeric_cast<unsigned int>(input.shape()[0]);
389 unsigned int inputChannels = boost::numeric_cast<unsigned int>(input.shape()[3]);
390 unsigned int inputHeight = boost::numeric_cast<unsigned int>(input.shape()[1]);
391 unsigned int inputWidth = boost::numeric_cast<unsigned int>(input.shape()[2]);
392
393 unsigned int kernelChanMul = boost::numeric_cast<unsigned int>(kernel.shape()[0]);
394 unsigned int kernelChannels = boost::numeric_cast<unsigned int>(kernel.shape()[3]);
395 unsigned int kernelHeight = boost::numeric_cast<unsigned int>(kernel.shape()[1]);
396 unsigned int kernelWidth = boost::numeric_cast<unsigned int>(kernel.shape()[2]);
397
398 unsigned int outputNum = boost::numeric_cast<unsigned int>(outputExpected.shape()[0]);
399 unsigned int outputChannels = boost::numeric_cast<unsigned int>(outputExpected.shape()[3]);
400 unsigned int outputHeight = boost::numeric_cast<unsigned int>(outputExpected.shape()[1]);
401 unsigned int outputWidth = boost::numeric_cast<unsigned int>(outputExpected.shape()[2]);
402
403 bool biasEnabled = bias.size() > 0;
404
405 // Creates the tensors.
406 armnn::TensorInfo inputTensorInfo({inputNum, inputHeight, inputWidth, inputChannels}, ArmnnType);
407 armnn::TensorInfo outputTensorInfo({outputNum, outputHeight, outputWidth, outputChannels},
Narumol Prangnawarate8cddeb2020-04-01 16:51:23 +0100408 OutType);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100409 armnn::TensorInfo kernelDesc({kernelChanMul, kernelHeight, kernelWidth, kernelChannels}, ArmnnType);
410 armnn::TensorInfo biasDesc({static_cast<unsigned int>(bias.size())}, ArmnnBType);
411
412 // Construct the input data.
413 std::vector<T> inputData;
414 inputData.assign(input.data(), input.data() + inputHeight*inputWidth*inputChannels);
415 auto batchedInput = MakeTensor<T, 4>(inputTensorInfo, inputData);
416
417 // Construct the output data, with bias applied, as appropriate.
Narumol Prangnawarate8cddeb2020-04-01 16:51:23 +0100418 std::vector<O> outputData;
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100419 outputData.assign(outputExpected.data(), outputExpected.data() + outputHeight*outputWidth*outputChannels);
420
Narumol Prangnawarate8cddeb2020-04-01 16:51:23 +0100421 LayerTestResult<O, 4> ret(outputTensorInfo);
422 ret.outputExpected = MakeTensor<O, 4>(outputTensorInfo, outputData);
Keith Davisf500d6c2020-08-31 08:32:55 +0100423
424 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
425 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
426
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100427 armnn::ScopedCpuTensorHandle weightsTensor(kernelDesc);
428 AllocateAndCopyDataToITensorHandle(&weightsTensor, &kernel[0][0][0][0]);
429
430 armnn::ScopedCpuTensorHandle biasTensor(biasDesc);
431
432 armnn::Convolution2dQueueDescriptor data;
433
434 data.m_Weight = &weightsTensor;
435 data.m_Bias = &biasTensor; // Still set this whether or not bias is enabled - can be a source of bugs.
436 data.m_Parameters.m_StrideX = strideX;
437 data.m_Parameters.m_StrideY = strideY;
438 data.m_Parameters.m_PadLeft = padLeft;
439 data.m_Parameters.m_PadRight = padRight;
440 data.m_Parameters.m_PadTop = padTop;
441 data.m_Parameters.m_PadBottom = padBottom;
442 data.m_Parameters.m_BiasEnabled = biasEnabled;
443 data.m_Parameters.m_DataLayout = dataLayout;
444
445 armnn::WorkloadInfo info;
446 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
447 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
448
449 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateConvolution2d(data, info);
450 inputHandle->Allocate();
451 outputHandle->Allocate();
452
453 CopyDataToITensorHandle(inputHandle.get(), &batchedInput[0][0][0][0]);
454
455 ExecuteWorkload(*workload, memoryManager);
456
457 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
458
459 return ret;
460}
461
462template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>>
463LayerTestResult<T,4> Convolution1dTestImpl(
464 armnn::IWorkloadFactory& workloadFactory,
465 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100466 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100467 float qScale,
468 int32_t qOffset,
469 bool biasEnabled)
470{
471 using B = armnn::ResolveType<ArmnnBType>;
472 // Until we have a specialist 1D convolution layer, we can fake one using
473 // 2D convolution with the final dimension set to 1.
474 // I don't anticipate this being particularly slow, given that convolution is implemented
475 // as a matrix multiplication, at which point dimension doesn't matter.
476
477 unsigned int batchSize = 1;
478 unsigned int inputChannels = 2;
479 unsigned int outputChannels = 3;
480 unsigned int inputSize = 5; // The 1D size (could view as 'width' or 'height').
481 unsigned int kernelSize = 3;
482 unsigned int padSize = 2;
483 unsigned int stride = 1;
484 unsigned int outputSize = 7; // (inputSize + 2 * padSize - kernelSize + 1) / stride.
485
486 armnn::TensorInfo inputInfo({batchSize, inputChannels, inputSize, 1}, ArmnnType);
487 armnn::TensorInfo outputInfo({batchSize, outputChannels, outputSize, 1}, ArmnnType);
488 armnn::TensorInfo kernelInfo({outputChannels, inputChannels, kernelSize, 1}, ArmnnType);
489 armnn::TensorInfo biasInfo({outputChannels}, ArmnnBType);
490
491 // Set quantization parameters if the requested type is a quantized type.
492 if(armnn::IsQuantizedType<T>())
493 {
494 inputInfo.SetQuantizationScale(qScale);
495 inputInfo.SetQuantizationOffset(qOffset);
496 outputInfo.SetQuantizationScale(qScale);
497 outputInfo.SetQuantizationOffset(qOffset);
498 kernelInfo.SetQuantizationScale(qScale);
499 kernelInfo.SetQuantizationOffset(qOffset);
500 biasInfo.SetQuantizationScale(inputInfo.GetQuantizationScale()*kernelInfo.GetQuantizationScale());
501 biasInfo.SetQuantizationOffset(0);
502 }
503
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100504 std::vector<T> inputData = QuantizedVector<T>(
505 {
506 5.0f, -2.0f, 2.5f, 0.0f, 1.0f,
507 -3.0f, 3.2f, 5.0f, 2.0f, 3.0f,
508 },
509 inputInfo.GetQuantizationScale(),
510 inputInfo.GetQuantizationOffset());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100511
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100512 std::vector<T> kernelData = QuantizedVector<T>(
513 {
514 1.0f, 0.0f, 0.0f,
515 0.0f, 2.0f, -1.5f,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100516
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100517 0.0f, 0.0f, 0.0f,
518 0.2f, 0.2f, 0.2f,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100519
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100520 0.5f, 0.0f, 0.5f,
521 0.0f, -1.0f, 0.0f
522 },
523 kernelInfo.GetQuantizationScale(),
524 kernelInfo.GetQuantizationOffset());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100525
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100526 std::vector<B> biasData =
527 QuantizedVector<B>({ 1.0f, 0.0f, 0.0f }, biasInfo.GetQuantizationScale(), biasInfo.GetQuantizationOffset());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100528
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100529 std::vector<T> outputData = QuantizedVector<T>(
530 {
531 4.5f, -10.8f, 5.0f + 6.4f - 7.5f, -2.0f + 10.0f -3.0f, 2.5f + 4.0f - 4.5f, 6.0f, 1.0f,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100532 -0.6f, -0.6f + 0.64f, -0.6f + 0.64f + 1.0f, 0.64f + 1.0f + 0.4f, 1.0f + 0.4f + 0.6f, 0.4f + 0.6f, 0.6f,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100533 2.5f, -1.0f + 3.0f, 1.25f - 3.2f + 2.5f, -1.0f - 5.0f, 1.25f + 0.5f - 2.0f, -3.0f, 0.5f
534 },
535 outputInfo.GetQuantizationScale(),
536 outputInfo.GetQuantizationOffset());
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100537
538 // Optionally apply bias to output image.
539 if(biasEnabled)
540 {
541 ApplyBias(outputData, outputInfo.GetQuantizationScale(), outputInfo.GetQuantizationOffset(),
542 biasData, biasInfo.GetQuantizationScale(), biasInfo.GetQuantizationOffset(),
543 1, outputSize);
544 }
Keith Davisf500d6c2020-08-31 08:32:55 +0100545
546 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputInfo);
547 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputInfo);
548
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100549 armnn::Convolution2dQueueDescriptor data;
550 armnn::WorkloadInfo info;
551 armnn::ScopedCpuTensorHandle weightsTensor(kernelInfo);
552 armnn::ScopedCpuTensorHandle biasTensor(biasInfo);
553
554 AllocateAndCopyDataToITensorHandle(&weightsTensor, kernelData.data());
555 AllocateAndCopyDataToITensorHandle(&biasTensor, biasData.data());
556
557 AddInputToWorkload(data, info, inputInfo, inputHandle.get());
558 AddOutputToWorkload(data, info, outputInfo, outputHandle.get());
559
560 data.m_Weight = &weightsTensor;
561 data.m_Bias = &biasTensor;
562 data.m_Parameters.m_StrideX = 1;
563 data.m_Parameters.m_StrideY = stride;
564 data.m_Parameters.m_PadLeft = 0;
565 data.m_Parameters.m_PadRight = 0;
566 data.m_Parameters.m_PadTop = padSize;
567 data.m_Parameters.m_PadBottom = padSize;
568 data.m_Parameters.m_BiasEnabled = biasEnabled;
569
570 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateConvolution2d(data, info);
571 inputHandle->Allocate();
572 outputHandle->Allocate();
573
574 CopyDataToITensorHandle(inputHandle.get(), inputData.data());
575
576 ExecuteWorkload(*workload, memoryManager);
577
578 // Output
579 LayerTestResult<T,4> ret(outputInfo);
580 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
581 ret.outputExpected = MakeTensor<T, 4>(outputInfo, outputData);
582 return ret;
583}
584
585template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
586LayerTestResult<T, 4> SimpleConvolution2d3x3NhwcTestCommon(
587 armnn::IWorkloadFactory& workloadFactory,
588 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100589 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100590 float qScale,
591 int32_t qOffset,
592 bool biasEnabled,
593 armnn::DataLayout dataLayout)
594{
Jan Eilers8eb25602020-03-09 12:13:48 +0000595 armnn::IgnoreUnused(biasEnabled);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100596 // Use common single-batch 5x5 image.
597
598 armnn::TensorInfo inputDesc({1, 3, 4, 1}, ArmnnType);
599 boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc,
600 {
601 1, 5, 2, 3,
602 8, 7, 3, 6,
603 3, 3, 9, 1
604 });
605
606
607 // Use a 2-element batch of 3-channel 3x3 kernels.
608 armnn::TensorInfo kernelDesc({1, 3, 3, 1}, ArmnnType);
609 boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc, {
610 4, 5, 6,
611 0, 0, 0,
612 3, 2, 1
613 });
614
615 // Expected output is 1 batch of a 5x5 image.
616 armnn::TensorInfo outputDesc({1, 3, 4, 1}, ArmnnType);
617
618 const std::vector<float> outputData =
619 {
620 23, 41, 33, 21,
621 44, 65, 76, 52,
622 82, 85, 79, 42
623 };
624
625 boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, outputData);
626
627 return SimpleConvolution2dNhwcTestImpl<ArmnnType, ArmnnType>(
628 workloadFactory,
629 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100630 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100631 input,
632 kernel,
633 boost::multi_array<T, 1>(),
634 expectedOutput,
635 dataLayout,
636 qScale,
637 qOffset);
638}
639
640template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
641LayerTestResult<T, 4> SimpleConvolution2d3x3Stride2x2TestCommon(
642 armnn::IWorkloadFactory& workloadFactory,
643 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100644 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100645 float qScale,
646 int32_t qOffset,
647 bool biasEnabled,
648 const armnn::DataLayout& dataLayout)
649{
Jan Eilers8eb25602020-03-09 12:13:48 +0000650 armnn::IgnoreUnused(biasEnabled);
Derek Lambertic374ff02019-12-10 21:57:35 +0000651
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100652 // Input is a single-batch, 1 channel, 5x5 image.
653 armnn::TensorInfo inputDesc({1, 5, 5, 1}, ArmnnType);
654 boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc,
655 {
656 1, 5, 2, 3, 5,
657 8, 7, 3, 6, 3,
658 3, 3, 9, 1, 9,
659 4, 1, 8, 1, 3,
660 6, 8, 1, 9, 2
661 });
662
663 // Use a 3x3 kernel.
664 armnn::TensorInfo kernelDesc({1, 3, 3, 1}, ArmnnType);
665 boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc,
666 {
667 4, 5, 6,
668 0, 0, 0,
669 3, 2, 1
670 });
671
672 // Expected output is a single-batch, 1 channel, 3x3 image.
673 armnn::TensorInfo outputDesc({1, 3, 3, 1}, ArmnnType);
674
675 const std::vector<T> outputData =
676 {
677 23, 33, 24,
678 91, 99, 48,
679 26, 50, 19
680 };
681
682 boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, outputData);
683
684 uint32_t padLeft = 1;
685 uint32_t padTop = 1;
686 uint32_t padRight = 1;
687 uint32_t padBottom = 1;
688 uint32_t strideX = 2;
689 uint32_t strideY = 2;
690
691 return SimpleConvolution2dNhwcTestImpl<ArmnnType, ArmnnType>(
692 workloadFactory,
693 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100694 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100695 input,
696 kernel,
697 boost::multi_array<T, 1>(),
698 expectedOutput,
699 dataLayout,
700 qScale,
701 qOffset,
702 padLeft,
703 padTop,
704 padRight,
705 padBottom,
706 strideX,
707 strideY);
708}
709
710template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>>
711LayerTestResult<T, 4> SimpleConvolution2d3x5TestCommon(
712 armnn::IWorkloadFactory& workloadFactory,
713 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100714 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100715 float qScale,
716 int32_t qOffset,
717 bool biasEnabled,
718 const armnn::DataLayout layout)
719{
720 // Use common single-batch 3-channel 16x8 image.
721 armnn::TensorInfo inputDesc({1, 3, 8, 16}, ArmnnType);
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100722 boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc, QuantizedVector<T>(ConvInput3x8x16, qScale, qOffset));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100723
724 // Use a 2-element batch with 3-channel 3x5 kernels.
725 armnn::TensorInfo kernelDesc({2, 3, 5, 3}, ArmnnType);
726 boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100727 QuantizedVector<T>({
728 1, 1, 1,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100729 1, -1, 1,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100730 1, 1, 1,
731 1, 1, 1,
732 1, 1, 1,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100733
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100734 0, 0, 0,
735 0, 0, 0,
736 0, 0, 0,
737 0, 0, 0,
738 0, 0, 0,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100739
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100740 2, 2, 2,
741 2, 2, 2,
742 2, 2, 2,
743 2, 2, 2,
744 2, 2, 2,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100745
746
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100747 0, 0, 0,
748 0, 0, 0,
749 0, 0, 0,
750 0, 0, 0,
751 0, 0, 0,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100752
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100753 1, 1, 1,
754 1, 1, 1,
755 1, 1, 1,
756 1, 1, 1,
757 1, 1, 1,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100758
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100759 0, 0, 0,
760 0, 0, 0,
761 0, 0, 0,
762 0, 0, 0,
763 0, 0, 0
764 },
765 qScale, qOffset)));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100766
767 // Expected output is 2 batch elements of a 1-channel 14x4 image.
768 armnn::TensorInfo outputDesc({1, 2, 4, 14}, ArmnnType);
769 boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100770 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100771 -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, -24,
772 -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, -25,
773 -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f,
774 -23.5f, -23.5f, -23.5f,
775 -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f, -23.5f,
776 -23.5f, -23.5f, -23.5f,
777
778 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
779 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
780 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
781 5, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100782 },
783 qScale, qOffset)));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100784
785 return SimpleConvolution2dTestImpl<ArmnnType, ArmnnBType>(
786 workloadFactory,
787 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100788 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100789 input,
790 kernel,
791 GetBias2<ArmnnBType>(biasEnabled, qScale * qScale),
792 expectedOutput,
793 qScale,
794 qOffset,
795 layout);
796}
797
798template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
799 typename T = armnn::ResolveType<ArmnnType>>
800LayerTestResult<T, 4> SimpleConvolution2d3x3TestCommon(
801 armnn::IWorkloadFactory& workloadFactory,
802 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100803 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100804 float qScale,
805 int32_t qOffset,
806 bool biasEnabled,
807 const armnn::DataLayout layout)
808{
809 // Use a 3x3 kernel, which exercises ArmCompute's direct convolution path.
810
811 // Use common single-batch 3-channel 16x8 image.
812 armnn::TensorInfo inputDesc({1, 3, 8, 16}, ArmnnType);
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100813 boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc, QuantizedVector<T>(ConvInput3x8x16, qScale, qOffset));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100814
815 // Use a 2-element batch of 3-channel 3x3 kernels.
816 armnn::TensorInfo kernelDesc({2, 3, 3, 3}, ArmnnType);
817 boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100818 QuantizedVector<T>({
819 1, 1, 1,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100820 1, -1, 1,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100821 1, 1, 1,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100822
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100823 0, 0, 0,
824 0, 0, 0,
825 0, 0, 0,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100826
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100827 2, 2, 2,
828 2, 2, 2,
829 2, 2, 2,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100830
831
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100832 0, 0, 0,
833 0, 0, 0,
834 0, 0, 0,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100835
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100836 1, 1, 1,
837 1, 1, 1,
838 1, 1, 1,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100839
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100840 0, 0, 0,
841 0, 0, 0,
842 0, 0, 0
843 },
844 qScale, qOffset)));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100845
846 // Expected output is 1 batch of a 2-channel 14x6 image.
847 armnn::TensorInfo outputDesc({1, 2, 6, 14}, ArmnnType);
848 boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100849 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100850 -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15, -15,
851 -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16,
852 -14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,
853 -14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,
854 -14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,
855 -14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,-14.5f,
856
857 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
858 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
859 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
860 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
861 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
862 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100863 },
864 qScale, qOffset)));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100865
866 return SimpleConvolution2dTestImpl<ArmnnType, ArmnnBType>(
867 workloadFactory,
868 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100869 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100870 input,
871 kernel,
872 GetBias2<ArmnnBType>(biasEnabled, qScale * qScale),
873 expectedOutput,
874 qScale,
875 qOffset,
876 layout);
877}
878
879template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
880 typename T = armnn::ResolveType<ArmnnType>>
881LayerTestResult<T, 4> Convolution2dAsymmetricPaddingLargerThanHalfKernelSizeTestCommon(
882 armnn::IWorkloadFactory& workloadFactory,
883 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100884 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100885 const armnn::DataLayout layout,
886 float qScale,
887 int32_t qOffset)
888{
889 // Use a single-batch 1-channel 3x3 image as input.
890 armnn::TensorInfo inputDesc({1, 1, 3, 3}, ArmnnType);
891 boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100892 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100893 11,21,31,
894 12,22,32,
895 13,23,33
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100896 },
897 qScale, qOffset)));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100898
899 // Use 1 batch of a 1-channel 2x2 kernel.
900 armnn::TensorInfo kernelDesc({1, 1, 2, 2}, ArmnnType);
901 boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100902 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100903 -11,-21,
904 -12,-22,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100905 },
906 qScale, qOffset)));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100907
908// Expected output is 1 batch of a 1-channel 6x8 image.
909// Manually calculated like this:
910//[-11*0 -21*0 -12*0 -22*0 ; -11*0 -21*0 -12*0 -22*0 ; -11*0 -21*0 -12*0 -22*0 ; -11*0 -21*0 -12*0 -22*0 ..]
911//[-11*0 -21*0 -12*0 -22*11 ; -11*0 -21*0 -12*11 -22*21 ; -11*0 -21*0 -12*21 -22*31 ; -11*0 -21*0 -12*31 -22*0 ..]
912//[-11*0 -21*11 -12*0 -22*12 ; -11*11 -21*21 -12*12 -22*22 ; -11*21 -21*31 -12*22 -22*32 ; -11*31 -21*0 -12*32 -22*0 ..]
913//[-11*0 -21*12 -12*0 -22*13 ; -11*12 -21*22 -12*13 -22*23 ; -11*22 -21*32 -12*23 -22*33 ; -11*32 -21*0 -12*33 -22*0 ..]
914//[-11*0 -21*13 -12*0 -22*0 ; -11*13 -21*23 -12*0 -22*0 ; -11*23 -21*33 -12*0 -22*0 ; -11*33 -21*0 -12*0 -22*0 ..]
915//[-11*0 -21*0 -12*0 -22*0 ; -11*0 -21*0 -12*0 -22*0 ; -11*0 -21*0 -12*0 -22*0 ; -11*0 -21*0 -12*0 -22*0 ..]
916//[..... ..... ..... ..... ; ..... ..... ..... ..... ; ..... ..... ..... ..... ; ..... ..... ..... ..... ..]
917 armnn::TensorInfo outputDesc({1, 1, 8, 6}, ArmnnType);
918 boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100919 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100920 0, 0, 0, 0, 0, 0,
921 -242, -594, -934, -372, 0, 0,
922 -495, -1190, -1850, -725, 0, 0,
923 -538, -1256, -1916, -748, 0, 0,
924 -273, -626, -946, -363, 0, 0,
925 0, 0, 0, 0, 0, 0,
926 0, 0, 0, 0, 0, 0,
927 0, 0, 0, 0, 0, 0
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100928 },
929 qScale, qOffset)));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100930
931 return SimpleConvolution2dTestImpl<ArmnnType, ArmnnBType>(
932 workloadFactory,
933 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100934 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100935 input,
936 kernel,
937 GetBias2<ArmnnBType>(false, qScale * qScale),
938 expectedOutput,
939 qScale,
940 qOffset,
941 layout,
942 1, // Padding left.
943 2, // Padding top.
944 3, // Padding right.
945 4); // Padding bottom.
946}
947
948template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
949 typename T = armnn::ResolveType<ArmnnType>>
950LayerTestResult<T, 4> SimpleConvolution2dAsymmetricPaddingTestCommon(
951 armnn::IWorkloadFactory& workloadFactory,
952 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100953 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100954 const armnn::DataLayout layout,
955 float qScale,
956 int32_t qOffset)
957{
958 // Use a single-batch 1-channel 5x5 image as input.
959 armnn::TensorInfo inputDesc({ 1, 1, 5, 5 }, ArmnnType);
960 boost::multi_array<T, 4> input = MakeTensor<T, 4>(inputDesc, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100961 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100962 11,21,31,41,51,
963 12,22,32,42,52,
964 13,23,33,43,53,
965 14,24,34,44,54,
966 15,25,35,45,55,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100967 }, qScale, qOffset)));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100968
969 // Use 1 batch of a 1-channel 4x4 kernel.
970 armnn::TensorInfo kernelDesc({ 1, 1, 4, 4 }, ArmnnType);
971 boost::multi_array<T, 4> kernel = MakeTensor<T, 4>(kernelDesc, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100972 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100973 -11,-21,-31,-41,
974 -12,-22,-32,-42,
975 -13,-23,-33,-43,
976 -14,-24,-34,-44,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100977 },
978 qScale, qOffset)));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100979
980 // Expected output is 1 batch of a 1-channel 5x5 image.
981 armnn::TensorInfo outputDesc({ 1, 1, 5, 5 }, ArmnnType);
982 std::vector<T> myVec(outputDesc.GetNumElements(), 0);
983 boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputDesc, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100984 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100985 -7140, -10580, -13940, -9300, -5230,
986 -9590, -14120, -18520, -12290, -6860,
987 -9980, -14560, -18960, -12560, -7000,
988 -7518, -10904, -14144, -9318, -5152,
989 -5032, -7256, -9376, -6142, -3368,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +0100990 },
991 qScale, qOffset)));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100992
993 return SimpleConvolution2dTestImpl<ArmnnType, ArmnnBType>(
994 workloadFactory,
995 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +0100996 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +0100997 input,
998 kernel,
999 GetBias2<ArmnnBType>(false, qScale * qScale),
1000 expectedOutput,
1001 qScale,
1002 qOffset,
1003 layout,
1004 1, // Padding left.
1005 1, // Padding top.
1006 2, // Padding right.
1007 2); // Padding bottom.
1008}
1009
1010template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>>
1011LayerTestResult<T, 4> Convolution2d3x3DilationTestCommon(
1012 armnn::IWorkloadFactory& workloadFactory,
1013 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001014 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001015 const std::vector<float>& inputNoQuantizedValues,
1016 armnn::TensorInfo& inputTensorInfo,
1017 const std::vector<float>& kernelNoQuantizedValues,
1018 armnn::TensorInfo& kernelTensorInfo,
1019 const std::vector<float>& outputExpectedNoQuantizedValues,
1020 armnn::TensorInfo& outputTensorInfo,
1021 uint32_t dilationX,
1022 uint32_t dilationY,
1023 armnn::DataLayout layout = armnn::DataLayout::NCHW,
1024 uint32_t padLeft = 0,
1025 uint32_t padTop = 0,
1026 uint32_t padRight = 0,
1027 uint32_t padBottom = 0,
1028 uint32_t strideX = 1,
1029 uint32_t strideY = 1,
1030 bool biasEnabled = false
1031)
1032{
1033 float qScale;
1034 int32_t qOffset;
1035 switch (ArmnnType)
1036 {
Derek Lambertif90c56d2020-01-10 17:14:08 +00001037 case armnn::DataType::QAsymmU8:
Sadik Armagan303980c2020-04-17 12:45:14 +01001038 case armnn::DataType::QAsymmS8:
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001039 {
1040 qScale = 0.1f;
1041 qOffset = 128;
1042 break;
1043 }
Derek Lambertif90c56d2020-01-10 17:14:08 +00001044 case armnn::DataType::QSymmS16:
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001045 {
1046 qScale = 0.1f;
1047 qOffset = 0;
1048 break;
1049 }
1050 case armnn::DataType::Float32:
1051 default:
1052 {
1053 qScale = 0.f;
1054 qOffset = 0;
1055 break;
1056 }
1057 }
1058
1059 inputTensorInfo.SetQuantizationScale(qScale);
1060 inputTensorInfo.SetQuantizationOffset(qOffset);
1061 kernelTensorInfo.SetQuantizationScale(qScale);
1062 kernelTensorInfo.SetQuantizationOffset(qOffset);
1063 outputTensorInfo.SetQuantizationScale(qScale);
1064 outputTensorInfo.SetQuantizationOffset(qOffset);
1065
1066 auto input = MakeTensor<T, 4>(inputTensorInfo,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01001067 std::vector<T>(QuantizedVector<T>(inputNoQuantizedValues,
1068 inputTensorInfo.GetQuantizationScale(),
1069 inputTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001070 auto kernel = MakeTensor<T, 4>(kernelTensorInfo,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01001071 std::vector<T>(QuantizedVector<T>(kernelNoQuantizedValues,
1072 kernelTensorInfo.GetQuantizationScale(),
1073 kernelTensorInfo.GetQuantizationOffset())));
1074 auto expectedOutput =
1075 MakeTensor<T, 4>(outputTensorInfo,
1076 std::vector<T>(QuantizedVector<T>(outputExpectedNoQuantizedValues,
1077 outputTensorInfo.GetQuantizationScale(),
1078 outputTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001079
1080 return SimpleConvolution2dTestImpl<ArmnnType, ArmnnBType>(
1081 workloadFactory,
1082 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001083 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001084 input,
1085 kernel,
1086 GetBias2<ArmnnBType>(biasEnabled, qScale * qScale),
1087 expectedOutput,
1088 qScale,
1089 qOffset,
1090 layout,
1091 padLeft,
1092 padTop,
1093 padRight,
1094 padBottom,
1095 strideX,
1096 strideY,
1097 dilationX,
1098 dilationY);
1099}
1100
1101template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T>
1102LayerTestResult<T, 4> Convolution2d3x3Dilation3x3Test(
1103 armnn::IWorkloadFactory& workloadFactory,
1104 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001105 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001106 bool biasEnabled,
1107 const armnn::DataLayout layout)
1108{
1109 armnn::TensorInfo inputTensorInfo({1, 1, 10, 10}, ArmnnType);
1110 std::vector<float> inputNoQuantizedValues =
1111 {
1112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1115 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1116 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1117 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1122 };
1123
1124 armnn::TensorInfo kernelTensorInfo({ 1, 1, 3, 3}, ArmnnType);
1125 std::vector<float> kernelNoQuantizedValues =
1126 {
1127 1, 2, 3,
1128 4, 5, 6,
1129 7, 8, 9
1130 };
1131
1132 // Since the dilation rate is 3 this will dilate the kernel to be like 7x7,
1133 // therefore the output will be 4x4: (I−K+2P)/S +1 => (10-7 +0)/1 +1
1134 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4}, ArmnnType);
1135 std::vector<float> outputExpectedNoQuantizedValues =
1136 {
1137 6., 5., 5., 5.,
1138 6., 5., 5., 5.,
1139 6., 5., 5., 5.,
1140 3., 2., 2., 2.
1141 };
1142
1143 return Convolution2d3x3DilationTestCommon<ArmnnType, ArmnnBType>(
1144 workloadFactory,
1145 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001146 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001147 inputNoQuantizedValues,
1148 inputTensorInfo,
1149 kernelNoQuantizedValues,
1150 kernelTensorInfo,
1151 outputExpectedNoQuantizedValues,
1152 outputTensorInfo,
1153 3,
1154 3,
1155 layout,
1156 biasEnabled);
1157}
1158
1159template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T>
1160LayerTestResult<T, 4> Convolution2d2x3x3Dilation3x3Test(
1161 armnn::IWorkloadFactory& workloadFactory,
1162 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001163 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001164 bool biasEnabled,
1165 const armnn::DataLayout layout)
1166{
1167 armnn::TensorInfo inputTensorInfo({1, 2, 10, 10}, ArmnnType);
1168 std::vector<float> inputNoQuantizedValues =
1169 {
1170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1173 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1174 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1175 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1180
1181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1184 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1185 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1186 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
1187 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1188 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1190 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1191 };
1192
1193 armnn::TensorInfo kernelTensorInfo({ 1, 2, 3, 3}, ArmnnType);
1194 std::vector<float> kernelNoQuantizedValues =
1195 {
1196 1, 2, 3,
1197 4, 5, 6,
1198 7, 8, 9,
1199
1200 1, 2, 3,
1201 4, 5, 6,
1202 7, 8, 9
1203 };
1204
1205 // Since the dilation rate is 3 this will dilate the kernel to be like 7x7,
1206 // therefore the output will be 4x4: (I−K+2P)/S +1 => (10-7 +0)/1 +1
1207 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4}, ArmnnType);
1208 std::vector<float> outputExpectedNoQuantizedValues =
1209 {
1210 12., 10., 10., 10.,
1211 12., 10., 10., 10.,
1212 12., 10., 10., 10.,
1213 6., 4., 4., 4.
1214 };
1215
1216 return Convolution2d3x3DilationTestCommon<ArmnnType, ArmnnBType>(
1217 workloadFactory,
1218 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001219 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001220 inputNoQuantizedValues,
1221 inputTensorInfo,
1222 kernelNoQuantizedValues,
1223 kernelTensorInfo,
1224 outputExpectedNoQuantizedValues,
1225 outputTensorInfo,
1226 3,
1227 3,
1228 layout,
1229 biasEnabled);
1230}
1231
1232template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T>
1233LayerTestResult<T, 4> Convolution2d2x2Dilation2x2Padding2x2Stride3x3Test(
1234 armnn::IWorkloadFactory &workloadFactory,
1235 const armnn::IBackendInternal::IMemoryManagerSharedPtr &memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001236 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001237 bool biasEnabled,
1238 const armnn::DataLayout layout)
1239{
1240 armnn::TensorInfo inputTensorInfo({1, 1, 10, 10}, ArmnnType);
1241 std::vector<float> inputNoQuantizedValues =
1242 {
1243 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1244 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1245 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1246 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1247 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1248 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1249 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1250 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1251 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1252 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
1253 };
1254
1255 armnn::TensorInfo kernelTensorInfo({ 1, 1, 2, 2}, ArmnnType);
1256 std::vector<float> kernelNoQuantizedValues =
1257 {
1258 1, 2,
1259 3, 4
1260 };
1261
1262 // Since the dilation rate is 2 this will dilate the kernel to be like 3x3: d(K-1)+1 --> 2 x (2-1) + 1 = 3,
1263 // therefore the output will be 4x4: (I − K + 2P)/S +1 => trunc ( (10 - 3 + 2x2 ) / 3 + 1 )
1264 // where, dilation size = d = 2; kernel size = K = 2; input size = I = 10; padding size = P = 2; stride = S = 3
1265 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4}, ArmnnType);
1266 std::vector<float> outputExpectedNoQuantizedValues =
1267 {
1268 4, 7, 7, 3,
1269 6, 10, 10, 4,
1270 6, 10, 10, 4,
1271 2, 3, 3, 1
1272 };
1273 uint32_t padLeft = 1;
1274 uint32_t padTop = 1;
1275 uint32_t padRight = 1;
1276 uint32_t padBottom = 1;
1277
1278 return Convolution2d3x3DilationTestCommon<ArmnnType, ArmnnBType>(
1279 workloadFactory,
1280 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001281 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001282 inputNoQuantizedValues,
1283 inputTensorInfo,
1284 kernelNoQuantizedValues,
1285 kernelTensorInfo,
1286 outputExpectedNoQuantizedValues,
1287 outputTensorInfo,
1288 2,
1289 2,
1290 layout,
1291 padLeft,
1292 padTop,
1293 padRight,
1294 padBottom,
1295 3,
1296 3,
1297 biasEnabled
1298 );
1299}
1300
1301template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
1302LayerTestResult<T,4> CompareConvolution2dTestImpl(
1303 armnn::IWorkloadFactory& workloadFactory,
1304 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001305 armnn::IWorkloadFactory& refWorkloadFactory,
1306 const armnn::ITensorHandleFactory& tensorHandleFactory,
1307 const armnn::ITensorHandleFactory& refTensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001308{
1309 unsigned int inputHeight = 8;
1310 unsigned int inputWidth = 16;
1311 unsigned int inputChannels = 3;
1312 unsigned int inputNum = 5;
1313
1314 unsigned int kernelHeight = 3;
1315 unsigned int kernelWidth = 3;
1316
1317 unsigned int strideX = 2;
1318 unsigned int strideY = 3;
1319 unsigned int padX = 1;
1320 unsigned int padY = 1;
1321
1322 unsigned int outputNum = inputNum;
1323 unsigned int outputChannels = 2;
1324 unsigned int outputHeight = (inputHeight + 2 * padY - kernelHeight + strideY) / strideY;
1325 unsigned int outputWidth = (inputWidth + 2 * padX - kernelWidth + strideX) / strideX;
1326
1327 armnn::TensorInfo inputTensorInfo;
1328 armnn::TensorInfo outputTensorInfo;
1329 armnn::TensorInfo kernelDesc;
1330 armnn::TensorInfo biasDesc;
1331
1332 unsigned int inputShape[] = {inputNum, inputChannels, inputHeight, inputWidth};
1333 unsigned int outputShape[] = {outputNum, outputChannels, outputHeight, outputWidth};
1334 unsigned int kernelShape[] = {outputChannels, inputChannels, kernelHeight, kernelWidth};
1335 unsigned int biasShape[] = {outputChannels};
1336
1337 inputTensorInfo = armnn::TensorInfo(4, inputShape, ArmnnType);
1338 outputTensorInfo = armnn::TensorInfo(4, outputShape, ArmnnType);
1339 kernelDesc = armnn::TensorInfo(4, kernelShape, ArmnnType);
1340 biasDesc = armnn::TensorInfo(1, biasShape, ArmnnType);
1341
1342 LayerTestResult<T,4> ret(outputTensorInfo);
1343
1344 auto input = MakeRandomTensor<T, 4>(inputTensorInfo, 124908);
1345 auto kernel = MakeRandomTensor<T, 4>(kernelDesc, 891234);
1346 auto bias = MakeRandomTensor<T, 1>(biasDesc, 1028);
Keith Davisf500d6c2020-08-31 08:32:55 +01001347
1348 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
1349 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
1350
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001351 armnn::Convolution2dQueueDescriptor data;
1352 armnn::WorkloadInfo info;
1353 armnn::ScopedCpuTensorHandle weightsTensor(kernelDesc);
1354 armnn::ScopedCpuTensorHandle biasTensor(biasDesc);
1355
1356 AllocateAndCopyDataToITensorHandle(&weightsTensor, &kernel[0][0][0][0]);
1357 AllocateAndCopyDataToITensorHandle(&biasTensor, &bias[0]);
1358
1359 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
1360 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
1361 data.m_Weight = &weightsTensor;
1362 data.m_Bias = &biasTensor;
1363 data.m_Parameters.m_StrideX = strideX;
1364 data.m_Parameters.m_StrideY = strideY;
1365 data.m_Parameters.m_PadLeft = padX;
1366 data.m_Parameters.m_PadRight = padX;
1367 data.m_Parameters.m_PadTop = padY;
1368 data.m_Parameters.m_PadBottom = padY;
1369 data.m_Parameters.m_BiasEnabled = true;
Keith Davisf500d6c2020-08-31 08:32:55 +01001370
1371 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refTensorHandleFactory.CreateTensorHandle(outputTensorInfo);
1372 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refTensorHandleFactory.CreateTensorHandle(inputTensorInfo);
1373
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001374 armnn::Convolution2dQueueDescriptor refData = data;
1375 armnn::WorkloadInfo refInfo = info;
1376 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
1377 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
1378
1379 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateConvolution2d(data, info);
1380 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateConvolution2d(refData, refInfo);
1381
1382 outputHandleRef->Allocate();
1383 inputHandleRef->Allocate();
1384
1385 inputHandle->Allocate();
1386 outputHandle->Allocate();
1387
1388 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
1389 CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0][0][0]);
1390
1391 ExecuteWorkload(*workload, memoryManager);
1392
1393 workloadRef->PostAllocationConfigure();
1394 workloadRef->Execute();
1395
1396 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
1397 CopyDataFromITensorHandle(&ret.outputExpected[0][0][0][0], outputHandleRef.get());
1398
1399 return ret;
1400}
1401
Narumol Prangnawarate8cddeb2020-04-01 16:51:23 +01001402LayerTestResult<float, 4> Convolution2d3x3Stride2x2BFloat16Test(
1403 armnn::IWorkloadFactory& workloadFactory,
1404 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001405 const armnn::ITensorHandleFactory& tensorHandleFactory,
Narumol Prangnawarate8cddeb2020-04-01 16:51:23 +01001406 bool biasEnabled,
1407 const armnn::DataLayout& dataLayout)
1408{
1409 // BFloat16 input and weight, Float32 output
1410 armnn::IgnoreUnused(biasEnabled);
1411
1412 // Input is a single-batch, 1 channel, 5x5 image.
1413 armnn::TensorInfo inputDesc({1, 5, 5, 1}, armnn::DataType::BFloat16);
1414
1415 std::vector<armnn::BFloat16> inputValues = armnnUtils::QuantizedVector<armnn::BFloat16>(
1416 {
1417 10.0367984f, // 10.0625
1418 2.0380895f, // 2.03125
1419 15.0420157f, // 15.0625
1420 22.0675631f, // 22.125
1421 8.0938920f, // 8.125
1422 5.0476106f, // 5.0625
1423 80.1035490f, // 80
1424 100.1260370f, // 100
1425 55.0461647f, // 55
1426 120.0883828f, // 120
1427 9.1159540f, // 9.125
1428 90.0498519f, // 90
1429 200.0104630f, // 200
1430 30.0154114f, // 30
1431 75.00137681f, // 75
1432 30.0344238f, // 30
1433 25.0356445f, // 25
1434 130.0495605f, // 130
1435 60.0683594f, // 60
1436 35.0991211f, // 35
1437 8.0461426f, // 8.0625
1438 12.0996094f, // 12.125
1439 98.1269530f, // 98
1440 125.0393066f, // 125
1441 5.103516f // 5.0937
1442 },
1443 1.0f, 0);
1444
1445 auto input = MakeTensor<armnn::BFloat16, 4>(inputDesc, inputValues);
1446
1447 // Use a 3x3 kernel.
1448 armnn::TensorInfo kernelDesc({1, 3, 3, 1}, armnn::DataType::BFloat16);
1449
1450 std::vector<armnn::BFloat16> kernelValues = armnnUtils::QuantizedVector<armnn::BFloat16>(
1451 {
1452 -0.126184f, // -0.125977
1453 -0.150468f, // -0.150391
1454 -0.101412f, // -0.101562
1455 -0.0586369f,// -0.0585938
1456 -0.0865864f,// -0.0864258
1457 -0.0435089f,// -0.043457
1458 0.0347555f, // 0.034668
1459 0.0323111f, // 0.0322266
1460 0.0385381f // 0.0385742
1461 },
1462 1.0f, 0);
1463
1464 auto kernel = MakeTensor<armnn::BFloat16, 4>(kernelDesc, kernelValues);
1465
1466 // Expected output is a single-batch, 1 channel, 3x3 image.
1467 armnn::TensorInfo outputDesc({1, 3, 3, 1}, armnn::DataType::Float32);
1468
1469 // Expected output (with results if calculated as FP32 in the comments)
1470 const std::vector<float> outputData =
1471 {
1472 2.296875f, // 2.29240716
1473 5.75f, // 5.75851926
1474 3.78125f, // 3.79855026
1475 -11.625f, // -11.65498118
1476 -47.25f, // -47.27316893
1477 -30.0f, // -30.04771684
1478 -8.25f, // -8.28126168
1479 -43.5f, // -43.46531337
1480 -20.625f // -20.63477281
1481 };
1482
1483 boost::multi_array<float, 4> expectedOutput = MakeTensor<float, 4>(outputDesc, outputData);
1484
1485 uint32_t padLeft = 1;
1486 uint32_t padTop = 1;
1487 uint32_t padRight = 1;
1488 uint32_t padBottom = 1;
1489 uint32_t strideX = 2;
1490 uint32_t strideY = 2;
1491
1492 return SimpleConvolution2dNhwcTestImpl
1493 <armnn::DataType::BFloat16, armnn::DataType::Float32, armnn::BFloat16, float, armnn::DataType::Float32, float>(
1494 workloadFactory,
1495 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001496 tensorHandleFactory,
Narumol Prangnawarate8cddeb2020-04-01 16:51:23 +01001497 input,
1498 kernel,
1499 boost::multi_array<float, 1>(),
1500 expectedOutput,
1501 dataLayout,
1502 1.0f,
1503 0,
1504 padLeft,
1505 padTop,
1506 padRight,
1507 padBottom,
1508 strideX,
1509 strideY);
1510}
1511
1512LayerTestResult<float, 4> Convolution2d3x3Stride2x2BFloat16SmallValueTest(
1513 armnn::IWorkloadFactory& workloadFactory,
1514 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001515 const armnn::ITensorHandleFactory& tensorHandleFactory,
Narumol Prangnawarate8cddeb2020-04-01 16:51:23 +01001516 bool biasEnabled,
1517 const armnn::DataLayout& dataLayout)
1518{
1519 // BFloat16 input and weight, Float32 output
1520 armnn::IgnoreUnused(biasEnabled);
1521
1522 // Input is a single-batch, 1 channel, 5x5 image.
1523 armnn::TensorInfo inputDesc({1, 5, 5, 1}, armnn::DataType::BFloat16);
1524
1525 std::vector<armnn::BFloat16> inputValues = armnnUtils::QuantizedVector<armnn::BFloat16>(
1526 {
1527 0.0367984f, // 0.0368652
1528 0.0380895f, // 0.0380859
1529 0.0420157f, // 0.0419922
1530 0.0675631f, // 0.0673828
1531 0.0938920f, // 0.09375
1532 0.0476106f, // 0.0476074
1533 0.1035490f, // 0.103516
1534 0.1260370f, // 0.125977
1535 0.0461647f, // 0.0461426
1536 0.0883828f, // 0.0883789
1537 0.1159540f, // 0.115723
1538 0.0498519f, // 0.0498047
1539 0.0104630f, // 0.010437
1540 0.0154114f, // 0.0154419
1541 0.00137681f, // 0.00137329
1542 0.0344238f, // 0.0344616
1543 0.0356445f, // 0.0355693
1544 0.0495605f, // 0.0495018
1545 0.0683594f, // 0.0683308
1546 0.0991211f, // 0.0988837
1547 0.0461426f, // 0.0461838
1548 0.0996094f, // 0.0997546
1549 0.1269530f, // 0.127099
1550 0.0393066f, // 0.0392791
1551 0.103516f // 0.103641
1552 },
1553 1.0f, 0);
1554
1555 auto input = MakeTensor<armnn::BFloat16, 4>(inputDesc, inputValues);
1556
1557 // Use a 3x3 kernel.
1558 armnn::TensorInfo kernelDesc({1, 3, 3, 1}, armnn::DataType::BFloat16);
1559
1560 std::vector<armnn::BFloat16> kernelValues = armnnUtils::QuantizedVector<armnn::BFloat16>(
1561 {
1562 -0.126184f, // -0.125977
1563 -0.150468f, // -0.150391
1564 -0.101412f, // -0.101562
1565 -0.0586369f,// -0.0585938
1566 -0.0865864f,// -0.0864258
1567 -0.0435089f,// -0.043457
1568 0.0347555f, // 0.034668
1569 0.0323111f, // 0.0322266
1570 0.0385381f // 0.0385742
1571 },
1572 1.0f, 0);
1573
1574 auto kernel = MakeTensor<armnn::BFloat16, 4>(kernelDesc, kernelValues);
1575
1576 // Expected output is a single-batch, 1 channel, 3x3 image.
1577 armnn::TensorInfo outputDesc({1, 3, 3, 1}, armnn::DataType::Float32);
1578
1579 // Expected output (with results if calculated as FP32 in the comments)
1580 const std::vector<float> outputData =
1581 {
1582 0.000686645508f, // 0.000685
1583 0.000640869141f, // 0.000639
1584 -0.00759887695f, // -0.007631
1585 -0.02734375f, // -0.027388
1586 -0.0356445312f, // -0.035737
1587 -0.0145874023f, // -0.014568
1588 -0.0170898438f, // -0.017124
1589 -0.0373535156f, // -0.037431
1590 -0.0346679688f // -0.034808
1591 };
1592
1593 boost::multi_array<float, 4> expectedOutput = MakeTensor<float, 4>(outputDesc, outputData);
1594
1595 uint32_t padLeft = 1;
1596 uint32_t padTop = 1;
1597 uint32_t padRight = 1;
1598 uint32_t padBottom = 1;
1599 uint32_t strideX = 2;
1600 uint32_t strideY = 2;
1601
1602 return SimpleConvolution2dNhwcTestImpl
1603 <armnn::DataType::BFloat16, armnn::DataType::Float32, armnn::BFloat16, float, armnn::DataType::Float32, float>(
1604 workloadFactory,
1605 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001606 tensorHandleFactory,
Narumol Prangnawarate8cddeb2020-04-01 16:51:23 +01001607 input,
1608 kernel,
1609 boost::multi_array<float, 1>(),
1610 expectedOutput,
1611 dataLayout,
1612 1.0f,
1613 0,
1614 padLeft,
1615 padTop,
1616 padRight,
1617 padBottom,
1618 strideX,
1619 strideY);
1620}
1621
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001622//
1623// DepthwiseConvolution2d implementations
1624//
1625
1626template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
1627 typename T = armnn::ResolveType<ArmnnType>, typename B = armnn::ResolveType<ArmnnBType>>
1628LayerTestResult<T, 4> DepthwiseConvolution2dAsymmetricTestImpl(
1629 armnn::IWorkloadFactory& workloadFactory,
1630 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001631 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001632 const boost::multi_array<T, 4>& input,
1633 const boost::multi_array<T, 4>& kernel,
1634 const boost::multi_array<B, 1>& bias,
1635 const boost::multi_array<T, 4>& outputExpected,
1636 float qScale,
1637 int32_t qOffset,
1638 const armnn::DataLayout layout,
1639 uint32_t padLeft = 0,
1640 uint32_t padTop = 0,
1641 uint32_t padRight = 0,
1642 uint32_t padBottom = 0,
1643 uint32_t strideX = 1,
1644 uint32_t strideY = 1)
1645{
1646 unsigned int inputNum = boost::numeric_cast<unsigned int>(input.shape()[0]);
1647 unsigned int inputChannels = boost::numeric_cast<unsigned int>(input.shape()[1]);
1648 unsigned int inputHeight = boost::numeric_cast<unsigned int>(input.shape()[2]);
1649 unsigned int inputWidth = boost::numeric_cast<unsigned int>(input.shape()[3]);
1650 unsigned int kernelChanMul = boost::numeric_cast<unsigned int>(kernel.shape()[0]);
1651 unsigned int kernelChannels = boost::numeric_cast<unsigned int>(kernel.shape()[1]);
1652 unsigned int kernelHeight = boost::numeric_cast<unsigned int>(kernel.shape()[2]);
1653 unsigned int kernelWidth = boost::numeric_cast<unsigned int>(kernel.shape()[3]);
1654 unsigned int outputNum = boost::numeric_cast<unsigned int>(outputExpected.shape()[0]);
1655 unsigned int outputChannels = boost::numeric_cast<unsigned int>(outputExpected.shape()[1]);
1656 unsigned int outputHeight = boost::numeric_cast<unsigned int>(outputExpected.shape()[2]);
1657 unsigned int outputWidth = boost::numeric_cast<unsigned int>(outputExpected.shape()[3]);
1658
1659 // If a bias is used, its size must equal the number of output channels.
1660 bool biasEnabled = bias.size() > 0;
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01001661 ARMNN_ASSERT(!biasEnabled || bias.size() == outputChannels);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001662
1663 // Creates the tensors.
1664 armnn::TensorInfo inputTensorInfo =
1665 armnnUtils::GetTensorInfo(inputNum, inputChannels, inputHeight, inputWidth, layout, ArmnnType);
1666 armnn::TensorInfo outputTensorInfo =
1667 armnnUtils::GetTensorInfo(outputNum, outputChannels, outputHeight, outputWidth, layout, ArmnnType);
1668 armnn::TensorInfo kernelDesc({kernelChanMul, kernelChannels, kernelHeight, kernelWidth}, ArmnnType);
1669 armnn::TensorInfo biasDesc({static_cast<unsigned int>(bias.size())}, ArmnnBType);
1670
1671 // Set quantization parameters if the requested type is a quantized type.
1672 if (armnn::IsQuantizedType<T>())
1673 {
1674 inputTensorInfo.SetQuantizationScale(qScale);
1675 inputTensorInfo.SetQuantizationOffset(qOffset);
1676 outputTensorInfo.SetQuantizationScale(qScale);
1677 outputTensorInfo.SetQuantizationOffset(qOffset);
1678 kernelDesc.SetQuantizationScale(qScale);
1679 kernelDesc.SetQuantizationOffset(qOffset);
1680 biasDesc.SetQuantizationScale(qScale*qScale);
1681 biasDesc.SetQuantizationOffset(0);
1682 }
1683
1684 // Construct the input data.
1685 std::vector<T> inputData;
1686 inputData.assign(input.data(), input.data() + inputChannels*inputHeight*inputWidth);
1687
1688 // At this point if we require it permute the input data
1689 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
1690 if (layout == armnn::DataLayout::NHWC)
1691 {
1692 std::vector<T> tmp(inputData.size());
1693 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data(), sizeof(T));
1694 inputData = tmp;
1695 }
1696
1697 auto batchedInput = MakeTensor<T, 4>(inputTensorInfo, inputData);
1698
1699 // Construct the output data, with bias applied, as appropriate.
1700 std::vector<T> outputData;
1701 outputData.assign(outputExpected.data(), outputExpected.data() + outputChannels*outputHeight*outputWidth);
1702 if (biasEnabled)
1703 {
1704 std::vector<T> biasV;
1705 biasV.assign(bias.data(), bias.data() + outputChannels);
1706 ApplyBias(outputData, outputTensorInfo.GetQuantizationScale(), outputTensorInfo.GetQuantizationOffset(),
1707 biasV, biasDesc.GetQuantizationScale(), biasDesc.GetQuantizationOffset(),
1708 outputWidth, outputHeight);
1709 }
1710
1711 LayerTestResult<T, 4> ret(outputTensorInfo);
1712
1713 // At this point if we require it permute the expected output
1714 if (layout == armnn::DataLayout::NHWC)
1715 {
1716 std::vector<T> tmp(outputData.size());
1717 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp.data(), sizeof(T));
1718 outputData = tmp;
1719 }
1720
1721 ret.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
Keith Davisf500d6c2020-08-31 08:32:55 +01001722
1723 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
1724 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
1725
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001726 armnn::ScopedCpuTensorHandle weightsTensor(kernelDesc);
1727
1728 AllocateAndCopyDataToITensorHandle(&weightsTensor, &kernel[0][0][0][0]);
1729
1730 armnn::ScopedCpuTensorHandle biasTensor(biasDesc);
1731 if (biasEnabled)
1732 {
1733 AllocateAndCopyDataToITensorHandle(&biasTensor, &bias[0]);
1734 }
1735
1736 armnn::DepthwiseConvolution2dQueueDescriptor data;
1737 data.m_Weight = &weightsTensor;
1738 data.m_Bias = &biasTensor; // Still set this whether or not bias is enabled - it can be a source of bugs.
1739 data.m_Parameters.m_StrideX = strideX;
1740 data.m_Parameters.m_StrideY = strideY;
1741 data.m_Parameters.m_PadLeft = padLeft;
1742 data.m_Parameters.m_PadRight = padRight;
1743 data.m_Parameters.m_PadTop = padTop;
1744 data.m_Parameters.m_PadBottom = padBottom;
1745 data.m_Parameters.m_BiasEnabled = biasEnabled;
1746 data.m_Parameters.m_DataLayout = layout;
1747
1748 armnn::WorkloadInfo info;
1749 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
1750 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
1751
1752 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateDepthwiseConvolution2d(data, info);
1753 inputHandle->Allocate();
1754 outputHandle->Allocate();
1755
1756 CopyDataToITensorHandle(inputHandle.get(), &batchedInput[0][0][0][0]);
1757
1758 ExecuteWorkload(*workload, memoryManager);
1759
1760 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
1761
1762 return ret;
1763}
1764
1765template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>>
1766LayerTestResult<T, 4> DepthwiseConvolution2dDepthMul1TestImpl(
1767 armnn::IWorkloadFactory& workloadFactory,
1768 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001769 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001770 float qScale,
1771 int32_t qOffset,
1772 bool biasEnabled,
1773 const armnn::DataLayout layout)
1774{
1775 using B = armnn::ResolveType<ArmnnBType>;
1776
1777 unsigned int inputHeight = 3;
1778 unsigned int inputWidth = 3;
1779 unsigned int inputChannels = 2;
1780 unsigned int inputNum = 1;
1781
1782 unsigned int kernelHeight = 3;
1783 unsigned int kernelWidth = 3;
1784 unsigned int kernelChannels = inputChannels;
1785 unsigned int kernelDepthMultiplier = 1;
1786
1787 unsigned int outputHeight = 1;
1788 unsigned int outputWidth = 1;
1789 unsigned int outputChannels = kernelChannels;
1790 unsigned int outputNum = inputNum;
1791
1792 armnn::TensorInfo inputTensorInfo =
1793 armnnUtils::GetTensorInfo(inputNum, inputChannels, inputHeight, inputWidth, layout, ArmnnType);
1794 armnn::TensorInfo outputTensorInfo =
1795 armnnUtils::GetTensorInfo(outputNum, outputChannels, outputHeight, outputWidth, layout, ArmnnType);
1796 armnn::TensorInfo kernelDesc({kernelDepthMultiplier, kernelChannels, kernelHeight, kernelWidth},
1797 ArmnnType);
1798 armnn::TensorInfo biasDesc({ outputChannels }, ArmnnBType);
1799
1800 // Set quantization parameters if the requested type is a quantized type.
1801 if(armnn::IsQuantizedType<T>())
1802 {
1803 inputTensorInfo.SetQuantizationScale(qScale);
1804 inputTensorInfo.SetQuantizationOffset(qOffset);
1805 outputTensorInfo.SetQuantizationScale(qScale);
1806 outputTensorInfo.SetQuantizationOffset(qOffset);
1807 kernelDesc.SetQuantizationScale(qScale);
1808 kernelDesc.SetQuantizationOffset(qOffset);
1809 biasDesc.SetQuantizationScale(qScale*qScale);
1810 biasDesc.SetQuantizationOffset(0);
1811 }
1812 std::vector<T> inputData = std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01001813 QuantizedVector<T>({
1814 1.f, 2.f, 1.f,
1815 2.f, 1.f, 2.f,
1816 1.f, 2.f, 1.f,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001817
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01001818 1.f, 2.f, 1.f,
1819 2.f, 1.f, 2.f,
1820 1.f, 2.f, 1.f,
1821 },
1822 inputTensorInfo.GetQuantizationScale(),
1823 inputTensorInfo.GetQuantizationOffset()));
1824
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001825 // at this point if we require it permute the input data
1826 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
1827 if (layout == armnn::DataLayout::NHWC)
1828 {
1829 std::vector<T> tmp(inputData.size());
1830 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data(), sizeof(T));
1831 inputData = tmp;
1832 }
1833 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
1834
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01001835 std::vector<B> biasV(QuantizedVector<B>({ 0, 2 },
1836 biasDesc.GetQuantizationScale(),
1837 biasDesc.GetQuantizationOffset()));
1838
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001839 auto bias = MakeTensor<B, 1>(biasDesc, biasV);
1840
1841 std::vector<T> kernelData = std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01001842 QuantizedVector<T>({
1843 1.f, 0.f, 1.f,
1844 0.f, 0.f, 0.f,
1845 -1.f, 0.f, -1.f,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001846
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01001847 1.f, 0.f, 1.f,
1848 0.f, 0.f, 0.f,
1849 -1.f, 0.f, -1.f,
1850 },
1851 kernelDesc.GetQuantizationScale(),
1852 kernelDesc.GetQuantizationOffset()));
1853
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001854 auto kernel = MakeTensor<T, 4>(kernelDesc, kernelData);
1855
1856 // Manually calculated.
1857 std::vector<T> outputImage(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01001858 QuantizedVector<T>({ 0.f, 0.f },
1859 outputTensorInfo.GetQuantizationScale(),
1860 outputTensorInfo.GetQuantizationOffset())
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001861 );
1862
1863 // Optionally apply bias to output image.
1864 if(biasEnabled)
1865 {
1866 ApplyBias(outputImage, outputTensorInfo.GetQuantizationScale(), outputTensorInfo.GetQuantizationOffset(),
1867 biasV, biasDesc.GetQuantizationScale(), biasDesc.GetQuantizationOffset(),
1868 outputWidth, outputHeight);
1869 }
1870
1871 LayerTestResult<T, 4> ret(outputTensorInfo);
1872 if (layout == armnn::DataLayout::NHWC)
1873 {
1874 std::vector<T> tmp(outputImage.size());
1875 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputImage.data(), tmp.data(), sizeof(T));
1876 outputImage = tmp;
1877 }
1878
1879 ret.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputImage);
Keith Davisf500d6c2020-08-31 08:32:55 +01001880
1881 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
1882 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
1883
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001884 armnn::DepthwiseConvolution2dQueueDescriptor data;
1885 armnn::WorkloadInfo info;
1886 armnn::ScopedCpuTensorHandle weightsTensor(kernelDesc);
1887 armnn::ScopedCpuTensorHandle biasTensor(biasDesc);
1888
1889 AllocateAndCopyDataToITensorHandle(&weightsTensor, &kernel[0][0][0][0]);
1890 AllocateAndCopyDataToITensorHandle(&biasTensor, &bias[0]);
1891
1892 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
1893 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
1894
1895 data.m_Weight = &weightsTensor;
1896 data.m_Bias = &biasTensor; // Still set this whether or not bias is enabled.
1897 data.m_Parameters.m_StrideX = 1;
1898 data.m_Parameters.m_StrideY = 1;
1899 data.m_Parameters.m_PadLeft = 0;
1900 data.m_Parameters.m_PadRight = 0;
1901 data.m_Parameters.m_PadTop = 0;
1902 data.m_Parameters.m_PadBottom = 0;
1903 data.m_Parameters.m_BiasEnabled = biasEnabled;
1904 data.m_Parameters.m_DataLayout = layout;
1905
1906 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateDepthwiseConvolution2d(data, info);
1907 inputHandle->Allocate();
1908 outputHandle->Allocate();
1909
1910 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
1911
1912 ExecuteWorkload(*workload, memoryManager);
1913
1914 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
1915
1916 return ret;
1917}
1918
1919template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>>
1920LayerTestResult<T, 4> DepthwiseConvolution2dTestImpl(
1921 armnn::IWorkloadFactory& workloadFactory,
1922 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01001923 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001924 float qScale,
1925 int32_t qOffset,
1926 bool biasEnabled,
1927 const armnn::DataLayout layout)
1928{
1929 using B = armnn::ResolveType<ArmnnBType>;
1930
1931 unsigned int depthMultiplier = 2;
1932
1933 unsigned int inputHeight = 8;
1934 unsigned int inputWidth = 16;
1935 unsigned int inputChannels = 2;
1936 unsigned int inputBatchSize = 1;
1937
1938 unsigned int kernelHeight = 5;
1939 unsigned int kernelWidth = 3;
1940
1941 unsigned int outputHeight = inputHeight - kernelHeight + 1 + 2;
1942 unsigned int outputWidth = (inputWidth - kernelWidth + 1)/2;
1943 unsigned int outputChannels = inputChannels * depthMultiplier;
1944 unsigned int outputBatchSize = inputBatchSize;
1945
1946 armnn::TensorInfo inputTensorInfo = armnnUtils::GetTensorInfo(
1947 inputBatchSize, inputChannels, inputHeight, inputWidth, layout, ArmnnType);
1948 armnn::TensorInfo outputTensorInfo = armnnUtils::GetTensorInfo(
1949 outputBatchSize, outputChannels, outputHeight, outputWidth, layout, ArmnnType);
1950 armnn::TensorInfo kernelDesc({depthMultiplier, inputChannels, kernelHeight, kernelWidth},
1951 ArmnnType);
1952 armnn::TensorInfo biasDesc({outputChannels}, ArmnnBType);
1953
1954 // Set quantization parameters if the requested type is a quantized type.
1955 if(armnn::IsQuantizedType<T>())
1956 {
1957 inputTensorInfo.SetQuantizationScale(qScale);
1958 inputTensorInfo.SetQuantizationOffset(qOffset);
1959 outputTensorInfo.SetQuantizationScale(qScale);
1960 outputTensorInfo.SetQuantizationOffset(qOffset);
1961 kernelDesc.SetQuantizationScale(qScale);
1962 kernelDesc.SetQuantizationOffset(qOffset);
1963 biasDesc.SetQuantizationScale(qScale*qScale);
1964 biasDesc.SetQuantizationOffset(0);
1965 }
1966
1967 // NOTE: originalInputData is in NCHW format
1968 std::vector<T> originalInputData = std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01001969 QuantizedVector<T>({
1970 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
1971 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1972 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
1973 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
1974 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
1975 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
1976 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
1977 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
1978 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1979 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1980 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1981 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1982 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1983 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1984 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1985 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
1986 },
1987 inputTensorInfo.GetQuantizationScale(),
1988 inputTensorInfo.GetQuantizationOffset()));
1989
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01001990 std::vector<T> inputData = originalInputData;
1991 // at this point if we require it permute the input data
1992 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
1993 if (layout == armnn::DataLayout::NHWC)
1994 {
1995 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC,
1996 originalInputData.data(), inputData.data(), sizeof(T));
1997 }
1998 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
1999
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002000 std::vector<B> biasV = QuantizedVector<B>({ 0, 2, 1, -1 },
2001 biasDesc.GetQuantizationScale(),
2002 biasDesc.GetQuantizationOffset());
2003
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002004 auto bias = MakeTensor<B, 1>(biasDesc, biasV);
2005
2006 std::vector<T> kernelData = std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002007 QuantizedVector<T>({
2008 1, 1, 1,
2009 1, -1, 1,
2010 1, 1, 1,
2011 1, 1, 1,
2012 1, 1, 1,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002013
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002014 2, 2, 2,
2015 2, 2, 2,
2016 2, 2, 2,
2017 2, 2, 2,
2018 2, 2, 2,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002019
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002020 0, 0, 0,
2021 0, -1, 0,
2022 0, 0, 0,
2023 0, 0, 0,
2024 0, 0, 0,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002025
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002026 0, 0, 0,
2027 0, 0, 0,
2028 0, 1, 0,
2029 0, 0, 0,
2030 0, 0, 0
2031 },
2032 kernelDesc.GetQuantizationScale(),
2033 kernelDesc.GetQuantizationOffset()));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002034
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002035 auto kernel = MakeTensor<T, 4>(kernelDesc, kernelData);
2036
2037 // Manually calculated.
2038 std::vector<T> originalOutputImage = std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002039 QuantizedVector<T>({
2040 3.5f, 3.5f, 3.5f, 3.5f, 3.5f, 3.5f, 3.5f,
2041 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f,
2042 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,
2043 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f,
2044 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f,
2045 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002046
2047 -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002048 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002049 -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f,
2050 -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f,
2051 -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f,
2052 -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f,
2053
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002054 8.0f, 8.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002055 10.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
2056 10.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
2057 10.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
2058 10.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002059 8.0f, 8.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002060
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002061 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
2062 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
2063 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
2064 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
2065 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
2066 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f
2067 },
2068 outputTensorInfo.GetQuantizationScale(),
2069 outputTensorInfo.GetQuantizationOffset()));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002070
2071 // Optionally apply bias to output image.
2072 if(biasEnabled)
2073 {
2074 ApplyBias(originalOutputImage,
2075 outputTensorInfo.GetQuantizationScale(),
2076 outputTensorInfo.GetQuantizationOffset(),
2077 biasV,
2078 biasDesc.GetQuantizationScale(),
2079 biasDesc.GetQuantizationOffset(),
2080 outputWidth,
2081 outputHeight);
2082 }
2083
2084 LayerTestResult<T, 4> ret(outputTensorInfo);
2085 std::vector<T> outputImage = originalOutputImage;
2086 if (layout == armnn::DataLayout::NHWC)
2087 {
2088 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC,
2089 originalOutputImage.data(), outputImage.data(), sizeof(T));
2090 }
2091
2092 ret.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputImage);
Keith Davisf500d6c2020-08-31 08:32:55 +01002093
2094 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
2095 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
2096
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002097 armnn::DepthwiseConvolution2dQueueDescriptor data;
2098 armnn::WorkloadInfo info;
2099 armnn::ScopedCpuTensorHandle weightsTensor(kernelDesc);
2100 armnn::ScopedCpuTensorHandle biasTensor(biasDesc);
2101
2102 AllocateAndCopyDataToITensorHandle(&weightsTensor, &kernel[0][0][0][0]);
2103 AllocateAndCopyDataToITensorHandle(&biasTensor, &bias[0]);
2104
2105 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
2106 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
2107
2108 data.m_Weight = &weightsTensor;
2109 data.m_Bias = &biasTensor; // Still set this whether or not bias is enabled.
2110 data.m_Parameters.m_StrideX = 2;
2111 data.m_Parameters.m_StrideY = 1;
2112 data.m_Parameters.m_PadLeft = 0;
2113 data.m_Parameters.m_PadRight = 0;
2114 data.m_Parameters.m_PadTop = 1;
2115 data.m_Parameters.m_PadBottom = 1;
2116 data.m_Parameters.m_BiasEnabled = biasEnabled;
2117 data.m_Parameters.m_DataLayout = layout;
2118
2119 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateDepthwiseConvolution2d(data, info);
2120 inputHandle->Allocate();
2121 outputHandle->Allocate();
2122
2123 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
2124
2125 ExecuteWorkload(*workload, memoryManager);
2126
2127 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
2128
2129 return ret;
2130}
2131
2132template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
2133 typename T = armnn::ResolveType<ArmnnType>, typename B = armnn::ResolveType<ArmnnBType>>
2134LayerTestResult<T, 4> DepthwiseConvolution2dTestImpl(
2135 armnn::IWorkloadFactory& workloadFactory,
2136 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002137 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002138 const boost::multi_array<T, 4>& originalInput,
2139 const boost::multi_array<T, 4>& originalKernel,
2140 const boost::multi_array<B, 1>& bias,
2141 const boost::multi_array<T, 4>& originalOutputExpected,
2142 float qScale,
2143 int32_t qOffset,
2144 const armnn::DataLayout layout = armnn::DataLayout::NCHW,
2145 uint32_t padLeft = 0,
2146 uint32_t padTop = 0,
2147 uint32_t padRight = 0,
2148 uint32_t padBottom = 0,
2149 uint32_t strideX = 1,
2150 uint32_t strideY = 1,
2151 uint32_t dilationX = 1,
2152 uint32_t dilationY = 1)
2153{
2154 unsigned int inputHeight = boost::numeric_cast<unsigned int>(originalInput.shape()[2]);
2155 unsigned int inputWidth = boost::numeric_cast<unsigned int>(originalInput.shape()[3]);
2156 unsigned int inputChannels = boost::numeric_cast<unsigned int>(originalInput.shape()[1]);
2157 unsigned int inputNum = boost::numeric_cast<unsigned int>(originalInput.shape()[0]);
2158
2159 unsigned int outputHeight = boost::numeric_cast<unsigned int>(originalOutputExpected.shape()[2]);
2160 unsigned int outputWidth = boost::numeric_cast<unsigned int>(originalOutputExpected.shape()[3]);
2161 unsigned int outputChannels = boost::numeric_cast<unsigned int>(originalOutputExpected.shape()[1]);
2162 unsigned int outputNum = boost::numeric_cast<unsigned int>(originalOutputExpected.shape()[0]);
2163
2164 unsigned int kernelHeight = boost::numeric_cast<unsigned int>(originalKernel.shape()[2]);
2165 unsigned int kernelWidth = boost::numeric_cast<unsigned int>(originalKernel.shape()[3]);
2166 unsigned int kernelChannels = boost::numeric_cast<unsigned int>(originalKernel.shape()[1]);
2167 unsigned int kernelDepthMul = boost::numeric_cast<unsigned int>(originalKernel.shape()[0]);
2168
2169 bool biasEnabled = bias.size() > 0;
2170
2171 // This function currently assumes 1 batch of input/output (and duplicates this into 2 batches).
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01002172 ARMNN_ASSERT(inputNum == 1);
2173 ARMNN_ASSERT(outputNum == 1);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002174
2175 // If a bias is used, its size must equal the number of output channels.
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +01002176 ARMNN_ASSERT(!biasEnabled || bias.size() == outputChannels);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002177
2178
2179 // Note these tensors will use two (identical) batches.
2180 armnn::TensorInfo inputTensorInfo =
2181 armnnUtils::GetTensorInfo(2*inputNum, inputChannels, inputHeight, inputWidth, layout, ArmnnType);
2182 armnn::TensorInfo outputTensorInfo =
2183 armnnUtils::GetTensorInfo(2*outputNum, outputChannels, outputHeight, outputWidth, layout, ArmnnType);
2184
2185 // Kernel must be NCHW layout always, independently of the layout of the input and output for depthwise convolution.
2186 armnn::TensorInfo kernelDesc({kernelDepthMul, kernelChannels, kernelHeight, kernelWidth}, ArmnnType);
2187
2188 armnn::TensorInfo biasDesc({static_cast<unsigned int>(bias.size())}, ArmnnBType);
2189
2190 // Set quantization parameters if the requested type is a quantized type.
2191 if(armnn::IsQuantizedType<T>())
2192 {
2193 inputTensorInfo.SetQuantizationScale(qScale);
2194 inputTensorInfo.SetQuantizationOffset(qOffset);
2195 outputTensorInfo.SetQuantizationScale(qScale);
2196 outputTensorInfo.SetQuantizationOffset(qOffset);
2197 kernelDesc.SetQuantizationScale(qScale);
2198 kernelDesc.SetQuantizationOffset(qOffset);
2199 biasDesc.SetQuantizationScale(qScale*qScale);
2200 biasDesc.SetQuantizationOffset(0);
2201 }
2202
2203 LayerTestResult<T, 4> ret(outputTensorInfo);
2204
2205 // Construct input data
2206 std::vector<T> input;
2207 input.assign(originalInput.data(), originalInput.data() + 1*inputChannels*inputHeight*inputWidth);
2208 std::vector<T> inputData;
2209 inputData.insert(inputData.end(), input.begin(), input.end());
2210 inputData.insert(inputData.end(), input.begin(), input.end());
2211
2212 // at this point if we require it permute the input data
2213 const armnn::PermutationVector NCHWToNHWC = { 0, 3, 1, 2 };
2214 if (layout == armnn::DataLayout::NHWC)
2215 {
2216 std::vector<T> tmp(inputData.size());
2217 armnnUtils::Permute(inputTensorInfo.GetShape(), NCHWToNHWC, inputData.data(), tmp.data(), sizeof(T));
2218 inputData = tmp;
2219 }
2220
2221 auto batchedInput = MakeTensor<T, 4>(inputTensorInfo, inputData);
2222
2223 std::vector<T> output;
2224 output.assign(originalOutputExpected.data(),
2225 originalOutputExpected.data() + outputChannels*outputHeight*outputWidth);
2226
2227 // Apply bias to output data if it is enabled.
2228 if(biasEnabled)
2229 {
2230 std::vector<T> biasV;
2231 biasV.assign(bias.data(), bias.data() + outputChannels);
2232 ApplyBias(output, outputTensorInfo.GetQuantizationScale(), outputTensorInfo.GetQuantizationOffset(),
2233 biasV, biasDesc.GetQuantizationScale(), biasDesc.GetQuantizationOffset(),
2234 outputWidth, outputHeight);
2235 }
2236
2237 // Construct expected output data
2238 std::vector<T> outputData;
2239 outputData.insert(outputData.end(), output.begin(), output.end());
2240 outputData.insert(outputData.end(), output.begin(), output.end());
2241
2242 // at this point if we require it permute the expected output
2243 if (layout == armnn::DataLayout::NHWC)
2244 {
2245 std::vector<T> tmp(outputData.size());
2246 armnnUtils::Permute(outputTensorInfo.GetShape(), NCHWToNHWC, outputData.data(), tmp.data(), sizeof(T));
2247 outputData = tmp;
2248 }
2249 ret.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputData);
Keith Davisf500d6c2020-08-31 08:32:55 +01002250
2251 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
2252 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
2253
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002254 armnn::DepthwiseConvolution2dQueueDescriptor data;
2255 armnn::WorkloadInfo info;
2256 armnn::ScopedCpuTensorHandle weightsTensor(kernelDesc);
2257 armnn::ScopedCpuTensorHandle biasTensor(biasDesc);
2258
2259 boost::multi_array<T, 4> kernel = boost::multi_array<T, 4>(originalKernel);
2260 AllocateAndCopyDataToITensorHandle(&weightsTensor, &kernel[0][0][0][0]);
2261
2262 if(biasEnabled)
2263 {
2264 AllocateAndCopyDataToITensorHandle(&biasTensor, &bias[0]);
2265 }
2266
2267 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
2268 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
2269
2270 data.m_Weight = &weightsTensor;
2271 data.m_Bias = &biasTensor; // Still set this whether or not bias is enabled - can be a source of bugs.
2272 data.m_Parameters.m_StrideX = strideX;
2273 data.m_Parameters.m_StrideY = strideY;
2274 data.m_Parameters.m_PadLeft = padLeft;
2275 data.m_Parameters.m_PadRight = padRight;
2276 data.m_Parameters.m_PadTop = padTop;
2277 data.m_Parameters.m_PadBottom = padBottom;
2278 data.m_Parameters.m_BiasEnabled = biasEnabled;
2279 data.m_Parameters.m_DataLayout = layout;
2280 data.m_Parameters.m_DilationX = dilationX;
2281 data.m_Parameters.m_DilationY = dilationY;
2282
2283 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateDepthwiseConvolution2d(data, info);
2284 inputHandle->Allocate();
2285 outputHandle->Allocate();
2286
2287 CopyDataToITensorHandle(inputHandle.get(), &batchedInput[0][0][0][0]);
2288
2289 ExecuteWorkload(*workload, memoryManager);
2290
2291 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
2292
2293 return ret;
2294}
2295
2296template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
2297 typename T = armnn::ResolveType<ArmnnType>>
2298LayerTestResult<T, 4> DepthwiseConvolution2dAsymmetricTestCommon(
2299 armnn::IWorkloadFactory& workloadFactory,
2300 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002301 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002302 float qScale,
2303 int32_t qOffset,
2304 bool biasEnabled,
2305 const armnn::DataLayout layout)
2306{
2307 // Use a single-batch 2-channel 5x5 image as input.
2308 armnn::TensorInfo inputTensorInfo({ 1, 2, 5, 5 }, ArmnnType);
2309 auto input = MakeTensor<T, 4>(inputTensorInfo, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002310 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002311 0, 1, 2, 3, 4,
2312 5, 6, 7, 8, 9,
2313 10, 11, 12, 13, 14,
2314 15, 16, 17, 18, 19,
2315 20, 21, 22, 23, 24,
2316
2317 25, 26, 27, 28, 29,
2318 30, 31, 32, 33, 34,
2319 35, 36, 37, 38, 39,
2320 40, 41, 42, 43, 44,
2321 45, 46, 47, 48, 49
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002322 },
2323 inputTensorInfo.GetQuantizationScale(),
2324 inputTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002325
2326 // Use a depth multiplier of 1 on a 2-channel 4x4 kernel.
2327 armnn::TensorInfo kernelTensorInfo({ 1, 2, 4, 4 }, ArmnnType);
2328 auto kernel = MakeTensor<T, 4>(kernelTensorInfo, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002329 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002330 32, 31, 30, 29,
2331 28, 27, 26, 25,
2332 24, 23, 22, 21,
2333 20, 19, 18, 17,
2334
2335 16, 15, 14, 13,
2336 12, 11, 10, 9,
2337 8, 7, 6, 5,
2338 4, 3, 2, 1
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002339 },
2340 kernelTensorInfo.GetQuantizationScale(),
2341 kernelTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002342
2343 // Expected output is 1 batch of a 2-channel 5x5 image.
2344 // Calculated using the python tensorflow library with strideX=1, strideY=1.
2345 armnn::TensorInfo outputTensorInfo({ 1, 2, 5, 5 }, ArmnnType);
2346 boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputTensorInfo, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002347 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002348 1062, 1580, 1850, 1530, 1117,
2349 2140, 3108, 3500, 2842, 2042,
2350 3580, 5068, 5460, 4342, 3062,
2351 3618, 5072, 5390, 4248, 2971,
2352 3074, 4282, 4510, 3533, 2457,
2353
2354 1550, 2284, 2362, 1955, 1428,
2355 2910, 4206, 4342, 3528, 2536,
2356 3390, 4886, 5022, 4068, 2916,
2357 3566, 5056, 5182, 4133, 2922,
2358 3100, 4352, 4452, 3517, 2465
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002359 },
2360 outputTensorInfo.GetQuantizationScale(),
2361 outputTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002362
2363 return DepthwiseConvolution2dAsymmetricTestImpl<ArmnnType, ArmnnBType>(
2364 workloadFactory,
2365 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002366 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002367 input,
2368 kernel,
2369 GetBias2<ArmnnBType>(biasEnabled, qScale * qScale),
2370 expectedOutput,
2371 qScale,
2372 qOffset,
2373 layout,
2374 1, // Padding left.
2375 1, // Padding top.
2376 2, // Padding right.
2377 2, // Padding bottom.
2378 1, // strideX
2379 1); // strideY
2380}
2381
2382template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
2383 typename T = armnn::ResolveType<ArmnnType>>
2384LayerTestResult<T, 4> DepthwiseConvolution2dNhwcTestCommon(
2385 armnn::IWorkloadFactory& workloadFactory,
2386 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002387 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002388 float qScale,
2389 int32_t qOffset,
2390 bool biasEnabled)
2391{
2392 auto layout = armnn::DataLayout::NHWC;
2393
2394 armnn::TensorInfo inputTensorInfo({ 1, 2, 5, 5}, ArmnnType);
2395 auto input = MakeTensor<T, 4>(inputTensorInfo, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002396 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002397 0, 1, 2, 3, 4,
2398 5, 6, 7, 8, 9,
2399 10, 11, 12, 13, 14,
2400 15, 16, 17, 18, 19,
2401 20, 21, 22, 23, 24,
2402
2403 25, 26, 27, 28, 29,
2404 30, 31, 32, 33, 34,
2405 35, 36, 37, 38, 39,
2406 40, 41, 42, 43, 44,
2407 45, 46, 47, 48, 49
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002408 },
2409 inputTensorInfo.GetQuantizationScale(),
2410 inputTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002411
2412 armnn::TensorInfo kernelTensorInfo({ 1, 2, 4, 4 }, ArmnnType);
2413 auto kernel = MakeTensor<T, 4>(kernelTensorInfo, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002414 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002415 32, 31, 30, 29,
2416 28, 27, 26, 25,
2417 24, 23, 22, 21,
2418 20, 19, 18, 17,
2419
2420 16, 15, 14, 13,
2421 12, 11, 10, 9,
2422 8, 7, 6, 5,
2423 4, 3, 2, 1
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002424 },
2425 kernelTensorInfo.GetQuantizationScale(),
2426 kernelTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002427
2428 armnn::TensorInfo outputTensorInfo({ 1, 2, 5, 5}, ArmnnType);
2429 boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputTensorInfo, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002430 QuantizedVector<T>({
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002431 1062, 1580, 1850, 1530, 1117,
2432 2140, 3108, 3500, 2842, 2042,
2433 3580, 5068, 5460, 4342, 3062,
2434 3618, 5072, 5390, 4248, 2971,
2435 3074, 4282, 4510, 3533, 2457,
2436
2437 1550, 2284, 2362, 1955, 1428,
2438 2910, 4206, 4342, 3528, 2536,
2439 3390, 4886, 5022, 4068, 2916,
2440 3566, 5056, 5182, 4133, 2922,
2441 3100, 4352, 4452, 3517, 2465
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002442 },
2443 outputTensorInfo.GetQuantizationScale(),
2444 outputTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002445
2446 return DepthwiseConvolution2dTestImpl<ArmnnType, ArmnnBType>(
2447 workloadFactory,
2448 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002449 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002450 input,
2451 kernel,
2452 GetBias2<ArmnnBType>(biasEnabled, qScale * qScale),
2453 expectedOutput,
2454 qScale,
2455 qOffset,
2456 layout,
2457 1, // Padding left.
2458 1, // Padding top.
2459 2, // Padding right.
2460 2, // Padding bottom.
2461 1, // strideX
2462 1); // strideY
2463}
2464
2465template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType,
2466 typename T = armnn::ResolveType<ArmnnType>>
2467LayerTestResult<T, 4> SimpleDepthwiseConvolution2d3x3Dilation3x3NhwcTestCommon(
2468 armnn::IWorkloadFactory& workloadFactory,
2469 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002470 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002471 float qScale,
2472 int32_t qOffset,
2473 bool biasEnabled)
2474{
2475 auto layout = armnn::DataLayout::NHWC;
2476
2477 armnn::TensorInfo inputTensorInfo({ 1, 1, 9, 9}, ArmnnType);
2478 auto input = MakeTensor<T, 4>(inputTensorInfo, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002479 QuantizedVector<T>({
2480 0, 0, 0, 0, 0, 0, 0, 0, 0,
2481 0, 0, 0, 0, 0, 0, 0, 0, 0,
2482 0, 0, 0, 0, 0, 0, 0, 0, 0,
2483 0, 0, 0, 1, 1, 1, 0, 0, 0,
2484 0, 0, 0, 1, 1, 1, 0, 0, 0,
2485 0, 0, 0, 1, 1, 1, 0, 0, 0,
2486 0, 0, 0, 0, 0, 0, 0, 0, 0,
2487 0, 0, 0, 0, 0, 0, 0, 0, 0,
2488 0, 0, 0, 0, 0, 0, 0, 0, 0
2489 },
2490 inputTensorInfo.GetQuantizationScale(),
2491 inputTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002492
2493 armnn::TensorInfo kernelTensorInfo({ 1, 1, 3, 3}, ArmnnType);
2494 auto kernel = MakeTensor<T, 4>(kernelTensorInfo, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002495 QuantizedVector<T>({
2496 1, 2, 3,
2497 4, 5, 6,
2498 7, 8, 9
2499 },
2500 kernelTensorInfo.GetQuantizationScale(),
2501 kernelTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002502
2503 uint32_t padLeft = 0;
2504 uint32_t padTop = 0;
2505 uint32_t padRight = 0;
2506 uint32_t padBottom = 0;
2507 uint32_t strideX = 1;
2508 uint32_t strideY = 1;
2509 uint32_t dilationX = 3;
2510 uint32_t dilationY = 3;
2511
2512 // Since the dilation rate is 3 this will reduce the size of the output from 9x9 to 3x3 of all 5s.
2513 armnn::TensorInfo outputTensorInfo({ 1, 1, 3, 3}, ArmnnType);
2514 boost::multi_array<T, 4> expectedOutput = MakeTensor<T, 4>(outputTensorInfo, std::vector<T>(
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002515 QuantizedVector<T>({
2516 5, 5, 5,
2517 5, 5, 5,
2518 5, 5, 5
2519 },
2520 outputTensorInfo.GetQuantizationScale(),
2521 outputTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002522
2523 return DepthwiseConvolution2dTestImpl<ArmnnType, ArmnnBType>(
2524 workloadFactory,
2525 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002526 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002527 input,
2528 kernel,
2529 GetBias2<ArmnnBType>(biasEnabled, qScale * qScale),
2530 expectedOutput,
2531 qScale,
2532 qOffset,
2533 layout,
2534 padLeft,
2535 padTop,
2536 padRight,
2537 padBottom,
2538 strideX,
2539 strideY,
2540 dilationX,
2541 dilationY);
2542}
2543
2544template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T = armnn::ResolveType<ArmnnType>>
2545LayerTestResult<T, 4> DepthwiseConvolution2d3x3DilationTestCommon(
2546 armnn::IWorkloadFactory& workloadFactory,
2547 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002548 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002549 const std::vector<float>& inputNoQuantizedValues,
2550 armnn::TensorInfo& inputTensorInfo,
2551 const std::vector<float>& kernelNoQuantizedValues,
2552 armnn::TensorInfo& kernelTensorInfo,
2553 const std::vector<float>& outputExpectedNoQuantizedValues,
2554 armnn::TensorInfo& outputTensorInfo,
2555 uint32_t dilationX,
2556 uint32_t dilationY,
2557 armnn::DataLayout layout = armnn::DataLayout::NCHW,
2558 bool biasEnabled = false)
2559{
2560 float qScale;
2561 int32_t qOffset;
2562 switch (ArmnnType)
2563 {
Sadik Armagan303980c2020-04-17 12:45:14 +01002564 case armnn::DataType::QAsymmS8:
Derek Lambertif90c56d2020-01-10 17:14:08 +00002565 case armnn::DataType::QAsymmU8:
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002566 {
2567 qScale = 0.1f;
2568 qOffset = 128;
2569 break;
2570 }
Derek Lambertif90c56d2020-01-10 17:14:08 +00002571 case armnn::DataType::QSymmS16:
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002572 {
2573 qScale = 0.1f;
2574 qOffset = 0;
2575 break;
2576 }
2577 case armnn::DataType::Float32:
2578 default:
2579 {
2580 qScale = 0.f;
2581 qOffset = 0;
2582 break;
2583 }
2584 }
2585
2586 inputTensorInfo.SetQuantizationScale(qScale);
2587 inputTensorInfo.SetQuantizationOffset(qOffset);
2588 kernelTensorInfo.SetQuantizationScale(qScale);
2589 kernelTensorInfo.SetQuantizationOffset(qOffset);
2590 outputTensorInfo.SetQuantizationScale(qScale);
2591 outputTensorInfo.SetQuantizationOffset(qOffset);
2592
2593 auto input = MakeTensor<T, 4>(inputTensorInfo,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002594 std::vector<T>(QuantizedVector<T>(inputNoQuantizedValues,
2595 inputTensorInfo.GetQuantizationScale(),
2596 inputTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002597 auto kernel = MakeTensor<T, 4>(kernelTensorInfo,
Aron Virginas-Tar48623a02019-10-22 10:00:28 +01002598 std::vector<T>(QuantizedVector<T>(kernelNoQuantizedValues,
2599 kernelTensorInfo.GetQuantizationScale(),
2600 kernelTensorInfo.GetQuantizationOffset())));
2601 auto expectedOutput =
2602 MakeTensor<T, 4>(outputTensorInfo,
2603 std::vector<T>(QuantizedVector<T>(outputExpectedNoQuantizedValues,
2604 outputTensorInfo.GetQuantizationScale(),
2605 outputTensorInfo.GetQuantizationOffset())));
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002606
2607 uint32_t padLeft = 0;
2608 uint32_t padTop = 0;
2609 uint32_t padRight = 0;
2610 uint32_t padBottom = 0;
2611 uint32_t strideX = 1;
2612 uint32_t strideY = 1;
2613
2614 return DepthwiseConvolution2dTestImpl<ArmnnType, ArmnnBType>(
2615 workloadFactory,
2616 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002617 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002618 input,
2619 kernel,
2620 GetBias<ArmnnBType>(biasEnabled, qScale * qScale, outputTensorInfo, layout),
2621 expectedOutput,
2622 qScale,
2623 qOffset,
2624 layout,
2625 padLeft,
2626 padTop,
2627 padRight,
2628 padBottom,
2629 strideX,
2630 strideY,
2631 dilationX,
2632 dilationY);
2633}
2634
2635template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T>
2636LayerTestResult<T, 4> DepthwiseConvolution2d3x3Dilation3x3Test(
2637 armnn::IWorkloadFactory& workloadFactory,
2638 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002639 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002640 bool biasEnabled,
2641 const armnn::DataLayout layout)
2642{
2643 armnn::TensorInfo inputTensorInfo({1, 1, 10, 10}, ArmnnType);
2644 std::vector<float> inputNoQuantizedValues =
2645 {
2646 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2647 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2648 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2649 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
2650 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
2651 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
2652 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2653 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2654 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2655 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2656 };
2657
2658 armnn::TensorInfo kernelTensorInfo({ 1, 1, 3, 3}, ArmnnType);
2659 std::vector<float> kernelNoQuantizedValues =
2660 {
2661 1, 2, 3,
2662 4, 5, 6,
2663 7, 8, 9
2664 };
2665
2666 // Since the dilation rate is 3 this will dilate the kernel to be like 7x7,
2667 // therefore the output will be 4x4: (I−K+2P)/S +1 => (10-7 +0)/1 +1
2668 armnn::TensorInfo outputTensorInfo({ 1, 1, 4, 4}, ArmnnType);
2669 std::vector<float> outputExpectedNoQuantizedValues =
2670 {
2671 6., 5., 5., 5.,
2672 6., 5., 5., 5.,
2673 6., 5., 5., 5.,
2674 3., 2., 2., 2.
2675 };
2676
2677 return DepthwiseConvolution2d3x3DilationTestCommon<ArmnnType, ArmnnBType>(
2678 workloadFactory,
2679 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002680 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002681 inputNoQuantizedValues,
2682 inputTensorInfo,
2683 kernelNoQuantizedValues,
2684 kernelTensorInfo,
2685 outputExpectedNoQuantizedValues,
2686 outputTensorInfo,
2687 3,
2688 3,
2689 layout,
2690 biasEnabled);
2691}
2692
2693template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T>
2694LayerTestResult<T, 4> DepthwiseConvolution2d2x3x3Dilation3x3Test(
2695 armnn::IWorkloadFactory& workloadFactory,
2696 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002697 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002698 bool biasEnabled,
2699 const armnn::DataLayout layout)
2700{
2701 armnn::TensorInfo inputTensorInfo({1, 2, 10, 10}, ArmnnType);
2702 std::vector<float> inputNoQuantizedValues =
2703 {
2704 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2705 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2706 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2707 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
2708 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
2709 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
2710 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2711 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2712 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2713 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2714
2715 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2716 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2717 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2718 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
2719 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
2720 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
2721 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2722 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2723 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2724 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2725 };
2726
2727 armnn::TensorInfo kernelTensorInfo({ 1, 2, 3, 3}, ArmnnType);
2728 std::vector<float> kernelNoQuantizedValues =
2729 {
2730 1, 2, 3,
2731 4, 5, 6,
2732 7, 8, 9,
2733
2734 1, 2, 3,
2735 4, 5, 6,
2736 7, 8, 9
2737 };
2738
2739 // Since the dilation rate is 3 this will dilate the kernel to be like 7x7,
2740 // therefore the output will be 2x4x4: (I−K+2P)/S +1 => (10-7 +0)/1 +1
2741 armnn::TensorInfo outputTensorInfo({ 1, 2, 4, 4}, ArmnnType);
2742 std::vector<float> outputExpectedNoQuantizedValues =
2743 {
2744 6., 5., 5., 5.,
2745 6., 5., 5., 5.,
2746 6., 5., 5., 5.,
2747 3., 2., 2., 2.,
2748
2749 6., 5., 5., 5.,
2750 6., 5., 5., 5.,
2751 6., 5., 5., 5.,
2752 3., 2., 2., 2.
2753 };
2754
2755 return DepthwiseConvolution2d3x3DilationTestCommon<ArmnnType, ArmnnBType>(
2756 workloadFactory,
2757 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002758 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002759 inputNoQuantizedValues,
2760 inputTensorInfo,
2761 kernelNoQuantizedValues,
2762 kernelTensorInfo,
2763 outputExpectedNoQuantizedValues,
2764 outputTensorInfo,
2765 3,
2766 3,
2767 layout,
2768 biasEnabled);
2769}
2770
2771template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T>
2772LayerTestResult<T, 4> DepthwiseConvolution2dMult4Test(
2773 armnn::IWorkloadFactory& workloadFactory,
2774 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002775 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002776 bool biasEnabled,
2777 const armnn::DataLayout layout)
2778{
2779 armnn::TensorInfo inputTensorInfo({1, 2, 3, 3}, ArmnnType);
2780 std::vector<float> inputNoQuantizedValues =
2781 {
2782 10.0, 10.0, 10.0,
2783 10.0, 10.0, 10.0,
2784 10.0, 10.0, 10.0,
2785
2786 21.0, 22.0, 23.0,
2787 24.0, 25.0, 26.0,
2788 27.0, 28.0, 29.0
2789 };
2790
2791 armnn::TensorInfo kernelTensorInfo({ 4, 2, 2, 2}, ArmnnType);
2792
2793 std::vector<float> kernelNoQuantizedValues =
2794 {
2795 0.25f, 0.25f,
2796 0.25f, 0.25f,
2797
2798 0.25f, 0.25f,
2799 0.25f, 0.25f,
2800
2801 0.0f , 0.0f,
2802 0.0f , 0.1f,
2803
2804 0.0f , 0.0f,
2805 0.0f , 0.1f,
2806
2807 0.2f , 0.0f,
2808 0.0f , 0.0f,
2809
2810 0.2f , 0.0f,
2811 0.0f , 0.0f,
2812
2813 0.0f , 0.3f,
2814 0.0f , 0.0f,
2815
2816 0.0f , 0.3f,
2817 0.0f , 0.0f
2818 };
2819
2820 armnn::TensorInfo outputTensorInfo({ 1, 8, 2, 2}, ArmnnType);
2821 std::vector<float> outputExpectedNoQuantizedValues =
2822 {
2823 10.f, 10.f,
2824 10.f, 10.f,
2825
2826 1.f, 1.f,
2827 1.f, 1.f,
2828
2829 2.f, 2.f,
2830 2.f, 2.f,
2831
2832 3.f, 3.f,
2833 3.f, 3.f,
2834
2835 23.f, 24.f,
2836 26.f, 27.f,
2837
2838 2.5f, 2.6000001f,
2839 2.8f, 2.9f,
2840
2841 4.2000003f, 4.4f,
2842 4.8f, 5.f,
2843
2844 6.6000004f, 6.9f,
2845 7.5000005f, 7.8f
2846 };
2847
2848
2849 return DepthwiseConvolution2d3x3DilationTestCommon<ArmnnType, ArmnnBType>(
2850 workloadFactory,
2851 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002852 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002853 inputNoQuantizedValues,
2854 inputTensorInfo,
2855 kernelNoQuantizedValues,
2856 kernelTensorInfo,
2857 outputExpectedNoQuantizedValues,
2858 outputTensorInfo,
2859 1,
2860 1,
2861 layout,
2862 biasEnabled);
2863}
2864
2865template<armnn::DataType ArmnnType, armnn::DataType ArmnnBType, typename T>
2866LayerTestResult<T, 4> DepthwiseConvolution2dMult2Test(
2867 armnn::IWorkloadFactory& workloadFactory,
2868 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002869 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002870 bool biasEnabled,
2871 const armnn::DataLayout layout)
2872{
2873 armnn::TensorInfo inputTensorInfo({1, 2, 3, 3}, ArmnnType);
2874 std::vector<float> inputNoQuantizedValues =
2875 {
2876 10.0, 10.0, 10.0,
2877 10.0, 10.0, 10.0,
2878 10.0, 10.0, 10.0,
2879
2880 21.0, 22.0, 23.0,
2881 24.0, 25.0, 26.0,
2882 27.0, 28.0, 29.0
2883 };
2884
2885 armnn::TensorInfo kernelTensorInfo({ 2, 2, 2, 2}, ArmnnType);
2886
2887 std::vector<float> kernelNoQuantizedValues =
2888 {
2889 0.25f, 0.25f,
2890 0.25f, 0.25f,
2891
2892 0.2f , 0.0f,
2893 0.0f , 0.0f,
2894
2895 0.0f , 0.0f,
2896 0.0f , 0.1f,
2897
2898 0.0f , 0.3f,
2899 0.0f , 0.0f
2900
2901 };
2902
2903 armnn::TensorInfo outputTensorInfo({ 1, 4, 2, 2}, ArmnnType);
2904 std::vector<float> outputExpectedNoQuantizedValues =
2905 {
2906 10.f, 10.f,
2907 10.f, 10.f,
2908
2909 1.f, 1.f,
2910 1.f, 1.f,
2911
2912 4.2000003f, 4.4f,
2913 4.8f, 5.f,
2914
2915 6.6000004f, 6.9f,
2916 7.5000005f, 7.8f
2917 };
2918
2919
2920 return DepthwiseConvolution2d3x3DilationTestCommon<ArmnnType, ArmnnBType>(
2921 workloadFactory,
2922 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01002923 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002924 inputNoQuantizedValues,
2925 inputTensorInfo,
2926 kernelNoQuantizedValues,
2927 kernelTensorInfo,
2928 outputExpectedNoQuantizedValues,
2929 outputTensorInfo,
2930 1,
2931 1,
2932 layout,
2933 biasEnabled);
2934}
2935
2936template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
2937LayerTestResult<T, 4> CompareDepthwiseConvolution2dTestImpl(
2938 armnn::IWorkloadFactory& workloadFactory,
2939 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
2940 armnn::IWorkloadFactory& refWorkloadFactory,
Keith Davisf500d6c2020-08-31 08:32:55 +01002941 const armnn::ITensorHandleFactory& tensorHandleFactory,
2942 const armnn::ITensorHandleFactory& refTensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01002943 const armnnUtils::DataLayoutIndexed& layout)
2944{
2945 unsigned int inputHeight = 8;
2946 unsigned int inputWidth = 16;
2947 unsigned int inputChannels = 3;
2948 unsigned int inputNum = 5;
2949
2950 unsigned int kernelHeight = 3;
2951 unsigned int kernelWidth = 3;
2952 unsigned int channelMultiplier = 1;
2953
2954 unsigned int strideX = 2;
2955 unsigned int strideY = 3;
2956 unsigned int padX = 1;
2957 unsigned int padY = 1;
2958
2959 unsigned int outputNum = inputNum;
2960 unsigned int outputChannels = inputChannels * channelMultiplier;
2961 unsigned int outputHeight = (inputHeight + 2 * padY - kernelHeight + strideY) / strideY;
2962 unsigned int outputWidth = (inputWidth + 2 * padX - kernelWidth + strideX) / strideX;
2963
2964 armnn::TensorInfo inputTensorInfo;
2965 armnn::TensorInfo outputTensorInfo;
2966 armnn::TensorInfo kernelDesc;
2967 armnn::TensorInfo biasDesc;
2968
2969
2970 std::vector<unsigned int> inputShape;
2971 std::vector<unsigned int> outputShape;
2972 std::vector<unsigned int> kernelShape{ channelMultiplier, inputChannels, kernelHeight, kernelWidth };
2973 std::vector<unsigned int> biasShape{ outputChannels };
2974 switch (layout.GetDataLayout())
2975 {
2976 case armnn::DataLayout::NCHW:
2977 inputShape = { inputNum, inputChannels, inputHeight, inputWidth };
2978 outputShape = { outputNum, outputChannels, outputHeight, outputWidth };
2979 break;
2980 case armnn::DataLayout ::NHWC:
2981 inputShape = { inputNum, inputHeight, inputWidth, inputChannels };
2982 outputShape = { outputNum, outputHeight, outputWidth, outputChannels };
2983 break;
2984 default:
2985 throw armnn::InvalidArgumentException("unknown data layout ["
2986 + std::to_string(static_cast<int>(layout.GetDataLayout())) + "]");
2987 }
2988
2989 float inputsQScale = armnn::IsQuantizedType<T>() ? 1.0f : 0;
2990 float outputQScale = armnn::IsQuantizedType<T>() ? 2.0f : 0;
2991 int32_t qOffset = 0;
2992
2993 inputTensorInfo = armnn::TensorInfo(4, inputShape.data(), ArmnnType, inputsQScale, qOffset);
2994 outputTensorInfo = armnn::TensorInfo(4, outputShape.data(), ArmnnType, outputQScale, qOffset);
2995 kernelDesc = armnn::TensorInfo(4, kernelShape.data(), ArmnnType, inputsQScale, qOffset);
2996 biasDesc = armnn::TensorInfo(
2997 1, biasShape.data(), armnn::GetBiasDataType(ArmnnType), inputsQScale, qOffset);
2998
2999 LayerTestResult<T, 4> ret(outputTensorInfo);
3000
3001 auto input = MakeRandomTensor<T, 4>(inputTensorInfo, 124908, 0.0f, 255.0f);
3002 auto kernel = MakeRandomTensor<T, 4>(kernelDesc, 891234, 0.0f, 255.0f);
3003 auto bias = MakeRandomTensor<typename FullyConnectedBiasTypeForInputType<T>::Type, 1>(
3004 biasDesc, 1028, 0.0f, 255.0f);
Keith Davisf500d6c2020-08-31 08:32:55 +01003005
3006 std::unique_ptr<armnn::ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputTensorInfo);
3007 std::unique_ptr<armnn::ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputTensorInfo);
3008
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003009 armnn::DepthwiseConvolution2dQueueDescriptor data;
3010 armnn::WorkloadInfo info;
3011 armnn::ScopedCpuTensorHandle weightsTensor(kernelDesc);
3012 armnn::ScopedCpuTensorHandle biasTensor(biasDesc);
3013
3014 AllocateAndCopyDataToITensorHandle(&weightsTensor, &kernel[0][0][0][0]);
3015 AllocateAndCopyDataToITensorHandle(&biasTensor, &bias[0]);
3016
3017 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
3018 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
3019 data.m_Weight = &weightsTensor;
3020 data.m_Bias = &biasTensor;
3021 data.m_Parameters.m_StrideX = strideX;
3022 data.m_Parameters.m_StrideY = strideY;
3023 data.m_Parameters.m_PadLeft = padX;
3024 data.m_Parameters.m_PadRight = padX;
3025 data.m_Parameters.m_PadTop = padY;
3026 data.m_Parameters.m_PadBottom = padY;
3027 data.m_Parameters.m_BiasEnabled = true;
3028 data.m_Parameters.m_DataLayout = layout.GetDataLayout();
Keith Davisf500d6c2020-08-31 08:32:55 +01003029
3030 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refTensorHandleFactory.CreateTensorHandle(outputTensorInfo);
3031 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refTensorHandleFactory.CreateTensorHandle(inputTensorInfo);
3032
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003033 armnn::DepthwiseConvolution2dQueueDescriptor refData = data;
3034 armnn::WorkloadInfo refInfo = info;
3035 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
3036 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
3037
3038 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateDepthwiseConvolution2d(data, info);
3039 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateDepthwiseConvolution2d(refData, refInfo);
3040
3041 outputHandleRef->Allocate();
3042 inputHandleRef->Allocate();
3043
3044 inputHandle->Allocate();
3045 outputHandle->Allocate();
3046
3047 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
3048 CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0][0][0]);
3049
3050 ExecuteWorkload(*workload, memoryManager);
3051
3052 workloadRef->PostAllocationConfigure();
3053 workloadRef->Execute();
3054
3055 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
3056 CopyDataFromITensorHandle(&ret.outputExpected[0][0][0][0], outputHandleRef.get());
3057
3058 return ret;
3059}
3060
3061//
3062// Explicit template specializations
3063//
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003064template LayerTestResult<armnn::ResolveType<armnn::DataType::BFloat16>, 4>
3065Convolution2d3x3Dilation3x3Test<armnn::DataType::BFloat16, armnn::DataType::BFloat16>(
3066 armnn::IWorkloadFactory&,
3067 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003068 const armnn::ITensorHandleFactory&,
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003069 bool,
3070 armnn::DataLayout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003071
3072template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 4>
3073Convolution2d3x3Dilation3x3Test<armnn::DataType::Float32, armnn::DataType::Float32>(
3074 armnn::IWorkloadFactory&,
3075 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003076 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003077 bool,
3078 armnn::DataLayout);
3079
Sadik Armagan303980c2020-04-17 12:45:14 +01003080template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmS8>, 4>
3081Convolution2d3x3Dilation3x3Test<armnn::DataType::QAsymmS8, armnn::DataType::Signed32>(
3082 armnn::IWorkloadFactory&,
3083 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003084 const armnn::ITensorHandleFactory&,
Sadik Armagan303980c2020-04-17 12:45:14 +01003085 bool,
3086 armnn::DataLayout);
3087
Derek Lambertif90c56d2020-01-10 17:14:08 +00003088template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmU8>, 4>
3089Convolution2d3x3Dilation3x3Test<armnn::DataType::QAsymmU8, armnn::DataType::Signed32>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003090 armnn::IWorkloadFactory&,
3091 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003092 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003093 bool,
3094 armnn::DataLayout);
3095
Derek Lambertif90c56d2020-01-10 17:14:08 +00003096template LayerTestResult<armnn::ResolveType<armnn::DataType::QSymmS16>, 4>
3097Convolution2d3x3Dilation3x3Test<armnn::DataType::QSymmS16, armnn::DataType::Signed32>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003098 armnn::IWorkloadFactory&,
3099 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003100 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003101 bool,
3102 armnn::DataLayout);
3103
3104template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 4>
3105Convolution2d2x3x3Dilation3x3Test<armnn::DataType::Float32, armnn::DataType::Float32>(
3106 armnn::IWorkloadFactory&,
3107 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003108 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003109 bool,
3110 armnn::DataLayout);
3111
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003112template LayerTestResult<armnn::ResolveType<armnn::DataType::BFloat16>, 4>
3113Convolution2d2x3x3Dilation3x3Test<armnn::DataType::BFloat16, armnn::DataType::BFloat16>(
3114 armnn::IWorkloadFactory&,
3115 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003116 const armnn::ITensorHandleFactory&,
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003117 bool,
3118 armnn::DataLayout);
3119
Sadik Armagan303980c2020-04-17 12:45:14 +01003120template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmS8>, 4>
3121Convolution2d2x3x3Dilation3x3Test<armnn::DataType::QAsymmS8, armnn::DataType::Signed32>(
3122 armnn::IWorkloadFactory&,
3123 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003124 const armnn::ITensorHandleFactory&,
Sadik Armagan303980c2020-04-17 12:45:14 +01003125 bool,
3126 armnn::DataLayout);
3127
Derek Lambertif90c56d2020-01-10 17:14:08 +00003128template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmU8>, 4>
3129Convolution2d2x3x3Dilation3x3Test<armnn::DataType::QAsymmU8, armnn::DataType::Signed32>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003130 armnn::IWorkloadFactory&,
3131 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003132 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003133 bool,
3134 armnn::DataLayout);
3135
Derek Lambertif90c56d2020-01-10 17:14:08 +00003136template LayerTestResult<armnn::ResolveType<armnn::DataType::QSymmS16>, 4>
3137Convolution2d2x3x3Dilation3x3Test<armnn::DataType::QSymmS16, armnn::DataType::Signed32>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003138 armnn::IWorkloadFactory&,
3139 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003140 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003141 bool,
3142 armnn::DataLayout);
3143
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003144template LayerTestResult<armnn::ResolveType<armnn::DataType::BFloat16>, 4>
3145Convolution2d2x2Dilation2x2Padding2x2Stride3x3Test<armnn::DataType::BFloat16, armnn::DataType::BFloat16>(
3146 armnn::IWorkloadFactory &workloadFactory,
3147 const armnn::IBackendInternal::IMemoryManagerSharedPtr &memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003148 const armnn::ITensorHandleFactory& tensorHandleFactory,
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003149 bool biasEnabled,
3150 const armnn::DataLayout layout);
3151
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003152template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 4>
3153Convolution2d2x2Dilation2x2Padding2x2Stride3x3Test<armnn::DataType::Float32, armnn::DataType::Float32>(
3154 armnn::IWorkloadFactory &workloadFactory,
3155 const armnn::IBackendInternal::IMemoryManagerSharedPtr &memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003156 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003157 bool biasEnabled,
3158 const armnn::DataLayout layout);
3159
Sadik Armagan303980c2020-04-17 12:45:14 +01003160template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmS8>, 4>
3161Convolution2d2x2Dilation2x2Padding2x2Stride3x3Test<armnn::DataType::QAsymmS8, armnn::DataType::Signed32>(
3162 armnn::IWorkloadFactory &workloadFactory,
3163 const armnn::IBackendInternal::IMemoryManagerSharedPtr &memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003164 const armnn::ITensorHandleFactory& tensorHandleFactory,
Sadik Armagan303980c2020-04-17 12:45:14 +01003165 bool biasEnabled,
3166 const armnn::DataLayout layout);
3167
Derek Lambertif90c56d2020-01-10 17:14:08 +00003168template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmU8>, 4>
3169Convolution2d2x2Dilation2x2Padding2x2Stride3x3Test<armnn::DataType::QAsymmU8, armnn::DataType::Signed32>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003170 armnn::IWorkloadFactory &workloadFactory,
3171 const armnn::IBackendInternal::IMemoryManagerSharedPtr &memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003172 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003173 bool biasEnabled,
3174 const armnn::DataLayout layout);
3175
Derek Lambertif90c56d2020-01-10 17:14:08 +00003176template LayerTestResult<armnn::ResolveType<armnn::DataType::QSymmS16>, 4>
3177Convolution2d2x2Dilation2x2Padding2x2Stride3x3Test<armnn::DataType::QSymmS16, armnn::DataType::Signed32>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003178 armnn::IWorkloadFactory &workloadFactory,
3179 const armnn::IBackendInternal::IMemoryManagerSharedPtr &memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003180 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003181 bool biasEnabled,
3182 const armnn::DataLayout layout);
3183
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003184template LayerTestResult<armnn::ResolveType<armnn::DataType::BFloat16>, 4>
3185DepthwiseConvolution2d3x3Dilation3x3Test<armnn::DataType::BFloat16, armnn::DataType::BFloat16>(
3186 armnn::IWorkloadFactory&,
3187 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003188 const armnn::ITensorHandleFactory&,
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003189 bool,
3190 armnn::DataLayout);
3191
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003192template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 4>
3193DepthwiseConvolution2d3x3Dilation3x3Test<armnn::DataType::Float32, armnn::DataType::Float32>(
3194 armnn::IWorkloadFactory&,
3195 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003196 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003197 bool,
3198 armnn::DataLayout);
3199
Sadik Armagan303980c2020-04-17 12:45:14 +01003200template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmS8>, 4>
3201DepthwiseConvolution2d3x3Dilation3x3Test<armnn::DataType::QAsymmS8, armnn::DataType::Signed32>(
3202 armnn::IWorkloadFactory&,
3203 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003204 const armnn::ITensorHandleFactory&,
Sadik Armagan303980c2020-04-17 12:45:14 +01003205 bool,
3206 armnn::DataLayout);
3207
Derek Lambertif90c56d2020-01-10 17:14:08 +00003208template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmU8>, 4>
3209DepthwiseConvolution2d3x3Dilation3x3Test<armnn::DataType::QAsymmU8, armnn::DataType::Signed32>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003210 armnn::IWorkloadFactory&,
3211 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003212 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003213 bool,
3214 armnn::DataLayout);
3215
Derek Lambertif90c56d2020-01-10 17:14:08 +00003216template LayerTestResult<armnn::ResolveType<armnn::DataType::QSymmS16>, 4>
3217DepthwiseConvolution2d3x3Dilation3x3Test<armnn::DataType::QSymmS16, armnn::DataType::Signed32>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003218 armnn::IWorkloadFactory&,
3219 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003220 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003221 bool,
3222 armnn::DataLayout);
3223
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003224template LayerTestResult<armnn::ResolveType<armnn::DataType::BFloat16>, 4>
3225DepthwiseConvolution2d2x3x3Dilation3x3Test<armnn::DataType::BFloat16, armnn::DataType::BFloat16>(
3226 armnn::IWorkloadFactory&,
3227 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003228 const armnn::ITensorHandleFactory&,
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003229 bool,
3230 armnn::DataLayout);
3231
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003232template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 4>
3233DepthwiseConvolution2d2x3x3Dilation3x3Test<armnn::DataType::Float32, armnn::DataType::Float32>(
3234 armnn::IWorkloadFactory&,
3235 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003236 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003237 bool,
3238 armnn::DataLayout);
3239
Sadik Armagan303980c2020-04-17 12:45:14 +01003240template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmS8>, 4>
3241DepthwiseConvolution2d2x3x3Dilation3x3Test<armnn::DataType::QAsymmS8, armnn::DataType::Signed32>(
3242 armnn::IWorkloadFactory&,
3243 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003244 const armnn::ITensorHandleFactory&,
Sadik Armagan303980c2020-04-17 12:45:14 +01003245 bool,
3246 armnn::DataLayout);
3247
Derek Lambertif90c56d2020-01-10 17:14:08 +00003248template LayerTestResult<armnn::ResolveType<armnn::DataType::QAsymmU8>, 4>
3249DepthwiseConvolution2d2x3x3Dilation3x3Test<armnn::DataType::QAsymmU8, armnn::DataType::Signed32>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003250 armnn::IWorkloadFactory&,
3251 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003252 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003253 bool,
3254 armnn::DataLayout);
3255
Derek Lambertif90c56d2020-01-10 17:14:08 +00003256template LayerTestResult<armnn::ResolveType<armnn::DataType::QSymmS16>, 4>
3257DepthwiseConvolution2d2x3x3Dilation3x3Test<armnn::DataType::QSymmS16, armnn::DataType::Signed32>(
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003258 armnn::IWorkloadFactory&,
3259 const armnn::IBackendInternal::IMemoryManagerSharedPtr&,
Keith Davisf500d6c2020-08-31 08:32:55 +01003260 const armnn::ITensorHandleFactory&,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003261 bool,
3262 armnn::DataLayout);
3263
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003264template LayerTestResult<armnn::ResolveType<armnn::DataType::BFloat16>, 4>
3265DepthwiseConvolution2dMult4Test<armnn::DataType::BFloat16, armnn::DataType::BFloat16>(
3266 armnn::IWorkloadFactory &workloadFactory,
3267 const armnn::IBackendInternal::IMemoryManagerSharedPtr &memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003268 const armnn::ITensorHandleFactory& tensorHandleFactory,
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003269 bool biasEnabled,
3270 const armnn::DataLayout layout);
3271
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003272template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 4>
3273DepthwiseConvolution2dMult4Test<armnn::DataType::Float32, armnn::DataType::Float32>(
3274 armnn::IWorkloadFactory &workloadFactory,
3275 const armnn::IBackendInternal::IMemoryManagerSharedPtr &memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003276 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003277 bool biasEnabled,
3278 const armnn::DataLayout layout);
3279
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003280template LayerTestResult<armnn::ResolveType<armnn::DataType::BFloat16>, 4>
3281DepthwiseConvolution2dMult2Test<armnn::DataType::BFloat16, armnn::DataType::BFloat16>(
3282 armnn::IWorkloadFactory &workloadFactory,
3283 const armnn::IBackendInternal::IMemoryManagerSharedPtr &memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003284 const armnn::ITensorHandleFactory& tensorHandleFactory,
Narumol Prangnawarat44179c32020-03-11 14:51:27 +00003285 bool biasEnabled,
3286 const armnn::DataLayout layout);
3287
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003288template LayerTestResult<armnn::ResolveType<armnn::DataType::Float32>, 4>
3289DepthwiseConvolution2dMult2Test<armnn::DataType::Float32, armnn::DataType::Float32>(
3290 armnn::IWorkloadFactory &workloadFactory,
3291 const armnn::IBackendInternal::IMemoryManagerSharedPtr &memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003292 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003293 bool biasEnabled,
3294 const armnn::DataLayout layout);
3295
3296//
3297// Implementation functions
3298//
3299
3300LayerTestResult<float, 4> SimpleConvolution2d3x5Test(
3301 armnn::IWorkloadFactory& workloadFactory,
3302 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003303 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003304 bool biasEnabled,
3305 const armnn::DataLayout layout)
3306{
3307 return SimpleConvolution2d3x5TestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003308 workloadFactory, memoryManager, tensorHandleFactory, 0.f, 0, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003309}
3310
3311LayerTestResult<uint8_t, 4> SimpleConvolution2d3x5Uint8Test(
3312 armnn::IWorkloadFactory& workloadFactory,
3313 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003314 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003315 bool biasEnabled,
3316 const armnn::DataLayout layout)
3317{
Derek Lambertif90c56d2020-01-10 17:14:08 +00003318 return SimpleConvolution2d3x5TestCommon<armnn::DataType::QAsymmU8, armnn::DataType::Signed32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003319 workloadFactory, memoryManager, tensorHandleFactory, 0.5f, 50, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003320}
3321
3322LayerTestResult<float, 4> SimpleConvolution2d3x3Test(
3323 armnn::IWorkloadFactory& workloadFactory,
3324 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003325 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003326 bool biasEnabled,
3327 const armnn::DataLayout layout)
3328{
3329 return SimpleConvolution2d3x3TestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003330 workloadFactory, memoryManager, tensorHandleFactory, 0.f, 0, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003331}
3332
3333LayerTestResult<float, 4> SimpleConvolution2d3x3NhwcTest(
3334 armnn::IWorkloadFactory& workloadFactory,
3335 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003336 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003337 bool biasEnabled)
3338{
3339 return SimpleConvolution2d3x3NhwcTestCommon<armnn::DataType::Float32>(
3340 workloadFactory,
3341 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003342 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003343 0.f,
3344 0,
3345 biasEnabled,
3346 armnn::DataLayout::NHWC);
3347}
3348
3349LayerTestResult<float, 4> SimpleConvolution2d3x3Stride2x2Test(
3350 armnn::IWorkloadFactory& workloadFactory,
3351 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003352 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003353 bool biasEnabled,
3354 const armnn::DataLayout layout)
3355{
3356 return SimpleConvolution2d3x3Stride2x2TestCommon<armnn::DataType::Float32>(
3357 workloadFactory,
3358 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003359 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003360 0.f,
3361 0,
3362 biasEnabled,
3363 layout);
3364}
3365
3366LayerTestResult<uint8_t, 4> SimpleConvolution2d3x3Uint8Test(
3367 armnn::IWorkloadFactory& workloadFactory,
3368 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003369 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003370 bool biasEnabled,
3371 const armnn::DataLayout layout)
3372{
Derek Lambertif90c56d2020-01-10 17:14:08 +00003373 return SimpleConvolution2d3x3TestCommon<armnn::DataType::QAsymmU8, armnn::DataType::Signed32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003374 workloadFactory, memoryManager, tensorHandleFactory, 0.5f, 50, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003375}
3376
3377LayerTestResult<int16_t, 4> SimpleConvolution2d3x5QSymm16Test(
3378 armnn::IWorkloadFactory& workloadFactory,
3379 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003380 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003381 bool biasEnabled,
3382 const armnn::DataLayout layout)
3383{
Derek Lambertif90c56d2020-01-10 17:14:08 +00003384 return SimpleConvolution2d3x5TestCommon<armnn::DataType::QSymmS16, armnn::DataType::Signed32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003385 workloadFactory, memoryManager, tensorHandleFactory, 0.5f, 50, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003386}
3387
3388LayerTestResult<int16_t, 4> SimpleConvolution2d3x3QSymm16Test(
3389 armnn::IWorkloadFactory& workloadFactory,
3390 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003391 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003392 bool biasEnabled,
3393 const armnn::DataLayout layout)
3394{
Derek Lambertif90c56d2020-01-10 17:14:08 +00003395 return SimpleConvolution2d3x3TestCommon<armnn::DataType::QSymmS16, armnn::DataType::Signed32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003396 workloadFactory, memoryManager, tensorHandleFactory, 0.5f, 50, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003397}
3398
3399LayerTestResult<float, 4> Convolution2dAsymmetricPaddingTest(
3400 armnn::IWorkloadFactory& workloadFactory,
3401 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003402 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003403 armnn::DataLayout layout)
3404{
3405 return SimpleConvolution2dAsymmetricPaddingTestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003406 workloadFactory, memoryManager, tensorHandleFactory, layout, 0.0f, 0);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003407}
3408
3409LayerTestResult<float, 4> Convolution2dAsymmetricPaddingLargerThanHalfKernelSizeTest(
3410 armnn::IWorkloadFactory& workloadFactory,
3411 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003412 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003413 armnn::DataLayout layout)
3414{
3415 return Convolution2dAsymmetricPaddingLargerThanHalfKernelSizeTestCommon
3416 <armnn::DataType::Float32, armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003417 workloadFactory, memoryManager, tensorHandleFactory, layout, 0.0f, 0);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003418}
3419
3420LayerTestResult<float, 4> Convolution1dTest(
3421 armnn::IWorkloadFactory& workloadFactory,
3422 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003423 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003424 bool biasEnabled)
3425{
3426 return Convolution1dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003427 workloadFactory, memoryManager, tensorHandleFactory, 0.0f, 0, biasEnabled);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003428}
3429
3430LayerTestResult<uint8_t, 4> Convolution1dUint8Test(
3431 armnn::IWorkloadFactory& workloadFactory,
3432 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003433 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003434 bool biasEnabled)
3435{
Derek Lambertif90c56d2020-01-10 17:14:08 +00003436 return Convolution1dTestImpl<armnn::DataType::QAsymmU8, armnn::DataType::Signed32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003437 workloadFactory, memoryManager, tensorHandleFactory, 0.1f, 128, biasEnabled);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003438}
3439
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +00003440LayerTestResult<uint8_t, 4> Convolution2dPerAxisQuantTest(
3441 armnn::IWorkloadFactory& workloadFactory,
3442 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003443 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +00003444 const armnn::DataLayout layout)
3445{
3446 using namespace armnn;
3447
Derek Lambertif90c56d2020-01-10 17:14:08 +00003448 const DataType inputType = DataType::QAsymmU8;
Derek Lambertid466a542020-01-22 15:37:29 +00003449 const DataType kernelType = DataType::QSymmS8;
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +00003450 const DataType biasType = DataType::Signed32;
3451
3452 TensorInfo inputInfo ({ 1, 3, 1, 2 }, inputType, 0.5f, 128);
3453 TensorInfo outputInfo({ 1, 3, 1, 3 }, inputType, 1.0f, 128);
3454
3455 const std::vector<float> quantScales{ 0.5f, 0.75f, 1.0f };
3456 constexpr unsigned int quantDimension = 0;
3457
3458 TensorInfo kernelInfo({ 3, 1, 1, 2 }, kernelType, quantScales, quantDimension);
3459
3460 const std::vector<float> biasQuantScales{ 0.25f, 0.375f, 0.5f };
3461 TensorInfo biasInfo({ 3 }, biasType, biasQuantScales, quantDimension);
3462
3463 std::vector<uint8_t> inputData =
3464 {
3465 138, 108, 138, 108, 138, 108
3466 };
3467
3468 std::vector<int8_t> kernelData =
3469 {
3470 1, 2, 1, 2, 1, 2
3471 };
3472
3473 std::vector<int32_t> biasData =
3474 {
3475 4, 4, 4
3476 };
3477
3478 std::vector<uint8_t> expectedOutputData =
3479 {
3480 121, 118, 115, 121, 118, 115, 121, 118, 115
3481 };
3482
3483 if (layout == DataLayout::NCHW)
3484 {
3485 PermuteTensorNhwcToNchw(inputInfo, inputData);
3486 PermuteTensorNhwcToNchw(kernelInfo, kernelData);
3487 PermuteTensorNhwcToNchw(outputInfo, expectedOutputData);
3488 }
3489
3490 Convolution2dDescriptor descriptor;
3491 descriptor.m_StrideX = 1;
3492 descriptor.m_StrideY = 1;
3493 descriptor.m_PadLeft = 0;
3494 descriptor.m_PadRight = 0;
3495 descriptor.m_PadTop = 0;
3496 descriptor.m_PadBottom = 0;
3497 descriptor.m_BiasEnabled = true;
3498 descriptor.m_DataLayout = layout;
3499
Keith Davisf500d6c2020-08-31 08:32:55 +01003500
3501 std::unique_ptr<ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputInfo);
3502 std::unique_ptr<ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputInfo);
3503
Aron Virginas-Tar5edc8812019-11-05 18:00:21 +00003504
3505 WorkloadInfo workloadInfo;
3506 ScopedCpuTensorHandle weightTensor(kernelInfo);
3507 ScopedCpuTensorHandle biasTensor(biasInfo);
3508
3509 AllocateAndCopyDataToITensorHandle(&weightTensor, kernelData.data());
3510 AllocateAndCopyDataToITensorHandle(&biasTensor, biasData.data());
3511
3512 Convolution2dQueueDescriptor queueDescriptor;
3513 queueDescriptor.m_Parameters = descriptor;
3514 queueDescriptor.m_Weight = &weightTensor;
3515 queueDescriptor.m_Bias = &biasTensor;
3516
3517 AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, inputHandle.get());
3518 AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, outputHandle.get());
3519
3520 std::unique_ptr<IWorkload> workload = workloadFactory.CreateConvolution2d(queueDescriptor, workloadInfo);
3521 inputHandle->Allocate();
3522 outputHandle->Allocate();
3523
3524 CopyDataToITensorHandle(inputHandle.get(), inputData.data());
3525
3526 ExecuteWorkload(*workload, memoryManager);
3527
3528 LayerTestResult<uint8_t, 4> ret(outputInfo);
3529 CopyDataFromITensorHandle(ret.output.origin(), outputHandle.get());
3530 ret.outputExpected = MakeTensor<uint8_t, 4>(outputInfo, expectedOutputData);
3531
3532 return ret;
3533}
3534
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003535LayerTestResult<float,4> CompareConvolution2dTest(
3536 armnn::IWorkloadFactory& workloadFactory,
3537 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003538 armnn::IWorkloadFactory& refWorkloadFactory,
3539 const armnn::ITensorHandleFactory& tensorHandleFactory,
3540 const armnn::ITensorHandleFactory& refTensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003541{
3542 return CompareConvolution2dTestImpl<armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003543 workloadFactory, memoryManager, refWorkloadFactory, tensorHandleFactory, refTensorHandleFactory);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003544}
3545
3546LayerTestResult<float, 4> DepthwiseConvolution2dTest(
3547 armnn::IWorkloadFactory& workloadFactory,
3548 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003549 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003550 bool biasEnabled,
3551 const armnn::DataLayout layout)
3552{
3553 return DepthwiseConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003554 workloadFactory, memoryManager, tensorHandleFactory, 0.0f, 0, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003555}
3556
3557LayerTestResult<float, 4> DepthwiseConvolution2dDepthNhwcTest(
3558 armnn::IWorkloadFactory& workloadFactory,
3559 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003560 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003561 bool biasEnabled)
3562{
3563 return DepthwiseConvolution2dNhwcTestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003564 workloadFactory, memoryManager, tensorHandleFactory, 0.0f, 0, biasEnabled);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003565}
3566
3567LayerTestResult<float, 4> DepthwiseConvolution2dDepthMul1Test(
3568 armnn::IWorkloadFactory& workloadFactory,
3569 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003570 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003571 bool biasEnabled,
3572 const armnn::DataLayout layout)
3573{
3574 return DepthwiseConvolution2dDepthMul1TestImpl<armnn::DataType::Float32, armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003575 workloadFactory, memoryManager, tensorHandleFactory, 0.0f, 0, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003576}
3577
3578LayerTestResult<float, 4> DepthwiseConvolution2dDepthMul64Test(
3579 armnn::IWorkloadFactory& workloadFactory,
Keith Davisf500d6c2020-08-31 08:32:55 +01003580 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3581 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003582{
3583 armnn::TensorInfo inputTensorInfo({ 1, 1, 2, 2 }, armnn::DataType::Float32);
3584 auto input = MakeTensor<float, 4>(inputTensorInfo, { 1.f, 2.f, 3.f, 4.f });
3585
3586 std::vector<float> kernelData;
3587 std::vector<float> singleDepthKernel{ 1.f, -1.f, -1.f, 1.f };
3588 for (unsigned int i = 0; i < 64; ++i)
3589 {
3590 kernelData.insert(kernelData.end(), singleDepthKernel.begin(), singleDepthKernel.end());
3591 }
3592 armnn::TensorInfo kernelTensorInfo({ 64, 1, 2, 2 }, armnn::DataType::Float32);
3593 auto kernel = MakeTensor<float, 4>(kernelTensorInfo, kernelData);
3594
3595 std::vector<float> expectedOutputData(64, 0.f);
3596 armnn::TensorInfo outputTensorInfo({ 1, 64, 1, 1 }, armnn::DataType::Float32);
3597 auto expectedOutput = MakeTensor<float, 4>(outputTensorInfo, expectedOutputData);
3598
3599 return DepthwiseConvolution2dTestImpl<armnn::DataType::Float32, armnn::DataType::Float32>(
3600 workloadFactory,
3601 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003602 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003603 input,
3604 kernel,
3605 boost::multi_array<float, 1>(),
3606 expectedOutput,
3607 0.f,
3608 0,
3609 armnn::DataLayout::NCHW);
3610}
3611
3612LayerTestResult<float, 4> DepthwiseConvolution2dAsymmetricTest(
3613 armnn::IWorkloadFactory& workloadFactory,
3614 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003615 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003616 bool biasEnabled,
3617 const armnn::DataLayout layout)
3618{
3619 return DepthwiseConvolution2dAsymmetricTestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003620 workloadFactory, memoryManager, tensorHandleFactory, 0.0f, 0, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003621}
3622
3623LayerTestResult<uint8_t, 4> DepthwiseConvolution2dUint8Test(
3624 armnn::IWorkloadFactory& workloadFactory,
3625 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003626 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003627 bool biasEnabled,
3628 const armnn::DataLayout layout)
3629{
Derek Lambertif90c56d2020-01-10 17:14:08 +00003630 return DepthwiseConvolution2dTestImpl<armnn::DataType::QAsymmU8, armnn::DataType::Signed32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003631 workloadFactory, memoryManager, tensorHandleFactory, 0.5f, 50, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003632}
3633
3634LayerTestResult<uint8_t, 4> DepthwiseConvolution2dDepthMul1Uint8Test(
3635 armnn::IWorkloadFactory& workloadFactory,
3636 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003637 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003638 bool biasEnabled,
3639 const armnn::DataLayout layout)
3640{
Derek Lambertif90c56d2020-01-10 17:14:08 +00003641 return DepthwiseConvolution2dDepthMul1TestImpl<armnn::DataType::QAsymmU8, armnn::DataType::Signed32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003642 workloadFactory, memoryManager, tensorHandleFactory, 0.5f, 50, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003643}
3644
3645LayerTestResult<float, 4> SimpleDepthwiseConvolution2d3x3Dilation3x3NhwcTest(
3646 armnn::IWorkloadFactory& workloadFactory,
Keith Davisf500d6c2020-08-31 08:32:55 +01003647 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3648 const armnn::ITensorHandleFactory& tensorHandleFactory)
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003649{
3650 return SimpleDepthwiseConvolution2d3x3Dilation3x3NhwcTestCommon<armnn::DataType::Float32, armnn::DataType::Float32>(
3651 workloadFactory,
3652 memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003653 tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003654 0.f,
3655 0,
3656 false);
3657}
3658
3659LayerTestResult<int16_t, 4> DepthwiseConvolution2dInt16Test(
3660 armnn::IWorkloadFactory& workloadFactory,
3661 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003662 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003663 bool biasEnabled,
3664 const armnn::DataLayout layout)
3665{
Derek Lambertif90c56d2020-01-10 17:14:08 +00003666 return DepthwiseConvolution2dTestImpl<armnn::DataType::QSymmS16, armnn::DataType::Signed32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003667 workloadFactory, memoryManager, tensorHandleFactory, 0.5f, 50, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003668}
3669
3670LayerTestResult<int16_t, 4> DepthwiseConvolution2dDepthMul1Int16Test(
3671 armnn::IWorkloadFactory& workloadFactory,
3672 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003673 const armnn::ITensorHandleFactory& tensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003674 bool biasEnabled,
3675 const armnn::DataLayout layout)
3676{
Derek Lambertif90c56d2020-01-10 17:14:08 +00003677 return DepthwiseConvolution2dDepthMul1TestImpl<armnn::DataType::QSymmS16, armnn::DataType::Signed32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003678 workloadFactory, memoryManager, tensorHandleFactory, 0.5f, 50, biasEnabled, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003679}
3680
Teresa Charlind8df0262019-11-11 12:28:15 +00003681LayerTestResult<uint8_t, 4> DepthwiseConvolution2dPerAxisQuantTest(
3682 armnn::IWorkloadFactory& workloadFactory,
3683 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
Keith Davisf500d6c2020-08-31 08:32:55 +01003684 const armnn::ITensorHandleFactory& tensorHandleFactory,
Teresa Charlind8df0262019-11-11 12:28:15 +00003685 const armnn::DataLayout layout)
3686{
3687 using namespace armnn;
3688
Derek Lambertif90c56d2020-01-10 17:14:08 +00003689 const DataType inputType = DataType::QAsymmU8;
Derek Lambertid466a542020-01-22 15:37:29 +00003690 const DataType kernelType = DataType::QSymmS8;
Teresa Charlind8df0262019-11-11 12:28:15 +00003691 const DataType biasType = DataType::Signed32;
3692
3693 TensorInfo inputInfo ({ 1, 3, 3, 2 }, inputType, 0.5f, 128); // N H W C
3694 TensorInfo outputInfo({ 1, 2, 2, 4 }, inputType, 1.0f, 128); // N H W C
3695
3696 const std::vector<float> quantScales{ 1.0f, 0.5f, 1.0f, 0.5f };
3697 const unsigned int quantDimension = 0;
3698 TensorInfo kernelInfo({ 2, 2, 2, 2 }, kernelType, quantScales, quantDimension); // M I H W
3699
3700 const std::vector<float> biasQuantScales{ 0.5f, 0.25f, 0.5f, 0.25f };
3701 constexpr unsigned int biasQuantDimension = 0;
3702 TensorInfo biasInfo({ 4 }, biasType, biasQuantScales, biasQuantDimension);
3703
3704 std::vector<uint8_t> inputData =
3705 {
3706 129, 130,
3707 129, 130,
3708 129, 130,
3709 129, 130,
3710 129, 130,
3711 129, 130,
3712 129, 130,
3713 129, 130,
3714 129, 130
3715 };
3716
3717 std::vector<int8_t> kernelData =
3718 {
3719 1, 1, 1, 1,
3720 1, 1, 1, 1,
3721 1, 1, 1, 1,
3722 1, 1, 1, 1
3723 };
3724
3725 std::vector<int32_t> biasData =
3726 {
3727 4, 4, 4, 4
3728 };
3729
3730 std::vector<uint8_t> expectedOutputData =
3731 {
3732 132, 130, 134, 131,
3733 132, 130, 134, 131,
3734 132, 130, 134, 131,
3735 132, 130, 134, 131
3736 };
3737
3738 if (layout == DataLayout::NCHW)
3739 {
3740 PermuteTensorNhwcToNchw(inputInfo, inputData);
3741 PermuteTensorNhwcToNchw(outputInfo, expectedOutputData);
3742 }
3743
3744 DepthwiseConvolution2dDescriptor descriptor;
3745 descriptor.m_StrideX = 1;
3746 descriptor.m_StrideY = 1;
3747 descriptor.m_PadLeft = 0;
3748 descriptor.m_PadRight = 0;
3749 descriptor.m_PadTop = 0;
3750 descriptor.m_PadBottom = 0;
3751 descriptor.m_DilationX = 1;
3752 descriptor.m_DilationY = 1;
3753 descriptor.m_BiasEnabled = true;
3754 descriptor.m_DataLayout = layout;
3755
Keith Davisf500d6c2020-08-31 08:32:55 +01003756 std::unique_ptr<ITensorHandle> inputHandle = tensorHandleFactory.CreateTensorHandle(inputInfo);
3757 std::unique_ptr<ITensorHandle> outputHandle = tensorHandleFactory.CreateTensorHandle(outputInfo);
Teresa Charlind8df0262019-11-11 12:28:15 +00003758
3759 WorkloadInfo workloadInfo;
3760 ScopedCpuTensorHandle weightTensor(kernelInfo);
3761 ScopedCpuTensorHandle biasTensor(biasInfo);
3762
3763 AllocateAndCopyDataToITensorHandle(&weightTensor, kernelData.data());
3764 AllocateAndCopyDataToITensorHandle(&biasTensor, biasData.data());
3765
3766 DepthwiseConvolution2dQueueDescriptor queueDescriptor;
3767 queueDescriptor.m_Parameters = descriptor;
3768 queueDescriptor.m_Weight = &weightTensor;
3769 queueDescriptor.m_Bias = &biasTensor;
3770
3771 AddInputToWorkload(queueDescriptor, workloadInfo, inputInfo, inputHandle.get());
3772 AddOutputToWorkload(queueDescriptor, workloadInfo, outputInfo, outputHandle.get());
3773
3774 std::unique_ptr<IWorkload> workload = workloadFactory.CreateDepthwiseConvolution2d(queueDescriptor, workloadInfo);
3775 inputHandle->Allocate();
3776 outputHandle->Allocate();
3777
3778 CopyDataToITensorHandle(inputHandle.get(), inputData.data());
3779
3780 ExecuteWorkload(*workload, memoryManager);
3781
3782 LayerTestResult<uint8_t, 4> ret(outputInfo);
3783
3784 CopyDataFromITensorHandle(ret.output.origin(), outputHandle.get());
3785 ret.outputExpected = MakeTensor<uint8_t, 4>(outputInfo, expectedOutputData);
3786
3787 return ret;
3788}
3789
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003790LayerTestResult<float, 4> CompareDepthwiseConvolution2dFloatTest(
3791 armnn::IWorkloadFactory& workloadFactory,
3792 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3793 armnn::IWorkloadFactory& refWorkloadFactory,
Keith Davisf500d6c2020-08-31 08:32:55 +01003794 const armnn::ITensorHandleFactory& tensorHandleFactory,
3795 const armnn::ITensorHandleFactory& refTensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003796 const armnn::DataLayout layout)
3797{
3798 return CompareDepthwiseConvolution2dTestImpl<armnn::DataType::Float32>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003799 workloadFactory, memoryManager, refWorkloadFactory, tensorHandleFactory, refTensorHandleFactory, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003800}
3801
3802LayerTestResult<uint8_t, 4> CompareDepthwiseConvolution2dUint8Test(
3803 armnn::IWorkloadFactory& workloadFactory,
3804 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
3805 armnn::IWorkloadFactory& refWorkloadFactory,
Keith Davisf500d6c2020-08-31 08:32:55 +01003806 const armnn::ITensorHandleFactory& tensorHandleFactory,
3807 const armnn::ITensorHandleFactory& refTensorHandleFactory,
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003808 const armnn::DataLayout layout)
3809{
Derek Lambertif90c56d2020-01-10 17:14:08 +00003810 return CompareDepthwiseConvolution2dTestImpl<armnn::DataType::QAsymmU8>(
Keith Davisf500d6c2020-08-31 08:32:55 +01003811 workloadFactory, memoryManager, refWorkloadFactory, tensorHandleFactory, refTensorHandleFactory, layout);
Aron Virginas-Tar00d306e2019-08-28 18:08:46 +01003812}