blob: 54fdc0c38622bfd233e5c58cb0fecf89ebbc3e51 [file] [log] [blame]
Moritz Pflanzerb3d25792017-07-26 11:49:37 +01001/*
Gian Marco20d78482018-01-11 15:10:58 +00002 * Copyright (c) 2017-2018 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 CONCLCTION 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/CL/CLTensor.h"
26#include "arm_compute/runtime/CL/CLTensorAllocator.h"
27#include "arm_compute/runtime/CL/functions/CLConvolutionLayer.h"
Isabella Gottardif07d28d2018-02-06 14:52:43 +000028#include "arm_compute/runtime/CL/functions/CLGEMMConvolutionLayer.h"
Moritz Pflanzerb3d25792017-07-26 11:49:37 +010029#include "tests/CL/CLAccessor.h"
30#include "tests/PaddingCalculator.h"
Moritz Pflanzera09de0c2017-09-01 20:41:12 +010031#include "tests/datasets/LargeConvolutionLayerDataset.h"
32#include "tests/datasets/SmallConvolutionLayerDataset.h"
Anthony Barbier1c0d0ff2018-01-31 13:05:09 +000033#include "tests/datasets/TinyConvolutionLayerDataset.h"
Moritz Pflanzera09de0c2017-09-01 20:41:12 +010034#include "tests/framework/Asserts.h"
35#include "tests/framework/Macros.h"
36#include "tests/framework/datasets/Datasets.h"
37#include "tests/validation/Validation.h"
38#include "tests/validation/fixtures/ConvolutionLayerFixture.h"
Moritz Pflanzerb3d25792017-07-26 11:49:37 +010039
40namespace arm_compute
41{
42namespace test
43{
44namespace validation
45{
46namespace
47{
Georgios Pinitas5e207532018-04-27 14:38:16 +010048constexpr AbsoluteTolerance<float> absolute_tolerance_float(0.0001f); /**< Absolute Tolerance value for comparing reference's output against implementation's output for DataType::F32 */
steniu01f81652d2017-09-11 15:29:12 +010049RelativeTolerance<float> tolerance_f32(0.05f); /**< Tolerance value for comparing reference's output against implementation's output for DataType::F32 */
50RelativeTolerance<half_float::half> tolerance_f16(half_float::half(0.2)); /**< Tolerance value for comparing reference's output against implementation's output for DataType::F16 */
Chunosov5124be52017-11-22 20:42:13 +070051constexpr AbsoluteTolerance<float> tolerance_qasymm8(0.0); /**< Tolerance value for comparing reference's output against implementation's output for quantized data types */
steniu01f81652d2017-09-11 15:29:12 +010052constexpr float tolerance_num = 0.07f; /**< Tolerance number */
Moritz Pflanzerb3d25792017-07-26 11:49:37 +010053
54/** CNN data types */
55const auto CNNDataTypes = framework::dataset::make("DataType",
56{
57 DataType::F16,
58 DataType::F32,
Chunosov5124be52017-11-22 20:42:13 +070059 DataType::QASYMM8,
Moritz Pflanzerb3d25792017-07-26 11:49:37 +010060});
Isabella Gottardi3f217ec2018-02-12 14:59:19 +000061const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
62{
63 ActivationLayerInfo(),
64 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
65 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 0.5f),
66 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 0.5f)
67});
Moritz Pflanzerb3d25792017-07-26 11:49:37 +010068} // namespace
69
70TEST_SUITE(CL)
71TEST_SUITE(ConvolutionLayer)
72
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +010073DATA_TEST_CASE(ValidateConvolutionMethod, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(zip(
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010074 framework::dataset::make("InputInfo", { TensorInfo(TensorShape(17U, 31U, 2U), 1, DataType::F32),
75 TensorInfo(TensorShape(17U, 31U, 2U), 1, DataType::F32),
76 TensorInfo(TensorShape(23U, 27U, 5U, 4U), 1, DataType::F32),
77 TensorInfo(TensorShape(23U, 27U, 31U, 4U), 1, DataType::F32),
78 TensorInfo(TensorShape(3U, 3U, 2U, 1U), 1, DataType::F32),
79 TensorInfo(TensorShape(33U, 27U, 7U, 4U), 1, DataType::F32),
80 TensorInfo(TensorShape(17U, 31U, 32U), 1, DataType::F32),
81 TensorInfo(TensorShape(17U, 31U, 2U), 1, DataType::F32)
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +010082 }),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010083 framework::dataset::make("WeightsInfo", { TensorInfo(TensorShape(5U, 5U, 2U, 19U), 1, DataType::F32),
84 TensorInfo(TensorShape(5U, 5U, 2U, 19U), 1, DataType::F32),
85 TensorInfo(TensorShape(3U, 3U, 5U, 21U), 1, DataType::F32),
86 TensorInfo(TensorShape(3U, 3U, 31U, 21U), 1, DataType::F32),
87 TensorInfo(TensorShape(3U, 3U, 5U, 21U), 1, DataType::F32),
88 TensorInfo(TensorShape(5U, 5U, 7U, 16U), 1, DataType::F16),
89 TensorInfo(TensorShape(5U, 5U, 32U, 19U), 1, DataType::F32),
90 TensorInfo(TensorShape(5U, 5U, 2U, 19U), 1, DataType::F32)
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +010091 })),
Vidhya Sudhan Loganathan7485d5a2018-07-04 09:34:00 +010092 framework::dataset::make("OutputInfo", { TensorInfo(TensorShape(15U, 15U, 19U), 1, DataType::F32),
93 TensorInfo(TensorShape(15U, 15U, 19U), 1, DataType::F32),
94 TensorInfo(TensorShape(21U, 25U, 21U, 4U), 1, DataType::F32),
95 TensorInfo(TensorShape(21U, 25U, 21U, 4U), 1, DataType::F32),
96 TensorInfo(TensorShape(11U, 25U, 21U), 1, DataType::F32),
97 TensorInfo(TensorShape(11U, 12U, 16U, 4U), 1, DataType::F32),
98 TensorInfo(TensorShape(17U, 31U, 19U), 1, DataType::F32),
99 TensorInfo(TensorShape(17U, 31U, 19U), 1, DataType::F32)
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100100 })),
101 framework::dataset::make("ConvInfo", { PadStrideInfo(1, 2, 1, 1),
102 PadStrideInfo(1, 2, 1, 1),
103 PadStrideInfo(1, 1, 0, 0),
Gian Marco Iodicea8aef292018-05-14 14:21:39 +0100104 PadStrideInfo(1, 1, 0, 0),
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100105 PadStrideInfo(2, 1, 0, 0),
106 PadStrideInfo(3, 2, 1, 0),
107 PadStrideInfo(1, 1, 2, 2),
108 PadStrideInfo(1, 1, 2, 2)
109 })),
110 framework::dataset::make("GpuTarget", { GPUTarget::BIFROST,
111 GPUTarget::MIDGARD,
112 GPUTarget::G71,
Gian Marco Iodicea8aef292018-05-14 14:21:39 +0100113 GPUTarget::G71,
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100114 GPUTarget::MIDGARD,
115 GPUTarget::BIFROST,
116 GPUTarget::BIFROST,
117 GPUTarget::BIFROST
118 })),
119 framework::dataset::make("Dilation",
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000120{
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100121 Size2D(1U, 1U),
122 Size2D(1U, 1U),
123 Size2D(1U, 1U),
124 Size2D(1U, 1U),
125 Size2D(1U, 1U),
126 Size2D(1U, 1U),
Gian Marco Iodicea8aef292018-05-14 14:21:39 +0100127 Size2D(1U, 1U),
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100128 Size2D(2U, 1U),
129})),
Gian Marco Iodicea8aef292018-05-14 14:21:39 +0100130framework::dataset::make("EnableFastMath", { false, false, false, false, false, false, true, true })),
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100131framework::dataset::make("Expected",
132{
Gian Marco Iodicea8aef292018-05-14 14:21:39 +0100133 ConvolutionMethod::GEMM, ConvolutionMethod::GEMM, ConvolutionMethod::GEMM, ConvolutionMethod::WINOGRAD, ConvolutionMethod::GEMM, ConvolutionMethod::GEMM, ConvolutionMethod::WINOGRAD, ConvolutionMethod::GEMM,
Gian Marco Iodice2213d4b2018-04-27 10:39:06 +0100134})),
135input_info, weights_info, output_info, conv_info, gpu_target, dilation, enable_fast_math, expected)
136{
137 ConvolutionMethod is_valid = CLConvolutionLayer::get_convolution_method(&input_info.clone()->set_is_resizable(true),
138 &weights_info.clone()->set_is_resizable(true),
139 &output_info.clone()->set_is_resizable(true), conv_info,
140 WeightsInfo(),
141 ActivationLayerInfo(),
142 gpu_target,
143 dilation,
144 enable_fast_math);
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000145 ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS);
146}
147TEST_SUITE_END()
148
149TEST_SUITE(GEMMConvolutionLayer)
150
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000151DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(framework::dataset::concat(datasets::SmallConvolutionLayerDataset(), datasets::LargeConvolutionLayerDataset()),
152 CNNDataTypes),
153 ActivationFunctionsDataset),
154 input_shape, weights_shape, bias_shape, output_shape, info, dilation, data_type, act_info)
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100155{
Chunosov5124be52017-11-22 20:42:13 +0700156 auto bias_data_type = is_data_type_quantized_asymmetric(data_type) ? DataType::S32 : data_type;
157
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100158 // Create tensors
Vidhya Sudhan Loganathan014333d2018-07-02 09:13:49 +0100159 CLTensor src = create_tensor<CLTensor>(input_shape, data_type, 1, QuantizationInfo(2.f / 255.f, 127));
160 CLTensor weights = create_tensor<CLTensor>(weights_shape, data_type, 1, QuantizationInfo(2.f / 255.f, 127));
161 CLTensor bias = create_tensor<CLTensor>(bias_shape, bias_data_type, 1, QuantizationInfo(2.f / 255.f, 127));
162 CLTensor dst = create_tensor<CLTensor>(output_shape, data_type, 1, QuantizationInfo(2.f / 255.f, 127));
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100163
164 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
165 ARM_COMPUTE_EXPECT(weights.info()->is_resizable(), framework::LogLevel::ERRORS);
166 ARM_COMPUTE_EXPECT(bias.info()->is_resizable(), framework::LogLevel::ERRORS);
167 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
168
Chunosov5124be52017-11-22 20:42:13 +0700169 const QuantizationInfo src_quantization_info = src.info()->quantization_info();
170 const QuantizationInfo weights_quantization_info = weights.info()->quantization_info();
171
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100172 // Create and configure function
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000173 CLGEMMConvolutionLayer conv;
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000174 conv.configure(&src, &weights, &bias, &dst, info, WeightsInfo(), dilation, act_info);
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100175
176 // Validate valid region
177 const ValidRegion src_valid_region = shape_to_valid_region(input_shape);
178 const ValidRegion weights_valid_region = shape_to_valid_region(weights_shape);
179 const ValidRegion bias_valid_region = shape_to_valid_region(bias_shape);
180 const ValidRegion dst_valid_region = shape_to_valid_region(output_shape);
181
182 validate(src.info()->valid_region(), src_valid_region);
183 validate(weights.info()->valid_region(), weights_valid_region);
184 validate(bias.info()->valid_region(), bias_valid_region);
185 validate(dst.info()->valid_region(), dst_valid_region);
186
Chunosov5124be52017-11-22 20:42:13 +0700187 // Validate QuantizationInfo
188 ARM_COMPUTE_EXPECT(src.info()->quantization_info() == src_quantization_info, framework::LogLevel::ERRORS);
189 ARM_COMPUTE_EXPECT(weights.info()->quantization_info() == weights_quantization_info, framework::LogLevel::ERRORS);
190
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100191 // Validate padding
192 //TODO(COMPMID-415) Need to validate padding?
193}
194
195template <typename T>
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000196using CLGEMMConvolutionLayerFixture = ConvolutionValidationFixture<CLTensor, CLAccessor, CLGEMMConvolutionLayer, T>;
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100197
198TEST_SUITE(Float)
199TEST_SUITE(FP16)
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000200
Michalis Spyroue2503892018-04-23 15:17:31 +0100201FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMConvolutionLayerFixture<half>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000202 framework::dataset::make("ReshapeWeights", { true })),
203 framework::dataset::make("DataType",
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000204 DataType::F16)),
Georgios Pinitas19ea4192018-06-19 13:09:53 +0100205 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000206 ActivationFunctionsDataset))
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100207{
208 // Validate output
steniu013e05e4e2017-08-25 17:18:01 +0100209 validate(CLAccessor(_target), _reference, tolerance_f16, tolerance_num);
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100210}
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000211
Michalis Spyroue2503892018-04-23 15:17:31 +0100212FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMConvolutionLayerFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(datasets::LargeConvolutionLayerDataset(),
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000213 framework::dataset::make("ReshapeWeights", { true })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000214 framework::dataset::make("DataType",
215 DataType::F16)),
Georgios Pinitas19ea4192018-06-19 13:09:53 +0100216 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000217 ActivationFunctionsDataset))
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100218{
219 // Validate output
steniu013e05e4e2017-08-25 17:18:01 +0100220 validate(CLAccessor(_target), _reference, tolerance_f16, tolerance_num);
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100221}
222TEST_SUITE_END()
223
224TEST_SUITE(FP32)
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000225
Michalis Spyroue2503892018-04-23 15:17:31 +0100226FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000227 framework::dataset::make("ReshapeWeights", { true })),
228 framework::dataset::make("DataType",
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000229 DataType::F32)),
Georgios Pinitas19ea4192018-06-19 13:09:53 +0100230 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000231 ActivationFunctionsDataset))
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100232{
233 // Validate output
234 validate(CLAccessor(_target), _reference, tolerance_f32);
235}
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000236
Michalis Spyroue2503892018-04-23 15:17:31 +0100237FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(datasets::LargeConvolutionLayerDataset(),
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000238 framework::dataset::make("ReshapeWeights", { true })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000239 framework::dataset::make("DataType",
240 DataType::F32)),
Georgios Pinitas19ea4192018-06-19 13:09:53 +0100241 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000242 ActivationFunctionsDataset))
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100243{
244 // Validate output
Georgios Pinitas5e207532018-04-27 14:38:16 +0100245 validate(CLAccessor(_target), _reference, tolerance_f32, 0.f, absolute_tolerance_float);
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100246}
247TEST_SUITE_END()
248TEST_SUITE_END()
249
250template <typename T>
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000251using CLGEMMConvolutionLayerQuantizedFixture = ConvolutionValidationQuantizedFixture<CLTensor, CLAccessor, CLGEMMConvolutionLayer, T>;
Chunosov5124be52017-11-22 20:42:13 +0700252
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000253const auto QuantizedActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
254{
255 ActivationLayerInfo(),
256 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
257 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 6.f)
258});
259
Chunosov5124be52017-11-22 20:42:13 +0700260TEST_SUITE(Quantized)
261TEST_SUITE(QASYMM8)
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000262
Georgios Pinitas19ea4192018-06-19 13:09:53 +0100263FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
Chunosov5124be52017-11-22 20:42:13 +0700264 framework::dataset::make("ReshapeWeights", { true })),
265 framework::dataset::make("DataType", DataType::QASYMM8)),
Gian Marco Iodicedff601d2018-08-09 13:28:41 +0100266 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000267 framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255.f, 10) })),
268 QuantizedActivationFunctionsDataset))
Chunosov5124be52017-11-22 20:42:13 +0700269{
270 // Validate output
271 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
272}
Georgios Pinitas19ea4192018-06-19 13:09:53 +0100273FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(combine(datasets::LargeConvolutionLayerDataset(),
Isabella Gottardif07d28d2018-02-06 14:52:43 +0000274 framework::dataset::make("ReshapeWeights", { true })),
275 framework::dataset::make("DataType", DataType::QASYMM8)),
Gian Marco Iodicedff601d2018-08-09 13:28:41 +0100276 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
Isabella Gottardi3f217ec2018-02-12 14:59:19 +0000277 framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255.f, 0) })),
278 QuantizedActivationFunctionsDataset))
Chunosov5124be52017-11-22 20:42:13 +0700279{
280 // Validate output
281 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
Moritz Pflanzerb3d25792017-07-26 11:49:37 +0100282}
283TEST_SUITE_END()
284TEST_SUITE_END()
285
286TEST_SUITE_END()
287TEST_SUITE_END()
288} // namespace validation
289} // namespace test
290} // namespace arm_compute