1 /* 2 * Copyright (c) 2017-2022 Arm Limited. 3 * 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_SCALE_FIXTURE 25 #define ARM_COMPUTE_TEST_SCALE_FIXTURE 26 27 #include "tests/framework/Fixture.h" 28 #include "tests/validation/reference/Permute.h" 29 #include "tests/validation/reference/Scale.h" 30 31 namespace arm_compute 32 { 33 namespace test 34 { 35 namespace validation 36 { 37 template <typename TensorType, typename AccessorType, typename FunctionType, typename T> 38 class ScaleValidationGenericFixture : public framework::Fixture 39 { 40 public: 41 template <typename...> setup(TensorShape shape,DataType data_type,QuantizationInfo quantization_info,DataLayout data_layout,InterpolationPolicy policy,BorderMode border_mode,SamplingPolicy sampling_policy,bool align_corners,bool mixed_layout,QuantizationInfo output_quantization_info)42 void setup(TensorShape shape, DataType data_type, QuantizationInfo quantization_info, DataLayout data_layout, InterpolationPolicy policy, BorderMode border_mode, SamplingPolicy sampling_policy, 43 bool align_corners, bool mixed_layout, QuantizationInfo output_quantization_info) 44 { 45 _shape = shape; 46 _policy = policy; 47 _border_mode = border_mode; 48 _sampling_policy = sampling_policy; 49 _data_type = data_type; 50 _input_quantization_info = quantization_info; 51 _output_quantization_info = output_quantization_info; 52 _align_corners = align_corners; 53 _mixed_layout = mixed_layout; 54 55 generate_scale(shape); 56 57 std::mt19937 generator(library->seed()); 58 std::uniform_int_distribution<uint32_t> distribution_u8(0, 255); 59 _constant_border_value = static_cast<T>(distribution_u8(generator)); 60 61 _target = compute_target(shape, data_layout); 62 _reference = compute_reference(shape); 63 } 64 65 protected: mix_layout(FunctionType & layer,TensorType & src,TensorType & dst)66 void mix_layout(FunctionType &layer, TensorType &src, TensorType &dst) 67 { 68 const DataLayout data_layout = src.info()->data_layout(); 69 // Test Multi DataLayout graph cases, when the data layout changes after configure 70 src.info()->set_data_layout(data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW); 71 dst.info()->set_data_layout(data_layout == DataLayout::NCHW ? DataLayout::NHWC : DataLayout::NCHW); 72 73 // Compute Convolution function 74 layer.run(); 75 76 // Reinstating original data layout for the test suite to properly check the values 77 src.info()->set_data_layout(data_layout); 78 dst.info()->set_data_layout(data_layout); 79 } 80 generate_scale(const TensorShape & shape)81 void generate_scale(const TensorShape &shape) 82 { 83 static constexpr float _min_scale{ 0.25f }; 84 static constexpr float _max_scale{ 3.f }; 85 86 constexpr float max_width{ 8192.0f }; 87 constexpr float max_height{ 6384.0f }; 88 const float min_width{ 1.f }; 89 const float min_height{ 1.f }; 90 91 std::mt19937 generator(library->seed()); 92 std::uniform_real_distribution<float> distribution_float(_min_scale, _max_scale); 93 94 auto generate = [&](size_t input_size, float min_output, float max_output) -> float 95 { 96 const float generated_scale = distribution_float(generator); 97 const float output_size = utility::clamp(static_cast<float>(input_size) * generated_scale, min_output, max_output); 98 return output_size / input_size; 99 }; 100 101 // Input shape is always given in NCHW layout. NHWC is dealt by permute in compute_target() 102 const int idx_width = get_data_layout_dimension_index(DataLayout::NCHW, DataLayoutDimension::WIDTH); 103 const int idx_height = get_data_layout_dimension_index(DataLayout::NCHW, DataLayoutDimension::HEIGHT); 104 105 _scale_x = generate(shape[idx_width], min_width, max_width); 106 _scale_y = generate(shape[idx_height], min_height, max_height); 107 } 108 109 template <typename U> fill(U && tensor)110 void fill(U &&tensor) 111 { 112 if(tensor.data_type() == DataType::F32) 113 { 114 std::uniform_real_distribution<float> distribution(-5.0f, 5.0f); 115 library->fill(tensor, distribution, 0); 116 } 117 else if(tensor.data_type() == DataType::F16) 118 { 119 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ -5.0f, 5.0f }; 120 library->fill(tensor, distribution, 0); 121 } 122 else if(is_data_type_quantized(tensor.data_type())) 123 { 124 std::uniform_int_distribution<> distribution(0, 100); 125 library->fill(tensor, distribution, 0); 126 } 127 else 128 { 129 library->fill_tensor_uniform(tensor, 0); 130 } 131 } 132 compute_target(TensorShape shape,DataLayout data_layout)133 TensorType compute_target(TensorShape shape, DataLayout data_layout) 134 { 135 // Change shape in case of NHWC. 136 if(data_layout == DataLayout::NHWC) 137 { 138 permute(shape, PermutationVector(2U, 0U, 1U)); 139 } 140 141 // Create tensors 142 TensorType src = create_tensor<TensorType>(shape, _data_type, 1, _input_quantization_info, data_layout); 143 144 const int idx_width = get_data_layout_dimension_index(data_layout, DataLayoutDimension::WIDTH); 145 const int idx_height = get_data_layout_dimension_index(data_layout, DataLayoutDimension::HEIGHT); 146 147 TensorShape shape_scaled(shape); 148 shape_scaled.set(idx_width, shape[idx_width] * _scale_x, /* apply_dim_correction = */ false); 149 shape_scaled.set(idx_height, shape[idx_height] * _scale_y, /* apply_dim_correction = */ false); 150 TensorType dst = create_tensor<TensorType>(shape_scaled, _data_type, 1, _output_quantization_info, data_layout); 151 152 // Create and configure function 153 FunctionType scale; 154 155 scale.configure(&src, &dst, ScaleKernelInfo{ _policy, _border_mode, _constant_border_value, _sampling_policy, /* use_padding */ false, _align_corners }); 156 157 ARM_COMPUTE_ASSERT(src.info()->is_resizable()); 158 ARM_COMPUTE_ASSERT(dst.info()->is_resizable()); 159 160 add_padding_x({ &src, &dst }, data_layout); 161 162 // Allocate tensors 163 src.allocator()->allocate(); 164 dst.allocator()->allocate(); 165 ARM_COMPUTE_ASSERT(!src.info()->is_resizable()); 166 ARM_COMPUTE_ASSERT(!dst.info()->is_resizable()); 167 168 // Fill tensors 169 fill(AccessorType(src)); 170 171 if(_mixed_layout) 172 { 173 mix_layout(scale, src, dst); 174 } 175 else 176 { 177 // Compute function 178 scale.run(); 179 } 180 return dst; 181 } 182 compute_reference(const TensorShape & shape)183 SimpleTensor<T> compute_reference(const TensorShape &shape) 184 { 185 // Create reference 186 SimpleTensor<T> src{ shape, _data_type, 1, _input_quantization_info }; 187 188 // Fill reference 189 fill(src); 190 191 return reference::scale<T>(src, _scale_x, _scale_y, _policy, _border_mode, _constant_border_value, _sampling_policy, /* ceil_policy_scale */ false, _align_corners, _output_quantization_info); 192 } 193 194 TensorType _target{}; 195 SimpleTensor<T> _reference{}; 196 TensorShape _shape{}; 197 InterpolationPolicy _policy{}; 198 BorderMode _border_mode{}; 199 T _constant_border_value{}; 200 SamplingPolicy _sampling_policy{}; 201 DataType _data_type{}; 202 QuantizationInfo _input_quantization_info{}; 203 QuantizationInfo _output_quantization_info{}; 204 bool _align_corners{ false }; 205 bool _mixed_layout{ false }; 206 float _scale_x{ 1.f }; 207 float _scale_y{ 1.f }; 208 }; 209 210 template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false> 211 class ScaleValidationQuantizedFixture : public ScaleValidationGenericFixture<TensorType, AccessorType, FunctionType, T> 212 { 213 public: 214 template <typename...> setup(TensorShape shape,DataType data_type,QuantizationInfo quantization_info,DataLayout data_layout,InterpolationPolicy policy,BorderMode border_mode,SamplingPolicy sampling_policy,bool align_corners)215 void setup(TensorShape shape, DataType data_type, QuantizationInfo quantization_info, DataLayout data_layout, InterpolationPolicy policy, BorderMode border_mode, SamplingPolicy sampling_policy, 216 bool align_corners) 217 { 218 ScaleValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, 219 data_type, 220 quantization_info, 221 data_layout, 222 policy, 223 border_mode, 224 sampling_policy, 225 align_corners, 226 mixed_layout, 227 quantization_info); 228 } 229 }; 230 template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false> 231 class ScaleValidationDifferentOutputQuantizedFixture : public ScaleValidationGenericFixture<TensorType, AccessorType, FunctionType, T> 232 { 233 public: 234 template <typename...> setup(TensorShape shape,DataType data_type,QuantizationInfo input_quantization_info,QuantizationInfo output_quantization_info,DataLayout data_layout,InterpolationPolicy policy,BorderMode border_mode,SamplingPolicy sampling_policy,bool align_corners)235 void setup(TensorShape shape, DataType data_type, QuantizationInfo input_quantization_info, QuantizationInfo output_quantization_info, DataLayout data_layout, InterpolationPolicy policy, 236 BorderMode border_mode, SamplingPolicy sampling_policy, 237 bool align_corners) 238 { 239 ScaleValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, 240 data_type, 241 input_quantization_info, 242 data_layout, 243 policy, 244 border_mode, 245 sampling_policy, 246 align_corners, 247 mixed_layout, 248 output_quantization_info); 249 } 250 }; 251 template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool mixed_layout = false> 252 class ScaleValidationFixture : public ScaleValidationGenericFixture<TensorType, AccessorType, FunctionType, T> 253 { 254 public: 255 template <typename...> setup(TensorShape shape,DataType data_type,DataLayout data_layout,InterpolationPolicy policy,BorderMode border_mode,SamplingPolicy sampling_policy,bool align_corners)256 void setup(TensorShape shape, DataType data_type, DataLayout data_layout, InterpolationPolicy policy, BorderMode border_mode, SamplingPolicy sampling_policy, bool align_corners) 257 { 258 ScaleValidationGenericFixture<TensorType, AccessorType, FunctionType, T>::setup(shape, 259 data_type, 260 QuantizationInfo(), 261 data_layout, 262 policy, 263 border_mode, 264 sampling_policy, 265 align_corners, 266 mixed_layout, 267 QuantizationInfo()); 268 } 269 }; 270 } // namespace validation 271 } // namespace test 272 } // namespace arm_compute 273 #endif /* ARM_COMPUTE_TEST_SCALE_FIXTURE */ 274