blob: d291a7736a98a6f61ee2042ce2b42d7281e6c6fa [file] [log] [blame]
Giorgio Arena93a690e2017-08-01 16:09:33 +01001/*
Matthew Bentham945b8da2023-07-12 11:54:59 +00002 * Copyright (c) 2017-2023 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:
Michele Di Giorgio633d30b2019-10-08 17:17:18 +010058 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation,
59 unsigned int depth_multiplier, DataType input_data_type, DataType weights_data_type,
60 QuantizationInfo input_quantization_info, QuantizationInfo weights_quantization_info, QuantizationInfo output_quantization_info,
Milos Puzovica7077e92022-10-28 16:49:15 +010061 DataLayout data_layout, ActivationLayerInfo act_info, bool mixed_layout = false, bool in_place = false, bool run_twice = false)
Giorgio Arena93a690e2017-08-01 16:09:33 +010062 {
SiCongLibc4e3112021-06-29 13:18:30 +010063 ARM_COMPUTE_ERROR_ON(mixed_layout && in_place);
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;
SiCongLibc4e3112021-06-29 13:18:30 +010076 _in_place = in_place;
Milos Puzovica7077e92022-10-28 16:49:15 +010077 _run_twice = run_twice;
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);
Milos Puzovica7077e92022-10-28 16:49:15 +0100108 if(_run_twice) {
109 _weights.info()->set_are_values_constant(false);
110 }
SiCongLibc4e3112021-06-29 13:18:30 +0100111 _biases = create_tensor<TensorType>(_biases_shape, _bias_data_type, 1, _input_quantization_info, _data_layout);
112 TensorType *target_to_use = nullptr;
113 if(!_in_place)
114 {
115 _target = create_tensor<TensorType>(output_shape, _input_data_type, 1, _output_quantization_info, _data_layout);
116 target_to_use = &_target;
117 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000118
Gian Marco Iodice5e281812021-07-06 13:19:41 +0100119 add_padding_x({ &_src, &_biases }, _data_layout);
120 add_padding_x({ &_weights }, _data_layout, true);
121 if(!_in_place)
122 {
123 add_padding_x({ &_target }, _data_layout);
124 }
125
Giorgio Arena68e29da2021-02-08 16:31:10 +0000126 // Create Depthwise Convolution configure function
SiCongLibc4e3112021-06-29 13:18:30 +0100127 _dwc.configure(&_src, &_weights, &_biases, target_to_use, _pad_stride_info, _depth_multiplier, _act_info, _dilation);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000128
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100129 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
130 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
131 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
132 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000133 }
134
135 void allocate_and_run_target()
136 {
137 // Allocate tensors
138 _src.allocator()->allocate();
139 _weights.allocator()->allocate();
140 _biases.allocator()->allocate();
Giorgio Arena68e29da2021-02-08 16:31:10 +0000141
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100142 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
143 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
144 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
SiCongLibc4e3112021-06-29 13:18:30 +0100145
146 if(!_in_place)
147 {
148 _target.allocator()->allocate();
149 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
150 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000151
152 // Fill tensors
153 fill(AccessorType(_src), 0);
154 fill(AccessorType(_weights), 1);
155 fill(AccessorType(_biases), 2);
Giorgio Arena63825e82021-03-25 14:54:50 +0000156
Milos Puzovica7077e92022-10-28 16:49:15 +0100157 // Run with variable input
158 if(_run_twice) {
159 _dwc.run();
160
161 // Fill tensors with a new seed
162 fill(AccessorType(_src), 3);
163 fill(AccessorType(_weights), 4);
164 fill(AccessorType(_biases), 5);
165 }
166
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000167 if(_mixed_layout)
168 {
169 mix_layout(_dwc, _src, _target);
170 }
171 else
172 {
173 // Compute function
174 _dwc.run();
175 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000176 }
177
178 void compute_reference()
179 {
180 SimpleTensor<T> src{ _input_shape, _input_data_type, 1, _input_quantization_info };
181 SimpleTensor<TW> weights{ _weights_shape, _weights_data_type, 1, _weights_quantization_info };
182 SimpleTensor<TBias> biases{ _biases_shape, _bias_data_type, 1, _input_quantization_info };
183
184 fill(src, 0);
185 fill(weights, 1);
186 fill(biases, 2);
Milos Puzovica7077e92022-10-28 16:49:15 +0100187 if(_run_twice) {
188 SimpleTensor<T> depth_out = reference::depthwise_convolution(src, weights, biases, _output_shape, _pad_stride_info, _depth_multiplier, _dilation, _output_quantization_info);
189 if(_act_info.enabled()) {
190 reference::activation_layer<T>(depth_out, _act_info);
191 }
192
193 fill(src, 3);
194 fill(weights, 4);
195 fill(biases, 5);
196 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000197
198 SimpleTensor<T> depth_out = reference::depthwise_convolution(src, weights, biases, _output_shape, _pad_stride_info, _depth_multiplier, _dilation, _output_quantization_info);
199 _reference = (_act_info.enabled()) ? reference::activation_layer<T>(depth_out, _act_info) : depth_out;
Giorgio Arena93a690e2017-08-01 16:09:33 +0100200 }
201
202protected:
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000203 void mix_layout(FunctionType &layer, TensorType &src, TensorType &dst)
204 {
SiCongLibc4e3112021-06-29 13:18:30 +0100205 ARM_COMPUTE_ERROR_ON(_in_place);
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000206 // Test Multi DataLayout graph cases, when the data layout changes after configure
207 src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
208 dst.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
209
210 // Compute Convolution function
211 layer.run();
212
213 // Reinstating original data layout for the test suite to properly check the values
214 src.info()->set_data_layout(_data_layout);
215 dst.info()->set_data_layout(_data_layout);
216 }
217
Giorgio Arena93a690e2017-08-01 16:09:33 +0100218 template <typename U>
219 void fill(U &&tensor, int i)
220 {
221 switch(tensor.data_type())
222 {
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700223 case DataType::QASYMM8:
224 {
Pablo Tello29cab362022-03-10 17:05:34 +0000225 std::uniform_int_distribution<uint32_t> distribution(0, 15);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700226 library->fill(tensor, distribution, i);
227 break;
228 }
Michele Di Giorgio4cd4cde2020-01-06 14:07:44 +0000229 case DataType::QASYMM8_SIGNED:
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100230 case DataType::QSYMM8_PER_CHANNEL:
231 {
Pablo Tello29cab362022-03-10 17:05:34 +0000232 std::uniform_int_distribution<int32_t> distribution(-10, 10);
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100233 library->fill(tensor, distribution, i);
234 break;
235 }
Frank Lei8cdfdb82018-01-02 16:49:33 +0800236 case DataType::F16:
Giorgio Arena93a690e2017-08-01 16:09:33 +0100237 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000238 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000239 library->fill(tensor, distribution, i);
240 break;
241 }
242 case DataType::F32:
243 {
244 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Giorgio Arena93a690e2017-08-01 16:09:33 +0100245 library->fill(tensor, distribution, i);
246 break;
247 }
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700248 case DataType::S32:
249 {
Georgios Pinitasf72f9362018-01-12 16:29:45 +0000250 std::uniform_int_distribution<int32_t> distribution(-100, 100);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700251 library->fill(tensor, distribution, i);
252 break;
253 }
Giorgio Arena93a690e2017-08-01 16:09:33 +0100254 default:
255 library->fill_tensor_uniform(tensor, i);
256 }
257 }
258
Georgios Pinitasddec4d62019-07-10 19:23:02 +0100259 TensorType _target{};
260 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000261
262 TensorType _src{};
263 TensorType _weights{};
264 TensorType _biases{};
265 FunctionType _dwc{};
266
267 TensorShape _input_shape{};
268 TensorShape _weights_shape{};
269 TensorShape _biases_shape{};
270 TensorShape _output_shape{};
271 DataType _input_data_type{};
272 DataType _weights_data_type{};
273 DataType _bias_data_type{};
274 QuantizationInfo _input_quantization_info{};
275 QuantizationInfo _weights_quantization_info{};
276 QuantizationInfo _output_quantization_info{};
277 DataLayout _data_layout{};
278 PadStrideInfo _pad_stride_info{};
279 ActivationLayerInfo _act_info{};
280 unsigned int _depth_multiplier{};
281 Size2D _dilation{};
Giorgio Arena63825e82021-03-25 14:54:50 +0000282 bool _mixed_layout{ false };
SiCongLibc4e3112021-06-29 13:18:30 +0100283 bool _in_place{ false };
Milos Puzovica7077e92022-10-28 16:49:15 +0100284 bool _run_twice{ false };
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700285};
286
Milos Puzovica7077e92022-10-28 16:49:15 +0100287template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false, bool in_place = false, bool run_twice = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100288class DepthwiseConvolutionLayerValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700289{
290public:
Manuel Bottinia788c2f2019-04-08 13:18:00 +0100291 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type, DataLayout data_layout,
292 ActivationLayerInfo act_info)
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700293 {
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100294 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
295 data_type, data_type, QuantizationInfo(), QuantizationInfo(), QuantizationInfo(),
Milos Puzovica7077e92022-10-28 16:49:15 +0100296 data_layout, act_info, mixed_layout, in_place, run_twice);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700297 }
298};
299
300template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100301class DepthwiseConvolutionLayerNativeValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Giorgio Arena44f55722019-07-12 14:49:49 +0100302{
303public:
Giorgio Arena44f55722019-07-12 14:49:49 +0100304 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,
305 DataLayout data_layout)
306 {
Giorgio Arena68e29da2021-02-08 16:31:10 +0000307 _dilation = dilation;
308 _depth_multiplier = depth_multiplier;
309 _data_type = data_type;
310 _data_layout = data_layout;
Giorgio Arena44f55722019-07-12 14:49:49 +0100311
Giorgio Arena68e29da2021-02-08 16:31:10 +0000312 _input_shape = TensorShape(width, height, channel, batch);
313 _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
314 _biases_shape = TensorShape(_weights_shape.z());
315
Giorgio Arena44f55722019-07-12 14:49:49 +0100316 if(padding_valid)
317 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100318 _conv_info = PadStrideInfo(stride.width, stride.height);
Giorgio Arena44f55722019-07-12 14:49:49 +0100319 }
320 else
321 {
Giorgio Arena68e29da2021-02-08 16:31:10 +0000322 _conv_info = calculate_same_pad(_input_shape, _weights_shape, PadStrideInfo(stride.width, stride.height), DataLayout::NCHW, _dilation);
323 }
324 }
325
326 void configure_target()
327 {
328 TensorShape input_shape = _input_shape;
329 TensorShape weights_shape = _weights_shape;
330
331 if(_data_layout == DataLayout::NHWC)
332 {
333 permute(input_shape, PermutationVector(2U, 0U, 1U));
334 permute(weights_shape, PermutationVector(2U, 0U, 1U));
Giorgio Arena44f55722019-07-12 14:49:49 +0100335 }
336
Giorgio Arena68e29da2021-02-08 16:31:10 +0000337 // Create tensors
338 _src = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
339 _weights = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
340 _biases = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
341 _target = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
342
Gian Marco Iodice5e281812021-07-06 13:19:41 +0100343 add_padding_x({ &_src, &_biases, &_target }, _data_layout);
344 add_padding_x({ &_weights }, _data_layout, true);
Gian Marco Iodice5e281812021-07-06 13:19:41 +0100345
Giorgio Arena68e29da2021-02-08 16:31:10 +0000346 // Create Depthwise Convolution configure function
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100347 const ConvolutionInfo info
348 {
349 _conv_info, _depth_multiplier, ActivationLayerInfo(), _dilation
350 };
351 _dwc.configure(_src.info(), _weights.info(), _biases.info(), _target.info(), info);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000352
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100353 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
354 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
355 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
356 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000357 }
358
359 void allocate_and_run_target()
360 {
361 // Allocate tensors
362 _src.allocator()->allocate();
363 _weights.allocator()->allocate();
364 _biases.allocator()->allocate();
365 _target.allocator()->allocate();
366
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100367 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
368 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
369 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
370 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000371
372 // Fill tensors
373 fill(AccessorType(_src), 0);
374 fill(AccessorType(_weights), 1);
375 fill(AccessorType(_biases), 2);
376
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100377 arm_compute::ITensorPack pack;
378 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_0, &_src);
379 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_1, &_weights);
380 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_2, &_biases);
381 pack.add_tensor(arm_compute::TensorType::ACL_DST, &_target);
382
Giorgio Arena68e29da2021-02-08 16:31:10 +0000383 // Compute function
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100384 _dwc.run(pack);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000385 }
386
387 void compute_reference()
388 {
389 SimpleTensor<T> src{ _input_shape, _data_type };
390 SimpleTensor<T> weights{ _weights_shape, _data_type };
391 SimpleTensor<T> biases{ _biases_shape, _data_type };
392
393 fill(src, 0);
394 fill(weights, 1);
395 fill(biases, 2);
396
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100397 const ConvolutionInfo info{ _conv_info, _depth_multiplier, ActivationLayerInfo(), _dilation };
398 const TensorShape dst_shape = compute_depthwise_convolution_shape(TensorInfo(_input_shape, 1, _data_type), TensorInfo(_weights_shape, 1, _data_type), info);
399 _reference = reference::depthwise_convolution(src, weights, biases, dst_shape, _conv_info, _depth_multiplier, _dilation);
Giorgio Arena44f55722019-07-12 14:49:49 +0100400 }
401
402protected:
403 template <typename U>
404 void fill(U &&tensor, int i)
405 {
406 switch(tensor.data_type())
407 {
408 case DataType::F32:
409 {
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000410 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Giorgio Arena44f55722019-07-12 14:49:49 +0100411 library->fill(tensor, distribution, i);
412 break;
413 }
414 default:
415 library->fill_tensor_uniform(tensor, i);
416 }
417 }
418
Giorgio Arena44f55722019-07-12 14:49:49 +0100419 TensorType _target{};
420 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000421
422 TensorType _src{};
423 TensorType _weights{};
424 TensorType _biases{};
425 FunctionType _dwc{};
426
427 TensorShape _input_shape{};
428 TensorShape _weights_shape{};
429 TensorShape _biases_shape{};
430 DataType _data_type{};
431 DataLayout _data_layout{};
432 PadStrideInfo _conv_info{};
433 Size2D _dilation{};
434 unsigned int _depth_multiplier{};
Giorgio Arena44f55722019-07-12 14:49:49 +0100435};
436
SiCongLibc4e3112021-06-29 13:18:30 +0100437template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool in_place = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100438class DepthwiseConvolutionLayerNativeConfigurableValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100439{
440public:
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100441 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 +0100442 DataLayout data_layout, const ActivationLayerInfo &act_info, unsigned int n0, bool export_to_cl_image)
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100443 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100444 _dilation = dilation;
445 _depth_multiplier = depth_multiplier;
446 _data_type = data_type;
447 _data_layout = data_layout;
448 _act_info = act_info;
449 _n0 = n0;
450 _export_to_cl_image = export_to_cl_image;
451 _in_place = in_place;
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100452
Giorgio Arena68e29da2021-02-08 16:31:10 +0000453 _input_shape = TensorShape(width, height, channel, batch);
454 _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
455 _biases_shape = TensorShape(_weights_shape.z());
456
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100457 if(padding_valid)
458 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100459 _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 +0100460 }
461 else
462 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100463 _conv_info = PadStrideInfo(stride.width, stride.height);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000464 }
465 }
466
467 void configure_target()
468 {
Sheri Zhang9d6ddfc2021-09-15 13:10:18 +0100469#if defined(ARM_COMPUTE_OPENCL_ENABLED)
470 if(_export_to_cl_image)
471 {
472 _validate_output &= image2d_from_buffer_supported(CLKernelLibrary::get().get_device());
473 _validate_output &= (get_cl_image_pitch_alignment(CLKernelLibrary::get().get_device()) != 0);
474 }
475#endif // ARM_COMPUTE_OPENCL_ENABLED
476
477 if(!_validate_output)
478 {
479 return;
480 }
481
Giorgio Arena68e29da2021-02-08 16:31:10 +0000482 TensorShape input_shape = _input_shape;
483 TensorShape weights_shape = _weights_shape;
484
485 if(_data_layout == DataLayout::NHWC)
486 {
487 permute(input_shape, PermutationVector(2U, 0U, 1U));
488 permute(weights_shape, PermutationVector(2U, 0U, 1U));
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100489 }
490
Giorgio Arena68e29da2021-02-08 16:31:10 +0000491 // Create tensors
SiCongLibc4e3112021-06-29 13:18:30 +0100492 _src = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
493 _weights = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
494 _biases = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
495 TensorType *target_to_use = nullptr;
496 if(!_in_place)
497 {
498 _target = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
499 target_to_use = &_target;
500 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000501
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100502 DWCComputeKernelInfo dwc_info;
503 dwc_info.n0 = _n0;
504 dwc_info.m0 = _conv_info.stride().first == 1 && _dilation.x() == 1 ? 8 : 1;
Gian Marco Iodicead9a7ed2022-09-16 14:14:21 +0100505 dwc_info.export_input_to_cl_image = false;
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100506 dwc_info.export_weights_to_cl_image = _export_to_cl_image;
Giorgio Arena68e29da2021-02-08 16:31:10 +0000507
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100508 const ConvolutionInfo conv_kernel_info
509 {
510 _conv_info, _depth_multiplier, _act_info, _dilation
511 };
Giorgio Arena68e29da2021-02-08 16:31:10 +0000512
Gian Marco Iodice5e281812021-07-06 13:19:41 +0100513 add_padding_x({ &_src, &_biases, &_target }, _data_layout);
514 add_padding_x({ &_weights }, _data_layout, _export_to_cl_image); // Don't add left padding if cl image will be used
515
Giorgio Arena68e29da2021-02-08 16:31:10 +0000516 // Create Depthwise Convolution configure function
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100517 _dwc.configure(&_src, &_weights, &_biases, target_to_use, dwc_info, conv_kernel_info);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000518
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100519 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
520 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
521 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
522 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000523 }
524
525 void allocate_and_run_target()
526 {
Sheri Zhang9d6ddfc2021-09-15 13:10:18 +0100527 if(!_validate_output)
528 {
529 return;
530 }
531
Giorgio Arena68e29da2021-02-08 16:31:10 +0000532 // Allocate tensors
533 _src.allocator()->allocate();
534 _weights.allocator()->allocate();
535 _biases.allocator()->allocate();
Giorgio Arena68e29da2021-02-08 16:31:10 +0000536
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100537 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
538 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
539 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
SiCongLibc4e3112021-06-29 13:18:30 +0100540 if(!_in_place)
541 {
542 _target.allocator()->allocate();
543 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
544 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000545
546 // Fill tensors
547 fill(AccessorType(_src), 0);
548 fill(AccessorType(_weights), 1);
549 fill(AccessorType(_biases), 2);
550
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000551 // Test Multi DataLayout graph cases, when the data layout changes after configure
552 _src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
SiCongLibc4e3112021-06-29 13:18:30 +0100553 if(!_in_place)
554 {
555 _target.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
556 }
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000557
Giorgio Arena68e29da2021-02-08 16:31:10 +0000558 // Compute function
Sheri Zhang9d6ddfc2021-09-15 13:10:18 +0100559 _dwc.run();
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000560
561 // Reinstating original data layout for the test suite to properly check the values
SiCongLibc4e3112021-06-29 13:18:30 +0100562 if(!_in_place)
563 {
564 _target.info()->set_data_layout(_data_layout);
565 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000566 }
567
568 void compute_reference()
569 {
Sheri Zhang9d6ddfc2021-09-15 13:10:18 +0100570 if(!_validate_output)
571 {
572 return;
573 }
574
Giorgio Arena68e29da2021-02-08 16:31:10 +0000575 SimpleTensor<T> src{ _input_shape, _data_type };
576 SimpleTensor<T> weights{ _weights_shape, _data_type };
577 SimpleTensor<T> biases{ _biases_shape, _data_type };
578
579 fill(src, 0);
580 fill(weights, 1);
581 fill(biases, 2);
582
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100583 const ConvolutionInfo info{ _conv_info, _depth_multiplier, _act_info, _dilation };
584 const TensorShape dst_shape = compute_depthwise_convolution_shape(TensorInfo(_input_shape, 1, _data_type), TensorInfo(_weights_shape, 1, _data_type), info);
Sheri Zhang9d6ddfc2021-09-15 13:10:18 +0100585 _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 +0100586 }
587
588protected:
589 template <typename U>
590 void fill(U &&tensor, int i)
591 {
592 switch(tensor.data_type())
593 {
594 case DataType::F32:
595 {
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000596 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100597 library->fill(tensor, distribution, i);
598 break;
599 }
600 case DataType::F16:
601 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000602 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100603 library->fill(tensor, distribution, i);
604 break;
605 }
606 default:
607 library->fill_tensor_uniform(tensor, i);
608 }
609 }
610
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100611 TensorType _target{};
612 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000613
614 TensorType _src{};
615 TensorType _weights{};
616 TensorType _biases{};
617 FunctionType _dwc{};
618
619 TensorShape _input_shape{};
620 TensorShape _weights_shape{};
621 TensorShape _biases_shape{};
622 DataType _data_type{};
623 DataLayout _data_layout{};
624 PadStrideInfo _conv_info{};
625 ActivationLayerInfo _act_info{};
626 Size2D _dilation{};
627 unsigned int _depth_multiplier{};
628 unsigned int _n0{};
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100629 bool _export_to_cl_image{};
630 bool _validate_output{ true };
SiCongLibc4e3112021-06-29 13:18:30 +0100631 bool _in_place{ false };
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100632};
633
SiCongLibc4e3112021-06-29 13:18:30 +0100634template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false, bool in_place = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100635class DepthwiseConvolutionLayerValidationQuantizedFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700636{
637public:
Pablo Telloa28aebc2019-06-03 14:59:48 +0100638 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type,
639 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700640 {
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100641 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier, data_type,
642 data_type, input_quantization_info, input_quantization_info, output_quantization_info,
SiCongLibc4e3112021-06-29 13:18:30 +0100643 data_layout, act_info, mixed_layout, in_place);
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100644 }
645};
646
SiCongLibc4e3112021-06-29 13:18:30 +0100647template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW, bool in_place = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100648class DepthwiseConvolutionLayerValidationQuantizedPerChannelFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>
649{
650public:
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100651 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 +0100652 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100653 {
Giorgio Arenad93e2632019-10-15 11:09:33 +0100654 const float out_scale = output_quantization_info.uniform().scale;
655 const float in_scale = input_quantization_info.uniform().scale;
656
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000657 std::vector<float> weights_scales{};
658 std::mt19937 gen(library->seed());
659 std::uniform_real_distribution<float> dis(0.01f, out_scale / in_scale);
Giorgio Arenad93e2632019-10-15 11:09:33 +0100660 for(size_t i = 0; i < in_shape.z() * depth_multiplier; ++i)
661 {
662 weights_scales.push_back(dis(gen));
663 }
664
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100665 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
666 input_data_type, weights_data_type,
Giorgio Arenad93e2632019-10-15 11:09:33 +0100667 input_quantization_info, QuantizationInfo(weights_scales), output_quantization_info,
SiCongLibc4e3112021-06-29 13:18:30 +0100668 data_layout, act_info, false, in_place);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700669 }
Giorgio Arena93a690e2017-08-01 16:09:33 +0100670};
671} // namespace validation
672} // namespace test
673} // namespace arm_compute
674#endif /* ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE */