blob: a1dbe38bbf3d59d9726c6448b392ddae6270076c [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
2 * Copyright (c) 2017 ARM Limited.
3 *
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 "NEON/Helper.h"
25#include "NEON/NEAccessor.h"
26#include "TypePrinter.h"
27#include "dataset/ConvolutionLayerDataset.h"
28#include "validation/Datasets.h"
29#include "validation/Reference.h"
30#include "validation/Validation.h"
31
32#include "arm_compute/core/Error.h"
33#include "arm_compute/runtime/NEON/functions/NEConvolutionLayer.h"
34
35#include <random>
36
37using namespace arm_compute;
38using namespace arm_compute::test;
39using namespace arm_compute::test::neon;
40using namespace arm_compute::test::validation;
41
42namespace
43{
44const float tolerance_f32 = 1e-03f; /**< Tolerance value for comparing reference's output against implementation's output for DataType::F32 */
45const float tolerance_qs8 = 3.0f; /**< Tolerance value for comparing reference's output against implementation's output for DataType::QS8 */
46
47Tensor compute_convolution_layer(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &bias_shape, const TensorShape &output_shape, DataType dt,
48 const PadStrideInfo &conv_info, int fixed_point_position)
49{
50 // Create tensors
51 Tensor src = create_tensor(input_shape, dt, 1, fixed_point_position);
52 Tensor weights = create_tensor(weights_shape, dt, 1, fixed_point_position);
53 Tensor bias = create_tensor(bias_shape, dt, 1, fixed_point_position);
54 Tensor dst = create_tensor(output_shape, dt, 1, fixed_point_position);
55
56 // Create and configure function
57 NEConvolutionLayer conv;
58 conv.configure(&src, &weights, &bias, &dst, conv_info);
59
60 // Allocate tensors
61 src.allocator()->allocate();
62 weights.allocator()->allocate();
63 bias.allocator()->allocate();
64 dst.allocator()->allocate();
65
66 BOOST_TEST(!src.info()->is_resizable());
67 BOOST_TEST(!weights.info()->is_resizable());
68 BOOST_TEST(!bias.info()->is_resizable());
69 BOOST_TEST(!dst.info()->is_resizable());
70
71 // Fill tensors
72 if(dt == DataType::F32)
73 {
74 std::uniform_real_distribution<> distribution(-1.0f, 1.0f);
75 library->fill(NEAccessor(src), distribution, 0);
76 library->fill(NEAccessor(weights), distribution, 1);
77 library->fill(NEAccessor(bias), distribution, 2);
78 }
79 else
80 {
81 library->fill_tensor_uniform(NEAccessor(src), 0);
82 library->fill_tensor_uniform(NEAccessor(weights), 1);
83 library->fill_tensor_uniform(NEAccessor(bias), 2);
84 }
85
86 // Compute NEConvolutionLayer function
87 conv.run();
88
89 return dst;
90}
91} // namespace
92
93#ifndef DOXYGEN_SKIP_THIS
94BOOST_AUTO_TEST_SUITE(NEON)
95BOOST_AUTO_TEST_SUITE(ConvolutionLayer)
96BOOST_AUTO_TEST_SUITE(GEMM)
97
98BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly"))
99BOOST_DATA_TEST_CASE(Configuration,
100 AlexNetConvolutionLayerDataset() * boost::unit_test::data::make({ DataType::F32, DataType::QS8 }),
101 conv_set, dt)
102{
103 // Set fixed point position data type allowed
104 int fixed_point_position = (dt == DataType::F32) ? 0 : 3;
105
106 // Create tensors
107 Tensor src = create_tensor(conv_set.src_shape, dt, 1, fixed_point_position);
108 Tensor weights = create_tensor(conv_set.weights_shape, dt, 1, fixed_point_position);
109 Tensor bias = create_tensor(conv_set.bias_shape, dt, 1, fixed_point_position);
110 Tensor dst = create_tensor(conv_set.dst_shape, dt, 1, fixed_point_position);
111
112 BOOST_TEST(src.info()->is_resizable());
113 BOOST_TEST(weights.info()->is_resizable());
114 BOOST_TEST(bias.info()->is_resizable());
115 BOOST_TEST(dst.info()->is_resizable());
116
117 // Create and configure function
118 NEConvolutionLayer conv;
119 conv.configure(&src, &weights, &bias, &dst, conv_set.info);
120
121 // Validate valid region
122 const ValidRegion src_valid_region = shape_to_valid_region(conv_set.src_shape);
123 const ValidRegion weights_valid_region = shape_to_valid_region(conv_set.weights_shape);
124 const ValidRegion bias_valid_region = shape_to_valid_region(conv_set.bias_shape);
125 const ValidRegion dst_valid_region = shape_to_valid_region(conv_set.dst_shape);
126
127 validate(src.info()->valid_region(), src_valid_region);
128 validate(weights.info()->valid_region(), weights_valid_region);
129 validate(bias.info()->valid_region(), bias_valid_region);
130 validate(dst.info()->valid_region(), dst_valid_region);
131}
132
133BOOST_AUTO_TEST_SUITE(Float)
134BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
135BOOST_DATA_TEST_CASE(SmallConvolutionLayer,
136 SmallConvolutionLayerDataset() * boost::unit_test::data::make(DataType::F32),
137 conv_set, dt)
138{
139 // Compute function
140 Tensor dst = compute_convolution_layer(conv_set.src_shape, conv_set.weights_shape, conv_set.bias_shape, conv_set.dst_shape, dt, conv_set.info, 0);
141
142 // Compute reference
143 RawTensor ref_dst = Reference::compute_reference_convolution_layer(conv_set.src_shape, conv_set.weights_shape, conv_set.bias_shape, conv_set.dst_shape, dt, conv_set.info, 0);
144
145 // Validate output
146 validate(NEAccessor(dst), ref_dst, tolerance_f32);
147}
148
149BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly"))
150BOOST_DATA_TEST_CASE(LargeConvolutionLayer,
151 AlexNetConvolutionLayerDataset() * boost::unit_test::data::make(DataType::F32),
152 conv_set, dt)
153{
154 // Compute function
155 Tensor dst = compute_convolution_layer(conv_set.src_shape, conv_set.weights_shape, conv_set.bias_shape, conv_set.dst_shape, dt, conv_set.info, 0);
156
157 // Compute reference
158 RawTensor ref_dst = Reference::compute_reference_convolution_layer(conv_set.src_shape, conv_set.weights_shape, conv_set.bias_shape, conv_set.dst_shape, dt, conv_set.info, 0);
159
160 // Validate output
161 validate(NEAccessor(dst), ref_dst, tolerance_f32);
162}
163BOOST_AUTO_TEST_SUITE_END()
164
165BOOST_AUTO_TEST_SUITE(Quantized)
166BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
167BOOST_DATA_TEST_CASE(SmallConvolutionLayer,
168 SmallConvolutionLayerDataset() * boost::unit_test::data::make(DataType::QS8) * boost::unit_test::data::xrange(4, 7),
169 conv_set, dt, fixed_point_position)
170{
171 // Compute function
172 Tensor dst = compute_convolution_layer(conv_set.src_shape, conv_set.weights_shape, conv_set.bias_shape, conv_set.dst_shape, dt, conv_set.info, fixed_point_position);
173
174 // Compute reference
175 RawTensor ref_dst = Reference::compute_reference_convolution_layer(conv_set.src_shape, conv_set.weights_shape, conv_set.bias_shape, conv_set.dst_shape, dt, conv_set.info, fixed_point_position);
176
177 // Validate output
178 validate(NEAccessor(dst), ref_dst, tolerance_qs8);
179}
180
181BOOST_TEST_DECORATOR(*boost::unit_test::label("nightly"))
182BOOST_DATA_TEST_CASE(LargeConvolutionLayer,
183 AlexNetConvolutionLayerDataset() * boost::unit_test::data::make(DataType::QS8) * boost::unit_test::data::xrange(4, 7),
184 conv_set, dt, fixed_point_position)
185{
186 // Compute function
187 Tensor dst = compute_convolution_layer(conv_set.src_shape, conv_set.weights_shape, conv_set.bias_shape, conv_set.dst_shape, dt, conv_set.info, fixed_point_position);
188
189 // Compute reference
190 RawTensor ref_dst = Reference::compute_reference_convolution_layer(conv_set.src_shape, conv_set.weights_shape, conv_set.bias_shape, conv_set.dst_shape, dt, conv_set.info, fixed_point_position);
191
192 // Validate output
193 validate(NEAccessor(dst), ref_dst, tolerance_qs8);
194}
195BOOST_AUTO_TEST_SUITE_END()
196
197BOOST_AUTO_TEST_SUITE_END()
198BOOST_AUTO_TEST_SUITE_END()
199BOOST_AUTO_TEST_SUITE_END()
200#endif