blob: 1061fd00ab792eb53f02aacd7366e20e2cb4a3a9 [file] [log] [blame]
Pablo Tello89519332017-11-17 11:52:36 +00001/*
Giorgio Arenab309fc22021-01-05 09:46:16 +00002 * Copyright (c) 2018-2021 Arm Limited.
Pablo Tello89519332017-11-17 11:52:36 +00003 *
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_WINOGRAD_LAYER_FIXTURE
25#define ARM_COMPUTE_TEST_WINOGRAD_LAYER_FIXTURE
26
27#include "arm_compute/core/TensorShape.h"
28#include "arm_compute/core/Types.h"
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +000029#include "arm_compute/core/utils/misc/ShapeCalculator.h"
Pablo Tello89519332017-11-17 11:52:36 +000030#include "tests/AssetsLibrary.h"
31#include "tests/Globals.h"
32#include "tests/IAccessor.h"
33#include "tests/framework/Asserts.h"
34#include "tests/framework/Fixture.h"
Pablo Tello89519332017-11-17 11:52:36 +000035#include "tests/validation/Helpers.h"
Isabella Gottardi3f217ec2018-02-12 14:59:19 +000036#include "tests/validation/reference/ActivationLayer.h"
Georgios Pinitas5a7e7762017-12-01 16:27:29 +000037#include "tests/validation/reference/ConvolutionLayer.h"
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +010038#include "tests/validation/reference/GEMM.h"
Giorgio Arena3695f9a2018-04-23 17:41:22 +010039#include "tests/validation/reference/Permute.h"
Georgios Pinitas5a7e7762017-12-01 16:27:29 +000040#include "tests/validation/reference/Utils.h"
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +000041#include "tests/validation/reference/Winograd.h"
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +000042#include "utils/Utils.h"
Pablo Tello89519332017-11-17 11:52:36 +000043
44#include <random>
45
46namespace arm_compute
47{
Pablo Tello89519332017-11-17 11:52:36 +000048namespace test
49{
50namespace validation
51{
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +000052using namespace arm_compute::misc::shape_calculator;
53
Andrew Mundy4d9379a2018-03-15 16:47:03 +000054template <typename TensorType, typename AccessorType, typename FunctionType, typename T, bool use_bias = true>
Gian Marco Iodiced2fab732018-03-02 11:18:12 +000055class WinogradConvolutionLayerValidationFixture : public framework::Fixture
Pablo Tello89519332017-11-17 11:52:36 +000056{
57public:
58 template <typename...>
Pablo Tello7df27862018-05-30 11:44:26 +010059 void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, Size2D dilation,
60 DataType data_type, ActivationLayerInfo act_info)
Pablo Tello89519332017-11-17 11:52:36 +000061 {
Alex Gilday7da29b62018-03-23 14:16:00 +000062 ARM_COMPUTE_UNUSED(dilation);
63
Isabella Gottardi3f217ec2018-02-12 14:59:19 +000064 _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, data_type, act_info);
65 _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type, act_info);
Pablo Tello89519332017-11-17 11:52:36 +000066 }
67
68protected:
69 template <typename U>
70 void fill(U &&tensor, int i, float min, float max)
71 {
72 switch(tensor.data_type())
73 {
Vidhya Sudhan Loganathan71ecf392018-08-31 16:10:16 +010074 case DataType::F16:
Giorgio Arena4bdd1772020-12-17 16:47:07 +000075 {
76 arm_compute::utils::uniform_real_distribution_fp16 distribution{ half(min), half(max) };
77 library->fill(tensor, distribution, i);
78 break;
79 }
Pablo Tello89519332017-11-17 11:52:36 +000080 case DataType::F32:
81 {
Giorgio Arena4bdd1772020-12-17 16:47:07 +000082 std::uniform_real_distribution<float> distribution(min, max);
Pablo Tello89519332017-11-17 11:52:36 +000083 library->fill(tensor, distribution, i);
84 break;
85 }
86 default:
87 {
88 ARM_COMPUTE_ERROR("Not supported");
Pablo Tello89519332017-11-17 11:52:36 +000089 }
90 }
91 }
92
Pablo Tello7df27862018-05-30 11:44:26 +010093 TensorType compute_target(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, const PadStrideInfo &info,
Isabella Gottardi3f217ec2018-02-12 14:59:19 +000094 DataType data_type, ActivationLayerInfo act_info)
Pablo Tello89519332017-11-17 11:52:36 +000095 {
96 // Create tensors
Gian Marco Iodiced2fab732018-03-02 11:18:12 +000097 TensorType src = create_tensor<TensorType>(input_shape, data_type, 1);
98 TensorType weights = create_tensor<TensorType>(weights_shape, data_type, 1);
99 TensorType bias = create_tensor<TensorType>(bias_shape, data_type, 1);
100 TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1);
Pablo Tello89519332017-11-17 11:52:36 +0000101
102 // Create and configure function
103 FunctionType conv;
Vidhya Sudhan Loganathan84ce1f92018-04-25 13:00:09 +0100104 ARM_COMPUTE_EXPECT(static_cast<bool>(conv.validate(src.info(), weights.info(), (use_bias) ? bias.info() : nullptr, dst.info(), info, act_info)), framework::LogLevel::ERRORS);
Andrew Mundy4d9379a2018-03-15 16:47:03 +0000105 conv.configure(&src, &weights, (use_bias) ? &bias : nullptr, &dst, info, act_info);
Pablo Tello89519332017-11-17 11:52:36 +0000106
107 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
108 ARM_COMPUTE_EXPECT(weights.info()->is_resizable(), framework::LogLevel::ERRORS);
109 ARM_COMPUTE_EXPECT(bias.info()->is_resizable(), framework::LogLevel::ERRORS);
110 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
111
112 // Allocate tensors
113 src.allocator()->allocate();
114 weights.allocator()->allocate();
Pablo Tello89519332017-11-17 11:52:36 +0000115 dst.allocator()->allocate();
Pablo Tellod6ca4782018-01-23 09:36:04 +0000116 bias.allocator()->allocate();
Pablo Tello89519332017-11-17 11:52:36 +0000117
118 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
119 ARM_COMPUTE_EXPECT(!weights.info()->is_resizable(), framework::LogLevel::ERRORS);
120 ARM_COMPUTE_EXPECT(!bias.info()->is_resizable(), framework::LogLevel::ERRORS);
121 ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
122
123 // Fill tensors
124 fill(AccessorType(src), 0, -1.f, 1.f);
125 fill(AccessorType(weights), 1, -1.f, 1.f);
Pablo Tellod6ca4782018-01-23 09:36:04 +0000126 fill(AccessorType(bias), 2, -1.f, 1.f);
Pablo Tello89519332017-11-17 11:52:36 +0000127
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000128 // Compute Winograd Convolution function
Pablo Tello89519332017-11-17 11:52:36 +0000129 conv.run();
130
131 return dst;
132 }
133
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000134 SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info,
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000135 DataType data_type, ActivationLayerInfo act_info)
Pablo Tello89519332017-11-17 11:52:36 +0000136 {
137 // Create reference
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000138 SimpleTensor<T> src{ input_shape, data_type, 1 };
139 SimpleTensor<T> weights{ weights_shape, data_type, 1 };
140 SimpleTensor<T> bias{ bias_shape, data_type, 1 };
Pablo Tello89519332017-11-17 11:52:36 +0000141
142 // Fill reference
143 fill(src, 0, -1.f, 1.f);
144 fill(weights, 1, -1.f, 1.f);
Andrew Mundy4d9379a2018-03-15 16:47:03 +0000145 if(use_bias)
146 {
147 fill(bias, 2, -1.f, 1.f);
148 }
149 else
150 {
151 fill(bias, 2, 0.f, 0.f);
152 }
Pablo Tello89519332017-11-17 11:52:36 +0000153
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000154 SimpleTensor<T> conv_out = reference::convolution_layer<T>(src, weights, bias, output_shape, info);
155
156 return (act_info.enabled()) ? reference::activation_layer<T>(conv_out, act_info) : conv_out;
Pablo Tello89519332017-11-17 11:52:36 +0000157 }
158
159 TensorType _target{};
160 SimpleTensor<T> _reference{};
Pablo Tello89519332017-11-17 11:52:36 +0000161};
162
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000163template <typename TensorType, typename AccessorType, typename FunctionType, typename T, typename T1 = T, bool use_bias = true>
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100164class WinogradConvolutionLayerFastMathValidationFixture : public framework::Fixture
165{
166public:
167 template <typename...>
Pablo Tello7282d562018-06-14 15:35:49 +0100168 void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, Size2D dilation,
169 DataType data_type, ActivationLayerInfo act_info, const DataLayout &data_layout)
170
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100171 {
172 ARM_COMPUTE_UNUSED(dilation);
Pablo Tello7282d562018-06-14 15:35:49 +0100173 _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, data_type, act_info, data_layout);
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100174 _reference = compute_reference(input_shape, weights_shape, bias_shape, info, data_type, act_info);
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100175 }
176
177protected:
178 template <typename U>
179 void fill(U &&tensor, int i, float min, float max)
180 {
181 switch(tensor.data_type())
182 {
Vidhya Sudhan Loganathan71ecf392018-08-31 16:10:16 +0100183 case DataType::F16:
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000184 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000185 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ float(min), float(max) };
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000186 library->fill(tensor, distribution, i);
187 break;
188 }
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100189 case DataType::F32:
190 {
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000191 std::uniform_real_distribution<float> distribution(min, max);
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100192 library->fill(tensor, distribution, i);
193 break;
194 }
195 default:
196 {
197 ARM_COMPUTE_ERROR("Not supported");
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100198 }
199 }
200 }
201
Pablo Tello7282d562018-06-14 15:35:49 +0100202 TensorType compute_target(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, const PadStrideInfo &info,
203 DataType data_type, ActivationLayerInfo act_info, const DataLayout data_layout)
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100204 {
Pablo Tello7282d562018-06-14 15:35:49 +0100205 if(data_layout == DataLayout::NHWC)
206 {
207 permute(input_shape, PermutationVector(2U, 0U, 1U));
208 permute(weights_shape, PermutationVector(2U, 0U, 1U));
209 permute(output_shape, PermutationVector(2U, 0U, 1U));
210 }
211
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100212 // Create tensors
Vidhya Sudhan Loganathan014333d2018-07-02 09:13:49 +0100213 TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, QuantizationInfo(), data_layout);
214 TensorType weights = create_tensor<TensorType>(weights_shape, data_type, 1, QuantizationInfo(), data_layout);
215 TensorType bias = create_tensor<TensorType>(bias_shape, data_type, 1, QuantizationInfo(), data_layout);
216 TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, QuantizationInfo(), data_layout);
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100217
218 // Create and configure function
219 FunctionType conv;
Giorgio Arenaa3221e62018-05-03 15:57:48 +0100220 ARM_COMPUTE_EXPECT(static_cast<bool>(conv.validate(src.info(), weights.info(), (use_bias) ? bias.info() : nullptr, dst.info(), info, act_info, true /* Enable fast math */)),
221 framework::LogLevel::ERRORS);
222 conv.configure(&src, &weights, (use_bias) ? &bias : nullptr, &dst, info, act_info, true /* Enable fast math */);
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100223
224 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
225 ARM_COMPUTE_EXPECT(weights.info()->is_resizable(), framework::LogLevel::ERRORS);
226 ARM_COMPUTE_EXPECT(bias.info()->is_resizable(), framework::LogLevel::ERRORS);
227 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
228
229 // Allocate tensors
230 src.allocator()->allocate();
231 weights.allocator()->allocate();
232 dst.allocator()->allocate();
233 bias.allocator()->allocate();
234
235 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
236 ARM_COMPUTE_EXPECT(!weights.info()->is_resizable(), framework::LogLevel::ERRORS);
237 ARM_COMPUTE_EXPECT(!bias.info()->is_resizable(), framework::LogLevel::ERRORS);
238 ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
239
240 // Fill tensors
Gian Marco Iodice6f688fd2019-08-19 11:45:26 +0100241 fill(AccessorType(src), 0, -0.5f, 0.5f);
242 fill(AccessorType(weights), 1, -0.5f, 0.5f);
243 fill(AccessorType(bias), 2, -0.5f, 0.5f);
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100244
245 // Compute Winograd Convolution function
246 conv.run();
247
248 return dst;
249 }
250
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100251 SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const PadStrideInfo &info,
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100252 DataType data_type, ActivationLayerInfo act_info)
253 {
254 // Create reference
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000255 SimpleTensor<T> src_t{ input_shape, data_type, 1 };
256 SimpleTensor<T> weights_t{ weights_shape, data_type, 1 };
257 SimpleTensor<T> bias_t{ bias_shape, data_type, 1 };
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100258
259 // Fill reference
Gian Marco Iodice6f688fd2019-08-19 11:45:26 +0100260 fill(src_t, 0, -0.5f, 0.5f);
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000261 SimpleTensor<T1> src_t1(copy_tensor<T1, T>(src_t));
262
Gian Marco Iodice6f688fd2019-08-19 11:45:26 +0100263 fill(weights_t, 1, -0.5f, 0.5f);
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000264 SimpleTensor<T1> weights_t1(copy_tensor<T1, T>(weights_t));
Giorgio Arenaa3221e62018-05-03 15:57:48 +0100265 if(use_bias)
266 {
Gian Marco Iodice6f688fd2019-08-19 11:45:26 +0100267 fill(bias_t, 2, -0.5f, 0.5f);
Giorgio Arenaa3221e62018-05-03 15:57:48 +0100268 }
269 else
270 {
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000271 fill(bias_t, 2, 0.f, 0.f);
Giorgio Arenaa3221e62018-05-03 15:57:48 +0100272 }
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000273 SimpleTensor<T1> bias_t1(copy_tensor<T1, T>(bias_t));
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100274
Gian Marco Iodicef1c2bf02018-06-13 14:05:54 +0100275 // Set output tile
276 Size2D output_tile(4U, 4U);
Pablo Tello96e922e2018-09-26 11:25:15 +0100277 if(weights_shape[0] == 7 && weights_shape[1] == 1)
278 {
279 output_tile.width = 2;
280 output_tile.height = 1;
281 }
282 else if(weights_shape[0] == 1 && weights_shape[1] == 7)
283 {
284 output_tile.width = 1;
285 output_tile.height = 2;
286 }
287 else if(weights_shape[0] == 1)
Gian Marco Iodicef1c2bf02018-06-13 14:05:54 +0100288 {
289 output_tile.width = 1;
290 }
291 else if(weights_shape[1] == 1)
292 {
293 output_tile.height = 1;
294 }
295
296 WinogradInfo winograd_info(output_tile,
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100297 Size2D(weights_shape[0], weights_shape[1]),
298 Size2D(input_shape[0], input_shape[1]),
299 info,
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000300 src_t1.data_layout());
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100301
302 // Compute tensor shapes for input, filter and output transforms
303 TensorShape input_transform_shape = compute_winograd_input_transform_shape(TensorInfo(input_shape, 1, data_type), winograd_info);
304 TensorShape filter_transform_shape = compute_winograd_filter_transform_shape(TensorInfo(weights_shape, 1, data_type), winograd_info);
305 TensorShape batched_gemm_shape = input_transform_shape;
306 batched_gemm_shape[0] = filter_transform_shape[0];
307 TensorShape output_transform_shape = compute_winograd_output_transform_shape(TensorInfo(batched_gemm_shape, 1, data_type), winograd_info);
308
309 // Dummy matrix C to perform matrix multiplication
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000310 SimpleTensor<T1> dummy_c{ batched_gemm_shape, data_type, 1 };
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100311
312 // Compute Winograd-based convolution
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000313 SimpleTensor<T1> input_transform_out = reference::winograd_input_transform<T1>(src_t1, input_transform_shape, winograd_info);
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100314
Vidhya Sudhan Loganathana25d16c2018-11-16 11:33:12 +0000315 SimpleTensor<T1> filter_transform_out = reference::winograd_filter_transform<T1>(weights_t1, filter_transform_shape, winograd_info);
316 SimpleTensor<T1> batched_gemm = reference::gemm<T1>(input_transform_out, filter_transform_out, dummy_c, 1.0f, 0.0f);
317 SimpleTensor<T1> conv_out = reference::winograd_output_transform<T1>(batched_gemm, bias_t1, output_transform_shape, winograd_info);
318 SimpleTensor<T> conv_out_t(std::move(copy_tensor<T, T1>(conv_out)));
319 return (act_info.enabled()) ? reference::activation_layer<T>(conv_out_t, act_info) : conv_out_t;
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100320 }
321
322 TensorType _target{};
323 SimpleTensor<T> _reference{};
324};
325
326template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000327class WinogradInputTransformValidationFixture : public framework::Fixture
328{
329public:
330 template <typename...>
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000331 void setup(TensorShape input_shape, WinogradInfo winograd_info, DataLayout data_layout, DataType data_type)
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000332 {
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000333 TensorShape output_shape = compute_winograd_input_transform_shape(TensorInfo(input_shape, 1, data_type), winograd_info);
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000334
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000335 _target = compute_target(input_shape, output_shape, winograd_info, data_layout, data_type);
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100336 _reference = compute_reference(input_shape, output_shape, winograd_info, data_type);
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000337 }
338
339protected:
340 template <typename U>
341 void fill(U &&tensor, int i, float min, float max)
342 {
343 switch(tensor.data_type())
344 {
Vidhya Sudhan Loganathan71ecf392018-08-31 16:10:16 +0100345 case DataType::F16:
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000346 {
347 arm_compute::utils::uniform_real_distribution_fp16 distribution{ half(min), half(max) };
348 library->fill(tensor, distribution, i);
349 break;
350 }
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000351 case DataType::F32:
352 {
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000353 std::uniform_real_distribution<float> distribution(min, max);
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000354 library->fill(tensor, distribution, i);
355 break;
356 }
357 default:
358 {
359 ARM_COMPUTE_ERROR("Not supported");
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000360 }
361 }
362 }
363
Giorgio Arenac42f28d2018-04-26 11:33:05 +0100364 TensorType compute_target(TensorShape input_shape, const TensorShape &output_shape, const WinogradInfo &winograd_info, DataLayout data_layout, DataType data_type)
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000365 {
Giorgio Arenac42f28d2018-04-26 11:33:05 +0100366 if(data_layout == DataLayout::NHWC)
367 {
368 permute(input_shape, PermutationVector(2U, 0U, 1U));
369 }
370
Vidhya Sudhan Loganathan014333d2018-07-02 09:13:49 +0100371 TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, QuantizationInfo(), data_layout);
372 TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, QuantizationInfo());
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000373
374 // Create and configure function
375 FunctionType transf;
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000376 transf.configure(&src, &dst, winograd_info);
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000377
378 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
379 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
380
381 // Allocate tensors
382 src.allocator()->allocate();
383 dst.allocator()->allocate();
384
385 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
386 ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
387
388 // Fill tensors
389 fill(AccessorType(src), 0, -1.f, 1.f);
390
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000391 // Compute Winograd input transform function
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000392 transf.run();
393
394 return dst;
395 }
396
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100397 SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &output_shape, const WinogradInfo &winograd_info, DataType data_type)
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000398 {
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000399 // Create reference
Vidhya Sudhan Loganathan014333d2018-07-02 09:13:49 +0100400 SimpleTensor<T> src{ input_shape, data_type, 1, QuantizationInfo() };
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000401
402 // Fill reference
403 fill(src, 0, -1.f, 1.f);
404
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000405 return reference::winograd_input_transform<T>(src, output_shape, winograd_info);
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000406 }
407
408 TensorType _target{};
409 SimpleTensor<T> _reference{};
410};
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000411
412template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
413class WinogradFilterTransformValidationFixture : public framework::Fixture
414{
415public:
416 template <typename...>
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000417 void setup(TensorShape input_shape, Size2D output_tile, DataLayout data_layout, DataType data_type)
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000418 {
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000419 WinogradInfo winograd_info(output_tile, Size2D(input_shape[0], input_shape[1]), Size2D() /* Not needed */, PadStrideInfo() /* Not needed */, DataLayout::NCHW /* Not needed */);
420 TensorShape output_shape = compute_winograd_filter_transform_shape(TensorInfo(input_shape, 1, data_type), winograd_info);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000421
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000422 _target = compute_target(input_shape, output_shape, winograd_info, data_layout, data_type);
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100423 _reference = compute_reference(input_shape, output_shape, winograd_info, data_type);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000424 }
425
426protected:
427 template <typename U>
428 void fill(U &&tensor, int i, float min, float max)
429 {
430 switch(tensor.data_type())
431 {
Vidhya Sudhan Loganathan71ecf392018-08-31 16:10:16 +0100432 case DataType::F16:
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000433 {
434 arm_compute::utils::uniform_real_distribution_fp16 distribution{ half(min), half(max) };
435 library->fill(tensor, distribution, i);
436 break;
437 }
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000438 case DataType::F32:
439 {
Giorgio Arena4bdd1772020-12-17 16:47:07 +0000440 std::uniform_real_distribution<float> distribution(min, max);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000441 library->fill(tensor, distribution, i);
442 break;
443 }
444 default:
445 {
446 ARM_COMPUTE_ERROR("Not supported");
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000447 }
448 }
449 }
450
Giorgio Arenadcb5b282018-04-25 12:07:29 +0100451 TensorType compute_target(TensorShape input_shape, const TensorShape &output_shape, const WinogradInfo &winograd_info, DataLayout data_layout, DataType data_type)
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000452 {
Giorgio Arenadcb5b282018-04-25 12:07:29 +0100453 if(data_layout == DataLayout::NHWC)
454 {
455 permute(input_shape, PermutationVector(2U, 0U, 1U));
456 }
457
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000458 // Create tensors
Vidhya Sudhan Loganathan014333d2018-07-02 09:13:49 +0100459 TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, QuantizationInfo(), data_layout);
460 TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, QuantizationInfo());
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000461
462 // Create and configure function
463 FunctionType filter_transform;
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000464 filter_transform.configure(&src, &dst, winograd_info);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000465
466 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
467 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
468
469 // Allocate tensors
470 src.allocator()->allocate();
471 dst.allocator()->allocate();
472
473 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
474 ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
475
476 // Fill tensors
477 fill(AccessorType(src), 0, -1.f, 1.f);
478
479 filter_transform.run();
480
481 return dst;
482 }
483
Michalis Spyrou6bff1952019-10-02 17:22:11 +0100484 SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &output_shape, const WinogradInfo &winograd_info, DataType data_type)
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000485 {
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000486 // Create reference
Vidhya Sudhan Loganathan014333d2018-07-02 09:13:49 +0100487 SimpleTensor<T> src{ input_shape, data_type, 1, QuantizationInfo() };
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000488
489 // Fill reference
490 fill(src, 0, -1.f, 1.f);
491
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000492 return reference::winograd_filter_transform<T>(src, output_shape, winograd_info);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000493 }
494
495 TensorType _target{};
496 SimpleTensor<T> _reference{};
497};
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000498
499template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
500class WinogradOutputTransformValidationFixture : public framework::Fixture
501{
502public:
503 template <typename...>
Manuel Bottini0d0028c2018-10-02 16:41:52 +0100504 void setup(TensorShape input_shape, WinogradInfo winograd_info, DataType data_type, ActivationLayerInfo act_info = ActivationLayerInfo())
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000505 {
Manuel Bottini0d0028c2018-10-02 16:41:52 +0100506 _target = compute_target(input_shape, winograd_info, data_type, act_info);
507 _reference = compute_reference(input_shape, winograd_info, data_type, act_info);
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000508 }
509
510protected:
511 template <typename U>
512 void fill(U &&tensor, int i, float min, float max)
513 {
514 switch(tensor.data_type())
515 {
Vidhya Sudhan Loganathan71ecf392018-08-31 16:10:16 +0100516 case DataType::F16:
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000517 {
Giorgio Arenaa8e2aeb2021-01-06 11:34:57 +0000518 arm_compute::utils::uniform_real_distribution_16bit<half> distribution{ float(min), float(max) };
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000519 library->fill(tensor, distribution, i);
520 break;
521 }
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000522 case DataType::F32:
523 {
Giorgio Arena6aeb2172020-12-15 15:45:43 +0000524 std::uniform_real_distribution<float> distribution(min, max);
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000525 library->fill(tensor, distribution, i);
526 break;
527 }
528 default:
529 {
530 ARM_COMPUTE_ERROR("Not supported");
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000531 }
532 }
533 }
534
Manuel Bottini0d0028c2018-10-02 16:41:52 +0100535 TensorType compute_target(const TensorShape &input_shape, const WinogradInfo &winograd_info, DataType data_type, ActivationLayerInfo act_info)
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000536 {
Giorgio Arena3695f9a2018-04-23 17:41:22 +0100537 TensorShape output_shape = compute_winograd_output_transform_shape(TensorInfo(input_shape, 1, data_type), winograd_info);
538
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000539 // Create tensors
Giorgio Arenaea55f912018-07-12 15:41:35 +0100540 TensorType src = create_tensor<TensorType>(input_shape, data_type);
541 TensorType bias = create_tensor<TensorType>(output_shape[get_data_layout_dimension_index(winograd_info.output_data_layout, DataLayoutDimension::CHANNEL)], data_type);
542 TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, QuantizationInfo(), winograd_info.output_data_layout);
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000543
544 // Create and configure function
545 FunctionType output_transform;
Manuel Bottini0d0028c2018-10-02 16:41:52 +0100546 output_transform.configure(&src, &bias, &dst, winograd_info, act_info);
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000547
548 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
Giorgio Arenaea55f912018-07-12 15:41:35 +0100549 ARM_COMPUTE_EXPECT(bias.info()->is_resizable(), framework::LogLevel::ERRORS);
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000550 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
551
552 // Allocate tensors
553 src.allocator()->allocate();
Giorgio Arenaea55f912018-07-12 15:41:35 +0100554 bias.allocator()->allocate();
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000555 dst.allocator()->allocate();
556
557 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
Giorgio Arenaea55f912018-07-12 15:41:35 +0100558 ARM_COMPUTE_EXPECT(!bias.info()->is_resizable(), framework::LogLevel::ERRORS);
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000559 ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
560
561 // Fill tensors
562 fill(AccessorType(src), 0, -1.f, 1.f);
Giorgio Arenaea55f912018-07-12 15:41:35 +0100563 fill(AccessorType(bias), 1, -1.f, 1.f);
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000564
565 output_transform.run();
566
567 return dst;
568 }
569
Manuel Bottini0d0028c2018-10-02 16:41:52 +0100570 SimpleTensor<T> compute_reference(const TensorShape &input_shape, WinogradInfo winograd_info, DataType data_type, ActivationLayerInfo act_info)
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000571 {
Giorgio Arena3695f9a2018-04-23 17:41:22 +0100572 winograd_info.output_data_layout = DataLayout::NCHW;
573 TensorShape output_shape = compute_winograd_output_transform_shape(TensorInfo(input_shape, 1, data_type), winograd_info);
574
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000575 // Create reference
Gian Marco Iodice247f52c2018-03-22 11:24:56 +0000576 SimpleTensor<T> src{ input_shape, data_type };
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100577 SimpleTensor<T> bias{ TensorShape(input_shape[0]), data_type };
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000578
579 // Fill reference
580 fill(src, 0, -1.f, 1.f);
Giorgio Arenaea55f912018-07-12 15:41:35 +0100581 fill(bias, 1, -1.f, 1.f);
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000582
Manuel Bottini0d0028c2018-10-02 16:41:52 +0100583 const SimpleTensor<T> winograd_output = reference::winograd_output_transform<T>(src, bias, output_shape, winograd_info);
584
585 return (act_info.enabled()) ? reference::activation_layer<T>(winograd_output, act_info) : winograd_output;
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000586 }
587
588 TensorType _target{};
589 SimpleTensor<T> _reference{};
590};
Pablo Tello89519332017-11-17 11:52:36 +0000591} // namespace validation
592} // namespace test
593} // namespace arm_compute
594#endif /* ARM_COMPUTE_TEST_WINOGRAD_LAYER_FIXTURE */