blob: ddbab7fe13155e23b1a73df63fc880633cc887f2 [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,
SiCongLibc4e3112021-06-29 13:18:30 +010062 DataLayout data_layout, ActivationLayerInfo act_info, bool mixed_layout = false, bool in_place = false)
Giorgio Arena93a690e2017-08-01 16:09:33 +010063 {
SiCongLibc4e3112021-06-29 13:18:30 +010064 ARM_COMPUTE_ERROR_ON(mixed_layout && in_place);
Manuel Bottinica62c6f2021-03-23 11:50:34 +000065 _mixed_layout = mixed_layout;
Giorgio Arena68e29da2021-02-08 16:31:10 +000066 _input_shape = in_shape;
67 _input_data_type = input_data_type;
68 _weights_data_type = weights_data_type;
69 _input_quantization_info = input_quantization_info;
70 _weights_quantization_info = weights_quantization_info;
71 _output_quantization_info = output_quantization_info;
72 _data_layout = data_layout;
73 _pad_stride_info = pad_stride_info;
74 _act_info = act_info;
75 _depth_multiplier = depth_multiplier;
76 _dilation = dilation;
SiCongLibc4e3112021-06-29 13:18:30 +010077 _in_place = in_place;
Giorgio Arena76572242018-04-04 17:44:26 +010078
Giorgio Arena68e29da2021-02-08 16:31:10 +000079 _bias_data_type = is_data_type_quantized(_input_data_type) ? DataType::S32 : _input_data_type;
Giorgio Arena76572242018-04-04 17:44:26 +010080
Giorgio Arena68e29da2021-02-08 16:31:10 +000081 _weights_shape = TensorShape(kernel_size.width, kernel_size.height);
Giorgio Arena76572242018-04-04 17:44:26 +010082
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010083 const TensorInfo in_info(_input_shape, 1, _input_data_type);
84 const TensorInfo we_info(_weights_shape, 1, _weights_data_type);
85 const ConvolutionInfo info{ _pad_stride_info, _depth_multiplier, _act_info, _dilation };
86 _output_shape = compute_depthwise_convolution_shape(in_info, we_info, info);
Dmitry Savenkod7295b72017-11-20 22:00:08 +070087
Giorgio Arena68e29da2021-02-08 16:31:10 +000088 _weights_shape.set(2, _output_shape.z());
89 _biases_shape = TensorShape(_weights_shape[2]);
90 }
91
92 void configure_target()
93 {
94 TensorShape input_shape = _input_shape;
95 TensorShape weights_shape = _weights_shape;
96 TensorShape output_shape = _output_shape;
97
98 if(_data_layout == DataLayout::NHWC)
99 {
100 permute(input_shape, PermutationVector(2U, 0U, 1U));
101 permute(weights_shape, PermutationVector(2U, 0U, 1U));
102 permute(output_shape, PermutationVector(2U, 0U, 1U));
103 }
104
105 // Create tensors
SiCongLibc4e3112021-06-29 13:18:30 +0100106 _src = create_tensor<TensorType>(input_shape, _input_data_type, 1, _input_quantization_info, _data_layout);
107 _weights = create_tensor<TensorType>(weights_shape, _weights_data_type, 1, _weights_quantization_info, _data_layout);
108 _biases = create_tensor<TensorType>(_biases_shape, _bias_data_type, 1, _input_quantization_info, _data_layout);
109 TensorType *target_to_use = nullptr;
110 if(!_in_place)
111 {
112 _target = create_tensor<TensorType>(output_shape, _input_data_type, 1, _output_quantization_info, _data_layout);
113 target_to_use = &_target;
114 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000115
Gian Marco Iodice5e281812021-07-06 13:19:41 +0100116 add_padding_x({ &_src, &_biases }, _data_layout);
117 add_padding_x({ &_weights }, _data_layout, true);
118 if(!_in_place)
119 {
120 add_padding_x({ &_target }, _data_layout);
121 }
122
Giorgio Arena68e29da2021-02-08 16:31:10 +0000123 // Create Depthwise Convolution configure function
SiCongLibc4e3112021-06-29 13:18:30 +0100124 _dwc.configure(&_src, &_weights, &_biases, target_to_use, _pad_stride_info, _depth_multiplier, _act_info, _dilation);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000125
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100126 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
127 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
128 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
129 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000130 }
131
132 void allocate_and_run_target()
133 {
134 // Allocate tensors
135 _src.allocator()->allocate();
136 _weights.allocator()->allocate();
137 _biases.allocator()->allocate();
Giorgio Arena68e29da2021-02-08 16:31:10 +0000138
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100139 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
140 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
141 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
SiCongLibc4e3112021-06-29 13:18:30 +0100142
143 if(!_in_place)
144 {
145 _target.allocator()->allocate();
146 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
147 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000148
149 // Fill tensors
150 fill(AccessorType(_src), 0);
151 fill(AccessorType(_weights), 1);
152 fill(AccessorType(_biases), 2);
Giorgio Arena63825e82021-03-25 14:54:50 +0000153
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000154 if(_mixed_layout)
155 {
156 mix_layout(_dwc, _src, _target);
157 }
158 else
159 {
160 // Compute function
161 _dwc.run();
162 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000163 }
164
165 void compute_reference()
166 {
167 SimpleTensor<T> src{ _input_shape, _input_data_type, 1, _input_quantization_info };
168 SimpleTensor<TW> weights{ _weights_shape, _weights_data_type, 1, _weights_quantization_info };
169 SimpleTensor<TBias> biases{ _biases_shape, _bias_data_type, 1, _input_quantization_info };
170
171 fill(src, 0);
172 fill(weights, 1);
173 fill(biases, 2);
174
175 SimpleTensor<T> depth_out = reference::depthwise_convolution(src, weights, biases, _output_shape, _pad_stride_info, _depth_multiplier, _dilation, _output_quantization_info);
176 _reference = (_act_info.enabled()) ? reference::activation_layer<T>(depth_out, _act_info) : depth_out;
Giorgio Arena93a690e2017-08-01 16:09:33 +0100177 }
178
179protected:
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000180 void mix_layout(FunctionType &layer, TensorType &src, TensorType &dst)
181 {
SiCongLibc4e3112021-06-29 13:18:30 +0100182 ARM_COMPUTE_ERROR_ON(_in_place);
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000183 // Test Multi DataLayout graph cases, when the data layout changes after configure
184 src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
185 dst.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
186
187 // Compute Convolution function
188 layer.run();
189
190 // Reinstating original data layout for the test suite to properly check the values
191 src.info()->set_data_layout(_data_layout);
192 dst.info()->set_data_layout(_data_layout);
193 }
194
Giorgio Arena93a690e2017-08-01 16:09:33 +0100195 template <typename U>
196 void fill(U &&tensor, int i)
197 {
198 switch(tensor.data_type())
199 {
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700200 case DataType::QASYMM8:
201 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100202 std::uniform_int_distribution<uint8_t> distribution(0, 15);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700203 library->fill(tensor, distribution, i);
204 break;
205 }
Michele Di Giorgio4cd4cde2020-01-06 14:07:44 +0000206 case DataType::QASYMM8_SIGNED:
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100207 case DataType::QSYMM8_PER_CHANNEL:
208 {
209 std::uniform_int_distribution<int8_t> distribution(-10, 10);
210 library->fill(tensor, distribution, i);
211 break;
212 }
Frank Lei8cdfdb82018-01-02 16:49:33 +0800213 case DataType::F16:
Giorgio Arena93a690e2017-08-01 16:09:33 +0100214 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000215 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000216 library->fill(tensor, distribution, i);
217 break;
218 }
219 case DataType::F32:
220 {
221 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Giorgio Arena93a690e2017-08-01 16:09:33 +0100222 library->fill(tensor, distribution, i);
223 break;
224 }
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700225 case DataType::S32:
226 {
Georgios Pinitasf72f9362018-01-12 16:29:45 +0000227 std::uniform_int_distribution<int32_t> distribution(-100, 100);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700228 library->fill(tensor, distribution, i);
229 break;
230 }
Giorgio Arena93a690e2017-08-01 16:09:33 +0100231 default:
232 library->fill_tensor_uniform(tensor, i);
233 }
234 }
235
Georgios Pinitasddec4d62019-07-10 19:23:02 +0100236 TensorType _target{};
237 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000238
239 TensorType _src{};
240 TensorType _weights{};
241 TensorType _biases{};
242 FunctionType _dwc{};
243
244 TensorShape _input_shape{};
245 TensorShape _weights_shape{};
246 TensorShape _biases_shape{};
247 TensorShape _output_shape{};
248 DataType _input_data_type{};
249 DataType _weights_data_type{};
250 DataType _bias_data_type{};
251 QuantizationInfo _input_quantization_info{};
252 QuantizationInfo _weights_quantization_info{};
253 QuantizationInfo _output_quantization_info{};
254 DataLayout _data_layout{};
255 PadStrideInfo _pad_stride_info{};
256 ActivationLayerInfo _act_info{};
257 unsigned int _depth_multiplier{};
258 Size2D _dilation{};
Giorgio Arena63825e82021-03-25 14:54:50 +0000259 bool _mixed_layout{ false };
SiCongLibc4e3112021-06-29 13:18:30 +0100260 bool _in_place{ false };
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700261};
262
SiCongLibc4e3112021-06-29 13:18:30 +0100263template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false, bool in_place = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100264class DepthwiseConvolutionLayerValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700265{
266public:
267 template <typename...>
Manuel Bottinia788c2f2019-04-08 13:18:00 +0100268 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type, DataLayout data_layout,
269 ActivationLayerInfo act_info)
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700270 {
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100271 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
272 data_type, data_type, QuantizationInfo(), QuantizationInfo(), QuantizationInfo(),
SiCongLibc4e3112021-06-29 13:18:30 +0100273 data_layout, act_info, mixed_layout, in_place);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700274 }
275};
276
277template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100278class DepthwiseConvolutionLayerNativeValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Giorgio Arena44f55722019-07-12 14:49:49 +0100279{
280public:
281 template <typename...>
282 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,
283 DataLayout data_layout)
284 {
Giorgio Arena68e29da2021-02-08 16:31:10 +0000285 _dilation = dilation;
286 _depth_multiplier = depth_multiplier;
287 _data_type = data_type;
288 _data_layout = data_layout;
Giorgio Arena44f55722019-07-12 14:49:49 +0100289
Giorgio Arena68e29da2021-02-08 16:31:10 +0000290 _input_shape = TensorShape(width, height, channel, batch);
291 _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
292 _biases_shape = TensorShape(_weights_shape.z());
293
Giorgio Arena44f55722019-07-12 14:49:49 +0100294 if(padding_valid)
295 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100296 _conv_info = PadStrideInfo(stride.width, stride.height);
Giorgio Arena44f55722019-07-12 14:49:49 +0100297 }
298 else
299 {
Giorgio Arena68e29da2021-02-08 16:31:10 +0000300 _conv_info = calculate_same_pad(_input_shape, _weights_shape, PadStrideInfo(stride.width, stride.height), DataLayout::NCHW, _dilation);
301 }
302 }
303
304 void configure_target()
305 {
306 TensorShape input_shape = _input_shape;
307 TensorShape weights_shape = _weights_shape;
308
309 if(_data_layout == DataLayout::NHWC)
310 {
311 permute(input_shape, PermutationVector(2U, 0U, 1U));
312 permute(weights_shape, PermutationVector(2U, 0U, 1U));
Giorgio Arena44f55722019-07-12 14:49:49 +0100313 }
314
Giorgio Arena68e29da2021-02-08 16:31:10 +0000315 // Create tensors
316 _src = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
317 _weights = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
318 _biases = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
319 _target = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
320
Gian Marco Iodice5e281812021-07-06 13:19:41 +0100321 add_padding_x({ &_src, &_biases, &_target }, _data_layout);
322 add_padding_x({ &_weights }, _data_layout, true);
323 add_padding_y({ &_src, &_target }, _data_layout);
324
Giorgio Arena68e29da2021-02-08 16:31:10 +0000325 // Create Depthwise Convolution configure function
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100326 const ConvolutionInfo info
327 {
328 _conv_info, _depth_multiplier, ActivationLayerInfo(), _dilation
329 };
330 _dwc.configure(_src.info(), _weights.info(), _biases.info(), _target.info(), info);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000331
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100332 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
333 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
334 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
335 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000336 }
337
338 void allocate_and_run_target()
339 {
340 // Allocate tensors
341 _src.allocator()->allocate();
342 _weights.allocator()->allocate();
343 _biases.allocator()->allocate();
344 _target.allocator()->allocate();
345
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100346 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
347 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
348 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
349 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000350
351 // Fill tensors
352 fill(AccessorType(_src), 0);
353 fill(AccessorType(_weights), 1);
354 fill(AccessorType(_biases), 2);
355
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100356 arm_compute::ITensorPack pack;
357 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_0, &_src);
358 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_1, &_weights);
359 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_2, &_biases);
360 pack.add_tensor(arm_compute::TensorType::ACL_DST, &_target);
361
Giorgio Arena68e29da2021-02-08 16:31:10 +0000362 // Compute function
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100363 _dwc.run(pack);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000364 }
365
366 void compute_reference()
367 {
368 SimpleTensor<T> src{ _input_shape, _data_type };
369 SimpleTensor<T> weights{ _weights_shape, _data_type };
370 SimpleTensor<T> biases{ _biases_shape, _data_type };
371
372 fill(src, 0);
373 fill(weights, 1);
374 fill(biases, 2);
375
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100376 const ConvolutionInfo info{ _conv_info, _depth_multiplier, ActivationLayerInfo(), _dilation };
377 const TensorShape dst_shape = compute_depthwise_convolution_shape(TensorInfo(_input_shape, 1, _data_type), TensorInfo(_weights_shape, 1, _data_type), info);
378 _reference = reference::depthwise_convolution(src, weights, biases, dst_shape, _conv_info, _depth_multiplier, _dilation);
Giorgio Arena44f55722019-07-12 14:49:49 +0100379 }
380
381protected:
382 template <typename U>
383 void fill(U &&tensor, int i)
384 {
385 switch(tensor.data_type())
386 {
387 case DataType::F32:
388 {
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000389 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Giorgio Arena44f55722019-07-12 14:49:49 +0100390 library->fill(tensor, distribution, i);
391 break;
392 }
393 default:
394 library->fill_tensor_uniform(tensor, i);
395 }
396 }
397
Giorgio Arena44f55722019-07-12 14:49:49 +0100398 TensorType _target{};
399 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000400
401 TensorType _src{};
402 TensorType _weights{};
403 TensorType _biases{};
404 FunctionType _dwc{};
405
406 TensorShape _input_shape{};
407 TensorShape _weights_shape{};
408 TensorShape _biases_shape{};
409 DataType _data_type{};
410 DataLayout _data_layout{};
411 PadStrideInfo _conv_info{};
412 Size2D _dilation{};
413 unsigned int _depth_multiplier{};
Giorgio Arena44f55722019-07-12 14:49:49 +0100414};
415
SiCongLibc4e3112021-06-29 13:18:30 +0100416template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool in_place = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100417class DepthwiseConvolutionLayerNativeConfigurableValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100418{
419public:
420 template <typename...>
421 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 Iodice8155c022021-04-16 15:08:59 +0100422 DataLayout data_layout, const ActivationLayerInfo &act_info, unsigned int n0, bool export_to_cl_image)
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100423 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100424 _dilation = dilation;
425 _depth_multiplier = depth_multiplier;
426 _data_type = data_type;
427 _data_layout = data_layout;
428 _act_info = act_info;
429 _n0 = n0;
430 _export_to_cl_image = export_to_cl_image;
431 _in_place = in_place;
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100432
Giorgio Arena68e29da2021-02-08 16:31:10 +0000433 _input_shape = TensorShape(width, height, channel, batch);
434 _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
435 _biases_shape = TensorShape(_weights_shape.z());
436
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100437 if(padding_valid)
438 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100439 _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 +0100440 }
441 else
442 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100443 _conv_info = PadStrideInfo(stride.width, stride.height);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000444 }
445 }
446
447 void configure_target()
448 {
449 TensorShape input_shape = _input_shape;
450 TensorShape weights_shape = _weights_shape;
451
452 if(_data_layout == DataLayout::NHWC)
453 {
454 permute(input_shape, PermutationVector(2U, 0U, 1U));
455 permute(weights_shape, PermutationVector(2U, 0U, 1U));
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100456 }
457
Giorgio Arena68e29da2021-02-08 16:31:10 +0000458 // Create tensors
SiCongLibc4e3112021-06-29 13:18:30 +0100459 _src = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
460 _weights = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
461 _biases = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
462 TensorType *target_to_use = nullptr;
463 if(!_in_place)
464 {
465 _target = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
466 target_to_use = &_target;
467 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000468
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100469 DWCComputeKernelInfo dwc_info;
470 dwc_info.n0 = _n0;
471 dwc_info.m0 = _conv_info.stride().first == 1 && _dilation.x() == 1 ? 8 : 1;
472 dwc_info.export_weights_to_cl_image = _export_to_cl_image;
Giorgio Arena68e29da2021-02-08 16:31:10 +0000473
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100474#if defined(ARM_COMPUTE_OPENCL_ENABLED)
475 if(_export_to_cl_image)
476 {
477 _validate_output |= image2d_from_buffer_supported(CLKernelLibrary::get().get_device());
478 _validate_output |= (get_cl_image_pitch_alignment(CLKernelLibrary::get().get_device()) != 0);
479 }
480#endif // ARM_COMPUTE_OPENCL_ENABLED
481
482 const ConvolutionInfo conv_kernel_info
483 {
484 _conv_info, _depth_multiplier, _act_info, _dilation
485 };
Giorgio Arena68e29da2021-02-08 16:31:10 +0000486
Gian Marco Iodice5e281812021-07-06 13:19:41 +0100487 add_padding_x({ &_src, &_biases, &_target }, _data_layout);
488 add_padding_x({ &_weights }, _data_layout, _export_to_cl_image); // Don't add left padding if cl image will be used
489
Giorgio Arena68e29da2021-02-08 16:31:10 +0000490 // Create Depthwise Convolution configure function
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100491 _dwc.configure(&_src, &_weights, &_biases, target_to_use, dwc_info, conv_kernel_info);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000492
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100493 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
494 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
495 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
496 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000497 }
498
499 void allocate_and_run_target()
500 {
501 // Allocate tensors
502 _src.allocator()->allocate();
503 _weights.allocator()->allocate();
504 _biases.allocator()->allocate();
Giorgio Arena68e29da2021-02-08 16:31:10 +0000505
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100506 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
507 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
508 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
SiCongLibc4e3112021-06-29 13:18:30 +0100509 if(!_in_place)
510 {
511 _target.allocator()->allocate();
512 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
513 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000514
515 // Fill tensors
516 fill(AccessorType(_src), 0);
517 fill(AccessorType(_weights), 1);
518 fill(AccessorType(_biases), 2);
519
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000520 // Test Multi DataLayout graph cases, when the data layout changes after configure
521 _src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
SiCongLibc4e3112021-06-29 13:18:30 +0100522 if(!_in_place)
523 {
524 _target.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
525 }
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000526
Giorgio Arena68e29da2021-02-08 16:31:10 +0000527 // Compute function
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100528 if(_validate_output)
529 {
530 _dwc.run();
531 }
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000532
533 // Reinstating original data layout for the test suite to properly check the values
SiCongLibc4e3112021-06-29 13:18:30 +0100534 if(!_in_place)
535 {
536 _target.info()->set_data_layout(_data_layout);
537 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000538 }
539
540 void compute_reference()
541 {
542 SimpleTensor<T> src{ _input_shape, _data_type };
543 SimpleTensor<T> weights{ _weights_shape, _data_type };
544 SimpleTensor<T> biases{ _biases_shape, _data_type };
545
546 fill(src, 0);
547 fill(weights, 1);
548 fill(biases, 2);
549
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100550 const ConvolutionInfo info{ _conv_info, _depth_multiplier, _act_info, _dilation };
551 const TensorShape dst_shape = compute_depthwise_convolution_shape(TensorInfo(_input_shape, 1, _data_type), TensorInfo(_weights_shape, 1, _data_type), info);
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100552 if(_validate_output)
553 {
554 _reference = reference::activation_layer(reference::depthwise_convolution(src, weights, biases, dst_shape, _conv_info, _depth_multiplier, _dilation), _act_info);
555 }
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100556 }
557
558protected:
559 template <typename U>
560 void fill(U &&tensor, int i)
561 {
562 switch(tensor.data_type())
563 {
564 case DataType::F32:
565 {
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000566 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100567 library->fill(tensor, distribution, i);
568 break;
569 }
570 case DataType::F16:
571 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000572 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100573 library->fill(tensor, distribution, i);
574 break;
575 }
576 default:
577 library->fill_tensor_uniform(tensor, i);
578 }
579 }
580
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100581 TensorType _target{};
582 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000583
584 TensorType _src{};
585 TensorType _weights{};
586 TensorType _biases{};
587 FunctionType _dwc{};
588
589 TensorShape _input_shape{};
590 TensorShape _weights_shape{};
591 TensorShape _biases_shape{};
592 DataType _data_type{};
593 DataLayout _data_layout{};
594 PadStrideInfo _conv_info{};
595 ActivationLayerInfo _act_info{};
596 Size2D _dilation{};
597 unsigned int _depth_multiplier{};
598 unsigned int _n0{};
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100599 bool _export_to_cl_image{};
600 bool _validate_output{ true };
SiCongLibc4e3112021-06-29 13:18:30 +0100601 bool _in_place{ false };
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100602};
603
SiCongLibc4e3112021-06-29 13:18:30 +0100604template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false, bool in_place = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100605class DepthwiseConvolutionLayerValidationQuantizedFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700606{
607public:
608 template <typename...>
Pablo Telloa28aebc2019-06-03 14:59:48 +0100609 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type,
610 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700611 {
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100612 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier, data_type,
613 data_type, input_quantization_info, input_quantization_info, output_quantization_info,
SiCongLibc4e3112021-06-29 13:18:30 +0100614 data_layout, act_info, mixed_layout, in_place);
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100615 }
616};
617
SiCongLibc4e3112021-06-29 13:18:30 +0100618template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW, bool in_place = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100619class DepthwiseConvolutionLayerValidationQuantizedPerChannelFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>
620{
621public:
622 template <typename...>
623 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 +0100624 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100625 {
Giorgio Arenad93e2632019-10-15 11:09:33 +0100626 const float out_scale = output_quantization_info.uniform().scale;
627 const float in_scale = input_quantization_info.uniform().scale;
628
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000629 std::vector<float> weights_scales{};
630 std::mt19937 gen(library->seed());
631 std::uniform_real_distribution<float> dis(0.01f, out_scale / in_scale);
Giorgio Arenad93e2632019-10-15 11:09:33 +0100632 for(size_t i = 0; i < in_shape.z() * depth_multiplier; ++i)
633 {
634 weights_scales.push_back(dis(gen));
635 }
636
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100637 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
638 input_data_type, weights_data_type,
Giorgio Arenad93e2632019-10-15 11:09:33 +0100639 input_quantization_info, QuantizationInfo(weights_scales), output_quantization_info,
SiCongLibc4e3112021-06-29 13:18:30 +0100640 data_layout, act_info, false, in_place);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700641 }
Giorgio Arena93a690e2017-08-01 16:09:33 +0100642};
643} // namespace validation
644} // namespace test
645} // namespace arm_compute
646#endif /* ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE */