blob: a08080a665d8807e56455579927c21bcc28d8cec [file] [log] [blame]
Giorgio Arena93a690e2017-08-01 16:09:33 +01001/*
Pablo Tello29cab362022-03-10 17:05:34 +00002 * Copyright (c) 2017-2022 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,
Milos Puzovica7077e92022-10-28 16:49:15 +010062 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 +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;
Milos Puzovica7077e92022-10-28 16:49:15 +010078 _run_twice = run_twice;
Giorgio Arena76572242018-04-04 17:44:26 +010079
Giorgio Arena68e29da2021-02-08 16:31:10 +000080 _bias_data_type = is_data_type_quantized(_input_data_type) ? DataType::S32 : _input_data_type;
Giorgio Arena76572242018-04-04 17:44:26 +010081
Giorgio Arena68e29da2021-02-08 16:31:10 +000082 _weights_shape = TensorShape(kernel_size.width, kernel_size.height);
Giorgio Arena76572242018-04-04 17:44:26 +010083
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +010084 const TensorInfo in_info(_input_shape, 1, _input_data_type);
85 const TensorInfo we_info(_weights_shape, 1, _weights_data_type);
86 const ConvolutionInfo info{ _pad_stride_info, _depth_multiplier, _act_info, _dilation };
87 _output_shape = compute_depthwise_convolution_shape(in_info, we_info, info);
Dmitry Savenkod7295b72017-11-20 22:00:08 +070088
Giorgio Arena68e29da2021-02-08 16:31:10 +000089 _weights_shape.set(2, _output_shape.z());
90 _biases_shape = TensorShape(_weights_shape[2]);
91 }
92
93 void configure_target()
94 {
95 TensorShape input_shape = _input_shape;
96 TensorShape weights_shape = _weights_shape;
97 TensorShape output_shape = _output_shape;
98
99 if(_data_layout == DataLayout::NHWC)
100 {
101 permute(input_shape, PermutationVector(2U, 0U, 1U));
102 permute(weights_shape, PermutationVector(2U, 0U, 1U));
103 permute(output_shape, PermutationVector(2U, 0U, 1U));
104 }
105
106 // Create tensors
SiCongLibc4e3112021-06-29 13:18:30 +0100107 _src = create_tensor<TensorType>(input_shape, _input_data_type, 1, _input_quantization_info, _data_layout);
108 _weights = create_tensor<TensorType>(weights_shape, _weights_data_type, 1, _weights_quantization_info, _data_layout);
Milos Puzovica7077e92022-10-28 16:49:15 +0100109 if(_run_twice) {
110 _weights.info()->set_are_values_constant(false);
111 }
SiCongLibc4e3112021-06-29 13:18:30 +0100112 _biases = create_tensor<TensorType>(_biases_shape, _bias_data_type, 1, _input_quantization_info, _data_layout);
113 TensorType *target_to_use = nullptr;
114 if(!_in_place)
115 {
116 _target = create_tensor<TensorType>(output_shape, _input_data_type, 1, _output_quantization_info, _data_layout);
117 target_to_use = &_target;
118 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000119
Gian Marco Iodice5e281812021-07-06 13:19:41 +0100120 add_padding_x({ &_src, &_biases }, _data_layout);
121 add_padding_x({ &_weights }, _data_layout, true);
122 if(!_in_place)
123 {
124 add_padding_x({ &_target }, _data_layout);
125 }
126
Giorgio Arena68e29da2021-02-08 16:31:10 +0000127 // Create Depthwise Convolution configure function
SiCongLibc4e3112021-06-29 13:18:30 +0100128 _dwc.configure(&_src, &_weights, &_biases, target_to_use, _pad_stride_info, _depth_multiplier, _act_info, _dilation);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000129
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100130 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
131 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
132 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
133 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000134 }
135
136 void allocate_and_run_target()
137 {
138 // Allocate tensors
139 _src.allocator()->allocate();
140 _weights.allocator()->allocate();
141 _biases.allocator()->allocate();
Giorgio Arena68e29da2021-02-08 16:31:10 +0000142
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100143 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
144 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
145 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
SiCongLibc4e3112021-06-29 13:18:30 +0100146
147 if(!_in_place)
148 {
149 _target.allocator()->allocate();
150 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
151 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000152
153 // Fill tensors
154 fill(AccessorType(_src), 0);
155 fill(AccessorType(_weights), 1);
156 fill(AccessorType(_biases), 2);
Giorgio Arena63825e82021-03-25 14:54:50 +0000157
Milos Puzovica7077e92022-10-28 16:49:15 +0100158 // Run with variable input
159 if(_run_twice) {
160 _dwc.run();
161
162 // Fill tensors with a new seed
163 fill(AccessorType(_src), 3);
164 fill(AccessorType(_weights), 4);
165 fill(AccessorType(_biases), 5);
166 }
167
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000168 if(_mixed_layout)
169 {
170 mix_layout(_dwc, _src, _target);
171 }
172 else
173 {
174 // Compute function
175 _dwc.run();
176 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000177 }
178
179 void compute_reference()
180 {
181 SimpleTensor<T> src{ _input_shape, _input_data_type, 1, _input_quantization_info };
182 SimpleTensor<TW> weights{ _weights_shape, _weights_data_type, 1, _weights_quantization_info };
183 SimpleTensor<TBias> biases{ _biases_shape, _bias_data_type, 1, _input_quantization_info };
184
185 fill(src, 0);
186 fill(weights, 1);
187 fill(biases, 2);
Milos Puzovica7077e92022-10-28 16:49:15 +0100188 if(_run_twice) {
189 SimpleTensor<T> depth_out = reference::depthwise_convolution(src, weights, biases, _output_shape, _pad_stride_info, _depth_multiplier, _dilation, _output_quantization_info);
190 if(_act_info.enabled()) {
191 reference::activation_layer<T>(depth_out, _act_info);
192 }
193
194 fill(src, 3);
195 fill(weights, 4);
196 fill(biases, 5);
197 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000198
199 SimpleTensor<T> depth_out = reference::depthwise_convolution(src, weights, biases, _output_shape, _pad_stride_info, _depth_multiplier, _dilation, _output_quantization_info);
200 _reference = (_act_info.enabled()) ? reference::activation_layer<T>(depth_out, _act_info) : depth_out;
Giorgio Arena93a690e2017-08-01 16:09:33 +0100201 }
202
203protected:
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000204 void mix_layout(FunctionType &layer, TensorType &src, TensorType &dst)
205 {
SiCongLibc4e3112021-06-29 13:18:30 +0100206 ARM_COMPUTE_ERROR_ON(_in_place);
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000207 // Test Multi DataLayout graph cases, when the data layout changes after configure
208 src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
209 dst.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
210
211 // Compute Convolution function
212 layer.run();
213
214 // Reinstating original data layout for the test suite to properly check the values
215 src.info()->set_data_layout(_data_layout);
216 dst.info()->set_data_layout(_data_layout);
217 }
218
Giorgio Arena93a690e2017-08-01 16:09:33 +0100219 template <typename U>
220 void fill(U &&tensor, int i)
221 {
222 switch(tensor.data_type())
223 {
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700224 case DataType::QASYMM8:
225 {
Pablo Tello29cab362022-03-10 17:05:34 +0000226 std::uniform_int_distribution<uint32_t> distribution(0, 15);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700227 library->fill(tensor, distribution, i);
228 break;
229 }
Michele Di Giorgio4cd4cde2020-01-06 14:07:44 +0000230 case DataType::QASYMM8_SIGNED:
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100231 case DataType::QSYMM8_PER_CHANNEL:
232 {
Pablo Tello29cab362022-03-10 17:05:34 +0000233 std::uniform_int_distribution<int32_t> distribution(-10, 10);
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100234 library->fill(tensor, distribution, i);
235 break;
236 }
Frank Lei8cdfdb82018-01-02 16:49:33 +0800237 case DataType::F16:
Giorgio Arena93a690e2017-08-01 16:09:33 +0100238 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000239 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000240 library->fill(tensor, distribution, i);
241 break;
242 }
243 case DataType::F32:
244 {
245 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Giorgio Arena93a690e2017-08-01 16:09:33 +0100246 library->fill(tensor, distribution, i);
247 break;
248 }
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700249 case DataType::S32:
250 {
Georgios Pinitasf72f9362018-01-12 16:29:45 +0000251 std::uniform_int_distribution<int32_t> distribution(-100, 100);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700252 library->fill(tensor, distribution, i);
253 break;
254 }
Giorgio Arena93a690e2017-08-01 16:09:33 +0100255 default:
256 library->fill_tensor_uniform(tensor, i);
257 }
258 }
259
Georgios Pinitasddec4d62019-07-10 19:23:02 +0100260 TensorType _target{};
261 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000262
263 TensorType _src{};
264 TensorType _weights{};
265 TensorType _biases{};
266 FunctionType _dwc{};
267
268 TensorShape _input_shape{};
269 TensorShape _weights_shape{};
270 TensorShape _biases_shape{};
271 TensorShape _output_shape{};
272 DataType _input_data_type{};
273 DataType _weights_data_type{};
274 DataType _bias_data_type{};
275 QuantizationInfo _input_quantization_info{};
276 QuantizationInfo _weights_quantization_info{};
277 QuantizationInfo _output_quantization_info{};
278 DataLayout _data_layout{};
279 PadStrideInfo _pad_stride_info{};
280 ActivationLayerInfo _act_info{};
281 unsigned int _depth_multiplier{};
282 Size2D _dilation{};
Giorgio Arena63825e82021-03-25 14:54:50 +0000283 bool _mixed_layout{ false };
SiCongLibc4e3112021-06-29 13:18:30 +0100284 bool _in_place{ false };
Milos Puzovica7077e92022-10-28 16:49:15 +0100285 bool _run_twice{ false };
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700286};
287
Milos Puzovica7077e92022-10-28 16:49:15 +0100288template <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 +0100289class DepthwiseConvolutionLayerValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700290{
291public:
292 template <typename...>
Manuel Bottinia788c2f2019-04-08 13:18:00 +0100293 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type, DataLayout data_layout,
294 ActivationLayerInfo act_info)
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700295 {
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100296 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
297 data_type, data_type, QuantizationInfo(), QuantizationInfo(), QuantizationInfo(),
Milos Puzovica7077e92022-10-28 16:49:15 +0100298 data_layout, act_info, mixed_layout, in_place, run_twice);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700299 }
300};
301
302template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100303class DepthwiseConvolutionLayerNativeValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Giorgio Arena44f55722019-07-12 14:49:49 +0100304{
305public:
306 template <typename...>
307 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,
308 DataLayout data_layout)
309 {
Giorgio Arena68e29da2021-02-08 16:31:10 +0000310 _dilation = dilation;
311 _depth_multiplier = depth_multiplier;
312 _data_type = data_type;
313 _data_layout = data_layout;
Giorgio Arena44f55722019-07-12 14:49:49 +0100314
Giorgio Arena68e29da2021-02-08 16:31:10 +0000315 _input_shape = TensorShape(width, height, channel, batch);
316 _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
317 _biases_shape = TensorShape(_weights_shape.z());
318
Giorgio Arena44f55722019-07-12 14:49:49 +0100319 if(padding_valid)
320 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100321 _conv_info = PadStrideInfo(stride.width, stride.height);
Giorgio Arena44f55722019-07-12 14:49:49 +0100322 }
323 else
324 {
Giorgio Arena68e29da2021-02-08 16:31:10 +0000325 _conv_info = calculate_same_pad(_input_shape, _weights_shape, PadStrideInfo(stride.width, stride.height), DataLayout::NCHW, _dilation);
326 }
327 }
328
329 void configure_target()
330 {
331 TensorShape input_shape = _input_shape;
332 TensorShape weights_shape = _weights_shape;
333
334 if(_data_layout == DataLayout::NHWC)
335 {
336 permute(input_shape, PermutationVector(2U, 0U, 1U));
337 permute(weights_shape, PermutationVector(2U, 0U, 1U));
Giorgio Arena44f55722019-07-12 14:49:49 +0100338 }
339
Giorgio Arena68e29da2021-02-08 16:31:10 +0000340 // Create tensors
341 _src = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
342 _weights = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
343 _biases = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
344 _target = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
345
Gian Marco Iodice5e281812021-07-06 13:19:41 +0100346 add_padding_x({ &_src, &_biases, &_target }, _data_layout);
347 add_padding_x({ &_weights }, _data_layout, true);
348 add_padding_y({ &_src, &_target }, _data_layout);
349
Giorgio Arena68e29da2021-02-08 16:31:10 +0000350 // Create Depthwise Convolution configure function
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100351 const ConvolutionInfo info
352 {
353 _conv_info, _depth_multiplier, ActivationLayerInfo(), _dilation
354 };
355 _dwc.configure(_src.info(), _weights.info(), _biases.info(), _target.info(), info);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000356
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100357 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
358 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
359 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
360 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000361 }
362
363 void allocate_and_run_target()
364 {
365 // Allocate tensors
366 _src.allocator()->allocate();
367 _weights.allocator()->allocate();
368 _biases.allocator()->allocate();
369 _target.allocator()->allocate();
370
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100371 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
372 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
373 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
374 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000375
376 // Fill tensors
377 fill(AccessorType(_src), 0);
378 fill(AccessorType(_weights), 1);
379 fill(AccessorType(_biases), 2);
380
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100381 arm_compute::ITensorPack pack;
382 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_0, &_src);
383 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_1, &_weights);
384 pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_2, &_biases);
385 pack.add_tensor(arm_compute::TensorType::ACL_DST, &_target);
386
Giorgio Arena68e29da2021-02-08 16:31:10 +0000387 // Compute function
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100388 _dwc.run(pack);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000389 }
390
391 void compute_reference()
392 {
393 SimpleTensor<T> src{ _input_shape, _data_type };
394 SimpleTensor<T> weights{ _weights_shape, _data_type };
395 SimpleTensor<T> biases{ _biases_shape, _data_type };
396
397 fill(src, 0);
398 fill(weights, 1);
399 fill(biases, 2);
400
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100401 const ConvolutionInfo info{ _conv_info, _depth_multiplier, ActivationLayerInfo(), _dilation };
402 const TensorShape dst_shape = compute_depthwise_convolution_shape(TensorInfo(_input_shape, 1, _data_type), TensorInfo(_weights_shape, 1, _data_type), info);
403 _reference = reference::depthwise_convolution(src, weights, biases, dst_shape, _conv_info, _depth_multiplier, _dilation);
Giorgio Arena44f55722019-07-12 14:49:49 +0100404 }
405
406protected:
407 template <typename U>
408 void fill(U &&tensor, int i)
409 {
410 switch(tensor.data_type())
411 {
412 case DataType::F32:
413 {
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000414 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Giorgio Arena44f55722019-07-12 14:49:49 +0100415 library->fill(tensor, distribution, i);
416 break;
417 }
418 default:
419 library->fill_tensor_uniform(tensor, i);
420 }
421 }
422
Giorgio Arena44f55722019-07-12 14:49:49 +0100423 TensorType _target{};
424 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000425
426 TensorType _src{};
427 TensorType _weights{};
428 TensorType _biases{};
429 FunctionType _dwc{};
430
431 TensorShape _input_shape{};
432 TensorShape _weights_shape{};
433 TensorShape _biases_shape{};
434 DataType _data_type{};
435 DataLayout _data_layout{};
436 PadStrideInfo _conv_info{};
437 Size2D _dilation{};
438 unsigned int _depth_multiplier{};
Giorgio Arena44f55722019-07-12 14:49:49 +0100439};
440
SiCongLibc4e3112021-06-29 13:18:30 +0100441template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool in_place = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100442class DepthwiseConvolutionLayerNativeConfigurableValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100443{
444public:
445 template <typename...>
446 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 +0100447 DataLayout data_layout, const ActivationLayerInfo &act_info, unsigned int n0, bool export_to_cl_image)
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100448 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100449 _dilation = dilation;
450 _depth_multiplier = depth_multiplier;
451 _data_type = data_type;
452 _data_layout = data_layout;
453 _act_info = act_info;
454 _n0 = n0;
455 _export_to_cl_image = export_to_cl_image;
456 _in_place = in_place;
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100457
Giorgio Arena68e29da2021-02-08 16:31:10 +0000458 _input_shape = TensorShape(width, height, channel, batch);
459 _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
460 _biases_shape = TensorShape(_weights_shape.z());
461
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100462 if(padding_valid)
463 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100464 _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 +0100465 }
466 else
467 {
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100468 _conv_info = PadStrideInfo(stride.width, stride.height);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000469 }
470 }
471
472 void configure_target()
473 {
Sheri Zhang9d6ddfc2021-09-15 13:10:18 +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 if(!_validate_output)
483 {
484 return;
485 }
486
Giorgio Arena68e29da2021-02-08 16:31:10 +0000487 TensorShape input_shape = _input_shape;
488 TensorShape weights_shape = _weights_shape;
489
490 if(_data_layout == DataLayout::NHWC)
491 {
492 permute(input_shape, PermutationVector(2U, 0U, 1U));
493 permute(weights_shape, PermutationVector(2U, 0U, 1U));
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100494 }
495
Giorgio Arena68e29da2021-02-08 16:31:10 +0000496 // Create tensors
SiCongLibc4e3112021-06-29 13:18:30 +0100497 _src = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
498 _weights = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
499 _biases = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
500 TensorType *target_to_use = nullptr;
501 if(!_in_place)
502 {
503 _target = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
504 target_to_use = &_target;
505 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000506
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100507 DWCComputeKernelInfo dwc_info;
508 dwc_info.n0 = _n0;
509 dwc_info.m0 = _conv_info.stride().first == 1 && _dilation.x() == 1 ? 8 : 1;
Gian Marco Iodicead9a7ed2022-09-16 14:14:21 +0100510 dwc_info.export_input_to_cl_image = false;
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100511 dwc_info.export_weights_to_cl_image = _export_to_cl_image;
Giorgio Arena68e29da2021-02-08 16:31:10 +0000512
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100513 const ConvolutionInfo conv_kernel_info
514 {
515 _conv_info, _depth_multiplier, _act_info, _dilation
516 };
Giorgio Arena68e29da2021-02-08 16:31:10 +0000517
Gian Marco Iodice5e281812021-07-06 13:19:41 +0100518 add_padding_x({ &_src, &_biases, &_target }, _data_layout);
519 add_padding_x({ &_weights }, _data_layout, _export_to_cl_image); // Don't add left padding if cl image will be used
520
Giorgio Arena68e29da2021-02-08 16:31:10 +0000521 // Create Depthwise Convolution configure function
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100522 _dwc.configure(&_src, &_weights, &_biases, target_to_use, dwc_info, conv_kernel_info);
Giorgio Arena68e29da2021-02-08 16:31:10 +0000523
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100524 ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
525 ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
526 ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
527 ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
Giorgio Arena68e29da2021-02-08 16:31:10 +0000528 }
529
530 void allocate_and_run_target()
531 {
Sheri Zhang9d6ddfc2021-09-15 13:10:18 +0100532 if(!_validate_output)
533 {
534 return;
535 }
536
Giorgio Arena68e29da2021-02-08 16:31:10 +0000537 // Allocate tensors
538 _src.allocator()->allocate();
539 _weights.allocator()->allocate();
540 _biases.allocator()->allocate();
Giorgio Arena68e29da2021-02-08 16:31:10 +0000541
Michele Di Giorgio4fc10b32021-04-30 18:30:41 +0100542 ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
543 ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
544 ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
SiCongLibc4e3112021-06-29 13:18:30 +0100545 if(!_in_place)
546 {
547 _target.allocator()->allocate();
548 ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
549 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000550
551 // Fill tensors
552 fill(AccessorType(_src), 0);
553 fill(AccessorType(_weights), 1);
554 fill(AccessorType(_biases), 2);
555
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000556 // Test Multi DataLayout graph cases, when the data layout changes after configure
557 _src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
SiCongLibc4e3112021-06-29 13:18:30 +0100558 if(!_in_place)
559 {
560 _target.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
561 }
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000562
Giorgio Arena68e29da2021-02-08 16:31:10 +0000563 // Compute function
Sheri Zhang9d6ddfc2021-09-15 13:10:18 +0100564 _dwc.run();
Manuel Bottinica62c6f2021-03-23 11:50:34 +0000565
566 // Reinstating original data layout for the test suite to properly check the values
SiCongLibc4e3112021-06-29 13:18:30 +0100567 if(!_in_place)
568 {
569 _target.info()->set_data_layout(_data_layout);
570 }
Giorgio Arena68e29da2021-02-08 16:31:10 +0000571 }
572
573 void compute_reference()
574 {
Sheri Zhang9d6ddfc2021-09-15 13:10:18 +0100575 if(!_validate_output)
576 {
577 return;
578 }
579
Giorgio Arena68e29da2021-02-08 16:31:10 +0000580 SimpleTensor<T> src{ _input_shape, _data_type };
581 SimpleTensor<T> weights{ _weights_shape, _data_type };
582 SimpleTensor<T> biases{ _biases_shape, _data_type };
583
584 fill(src, 0);
585 fill(weights, 1);
586 fill(biases, 2);
587
Michalis Spyrou60c3b0e2021-04-08 12:02:58 +0100588 const ConvolutionInfo info{ _conv_info, _depth_multiplier, _act_info, _dilation };
589 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 +0100590 _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 +0100591 }
592
593protected:
594 template <typename U>
595 void fill(U &&tensor, int i)
596 {
597 switch(tensor.data_type())
598 {
599 case DataType::F32:
600 {
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000601 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100602 library->fill(tensor, distribution, i);
603 break;
604 }
605 case DataType::F16:
606 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000607 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100608 library->fill(tensor, distribution, i);
609 break;
610 }
611 default:
612 library->fill_tensor_uniform(tensor, i);
613 }
614 }
615
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100616 TensorType _target{};
617 SimpleTensor<T> _reference{};
Giorgio Arena68e29da2021-02-08 16:31:10 +0000618
619 TensorType _src{};
620 TensorType _weights{};
621 TensorType _biases{};
622 FunctionType _dwc{};
623
624 TensorShape _input_shape{};
625 TensorShape _weights_shape{};
626 TensorShape _biases_shape{};
627 DataType _data_type{};
628 DataLayout _data_layout{};
629 PadStrideInfo _conv_info{};
630 ActivationLayerInfo _act_info{};
631 Size2D _dilation{};
632 unsigned int _depth_multiplier{};
633 unsigned int _n0{};
Gian Marco Iodice8155c022021-04-16 15:08:59 +0100634 bool _export_to_cl_image{};
635 bool _validate_output{ true };
SiCongLibc4e3112021-06-29 13:18:30 +0100636 bool _in_place{ false };
Gian Marco Iodice9285adb2019-09-05 16:10:27 +0100637};
638
SiCongLibc4e3112021-06-29 13:18:30 +0100639template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false, bool in_place = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100640class DepthwiseConvolutionLayerValidationQuantizedFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700641{
642public:
643 template <typename...>
Pablo Telloa28aebc2019-06-03 14:59:48 +0100644 void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type,
645 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700646 {
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100647 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier, data_type,
648 data_type, input_quantization_info, input_quantization_info, output_quantization_info,
SiCongLibc4e3112021-06-29 13:18:30 +0100649 data_layout, act_info, mixed_layout, in_place);
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100650 }
651};
652
SiCongLibc4e3112021-06-29 13:18:30 +0100653template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW, bool in_place = false>
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100654class DepthwiseConvolutionLayerValidationQuantizedPerChannelFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>
655{
656public:
657 template <typename...>
658 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 +0100659 QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100660 {
Giorgio Arenad93e2632019-10-15 11:09:33 +0100661 const float out_scale = output_quantization_info.uniform().scale;
662 const float in_scale = input_quantization_info.uniform().scale;
663
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000664 std::vector<float> weights_scales{};
665 std::mt19937 gen(library->seed());
666 std::uniform_real_distribution<float> dis(0.01f, out_scale / in_scale);
Giorgio Arenad93e2632019-10-15 11:09:33 +0100667 for(size_t i = 0; i < in_shape.z() * depth_multiplier; ++i)
668 {
669 weights_scales.push_back(dis(gen));
670 }
671
Michele Di Giorgio633d30b2019-10-08 17:17:18 +0100672 DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
673 input_data_type, weights_data_type,
Giorgio Arenad93e2632019-10-15 11:09:33 +0100674 input_quantization_info, QuantizationInfo(weights_scales), output_quantization_info,
SiCongLibc4e3112021-06-29 13:18:30 +0100675 data_layout, act_info, false, in_place);
Dmitry Savenkod7295b72017-11-20 22:00:08 +0700676 }
Giorgio Arena93a690e2017-08-01 16:09:33 +0100677};
678} // namespace validation
679} // namespace test
680} // namespace arm_compute
681#endif /* ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE */