blob: 05c430a1c797e23e072a0dbbdb6c209b6ddb50a2 [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
Michalis Spyrou5ce99a22019-01-25 14:17:49 +000088const auto data_f32_nightly = combine(data_f32, framework::dataset::make("NumKernels", { 1, 4 }));
89const auto data_f16_nightly = combine(data_f16, framework::dataset::make("NumKernels", { 1, 4 }));
Michalis Spyrouaeebe4a2019-01-09 14:21:03 +000090
91const auto data_precommit = combine(data, framework::dataset::make("NumKernels", { 1 }));
Gian Marco Iodice41acb762018-08-23 10:25:06 +010092
Isabella Gottardi3f217ec2018-02-12 14:59:19 +000093/** Activation function Dataset*/
94const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
Michalis Spyrou5ce99a22019-01-25 14:17:49 +000095{ ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 0.5f) });
Moritz Pflanzerb3d25792017-07-26 11:49:37 +010096} // namespace
97
98TEST_SUITE(NEON)
99TEST_SUITE(DirectConvolutionLayer)
100
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000101// *INDENT-OFF*
102// clang-format off
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000103DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100104 framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Mismatching data type input/weights
105 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Mismatching input feature maps
106 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Unsupported kernel width
107 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Non-rectangular weights dimensions
108 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid weights dimensions
109 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid stride
110 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid biases size
111 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid biases dimensions
112 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid output size
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000113 }),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100114 framework::dataset::make("WeightsInfo",{ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F16),
115 TensorInfo(TensorShape(3U, 3U, 3U, 4U), 1, DataType::F32),
116 TensorInfo(TensorShape(9U, 9U, 2U, 4U), 1, DataType::F32),
117 TensorInfo(TensorShape(5U, 3U, 2U, 4U), 1, DataType::F32),
118 TensorInfo(TensorShape(3U, 3U, 2U, 4U, 3U), 1, DataType::F32),
119 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
120 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
121 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
122 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000123 })),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100124 framework::dataset::make("BiasesInfo",{ TensorInfo(TensorShape(4U), 1, DataType::F32),
125 TensorInfo(TensorShape(4U), 1, DataType::F32),
126 TensorInfo(TensorShape(4U), 1, DataType::F32),
127 TensorInfo(TensorShape(4U), 1, DataType::F32),
128 TensorInfo(TensorShape(4U), 1, DataType::F32),
129 TensorInfo(TensorShape(4U), 1, DataType::F32),
130 TensorInfo(TensorShape(3U), 1, DataType::F32),
131 TensorInfo(TensorShape(4U, 2U), 1, DataType::F32),
132 TensorInfo(TensorShape(4U), 1, DataType::F32),
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000133 })),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +0100134 framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
135 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
136 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
137 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
138 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
139 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
140 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
141 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
142 TensorInfo(TensorShape(26U, 11U, 4U), 1, DataType::F32),
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000143 })),
144 framework::dataset::make("ConvInfo", { PadStrideInfo(1, 1, 0, 0),
145 PadStrideInfo(1, 1, 0, 0),
146 PadStrideInfo(1, 1, 0, 0),
147 PadStrideInfo(1, 1, 0, 0),
148 PadStrideInfo(1, 1, 0, 0),
149 PadStrideInfo(3, 3, 0, 0),
150 PadStrideInfo(1, 1, 0, 0),
151 PadStrideInfo(1, 1, 0, 0),
152 PadStrideInfo(1, 1, 0, 0),
153 })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000154 framework::dataset::make("ActivationInfo",
Michalis Spyrouafa5d812017-11-30 14:25:57 +0000155{
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000156 ActivationLayerInfo(),
157 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)
158})),
159 framework::dataset::make("Expected", { false, false, false, false, false, false, false, false, false })),
160 input_info, weights_info, biases_info, output_info, conv_info, act_info, expected)
161{
162 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 +0000163 ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS);
164}
165// clang-format on
166// *INDENT-ON*
167
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100168//TODO(COMPMID-415): Configuration tests?
169
170template <typename T>
171using NEDirectConvolutionLayerFixture = DirectConvolutionValidationFixture<Tensor, Accessor, NEDirectConvolutionLayer, T>;
172
173TEST_SUITE(Float)
Ioan-Cristian Szabo5edbd1c2017-11-13 13:34:08 +0000174#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100175TEST_SUITE(FP16)
Michalis Spyrouaeebe4a2019-01-09 14:21:03 +0000176FIXTURE_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 +0000177 DataType::F16)),
178 ActivationFunctionsDataset),
179 framework::dataset::make("DataLayout", DataLayout::NCHW)))
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100180{
181 // Validate output
Gian Marco Iodice41acb762018-08-23 10:25:06 +0100182 validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num, abs_tolerance_f16);
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100183}
Michalis Spyrou064add62018-11-01 18:14:27 +0000184FIXTURE_DATA_TEST_CASE(RunLarge, NEDirectConvolutionLayerFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_f16_nightly, framework::dataset::make("DataType", DataType::F16)),
185 ActivationFunctionsDataset),
186 framework::dataset::make("DataLayout", DataLayout::NCHW)))
187{
188 // Validate output
189 validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num, abs_tolerance_f16);
190}
191TEST_SUITE_END() // FP16
192#endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100193
194TEST_SUITE(FP32)
Michalis Spyrouaeebe4a2019-01-09 14:21:03 +0000195FIXTURE_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 +0000196 DataType::F32)),
197 ActivationFunctionsDataset),
198 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100199{
200 // Validate output
201 validate(Accessor(_target), _reference, tolerance_fp32);
202}
Michalis Spyrou064add62018-11-01 18:14:27 +0000203FIXTURE_DATA_TEST_CASE(RunLarge, NEDirectConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_f32_nightly, framework::dataset::make("DataType",
204 DataType::F32)),
205 ActivationFunctionsDataset),
206 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
207{
208 // Validate output
209 validate(Accessor(_target), _reference, tolerance_fp32);
210}
211TEST_SUITE_END() // FP32
212TEST_SUITE_END() // Float
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100213
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000214const auto QuantizedActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
215{
216 ActivationLayerInfo(),
217 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
218 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 6.f)
219});
220
Michalis Spyrou064add62018-11-01 18:14:27 +0000221TEST_SUITE_END() // DirectConvolutionLayer
222TEST_SUITE_END() // NEON
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100223} // namespace validation
224} // namespace test
225} // namespace arm_compute