blob: 8e187bf2782a743463606d934b40d0e5d7c3591b [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 Iodice561c1762021-04-16 15:08:59 +0100278 _conv_info = PadStrideInfo(stride.width, stride.height);
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 Iodice561c1762021-04-16 15:08:59 +0100402 DataLayout data_layout, const ActivationLayerInfo &act_info, unsigned int n0, bool export_to_cl_image)
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100403 {
Gian Marco Iodice561c1762021-04-16 15:08:59 +0100404 _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;
410 _export_to_cl_image = export_to_cl_image;
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100411
Giorgio Arena68e29da2021-02-08 16:31:10 +0000412 _input_shape = TensorShape(width, height, channel, batch);
413 _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
414 _biases_shape = TensorShape(_weights_shape.z());
415
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100416 if(padding_valid)
417 {
Gian Marco Iodice561c1762021-04-16 15:08:59 +0100418 _conv_info = calculate_same_pad(_input_shape, _weights_shape, PadStrideInfo(stride.width, stride.height), DataLayout::NCHW, _dilation);
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100419 }
420 else
421 {
Gian Marco Iodice561c1762021-04-16 15:08:59 +0100422 _conv_info = PadStrideInfo(stride.width, stride.height);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000423 }
424 }
425
426 void configure_target()
427 {
428 TensorShape input_shape = _input_shape;
429 TensorShape weights_shape = _weights_shape;
430
431 if(_data_layout == DataLayout::NHWC)
432 {
433 permute(input_shape, PermutationVector(2U, 0U, 1U));
434 permute(weights_shape, PermutationVector(2U, 0U, 1U));
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100435 }
436
Giorgio Arena68e29da2021-02-08 16:31:10 +0000437 // Create tensors
438 _src = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
439 _weights = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
440 _biases = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
441 _target = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
442
Gian Marco Iodice561c1762021-04-16 15:08:59 +0100443 DWCComputeKernelInfo dwc_info;
444 dwc_info.n0 = _n0;
445 dwc_info.m0 = _conv_info.stride().first == 1 && _dilation.x() == 1 ? 8 : 1;
446 dwc_info.export_weights_to_cl_image = _export_to_cl_image;
Giorgio Arena68e29da2021-02-08 16:31:10 +0000447
Gian Marco Iodice561c1762021-04-16 15:08:59 +0100448#if defined(ARM_COMPUTE_OPENCL_ENABLED)
449 if(_export_to_cl_image)
450 {
451 _validate_output |= image2d_from_buffer_supported(CLKernelLibrary::get().get_device());
452 _validate_output |= (get_cl_image_pitch_alignment(CLKernelLibrary::get().get_device()) != 0);
453 }
454#endif // ARM_COMPUTE_OPENCL_ENABLED
455
456 const ConvolutionInfo conv_kernel_info
457 {
458 _conv_info, _depth_multiplier, _act_info, _dilation
459 };
Giorgio Arena68e29da2021-02-08 16:31:10 +0000460
461 // Create Depthwise Convolution configure function
Gian Marco Iodice561c1762021-04-16 15:08:59 +0100462 _dwc.configure(&_src, &_weights, &_biases, &_target, dwc_info, conv_kernel_info);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000463
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100464 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
465 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
466 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
467 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000468 }
469
470 void allocate_and_run_target()
471 {
Gian Marco Iodice561c1762021-04-16 15:08:59 +0100472 add_padding_x({ &_src, &_biases, &_target }, _data_layout);
473 add_padding_x({ &_weights }, _data_layout, _export_to_cl_image); // Don't add left padding if cl image will be used
Giorgio Arena63825e82021-03-25 14:54:50 +0000474
Giorgio Arena68e29da2021-02-08 16:31:10 +0000475 // Allocate tensors
476 _src.allocator()->allocate();
477 _weights.allocator()->allocate();
478 _biases.allocator()->allocate();
479 _target.allocator()->allocate();
480
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100481 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
482 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
483 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
484 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000485
486 // Fill tensors
487 fill(AccessorType(_src), 0);
488 fill(AccessorType(_weights), 1);
489 fill(AccessorType(_biases), 2);
490
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000491 // Test Multi DataLayout graph cases, when the data layout changes after configure
492 _src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
493 _target.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
494
Giorgio Arena68e29da2021-02-08 16:31:10 +0000495 // Compute function
Gian Marco Iodice561c1762021-04-16 15:08:59 +0100496 if(_validate_output)
497 {
498 _dwc.run();
499 }
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000500
501 // Reinstating original data layout for the test suite to properly check the values
502 _target.info()->set_data_layout(_data_layout);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000503 }
504
505 void compute_reference()
506 {
507 SimpleTensor<T> src{ _input_shape, _data_type };
508 SimpleTensor<T> weights{ _weights_shape, _data_type };
509 SimpleTensor<T> biases{ _biases_shape, _data_type };
510
511 fill(src, 0);
512 fill(weights, 1);
513 fill(biases, 2);
514
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100515 const ConvolutionInfo info{ _conv_info, _depth_multiplier, _act_info, _dilation };
516 const TensorShape dst_shape = compute_depthwise_convolution_shape(TensorInfo(_input_shape, 1, _data_type), TensorInfo(_weights_shape, 1, _data_type), info);
Gian Marco Iodice561c1762021-04-16 15:08:59 +0100517 if(_validate_output)
518 {
519 _reference = reference::activation_layer(reference::depthwise_convolution(src, weights, biases, dst_shape, _conv_info, _depth_multiplier, _dilation), _act_info);
520 }
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100521 }
522
523protected:
524 template <typename U>
525 void fill(U &&tensor, int i)
526 {
527 switch(tensor.data_type())
528 {
529 case DataType::F32:
530 {
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000531 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100532 library->fill(tensor, distribution, i);
533 break;
534 }
535 case DataType::F16:
536 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000537 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100538 library->fill(tensor, distribution, i);
539 break;
540 }
541 default:
542 library->fill_tensor_uniform(tensor, i);
543 }
544 }
545
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100546 TensorType _target{};
547 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000548
549 TensorType _src{};
550 TensorType _weights{};
551 TensorType _biases{};
552 FunctionType _dwc{};
553
554 TensorShape _input_shape{};
555 TensorShape _weights_shape{};
556 TensorShape _biases_shape{};
557 DataType _data_type{};
558 DataLayout _data_layout{};
559 PadStrideInfo _conv_info{};
560 ActivationLayerInfo _act_info{};
561 Size2D _dilation{};
562 unsigned int _depth_multiplier{};
563 unsigned int _n0{};
Gian Marco Iodice561c1762021-04-16 15:08:59 +0100564 bool _export_to_cl_image{};
565 bool _validate_output{ true };
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100566};
567
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000568template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100569class DepthwiseConvolutionLayerValidationQuantizedFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700570{
571public:
572 template <typename...>
Pablo Telloa28aebc2019-06-03 14:59:48 +0100573 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type,
574 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700575 {
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100576 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier, data_type,
577 data_type, input_quantization_info, input_quantization_info, output_quantization_info,
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000578 data_layout, act_info, mixed_layout);
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100579 }
580};
581
582template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW>
583class DepthwiseConvolutionLayerValidationQuantizedPerChannelFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>
584{
585public:
586 template <typename...>
587 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 +0100588 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100589 {
Giorgio Arenad93e2632019-10-15 11:09:33 +0100590 const float out_scale = output_quantization_info.uniform().scale;
591 const float in_scale = input_quantization_info.uniform().scale;
592
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000593 std::vector<float> weights_scales{};
594 std::mt19937 gen(library->seed());
595 std::uniform_real_distribution<float> dis(0.01f, out_scale / in_scale);
Giorgio Arenad93e2632019-10-15 11:09:33 +0100596 for(size_t i = 0; i < in_shape.z() * depth_multiplier; ++i)
597 {
598 weights_scales.push_back(dis(gen));
599 }
600
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100601 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
602 input_data_type, weights_data_type,
Giorgio Arenad93e2632019-10-15 11:09:33 +0100603 input_quantization_info, QuantizationInfo(weights_scales), output_quantization_info,
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100604 data_layout, act_info);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700605 }
Giorgio Arena93a690e2017-08-01 16:09:33 +0100606};
607} // namespace validation
608} // namespace test
609} // namespace arm_compute
610#endif /* ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE */