blob: c427f8d20ee80ec85e439ea41ec292f21afcb514 [file] [log] [blame]
Pablo Tello89519332017-11-17 11:52:36 +00001/*
Pablo Tellod6ca4782018-01-23 09:36:04 +00002 * Copyright (c) 2017-2018 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"
Georgios Pinitas5a7e7762017-12-01 16:27:29 +000036#include "tests/validation/reference/ConvolutionLayer.h"
37#include "tests/validation/reference/Utils.h"
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +000038#include "tests/validation/reference/Winograd.h"
Pablo Tello89519332017-11-17 11:52:36 +000039
40#include <random>
41
42namespace arm_compute
43{
Pablo Tello89519332017-11-17 11:52:36 +000044namespace test
45{
46namespace validation
47{
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +000048using namespace arm_compute::misc::shape_calculator;
49
Pablo Tello89519332017-11-17 11:52:36 +000050template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
Gian Marco Iodiced2fab732018-03-02 11:18:12 +000051class WinogradConvolutionLayerValidationFixture : public framework::Fixture
Pablo Tello89519332017-11-17 11:52:36 +000052{
53public:
54 template <typename...>
Gian Marco Iodiced2fab732018-03-02 11:18:12 +000055 void setup(TensorShape input_shape, TensorShape weights_shape, TensorShape bias_shape, TensorShape output_shape, PadStrideInfo info, DataType data_type)
Pablo Tello89519332017-11-17 11:52:36 +000056 {
Gian Marco Iodiced2fab732018-03-02 11:18:12 +000057 _target = compute_target(input_shape, weights_shape, bias_shape, output_shape, info, data_type);
58 _reference = compute_reference(input_shape, weights_shape, bias_shape, output_shape, info, data_type);
Pablo Tello89519332017-11-17 11:52:36 +000059 }
60
61protected:
62 template <typename U>
63 void fill(U &&tensor, int i, float min, float max)
64 {
65 switch(tensor.data_type())
66 {
67 case DataType::F32:
68 {
69 std::uniform_real_distribution<> distribution(min, max);
70 library->fill(tensor, distribution, i);
71 break;
72 }
73 default:
74 {
75 ARM_COMPUTE_ERROR("Not supported");
76 library->fill_tensor_uniform(tensor, i);
77 break;
78 }
79 }
80 }
81
Gian Marco Iodiced2fab732018-03-02 11:18:12 +000082 TensorType compute_target(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info,
83 DataType data_type)
Pablo Tello89519332017-11-17 11:52:36 +000084 {
85 // Create tensors
Gian Marco Iodiced2fab732018-03-02 11:18:12 +000086 TensorType src = create_tensor<TensorType>(input_shape, data_type, 1);
87 TensorType weights = create_tensor<TensorType>(weights_shape, data_type, 1);
88 TensorType bias = create_tensor<TensorType>(bias_shape, data_type, 1);
89 TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1);
Pablo Tello89519332017-11-17 11:52:36 +000090
91 // Create and configure function
92 FunctionType conv;
Pablo Tellod6ca4782018-01-23 09:36:04 +000093 conv.configure(&src, &weights, &bias, &dst, info);
Pablo Tello89519332017-11-17 11:52:36 +000094
95 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
96 ARM_COMPUTE_EXPECT(weights.info()->is_resizable(), framework::LogLevel::ERRORS);
97 ARM_COMPUTE_EXPECT(bias.info()->is_resizable(), framework::LogLevel::ERRORS);
98 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
99
100 // Allocate tensors
101 src.allocator()->allocate();
102 weights.allocator()->allocate();
Pablo Tello89519332017-11-17 11:52:36 +0000103 dst.allocator()->allocate();
Pablo Tellod6ca4782018-01-23 09:36:04 +0000104 bias.allocator()->allocate();
Pablo Tello89519332017-11-17 11:52:36 +0000105
106 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
107 ARM_COMPUTE_EXPECT(!weights.info()->is_resizable(), framework::LogLevel::ERRORS);
108 ARM_COMPUTE_EXPECT(!bias.info()->is_resizable(), framework::LogLevel::ERRORS);
109 ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
110
111 // Fill tensors
112 fill(AccessorType(src), 0, -1.f, 1.f);
113 fill(AccessorType(weights), 1, -1.f, 1.f);
Pablo Tellod6ca4782018-01-23 09:36:04 +0000114 fill(AccessorType(bias), 2, -1.f, 1.f);
Pablo Tello89519332017-11-17 11:52:36 +0000115
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000116 // Compute Winograd Convolution function
Pablo Tello89519332017-11-17 11:52:36 +0000117 conv.run();
118
119 return dst;
120 }
121
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000122 SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, const PadStrideInfo &info,
123 DataType data_type)
Pablo Tello89519332017-11-17 11:52:36 +0000124 {
125 // Create reference
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000126 SimpleTensor<T> src{ input_shape, data_type, 1 };
127 SimpleTensor<T> weights{ weights_shape, data_type, 1 };
128 SimpleTensor<T> bias{ bias_shape, data_type, 1 };
Pablo Tello89519332017-11-17 11:52:36 +0000129
130 // Fill reference
131 fill(src, 0, -1.f, 1.f);
132 fill(weights, 1, -1.f, 1.f);
Pablo Tellod6ca4782018-01-23 09:36:04 +0000133 fill(bias, 2, -1.f, 1.f);
Pablo Tello89519332017-11-17 11:52:36 +0000134
135 return reference::convolution_layer<T>(src, weights, bias, output_shape, info);
136 }
137
138 TensorType _target{};
139 SimpleTensor<T> _reference{};
Pablo Tello89519332017-11-17 11:52:36 +0000140};
141
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000142template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
143class WinogradInputTransformValidationFixture : public framework::Fixture
144{
145public:
146 template <typename...>
147 void setup(TensorShape input_shape, PadStrideInfo conv_info, Size2D kernel_dims, bool is_nchw_format, DataType data_type)
148 {
149 TensorShape output_shape = compute_winograd_input_transform_shape(TensorInfo(input_shape, 1, data_type), conv_info, kernel_dims);
150
151 _target = compute_target(input_shape, output_shape, conv_info, kernel_dims, is_nchw_format, data_type);
152 _reference = compute_reference(input_shape, output_shape, conv_info, kernel_dims, is_nchw_format, data_type);
153 }
154
155protected:
156 template <typename U>
157 void fill(U &&tensor, int i, float min, float max)
158 {
159 switch(tensor.data_type())
160 {
161 case DataType::F32:
162 {
163 std::uniform_real_distribution<> distribution(min, max);
164 library->fill(tensor, distribution, i);
165 break;
166 }
167 default:
168 {
169 ARM_COMPUTE_ERROR("Not supported");
170 library->fill_tensor_uniform(tensor, i);
171 break;
172 }
173 }
174 }
175
176 TensorType compute_target(const TensorShape &input_shape, const TensorShape &output_shape, const PadStrideInfo &conv_info, const Size2D &kernel_dims, bool is_nchw_format, DataType data_type)
177 {
178 ARM_COMPUTE_UNUSED(is_nchw_format);
179
Giorgio Arena1f9ca1d2018-03-01 11:13:45 +0000180 TensorType src = create_tensor<TensorType>(input_shape, data_type);
181 TensorType dst = create_tensor<TensorType>(output_shape, data_type);
182
183 // Create and configure function
184 FunctionType transf;
185 transf.configure(&src, &dst, conv_info, kernel_dims);
186
187 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
188 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
189
190 // Allocate tensors
191 src.allocator()->allocate();
192 dst.allocator()->allocate();
193
194 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
195 ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
196
197 // Fill tensors
198 fill(AccessorType(src), 0, -1.f, 1.f);
199
200 // Compute CLWinogradInputTransform function
201 transf.run();
202
203 return dst;
204 }
205
206 SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &output_shape, const PadStrideInfo &conv_info, const Size2D &kernel_dims, bool is_nchw_format, DataType data_type)
207 {
208 ARM_COMPUTE_UNUSED(is_nchw_format);
209
210 // Create reference
211 SimpleTensor<T> src{ input_shape, data_type };
212
213 // Fill reference
214 fill(src, 0, -1.f, 1.f);
215
216 return reference::winograd_input_transform<T>(src, output_shape, conv_info, kernel_dims);
217 }
218
219 TensorType _target{};
220 SimpleTensor<T> _reference{};
221};
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000222
223template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
224class WinogradFilterTransformValidationFixture : public framework::Fixture
225{
226public:
227 template <typename...>
Giorgio Arena2d9de0a2018-03-15 17:58:20 +0000228 void setup(TensorShape input_shape, bool is_nchw_format, Size2D output_tile, DataType data_type)
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000229 {
Giorgio Arena2d9de0a2018-03-15 17:58:20 +0000230 TensorShape output_shape = compute_winograd_filter_transform_shape(TensorInfo(input_shape, 1, data_type), output_tile);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000231
Giorgio Arena2d9de0a2018-03-15 17:58:20 +0000232 _target = compute_target(input_shape, output_shape, is_nchw_format, output_tile, data_type);
233 _reference = compute_reference(input_shape, output_shape, is_nchw_format, output_tile, data_type);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000234 }
235
236protected:
237 template <typename U>
238 void fill(U &&tensor, int i, float min, float max)
239 {
240 switch(tensor.data_type())
241 {
242 case DataType::F32:
243 {
244 std::uniform_real_distribution<> distribution(min, max);
245 library->fill(tensor, distribution, i);
246 break;
247 }
248 default:
249 {
250 ARM_COMPUTE_ERROR("Not supported");
251 library->fill_tensor_uniform(tensor, i);
252 break;
253 }
254 }
255 }
256
Giorgio Arena2d9de0a2018-03-15 17:58:20 +0000257 TensorType compute_target(const TensorShape &input_shape, const TensorShape &output_shape, bool is_nchw_format, const Size2D &output_tile, DataType data_type)
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000258 {
259 ARM_COMPUTE_UNUSED(is_nchw_format);
260
261 // Create tensors
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000262 TensorType src = create_tensor<TensorType>(input_shape, data_type, 1);
263 TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000264
265 // Create and configure function
266 FunctionType filter_transform;
Giorgio Arena2d9de0a2018-03-15 17:58:20 +0000267 filter_transform.configure(&src, &dst, output_tile);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000268
269 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
270 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
271
272 // Allocate tensors
273 src.allocator()->allocate();
274 dst.allocator()->allocate();
275
276 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
277 ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
278
279 // Fill tensors
280 fill(AccessorType(src), 0, -1.f, 1.f);
281
282 filter_transform.run();
283
284 return dst;
285 }
286
Giorgio Arena2d9de0a2018-03-15 17:58:20 +0000287 SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &output_shape, bool is_nchw_format, const Size2D &output_tile, DataType data_type)
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000288 {
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000289 ARM_COMPUTE_UNUSED(is_nchw_format);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000290
291 // Create reference
292 SimpleTensor<T> src{ input_shape, data_type, 1 };
293
294 // Fill reference
295 fill(src, 0, -1.f, 1.f);
296
Giorgio Arena2d9de0a2018-03-15 17:58:20 +0000297 return reference::winograd_filter_transform<T>(src, output_shape, output_tile);
Gian Marco Iodice7e4b2392018-02-22 16:17:20 +0000298 }
299
300 TensorType _target{};
301 SimpleTensor<T> _reference{};
302};
Gian Marco Iodiced2fab732018-03-02 11:18:12 +0000303
304template <typename TensorType, typename AccessorType, typename FunctionType, typename T>
305class WinogradOutputTransformValidationFixture : public framework::Fixture
306{
307public:
308 template <typename...>
309 void setup(TensorShape input_shape, Size2D kernel_dims, Size2D output_convolved_dims, Size2D num_tiles, DataLayout data_layout, DataType data_type)
310 {
311 TensorShape output_shape = compute_winograd_output_transform_shape(TensorInfo(input_shape, 1, data_type), output_convolved_dims, data_layout);
312
313 _target = compute_target(input_shape, output_shape, kernel_dims, output_convolved_dims, num_tiles, data_layout, data_type);
314 _reference = compute_reference(input_shape, output_shape, kernel_dims, output_convolved_dims, num_tiles, data_layout, data_type);
315 }
316
317protected:
318 template <typename U>
319 void fill(U &&tensor, int i, float min, float max)
320 {
321 switch(tensor.data_type())
322 {
323 case DataType::F32:
324 {
325 std::uniform_real_distribution<> distribution(min, max);
326 library->fill(tensor, distribution, i);
327 break;
328 }
329 default:
330 {
331 ARM_COMPUTE_ERROR("Not supported");
332 library->fill_tensor_uniform(tensor, i);
333 break;
334 }
335 }
336 }
337
338 TensorType compute_target(const TensorShape &input_shape, const TensorShape &output_shape, const Size2D &kernel_dims, const Size2D &output_convolved_dims, Size2D &num_tiles, DataLayout data_layout,
339 DataType data_type)
340 {
341 // Create tensors
342 TensorType src = create_tensor<TensorType>(input_shape, data_type, 1, 0, QuantizationInfo(), data_layout);
343 TensorType dst = create_tensor<TensorType>(output_shape, data_type, 1, 0, QuantizationInfo(), data_layout);
344
345 // Create and configure function
346 FunctionType output_transform;
347 output_transform.configure(&src, nullptr, &dst, kernel_dims, output_convolved_dims, num_tiles);
348
349 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
350 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
351
352 // Allocate tensors
353 src.allocator()->allocate();
354 dst.allocator()->allocate();
355
356 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
357 ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
358
359 // Fill tensors
360 fill(AccessorType(src), 0, -1.f, 1.f);
361
362 output_transform.run();
363
364 return dst;
365 }
366
367 SimpleTensor<T> compute_reference(const TensorShape &input_shape, const TensorShape &output_shape, const Size2D &kernel_dims, const Size2D &output_convolved_dims, Size2D &num_tiles,
368 DataLayout data_layout,
369 DataType data_type)
370 {
371 // Create reference
372 SimpleTensor<T> src{ input_shape, data_type, 1, 0, QuantizationInfo(), data_layout };
373
374 // Fill reference
375 fill(src, 0, -1.f, 1.f);
376
377 return reference::winograd_output_transform<T>(src, output_shape, kernel_dims, num_tiles);
378 }
379
380 TensorType _target{};
381 SimpleTensor<T> _reference{};
382};
Pablo Tello89519332017-11-17 11:52:36 +0000383} // namespace validation
384} // namespace test
385} // namespace arm_compute
386#endif /* ARM_COMPUTE_TEST_WINOGRAD_LAYER_FIXTURE */