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 #include "arm_compute/core/Helpers.h" 25*c217d954SCole Faust #include "arm_compute/core/TensorShape.h" 26*c217d954SCole Faust #include "arm_compute/core/Types.h" 27*c217d954SCole Faust #include "arm_compute/core/utils/misc/ShapeCalculator.h" 28*c217d954SCole Faust #include "tests/AssetsLibrary.h" 29*c217d954SCole Faust #include "tests/Globals.h" 30*c217d954SCole Faust #include "tests/IAccessor.h" 31*c217d954SCole Faust #include "tests/framework/Asserts.h" 32*c217d954SCole Faust #include "tests/framework/Fixture.h" 33*c217d954SCole Faust #include "tests/validation/Helpers.h" 34*c217d954SCole Faust #include "tests/validation/fixtures/ConvolutionLayerFixture.h" 35*c217d954SCole Faust #include "tests/validation/reference/ConvolutionLayer.h" 36*c217d954SCole Faust #include "tests/validation/reference/Permute.h" 37*c217d954SCole Faust 38*c217d954SCole Faust #include <random> 39*c217d954SCole Faust 40*c217d954SCole Faust namespace arm_compute 41*c217d954SCole Faust { 42*c217d954SCole Faust namespace test 43*c217d954SCole Faust { 44*c217d954SCole Faust namespace validation 45*c217d954SCole Faust { 46*c217d954SCole Faust using namespace arm_compute::misc::shape_calculator; 47*c217d954SCole Faust 48*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T> 49*c217d954SCole Faust class DirectConvolutionValidationGenericFixture : public framework::Fixture 50*c217d954SCole Faust { 51*c217d954SCole Faust public: 52*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; 53*c217d954SCole Faust 54*c217d954SCole Faust template <typename...> 55*c217d954SCole Faust void setup(TensorShape input_shape, int stride_x, int stride_y, int pad_x, int pad_y, unsigned int kernel_size, unsigned int num_kernels, 56*c217d954SCole Faust DataType data_type, QuantizationInfo quantization_info, ActivationLayerInfo act_info, DataLayout data_layout, bool mixed_layout = false) 57*c217d954SCole Faust { 58*c217d954SCole Faust _quantization_info = quantization_info; 59*c217d954SCole Faust _data_type = data_type; 60*c217d954SCole Faust _mixed_layout = mixed_layout; 61*c217d954SCole Faust 62*c217d954SCole Faust TensorShape weights_shape(kernel_size, kernel_size, input_shape.z(), num_kernels); 63*c217d954SCole Faust const TensorShape bias_shape(num_kernels); 64*c217d954SCole Faust const PadStrideInfo info(stride_x, stride_y, pad_x, pad_y, DimensionRoundingType::FLOOR); 65*c217d954SCole Faust const DataType bias_data_type = is_data_type_quantized_asymmetric(data_type) ? DataType::S32 : data_type; 66*c217d954SCole Faust 67*c217d954SCole Faust TensorInfo input_info = TensorInfo(input_shape, 1, data_type); 68*c217d954SCole Faust TensorInfo weights_info = TensorInfo(weights_shape, 1, data_type); 69*c217d954SCole Faust 70*c217d954SCole Faust const TensorShape output_shape = compute_deep_convolution_shape(input_info, weights_info, info); 71*c217d954SCole Faust 72*c217d954SCole Faust _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, data_type, bias_data_type, quantization_info, act_info, data_layout); 73*c217d954SCole Faust _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type, bias_data_type, quantization_info, act_info); 74*c217d954SCole Faust } 75*c217d954SCole Faust 76*c217d954SCole Faust template <typename...> setup(TensorShape input_shape,TensorShape weights_shape,TensorShape bias_shape,TensorShape output_shape,PadStrideInfo info,Size2D dilation,DataType data_type,QuantizationInfo quantization_info,ActivationLayerInfo act_info,DataLayout data_layout)77*c217d954SCole Faust void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, Size2D dilation, 78*c217d954SCole Faust DataType data_type, QuantizationInfo quantization_info, ActivationLayerInfo act_info, DataLayout data_layout) 79*c217d954SCole Faust { 80*c217d954SCole Faust ARM_COMPUTE_ERROR_ON(data_layout == DataLayout::UNKNOWN); 81*c217d954SCole Faust ARM_COMPUTE_UNUSED(dilation); 82*c217d954SCole Faust 83*c217d954SCole Faust _quantization_info = quantization_info; 84*c217d954SCole Faust _data_type = data_type; 85*c217d954SCole Faust 86*c217d954SCole Faust const DataType bias_data_type = is_data_type_quantized_asymmetric(data_type) ? DataType::S32 : data_type; 87*c217d954SCole Faust 88*c217d954SCole Faust _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, data_type, bias_data_type, quantization_info, act_info, data_layout); 89*c217d954SCole Faust _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type, bias_data_type, quantization_info, act_info); 90*c217d954SCole Faust } 91*c217d954SCole Faust 92*c217d954SCole Faust protected: mix_layout(FunctionType & layer,TensorType & src,TensorType & dst)93*c217d954SCole Faust void mix_layout(FunctionType &layer, TensorType &src, TensorType &dst) 94*c217d954SCole Faust { 95*c217d954SCole Faust DataLayout data_layout = src.info()->data_layout(); 96*c217d954SCole Faust // Test Multi DataLayout graph cases, when the data layout changes after configure 97*c217d954SCole Faust src.info()->set_data_layout(data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW); 98*c217d954SCole Faust dst.info()->set_data_layout(data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW); 99*c217d954SCole Faust 100*c217d954SCole Faust // Compute Convolution function 101*c217d954SCole Faust layer.run(); 102*c217d954SCole Faust 103*c217d954SCole Faust // Reinstating original data layout for the test suite to properly check the values 104*c217d954SCole Faust src.info()->set_data_layout(data_layout); 105*c217d954SCole Faust dst.info()->set_data_layout(data_layout); 106*c217d954SCole Faust } 107*c217d954SCole Faust 108*c217d954SCole Faust template <typename U> fill(U && tensor,int i)109*c217d954SCole Faust void fill(U &&tensor, int i) 110*c217d954SCole Faust { 111*c217d954SCole Faust switch(tensor.data_type()) 112*c217d954SCole Faust { 113*c217d954SCole Faust case DataType::QASYMM8: 114*c217d954SCole Faust { 115*c217d954SCole Faust std::uniform_int_distribution<uint32_t> distribution(0, 50); 116*c217d954SCole Faust library->fill(tensor, distribution, i); 117*c217d954SCole Faust break; 118*c217d954SCole Faust } 119*c217d954SCole Faust case DataType::QASYMM8_SIGNED: 120*c217d954SCole Faust { 121*c217d954SCole Faust // Use small input range to avoid all the test results being saturated at the end. 122*c217d954SCole Faust std::uniform_int_distribution<int32_t> distribution(-25, 25); 123*c217d954SCole Faust library->fill(tensor, distribution, i); 124*c217d954SCole Faust break; 125*c217d954SCole Faust } 126*c217d954SCole Faust case DataType::F16: 127*c217d954SCole Faust { 128*c217d954SCole Faust arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -1.0f, 1.0f }; 129*c217d954SCole Faust library->fill(tensor, distribution, i); 130*c217d954SCole Faust break; 131*c217d954SCole Faust } 132*c217d954SCole Faust case DataType::F32: 133*c217d954SCole Faust { 134*c217d954SCole Faust std::uniform_real_distribution<float> distribution(-1.0f, 1.0f); 135*c217d954SCole Faust library->fill(tensor, distribution, i); 136*c217d954SCole Faust break; 137*c217d954SCole Faust } 138*c217d954SCole Faust case DataType::S32: 139*c217d954SCole Faust { 140*c217d954SCole Faust std::uniform_int_distribution<int32_t> distribution(-5, 5); 141*c217d954SCole Faust library->fill(tensor, distribution, i); 142*c217d954SCole Faust break; 143*c217d954SCole Faust } 144*c217d954SCole Faust default: 145*c217d954SCole Faust library->fill_tensor_uniform(tensor, i); 146*c217d954SCole Faust } 147*c217d954SCole Faust } 148*c217d954SCole Faust compute_target(TensorShape input_shape,TensorShape weights_shape,const TensorShape & bias_shape,TensorShape output_shape,const PadStrideInfo & info,DataType data_type,DataType bias_data_type,QuantizationInfo quantization_info,ActivationLayerInfo act_info,const DataLayout & data_layout)149*c217d954SCole Faust TensorType compute_target(TensorShape input_shape, TensorShape weights_shape, const TensorShape &bias_shape, TensorShape output_shape, const PadStrideInfo &info, 150*c217d954SCole Faust DataType data_type, DataType bias_data_type, QuantizationInfo quantization_info, ActivationLayerInfo act_info, const DataLayout &data_layout) 151*c217d954SCole Faust { 152*c217d954SCole Faust if(data_layout == DataLayout::NHWC) 153*c217d954SCole Faust { 154*c217d954SCole Faust permute(input_shape, PermutationVector(2U, 0U, 1U)); 155*c217d954SCole Faust permute(weights_shape, PermutationVector(2U, 0U, 1U)); 156*c217d954SCole Faust permute(output_shape, PermutationVector(2U, 0U, 1U)); 157*c217d954SCole Faust } 158*c217d954SCole Faust 159*c217d954SCole Faust // Create tensors 160*c217d954SCole Faust TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, quantization_info, data_layout); 161*c217d954SCole Faust TensorType weights = create_tensor<TensorType>(weights_shape, data_type, 1, quantization_info, data_layout); 162*c217d954SCole Faust TensorType bias = create_tensor<TensorType>(bias_shape, bias_data_type, 1, quantization_info); 163*c217d954SCole Faust TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, quantization_info, data_layout); 164*c217d954SCole Faust 165*c217d954SCole Faust add_padding_x({ &src, &bias, &dst }, data_layout); 166*c217d954SCole Faust add_padding_x({ &weights }, data_layout, input_shape[0] % 4 == 0); // Don't add left padding if cl image will be used 167*c217d954SCole Faust 168*c217d954SCole Faust // Create and configure function 169*c217d954SCole Faust FunctionType conv; 170*c217d954SCole Faust conv.configure(&src, &weights, &bias, &dst, info, act_info); 171*c217d954SCole Faust 172*c217d954SCole Faust ARM_COMPUTE_ASSERT(src.info()->is_resizable()); 173*c217d954SCole Faust ARM_COMPUTE_ASSERT(weights.info()->is_resizable()); 174*c217d954SCole Faust ARM_COMPUTE_ASSERT(bias.info()->is_resizable()); 175*c217d954SCole Faust ARM_COMPUTE_ASSERT(dst.info()->is_resizable()); 176*c217d954SCole Faust 177*c217d954SCole Faust // Allocate tensors 178*c217d954SCole Faust src.allocator()->allocate(); 179*c217d954SCole Faust weights.allocator()->allocate(); 180*c217d954SCole Faust bias.allocator()->allocate(); 181*c217d954SCole Faust dst.allocator()->allocate(); 182*c217d954SCole Faust 183*c217d954SCole Faust ARM_COMPUTE_ASSERT(!src.info()->is_resizable()); 184*c217d954SCole Faust ARM_COMPUTE_ASSERT(!weights.info()->is_resizable()); 185*c217d954SCole Faust ARM_COMPUTE_ASSERT(!bias.info()->is_resizable()); 186*c217d954SCole Faust ARM_COMPUTE_ASSERT(!dst.info()->is_resizable()); 187*c217d954SCole Faust 188*c217d954SCole Faust // Fill tensors 189*c217d954SCole Faust fill(AccessorType(src), 0); 190*c217d954SCole Faust fill(AccessorType(weights), 1); 191*c217d954SCole Faust fill(AccessorType(bias), 2); 192*c217d954SCole Faust 193*c217d954SCole Faust if(_mixed_layout) 194*c217d954SCole Faust { 195*c217d954SCole Faust mix_layout(conv, src, dst); 196*c217d954SCole Faust } 197*c217d954SCole Faust else 198*c217d954SCole Faust { 199*c217d954SCole Faust // Compute Convolution function 200*c217d954SCole Faust conv.run(); 201*c217d954SCole Faust } 202*c217d954SCole Faust 203*c217d954SCole Faust return dst; 204*c217d954SCole Faust } 205*c217d954SCole Faust compute_reference(const TensorShape & input_shape,const TensorShape & weights_shape,const TensorShape & bias_shape,const TensorShape & output_shape,const PadStrideInfo & info,DataType data_type,DataType bias_data_type,QuantizationInfo quantization_info,ActivationLayerInfo act_info)206*c217d954SCole Faust SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info, 207*c217d954SCole Faust DataType data_type, DataType bias_data_type, QuantizationInfo quantization_info, ActivationLayerInfo act_info) 208*c217d954SCole Faust { 209*c217d954SCole Faust // Create reference 210*c217d954SCole Faust SimpleTensor<T> src{ input_shape, data_type, 1, quantization_info }; 211*c217d954SCole Faust SimpleTensor<T> weights{ weights_shape, data_type, 1, quantization_info }; 212*c217d954SCole Faust SimpleTensor<TBias> bias{ bias_shape, bias_data_type, 1, quantization_info }; 213*c217d954SCole Faust 214*c217d954SCole Faust // Fill reference 215*c217d954SCole Faust fill(src, 0); 216*c217d954SCole Faust fill(weights, 1); 217*c217d954SCole Faust fill(bias, 2); 218*c217d954SCole Faust 219*c217d954SCole Faust SimpleTensor<T> dst = reference::convolution_layer<T>(src, weights, bias, output_shape, info); 220*c217d954SCole Faust return (act_info.enabled()) ? reference::activation_layer<T>(dst, act_info) : dst; 221*c217d954SCole Faust } 222*c217d954SCole Faust TensorType _target{}; 223*c217d954SCole Faust SimpleTensor<T> _reference{}; 224*c217d954SCole Faust QuantizationInfo _quantization_info{}; 225*c217d954SCole Faust DataType _data_type{}; 226*c217d954SCole Faust bool _mixed_layout{ false }; 227*c217d954SCole Faust }; 228*c217d954SCole Faust 229*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false> 230*c217d954SCole Faust class DirectConvolutionValidationFixture : public DirectConvolutionValidationGenericFixture<TensorType, AccessorType, FunctionType, T> 231*c217d954SCole Faust { 232*c217d954SCole Faust public: 233*c217d954SCole Faust template <typename...> setup(TensorShape input_shape,int stride_x,int stride_y,int pad_x,int pad_y,unsigned int kernel_size,unsigned int num_kernels,DataType data_type,ActivationLayerInfo act_info,DataLayout data_layout)234*c217d954SCole Faust void setup(TensorShape input_shape, int stride_x, int stride_y, int pad_x, int pad_y, unsigned int kernel_size, unsigned int num_kernels, DataType data_type, ActivationLayerInfo act_info, 235*c217d954SCole Faust DataLayout data_layout) 236*c217d954SCole Faust { 237*c217d954SCole Faust DirectConvolutionValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, stride_x, stride_y, pad_x, pad_y, kernel_size, num_kernels, data_type, QuantizationInfo(), 238*c217d954SCole Faust act_info, data_layout, mixed_layout); 239*c217d954SCole Faust } 240*c217d954SCole Faust }; 241*c217d954SCole Faust 242*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false> 243*c217d954SCole Faust class DirectConvolutionValidationQuantizedFixture : public DirectConvolutionValidationGenericFixture<TensorType, AccessorType, FunctionType, T> 244*c217d954SCole Faust { 245*c217d954SCole Faust public: 246*c217d954SCole Faust template <typename...> setup(TensorShape input_shape,int stride_x,int stride_y,int pad_x,int pad_y,unsigned int kernel_size,unsigned int num_kernels,DataType data_type,QuantizationInfo quantization_info,ActivationLayerInfo act_info,DataLayout data_layout)247*c217d954SCole Faust void setup(TensorShape input_shape, int stride_x, int stride_y, int pad_x, int pad_y, unsigned int kernel_size, unsigned int num_kernels, DataType data_type, QuantizationInfo quantization_info, 248*c217d954SCole Faust ActivationLayerInfo act_info, DataLayout data_layout) 249*c217d954SCole Faust { 250*c217d954SCole Faust DirectConvolutionValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, stride_x, stride_y, pad_x, pad_y, kernel_size, num_kernels, data_type, quantization_info, 251*c217d954SCole Faust act_info, data_layout, mixed_layout); 252*c217d954SCole Faust } 253*c217d954SCole Faust }; 254*c217d954SCole Faust 255*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T> 256*c217d954SCole Faust class DirectConvolutionValidationWithTensorShapesQuantizedFixture : public DirectConvolutionValidationGenericFixture<TensorType, AccessorType, FunctionType, T> 257*c217d954SCole Faust { 258*c217d954SCole Faust public: 259*c217d954SCole Faust template <typename...> setup(TensorShape input_shape,TensorShape weights_shape,TensorShape bias_shape,TensorShape output_shape,PadStrideInfo info,Size2D dilation,DataType data_type,QuantizationInfo quantization_info,ActivationLayerInfo act_info,DataLayout data_layout)260*c217d954SCole Faust void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, Size2D dilation, 261*c217d954SCole Faust DataType data_type, QuantizationInfo quantization_info, ActivationLayerInfo act_info, DataLayout data_layout) 262*c217d954SCole Faust { 263*c217d954SCole Faust DirectConvolutionValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, dilation, data_type, quantization_info, 264*c217d954SCole Faust act_info, data_layout); 265*c217d954SCole Faust } 266*c217d954SCole Faust }; 267*c217d954SCole Faust 268*c217d954SCole Faust template <typename TensorType, typename AccessorType, typename FunctionType, typename T> 269*c217d954SCole Faust class DirectConvolutionValidationWithTensorShapesFixture : public DirectConvolutionValidationGenericFixture<TensorType, AccessorType, FunctionType, T> 270*c217d954SCole Faust { 271*c217d954SCole Faust public: 272*c217d954SCole Faust template <typename...> setup(TensorShape input_shape,TensorShape weights_shape,TensorShape bias_shape,TensorShape output_shape,PadStrideInfo info,Size2D dilation,DataType data_type,ActivationLayerInfo act_info)273*c217d954SCole Faust void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, Size2D dilation, 274*c217d954SCole Faust DataType data_type, ActivationLayerInfo act_info) 275*c217d954SCole Faust { 276*c217d954SCole Faust DirectConvolutionValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(input_shape, weights_shape, bias_shape, output_shape, info, dilation, data_type, QuantizationInfo(), 277*c217d954SCole Faust act_info, DataLayout::NCHW); 278*c217d954SCole Faust } 279*c217d954SCole Faust }; 280*c217d954SCole Faust 281*c217d954SCole Faust } // namespace validation 282*c217d954SCole Faust } // namespace test 283*c217d954SCole Faust } // namespace arm_compute 284