blob: d98f99a63cbfff70782e6e8525e61ae913d9c53f [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 */
Moritz Pflanzerd58cec02017-07-18 15:44:21 +010024#include "NEON/Accessor.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010025#include "TypePrinter.h"
Moritz Pflanzer94450f12017-06-30 12:48:43 +010026#include "tests/Globals.h"
Pablo Tello8fda1cb2017-07-05 15:20:38 +010027#include "tests/NEON/Helper.h"
Moritz Pflanzer94450f12017-06-30 12:48:43 +010028#include "tests/Utils.h"
Moritz Pflanzera09de0c2017-09-01 20:41:12 +010029#include "tests/validation_old/Datasets.h"
30#include "tests/validation_old/Helpers.h"
31#include "tests/validation_old/Reference.h"
32#include "tests/validation_old/Validation.h"
33#include "tests/validation_old/dataset/BatchNormalizationLayerDataset.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010034
35#include "arm_compute/runtime/NEON/functions/NEBatchNormalizationLayer.h"
36
37#include <random>
38
39using namespace arm_compute;
40using namespace arm_compute::test;
Anthony Barbier6ff3b192017-09-04 18:44:23 +010041using namespace arm_compute::test::validation;
42
43namespace
44{
Pablo Tello8fda1cb2017-07-05 15:20:38 +010045const float tolerance_qs8 = 6; /**< Tolerance value for comparing reference's output against quantized implementation's output */
46const float tolerance_qs16 = 6; /**< Tolerance value for comparing reference's output against quantized implementation's output */
47const float tolerance_f32 = 1e-05f; /**< Tolerance value for comparing reference's output against floating point implementation's output */
48#ifdef ARM_COMPUTE_ENABLE_FP16
49const float tolerance_f16 = 0.01f; /**< Tolerance value for comparing reference's output against half precision floating point implementation's output */
50#endif /* ARM_COMPUTE_ENABLE_FP16 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +010051
52/** Compute Neon batch normalization function.
53 *
54 * @param[in] shape Shape of the input and output tensors.
55 * @param[in] dt Data type of input and output tensors.
56 * @param[in] norm_info Normalization Layer information.
57 *
58 * @return Computed output tensor.
59 */
60Tensor compute_reference_batch_normalization_layer(const TensorShape &shape0, const TensorShape &shape1, DataType dt, float epsilon, int fixed_point_position = 0)
61{
62 // Create tensors
Moritz Pflanzer94450f12017-06-30 12:48:43 +010063 Tensor src = create_tensor<Tensor>(shape0, dt, 1, fixed_point_position);
64 Tensor dst = create_tensor<Tensor>(shape0, dt, 1, fixed_point_position);
65 Tensor mean = create_tensor<Tensor>(shape1, dt, 1, fixed_point_position);
66 Tensor var = create_tensor<Tensor>(shape1, dt, 1, fixed_point_position);
67 Tensor beta = create_tensor<Tensor>(shape1, dt, 1, fixed_point_position);
68 Tensor gamma = create_tensor<Tensor>(shape1, dt, 1, fixed_point_position);
Anthony Barbier6ff3b192017-09-04 18:44:23 +010069
70 // Create and configure function
71 NEBatchNormalizationLayer norm;
72 norm.configure(&src, &dst, &mean, &var, &beta, &gamma, epsilon);
73
74 // Allocate tensors
75 src.allocator()->allocate();
76 dst.allocator()->allocate();
77 mean.allocator()->allocate();
78 var.allocator()->allocate();
79 beta.allocator()->allocate();
80 gamma.allocator()->allocate();
81
82 BOOST_TEST(!src.info()->is_resizable());
83 BOOST_TEST(!dst.info()->is_resizable());
84 BOOST_TEST(!mean.info()->is_resizable());
85 BOOST_TEST(!var.info()->is_resizable());
86 BOOST_TEST(!beta.info()->is_resizable());
87 BOOST_TEST(!gamma.info()->is_resizable());
88
89 // Fill tensors
Pablo Tello8fda1cb2017-07-05 15:20:38 +010090 switch(dt)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010091 {
Pablo Tello8fda1cb2017-07-05 15:20:38 +010092 case DataType::QS8:
Michalis Spyrou172e5702017-06-26 14:18:47 +010093 {
Pablo Tello8fda1cb2017-07-05 15:20:38 +010094 const std::pair<int8_t, int8_t> bounds = get_batchnormalization_layer_test_bounds<int8_t>(fixed_point_position);
95 std::uniform_int_distribution<> distribution(bounds.first, bounds.second);
96 std::uniform_int_distribution<> distribution_var(0, bounds.second);
97 test::fill_tensors(distribution, { 0, 1, 3, 4 }, &src, &mean, &beta, &gamma);
98 test::fill_tensors(distribution_var, { 0 }, &var);
99 break;
Michalis Spyrou172e5702017-06-26 14:18:47 +0100100 }
Pablo Tello8fda1cb2017-07-05 15:20:38 +0100101 case DataType::QS16:
Michalis Spyrou172e5702017-06-26 14:18:47 +0100102 {
Pablo Tello8fda1cb2017-07-05 15:20:38 +0100103 const std::pair<int16_t, int16_t> bounds = get_batchnormalization_layer_test_bounds<int16_t>(fixed_point_position);
104 std::uniform_int_distribution<> distribution(bounds.first, bounds.second);
105 std::uniform_int_distribution<> distribution_var(0, bounds.second);
106 test::fill_tensors(distribution, { 0, 1, 3, 4 }, &src, &mean, &beta, &gamma);
107 test::fill_tensors(distribution_var, { 0 }, &var);
108 break;
Michalis Spyrou172e5702017-06-26 14:18:47 +0100109 }
Pablo Tello8fda1cb2017-07-05 15:20:38 +0100110#ifdef ARM_COMPUTE_ENABLE_FP16
111 case DataType::F16:
112 {
113 const std::pair<half_float::half, half_float::half> bounds = get_batchnormalization_layer_test_bounds<half_float::half>();
114 std::uniform_real_distribution<> distribution(bounds.first, bounds.second);
115 std::uniform_real_distribution<> distribution_var(0, bounds.second);
116 test::fill_tensors(distribution, { 0, 1, 3, 4 }, &src, &mean, &beta, &gamma);
117 test::fill_tensors(distribution_var, { 0 }, &var);
118 break;
119 }
120#endif /* ARM_COMPUTE_ENABLE_FP16 */
121 case DataType::F32:
122 {
123 const std::pair<float, float> bounds = get_batchnormalization_layer_test_bounds<float>();
124 std::uniform_real_distribution<> distribution(bounds.first, bounds.second);
125 std::uniform_real_distribution<> distribution_var(0, bounds.second);
126 test::fill_tensors(distribution, { 0, 1, 3, 4 }, &src, &mean, &beta, &gamma);
127 test::fill_tensors(distribution_var, { 0 }, &var);
128 break;
129 }
130 default:
131 {
132 ARM_COMPUTE_ERROR("Not supported");
133 break;
134 }
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100135 }
136
137 // Compute function
138 norm.run();
139
140 return dst;
141}
142} // namespace
143
144#ifndef DOXYGEN_SKIP_THIS
145BOOST_AUTO_TEST_SUITE(NEON)
146BOOST_AUTO_TEST_SUITE(BatchNormalizationLayer)
147
148BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit") * boost::unit_test::label("nightly"))
Michalis Spyroubbd3d602017-06-21 17:29:40 +0100149BOOST_DATA_TEST_CASE(Configuration, RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make({ DataType::QS8, DataType::QS16, DataType::F32 }), obj, dt)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100150{
151 // Set fixed point position data type allowed
152 int fixed_point_position = (arm_compute::is_data_type_fixed_point(dt)) ? 3 : 0;
153
154 // Create tensors
Moritz Pflanzer94450f12017-06-30 12:48:43 +0100155 Tensor src = create_tensor<Tensor>(obj.shape0, dt, 1, fixed_point_position);
156 Tensor dst = create_tensor<Tensor>(obj.shape0, dt, 1, fixed_point_position);
157 Tensor mean = create_tensor<Tensor>(obj.shape1, dt, 1, fixed_point_position);
158 Tensor var = create_tensor<Tensor>(obj.shape1, dt, 1, fixed_point_position);
159 Tensor beta = create_tensor<Tensor>(obj.shape1, dt, 1, fixed_point_position);
160 Tensor gamma = create_tensor<Tensor>(obj.shape1, dt, 1, fixed_point_position);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100161
162 BOOST_TEST(src.info()->is_resizable());
163 BOOST_TEST(dst.info()->is_resizable());
164 BOOST_TEST(mean.info()->is_resizable());
165 BOOST_TEST(var.info()->is_resizable());
166 BOOST_TEST(beta.info()->is_resizable());
167 BOOST_TEST(gamma.info()->is_resizable());
168
169 // Create and configure function
170 NEBatchNormalizationLayer norm;
171 norm.configure(&src, &dst, &mean, &var, &beta, &gamma, obj.epsilon);
172
173 // Validate valid region
174 const ValidRegion valid_region = shape_to_valid_region(obj.shape0);
175 const ValidRegion valid_region_vec = shape_to_valid_region(obj.shape1);
176 validate(src.info()->valid_region(), valid_region);
177 validate(dst.info()->valid_region(), valid_region);
178 validate(mean.info()->valid_region(), valid_region_vec);
179 validate(var.info()->valid_region(), valid_region_vec);
180 validate(beta.info()->valid_region(), valid_region_vec);
181 validate(gamma.info()->valid_region(), valid_region_vec);
182}
183
184BOOST_AUTO_TEST_SUITE(Float)
185BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
186BOOST_DATA_TEST_CASE(Random,
187 RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::F32),
188 obj, dt)
189{
190 // Compute function
191 Tensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon);
192
193 // Compute reference
194 RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon);
195
196 // Validate output
Pablo Tello8fda1cb2017-07-05 15:20:38 +0100197 validate(Accessor(dst), ref_dst, tolerance_f32, 0);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100198}
199BOOST_AUTO_TEST_SUITE_END()
200
Pablo Tello8fda1cb2017-07-05 15:20:38 +0100201#ifdef ARM_COMPUTE_ENABLE_FP16
202BOOST_AUTO_TEST_SUITE(Float16)
203BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
204BOOST_DATA_TEST_CASE(Random,
205 RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::F16),
206 obj, dt)
207{
208 // Compute function
209 Tensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon);
210
211 // Compute reference
212 RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon);
213
214 // Validate output
215 validate(Accessor(dst), ref_dst, tolerance_f16, 0);
216}
217BOOST_AUTO_TEST_SUITE_END()
218#endif /* ARM_COMPUTE_ENABLE_FP16 */
219
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100220BOOST_AUTO_TEST_SUITE(Quantized)
Michalis Spyroubbd3d602017-06-21 17:29:40 +0100221BOOST_AUTO_TEST_SUITE(QS8)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100222BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
223BOOST_DATA_TEST_CASE(Random,
224 RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::QS8) * boost::unit_test::data::xrange(1, 6),
225 obj, dt, fixed_point_position)
226{
227 // Compute function
228 Tensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position);
229
230 // Compute reference
231 RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position);
232
233 // Validate output
Moritz Pflanzerd58cec02017-07-18 15:44:21 +0100234 validate(Accessor(dst), ref_dst, tolerance_qs8);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100235}
236BOOST_AUTO_TEST_SUITE_END()
237
Michalis Spyroubbd3d602017-06-21 17:29:40 +0100238BOOST_AUTO_TEST_SUITE(QS16)
239BOOST_TEST_DECORATOR(*boost::unit_test::label("precommit"))
240BOOST_DATA_TEST_CASE(Random,
241 RandomBatchNormalizationLayerDataset() * boost::unit_test::data::make(DataType::QS16) * boost::unit_test::data::xrange(1, 14),
242 obj, dt, fixed_point_position)
243{
244 // Compute function
245 Tensor dst = compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position);
246
247 // Compute reference
248 RawTensor ref_dst = Reference::compute_reference_batch_normalization_layer(obj.shape0, obj.shape1, dt, obj.epsilon, fixed_point_position);
249
250 // Validate output
Moritz Pflanzerd58cec02017-07-18 15:44:21 +0100251 validate(Accessor(dst), ref_dst, tolerance_qs16);
Michalis Spyroubbd3d602017-06-21 17:29:40 +0100252}
253BOOST_AUTO_TEST_SUITE_END()
254BOOST_AUTO_TEST_SUITE_END()
255
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100256BOOST_AUTO_TEST_SUITE_END()
257BOOST_AUTO_TEST_SUITE_END()
Anthony Barbierac69aa12017-07-03 17:39:37 +0100258#endif /* DOXYGEN_SKIP_THIS */