blob: 88578ca586eff2ab35b154ce040d1a7f4ae883eb [file] [log] [blame]
Moritz Pflanzerb3d25792017-07-26 11:49:37 +01001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2017-2020 Arm Limited.
Moritz Pflanzerb3d25792017-07-26 11:49:37 +01003 *
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#include "arm_compute/core/Types.h"
25#include "arm_compute/runtime/NEON/functions/NEDirectConvolutionLayer.h"
26#include "arm_compute/runtime/Tensor.h"
27#include "arm_compute/runtime/TensorAllocator.h"
Moritz Pflanzerb3d25792017-07-26 11:49:37 +010028#include "tests/NEON/Accessor.h"
29#include "tests/PaddingCalculator.h"
Moritz Pflanzera09de0c2017-09-01 20:41:12 +010030#include "tests/datasets/ShapeDatasets.h"
31#include "tests/framework/Asserts.h"
32#include "tests/framework/Macros.h"
33#include "tests/framework/datasets/Datasets.h"
34#include "tests/validation/Validation.h"
35#include "tests/validation/fixtures/DirectConvolutionLayerFixture.h"
Moritz Pflanzerb3d25792017-07-26 11:49:37 +010036
37namespace arm_compute
38{
39namespace test
40{
41namespace validation
42{
43namespace
44{
Ioan-Cristian Szabo5edbd1c2017-11-13 13:34:08 +000045#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Gian Marco Iodice41acb762018-08-23 10:25:06 +010046const RelativeTolerance<half_float::half> rel_tolerance_f16(half_float::half(0.2f)); /**< Relative tolerance value for FP16 types */
47const AbsoluteTolerance<float> abs_tolerance_f16(0.2f); /**< Absolute tolerance for FP16 types */
48constexpr float tolerance_num = 0.07f; /**< Tolerance number for the FP16 implementation */
49#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
50constexpr AbsoluteTolerance<float> tolerance_fp32(0.001f); /**< Tolerance for floating point tests */
Moritz Pflanzerb3d25792017-07-26 11:49:37 +010051
Gian Marco Iodice41acb762018-08-23 10:25:06 +010052/** Direct convolution data set.for FP32 */
Giorgio Arenac0f54432018-03-16 14:02:34 +000053const auto data_pad_f32 = concat(concat(combine(framework::dataset::make("PadX", { 0, 1 }),
54 combine(framework::dataset::make("PadY", { 0, 1 }),
55 framework::dataset::make("KernelSize", 3))),
56 combine(framework::dataset::make("PadX", { 0, 2 }),
57 combine(framework::dataset::make("PadY", { 0, 2 }),
Pablo Tello06da39d2017-08-10 15:10:40 +010058 framework::dataset::make("KernelSize", 3)))),
Giorgio Arenac0f54432018-03-16 14:02:34 +000059 combine(framework::dataset::make("PadX", { 0, 3 }),
60 combine(framework::dataset::make("PadY", { 0, 3 }),
Pablo Tello06da39d2017-08-10 15:10:40 +010061 framework::dataset::make("KernelSize", 5))));
62
Gian Marco Iodice41acb762018-08-23 10:25:06 +010063/** Direct convolution data set.for FP16 */
64const auto data_pad_f16 = concat(combine(framework::dataset::make("PadX", { 0, 1 }),
65 combine(framework::dataset::make("PadY", { 0, 1 }),
66 framework::dataset::make("KernelSize", 3))),
67 combine(framework::dataset::make("PadX", { 0 }),
68 combine(framework::dataset::make("PadY", { 0 }),
69 framework::dataset::make("KernelSize", 1))));
70
Pablo Tello06da39d2017-08-10 15:10:40 +010071const auto data_f32 = combine(datasets::SmallDirectConvolutionShapes(),
Gian Marco Iodice41acb762018-08-23 10:25:06 +010072 combine(framework::dataset::make("StrideX", { 1, 2, 3 }),
73 combine(framework::dataset::make("StrideY", { 1, 2, 3 }),
Michalis Spyrou064add62018-11-01 18:14:27 +000074 data_pad_f32)));
Pablo Tello06da39d2017-08-10 15:10:40 +010075
Gian Marco Iodice41acb762018-08-23 10:25:06 +010076const auto data_f16 = combine(datasets::SmallDirectConvolutionShapes(),
77 combine(framework::dataset::make("StrideX", { 1, 2, 3 }),
78 combine(framework::dataset::make("StrideY", { 1, 2, 3 }),
Michalis Spyrou064add62018-11-01 18:14:27 +000079 data_pad_f16)));
80
Michalis Spyrouaeebe4a2019-01-09 14:21:03 +000081const auto data = combine(datasets::SmallDirectConvolutionShapes(),
82 combine(framework::dataset::make("StrideX", { 1 }),
83 combine(framework::dataset::make("StrideY", { 1 }),
84 combine(framework::dataset::make("PadX", { 1 }),
85 combine(framework::dataset::make("PadY", { 1 }),
86 framework::dataset::make("KernelSize", 3))))));
87
Gian Marco Iodice95f93612019-06-13 15:58:32 +010088const auto data9x9 = combine(datasets::SmallDirectConvolutionShapes(),
89 combine(framework::dataset::make("StrideX", { 1 }),
90 combine(framework::dataset::make("StrideY", { 1 }),
91 combine(framework::dataset::make("PadX", { 0, 2 }),
92 combine(framework::dataset::make("PadY", { 0, 3 }),
93 framework::dataset::make("KernelSize", 9))))));
94
Michalis Spyrou5ce99a22019-01-25 14:17:49 +000095const auto data_f32_nightly = combine(data_f32, framework::dataset::make("NumKernels", { 1, 4 }));
96const auto data_f16_nightly = combine(data_f16, framework::dataset::make("NumKernels", { 1, 4 }));
Michalis Spyrouaeebe4a2019-01-09 14:21:03 +000097
Gian Marco Iodice95f93612019-06-13 15:58:32 +010098const auto data_precommit = combine(data, framework::dataset::make("NumKernels", { 1 }));
99const auto data_precommit9x9 = combine(data9x9, framework::dataset::make("NumKernels", { 4 }));
Gian Marco Iodice41acb762018-08-23 10:25:06 +0100100
Sang-Hoon Park38515422020-07-08 11:06:30 +0100101/* The following tests is from real use-case that made DirectConvolution
102 * overflows in terms of its tensor indexing. This test case is using
103 * a separate tolerance due to the following reason.
104 * - It has shown that it requires generally larger absolute tolerance
105 * for large numbers or larger relative tolerance for small numbers.
106 * - With the first reason, since it is mainly testing index overflow,
107 * a value with a margin is used to avoid uninteded test failures
108 * during nightly.
109 */
110constexpr AbsoluteTolerance<float> usecase_tolerance_fp32(0.05f);
111
112const auto data_nightly_usecase = combine(framework::dataset::make("InputShape", { TensorShape{ 3U, 800U, 800U } }),
113 combine(framework::dataset::make("StrideX", { 1 }),
114 combine(framework::dataset::make("StrideY", { 1 }),
115 combine(framework::dataset::make("PadX", { 4 }),
116 combine(framework::dataset::make("PadY", { 4 }),
117 combine(framework::dataset::make("KernelSize", 9),
118 framework::dataset::make("NumKernels", { 16 })))))));
119
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000120/** Activation function Dataset*/
121const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
Gian Marco Iodice95f93612019-06-13 15:58:32 +0100122{
123 ActivationLayerInfo(),
124 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 0.5f)
125});
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100126} // namespace
127
128TEST_SUITE(NEON)
129TEST_SUITE(DirectConvolutionLayer)
130
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000131// *INDENT-OFF*
132// clang-format off
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000133DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100134 framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Mismatching data type input/weights
135 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Mismatching input feature maps
136 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Unsupported kernel width
137 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Non-rectangular weights dimensions
138 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid weights dimensions
139 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid stride
140 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid biases size
141 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid biases dimensions
142 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid output size
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000143 }),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100144 framework::dataset::make("WeightsInfo",{ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F16),
145 TensorInfo(TensorShape(3U, 3U, 3U, 4U), 1, DataType::F32),
146 TensorInfo(TensorShape(9U, 9U, 2U, 4U), 1, DataType::F32),
147 TensorInfo(TensorShape(5U, 3U, 2U, 4U), 1, DataType::F32),
148 TensorInfo(TensorShape(3U, 3U, 2U, 4U, 3U), 1, DataType::F32),
149 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
150 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
151 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
152 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000153 })),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100154 framework::dataset::make("BiasesInfo",{ TensorInfo(TensorShape(4U), 1, DataType::F32),
155 TensorInfo(TensorShape(4U), 1, DataType::F32),
156 TensorInfo(TensorShape(4U), 1, DataType::F32),
157 TensorInfo(TensorShape(4U), 1, DataType::F32),
158 TensorInfo(TensorShape(4U), 1, DataType::F32),
159 TensorInfo(TensorShape(4U), 1, DataType::F32),
160 TensorInfo(TensorShape(3U), 1, DataType::F32),
161 TensorInfo(TensorShape(4U, 2U), 1, DataType::F32),
162 TensorInfo(TensorShape(4U), 1, DataType::F32),
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000163 })),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100164 framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
165 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
166 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
167 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
168 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
169 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
170 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
171 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
172 TensorInfo(TensorShape(26U, 11U, 4U), 1, DataType::F32),
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000173 })),
174 framework::dataset::make("ConvInfo", { PadStrideInfo(1, 1, 0, 0),
175 PadStrideInfo(1, 1, 0, 0),
176 PadStrideInfo(1, 1, 0, 0),
177 PadStrideInfo(1, 1, 0, 0),
178 PadStrideInfo(1, 1, 0, 0),
179 PadStrideInfo(3, 3, 0, 0),
180 PadStrideInfo(1, 1, 0, 0),
181 PadStrideInfo(1, 1, 0, 0),
182 PadStrideInfo(1, 1, 0, 0),
183 })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000184 framework::dataset::make("ActivationInfo",
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000185{
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000186 ActivationLayerInfo(),
187 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)
188})),
189 framework::dataset::make("Expected", { false, false, false, false, false, false, false, false, false })),
190 input_info, weights_info, biases_info, output_info, conv_info, act_info, expected)
191{
192 bool is_valid = bool(NEDirectConvolutionLayer::validate(&input_info.clone()->set_is_resizable(false), &weights_info.clone()->set_is_resizable(false), &biases_info.clone()->set_is_resizable(false), &output_info.clone()->set_is_resizable(false), conv_info, act_info));
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000193 ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS);
194}
195// clang-format on
196// *INDENT-ON*
197
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100198//TODO(COMPMID-415): Configuration tests?
199
200template <typename T>
201using NEDirectConvolutionLayerFixture = DirectConvolutionValidationFixture<Tensor, Accessor, NEDirectConvolutionLayer, T>;
202
203TEST_SUITE(Float)
Ioan-Cristian Szabo5edbd1c2017-11-13 13:34:08 +0000204#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100205TEST_SUITE(FP16)
Michalis Spyrouaeebe4a2019-01-09 14:21:03 +0000206FIXTURE_DATA_TEST_CASE(RunSmall, NEDirectConvolutionLayerFixture<half>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit, framework::dataset::make("DataType",
Michalis Spyrou064add62018-11-01 18:14:27 +0000207 DataType::F16)),
208 ActivationFunctionsDataset),
209 framework::dataset::make("DataLayout", DataLayout::NCHW)))
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100210{
211 // Validate output
Gian Marco Iodice41acb762018-08-23 10:25:06 +0100212 validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num, abs_tolerance_f16);
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100213}
Michalis Spyrou064add62018-11-01 18:14:27 +0000214FIXTURE_DATA_TEST_CASE(RunLarge, NEDirectConvolutionLayerFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_f16_nightly, framework::dataset::make("DataType", DataType::F16)),
215 ActivationFunctionsDataset),
216 framework::dataset::make("DataLayout", DataLayout::NCHW)))
217{
218 // Validate output
219 validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num, abs_tolerance_f16);
220}
221TEST_SUITE_END() // FP16
222#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100223
224TEST_SUITE(FP32)
Michalis Spyrouaeebe4a2019-01-09 14:21:03 +0000225FIXTURE_DATA_TEST_CASE(RunSmall, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit, framework::dataset::make("DataType",
Michalis Spyrou064add62018-11-01 18:14:27 +0000226 DataType::F32)),
227 ActivationFunctionsDataset),
228 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100229{
230 // Validate output
231 validate(Accessor(_target), _reference, tolerance_fp32);
232}
Gian Marco Iodice95f93612019-06-13 15:58:32 +0100233FIXTURE_DATA_TEST_CASE(RunSmall9x9, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit9x9, framework::dataset::make("DataType",
234 DataType::F32)),
235 ActivationFunctionsDataset),
236 framework::dataset::make("DataLayout", { DataLayout::NHWC })))
237{
238 // Validate output
239 validate(Accessor(_target), _reference, tolerance_fp32);
240}
Michalis Spyrou064add62018-11-01 18:14:27 +0000241FIXTURE_DATA_TEST_CASE(RunLarge, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_f32_nightly, framework::dataset::make("DataType",
242 DataType::F32)),
243 ActivationFunctionsDataset),
244 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
245{
246 // Validate output
247 validate(Accessor(_target), _reference, tolerance_fp32);
248}
Sang-Hoon Park38515422020-07-08 11:06:30 +0100249FIXTURE_DATA_TEST_CASE(RunLargeUsecase, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_nightly_usecase, framework::dataset::make("DataType",
250 DataType::F32)),
251 framework::dataset::make("ActivationInfo", { ActivationLayerInfo() })),
252 framework::dataset::make("DataLayout", { DataLayout::NHWC })))
253{
254 // Validate output
255 validate(Accessor(_target), _reference, usecase_tolerance_fp32);
256}
Michalis Spyrou064add62018-11-01 18:14:27 +0000257TEST_SUITE_END() // FP32
258TEST_SUITE_END() // Float
Michalis Spyrou064add62018-11-01 18:14:27 +0000259TEST_SUITE_END() // DirectConvolutionLayer
260TEST_SUITE_END() // NEON
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100261} // namespace validation
262} // namespace test
263} // namespace arm_compute