blob: 19ec6b25601f692a99b01c0f3bd0eacf464e74f5 [file] [log] [blame]
Giorgio Arena93a690e2017-08-01 16:09:33 +01001/*
Giorgio Arenab309fc22021-01-05 09:46:16 +00002 * Copyright (c) 2017-2021 Arm Limited.
Giorgio Arena93a690e2017-08-01 16:09:33 +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#ifndef ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE
25#define ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE
26
27#include "arm_compute/core/TensorShape.h"
28#include "arm_compute/core/Types.h"
Giorgio Arena76572242018-04-04 17:44:26 +010029#include "arm_compute/core/utils/misc/ShapeCalculator.h"
Giorgio Arena93a690e2017-08-01 16:09:33 +010030#include "tests/AssetsLibrary.h"
31#include "tests/Globals.h"
32#include "tests/IAccessor.h"
Moritz Pflanzera09de0c2017-09-01 20:41:12 +010033#include "tests/framework/Asserts.h"
34#include "tests/framework/Fixture.h"
Moritz Pflanzera09de0c2017-09-01 20:41:12 +010035#include "tests/validation/Helpers.h"
Manuel Bottinia788c2f2019-04-08 13:18:00 +010036#include "tests/validation/reference/ActivationLayer.h"
Georgios Pinitas5a7e7762017-12-01 16:27:29 +000037#include "tests/validation/reference/DepthwiseConvolutionLayer.h"
Giorgio Arena93a690e2017-08-01 16:09:33 +010038
Georgios Pinitasf72f9362018-01-12 16:29:45 +000039#include "utils/Utils.h"
40
Giorgio Arena93a690e2017-08-01 16:09:33 +010041#include <random>
42
43namespace arm_compute
44{
45namespace test
46{
47namespace validation
48{
Giorgio Arena76572242018-04-04 17:44:26 +010049using namespace arm_compute::misc::shape_calculator;
50
Michele Di Giorgio633d30b2019-10-08 17:17:18 +010051template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW>
Giorgio Arena04a8f8c2017-11-23 11:45:24 +000052class DepthwiseConvolutionLayerValidationGenericFixture : public framework::Fixture
Giorgio Arena93a690e2017-08-01 16:09:33 +010053{
54public:
Michele Di Giorgio633d30b2019-10-08 17:17:18 +010055 using TBias = typename std::conditional < std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value, int32_t, T >::type;
Dmitry Savenkod7295b72017-11-20 22:00:08 +070056
57public:
Giorgio Arena93a690e2017-08-01 16:09:33 +010058 template <typename...>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +010059 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation,
60 unsigned int depth_multiplier, DataType input_data_type, DataType weights_data_type,
61 QuantizationInfo input_quantization_info, QuantizationInfo weights_quantization_info, QuantizationInfo output_quantization_info,
Manuel Bottinica62c6f2021-03-23 11:50:34 +000062 DataLayout data_layout, ActivationLayerInfo act_info, bool mixed_layout = false)
Giorgio Arena93a690e2017-08-01 16:09:33 +010063 {
Manuel Bottinica62c6f2021-03-23 11:50:34 +000064 _mixed_layout = mixed_layout;
Giorgio Arena68e29da2021-02-08 16:31:10 +000065 _input_shape = in_shape;
66 _input_data_type = input_data_type;
67 _weights_data_type = weights_data_type;
68 _input_quantization_info = input_quantization_info;
69 _weights_quantization_info = weights_quantization_info;
70 _output_quantization_info = output_quantization_info;
71 _data_layout = data_layout;
72 _pad_stride_info = pad_stride_info;
73 _act_info = act_info;
74 _depth_multiplier = depth_multiplier;
75 _dilation = dilation;
Giorgio Arena76572242018-04-04 17:44:26 +010076
Giorgio Arena68e29da2021-02-08 16:31:10 +000077 _bias_data_type = is_data_type_quantized(_input_data_type) ? DataType::S32 : _input_data_type;
Giorgio Arena76572242018-04-04 17:44:26 +010078
Giorgio Arena68e29da2021-02-08 16:31:10 +000079 _weights_shape = TensorShape(kernel_size.width, kernel_size.height);
Giorgio Arena76572242018-04-04 17:44:26 +010080
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010081 const TensorInfo in_info(_input_shape, 1, _input_data_type);
82 const TensorInfo we_info(_weights_shape, 1, _weights_data_type);
83 const ConvolutionInfo info{ _pad_stride_info, _depth_multiplier, _act_info, _dilation };
84 _output_shape = compute_depthwise_convolution_shape(in_info, we_info, info);
Dmitry Savenkod7295b72017-11-20 22:00:08 +070085
Giorgio Arena68e29da2021-02-08 16:31:10 +000086 _weights_shape.set(2, _output_shape.z());
87 _biases_shape = TensorShape(_weights_shape[2]);
88 }
89
90 void configure_target()
91 {
92 TensorShape input_shape = _input_shape;
93 TensorShape weights_shape = _weights_shape;
94 TensorShape output_shape = _output_shape;
95
96 if(_data_layout == DataLayout::NHWC)
97 {
98 permute(input_shape, PermutationVector(2U, 0U, 1U));
99 permute(weights_shape, PermutationVector(2U, 0U, 1U));
100 permute(output_shape, PermutationVector(2U, 0U, 1U));
101 }
102
103 // Create tensors
104 _src = create_tensor<TensorType>(input_shape, _input_data_type, 1, _input_quantization_info, _data_layout);
105 _weights = create_tensor<TensorType>(weights_shape, _weights_data_type, 1, _weights_quantization_info, _data_layout);
106 _biases = create_tensor<TensorType>(_biases_shape, _bias_data_type, 1, _input_quantization_info, _data_layout);
107 _target = create_tensor<TensorType>(output_shape, _input_data_type, 1, _output_quantization_info, _data_layout);
108
109 // Create Depthwise Convolution configure function
110 _dwc.configure(&_src, &_weights, &_biases, &_target, _pad_stride_info, _depth_multiplier, _act_info, _dilation);
111
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100112 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
113 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
114 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
115 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000116 }
117
118 void allocate_and_run_target()
119 {
Michele Di Giorgiod02d5ed2021-01-22 09:47:04 +0000120 add_padding_x({ &_src, &_weights, &_biases, &_target }, _data_layout);
Giorgio Arena63825e82021-03-25 14:54:50 +0000121
Giorgio Arena68e29da2021-02-08 16:31:10 +0000122 // Allocate tensors
123 _src.allocator()->allocate();
124 _weights.allocator()->allocate();
125 _biases.allocator()->allocate();
126 _target.allocator()->allocate();
127
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100128 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
129 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
130 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
131 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000132
133 // Fill tensors
134 fill(AccessorType(_src), 0);
135 fill(AccessorType(_weights), 1);
136 fill(AccessorType(_biases), 2);
Giorgio Arena63825e82021-03-25 14:54:50 +0000137
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000138 if(_mixed_layout)
139 {
140 mix_layout(_dwc, _src, _target);
141 }
142 else
143 {
144 // Compute function
145 _dwc.run();
146 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000147 }
148
149 void compute_reference()
150 {
151 SimpleTensor<T> src{ _input_shape, _input_data_type, 1, _input_quantization_info };
152 SimpleTensor<TW> weights{ _weights_shape, _weights_data_type, 1, _weights_quantization_info };
153 SimpleTensor<TBias> biases{ _biases_shape, _bias_data_type, 1, _input_quantization_info };
154
155 fill(src, 0);
156 fill(weights, 1);
157 fill(biases, 2);
158
159 SimpleTensor<T> depth_out = reference::depthwise_convolution(src, weights, biases, _output_shape, _pad_stride_info, _depth_multiplier, _dilation, _output_quantization_info);
160 _reference = (_act_info.enabled()) ? reference::activation_layer<T>(depth_out, _act_info) : depth_out;
Giorgio Arena93a690e2017-08-01 16:09:33 +0100161 }
162
163protected:
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000164 void mix_layout(FunctionType &layer, TensorType &src, TensorType &dst)
165 {
166 // Test Multi DataLayout graph cases, when the data layout changes after configure
167 src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
168 dst.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
169
170 // Compute Convolution function
171 layer.run();
172
173 // Reinstating original data layout for the test suite to properly check the values
174 src.info()->set_data_layout(_data_layout);
175 dst.info()->set_data_layout(_data_layout);
176 }
177
Giorgio Arena93a690e2017-08-01 16:09:33 +0100178 template <typename U>
179 void fill(U &&tensor, int i)
180 {
181 switch(tensor.data_type())
182 {
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700183 case DataType::QASYMM8:
184 {
185 std::uniform_int_distribution<uint8_t> distribution(0, 10);
186 library->fill(tensor, distribution, i);
187 break;
188 }
Michele Di Giorgio4cd4cde2020-01-06 14:07:44 +0000189 case DataType::QASYMM8_SIGNED:
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100190 case DataType::QSYMM8_PER_CHANNEL:
191 {
192 std::uniform_int_distribution<int8_t> distribution(-10, 10);
193 library->fill(tensor, distribution, i);
194 break;
195 }
Frank Lei8cdfdb82018-01-02 16:49:33 +0800196 case DataType::F16:
Giorgio Arena93a690e2017-08-01 16:09:33 +0100197 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000198 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000199 library->fill(tensor, distribution, i);
200 break;
201 }
202 case DataType::F32:
203 {
204 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Giorgio Arena93a690e2017-08-01 16:09:33 +0100205 library->fill(tensor, distribution, i);
206 break;
207 }
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700208 case DataType::S32:
209 {
Georgios Pinitasf72f9362018-01-12 16:29:45 +0000210 std::uniform_int_distribution<int32_t> distribution(-100, 100);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700211 library->fill(tensor, distribution, i);
212 break;
213 }
Giorgio Arena93a690e2017-08-01 16:09:33 +0100214 default:
215 library->fill_tensor_uniform(tensor, i);
216 }
217 }
218
Georgios Pinitasddec4d62019-07-10 19:23:02 +0100219 TensorType _target{};
220 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000221
222 TensorType _src{};
223 TensorType _weights{};
224 TensorType _biases{};
225 FunctionType _dwc{};
226
227 TensorShape _input_shape{};
228 TensorShape _weights_shape{};
229 TensorShape _biases_shape{};
230 TensorShape _output_shape{};
231 DataType _input_data_type{};
232 DataType _weights_data_type{};
233 DataType _bias_data_type{};
234 QuantizationInfo _input_quantization_info{};
235 QuantizationInfo _weights_quantization_info{};
236 QuantizationInfo _output_quantization_info{};
237 DataLayout _data_layout{};
238 PadStrideInfo _pad_stride_info{};
239 ActivationLayerInfo _act_info{};
240 unsigned int _depth_multiplier{};
241 Size2D _dilation{};
Giorgio Arena63825e82021-03-25 14:54:50 +0000242 bool _mixed_layout{ false };
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700243};
244
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000245template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100246class DepthwiseConvolutionLayerValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700247{
248public:
249 template <typename...>
Manuel Bottinia788c2f2019-04-08 13:18:00 +0100250 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type, DataLayout data_layout,
251 ActivationLayerInfo act_info)
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700252 {
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100253 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
254 data_type, data_type, QuantizationInfo(), QuantizationInfo(), QuantizationInfo(),
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000255 data_layout, act_info, mixed_layout);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700256 }
257};
258
259template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100260class DepthwiseConvolutionLayerNativeValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Giorgio Arena44f55722019-07-12 14:49:49 +0100261{
262public:
263 template <typename...>
264 void setup(size_t width, size_t height, size_t channel, size_t batch, Size2D kernel_size, size_t depth_multiplier, Size2D dilation, Size2D stride, bool padding_valid, DataType data_type,
265 DataLayout data_layout)
266 {
Giorgio Arena68e29da2021-02-08 16:31:10 +0000267 _dilation = dilation;
268 _depth_multiplier = depth_multiplier;
269 _data_type = data_type;
270 _data_layout = data_layout;
Giorgio Arena44f55722019-07-12 14:49:49 +0100271
Giorgio Arena68e29da2021-02-08 16:31:10 +0000272 _input_shape = TensorShape(width, height, channel, batch);
273 _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
274 _biases_shape = TensorShape(_weights_shape.z());
275
Giorgio Arena44f55722019-07-12 14:49:49 +0100276 if(padding_valid)
277 {
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000278 _conv_info = PadStrideInfo();
Giorgio Arena44f55722019-07-12 14:49:49 +0100279 }
280 else
281 {
Giorgio Arena68e29da2021-02-08 16:31:10 +0000282 _conv_info = calculate_same_pad(_input_shape, _weights_shape, PadStrideInfo(stride.width, stride.height), DataLayout::NCHW, _dilation);
283 }
284 }
285
286 void configure_target()
287 {
288 TensorShape input_shape = _input_shape;
289 TensorShape weights_shape = _weights_shape;
290
291 if(_data_layout == DataLayout::NHWC)
292 {
293 permute(input_shape, PermutationVector(2U, 0U, 1U));
294 permute(weights_shape, PermutationVector(2U, 0U, 1U));
Giorgio Arena44f55722019-07-12 14:49:49 +0100295 }
296
Giorgio Arena68e29da2021-02-08 16:31:10 +0000297 // Create tensors
298 _src = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
299 _weights = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
300 _biases = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
301 _target = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
302
303 // Create Depthwise Convolution configure function
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100304 const ConvolutionInfo info
305 {
306 _conv_info, _depth_multiplier, ActivationLayerInfo(), _dilation
307 };
308 _dwc.configure(_src.info(), _weights.info(), _biases.info(), _target.info(), info);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000309
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100310 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
311 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
312 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
313 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000314 }
315
316 void allocate_and_run_target()
317 {
Giorgio Arena63825e82021-03-25 14:54:50 +0000318 add_padding_x({ &_src, &_weights, &_biases, &_target }, _data_layout);
319
Giorgio Arena68e29da2021-02-08 16:31:10 +0000320 // Allocate tensors
321 _src.allocator()->allocate();
322 _weights.allocator()->allocate();
323 _biases.allocator()->allocate();
324 _target.allocator()->allocate();
325
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100326 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
327 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
328 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
329 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000330
331 // Fill tensors
332 fill(AccessorType(_src), 0);
333 fill(AccessorType(_weights), 1);
334 fill(AccessorType(_biases), 2);
335
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100336 arm_compute::ITensorPack pack;
337 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_0, &_src);
338 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_1, &_weights);
339 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_2, &_biases);
340 pack.add_tensor(arm_compute::TensorType::ACL_DST, &_target);
341
Giorgio Arena68e29da2021-02-08 16:31:10 +0000342 // Compute function
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100343 _dwc.run(pack);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000344 }
345
346 void compute_reference()
347 {
348 SimpleTensor<T> src{ _input_shape, _data_type };
349 SimpleTensor<T> weights{ _weights_shape, _data_type };
350 SimpleTensor<T> biases{ _biases_shape, _data_type };
351
352 fill(src, 0);
353 fill(weights, 1);
354 fill(biases, 2);
355
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100356 const ConvolutionInfo info{ _conv_info, _depth_multiplier, ActivationLayerInfo(), _dilation };
357 const TensorShape dst_shape = compute_depthwise_convolution_shape(TensorInfo(_input_shape, 1, _data_type), TensorInfo(_weights_shape, 1, _data_type), info);
358 _reference = reference::depthwise_convolution(src, weights, biases, dst_shape, _conv_info, _depth_multiplier, _dilation);
Giorgio Arena44f55722019-07-12 14:49:49 +0100359 }
360
361protected:
362 template <typename U>
363 void fill(U &&tensor, int i)
364 {
365 switch(tensor.data_type())
366 {
367 case DataType::F32:
368 {
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000369 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Giorgio Arena44f55722019-07-12 14:49:49 +0100370 library->fill(tensor, distribution, i);
371 break;
372 }
373 default:
374 library->fill_tensor_uniform(tensor, i);
375 }
376 }
377
Giorgio Arena44f55722019-07-12 14:49:49 +0100378 TensorType _target{};
379 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000380
381 TensorType _src{};
382 TensorType _weights{};
383 TensorType _biases{};
384 FunctionType _dwc{};
385
386 TensorShape _input_shape{};
387 TensorShape _weights_shape{};
388 TensorShape _biases_shape{};
389 DataType _data_type{};
390 DataLayout _data_layout{};
391 PadStrideInfo _conv_info{};
392 Size2D _dilation{};
393 unsigned int _depth_multiplier{};
Giorgio Arena44f55722019-07-12 14:49:49 +0100394};
395
396template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100397class DepthwiseConvolutionLayerNativeConfigurableValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100398{
399public:
400 template <typename...>
401 void setup(size_t width, size_t height, size_t channel, size_t batch, Size2D kernel_size, size_t depth_multiplier, Size2D dilation, Size2D stride, bool padding_valid, DataType data_type,
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000402 DataLayout data_layout, const ActivationLayerInfo &act_info, unsigned int n0)
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100403 {
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000404 _dilation = dilation;
405 _depth_multiplier = depth_multiplier;
406 _data_type = data_type;
407 _data_layout = data_layout;
408 _act_info = act_info;
409 _n0 = n0;
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100410
Giorgio Arena68e29da2021-02-08 16:31:10 +0000411 _input_shape = TensorShape(width, height, channel, batch);
412 _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
413 _biases_shape = TensorShape(_weights_shape.z());
414
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100415 if(padding_valid)
416 {
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000417 _conv_info = PadStrideInfo();
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100418 }
419 else
420 {
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000421 _conv_info = calculate_same_pad(_input_shape, _weights_shape, PadStrideInfo(stride.width, stride.height), DataLayout::NCHW, _dilation);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000422 }
423 }
424
425 void configure_target()
426 {
427 TensorShape input_shape = _input_shape;
428 TensorShape weights_shape = _weights_shape;
429
430 if(_data_layout == DataLayout::NHWC)
431 {
432 permute(input_shape, PermutationVector(2U, 0U, 1U));
433 permute(weights_shape, PermutationVector(2U, 0U, 1U));
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100434 }
435
Giorgio Arena68e29da2021-02-08 16:31:10 +0000436 // Create tensors
437 _src = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
438 _weights = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
439 _biases = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
440 _target = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
441
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000442 DWCWeightsKernelInfo dwc_weights_info;
443 dwc_weights_info.n0 = _n0;
Giorgio Arena68e29da2021-02-08 16:31:10 +0000444
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000445 DWCKernelInfo dwc_info;
446 dwc_info.activation_info = _act_info;
Giorgio Arena68e29da2021-02-08 16:31:10 +0000447
448 // Create Depthwise Convolution configure function
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000449 _dwc.configure(&_src, &_weights, &_biases, &_target, dwc_weights_info, dwc_info, _conv_info, _depth_multiplier, _dilation);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000450
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100451 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
452 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
453 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
454 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000455 }
456
457 void allocate_and_run_target()
458 {
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000459 add_padding_x({ &_src, &_weights, &_biases, &_target }, _data_layout);
Giorgio Arena63825e82021-03-25 14:54:50 +0000460
Giorgio Arena68e29da2021-02-08 16:31:10 +0000461 // Allocate tensors
462 _src.allocator()->allocate();
463 _weights.allocator()->allocate();
464 _biases.allocator()->allocate();
465 _target.allocator()->allocate();
466
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100467 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
468 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
469 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
470 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000471
472 // Fill tensors
473 fill(AccessorType(_src), 0);
474 fill(AccessorType(_weights), 1);
475 fill(AccessorType(_biases), 2);
476
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000477 // Test Multi DataLayout graph cases, when the data layout changes after configure
478 _src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
479 _target.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
480
Giorgio Arena68e29da2021-02-08 16:31:10 +0000481 // Compute function
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000482 _dwc.run();
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000483
484 // Reinstating original data layout for the test suite to properly check the values
485 _target.info()->set_data_layout(_data_layout);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000486 }
487
488 void compute_reference()
489 {
490 SimpleTensor<T> src{ _input_shape, _data_type };
491 SimpleTensor<T> weights{ _weights_shape, _data_type };
492 SimpleTensor<T> biases{ _biases_shape, _data_type };
493
494 fill(src, 0);
495 fill(weights, 1);
496 fill(biases, 2);
497
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100498 const ConvolutionInfo info{ _conv_info, _depth_multiplier, _act_info, _dilation };
499 const TensorShape dst_shape = compute_depthwise_convolution_shape(TensorInfo(_input_shape, 1, _data_type), TensorInfo(_weights_shape, 1, _data_type), info);
Gian Marco Iodicec63b7222021-06-30 08:39:44 +0000500 _reference = reference::activation_layer(reference::depthwise_convolution(src, weights, biases, dst_shape, _conv_info, _depth_multiplier, _dilation), _act_info);
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100501 }
502
503protected:
504 template <typename U>
505 void fill(U &&tensor, int i)
506 {
507 switch(tensor.data_type())
508 {
509 case DataType::F32:
510 {
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000511 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100512 library->fill(tensor, distribution, i);
513 break;
514 }
515 case DataType::F16:
516 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000517 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100518 library->fill(tensor, distribution, i);
519 break;
520 }
521 default:
522 library->fill_tensor_uniform(tensor, i);
523 }
524 }
525
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100526 TensorType _target{};
527 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000528
529 TensorType _src{};
530 TensorType _weights{};
531 TensorType _biases{};
532 FunctionType _dwc{};
533
534 TensorShape _input_shape{};
535 TensorShape _weights_shape{};
536 TensorShape _biases_shape{};
537 DataType _data_type{};
538 DataLayout _data_layout{};
539 PadStrideInfo _conv_info{};
540 ActivationLayerInfo _act_info{};
541 Size2D _dilation{};
542 unsigned int _depth_multiplier{};
543 unsigned int _n0{};
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100544};
545
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000546template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100547class DepthwiseConvolutionLayerValidationQuantizedFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700548{
549public:
550 template <typename...>
Pablo Telloa28aebc2019-06-03 14:59:48 +0100551 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type,
552 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700553 {
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100554 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier, data_type,
555 data_type, input_quantization_info, input_quantization_info, output_quantization_info,
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000556 data_layout, act_info, mixed_layout);
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100557 }
558};
559
560template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW>
561class DepthwiseConvolutionLayerValidationQuantizedPerChannelFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>
562{
563public:
564 template <typename...>
565 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType input_data_type, DataType weights_data_type,
Giorgio Arenad93e2632019-10-15 11:09:33 +0100566 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100567 {
Giorgio Arenad93e2632019-10-15 11:09:33 +0100568 const float out_scale = output_quantization_info.uniform().scale;
569 const float in_scale = input_quantization_info.uniform().scale;
570
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000571 std::vector<float> weights_scales{};
572 std::mt19937 gen(library->seed());
573 std::uniform_real_distribution<float> dis(0.01f, out_scale / in_scale);
Giorgio Arenad93e2632019-10-15 11:09:33 +0100574 for(size_t i = 0; i < in_shape.z() * depth_multiplier; ++i)
575 {
576 weights_scales.push_back(dis(gen));
577 }
578
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100579 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
580 input_data_type, weights_data_type,
Giorgio Arenad93e2632019-10-15 11:09:33 +0100581 input_quantization_info, QuantizationInfo(weights_scales), output_quantization_info,
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100582 data_layout, act_info);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700583 }
Giorgio Arena93a690e2017-08-01 16:09:33 +0100584};
585} // namespace validation
586} // namespace test
587} // namespace arm_compute
588#endif /* ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE */