blob: 078096a0dd16bf889afe5cc4eabcba61a01fee52 [file] [log] [blame]
Pablo Tello299025a2017-09-29 11:30:12 +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 */
Gian Marco Iodiceab182122017-10-09 15:05:40 +010024#include "arm_compute/core/NEON/kernels/NEGEMMInterleaveBlockedKernel.h"
Pablo Tello181e6512017-11-15 13:28:27 +000025#include "arm_compute/core/NEON/kernels/arm64/NEGEMMLowpAArch64Kernel.h"
Pablo Tello299025a2017-09-29 11:30:12 +010026#include "arm_compute/core/Types.h"
Pablo Tello181e6512017-11-15 13:28:27 +000027#include "arm_compute/runtime/NEON/functions/NEGEMMLowpAssemblyMatrixMultiplyCore.h"
Gian Marcoe75a02b2017-11-08 12:24:09 +000028#include "arm_compute/runtime/NEON/functions/NEGEMMLowpMatrixMultiplyCore.h"
29#include "arm_compute/runtime/NEON/functions/NEGEMMLowpOutputStage.h"
Pablo Tello299025a2017-09-29 11:30:12 +010030#include "arm_compute/runtime/Tensor.h"
31#include "arm_compute/runtime/TensorAllocator.h"
32#include "tests/NEON/Accessor.h"
Gian Marco Iodiceab182122017-10-09 15:05:40 +010033#include "tests/NEON/Helper.h"
Gian Marcoe75a02b2017-11-08 12:24:09 +000034#include "tests/PaddingCalculator.h"
Gian Marcofa4cacd2017-10-18 17:05:02 +010035#include "tests/datasets/LargeGEMMLowpDataset.h"
Gian Marcoe75a02b2017-11-08 12:24:09 +000036#include "tests/datasets/ShapeDatasets.h"
Gian Marcofa4cacd2017-10-18 17:05:02 +010037#include "tests/datasets/SmallGEMMLowpDataset.h"
Pablo Tello299025a2017-09-29 11:30:12 +010038#include "tests/framework/Asserts.h"
39#include "tests/framework/Macros.h"
40#include "tests/framework/datasets/Datasets.h"
41#include "tests/validation/Validation.h"
Pablo Tellobf2fb952017-09-29 16:43:25 +010042#include "tests/validation/fixtures/GEMMInterleaveBlockedFixture.h"
Pablo Tello181e6512017-11-15 13:28:27 +000043#include "tests/validation/fixtures/GEMMLowpAssemblyFixture.h"
Pablo Tello299025a2017-09-29 11:30:12 +010044#include "tests/validation/fixtures/GEMMLowpFixture.h"
45
46namespace arm_compute
47{
48namespace test
49{
50namespace validation
51{
52namespace
53{
Pablo Tello181e6512017-11-15 13:28:27 +000054const auto data_int_blk = framework::dataset::make("M", 8, 12) * framework::dataset::make("N", 8, 12) * framework::dataset::make("by", 8, 13) * framework::dataset::make("block", 4, 9);
55const auto data_int_blk_tr = framework::dataset::make("M", 8, 17) * framework::dataset::make("N", 8, 14) * framework::dataset::make("by", 12) * framework::dataset::make("block", 4);
56const auto data_matrix_multiply = framework::dataset::make("M", 12, 20) * framework::dataset::make("N", 12, 20) * framework::dataset::make("K", 16);
Pablo Tello299025a2017-09-29 11:30:12 +010057} // namespace
58
59TEST_SUITE(NEON)
Pablo Tello181e6512017-11-15 13:28:27 +000060TEST_SUITE(ASSEMBLY_MATRIX_MULTIPLY)
61using NEGEMMAssemblyFixture = GEMMLowpAssemblyFixture<Tensor, Accessor, NEGEMMLowpAssemblyMatrixMultiplyCore>;
62FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMAssemblyFixture, framework::DatasetMode::PRECOMMIT, data_matrix_multiply)
63{
64 // Validate output
65 validate(Accessor(_target), _reference);
66}
67TEST_SUITE_END()
68
Pablo Tello299025a2017-09-29 11:30:12 +010069TEST_SUITE(GEMMLowp)
70
Pablo Tellobf2fb952017-09-29 16:43:25 +010071TEST_SUITE(INTERLEAVE_BLOCKED)
72
73using NEInterleaveBlocked = NESynthetizeFunction<NEGEMMInterleaveBlockedKernel>;
74using NEGEMMInterleaveBlockedFixture = GEMMInterleaveBlockedValidationFixture<Tensor, Accessor, NEInterleaveBlocked>;
75FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMInterleaveBlockedFixture, framework::DatasetMode::PRECOMMIT, data_int_blk)
76{
77 // Validate output
Gian Marcofa4cacd2017-10-18 17:05:02 +010078 validate(Accessor(_target), _reference);
Pablo Tellobf2fb952017-09-29 16:43:25 +010079}
80TEST_SUITE_END()
81
82TEST_SUITE(INTERLEAVE_BLOCKED_TRANSPOSED)
83using NEInterleaveBlockedTransposed = NESynthetizeFunction<NEGEMMInterleaveBlockedKernel>;
84using NEGEMMInterleaveBlockedTransposedFixture = GEMMInterleaveBlockedValidationFixture<Tensor, Accessor, NEInterleaveBlockedTransposed, true>;
85FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMInterleaveBlockedTransposedFixture, framework::DatasetMode::PRECOMMIT, data_int_blk_tr)
86{
87 // Validate output
Gian Marcofa4cacd2017-10-18 17:05:02 +010088 validate(Accessor(_target), _reference);
Pablo Tellobf2fb952017-09-29 16:43:25 +010089}
90
91TEST_SUITE_END()
92
Gian Marcoe75a02b2017-11-08 12:24:09 +000093TEST_SUITE(MatrixMultiplyCore)
94using NEGEMMLowpMatrixMultiplyCoreFixture = GEMMLowpMatrixMultiplyCoreValidationFixture<Tensor, Accessor, NEGEMMLowpMatrixMultiplyCore>;
Gian Marcofa4cacd2017-10-18 17:05:02 +010095
Gian Marcoe75a02b2017-11-08 12:24:09 +000096DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, framework::dataset::concat(datasets::SmallGEMMLowpDataset(), datasets::LargeGEMMLowpDataset()),
97 shape_a, shape_b, shape_c, a_offset, b_offset)
Gian Marcofa4cacd2017-10-18 17:05:02 +010098{
99 // Create tensors
Gian Marcoe75a02b2017-11-08 12:24:09 +0000100 Tensor a = create_tensor<Tensor>(shape_a, DataType::QASYMM8);
101 Tensor b = create_tensor<Tensor>(shape_b, DataType::QASYMM8);
102 Tensor c = create_tensor<Tensor>(shape_c, DataType::S32);
103
104 a.info()->set_quantization_info(QuantizationInfo(1.0f / 255, a_offset));
105 b.info()->set_quantization_info(QuantizationInfo(1.0f / 255, b_offset));
Gian Marcofa4cacd2017-10-18 17:05:02 +0100106
107 ARM_COMPUTE_EXPECT(a.info()->is_resizable(), framework::LogLevel::ERRORS);
108 ARM_COMPUTE_EXPECT(b.info()->is_resizable(), framework::LogLevel::ERRORS);
109 ARM_COMPUTE_EXPECT(c.info()->is_resizable(), framework::LogLevel::ERRORS);
110
111 // Create and configure function
Gian Marcoe75a02b2017-11-08 12:24:09 +0000112 NEGEMMLowpMatrixMultiplyCore gemmlowp_mm;
113 gemmlowp_mm.configure(&a, &b, &c);
Gian Marcofa4cacd2017-10-18 17:05:02 +0100114}
115
Gian Marcoe75a02b2017-11-08 12:24:09 +0000116FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMLowpMatrixMultiplyCoreFixture, framework::DatasetMode::ALL, datasets::SmallGEMMLowpDataset())
Pablo Tello299025a2017-09-29 11:30:12 +0100117{
118 // Validate output
Gian Marcofa4cacd2017-10-18 17:05:02 +0100119 validate(Accessor(_target), _reference);
120}
121
Gian Marcoe75a02b2017-11-08 12:24:09 +0000122FIXTURE_DATA_TEST_CASE(RunLarge, NEGEMMLowpMatrixMultiplyCoreFixture, framework::DatasetMode::NIGHTLY, datasets::LargeGEMMLowpDataset())
Gian Marcofa4cacd2017-10-18 17:05:02 +0100123{
124 // Validate output
125 validate(Accessor(_target), _reference);
Pablo Tello299025a2017-09-29 11:30:12 +0100126}
Pablo Tello299025a2017-09-29 11:30:12 +0100127
Gian Marcoe75a02b2017-11-08 12:24:09 +0000128TEST_SUITE_END() // MatrixMultiplyCore
129
130TEST_SUITE(OutputStage)
131
132TEST_SUITE(QuantizeDownInt32ToUint8Scale)
133
Gian Marco6b77e912017-11-17 09:27:57 +0000134const auto quantize_down_int32_to_uint8_scale_cases = framework::dataset::make("result_offset", -2, 2) * framework::dataset::make("result_mult_int", 1, 2) * framework::dataset::make("result_shift", 2,
135 3)
136 * framework::dataset::make("min", 0) * framework::dataset::make("max", 0) * framework::dataset::make("addBias", { false, true });
137
138const auto quantize_down_int32_to_uint8_scale_relu_cases = framework::dataset::make("result_offset", -2, 2) * framework::dataset::make("result_mult_int", 1,
139 2)
140 * framework::dataset::make("result_shift", 2, 3) * framework::dataset::make("min", 0, 2) * framework::dataset::make("max", 171, 174) * framework::dataset::make("addBias", { false, true });
141
Gian Marcoe75a02b2017-11-08 12:24:09 +0000142using NEGEMMLowpQuantizeDownInt32ToUint8ScaleFixture = GEMMLowpQuantizeDownInt32ToUint8ScaleValidationFixture<Tensor, Accessor, NEGEMMLowpQuantizeDownInt32ToUint8Scale>;
143
Gian Marcoe75a02b2017-11-08 12:24:09 +0000144DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(framework::dataset::concat(datasets::SmallShapes(), datasets::LargeShapes()), quantize_down_int32_to_uint8_scale_cases),
Gian Marco6b77e912017-11-17 09:27:57 +0000145 shape, result_offset, result_mult_int, result_shift, min, max, add_bias)
Gian Marcoe75a02b2017-11-08 12:24:09 +0000146{
Gian Marco6b77e912017-11-17 09:27:57 +0000147 TensorShape shape_bias(shape[0]);
148
Gian Marcoe75a02b2017-11-08 12:24:09 +0000149 // Create tensors
Gian Marco6b77e912017-11-17 09:27:57 +0000150 Tensor in = create_tensor<Tensor>(shape, DataType::S32);
151 Tensor bias = create_tensor<Tensor>(shape_bias, DataType::S32);
152 Tensor out = create_tensor<Tensor>(shape, DataType::QASYMM8);
Gian Marcoe75a02b2017-11-08 12:24:09 +0000153
154 ARM_COMPUTE_EXPECT(in.info()->is_resizable(), framework::LogLevel::ERRORS);
Gian Marco6b77e912017-11-17 09:27:57 +0000155 ARM_COMPUTE_EXPECT(bias.info()->is_resizable(), framework::LogLevel::ERRORS);
Gian Marcoe75a02b2017-11-08 12:24:09 +0000156 ARM_COMPUTE_EXPECT(out.info()->is_resizable(), framework::LogLevel::ERRORS);
157
158 // Create and configure function
159 NEGEMMLowpQuantizeDownInt32ToUint8Scale output_stage;
Gian Marco6b77e912017-11-17 09:27:57 +0000160 output_stage.configure(&in, add_bias ? &bias : nullptr, &out, result_offset, result_mult_int, result_shift, min, max);
Gian Marcoe75a02b2017-11-08 12:24:09 +0000161
Gian Marco6b77e912017-11-17 09:27:57 +0000162 // Validate valid region input and output
Gian Marcoe75a02b2017-11-08 12:24:09 +0000163 const ValidRegion valid_region = shape_to_valid_region(shape);
164 validate(in.info()->valid_region(), valid_region);
165 validate(out.info()->valid_region(), valid_region);
166
Gian Marco6b77e912017-11-17 09:27:57 +0000167 // Validate valid region bias
168 if(add_bias)
169 {
170 const ValidRegion valid_region_bias = shape_to_valid_region(shape_bias);
171 validate(bias.info()->valid_region(), valid_region_bias);
172 }
173
Gian Marcoe75a02b2017-11-08 12:24:09 +0000174 // Validate padding
175 const PaddingSize padding = PaddingCalculator(shape.x(), 16).required_padding();
176 validate(in.info()->padding(), padding);
177 validate(out.info()->padding(), padding);
Gian Marco6b77e912017-11-17 09:27:57 +0000178
179 if(add_bias)
180 {
181 validate(bias.info()->padding(), padding);
182 }
Gian Marcoe75a02b2017-11-08 12:24:09 +0000183}
184
185FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMLowpQuantizeDownInt32ToUint8ScaleFixture, framework::DatasetMode::ALL, combine(datasets::SmallShapes(), quantize_down_int32_to_uint8_scale_cases))
Pablo Tellobf2fb952017-09-29 16:43:25 +0100186{
187 // Validate output
Gian Marcofa4cacd2017-10-18 17:05:02 +0100188 validate(Accessor(_target), _reference);
Pablo Tellobf2fb952017-09-29 16:43:25 +0100189}
Pablo Tello6ff12a02017-11-02 16:09:35 +0000190
Gian Marcoe75a02b2017-11-08 12:24:09 +0000191FIXTURE_DATA_TEST_CASE(RunLarge, NEGEMMLowpQuantizeDownInt32ToUint8ScaleFixture, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), quantize_down_int32_to_uint8_scale_cases))
192{
193 // Validate output
194 validate(Accessor(_target), _reference);
195}
196
Gian Marco6b77e912017-11-17 09:27:57 +0000197TEST_SUITE(BoundedReLu)
198FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMLowpQuantizeDownInt32ToUint8ScaleFixture, framework::DatasetMode::ALL, combine(datasets::SmallShapes(), quantize_down_int32_to_uint8_scale_relu_cases))
199{
200 // Validate output
201 validate(Accessor(_target), _reference);
202}
Gian Marcoe75a02b2017-11-08 12:24:09 +0000203
Gian Marco6b77e912017-11-17 09:27:57 +0000204FIXTURE_DATA_TEST_CASE(RunLarge, NEGEMMLowpQuantizeDownInt32ToUint8ScaleFixture, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), quantize_down_int32_to_uint8_scale_relu_cases))
205{
206 // Validate output
207 validate(Accessor(_target), _reference);
208}
209TEST_SUITE_END() // BoundedReLu
210
211TEST_SUITE(AddBias)
212FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMLowpQuantizeDownInt32ToUint8ScaleFixture, framework::DatasetMode::ALL, combine(datasets::SmallShapes(), quantize_down_int32_to_uint8_scale_relu_cases))
213{
214 // Validate output
215 validate(Accessor(_target), _reference);
216}
217
218FIXTURE_DATA_TEST_CASE(RunLarge, NEGEMMLowpQuantizeDownInt32ToUint8ScaleFixture, framework::DatasetMode::NIGHTLY, combine(datasets::LargeShapes(), quantize_down_int32_to_uint8_scale_relu_cases))
219{
220 // Validate output
221 validate(Accessor(_target), _reference);
222}
223TEST_SUITE_END() // AddBias
224
225TEST_SUITE_END() // QuantizeDownInt32ToUint8Scale
Gian Marcoe75a02b2017-11-08 12:24:09 +0000226TEST_SUITE_END() // OutputStage
227
228TEST_SUITE_END() // GEMMLowp
229TEST_SUITE_END() // NEON
Pablo Tello299025a2017-09-29 11:30:12 +0100230} // namespace validation
231} // namespace test
232} // namespace arm_compute