blob: 83170c413c5afee2ff0d1d803c2c639fd3e4e7c7 [file] [log] [blame]
Pablo Tellof5f34bb2017-08-22 13:34:13 +01001/*
Viet-Hoa Do019a7d92023-06-27 16:33:57 +01002 * Copyright (c) 2017-2023 Arm Limited.
Pablo Tellof5f34bb2017-08-22 13:34:13 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "arm_compute/core/TensorShape.h"
25#include "arm_compute/core/Types.h"
Michele Di Giorgioed5a4922018-09-13 16:22:01 +010026#include "arm_compute/core/utils/misc/ShapeCalculator.h"
Pablo Tellof5f34bb2017-08-22 13:34:13 +010027#include "tests/AssetsLibrary.h"
28#include "tests/Globals.h"
29#include "tests/IAccessor.h"
30#include "tests/framework/Asserts.h"
31#include "tests/framework/Fixture.h"
Pablo Tellof5f34bb2017-08-22 13:34:13 +010032#include "tests/validation/Helpers.h"
Georgios Pinitas5a7e7762017-12-01 16:27:29 +000033#include "tests/validation/reference/DeconvolutionLayer.h"
Pablo Tellof5f34bb2017-08-22 13:34:13 +010034
35#include <random>
36
37namespace arm_compute
38{
39namespace test
40{
41namespace validation
42{
Michele Di Giorgioed5a4922018-09-13 16:22:01 +010043using namespace arm_compute::misc::shape_calculator;
44
Freddie Liardet9d061b02021-04-06 15:59:28 +010045template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW>
Pablo Tellof5f34bb2017-08-22 13:34:13 +010046class DeconvolutionLayerFixtureBase : public framework::Fixture
47{
48public:
Luca Foschianifedefc32020-02-17 17:02:49 +000049 using TBias = typename std::conditional < std::is_same<typename std::decay<T>::type, uint8_t>::value || std::is_same<typename std::decay<T>::type, int8_t>::value, int32_t, T >::type;
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +010050
51public:
Pablo Tellof5f34bb2017-08-22 13:34:13 +010052 void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info,
Freddie Liardet9d061b02021-04-06 15:59:28 +010053 DataType data_type, DataType weights_data_type, DataLayout data_layout,
54 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, QuantizationInfo weights_quantization_info, bool add_bias)
Pablo Tellof5f34bb2017-08-22 13:34:13 +010055 {
Freddie Liardet9d061b02021-04-06 15:59:28 +010056 _data_type = data_type;
57 _weights_data_type = weights_data_type;
58 _bias_data_type = is_data_type_quantized_asymmetric(data_type) ? DataType::S32 : data_type;
59 _data_layout = data_layout;
60 _input_quantization_info = input_quantization_info;
61 _output_quantization_info = output_quantization_info;
62 _weights_quantization_info = weights_quantization_info;
Pablo Tellof5f34bb2017-08-22 13:34:13 +010063
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +010064 _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, add_bias);
65 _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, add_bias);
Pablo Tellof5f34bb2017-08-22 13:34:13 +010066 }
67
68protected:
69 template <typename U>
70 void fill(U &&tensor, int i)
71 {
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +010072 switch(tensor.data_type())
Pablo Tellof5f34bb2017-08-22 13:34:13 +010073 {
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +010074 case DataType::QASYMM8:
75 {
Michele Di Giorgioed5a4922018-09-13 16:22:01 +010076 std::pair<int, int> bounds = get_quantized_bounds(tensor.quantization_info(), -1.0f, 1.0f);
Pablo Tello29cab362022-03-10 17:05:34 +000077 std::uniform_int_distribution<uint32_t> distribution(bounds.first, bounds.second);
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +010078 library->fill(tensor, distribution, i);
79 break;
80 }
Sheri Zhanga14817a2020-02-26 10:30:15 +000081 case DataType::QASYMM8_SIGNED:
82 {
83 std::pair<int, int> bounds = get_quantized_qasymm8_signed_bounds(tensor.quantization_info(), -1.0f, 1.0f);
Pablo Tello29cab362022-03-10 17:05:34 +000084 std::uniform_int_distribution<int32_t> distribution(bounds.first, bounds.second);
Sheri Zhanga14817a2020-02-26 10:30:15 +000085 library->fill(tensor, distribution, i);
86 break;
87 }
Freddie Liardet9d061b02021-04-06 15:59:28 +010088 case DataType::QSYMM8_PER_CHANNEL:
89 {
90 int min_bound = 128;
91 int max_bound = -127;
92 for(size_t i = 0; i < _input_quantization_info.scale().size(); i++)
93 {
94 std::pair<int, int> bounds = get_symm_quantized_per_channel_bounds(tensor.quantization_info(), -1.0f, 1.0f);
95 if(bounds.first < min_bound)
96 {
97 min_bound = bounds.first;
98 }
99 if(bounds.second > max_bound)
100 {
101 max_bound = bounds.second;
102 }
103 }
Pablo Tello29cab362022-03-10 17:05:34 +0000104 std::uniform_int_distribution<int32_t> distribution(min_bound, max_bound);
Freddie Liardet9d061b02021-04-06 15:59:28 +0100105 library->fill(tensor, distribution, i);
106 break;
107 }
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +0100108 case DataType::S32:
109 {
110 std::uniform_int_distribution<int32_t> distribution(-100, 100);
111 library->fill(tensor, distribution, i);
112 break;
113 }
114 case DataType::F16:
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000115 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000116 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000117 library->fill(tensor, distribution, i);
118 break;
119 }
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +0100120 case DataType::F32:
121 {
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000122 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +0100123 library->fill(tensor, distribution, i);
124 break;
125 }
126 default:
127 library->fill_tensor_uniform(tensor, i);
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100128 }
129 }
Michalis Spyrou780db4e2017-11-23 09:49:51 +0000130
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100131 template <typename U>
132 void fill_zeros(U &&tensor)
133 {
134 switch(tensor.data_type())
135 {
136 case DataType::S32:
137 {
Freddie Liardete92b0452021-04-22 14:55:17 +0100138 library->fill_tensor_value(tensor, 0);
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100139 break;
140 }
141 case DataType::F16:
142 library->fill_tensor_value(tensor, static_cast<half>(0.0f));
143 break;
144 case DataType::F32:
145 library->fill_tensor_value(tensor, static_cast<float>(0.0f));
146 break;
147 default:
148 ARM_COMPUTE_ERROR("Not supported");
149 }
150 }
151
Michele Di Giorgioed5a4922018-09-13 16:22:01 +0100152 TensorType compute_target(TensorShape input_shape, TensorShape weights_shape, const TensorShape bias_shape, TensorShape output_shape,
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100153 const PadStrideInfo &info, bool add_bias)
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100154 {
Michele Di Giorgioed5a4922018-09-13 16:22:01 +0100155 if(_data_layout == DataLayout::NHWC)
156 {
157 permute(input_shape, PermutationVector(2U, 0U, 1U));
158 permute(weights_shape, PermutationVector(2U, 0U, 1U));
159 permute(output_shape, PermutationVector(2U, 0U, 1U));
160 }
161
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100162 // Create tensors
Manuel Bottini279814b2019-10-25 10:28:28 +0100163 TensorType src = create_tensor<TensorType>(input_shape, _data_type, 1, _input_quantization_info, _data_layout);
Freddie Liardet9d061b02021-04-06 15:59:28 +0100164 TensorType weights = create_tensor<TensorType>(weights_shape, _weights_data_type, 1, _weights_quantization_info, _data_layout);
Manuel Bottini279814b2019-10-25 10:28:28 +0100165 TensorType bias = create_tensor<TensorType>(bias_shape, _bias_data_type, 1, _input_quantization_info, _data_layout);
166 TensorType dst = create_tensor<TensorType>(output_shape, _data_type, 1, _output_quantization_info, _data_layout);
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100167
168 // Create and configure function
169 FunctionType conv;
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100170 conv.configure(&src, &weights, add_bias ? &bias : nullptr, &dst, info);
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100171
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100172 ARM_COMPUTE_ASSERT(src.info()->is_resizable());
173 ARM_COMPUTE_ASSERT(weights.info()->is_resizable());
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100174 if(add_bias)
175 {
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100176 ARM_COMPUTE_ASSERT(bias.info()->is_resizable());
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100177 }
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100178 ARM_COMPUTE_ASSERT(dst.info()->is_resizable());
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100179
180 // Allocate tensors
181 src.allocator()->allocate();
182 weights.allocator()->allocate();
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100183 if(add_bias)
184 {
185 bias.allocator()->allocate();
186 }
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100187 dst.allocator()->allocate();
188
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100189 ARM_COMPUTE_ASSERT(!src.info()->is_resizable());
190 ARM_COMPUTE_ASSERT(!weights.info()->is_resizable());
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100191 if(add_bias)
192 {
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100193 ARM_COMPUTE_ASSERT(!bias.info()->is_resizable());
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100194 }
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100195 ARM_COMPUTE_ASSERT(!dst.info()->is_resizable());
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100196
197 // Fill tensors
198 fill(AccessorType(src), 0);
199 fill(AccessorType(weights), 1);
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100200 if(add_bias)
201 {
202 fill(AccessorType(bias), 2);
203 }
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100204
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +0100205 // Compute DeconvolutionLayer function
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100206 conv.run();
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100207 return dst;
208 }
209
210 SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape,
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100211 const PadStrideInfo &info, bool add_bias)
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100212 {
213 // Create reference
Manuel Bottini279814b2019-10-25 10:28:28 +0100214 SimpleTensor<T> src{ input_shape, _data_type, 1, _input_quantization_info };
Freddie Liardet9d061b02021-04-06 15:59:28 +0100215 SimpleTensor<TW> weights{ weights_shape, _weights_data_type, 1, _weights_quantization_info };
Manuel Bottini279814b2019-10-25 10:28:28 +0100216 SimpleTensor<TBias> bias{ bias_shape, _bias_data_type, 1, _input_quantization_info };
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100217
218 // Fill reference
219 fill(src, 0);
220 fill(weights, 1);
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100221
222 if(add_bias)
223 {
224 fill(bias, 2);
225 }
226 else
227 {
228 fill_zeros(bias);
229 }
Freddie Liardet9d061b02021-04-06 15:59:28 +0100230 return reference::deconvolution_layer<T, TW>(src, weights, bias, output_shape, info, _output_quantization_info);
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100231 }
232
Michele Di Giorgioed5a4922018-09-13 16:22:01 +0100233 TensorType _target{};
234 SimpleTensor<T> _reference{};
235 DataType _data_type{};
Freddie Liardet9d061b02021-04-06 15:59:28 +0100236 DataType _weights_data_type{};
Michele Di Giorgioed5a4922018-09-13 16:22:01 +0100237 DataType _bias_data_type{};
238 DataLayout _data_layout{};
Manuel Bottini279814b2019-10-25 10:28:28 +0100239 QuantizationInfo _input_quantization_info{};
240 QuantizationInfo _output_quantization_info{};
Freddie Liardet9d061b02021-04-06 15:59:28 +0100241 QuantizationInfo _weights_quantization_info{};
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100242};
243
244template <typename TensorType, typename AccessorType, typename FunctionType, typename T, unsigned int kernel_size_x, unsigned int kernel_size_y>
Freddie Liardet9d061b02021-04-06 15:59:28 +0100245class DeconvolutionValidationFixture : public DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T, T>
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100246{
247public:
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100248 void setup(TensorShape input_shape, unsigned int sx, unsigned int sy, unsigned int padx, unsigned int pady,
Manuel Bottini9f0d5ec2019-08-19 13:31:38 +0100249 unsigned int num_kernels, DataType data_type, DataLayout data_layout, bool add_bias)
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100250 {
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100251 const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
252 const TensorShape bias_shape(num_kernels);
253 const PadStrideInfo info(sx, sy, padx, pady, DimensionRoundingType::CEIL);
Matthew Jacksonb9070a42019-08-22 16:13:27 +0100254 auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, info);
255 TensorInfo input_info(input_shape, 1, data_type);
256 TensorInfo weights_info(weights_shape, 1, data_type);
257 TensorShape output_shape = compute_deconvolution_output_shape(out_dim, input_info, weights_info);
Freddie Liardet9d061b02021-04-06 15:59:28 +0100258 DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, data_type, data_type, data_layout, QuantizationInfo(),
259 QuantizationInfo(), QuantizationInfo(), add_bias);
Matthew Jacksonb9070a42019-08-22 16:13:27 +0100260 }
261};
262
263template <typename TensorType, typename AccessorType, typename FunctionType, typename T, unsigned int kernel_size_x, unsigned int kernel_size_y>
Freddie Liardet9d061b02021-04-06 15:59:28 +0100264class DeconvolutionValidationAsymmFixture : public DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T, T>
Matthew Jacksonb9070a42019-08-22 16:13:27 +0100265{
266public:
Matthew Jacksonb9070a42019-08-22 16:13:27 +0100267 void setup(TensorShape input_shape, unsigned int sx, unsigned int sy, unsigned int pad_left, unsigned int pad_right, unsigned int pad_top,
268 unsigned int pad_bottom, unsigned int num_kernels, DataType data_type, DataLayout data_layout, bool add_bias)
269 {
Matthew Jacksonb9070a42019-08-22 16:13:27 +0100270 const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
271 const TensorShape bias_shape(num_kernels);
272 const PadStrideInfo info(sx, sy, pad_left, pad_right, pad_top, pad_bottom, DimensionRoundingType::CEIL);
273 auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, info);
giuros01a69a88b2019-01-31 16:29:19 +0000274 TensorInfo input_info(input_shape, 1, data_type);
275 TensorInfo weights_info(weights_shape, 1, data_type);
276 TensorShape output_shape = compute_deconvolution_output_shape(out_dim, input_info, weights_info);
Freddie Liardet9d061b02021-04-06 15:59:28 +0100277 DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, data_type, data_type, data_layout, QuantizationInfo(),
278 QuantizationInfo(), QuantizationInfo(), add_bias);
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +0100279 }
280};
281
282template <typename TensorType, typename AccessorType, typename FunctionType, typename T, unsigned int kernel_size_x, unsigned int kernel_size_y>
Freddie Liardet9d061b02021-04-06 15:59:28 +0100283class DeconvolutionValidationQuantizedFixture : public DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T, T>
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +0100284{
285public:
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +0100286 void setup(TensorShape input_shape, unsigned int sx, unsigned int sy, unsigned int padx, unsigned int pady,
Manuel Bottini279814b2019-10-25 10:28:28 +0100287 unsigned int num_kernels, DataType data_type, DataLayout data_layout, QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, bool add_bias)
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +0100288 {
Michele Di Giorgio9fef38a2018-07-06 18:06:58 +0100289 const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
290 const TensorShape bias_shape(num_kernels);
291 const PadStrideInfo info(sx, sy, padx, pady, DimensionRoundingType::CEIL);
Matthew Jacksonb9070a42019-08-22 16:13:27 +0100292 auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, info);
Manuel Bottini279814b2019-10-25 10:28:28 +0100293 TensorInfo input_info(input_shape, 1, data_type, input_quantization_info);
294 TensorInfo weights_info(weights_shape, 1, data_type, input_quantization_info);
giuros01a69a88b2019-01-31 16:29:19 +0000295 TensorShape output_shape = compute_deconvolution_output_shape(out_dim, input_info, weights_info);
Freddie Liardet9d061b02021-04-06 15:59:28 +0100296 DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, data_type, data_type, data_layout,
297 input_quantization_info,
298 output_quantization_info, input_quantization_info, add_bias);
299 }
300};
301
302template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW, unsigned int kernel_size_x, unsigned int kernel_size_y>
303class DeconvolutionValidationQuantizedPerChannelFixture : public DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T, TW>
304{
305public:
Freddie Liardet9d061b02021-04-06 15:59:28 +0100306 void setup(TensorShape input_shape, unsigned int sx, unsigned int sy, unsigned int padx, unsigned int pady,
307 unsigned int num_kernels, DataType data_type, DataLayout data_layout, QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, bool add_bias,
308 DataType weights_data_type)
309 {
Freddie Liardet9d061b02021-04-06 15:59:28 +0100310 const TensorShape weights_shape(kernel_size_x, kernel_size_y, input_shape.z(), num_kernels);
311 const TensorShape bias_shape(num_kernels);
312 const PadStrideInfo info(sx, sy, padx, pady, DimensionRoundingType::CEIL);
313 auto out_dim = deconvolution_output_dimensions(input_shape.x(), input_shape.y(), kernel_size_x, kernel_size_y, info);
314 TensorInfo input_info(input_shape, 1, data_type, input_quantization_info);
315 TensorInfo weights_info(weights_shape, 1, weights_data_type, input_quantization_info);
316 TensorShape output_shape = compute_deconvolution_output_shape(out_dim, input_info, weights_info);
317
318 std::vector<float> weights_scales{};
319 std::mt19937 gen(library->seed());
320 std::uniform_real_distribution<float> dis(0.01f, 1.f);
321 for(size_t i = 0; i < output_shape[2]; ++i)
322 {
323 weights_scales.push_back(dis(gen));
324 }
325 DeconvolutionLayerFixtureBase<TensorType, AccessorType, FunctionType, T, TW>::setup(input_shape, weights_shape, bias_shape, output_shape, info, data_type, weights_data_type, data_layout,
326 input_quantization_info,
327 output_quantization_info, QuantizationInfo(weights_scales), add_bias);
Pablo Tellof5f34bb2017-08-22 13:34:13 +0100328 }
329};
330
331} // namespace validation
332} // namespace test
333} // namespace arm_compute