xref: /aosp_15_r20/external/ComputeLibrary/tests/validation/fixtures/DepthwiseConvolutionLayerFixture.h (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1*c217d954SCole Faust /*
2*c217d954SCole Faust  * Copyright (c) 2017-2022 Arm Limited.
3*c217d954SCole Faust  *
4*c217d954SCole Faust  * SPDX-License-Identifier: MIT
5*c217d954SCole Faust  *
6*c217d954SCole Faust  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*c217d954SCole Faust  * of this software and associated documentation files (the "Software"), to
8*c217d954SCole Faust  * deal in the Software without restriction, including without limitation the
9*c217d954SCole Faust  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*c217d954SCole Faust  * sell copies of the Software, and to permit persons to whom the Software is
11*c217d954SCole Faust  * furnished to do so, subject to the following conditions:
12*c217d954SCole Faust  *
13*c217d954SCole Faust  * The above copyright notice and this permission notice shall be included in all
14*c217d954SCole Faust  * copies or substantial portions of the Software.
15*c217d954SCole Faust  *
16*c217d954SCole Faust  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*c217d954SCole Faust  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*c217d954SCole Faust  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*c217d954SCole Faust  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*c217d954SCole Faust  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*c217d954SCole Faust  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*c217d954SCole Faust  * SOFTWARE.
23*c217d954SCole Faust  */
24*c217d954SCole Faust #ifndef ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE
25*c217d954SCole Faust #define ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE
26*c217d954SCole Faust 
27*c217d954SCole Faust #include "arm_compute/core/TensorShape.h"
28*c217d954SCole Faust #include "arm_compute/core/Types.h"
29*c217d954SCole Faust #include "arm_compute/core/utils/misc/ShapeCalculator.h"
30*c217d954SCole Faust #include "tests/AssetsLibrary.h"
31*c217d954SCole Faust #include "tests/Globals.h"
32*c217d954SCole Faust #include "tests/IAccessor.h"
33*c217d954SCole Faust #include "tests/framework/Asserts.h"
34*c217d954SCole Faust #include "tests/framework/Fixture.h"
35*c217d954SCole Faust #include "tests/validation/Helpers.h"
36*c217d954SCole Faust #include "tests/validation/reference/ActivationLayer.h"
37*c217d954SCole Faust #include "tests/validation/reference/DepthwiseConvolutionLayer.h"
38*c217d954SCole Faust 
39*c217d954SCole Faust #include "utils/Utils.h"
40*c217d954SCole Faust 
41*c217d954SCole Faust #include <random>
42*c217d954SCole Faust 
43*c217d954SCole Faust namespace arm_compute
44*c217d954SCole Faust {
45*c217d954SCole Faust namespace test
46*c217d954SCole Faust {
47*c217d954SCole Faust namespace validation
48*c217d954SCole Faust {
49*c217d954SCole Faust using namespace arm_compute::misc::shape_calculator;
50*c217d954SCole Faust 
51*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW>
52*c217d954SCole Faust class DepthwiseConvolutionLayerValidationGenericFixture : public framework::Fixture
53*c217d954SCole Faust {
54*c217d954SCole Faust public:
55*c217d954SCole Faust     using TBias = typename std::conditional < std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value, int32_t, T >::type;
56*c217d954SCole Faust 
57*c217d954SCole Faust public:
58*c217d954SCole Faust     template <typename...>
59*c217d954SCole Faust     void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation,
60*c217d954SCole Faust                unsigned int depth_multiplier, DataType input_data_type, DataType weights_data_type,
61*c217d954SCole Faust                QuantizationInfo input_quantization_info, QuantizationInfo weights_quantization_info, QuantizationInfo output_quantization_info,
62*c217d954SCole Faust                DataLayout data_layout, ActivationLayerInfo act_info, bool mixed_layout = false, bool in_place = false, bool run_twice = false)
63*c217d954SCole Faust     {
64*c217d954SCole Faust         ARM_COMPUTE_ERROR_ON(mixed_layout && in_place);
65*c217d954SCole Faust         _mixed_layout              = mixed_layout;
66*c217d954SCole Faust         _input_shape               = in_shape;
67*c217d954SCole Faust         _input_data_type           = input_data_type;
68*c217d954SCole Faust         _weights_data_type         = weights_data_type;
69*c217d954SCole Faust         _input_quantization_info   = input_quantization_info;
70*c217d954SCole Faust         _weights_quantization_info = weights_quantization_info;
71*c217d954SCole Faust         _output_quantization_info  = output_quantization_info;
72*c217d954SCole Faust         _data_layout               = data_layout;
73*c217d954SCole Faust         _pad_stride_info           = pad_stride_info;
74*c217d954SCole Faust         _act_info                  = act_info;
75*c217d954SCole Faust         _depth_multiplier          = depth_multiplier;
76*c217d954SCole Faust         _dilation                  = dilation;
77*c217d954SCole Faust         _in_place                  = in_place;
78*c217d954SCole Faust         _run_twice                 = run_twice;
79*c217d954SCole Faust 
80*c217d954SCole Faust         _bias_data_type = is_data_type_quantized(_input_data_type) ? DataType::S32 : _input_data_type;
81*c217d954SCole Faust 
82*c217d954SCole Faust         _weights_shape = TensorShape(kernel_size.width, kernel_size.height);
83*c217d954SCole Faust 
84*c217d954SCole Faust         const TensorInfo      in_info(_input_shape, 1, _input_data_type);
85*c217d954SCole Faust         const TensorInfo      we_info(_weights_shape, 1, _weights_data_type);
86*c217d954SCole Faust         const ConvolutionInfo info{ _pad_stride_info, _depth_multiplier, _act_info, _dilation };
87*c217d954SCole Faust         _output_shape = compute_depthwise_convolution_shape(in_info, we_info, info);
88*c217d954SCole Faust 
89*c217d954SCole Faust         _weights_shape.set(2, _output_shape.z());
90*c217d954SCole Faust         _biases_shape = TensorShape(_weights_shape[2]);
91*c217d954SCole Faust     }
92*c217d954SCole Faust 
configure_target()93*c217d954SCole Faust     void configure_target()
94*c217d954SCole Faust     {
95*c217d954SCole Faust         TensorShape input_shape   = _input_shape;
96*c217d954SCole Faust         TensorShape weights_shape = _weights_shape;
97*c217d954SCole Faust         TensorShape output_shape  = _output_shape;
98*c217d954SCole Faust 
99*c217d954SCole Faust         if(_data_layout == DataLayout::NHWC)
100*c217d954SCole Faust         {
101*c217d954SCole Faust             permute(input_shape, PermutationVector(2U, 0U, 1U));
102*c217d954SCole Faust             permute(weights_shape, PermutationVector(2U, 0U, 1U));
103*c217d954SCole Faust             permute(output_shape, PermutationVector(2U, 0U, 1U));
104*c217d954SCole Faust         }
105*c217d954SCole Faust 
106*c217d954SCole Faust         // Create tensors
107*c217d954SCole Faust         _src                      = create_tensor<TensorType>(input_shape, _input_data_type, 1, _input_quantization_info, _data_layout);
108*c217d954SCole Faust         _weights                  = create_tensor<TensorType>(weights_shape, _weights_data_type, 1, _weights_quantization_info, _data_layout);
109*c217d954SCole Faust         if(_run_twice) {
110*c217d954SCole Faust             _weights.info()->set_are_values_constant(false);
111*c217d954SCole Faust         }
112*c217d954SCole Faust         _biases                   = create_tensor<TensorType>(_biases_shape, _bias_data_type, 1, _input_quantization_info, _data_layout);
113*c217d954SCole Faust         TensorType *target_to_use = nullptr;
114*c217d954SCole Faust         if(!_in_place)
115*c217d954SCole Faust         {
116*c217d954SCole Faust             _target       = create_tensor<TensorType>(output_shape, _input_data_type, 1, _output_quantization_info, _data_layout);
117*c217d954SCole Faust             target_to_use = &_target;
118*c217d954SCole Faust         }
119*c217d954SCole Faust 
120*c217d954SCole Faust         add_padding_x({ &_src, &_biases }, _data_layout);
121*c217d954SCole Faust         add_padding_x({ &_weights }, _data_layout, true);
122*c217d954SCole Faust         if(!_in_place)
123*c217d954SCole Faust         {
124*c217d954SCole Faust             add_padding_x({ &_target }, _data_layout);
125*c217d954SCole Faust         }
126*c217d954SCole Faust 
127*c217d954SCole Faust         // Create Depthwise Convolution configure function
128*c217d954SCole Faust         _dwc.configure(&_src, &_weights, &_biases, target_to_use, _pad_stride_info, _depth_multiplier, _act_info, _dilation);
129*c217d954SCole Faust 
130*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
131*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
132*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
133*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
134*c217d954SCole Faust     }
135*c217d954SCole Faust 
allocate_and_run_target()136*c217d954SCole Faust     void allocate_and_run_target()
137*c217d954SCole Faust     {
138*c217d954SCole Faust         // Allocate tensors
139*c217d954SCole Faust         _src.allocator()->allocate();
140*c217d954SCole Faust         _weights.allocator()->allocate();
141*c217d954SCole Faust         _biases.allocator()->allocate();
142*c217d954SCole Faust 
143*c217d954SCole Faust         ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
144*c217d954SCole Faust         ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
145*c217d954SCole Faust         ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
146*c217d954SCole Faust 
147*c217d954SCole Faust         if(!_in_place)
148*c217d954SCole Faust         {
149*c217d954SCole Faust             _target.allocator()->allocate();
150*c217d954SCole Faust             ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
151*c217d954SCole Faust         }
152*c217d954SCole Faust 
153*c217d954SCole Faust         // Fill tensors
154*c217d954SCole Faust         fill(AccessorType(_src), 0);
155*c217d954SCole Faust         fill(AccessorType(_weights), 1);
156*c217d954SCole Faust         fill(AccessorType(_biases), 2);
157*c217d954SCole Faust 
158*c217d954SCole Faust         // Run with variable input
159*c217d954SCole Faust         if(_run_twice) {
160*c217d954SCole Faust             _dwc.run();
161*c217d954SCole Faust 
162*c217d954SCole Faust             // Fill tensors with a new seed
163*c217d954SCole Faust             fill(AccessorType(_src), 3);
164*c217d954SCole Faust             fill(AccessorType(_weights), 4);
165*c217d954SCole Faust             fill(AccessorType(_biases), 5);
166*c217d954SCole Faust         }
167*c217d954SCole Faust 
168*c217d954SCole Faust         if(_mixed_layout)
169*c217d954SCole Faust         {
170*c217d954SCole Faust             mix_layout(_dwc, _src, _target);
171*c217d954SCole Faust         }
172*c217d954SCole Faust         else
173*c217d954SCole Faust         {
174*c217d954SCole Faust             // Compute function
175*c217d954SCole Faust             _dwc.run();
176*c217d954SCole Faust         }
177*c217d954SCole Faust     }
178*c217d954SCole Faust 
compute_reference()179*c217d954SCole Faust     void compute_reference()
180*c217d954SCole Faust     {
181*c217d954SCole Faust         SimpleTensor<T>     src{ _input_shape, _input_data_type, 1, _input_quantization_info };
182*c217d954SCole Faust         SimpleTensor<TW>    weights{ _weights_shape, _weights_data_type, 1, _weights_quantization_info };
183*c217d954SCole Faust         SimpleTensor<TBias> biases{ _biases_shape, _bias_data_type, 1, _input_quantization_info };
184*c217d954SCole Faust 
185*c217d954SCole Faust         fill(src, 0);
186*c217d954SCole Faust         fill(weights, 1);
187*c217d954SCole Faust         fill(biases, 2);
188*c217d954SCole Faust         if(_run_twice) {
189*c217d954SCole Faust             SimpleTensor<T> depth_out = reference::depthwise_convolution(src, weights, biases, _output_shape, _pad_stride_info, _depth_multiplier, _dilation, _output_quantization_info);
190*c217d954SCole Faust             if(_act_info.enabled()) {
191*c217d954SCole Faust                 reference::activation_layer<T>(depth_out, _act_info);
192*c217d954SCole Faust             }
193*c217d954SCole Faust 
194*c217d954SCole Faust             fill(src, 3);
195*c217d954SCole Faust             fill(weights, 4);
196*c217d954SCole Faust             fill(biases, 5);
197*c217d954SCole Faust         }
198*c217d954SCole Faust 
199*c217d954SCole Faust         SimpleTensor<T> depth_out = reference::depthwise_convolution(src, weights, biases, _output_shape, _pad_stride_info, _depth_multiplier, _dilation, _output_quantization_info);
200*c217d954SCole Faust         _reference                = (_act_info.enabled()) ? reference::activation_layer<T>(depth_out, _act_info) : depth_out;
201*c217d954SCole Faust     }
202*c217d954SCole Faust 
203*c217d954SCole Faust protected:
mix_layout(FunctionType & layer,TensorType & src,TensorType & dst)204*c217d954SCole Faust     void mix_layout(FunctionType &layer, TensorType &src, TensorType &dst)
205*c217d954SCole Faust     {
206*c217d954SCole Faust         ARM_COMPUTE_ERROR_ON(_in_place);
207*c217d954SCole Faust         // Test Multi DataLayout graph cases, when the data layout changes after configure
208*c217d954SCole Faust         src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
209*c217d954SCole Faust         dst.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
210*c217d954SCole Faust 
211*c217d954SCole Faust         // Compute Convolution function
212*c217d954SCole Faust         layer.run();
213*c217d954SCole Faust 
214*c217d954SCole Faust         // Reinstating original data layout for the test suite to properly check the values
215*c217d954SCole Faust         src.info()->set_data_layout(_data_layout);
216*c217d954SCole Faust         dst.info()->set_data_layout(_data_layout);
217*c217d954SCole Faust     }
218*c217d954SCole Faust 
219*c217d954SCole Faust     template <typename U>
fill(U && tensor,int i)220*c217d954SCole Faust     void fill(U &&tensor, int i)
221*c217d954SCole Faust     {
222*c217d954SCole Faust         switch(tensor.data_type())
223*c217d954SCole Faust         {
224*c217d954SCole Faust             case DataType::QASYMM8:
225*c217d954SCole Faust             {
226*c217d954SCole Faust                 std::uniform_int_distribution<uint32_t> distribution(0, 15);
227*c217d954SCole Faust                 library->fill(tensor, distribution, i);
228*c217d954SCole Faust                 break;
229*c217d954SCole Faust             }
230*c217d954SCole Faust             case DataType::QASYMM8_SIGNED:
231*c217d954SCole Faust             case DataType::QSYMM8_PER_CHANNEL:
232*c217d954SCole Faust             {
233*c217d954SCole Faust                 std::uniform_int_distribution<int32_t> distribution(-10, 10);
234*c217d954SCole Faust                 library->fill(tensor, distribution, i);
235*c217d954SCole Faust                 break;
236*c217d954SCole Faust             }
237*c217d954SCole Faust             case DataType::F16:
238*c217d954SCole Faust             {
239*c217d954SCole Faust                 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
240*c217d954SCole Faust                 library->fill(tensor, distribution, i);
241*c217d954SCole Faust                 break;
242*c217d954SCole Faust             }
243*c217d954SCole Faust             case DataType::F32:
244*c217d954SCole Faust             {
245*c217d954SCole Faust                 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
246*c217d954SCole Faust                 library->fill(tensor, distribution, i);
247*c217d954SCole Faust                 break;
248*c217d954SCole Faust             }
249*c217d954SCole Faust             case DataType::S32:
250*c217d954SCole Faust             {
251*c217d954SCole Faust                 std::uniform_int_distribution<int32_t> distribution(-100, 100);
252*c217d954SCole Faust                 library->fill(tensor, distribution, i);
253*c217d954SCole Faust                 break;
254*c217d954SCole Faust             }
255*c217d954SCole Faust             default:
256*c217d954SCole Faust                 library->fill_tensor_uniform(tensor, i);
257*c217d954SCole Faust         }
258*c217d954SCole Faust     }
259*c217d954SCole Faust 
260*c217d954SCole Faust     TensorType      _target{};
261*c217d954SCole Faust     SimpleTensor<T> _reference{};
262*c217d954SCole Faust 
263*c217d954SCole Faust     TensorType   _src{};
264*c217d954SCole Faust     TensorType   _weights{};
265*c217d954SCole Faust     TensorType   _biases{};
266*c217d954SCole Faust     FunctionType _dwc{};
267*c217d954SCole Faust 
268*c217d954SCole Faust     TensorShape         _input_shape{};
269*c217d954SCole Faust     TensorShape         _weights_shape{};
270*c217d954SCole Faust     TensorShape         _biases_shape{};
271*c217d954SCole Faust     TensorShape         _output_shape{};
272*c217d954SCole Faust     DataType            _input_data_type{};
273*c217d954SCole Faust     DataType            _weights_data_type{};
274*c217d954SCole Faust     DataType            _bias_data_type{};
275*c217d954SCole Faust     QuantizationInfo    _input_quantization_info{};
276*c217d954SCole Faust     QuantizationInfo    _weights_quantization_info{};
277*c217d954SCole Faust     QuantizationInfo    _output_quantization_info{};
278*c217d954SCole Faust     DataLayout          _data_layout{};
279*c217d954SCole Faust     PadStrideInfo       _pad_stride_info{};
280*c217d954SCole Faust     ActivationLayerInfo _act_info{};
281*c217d954SCole Faust     unsigned int        _depth_multiplier{};
282*c217d954SCole Faust     Size2D              _dilation{};
283*c217d954SCole Faust     bool                _mixed_layout{ false };
284*c217d954SCole Faust     bool                _in_place{ false };
285*c217d954SCole Faust     bool                _run_twice{ false };
286*c217d954SCole Faust };
287*c217d954SCole Faust 
288*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false, bool in_place = false, bool run_twice = false>
289*c217d954SCole Faust class DepthwiseConvolutionLayerValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
290*c217d954SCole Faust {
291*c217d954SCole Faust public:
292*c217d954SCole Faust     template <typename...>
setup(TensorShape in_shape,Size2D kernel_size,PadStrideInfo pad_stride_info,Size2D dilation,unsigned int depth_multiplier,DataType data_type,DataLayout data_layout,ActivationLayerInfo act_info)293*c217d954SCole Faust     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*c217d954SCole Faust                ActivationLayerInfo act_info)
295*c217d954SCole Faust     {
296*c217d954SCole Faust         DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
297*c217d954SCole Faust                                                                                                                data_type, data_type, QuantizationInfo(), QuantizationInfo(), QuantizationInfo(),
298*c217d954SCole Faust                                                                                                                data_layout, act_info, mixed_layout, in_place, run_twice);
299*c217d954SCole Faust     }
300*c217d954SCole Faust };
301*c217d954SCole Faust 
302*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
303*c217d954SCole Faust class DepthwiseConvolutionLayerNativeValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
304*c217d954SCole Faust {
305*c217d954SCole Faust public:
306*c217d954SCole Faust     template <typename...>
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,DataLayout data_layout)307*c217d954SCole Faust     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*c217d954SCole Faust                DataLayout data_layout)
309*c217d954SCole Faust     {
310*c217d954SCole Faust         _dilation         = dilation;
311*c217d954SCole Faust         _depth_multiplier = depth_multiplier;
312*c217d954SCole Faust         _data_type        = data_type;
313*c217d954SCole Faust         _data_layout      = data_layout;
314*c217d954SCole Faust 
315*c217d954SCole Faust         _input_shape   = TensorShape(width, height, channel, batch);
316*c217d954SCole Faust         _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
317*c217d954SCole Faust         _biases_shape  = TensorShape(_weights_shape.z());
318*c217d954SCole Faust 
319*c217d954SCole Faust         if(padding_valid)
320*c217d954SCole Faust         {
321*c217d954SCole Faust             _conv_info = PadStrideInfo(stride.width, stride.height);
322*c217d954SCole Faust         }
323*c217d954SCole Faust         else
324*c217d954SCole Faust         {
325*c217d954SCole Faust             _conv_info = calculate_same_pad(_input_shape, _weights_shape, PadStrideInfo(stride.width, stride.height), DataLayout::NCHW, _dilation);
326*c217d954SCole Faust         }
327*c217d954SCole Faust     }
328*c217d954SCole Faust 
configure_target()329*c217d954SCole Faust     void configure_target()
330*c217d954SCole Faust     {
331*c217d954SCole Faust         TensorShape input_shape   = _input_shape;
332*c217d954SCole Faust         TensorShape weights_shape = _weights_shape;
333*c217d954SCole Faust 
334*c217d954SCole Faust         if(_data_layout == DataLayout::NHWC)
335*c217d954SCole Faust         {
336*c217d954SCole Faust             permute(input_shape, PermutationVector(2U, 0U, 1U));
337*c217d954SCole Faust             permute(weights_shape, PermutationVector(2U, 0U, 1U));
338*c217d954SCole Faust         }
339*c217d954SCole Faust 
340*c217d954SCole Faust         // Create tensors
341*c217d954SCole Faust         _src     = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
342*c217d954SCole Faust         _weights = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
343*c217d954SCole Faust         _biases  = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
344*c217d954SCole Faust         _target  = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
345*c217d954SCole Faust 
346*c217d954SCole Faust         add_padding_x({ &_src, &_biases, &_target }, _data_layout);
347*c217d954SCole Faust         add_padding_x({ &_weights }, _data_layout, true);
348*c217d954SCole Faust         add_padding_y({ &_src, &_target }, _data_layout);
349*c217d954SCole Faust 
350*c217d954SCole Faust         // Create Depthwise Convolution configure function
351*c217d954SCole Faust         const ConvolutionInfo info
352*c217d954SCole Faust         {
353*c217d954SCole Faust             _conv_info, _depth_multiplier, ActivationLayerInfo(), _dilation
354*c217d954SCole Faust         };
355*c217d954SCole Faust         _dwc.configure(_src.info(), _weights.info(), _biases.info(), _target.info(), info);
356*c217d954SCole Faust 
357*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
358*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
359*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
360*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
361*c217d954SCole Faust     }
362*c217d954SCole Faust 
allocate_and_run_target()363*c217d954SCole Faust     void allocate_and_run_target()
364*c217d954SCole Faust     {
365*c217d954SCole Faust         // Allocate tensors
366*c217d954SCole Faust         _src.allocator()->allocate();
367*c217d954SCole Faust         _weights.allocator()->allocate();
368*c217d954SCole Faust         _biases.allocator()->allocate();
369*c217d954SCole Faust         _target.allocator()->allocate();
370*c217d954SCole Faust 
371*c217d954SCole Faust         ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
372*c217d954SCole Faust         ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
373*c217d954SCole Faust         ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
374*c217d954SCole Faust         ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
375*c217d954SCole Faust 
376*c217d954SCole Faust         // Fill tensors
377*c217d954SCole Faust         fill(AccessorType(_src), 0);
378*c217d954SCole Faust         fill(AccessorType(_weights), 1);
379*c217d954SCole Faust         fill(AccessorType(_biases), 2);
380*c217d954SCole Faust 
381*c217d954SCole Faust         arm_compute::ITensorPack pack;
382*c217d954SCole Faust         pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_0, &_src);
383*c217d954SCole Faust         pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_1, &_weights);
384*c217d954SCole Faust         pack.add_const_tensor(arm_compute::TensorType::ACL_SRC_2, &_biases);
385*c217d954SCole Faust         pack.add_tensor(arm_compute::TensorType::ACL_DST, &_target);
386*c217d954SCole Faust 
387*c217d954SCole Faust         // Compute function
388*c217d954SCole Faust         _dwc.run(pack);
389*c217d954SCole Faust     }
390*c217d954SCole Faust 
compute_reference()391*c217d954SCole Faust     void compute_reference()
392*c217d954SCole Faust     {
393*c217d954SCole Faust         SimpleTensor<T> src{ _input_shape, _data_type };
394*c217d954SCole Faust         SimpleTensor<T> weights{ _weights_shape, _data_type };
395*c217d954SCole Faust         SimpleTensor<T> biases{ _biases_shape, _data_type };
396*c217d954SCole Faust 
397*c217d954SCole Faust         fill(src, 0);
398*c217d954SCole Faust         fill(weights, 1);
399*c217d954SCole Faust         fill(biases, 2);
400*c217d954SCole Faust 
401*c217d954SCole Faust         const ConvolutionInfo info{ _conv_info, _depth_multiplier, ActivationLayerInfo(), _dilation };
402*c217d954SCole Faust         const TensorShape     dst_shape = compute_depthwise_convolution_shape(TensorInfo(_input_shape, 1, _data_type), TensorInfo(_weights_shape, 1, _data_type), info);
403*c217d954SCole Faust         _reference                      = reference::depthwise_convolution(src, weights, biases, dst_shape, _conv_info, _depth_multiplier, _dilation);
404*c217d954SCole Faust     }
405*c217d954SCole Faust 
406*c217d954SCole Faust protected:
407*c217d954SCole Faust     template <typename U>
fill(U && tensor,int i)408*c217d954SCole Faust     void fill(U &&tensor, int i)
409*c217d954SCole Faust     {
410*c217d954SCole Faust         switch(tensor.data_type())
411*c217d954SCole Faust         {
412*c217d954SCole Faust             case DataType::F32:
413*c217d954SCole Faust             {
414*c217d954SCole Faust                 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
415*c217d954SCole Faust                 library->fill(tensor, distribution, i);
416*c217d954SCole Faust                 break;
417*c217d954SCole Faust             }
418*c217d954SCole Faust             default:
419*c217d954SCole Faust                 library->fill_tensor_uniform(tensor, i);
420*c217d954SCole Faust         }
421*c217d954SCole Faust     }
422*c217d954SCole Faust 
423*c217d954SCole Faust     TensorType      _target{};
424*c217d954SCole Faust     SimpleTensor<T> _reference{};
425*c217d954SCole Faust 
426*c217d954SCole Faust     TensorType   _src{};
427*c217d954SCole Faust     TensorType   _weights{};
428*c217d954SCole Faust     TensorType   _biases{};
429*c217d954SCole Faust     FunctionType _dwc{};
430*c217d954SCole Faust 
431*c217d954SCole Faust     TensorShape   _input_shape{};
432*c217d954SCole Faust     TensorShape   _weights_shape{};
433*c217d954SCole Faust     TensorShape   _biases_shape{};
434*c217d954SCole Faust     DataType      _data_type{};
435*c217d954SCole Faust     DataLayout    _data_layout{};
436*c217d954SCole Faust     PadStrideInfo _conv_info{};
437*c217d954SCole Faust     Size2D        _dilation{};
438*c217d954SCole Faust     unsigned int  _depth_multiplier{};
439*c217d954SCole Faust };
440*c217d954SCole Faust 
441*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool in_place = false>
442*c217d954SCole Faust class DepthwiseConvolutionLayerNativeConfigurableValidationFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
443*c217d954SCole Faust {
444*c217d954SCole Faust public:
445*c217d954SCole Faust     template <typename...>
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,DataLayout data_layout,const ActivationLayerInfo & act_info,unsigned int n0,bool export_to_cl_image)446*c217d954SCole Faust     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,
447*c217d954SCole Faust                DataLayout data_layout, const ActivationLayerInfo &act_info, unsigned int n0, bool export_to_cl_image)
448*c217d954SCole Faust     {
449*c217d954SCole Faust         _dilation           = dilation;
450*c217d954SCole Faust         _depth_multiplier   = depth_multiplier;
451*c217d954SCole Faust         _data_type          = data_type;
452*c217d954SCole Faust         _data_layout        = data_layout;
453*c217d954SCole Faust         _act_info           = act_info;
454*c217d954SCole Faust         _n0                 = n0;
455*c217d954SCole Faust         _export_to_cl_image = export_to_cl_image;
456*c217d954SCole Faust         _in_place           = in_place;
457*c217d954SCole Faust 
458*c217d954SCole Faust         _input_shape   = TensorShape(width, height, channel, batch);
459*c217d954SCole Faust         _weights_shape = TensorShape(kernel_size.width, kernel_size.height, channel * _depth_multiplier);
460*c217d954SCole Faust         _biases_shape  = TensorShape(_weights_shape.z());
461*c217d954SCole Faust 
462*c217d954SCole Faust         if(padding_valid)
463*c217d954SCole Faust         {
464*c217d954SCole Faust             _conv_info = calculate_same_pad(_input_shape, _weights_shape, PadStrideInfo(stride.width, stride.height), DataLayout::NCHW, _dilation);
465*c217d954SCole Faust         }
466*c217d954SCole Faust         else
467*c217d954SCole Faust         {
468*c217d954SCole Faust             _conv_info = PadStrideInfo(stride.width, stride.height);
469*c217d954SCole Faust         }
470*c217d954SCole Faust     }
471*c217d954SCole Faust 
configure_target()472*c217d954SCole Faust     void configure_target()
473*c217d954SCole Faust     {
474*c217d954SCole Faust #if defined(ARM_COMPUTE_OPENCL_ENABLED)
475*c217d954SCole Faust         if(_export_to_cl_image)
476*c217d954SCole Faust         {
477*c217d954SCole Faust             _validate_output &= image2d_from_buffer_supported(CLKernelLibrary::get().get_device());
478*c217d954SCole Faust             _validate_output &= (get_cl_image_pitch_alignment(CLKernelLibrary::get().get_device()) != 0);
479*c217d954SCole Faust         }
480*c217d954SCole Faust #endif // ARM_COMPUTE_OPENCL_ENABLED
481*c217d954SCole Faust 
482*c217d954SCole Faust         if(!_validate_output)
483*c217d954SCole Faust         {
484*c217d954SCole Faust             return;
485*c217d954SCole Faust         }
486*c217d954SCole Faust 
487*c217d954SCole Faust         TensorShape input_shape   = _input_shape;
488*c217d954SCole Faust         TensorShape weights_shape = _weights_shape;
489*c217d954SCole Faust 
490*c217d954SCole Faust         if(_data_layout == DataLayout::NHWC)
491*c217d954SCole Faust         {
492*c217d954SCole Faust             permute(input_shape, PermutationVector(2U, 0U, 1U));
493*c217d954SCole Faust             permute(weights_shape, PermutationVector(2U, 0U, 1U));
494*c217d954SCole Faust         }
495*c217d954SCole Faust 
496*c217d954SCole Faust         // Create tensors
497*c217d954SCole Faust         _src                      = create_tensor<TensorType>(input_shape, _data_type, 1, QuantizationInfo(), _data_layout);
498*c217d954SCole Faust         _weights                  = create_tensor<TensorType>(weights_shape, _data_type, 1, QuantizationInfo(), _data_layout);
499*c217d954SCole Faust         _biases                   = create_tensor<TensorType>(_biases_shape, _data_type, 1, QuantizationInfo(), _data_layout);
500*c217d954SCole Faust         TensorType *target_to_use = nullptr;
501*c217d954SCole Faust         if(!_in_place)
502*c217d954SCole Faust         {
503*c217d954SCole Faust             _target       = create_tensor<TensorType>(TensorShape(), _data_type, 1, QuantizationInfo(), _data_layout);
504*c217d954SCole Faust             target_to_use = &_target;
505*c217d954SCole Faust         }
506*c217d954SCole Faust 
507*c217d954SCole Faust         DWCComputeKernelInfo dwc_info;
508*c217d954SCole Faust         dwc_info.n0                         = _n0;
509*c217d954SCole Faust         dwc_info.m0                         = _conv_info.stride().first == 1 && _dilation.x() == 1 ? 8 : 1;
510*c217d954SCole Faust         dwc_info.export_input_to_cl_image   = false;
511*c217d954SCole Faust         dwc_info.export_weights_to_cl_image = _export_to_cl_image;
512*c217d954SCole Faust 
513*c217d954SCole Faust         const ConvolutionInfo conv_kernel_info
514*c217d954SCole Faust         {
515*c217d954SCole Faust             _conv_info, _depth_multiplier, _act_info, _dilation
516*c217d954SCole Faust         };
517*c217d954SCole Faust 
518*c217d954SCole Faust         add_padding_x({ &_src, &_biases, &_target }, _data_layout);
519*c217d954SCole Faust         add_padding_x({ &_weights }, _data_layout, _export_to_cl_image); // Don't add left padding if cl image will be used
520*c217d954SCole Faust 
521*c217d954SCole Faust         // Create Depthwise Convolution configure function
522*c217d954SCole Faust         _dwc.configure(&_src, &_weights, &_biases, target_to_use, dwc_info, conv_kernel_info);
523*c217d954SCole Faust 
524*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_src.info()->is_resizable());
525*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_weights.info()->is_resizable());
526*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_biases.info()->is_resizable());
527*c217d954SCole Faust         ARM_COMPUTE_ASSERT(_target.info()->is_resizable());
528*c217d954SCole Faust     }
529*c217d954SCole Faust 
allocate_and_run_target()530*c217d954SCole Faust     void allocate_and_run_target()
531*c217d954SCole Faust     {
532*c217d954SCole Faust         if(!_validate_output)
533*c217d954SCole Faust         {
534*c217d954SCole Faust             return;
535*c217d954SCole Faust         }
536*c217d954SCole Faust 
537*c217d954SCole Faust         // Allocate tensors
538*c217d954SCole Faust         _src.allocator()->allocate();
539*c217d954SCole Faust         _weights.allocator()->allocate();
540*c217d954SCole Faust         _biases.allocator()->allocate();
541*c217d954SCole Faust 
542*c217d954SCole Faust         ARM_COMPUTE_ASSERT(!_src.info()->is_resizable());
543*c217d954SCole Faust         ARM_COMPUTE_ASSERT(!_weights.info()->is_resizable());
544*c217d954SCole Faust         ARM_COMPUTE_ASSERT(!_biases.info()->is_resizable());
545*c217d954SCole Faust         if(!_in_place)
546*c217d954SCole Faust         {
547*c217d954SCole Faust             _target.allocator()->allocate();
548*c217d954SCole Faust             ARM_COMPUTE_ASSERT(!_target.info()->is_resizable());
549*c217d954SCole Faust         }
550*c217d954SCole Faust 
551*c217d954SCole Faust         // Fill tensors
552*c217d954SCole Faust         fill(AccessorType(_src), 0);
553*c217d954SCole Faust         fill(AccessorType(_weights), 1);
554*c217d954SCole Faust         fill(AccessorType(_biases), 2);
555*c217d954SCole Faust 
556*c217d954SCole Faust         // Test Multi DataLayout graph cases, when the data layout changes after configure
557*c217d954SCole Faust         _src.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
558*c217d954SCole Faust         if(!_in_place)
559*c217d954SCole Faust         {
560*c217d954SCole Faust             _target.info()->set_data_layout(_data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW);
561*c217d954SCole Faust         }
562*c217d954SCole Faust 
563*c217d954SCole Faust         // Compute function
564*c217d954SCole Faust         _dwc.run();
565*c217d954SCole Faust 
566*c217d954SCole Faust         // Reinstating original data layout for the test suite to properly check the values
567*c217d954SCole Faust         if(!_in_place)
568*c217d954SCole Faust         {
569*c217d954SCole Faust             _target.info()->set_data_layout(_data_layout);
570*c217d954SCole Faust         }
571*c217d954SCole Faust     }
572*c217d954SCole Faust 
compute_reference()573*c217d954SCole Faust     void compute_reference()
574*c217d954SCole Faust     {
575*c217d954SCole Faust         if(!_validate_output)
576*c217d954SCole Faust         {
577*c217d954SCole Faust             return;
578*c217d954SCole Faust         }
579*c217d954SCole Faust 
580*c217d954SCole Faust         SimpleTensor<T> src{ _input_shape, _data_type };
581*c217d954SCole Faust         SimpleTensor<T> weights{ _weights_shape, _data_type };
582*c217d954SCole Faust         SimpleTensor<T> biases{ _biases_shape, _data_type };
583*c217d954SCole Faust 
584*c217d954SCole Faust         fill(src, 0);
585*c217d954SCole Faust         fill(weights, 1);
586*c217d954SCole Faust         fill(biases, 2);
587*c217d954SCole Faust 
588*c217d954SCole Faust         const ConvolutionInfo info{ _conv_info, _depth_multiplier, _act_info, _dilation };
589*c217d954SCole Faust         const TensorShape     dst_shape = compute_depthwise_convolution_shape(TensorInfo(_input_shape, 1, _data_type), TensorInfo(_weights_shape, 1, _data_type), info);
590*c217d954SCole Faust         _reference                      = reference::activation_layer(reference::depthwise_convolution(src, weights, biases, dst_shape, _conv_info, _depth_multiplier, _dilation), _act_info);
591*c217d954SCole Faust     }
592*c217d954SCole Faust 
593*c217d954SCole Faust protected:
594*c217d954SCole Faust     template <typename U>
fill(U && tensor,int i)595*c217d954SCole Faust     void fill(U &&tensor, int i)
596*c217d954SCole Faust     {
597*c217d954SCole Faust         switch(tensor.data_type())
598*c217d954SCole Faust         {
599*c217d954SCole Faust             case DataType::F32:
600*c217d954SCole Faust             {
601*c217d954SCole Faust                 std::uniform_real_distribution<float> distribution(-1.0f, 1.0f);
602*c217d954SCole Faust                 library->fill(tensor, distribution, i);
603*c217d954SCole Faust                 break;
604*c217d954SCole Faust             }
605*c217d954SCole Faust             case DataType::F16:
606*c217d954SCole Faust             {
607*c217d954SCole Faust                 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f };
608*c217d954SCole Faust                 library->fill(tensor, distribution, i);
609*c217d954SCole Faust                 break;
610*c217d954SCole Faust             }
611*c217d954SCole Faust             default:
612*c217d954SCole Faust                 library->fill_tensor_uniform(tensor, i);
613*c217d954SCole Faust         }
614*c217d954SCole Faust     }
615*c217d954SCole Faust 
616*c217d954SCole Faust     TensorType      _target{};
617*c217d954SCole Faust     SimpleTensor<T> _reference{};
618*c217d954SCole Faust 
619*c217d954SCole Faust     TensorType   _src{};
620*c217d954SCole Faust     TensorType   _weights{};
621*c217d954SCole Faust     TensorType   _biases{};
622*c217d954SCole Faust     FunctionType _dwc{};
623*c217d954SCole Faust 
624*c217d954SCole Faust     TensorShape         _input_shape{};
625*c217d954SCole Faust     TensorShape         _weights_shape{};
626*c217d954SCole Faust     TensorShape         _biases_shape{};
627*c217d954SCole Faust     DataType            _data_type{};
628*c217d954SCole Faust     DataLayout          _data_layout{};
629*c217d954SCole Faust     PadStrideInfo       _conv_info{};
630*c217d954SCole Faust     ActivationLayerInfo _act_info{};
631*c217d954SCole Faust     Size2D              _dilation{};
632*c217d954SCole Faust     unsigned int        _depth_multiplier{};
633*c217d954SCole Faust     unsigned int        _n0{};
634*c217d954SCole Faust     bool                _export_to_cl_image{};
635*c217d954SCole Faust     bool                _validate_output{ true };
636*c217d954SCole Faust     bool                _in_place{ false };
637*c217d954SCole Faust };
638*c217d954SCole Faust 
639*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false, bool in_place = false>
640*c217d954SCole Faust class DepthwiseConvolutionLayerValidationQuantizedFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>
641*c217d954SCole Faust {
642*c217d954SCole Faust public:
643*c217d954SCole Faust     template <typename...>
setup(TensorShape in_shape,Size2D kernel_size,PadStrideInfo pad_stride_info,Size2D dilation,unsigned int depth_multiplier,DataType data_type,QuantizationInfo input_quantization_info,QuantizationInfo output_quantization_info,DataLayout data_layout,ActivationLayerInfo act_info)644*c217d954SCole Faust     void setup(TensorShape in_shape, Size2D kernel_size, PadStrideInfo pad_stride_info, Size2D dilation, unsigned int depth_multiplier, DataType data_type,
645*c217d954SCole Faust                QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
646*c217d954SCole Faust     {
647*c217d954SCole Faust         DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, T>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier, data_type,
648*c217d954SCole Faust                                                                                                                data_type, input_quantization_info, input_quantization_info, output_quantization_info,
649*c217d954SCole Faust                                                                                                                data_layout, act_info, mixed_layout, in_place);
650*c217d954SCole Faust     }
651*c217d954SCole Faust };
652*c217d954SCole Faust 
653*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename TW, bool in_place = false>
654*c217d954SCole Faust class DepthwiseConvolutionLayerValidationQuantizedPerChannelFixture : public DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>
655*c217d954SCole Faust {
656*c217d954SCole Faust public:
657*c217d954SCole Faust     template <typename...>
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,QuantizationInfo input_quantization_info,QuantizationInfo output_quantization_info,DataLayout data_layout,ActivationLayerInfo act_info)658*c217d954SCole Faust     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,
659*c217d954SCole Faust                QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, ActivationLayerInfo act_info)
660*c217d954SCole Faust     {
661*c217d954SCole Faust         const float out_scale = output_quantization_info.uniform().scale;
662*c217d954SCole Faust         const float in_scale  = input_quantization_info.uniform().scale;
663*c217d954SCole Faust 
664*c217d954SCole Faust         std::vector<float>                    weights_scales{};
665*c217d954SCole Faust         std::mt19937                          gen(library->seed());
666*c217d954SCole Faust         std::uniform_real_distribution<float> dis(0.01f, out_scale / in_scale);
667*c217d954SCole Faust         for(size_t i = 0; i < in_shape.z() * depth_multiplier; ++i)
668*c217d954SCole Faust         {
669*c217d954SCole Faust             weights_scales.push_back(dis(gen));
670*c217d954SCole Faust         }
671*c217d954SCole Faust 
672*c217d954SCole Faust         DepthwiseConvolutionLayerValidationGenericFixture<TensorType, AccessorType, FunctionType, T, TW>::setup(in_shape, kernel_size, pad_stride_info, dilation, depth_multiplier,
673*c217d954SCole Faust                                                                                                                 input_data_type, weights_data_type,
674*c217d954SCole Faust                                                                                                                 input_quantization_info, QuantizationInfo(weights_scales), output_quantization_info,
675*c217d954SCole Faust                                                                                                                 data_layout, act_info, false, in_place);
676*c217d954SCole Faust     }
677*c217d954SCole Faust };
678*c217d954SCole Faust } // namespace validation
679*c217d954SCole Faust } // namespace test
680*c217d954SCole Faust } // namespace arm_compute
681*c217d954SCole Faust #endif /* ARM_COMPUTE_TEST_DEPTHWISE_CONVOLUTION_FIXTURE */
682