blob: 439f81af73bbb99c22482a645ab1a3f5cfdbbe7b [file] [log] [blame]
Moritz Pflanzerb3d25792017-07-26 11:49:37 +01001/*
Michalis Spyrouaeebe4a2019-01-09 14:21:03 +00002 * Copyright (c) 2017-2019 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
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000101/** Activation function Dataset*/
102const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
Gian Marco Iodice95f93612019-06-13 15:58:32 +0100103{
104 ActivationLayerInfo(),
105 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 0.5f)
106});
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100107} // namespace
108
109TEST_SUITE(NEON)
110TEST_SUITE(DirectConvolutionLayer)
111
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000112// *INDENT-OFF*
113// clang-format off
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000114DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100115 framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Mismatching data type input/weights
116 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Mismatching input feature maps
117 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Unsupported kernel width
118 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Non-rectangular weights dimensions
119 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid weights dimensions
120 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid stride
121 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid biases size
122 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid biases dimensions
123 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid output size
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000124 }),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100125 framework::dataset::make("WeightsInfo",{ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F16),
126 TensorInfo(TensorShape(3U, 3U, 3U, 4U), 1, DataType::F32),
127 TensorInfo(TensorShape(9U, 9U, 2U, 4U), 1, DataType::F32),
128 TensorInfo(TensorShape(5U, 3U, 2U, 4U), 1, DataType::F32),
129 TensorInfo(TensorShape(3U, 3U, 2U, 4U, 3U), 1, DataType::F32),
130 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
131 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
132 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
133 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000134 })),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100135 framework::dataset::make("BiasesInfo",{ TensorInfo(TensorShape(4U), 1, DataType::F32),
136 TensorInfo(TensorShape(4U), 1, DataType::F32),
137 TensorInfo(TensorShape(4U), 1, DataType::F32),
138 TensorInfo(TensorShape(4U), 1, DataType::F32),
139 TensorInfo(TensorShape(4U), 1, DataType::F32),
140 TensorInfo(TensorShape(4U), 1, DataType::F32),
141 TensorInfo(TensorShape(3U), 1, DataType::F32),
142 TensorInfo(TensorShape(4U, 2U), 1, DataType::F32),
143 TensorInfo(TensorShape(4U), 1, DataType::F32),
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000144 })),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100145 framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
146 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
147 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
148 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
149 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
150 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
151 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
152 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
153 TensorInfo(TensorShape(26U, 11U, 4U), 1, DataType::F32),
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000154 })),
155 framework::dataset::make("ConvInfo", { PadStrideInfo(1, 1, 0, 0),
156 PadStrideInfo(1, 1, 0, 0),
157 PadStrideInfo(1, 1, 0, 0),
158 PadStrideInfo(1, 1, 0, 0),
159 PadStrideInfo(1, 1, 0, 0),
160 PadStrideInfo(3, 3, 0, 0),
161 PadStrideInfo(1, 1, 0, 0),
162 PadStrideInfo(1, 1, 0, 0),
163 PadStrideInfo(1, 1, 0, 0),
164 })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000165 framework::dataset::make("ActivationInfo",
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000166{
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000167 ActivationLayerInfo(),
168 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)
169})),
170 framework::dataset::make("Expected", { false, false, false, false, false, false, false, false, false })),
171 input_info, weights_info, biases_info, output_info, conv_info, act_info, expected)
172{
173 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 +0000174 ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS);
175}
176// clang-format on
177// *INDENT-ON*
178
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100179//TODO(COMPMID-415): Configuration tests?
180
181template <typename T>
182using NEDirectConvolutionLayerFixture = DirectConvolutionValidationFixture<Tensor, Accessor, NEDirectConvolutionLayer, T>;
183
184TEST_SUITE(Float)
Ioan-Cristian Szabo5edbd1c2017-11-13 13:34:08 +0000185#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100186TEST_SUITE(FP16)
Michalis Spyrouaeebe4a2019-01-09 14:21:03 +0000187FIXTURE_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 +0000188 DataType::F16)),
189 ActivationFunctionsDataset),
190 framework::dataset::make("DataLayout", DataLayout::NCHW)))
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100191{
192 // Validate output
Gian Marco Iodice41acb762018-08-23 10:25:06 +0100193 validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num, abs_tolerance_f16);
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100194}
Michalis Spyrou064add62018-11-01 18:14:27 +0000195FIXTURE_DATA_TEST_CASE(RunLarge, NEDirectConvolutionLayerFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_f16_nightly, framework::dataset::make("DataType", DataType::F16)),
196 ActivationFunctionsDataset),
197 framework::dataset::make("DataLayout", DataLayout::NCHW)))
198{
199 // Validate output
200 validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num, abs_tolerance_f16);
201}
202TEST_SUITE_END() // FP16
203#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100204
205TEST_SUITE(FP32)
Michalis Spyrouaeebe4a2019-01-09 14:21:03 +0000206FIXTURE_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 +0000207 DataType::F32)),
208 ActivationFunctionsDataset),
209 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100210{
211 // Validate output
212 validate(Accessor(_target), _reference, tolerance_fp32);
213}
Gian Marco Iodice95f93612019-06-13 15:58:32 +0100214FIXTURE_DATA_TEST_CASE(RunSmall9x9, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit9x9, framework::dataset::make("DataType",
215 DataType::F32)),
216 ActivationFunctionsDataset),
217 framework::dataset::make("DataLayout", { DataLayout::NHWC })))
218{
219 // Validate output
220 validate(Accessor(_target), _reference, tolerance_fp32);
221}
Michalis Spyrou064add62018-11-01 18:14:27 +0000222FIXTURE_DATA_TEST_CASE(RunLarge, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_f32_nightly, framework::dataset::make("DataType",
223 DataType::F32)),
224 ActivationFunctionsDataset),
225 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
226{
227 // Validate output
228 validate(Accessor(_target), _reference, tolerance_fp32);
229}
230TEST_SUITE_END() // FP32
231TEST_SUITE_END() // Float
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100232
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000233const auto QuantizedActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
234{
235 ActivationLayerInfo(),
236 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
237 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 6.f)
238});
239
Michalis Spyrou064add62018-11-01 18:14:27 +0000240TEST_SUITE_END() // DirectConvolutionLayer
241TEST_SUITE_END() // NEON
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100242} // namespace validation
243} // namespace test
244} // namespace arm_compute