1*c217d954SCole Faust /*
2*c217d954SCole Faust * Copyright (c) 2017-2021 Arm Limited.
3*c217d954SCole Faust *
4*c217d954SCole Faust * SPDX-License-Identifier: MIT
5*c217d954SCole Faust *
6*c217d954SCole Faust * Permission is hereby granted, free of charge, to any person obtaining a copy
7*c217d954SCole Faust * of this software and associated documentation files (the "Software"), to
8*c217d954SCole Faust * deal in the Software without restriction, including without limitation the
9*c217d954SCole Faust * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*c217d954SCole Faust * sell copies of the Software, and to permit persons to whom the Software is
11*c217d954SCole Faust * furnished to do so, subject to the following conditions:
12*c217d954SCole Faust *
13*c217d954SCole Faust * The above copyright notice and this permission notice shall be included in all
14*c217d954SCole Faust * copies or substantial portions of the Software.
15*c217d954SCole Faust *
16*c217d954SCole Faust * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*c217d954SCole Faust * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*c217d954SCole Faust * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*c217d954SCole Faust * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*c217d954SCole Faust * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*c217d954SCole Faust * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*c217d954SCole Faust * SOFTWARE.
23*c217d954SCole Faust */
24*c217d954SCole Faust #include "arm_compute/core/Types.h"
25*c217d954SCole Faust #include "arm_compute/runtime/NEON/functions/NEFullyConnectedLayer.h"
26*c217d954SCole Faust #include "arm_compute/runtime/Tensor.h"
27*c217d954SCole Faust #include "arm_compute/runtime/TensorAllocator.h"
28*c217d954SCole Faust #include "src/core/helpers/MemoryHelpers.h"
29*c217d954SCole Faust #include "src/cpu/operators/CpuFullyConnected.h"
30*c217d954SCole Faust #include "tests/NEON/Accessor.h"
31*c217d954SCole Faust #include "tests/PaddingCalculator.h"
32*c217d954SCole Faust #include "tests/datasets/FullyConnectedLayerDataset.h"
33*c217d954SCole Faust #include "tests/framework/Asserts.h"
34*c217d954SCole Faust #include "tests/framework/Macros.h"
35*c217d954SCole Faust #include "tests/framework/datasets/Datasets.h"
36*c217d954SCole Faust #include "tests/validation/Validation.h"
37*c217d954SCole Faust #include "tests/validation/fixtures/FullyConnectedLayerFixture.h"
38*c217d954SCole Faust
39*c217d954SCole Faust namespace arm_compute
40*c217d954SCole Faust {
41*c217d954SCole Faust namespace test
42*c217d954SCole Faust {
43*c217d954SCole Faust namespace validation
44*c217d954SCole Faust {
45*c217d954SCole Faust namespace
46*c217d954SCole Faust {
47*c217d954SCole Faust /** Tolerance for float operations */
48*c217d954SCole Faust constexpr RelativeTolerance<float> rel_tolerance_f32(0.01f); /**< Relative tolerance value for comparing reference's output against implementation's output for DataType::F32 */
49*c217d954SCole Faust constexpr AbsoluteTolerance<float> abs_tolerance_f32(0.001f); /**< Absolute tolerance value for comparing reference's output against implementation's output for DataType::F32 */
50*c217d954SCole Faust #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
51*c217d954SCole Faust const AbsoluteTolerance<float> abs_tolerance_f16(0.3f); /**< Absolute tolerance value for comparing reference's output against implementation's output for DataType::F16 */
52*c217d954SCole Faust const RelativeTolerance<half_float::half> rel_tolerance_f16(half_float::half(0.2f)); /**< Relative tolerance value for comparing reference's output against implementation's output for DataType::F16 */
53*c217d954SCole Faust constexpr float tolerance_num_f16 = 0.07f; /**< Tolerance number for FP16 */
54*c217d954SCole Faust #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC*/
55*c217d954SCole Faust
56*c217d954SCole Faust /** Tolerance for quantized asymmetric operations */
57*c217d954SCole Faust constexpr AbsoluteTolerance<uint8_t> tolerance_qasymm8(1);
58*c217d954SCole Faust constexpr AbsoluteTolerance<int8_t> tolerance_qasymm8_signed(1);
59*c217d954SCole Faust
60*c217d954SCole Faust /** CNN data types */
61*c217d954SCole Faust const auto CNNDataTypes = framework::dataset::make("DataType",
62*c217d954SCole Faust {
63*c217d954SCole Faust #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
64*c217d954SCole Faust DataType::F16,
65*c217d954SCole Faust #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
66*c217d954SCole Faust DataType::F32,
67*c217d954SCole Faust });
68*c217d954SCole Faust
69*c217d954SCole Faust const auto FullyConnectedParameters = combine(framework::dataset::make("TransposeWeights", { false, true }), framework::dataset::make("ReshapeWeights", { false, true }));
70*c217d954SCole Faust
71*c217d954SCole Faust const auto QuantizationData = framework::dataset::make("QuantizationInfo",
72*c217d954SCole Faust {
73*c217d954SCole Faust QuantizationInfo(1.f / 256.f, 10),
74*c217d954SCole Faust QuantizationInfo(1.1f, 10),
75*c217d954SCole Faust });
76*c217d954SCole Faust const auto EmptyActivationFunctionDataset = framework::dataset::make("ActivationInfo",
77*c217d954SCole Faust {
78*c217d954SCole Faust ActivationLayerInfo(),
79*c217d954SCole Faust });
80*c217d954SCole Faust const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
81*c217d954SCole Faust {
82*c217d954SCole Faust ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
83*c217d954SCole Faust ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 0.5f),
84*c217d954SCole Faust ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 0.75f, 0.25f),
85*c217d954SCole Faust ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::TANH),
86*c217d954SCole Faust });
87*c217d954SCole Faust
88*c217d954SCole Faust const auto ActivationFunctionsQuantizedDataset = framework::dataset::make("ActivationInfo",
89*c217d954SCole Faust {
90*c217d954SCole Faust ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
91*c217d954SCole Faust ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 0.5f),
92*c217d954SCole Faust ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 0.75f, 0.25f),
93*c217d954SCole Faust });
94*c217d954SCole Faust } // namespace
95*c217d954SCole Faust
96*c217d954SCole Faust TEST_SUITE(NEON)
TEST_SUITE(FullyConnectedLayer)97*c217d954SCole Faust TEST_SUITE(FullyConnectedLayer)
98*c217d954SCole Faust
99*c217d954SCole Faust /** Test case for memory injection in @ref cpu::CpuFullyConnected.
100*c217d954SCole Faust *
101*c217d954SCole Faust * Configure the operator once and inject memory at run-time in multiple executions.
102*c217d954SCole Faust *
103*c217d954SCole Faust * Checks performed in order:
104*c217d954SCole Faust * - Both runs compute the same output
105*c217d954SCole Faust */
106*c217d954SCole Faust TEST_CASE(MemoryInjection, framework::DatasetMode::ALL)
107*c217d954SCole Faust {
108*c217d954SCole Faust auto fc = std::make_unique<cpu::CpuFullyConnected>();
109*c217d954SCole Faust const auto src_info = TensorInfo(TensorShape(8U), 1, DataType::F32, DataLayout::NHWC);
110*c217d954SCole Faust const auto weight_info = TensorInfo(TensorShape(8U, 4U), 1, DataType::F32, DataLayout::NHWC);
111*c217d954SCole Faust const auto bias_info = TensorInfo(TensorShape(4U), 1, DataType::F32, DataLayout::NHWC);
112*c217d954SCole Faust auto dst_info = TensorInfo(TensorShape(4U), 1, DataType::F32, DataLayout::NHWC);
113*c217d954SCole Faust const auto fc_info = FullyConnectedLayerInfo{};
114*c217d954SCole Faust fc->configure(&src_info, &weight_info, &bias_info, &dst_info, fc_info);
115*c217d954SCole Faust
116*c217d954SCole Faust // telhs are newly created every call of this lambda function
117*c217d954SCole Faust auto src = create_tensor<Tensor>(src_info);
118*c217d954SCole Faust auto weight = create_tensor<Tensor>(weight_info);
119*c217d954SCole Faust auto bias = create_tensor<Tensor>(bias_info);
120*c217d954SCole Faust src.allocator()->allocate();
121*c217d954SCole Faust weight.allocator()->allocate();
122*c217d954SCole Faust bias.allocator()->allocate();
123*c217d954SCole Faust
124*c217d954SCole Faust ITensorPack run_pack{ { TensorType::ACL_SRC_0, &src }, { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
125*c217d954SCole Faust ITensorPack prep_pack{ { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
126*c217d954SCole Faust
127*c217d954SCole Faust auto mg = MemoryGroup{};
128*c217d954SCole Faust auto ws = manage_workspace<Tensor>(fc->workspace(), mg, run_pack, prep_pack);
129*c217d954SCole Faust
130*c217d954SCole Faust auto run_conv = [&]() -> Tensor
131*c217d954SCole Faust {
132*c217d954SCole Faust auto dst = create_tensor<Tensor>(dst_info);
133*c217d954SCole Faust dst.allocator()->allocate();
134*c217d954SCole Faust run_pack.add_tensor(TensorType::ACL_DST, &dst);
135*c217d954SCole Faust
136*c217d954SCole Faust library->fill_tensor_value(Accessor(src), 1.f);
137*c217d954SCole Faust library->fill_tensor_value(Accessor(weight), 2.f);
138*c217d954SCole Faust library->fill_tensor_value(Accessor(bias), 3.f);
139*c217d954SCole Faust // This operator is configured once and captured by this lambda.
140*c217d954SCole Faust fc->prepare(prep_pack);
141*c217d954SCole Faust fc->run(run_pack);
142*c217d954SCole Faust return dst;
143*c217d954SCole Faust };
144*c217d954SCole Faust auto result_0 = run_conv();
145*c217d954SCole Faust auto result_1 = run_conv();
146*c217d954SCole Faust for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
147*c217d954SCole Faust {
148*c217d954SCole Faust ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
149*c217d954SCole Faust }
150*c217d954SCole Faust }
151*c217d954SCole Faust
152*c217d954SCole Faust /** Test case for memory injection in @ref NEFullyConnectedLayer.
153*c217d954SCole Faust *
154*c217d954SCole Faust * Make sure @ref NEFullyConnectedLayer still works through injecting the memory at configure time using the old API.
155*c217d954SCole Faust *
156*c217d954SCole Faust * Checks performed in order:
157*c217d954SCole Faust * - Both runs compute the same output
158*c217d954SCole Faust */
TEST_CASE(MultipleExecutionWithConfigure,framework::DatasetMode::ALL)159*c217d954SCole Faust TEST_CASE(MultipleExecutionWithConfigure, framework::DatasetMode::ALL)
160*c217d954SCole Faust {
161*c217d954SCole Faust auto fc = std::make_unique<NEFullyConnectedLayer>();
162*c217d954SCole Faust const auto src_info = TensorInfo(TensorShape(8U), 1, DataType::F32, DataLayout::NHWC);
163*c217d954SCole Faust const auto weight_info = TensorInfo(TensorShape(8U, 4U), 1, DataType::F32, DataLayout::NHWC);
164*c217d954SCole Faust const auto bias_info = TensorInfo(TensorShape(4U), 1, DataType::F32, DataLayout::NHWC);
165*c217d954SCole Faust auto dst_info = TensorInfo(TensorShape(4U), 1, DataType::F32, DataLayout::NHWC);
166*c217d954SCole Faust const auto fc_info = FullyConnectedLayerInfo{};
167*c217d954SCole Faust auto run_conv = [&]()
168*c217d954SCole Faust {
169*c217d954SCole Faust auto src = create_tensor<Tensor>(src_info);
170*c217d954SCole Faust auto weight = create_tensor<Tensor>(weight_info);
171*c217d954SCole Faust auto bias = create_tensor<Tensor>(bias_info);
172*c217d954SCole Faust auto dst = create_tensor<Tensor>(dst_info);
173*c217d954SCole Faust fc->configure(&src, &weight, &bias, &dst, fc_info);
174*c217d954SCole Faust src.allocator()->allocate();
175*c217d954SCole Faust weight.allocator()->allocate();
176*c217d954SCole Faust bias.allocator()->allocate();
177*c217d954SCole Faust dst.allocator()->allocate();
178*c217d954SCole Faust library->fill_tensor_value(Accessor(src), 1.f);
179*c217d954SCole Faust library->fill_tensor_value(Accessor(weight), 2.f);
180*c217d954SCole Faust library->fill_tensor_value(Accessor(bias), 3.f);
181*c217d954SCole Faust fc->run();
182*c217d954SCole Faust return dst;
183*c217d954SCole Faust };
184*c217d954SCole Faust auto result_0 = run_conv();
185*c217d954SCole Faust auto result_1 = run_conv();
186*c217d954SCole Faust for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
187*c217d954SCole Faust {
188*c217d954SCole Faust ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
189*c217d954SCole Faust }
190*c217d954SCole Faust }
191*c217d954SCole Faust
192*c217d954SCole Faust /** Unit test for @ref cpu::CpuFullyConnected with quantized multipler > 1
193*c217d954SCole Faust *
194*c217d954SCole Faust * Tests output correctness.
195*c217d954SCole Faust */
TEST_CASE(Quant8_Signed_Mult_gt_1,framework::DatasetMode::ALL)196*c217d954SCole Faust TEST_CASE(Quant8_Signed_Mult_gt_1, framework::DatasetMode::ALL)
197*c217d954SCole Faust {
198*c217d954SCole Faust auto fc = std::make_unique<cpu::CpuFullyConnected>();
199*c217d954SCole Faust const auto src_info = TensorInfo(TensorShape(1U, 3U), 1, DataType::QASYMM8_SIGNED, QuantizationInfo(0.5f, -1));
200*c217d954SCole Faust const auto weight_info = TensorInfo(TensorShape(1U), 1, DataType::QASYMM8_SIGNED, QuantizationInfo(0.5, -8));
201*c217d954SCole Faust const auto bias_info = TensorInfo(TensorShape(1U), 1, DataType::S32);
202*c217d954SCole Faust auto dst_info = TensorInfo(TensorShape(1U, 3U), 1, DataType::QASYMM8_SIGNED, QuantizationInfo(0.1f, 0));
203*c217d954SCole Faust const auto fc_info = FullyConnectedLayerInfo{};
204*c217d954SCole Faust fc->configure(&src_info, &weight_info, &bias_info, &dst_info, fc_info);
205*c217d954SCole Faust
206*c217d954SCole Faust // telhs are newly created every call of this lambda function
207*c217d954SCole Faust auto src = create_tensor<Tensor>(src_info);
208*c217d954SCole Faust auto weight = create_tensor<Tensor>(weight_info);
209*c217d954SCole Faust auto bias = create_tensor<Tensor>(bias_info);
210*c217d954SCole Faust auto dst = create_tensor<Tensor>(dst_info);
211*c217d954SCole Faust src.allocator()->allocate();
212*c217d954SCole Faust weight.allocator()->allocate();
213*c217d954SCole Faust bias.allocator()->allocate();
214*c217d954SCole Faust dst.allocator()->allocate();
215*c217d954SCole Faust
216*c217d954SCole Faust ITensorPack run_pack{ { TensorType::ACL_SRC_0, &src }, { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias }, { TensorType::ACL_DST, &dst } };
217*c217d954SCole Faust ITensorPack prep_pack{ { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
218*c217d954SCole Faust
219*c217d954SCole Faust auto mg = MemoryGroup{};
220*c217d954SCole Faust auto ws = manage_workspace<Tensor>(fc->workspace(), mg, run_pack, prep_pack);
221*c217d954SCole Faust
222*c217d954SCole Faust // Initialize input values
223*c217d954SCole Faust const std::vector<int8_t> src_values = { 3, 63, 31 };
224*c217d954SCole Faust const std::vector<int8_t> weight_values = { -4 };
225*c217d954SCole Faust const std::vector<int32_t> bias_values = { 16 };
226*c217d954SCole Faust const std::vector<int32_t> expected = { 80, 127, 127 };
227*c217d954SCole Faust library->fill_static_values(Accessor(src), src_values);
228*c217d954SCole Faust library->fill_static_values(Accessor(weight), weight_values);
229*c217d954SCole Faust library->fill_static_values(Accessor(bias), bias_values);
230*c217d954SCole Faust
231*c217d954SCole Faust // Run FC layer
232*c217d954SCole Faust fc->prepare(prep_pack);
233*c217d954SCole Faust fc->run(run_pack);
234*c217d954SCole Faust
235*c217d954SCole Faust auto dst_ptr = reinterpret_cast<int8_t *>(dst.buffer());
236*c217d954SCole Faust for(size_t i = 0; i < dst.info()->tensor_shape().total_size(); ++i)
237*c217d954SCole Faust {
238*c217d954SCole Faust ARM_COMPUTE_EXPECT(dst_ptr[i] == expected[i], framework::LogLevel::ERRORS);
239*c217d954SCole Faust }
240*c217d954SCole Faust }
241*c217d954SCole Faust
242*c217d954SCole Faust // *INDENT-OFF*
243*c217d954SCole Faust // clang-format off
244*c217d954SCole Faust DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(
245*c217d954SCole Faust framework::dataset::make("InputInfo", { TensorInfo(TensorShape(9U, 5U, 7U, 3U), 1, DataType::F32), // Mismatching data types
246*c217d954SCole Faust TensorInfo(TensorShape(8U, 4U, 6U, 4U), 1, DataType::F32),
247*c217d954SCole Faust TensorInfo(TensorShape(8U, 4U, 6U, 4U), 1, DataType::F32),
248*c217d954SCole Faust TensorInfo(TensorShape(9U, 5U, 7U, 3U), 1, DataType::F32), // Invalid weights dimensions
249*c217d954SCole Faust TensorInfo(TensorShape(9U, 5U, 7U, 3U), 1, DataType::F32), // Wrongly reshaped weights
250*c217d954SCole Faust TensorInfo(TensorShape(8U, 4U, 6U, 4U), 1, DataType::F32),
251*c217d954SCole Faust }),
252*c217d954SCole Faust framework::dataset::make("WeightsInfo",{ TensorInfo(TensorShape(315U, 271U), 1, DataType::F16),
253*c217d954SCole Faust TensorInfo(TensorShape(192U, 192U), 1, DataType::F32),
254*c217d954SCole Faust TensorInfo(TensorShape(192U, 192U), 1, DataType::F32),
255*c217d954SCole Faust TensorInfo(TensorShape(217U, 315U), 1, DataType::F32),
256*c217d954SCole Faust TensorInfo(TensorShape(217U, 315U), 1, DataType::F32),
257*c217d954SCole Faust TensorInfo(TensorShape(192U, 192U), 1, DataType::F32),
258*c217d954SCole Faust })),
259*c217d954SCole Faust framework::dataset::make("BiasInfo",{ TensorInfo(TensorShape(271U), 1, DataType::F32),
260*c217d954SCole Faust TensorInfo(TensorShape(192U), 1, DataType::F32),
261*c217d954SCole Faust TensorInfo(TensorShape(192U), 1, DataType::F32),
262*c217d954SCole Faust TensorInfo(TensorShape(271U), 1, DataType::F32),
263*c217d954SCole Faust TensorInfo(TensorShape(271U), 1, DataType::F32),
264*c217d954SCole Faust TensorInfo(TensorShape(192U), 1, DataType::F32),
265*c217d954SCole Faust })),
266*c217d954SCole Faust framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(271U, 3U), 1, DataType::F32),
267*c217d954SCole Faust TensorInfo(TensorShape(192U, 4U), 1, DataType::F32),
268*c217d954SCole Faust TensorInfo(TensorShape(192U, 4U), 1, DataType::F32),
269*c217d954SCole Faust TensorInfo(TensorShape(271U, 3U), 1, DataType::F32),
270*c217d954SCole Faust TensorInfo(TensorShape(271U, 3U), 1, DataType::F32),
271*c217d954SCole Faust TensorInfo(TensorShape(192U, 4U), 1, DataType::F32),
272*c217d954SCole Faust })),
273*c217d954SCole Faust framework::dataset::make("TransposeWeights",{ true, true, false, true, true, true })),
274*c217d954SCole Faust framework::dataset::make("ReshapedWeights",{ false, false, false, false, false , false})),
275*c217d954SCole Faust framework::dataset::make("Expected", { false, true, true, false, false, true })),
276*c217d954SCole Faust input_info, weights_info, bias_info, output_info, transpose_weights, reshaped_weights, expected)
277*c217d954SCole Faust {
278*c217d954SCole Faust // Create Fully Connected layer info
279*c217d954SCole Faust FullyConnectedLayerInfo fc_info;
280*c217d954SCole Faust fc_info.transpose_weights = transpose_weights;
281*c217d954SCole Faust fc_info.are_weights_reshaped = reshaped_weights;
282*c217d954SCole Faust
283*c217d954SCole Faust Status status = NEFullyConnectedLayer::validate(&input_info.clone()->set_is_resizable(false), &weights_info.clone()->set_is_resizable(false), &bias_info.clone()->set_is_resizable(false), &output_info.clone()->set_is_resizable(false), fc_info);
284*c217d954SCole Faust ARM_COMPUTE_EXPECT(bool(status) == expected, framework::LogLevel::ERRORS);
285*c217d954SCole Faust }
286*c217d954SCole Faust // clang-format on
287*c217d954SCole Faust // *INDENT-ON*
288*c217d954SCole Faust
289*c217d954SCole Faust template <typename T>
290*c217d954SCole Faust using NEFullyConnectedLayerFixture = FullyConnectedLayerValidationFixture<Tensor, Accessor, NEFullyConnectedLayer, T>;
291*c217d954SCole Faust template <typename T>
292*c217d954SCole Faust using NEFullyConnectedLayerMixedDataLayoutFixture = FullyConnectedLayerValidationFixture<Tensor, Accessor, NEFullyConnectedLayer, T, true>;
293*c217d954SCole Faust template <typename T>
294*c217d954SCole Faust using NEFullyConnectedLayerDynamicWeightsFixture = FullyConnectedWithDynamicWeightsFixture<Tensor, Accessor, NEFullyConnectedLayer, T>;
295*c217d954SCole Faust template <typename T>
296*c217d954SCole Faust using NEFullyConnectedLayerDynamicBiasFixture = FullyConnectedWithDynamicBiasFixture<Tensor, Accessor, NEFullyConnectedLayer, T>;
297*c217d954SCole Faust
298*c217d954SCole Faust TEST_SUITE(Float)
299*c217d954SCole Faust #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
TEST_SUITE(FP16)300*c217d954SCole Faust TEST_SUITE(FP16)
301*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEFullyConnectedLayerFixture<half>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallFullyConnectedLayerDataset(),
302*c217d954SCole Faust FullyConnectedParameters),
303*c217d954SCole Faust framework::dataset::make("DataType", DataType::F16)),
304*c217d954SCole Faust EmptyActivationFunctionDataset))
305*c217d954SCole Faust {
306*c217d954SCole Faust // Validate output
307*c217d954SCole Faust validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num_f16, abs_tolerance_f16);
308*c217d954SCole Faust }
309*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunWithActivation, NEFullyConnectedLayerFixture<half>, framework::DatasetMode::PRECOMMIT, combine(combine(
310*c217d954SCole Faust combine(datasets::FullyConnectedLayerWithActivationDataset(),
311*c217d954SCole Faust FullyConnectedParameters),
312*c217d954SCole Faust framework::dataset::make("DataType", DataType::F16)),
313*c217d954SCole Faust ActivationFunctionsDataset))
314*c217d954SCole Faust {
315*c217d954SCole Faust // Validate output
316*c217d954SCole Faust validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num_f16, abs_tolerance_f16);
317*c217d954SCole Faust }
318*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEFullyConnectedLayerFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeFullyConnectedLayerDataset(),
319*c217d954SCole Faust FullyConnectedParameters),
320*c217d954SCole Faust framework::dataset::make("DataType", DataType::F16)),
321*c217d954SCole Faust EmptyActivationFunctionDataset))
322*c217d954SCole Faust {
323*c217d954SCole Faust // Validate output
324*c217d954SCole Faust validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num_f16, abs_tolerance_f16);
325*c217d954SCole Faust }
326*c217d954SCole Faust TEST_SUITE_END()
327*c217d954SCole Faust #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
328*c217d954SCole Faust
TEST_SUITE(FP32)329*c217d954SCole Faust TEST_SUITE(FP32)
330*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEFullyConnectedLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallFullyConnectedLayerDataset(), FullyConnectedParameters),
331*c217d954SCole Faust framework::dataset::make("DataType", DataType::F32)),
332*c217d954SCole Faust EmptyActivationFunctionDataset))
333*c217d954SCole Faust {
334*c217d954SCole Faust // Validate output
335*c217d954SCole Faust validate(Accessor(_target), _reference, rel_tolerance_f32, 0, abs_tolerance_f32);
336*c217d954SCole Faust }
337*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, NEFullyConnectedLayerMixedDataLayoutFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(combine(combine(
338*c217d954SCole Faust framework::dataset::make("Input", TensorShape(9U, 5U, 7U)),
339*c217d954SCole Faust framework::dataset::make("Weights", TensorShape(315U, 271U))),
340*c217d954SCole Faust framework::dataset::make("Biases", TensorShape(271U))),
341*c217d954SCole Faust framework::dataset::make("Output", TensorShape(271U))),
342*c217d954SCole Faust FullyConnectedParameters),
343*c217d954SCole Faust framework::dataset::make("DataType", DataType::F32)),
344*c217d954SCole Faust framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))))
345*c217d954SCole Faust {
346*c217d954SCole Faust // Validate output
347*c217d954SCole Faust validate(Accessor(_target), _reference, rel_tolerance_f32, 0, abs_tolerance_f32);
348*c217d954SCole Faust }
349*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunWithActivation, NEFullyConnectedLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(
350*c217d954SCole Faust combine(datasets::FullyConnectedLayerWithActivationDataset(),
351*c217d954SCole Faust FullyConnectedParameters),
352*c217d954SCole Faust framework::dataset::make("DataType", DataType::F32)),
353*c217d954SCole Faust ActivationFunctionsDataset))
354*c217d954SCole Faust {
355*c217d954SCole Faust // Validate output
356*c217d954SCole Faust validate(Accessor(_target), _reference, rel_tolerance_f32, 0, abs_tolerance_f32);
357*c217d954SCole Faust }
358*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEFullyConnectedLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeFullyConnectedLayerDataset(), FullyConnectedParameters),
359*c217d954SCole Faust framework::dataset::make("DataType", DataType::F32)),
360*c217d954SCole Faust EmptyActivationFunctionDataset))
361*c217d954SCole Faust {
362*c217d954SCole Faust // Validate output
363*c217d954SCole Faust validate(Accessor(_target), _reference, rel_tolerance_f32, 0, abs_tolerance_f32);
364*c217d954SCole Faust }
365*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunDynamicWeights, NEFullyConnectedLayerDynamicWeightsFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallFullyConnectedLayerDataset(),
366*c217d954SCole Faust framework::dataset::make("DataType", DataType::F32)),
367*c217d954SCole Faust framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))))
368*c217d954SCole Faust {
369*c217d954SCole Faust }
370*c217d954SCole Faust TEST_SUITE_END()
371*c217d954SCole Faust TEST_SUITE_END()
372*c217d954SCole Faust
373*c217d954SCole Faust template <typename T>
374*c217d954SCole Faust using NEFullyConnectedLayerQuantizedFixture = FullyConnectedLayerValidationQuantizedFixture<Tensor, Accessor, NEFullyConnectedLayer, T>;
375*c217d954SCole Faust template <typename T>
376*c217d954SCole Faust using NEFullyConnectedLayerQuantizedMixedDataLayoutFixture = FullyConnectedLayerValidationQuantizedFixture<Tensor, Accessor, NEFullyConnectedLayer, T, true>;
377*c217d954SCole Faust
378*c217d954SCole Faust TEST_SUITE(Quantized)
TEST_SUITE(QASYMM8)379*c217d954SCole Faust TEST_SUITE(QASYMM8)
380*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEFullyConnectedLayerQuantizedFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(
381*c217d954SCole Faust combine(datasets::SmallFullyConnectedLayerDataset(),
382*c217d954SCole Faust FullyConnectedParameters),
383*c217d954SCole Faust framework::dataset::make("DataType", DataType::QASYMM8)),
384*c217d954SCole Faust QuantizationData),
385*c217d954SCole Faust EmptyActivationFunctionDataset))
386*c217d954SCole Faust {
387*c217d954SCole Faust // Validate output
388*c217d954SCole Faust validate(Accessor(_target), _reference, tolerance_qasymm8);
389*c217d954SCole Faust }
390*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, NEFullyConnectedLayerQuantizedMixedDataLayoutFixture<uint8_t>, framework::DatasetMode::PRECOMMIT,
391*c217d954SCole Faust combine(combine(combine(combine(combine(combine(combine(
392*c217d954SCole Faust framework::dataset::make("Input", TensorShape(9U, 5U, 7U)),
393*c217d954SCole Faust framework::dataset::make("Weights", TensorShape(315U, 271U))),
394*c217d954SCole Faust framework::dataset::make("Biases", TensorShape(271U))),
395*c217d954SCole Faust framework::dataset::make("Output", TensorShape(271U))),
396*c217d954SCole Faust FullyConnectedParameters),
397*c217d954SCole Faust framework::dataset::make("DataType", DataType::QASYMM8)),
398*c217d954SCole Faust QuantizationData),
399*c217d954SCole Faust framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))))
400*c217d954SCole Faust {
401*c217d954SCole Faust // Validate output
402*c217d954SCole Faust validate(Accessor(_target), _reference, tolerance_qasymm8);
403*c217d954SCole Faust }
404*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunWithActivation, NEFullyConnectedLayerQuantizedFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(
405*c217d954SCole Faust combine(datasets::FullyConnectedLayerWithActivationDataset(),
406*c217d954SCole Faust FullyConnectedParameters),
407*c217d954SCole Faust framework::dataset::make("DataType", DataType::QASYMM8)),
408*c217d954SCole Faust QuantizationData),
409*c217d954SCole Faust ActivationFunctionsQuantizedDataset))
410*c217d954SCole Faust {
411*c217d954SCole Faust // Validate output
412*c217d954SCole Faust validate(Accessor(_target), _reference, tolerance_qasymm8);
413*c217d954SCole Faust }
414*c217d954SCole Faust
415*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEFullyConnectedLayerQuantizedFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(
416*c217d954SCole Faust combine(datasets::LargeFullyConnectedLayerDataset(),
417*c217d954SCole Faust FullyConnectedParameters),
418*c217d954SCole Faust framework::dataset::make("DataType", DataType::QASYMM8)),
419*c217d954SCole Faust QuantizationData),
420*c217d954SCole Faust EmptyActivationFunctionDataset))
421*c217d954SCole Faust {
422*c217d954SCole Faust // Validate output
423*c217d954SCole Faust validate(Accessor(_target), _reference, tolerance_qasymm8);
424*c217d954SCole Faust }
425*c217d954SCole Faust
426*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunDynamicBias, NEFullyConnectedLayerDynamicBiasFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(datasets::SmallFullyConnectedLayerDataset(),
427*c217d954SCole Faust framework::dataset::make("DataType", DataType::QASYMM8)),
428*c217d954SCole Faust framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))))
429*c217d954SCole Faust {
430*c217d954SCole Faust }
431*c217d954SCole Faust TEST_SUITE_END()
TEST_SUITE(QASYMM8_SIGNED)432*c217d954SCole Faust TEST_SUITE(QASYMM8_SIGNED)
433*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEFullyConnectedLayerQuantizedFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(
434*c217d954SCole Faust combine(datasets::SmallFullyConnectedLayerDataset(),
435*c217d954SCole Faust FullyConnectedParameters),
436*c217d954SCole Faust framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)),
437*c217d954SCole Faust QuantizationData),
438*c217d954SCole Faust EmptyActivationFunctionDataset))
439*c217d954SCole Faust {
440*c217d954SCole Faust // Validate output
441*c217d954SCole Faust validate(Accessor(_target), _reference, tolerance_qasymm8_signed);
442*c217d954SCole Faust }
443*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, NEFullyConnectedLayerQuantizedMixedDataLayoutFixture<int8_t>, framework::DatasetMode::PRECOMMIT,
444*c217d954SCole Faust combine(combine(combine(combine(combine(combine(combine(
445*c217d954SCole Faust framework::dataset::make("Input", TensorShape(9U, 5U, 7U)),
446*c217d954SCole Faust framework::dataset::make("Weights", TensorShape(315U, 271U))),
447*c217d954SCole Faust framework::dataset::make("Biases", TensorShape(271U))),
448*c217d954SCole Faust framework::dataset::make("Output", TensorShape(271U))),
449*c217d954SCole Faust FullyConnectedParameters),
450*c217d954SCole Faust framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)),
451*c217d954SCole Faust QuantizationData),
452*c217d954SCole Faust framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))))
453*c217d954SCole Faust {
454*c217d954SCole Faust // Validate output
455*c217d954SCole Faust validate(Accessor(_target), _reference, tolerance_qasymm8);
456*c217d954SCole Faust }
457*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunWithActivation, NEFullyConnectedLayerQuantizedFixture<int8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(
458*c217d954SCole Faust combine(datasets::FullyConnectedLayerWithActivationDataset(),
459*c217d954SCole Faust FullyConnectedParameters),
460*c217d954SCole Faust framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)),
461*c217d954SCole Faust QuantizationData),
462*c217d954SCole Faust ActivationFunctionsQuantizedDataset))
463*c217d954SCole Faust {
464*c217d954SCole Faust // Validate output
465*c217d954SCole Faust validate(Accessor(_target), _reference, tolerance_qasymm8_signed);
466*c217d954SCole Faust }
467*c217d954SCole Faust TEST_SUITE_END() // QASYMM8_SIGNED
468*c217d954SCole Faust TEST_SUITE_END() // Quantized
469*c217d954SCole Faust TEST_SUITE_END() // FullyConnectedLayer
470*c217d954SCole Faust TEST_SUITE_END() // NEON
471*c217d954SCole Faust } // namespace validation
472*c217d954SCole Faust } // namespace test
473*c217d954SCole Faust } // namespace arm_compute
474