xref: /aosp_15_r20/external/ComputeLibrary/tests/validation/NEON/ConvolutionLayer.cpp (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1*c217d954SCole Faust /*
2*c217d954SCole Faust  * Copyright (c) 2017-2023 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/NEConvolutionLayer.h"
26*c217d954SCole Faust #include "arm_compute/runtime/NEON/functions/NEGEMMConv2d.h"
27*c217d954SCole Faust #include "arm_compute/runtime/NEON/functions/NEGEMMConvolutionLayer.h"
28*c217d954SCole Faust #include "arm_compute/runtime/NEON/functions/NEWinogradConvolutionLayer.h"
29*c217d954SCole Faust #include "arm_compute/runtime/Tensor.h"
30*c217d954SCole Faust #include "arm_compute/runtime/TensorAllocator.h"
31*c217d954SCole Faust #include "src/core/helpers/MemoryHelpers.h"
32*c217d954SCole Faust #include "src/cpu/operators/CpuGemmConv2d.h"
33*c217d954SCole Faust #include "src/cpu/operators/CpuGemmDirectConv2d.h"
34*c217d954SCole Faust #include "src/cpu/operators/CpuWinogradConv2d.h"
35*c217d954SCole Faust #include "tests/NEON/Accessor.h"
36*c217d954SCole Faust #include "tests/PaddingCalculator.h"
37*c217d954SCole Faust #include "tests/datasets/LargeConvolutionLayerDataset.h"
38*c217d954SCole Faust #include "tests/datasets/SmallConvolutionLayerDataset.h"
39*c217d954SCole Faust #include "tests/datasets/TinyConvolutionLayerDataset.h"
40*c217d954SCole Faust #include "tests/framework/Asserts.h"
41*c217d954SCole Faust #include "tests/framework/Macros.h"
42*c217d954SCole Faust #include "tests/framework/datasets/Datasets.h"
43*c217d954SCole Faust #include "tests/validation/Validation.h"
44*c217d954SCole Faust #include "tests/validation/fixtures/ConvolutionLayerFixture.h"
45*c217d954SCole Faust #include "tests/validation/fixtures/WinogradConvolutionLayerFixture.h"
46*c217d954SCole Faust 
47*c217d954SCole Faust namespace arm_compute
48*c217d954SCole Faust {
49*c217d954SCole Faust namespace test
50*c217d954SCole Faust {
51*c217d954SCole Faust namespace validation
52*c217d954SCole Faust {
53*c217d954SCole Faust namespace detail
54*c217d954SCole Faust {
55*c217d954SCole Faust template <>
configure_conv_function(NEGEMMConv2d & func,Tensor * src,const Tensor * weights,const Tensor * bias,Tensor * dst,const PadStrideInfo & info,const WeightsInfo & weights_info,const Size2D & dilation,const ActivationLayerInfo & act_info,unsigned int num_groups)56*c217d954SCole Faust void configure_conv_function<NEGEMMConv2d, Tensor>(NEGEMMConv2d &func,
57*c217d954SCole Faust                                                    Tensor *src, const Tensor *weights, const Tensor *bias, Tensor *dst,
58*c217d954SCole Faust                                                    const PadStrideInfo &info, const WeightsInfo &weights_info,
59*c217d954SCole Faust                                                    const Size2D &dilation, const ActivationLayerInfo &act_info, unsigned int num_groups)
60*c217d954SCole Faust {
61*c217d954SCole Faust     ARM_COMPUTE_UNUSED(weights_info);
62*c217d954SCole Faust 
63*c217d954SCole Faust     Conv2dInfo conv_info(info, dilation, act_info, false, num_groups);
64*c217d954SCole Faust     func.configure(src, weights, bias, dst, conv_info);
65*c217d954SCole Faust }
66*c217d954SCole Faust } // namespace detail
67*c217d954SCole Faust namespace
68*c217d954SCole Faust {
69*c217d954SCole Faust const RelativeTolerance<float> rel_tolerance_f32(0.01f);              /**< Relative tolerance for FP32 types */
70*c217d954SCole Faust const RelativeTolerance<float> rel_tolerance_winograd_3x3_f32(0.05f); /**< Relative tolerance for FP32 types */
71*c217d954SCole Faust const AbsoluteTolerance<float> abs_tolerance_f32(0.002f);             /**< Absolute tolerance for FP32 types */
72*c217d954SCole Faust const AbsoluteTolerance<float> abs_tolerance_1xN_f32(0.0041f);        /**< Absolute tolerance for FP32 types */
73*c217d954SCole Faust 
74*c217d954SCole Faust #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
75*c217d954SCole Faust const AbsoluteTolerance<half> tolerance_convolution_layer_f16(half(0.4f));
76*c217d954SCole Faust constexpr float               tolerance_num_f16 = 0.15f;
77*c217d954SCole Faust #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
78*c217d954SCole Faust 
79*c217d954SCole Faust #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
80*c217d954SCole Faust const RelativeTolerance<half_float::half> rel_tolerance_f16(half_float::half(0.2f)); /**< Relative tolerance value for FP16 types */
81*c217d954SCole Faust const AbsoluteTolerance<float>            abs_tolerance_f16(0.2f);                   /**< Absolute tolerance for FP16 types */
82*c217d954SCole Faust constexpr float                           tolerance_num = 0.07f;                     /**< Tolerance number for the FP16 implementation */
83*c217d954SCole Faust #endif                                                                               /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
84*c217d954SCole Faust constexpr AbsoluteTolerance<float> tolerance_qasymm8(0.0);                           /**< Tolerance value for comparing reference's output against implementation's output for quantized data types */
85*c217d954SCole Faust 
86*c217d954SCole Faust /** CNN data types */
87*c217d954SCole Faust const auto CNNDataTypes = framework::dataset::make("DataType",
88*c217d954SCole Faust {
89*c217d954SCole Faust #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
90*c217d954SCole Faust     DataType::F16,
91*c217d954SCole Faust #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
92*c217d954SCole Faust     DataType::F32,
93*c217d954SCole Faust     DataType::QASYMM8,
94*c217d954SCole Faust });
95*c217d954SCole Faust const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
96*c217d954SCole Faust {
97*c217d954SCole Faust     ActivationLayerInfo(),
98*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
99*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 0.5f)
100*c217d954SCole Faust });
101*c217d954SCole Faust 
102*c217d954SCole Faust const auto QuantizationData = framework::dataset::make("QuantizationInfo",
103*c217d954SCole Faust {
104*c217d954SCole Faust     QuantizationInfo(0.5f, 10),
105*c217d954SCole Faust     QuantizationInfo(0.3f, 3),
106*c217d954SCole Faust     QuantizationInfo(1.f, 10),
107*c217d954SCole Faust     QuantizationInfo(1.1f, 10),
108*c217d954SCole Faust });
109*c217d954SCole Faust } // namespace
110*c217d954SCole Faust 
111*c217d954SCole Faust TEST_SUITE(NEON)
TEST_SUITE(ConvolutionLayer)112*c217d954SCole Faust TEST_SUITE(ConvolutionLayer)
113*c217d954SCole Faust 
114*c217d954SCole Faust // *INDENT-OFF*
115*c217d954SCole Faust // clang-format off
116*c217d954SCole Faust DATA_TEST_CASE(ValidateConvolutionMethod, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(
117*c217d954SCole Faust                                           framework::dataset::make("InputInfo", { TensorInfo(TensorShape(18U, 18U, 32U), 1, DataType::F32),
118*c217d954SCole Faust                                                                                   TensorInfo(TensorShape(23U, 27U, 32U, 4U), 1, DataType::F32),
119*c217d954SCole Faust                                                                                   TensorInfo(TensorShape(3U, 3U, 2U, 1U), 1, DataType::F32),
120*c217d954SCole Faust                                                                                   TensorInfo(TensorShape(33U, 27U, 7U, 4U), 1, DataType::F32)
121*c217d954SCole Faust                                           }),
122*c217d954SCole Faust                                           framework::dataset::make("WeightsInfo", { TensorInfo(TensorShape(3U, 3U, 32U, 21U), 1, DataType::F32),
123*c217d954SCole Faust                                                                                     TensorInfo(TensorShape(5U, 5U, 32U, 21U), 1, DataType::F32),
124*c217d954SCole Faust                                                                                     TensorInfo(TensorShape(3U, 3U, 5U, 21U), 1, DataType::F32),
125*c217d954SCole Faust                                                                                     TensorInfo(TensorShape(5U, 5U, 7U, 16U), 1, DataType::F16)
126*c217d954SCole Faust                                           })),
127*c217d954SCole Faust                                           framework::dataset::make("OutputInfo", { TensorInfo(TensorShape(16U, 16U, 21U), 1, DataType::F32),
128*c217d954SCole Faust                                                                                    TensorInfo(TensorShape(19U, 23U, 21U, 4U), 1, DataType::F32),
129*c217d954SCole Faust                                                                                    TensorInfo(TensorShape(11U, 25U, 21U), 1, DataType::F32),
130*c217d954SCole Faust                                                                                    TensorInfo(TensorShape(11U, 12U, 16U, 4U), 1, DataType::F32)
131*c217d954SCole Faust                                           })),
132*c217d954SCole Faust                                           framework::dataset::make("ConvInfo", { PadStrideInfo(1, 1, 0, 0),
133*c217d954SCole Faust                                                                                  PadStrideInfo(1, 1, 0, 0),
134*c217d954SCole Faust                                                                                  PadStrideInfo(2, 1, 0, 0),
135*c217d954SCole Faust                                                                                  PadStrideInfo(3, 2, 1, 0)
136*c217d954SCole Faust                                           })),
137*c217d954SCole Faust                                           framework::dataset::make("FastMath", { true,
138*c217d954SCole Faust                                                                                  true,
139*c217d954SCole Faust                                                                                  false,
140*c217d954SCole Faust                                                                                  false
141*c217d954SCole Faust                                           })),
142*c217d954SCole Faust                                                                            framework::dataset::make("Expected", { ConvolutionMethod::WINOGRAD, ConvolutionMethod::WINOGRAD, ConvolutionMethod::GEMM, ConvolutionMethod::GEMM })),
143*c217d954SCole Faust                input_info, weights_info, output_info, conv_info, fast_math, expected)
144*c217d954SCole Faust {
145*c217d954SCole Faust     ConvolutionMethod is_valid = NEConvolutionLayer::get_convolution_method(&input_info.clone()->set_is_resizable(true),
146*c217d954SCole Faust                                                                             &weights_info.clone()->set_is_resizable(true),
147*c217d954SCole Faust                                                                             &output_info.clone()->set_is_resizable(true), conv_info, WeightsInfo(), Size2D(1U, 1U), ActivationLayerInfo(), fast_math);
148*c217d954SCole Faust     ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS);
149*c217d954SCole Faust }
150*c217d954SCole Faust // clang-format on
151*c217d954SCole Faust // *INDENT-ON*
152*c217d954SCole Faust TEST_SUITE_END() // ConvolutionLayer
153*c217d954SCole Faust 
154*c217d954SCole Faust TEST_SUITE(WinogradLayer)
155*c217d954SCole Faust template <typename T>
156*c217d954SCole Faust using NEWinogradConvolutionLayerFixture = WinogradConvolutionLayerFastMathValidationFixture<Tensor, Accessor, NEWinogradConvolutionLayer, T>;
157*c217d954SCole Faust template <typename T>
158*c217d954SCole Faust using NEWinogradConvolutionLayerMixedDataLayoutFixture = WinogradConvolutionLayerFastMathValidationFixture<Tensor, Accessor, NEWinogradConvolutionLayer, T, T, true, true>;
159*c217d954SCole Faust 
160*c217d954SCole Faust template <typename T>
161*c217d954SCole Faust using NEWinogradConvolutionLayerNoBiasFixture = WinogradConvolutionLayerFastMathValidationFixture<Tensor, Accessor, NEWinogradConvolutionLayer, T, T, false>;
162*c217d954SCole Faust 
163*c217d954SCole Faust /** Test case for memory injection in @ref cpu::CpuWinogradConv2d.
164*c217d954SCole Faust  *
165*c217d954SCole Faust  * Configure the operator once and inject memory at run-time in multiple executions.
166*c217d954SCole Faust  *
167*c217d954SCole Faust  * Checks performed in order:
168*c217d954SCole Faust  * - Both runs compute the same output
169*c217d954SCole Faust  */
TEST_CASE(MemoryInjection,framework::DatasetMode::ALL)170*c217d954SCole Faust TEST_CASE(MemoryInjection, framework::DatasetMode::ALL)
171*c217d954SCole Faust {
172*c217d954SCole Faust     auto                winograd = std::make_unique<cpu::CpuWinogradConv2d>();
173*c217d954SCole Faust     const auto          src_info = TensorInfo(TensorShape(8U, 8U, 32U), 1, DataType::F32);
174*c217d954SCole Faust     const auto          w_info   = TensorInfo(TensorShape(1U), 1, DataType::F32);
175*c217d954SCole Faust     const auto          b_info   = TensorInfo(TensorShape(1U, 3U, 32U, 1U), 1, DataType::F32);
176*c217d954SCole Faust     auto                dst_info = TensorInfo(TensorShape(8U, 6U, 1U), 1, DataType::F32);
177*c217d954SCole Faust     const PadStrideInfo pad_info{};
178*c217d954SCole Faust 
179*c217d954SCole Faust     winograd->configure(&src_info, &b_info, &w_info, &dst_info, pad_info);
180*c217d954SCole Faust 
181*c217d954SCole Faust     // telhs are newly created every call of this lambda function
182*c217d954SCole Faust     auto a = create_tensor<Tensor>(src_info);
183*c217d954SCole Faust     auto b = create_tensor<Tensor>(b_info);
184*c217d954SCole Faust     auto c = create_tensor<Tensor>(w_info);
185*c217d954SCole Faust     a.allocator()->allocate();
186*c217d954SCole Faust     b.allocator()->allocate();
187*c217d954SCole Faust     c.allocator()->allocate();
188*c217d954SCole Faust 
189*c217d954SCole Faust     ITensorPack run_pack{ { TensorType::ACL_SRC_0, &a }, { TensorType::ACL_SRC_1, &b }, { TensorType::ACL_SRC_2, &c } };
190*c217d954SCole Faust     ITensorPack prep_pack{ { TensorType::ACL_SRC_1, &b }, { TensorType::ACL_SRC_2, &c } };
191*c217d954SCole Faust 
192*c217d954SCole Faust     auto mg       = MemoryGroup{};
193*c217d954SCole Faust     auto ws       = manage_workspace<Tensor>(winograd->workspace(), mg, run_pack, prep_pack);
194*c217d954SCole Faust     auto run_conv = [&]() -> Tensor
195*c217d954SCole Faust     {
196*c217d954SCole Faust         auto dst = create_tensor<Tensor>(dst_info);
197*c217d954SCole Faust         dst.allocator()->allocate();
198*c217d954SCole Faust 
199*c217d954SCole Faust         run_pack.add_tensor(TensorType::ACL_DST, &dst);
200*c217d954SCole Faust         library->fill_tensor_value(Accessor(a), 1.f);
201*c217d954SCole Faust         library->fill_tensor_value(Accessor(b), 2.f);
202*c217d954SCole Faust         library->fill_tensor_value(Accessor(c), 3.f);
203*c217d954SCole Faust 
204*c217d954SCole Faust         // This operator is configured once and captured by this lambda.
205*c217d954SCole Faust         winograd->prepare(prep_pack);
206*c217d954SCole Faust         winograd->run(run_pack);
207*c217d954SCole Faust         return dst;
208*c217d954SCole Faust     };
209*c217d954SCole Faust 
210*c217d954SCole Faust     auto result_0 = run_conv();
211*c217d954SCole Faust     auto result_1 = run_conv();
212*c217d954SCole Faust 
213*c217d954SCole Faust     for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
214*c217d954SCole Faust     {
215*c217d954SCole Faust         ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
216*c217d954SCole Faust     }
217*c217d954SCole Faust }
218*c217d954SCole Faust 
219*c217d954SCole Faust /** Test case for memory injection in @ref NEWinogradConvolutionLayer.
220*c217d954SCole Faust  *
221*c217d954SCole Faust  * Make sure @ref NEWinogradConvolutionLayer still works through injecting the memory at configure time using the old API.
222*c217d954SCole Faust  *
223*c217d954SCole Faust  * Checks performed in order:
224*c217d954SCole Faust  * - Both runs compute the same output
225*c217d954SCole Faust  */
TEST_CASE(MultipleExecutionWithConfigure,framework::DatasetMode::ALL)226*c217d954SCole Faust TEST_CASE(MultipleExecutionWithConfigure, framework::DatasetMode::ALL)
227*c217d954SCole Faust {
228*c217d954SCole Faust     auto                gemm     = std::make_unique<NEWinogradConvolutionLayer>();
229*c217d954SCole Faust     const auto          src_info = TensorInfo(TensorShape(8U, 8U, 32U), 1, DataType::F32);
230*c217d954SCole Faust     const auto          w_info   = TensorInfo(TensorShape(1U), 1, DataType::F32);
231*c217d954SCole Faust     const auto          b_info   = TensorInfo(TensorShape(1U, 3U, 32U, 1U), 1, DataType::F32);
232*c217d954SCole Faust     auto                dst_info = TensorInfo(TensorShape(8U, 6U, 1U), 1, DataType::F32);
233*c217d954SCole Faust     const PadStrideInfo pad_info{};
234*c217d954SCole Faust 
235*c217d954SCole Faust     auto run_conv = [&]()
236*c217d954SCole Faust     {
237*c217d954SCole Faust         auto src = create_tensor<Tensor>(src_info);
238*c217d954SCole Faust         auto w   = create_tensor<Tensor>(w_info);
239*c217d954SCole Faust         auto b   = create_tensor<Tensor>(b_info);
240*c217d954SCole Faust         auto dst = create_tensor<Tensor>(dst_info);
241*c217d954SCole Faust 
242*c217d954SCole Faust         gemm->configure(&src, &b, &w, &dst, pad_info);
243*c217d954SCole Faust 
244*c217d954SCole Faust         src.allocator()->allocate();
245*c217d954SCole Faust         b.allocator()->allocate();
246*c217d954SCole Faust         w.allocator()->allocate();
247*c217d954SCole Faust         dst.allocator()->allocate();
248*c217d954SCole Faust 
249*c217d954SCole Faust         library->fill_tensor_value(Accessor(src), 1.f);
250*c217d954SCole Faust         library->fill_tensor_value(Accessor(b), 2.f);
251*c217d954SCole Faust         library->fill_tensor_value(Accessor(w), 3.f);
252*c217d954SCole Faust         gemm->run();
253*c217d954SCole Faust         return dst;
254*c217d954SCole Faust     };
255*c217d954SCole Faust 
256*c217d954SCole Faust     auto result_0 = run_conv();
257*c217d954SCole Faust     auto result_1 = run_conv();
258*c217d954SCole Faust 
259*c217d954SCole Faust     for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
260*c217d954SCole Faust     {
261*c217d954SCole Faust         ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
262*c217d954SCole Faust     }
263*c217d954SCole Faust }
264*c217d954SCole Faust 
265*c217d954SCole Faust TEST_SUITE(FP32)
266*c217d954SCole Faust 
TEST_SUITE(Conv1x3)267*c217d954SCole Faust TEST_SUITE(Conv1x3)
268*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
269*c217d954SCole Faust                        combine(combine(combine(datasets::SmallWinogradConvolutionLayer1x3Dataset(),
270*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
271*c217d954SCole Faust                                        ActivationFunctionsDataset),
272*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
273*c217d954SCole Faust {
274*c217d954SCole Faust     // Validate output
275*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
276*c217d954SCole Faust }
277*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, NEWinogradConvolutionLayerMixedDataLayoutFixture<float>, framework::DatasetMode::PRECOMMIT,
278*c217d954SCole Faust                        combine(combine(combine(combine(combine(combine(combine(combine(
279*c217d954SCole Faust                                                                                    framework::dataset::make("Input", TensorShape(8U, 8U, 32U)),
280*c217d954SCole Faust                                                                                    framework::dataset::make("Weight", TensorShape(1U, 3U, 32U, 1U))),
281*c217d954SCole Faust                                                                                framework::dataset::make("Bias", TensorShape(1U))),
282*c217d954SCole Faust                                                                        framework::dataset::make("Output", TensorShape(8U, 6U, 1U))),
283*c217d954SCole Faust                                                                framework::dataset::make("PadStrideInfo", PadStrideInfo(1, 1, 0, 0))),
284*c217d954SCole Faust                                                        framework::dataset::make("Dilation", Size2D(1U, 1U))),
285*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
286*c217d954SCole Faust                                        ActivationFunctionsDataset),
287*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
288*c217d954SCole Faust {
289*c217d954SCole Faust     // Validate output
290*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
291*c217d954SCole Faust }
292*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY,
293*c217d954SCole Faust                        combine(combine(combine(datasets::LargeWinogradConvolutionLayer1x3Dataset(),
294*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
295*c217d954SCole Faust                                        ActivationFunctionsDataset),
296*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
297*c217d954SCole Faust {
298*c217d954SCole Faust     // Validate output
299*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
300*c217d954SCole Faust }
301*c217d954SCole Faust 
302*c217d954SCole Faust TEST_SUITE_END() // Conv1x3
303*c217d954SCole Faust 
TEST_SUITE(Conv3x1)304*c217d954SCole Faust TEST_SUITE(Conv3x1)
305*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
306*c217d954SCole Faust                        combine(combine(combine(datasets::SmallWinogradConvolutionLayer3x1Dataset(),
307*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
308*c217d954SCole Faust                                        ActivationFunctionsDataset),
309*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
310*c217d954SCole Faust {
311*c217d954SCole Faust     // Validate output
312*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
313*c217d954SCole Faust }
314*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY,
315*c217d954SCole Faust                        combine(combine(combine(datasets::LargeWinogradConvolutionLayer3x1Dataset(),
316*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
317*c217d954SCole Faust                                        ActivationFunctionsDataset),
318*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
319*c217d954SCole Faust {
320*c217d954SCole Faust     // Validate output
321*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
322*c217d954SCole Faust }
323*c217d954SCole Faust 
324*c217d954SCole Faust TEST_SUITE_END() // Conv3x1
325*c217d954SCole Faust 
TEST_SUITE(Conv1x5)326*c217d954SCole Faust TEST_SUITE(Conv1x5)
327*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
328*c217d954SCole Faust                        combine(combine(combine(datasets::SmallWinogradConvolutionLayer1x5Dataset(),
329*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
330*c217d954SCole Faust                                        ActivationFunctionsDataset),
331*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
332*c217d954SCole Faust {
333*c217d954SCole Faust     // Validate output
334*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
335*c217d954SCole Faust }
336*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY,
337*c217d954SCole Faust                        combine(combine(combine(datasets::LargeWinogradConvolutionLayer1x5Dataset(),
338*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
339*c217d954SCole Faust                                        ActivationFunctionsDataset),
340*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
341*c217d954SCole Faust {
342*c217d954SCole Faust     // Validate output
343*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
344*c217d954SCole Faust }
345*c217d954SCole Faust 
346*c217d954SCole Faust TEST_SUITE_END() // Conv1x5
347*c217d954SCole Faust 
TEST_SUITE(Conv5x1)348*c217d954SCole Faust TEST_SUITE(Conv5x1)
349*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
350*c217d954SCole Faust                        combine(combine(combine(datasets::SmallWinogradConvolutionLayer5x1Dataset(),
351*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
352*c217d954SCole Faust                                        ActivationFunctionsDataset),
353*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
354*c217d954SCole Faust {
355*c217d954SCole Faust     // Validate output
356*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
357*c217d954SCole Faust }
358*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY,
359*c217d954SCole Faust                        combine(combine(combine(datasets::LargeWinogradConvolutionLayer5x1Dataset(),
360*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
361*c217d954SCole Faust                                        ActivationFunctionsDataset),
362*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
363*c217d954SCole Faust {
364*c217d954SCole Faust     // Validate output
365*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
366*c217d954SCole Faust }
367*c217d954SCole Faust 
368*c217d954SCole Faust TEST_SUITE_END() // Conv5x1
369*c217d954SCole Faust 
TEST_SUITE(Conv7x1)370*c217d954SCole Faust TEST_SUITE(Conv7x1)
371*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
372*c217d954SCole Faust                        combine(combine(combine(datasets::SmallWinogradConvolutionLayer7x1Dataset(),
373*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
374*c217d954SCole Faust                                        ActivationFunctionsDataset),
375*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
376*c217d954SCole Faust {
377*c217d954SCole Faust     // Validate output
378*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
379*c217d954SCole Faust }
380*c217d954SCole Faust 
381*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY,
382*c217d954SCole Faust                        combine(combine(combine(datasets::LargeWinogradConvolutionLayer7x1Dataset(),
383*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
384*c217d954SCole Faust                                        ActivationFunctionsDataset),
385*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
386*c217d954SCole Faust {
387*c217d954SCole Faust     // Validate output
388*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
389*c217d954SCole Faust }
390*c217d954SCole Faust TEST_SUITE_END() // Conv7x1
391*c217d954SCole Faust 
TEST_SUITE(Conv1x7)392*c217d954SCole Faust TEST_SUITE(Conv1x7)
393*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
394*c217d954SCole Faust                        combine(combine(combine(datasets::SmallWinogradConvolutionLayer1x7Dataset(),
395*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
396*c217d954SCole Faust                                        ActivationFunctionsDataset),
397*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
398*c217d954SCole Faust {
399*c217d954SCole Faust     // Validate output
400*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
401*c217d954SCole Faust }
402*c217d954SCole Faust 
403*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY,
404*c217d954SCole Faust                        combine(combine(combine(datasets::LargeWinogradConvolutionLayer7x1Dataset(),
405*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
406*c217d954SCole Faust                                        ActivationFunctionsDataset),
407*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
408*c217d954SCole Faust {
409*c217d954SCole Faust     // Validate output
410*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
411*c217d954SCole Faust }
412*c217d954SCole Faust TEST_SUITE_END() // Conv1x7
413*c217d954SCole Faust 
TEST_SUITE(Conv3x3)414*c217d954SCole Faust TEST_SUITE(Conv3x3)
415*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
416*c217d954SCole Faust                        combine(combine(combine(datasets::SmallWinogradConvolutionLayer3x3Dataset(),
417*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
418*c217d954SCole Faust                                        ActivationFunctionsDataset),
419*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
420*c217d954SCole Faust 
421*c217d954SCole Faust {
422*c217d954SCole Faust     // Validate output
423*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
424*c217d954SCole Faust }
425*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY,
426*c217d954SCole Faust                        combine(combine(combine(datasets::LargeWinogradConvolutionLayer3x3Dataset(),
427*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
428*c217d954SCole Faust                                        ActivationFunctionsDataset),
429*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
430*c217d954SCole Faust 
431*c217d954SCole Faust {
432*c217d954SCole Faust     // Validate output
433*c217d954SCole Faust     // floating point arithmetic the Winograd results will not be exactly the same as direct convolution, especially for big shapes
434*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_winograd_3x3_f32, 0.f, float(abs_tolerance_f32));
435*c217d954SCole Faust }
436*c217d954SCole Faust TEST_SUITE_END() // Conv3x3
437*c217d954SCole Faust 
TEST_SUITE(Conv5x5)438*c217d954SCole Faust TEST_SUITE(Conv5x5)
439*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
440*c217d954SCole Faust                        combine(combine(combine(datasets::SmallWinogradConvolutionLayer5x5Dataset(),
441*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
442*c217d954SCole Faust                                        ActivationFunctionsDataset),
443*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
444*c217d954SCole Faust 
445*c217d954SCole Faust {
446*c217d954SCole Faust     // Validate output
447*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
448*c217d954SCole Faust }
449*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY,
450*c217d954SCole Faust                        combine(combine(combine(datasets::LargeWinogradConvolutionLayer5x5Dataset(),
451*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
452*c217d954SCole Faust                                        ActivationFunctionsDataset),
453*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
454*c217d954SCole Faust 
455*c217d954SCole Faust {
456*c217d954SCole Faust     // Validate output
457*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
458*c217d954SCole Faust }
459*c217d954SCole Faust 
460*c217d954SCole Faust TEST_SUITE_END() // Conv5x5
461*c217d954SCole Faust 
462*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmallNoBias, NEWinogradConvolutionLayerNoBiasFixture<float>, framework::DatasetMode::PRECOMMIT,
463*c217d954SCole Faust                        combine(combine(combine(framework::dataset::concat(datasets::SmallWinogradConvolutionLayer3x3Dataset(),
464*c217d954SCole Faust                                                                           datasets::SmallWinogradConvolutionLayer5x5Dataset()),
465*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F32 })),
466*c217d954SCole Faust                                        ActivationFunctionsDataset),
467*c217d954SCole Faust 
468*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
469*c217d954SCole Faust {
470*c217d954SCole Faust     // Validate output
471*c217d954SCole Faust     validate(Accessor(_target), _reference, abs_tolerance_f32);
472*c217d954SCole Faust }
473*c217d954SCole Faust 
474*c217d954SCole Faust TEST_SUITE_END() // FP32
475*c217d954SCole Faust 
476*c217d954SCole Faust #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
477*c217d954SCole Faust TEST_SUITE(FP16)
478*c217d954SCole Faust using CLWinogradConvolutionLayerFastMathFixture16 = WinogradConvolutionLayerFastMathValidationFixture<Tensor, Accessor, NEWinogradConvolutionLayer, half, float>;
479*c217d954SCole Faust 
480*c217d954SCole Faust DATA_TEST_CASE(ValidateConvolutionMethod, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(
481*c217d954SCole Faust                                           framework::dataset::make("InputInfo", { TensorInfo(TensorShape(18U, 18U, 32U), 1, DataType::F16),
482*c217d954SCole Faust                                                                                   TensorInfo(TensorShape(18U, 18U, 32U), 1, DataType::F16)
483*c217d954SCole Faust                                           }),
484*c217d954SCole Faust                                           framework::dataset::make("WeightsInfo", { TensorInfo(TensorShape(3U, 3U, 32U, 21U), 1, DataType::F16),
485*c217d954SCole Faust                                                                                     TensorInfo(TensorShape(3U, 3U, 32U, 21U), 1, DataType::F16)
486*c217d954SCole Faust                                           })),
487*c217d954SCole Faust                                           framework::dataset::make("OutputInfo", { TensorInfo(TensorShape(16U, 16U, 21U), 1, DataType::F32),
488*c217d954SCole Faust                                                                                    TensorInfo(TensorShape(16U, 16U, 21U), 1, DataType::F16)
489*c217d954SCole Faust                                           })),
490*c217d954SCole Faust                                           framework::dataset::make("ConvInfo", { PadStrideInfo(1, 1, 0, 0),
491*c217d954SCole Faust                                                                                  PadStrideInfo(1, 1, 0, 0)
492*c217d954SCole Faust                                           })),
493*c217d954SCole Faust                                           framework::dataset::make("FastMath", { false, // case fp16 and fast_math False then disable Winograd
494*c217d954SCole Faust                                                                                  true   // case fp16 and fast_math True then enable Winograd
495*c217d954SCole Faust                                           })),
496*c217d954SCole Faust                                                                            framework::dataset::make("Expected", { ConvolutionMethod::GEMM, ConvolutionMethod::WINOGRAD })),
497*c217d954SCole Faust                input_info, weights_info, output_info, conv_info, fast_math, expected)
498*c217d954SCole Faust {
499*c217d954SCole Faust     ConvolutionMethod is_valid = NEConvolutionLayer::get_convolution_method(&input_info.clone()->set_is_resizable(true),
500*c217d954SCole Faust                                                                             &weights_info.clone()->set_is_resizable(true),
501*c217d954SCole Faust                                                                             &output_info.clone()->set_is_resizable(true), conv_info, WeightsInfo(), Size2D(1U, 1U), ActivationLayerInfo(), fast_math);
502*c217d954SCole Faust     ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS);
503*c217d954SCole Faust }
504*c217d954SCole Faust 
505*c217d954SCole Faust TEST_SUITE(Conv3x3)
506*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::PRECOMMIT,
507*c217d954SCole Faust                        combine(combine(combine(datasets::SmallWinogradConvolutionLayer3x3Dataset(),
508*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F16 })),
509*c217d954SCole Faust                                        ActivationFunctionsDataset),
510*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
511*c217d954SCole Faust 
512*c217d954SCole Faust {
513*c217d954SCole Faust     // Validate output
514*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_convolution_layer_f16, tolerance_num_f16);
515*c217d954SCole Faust }
516*c217d954SCole Faust 
517*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::NIGHTLY,
518*c217d954SCole Faust                        combine(combine(combine(datasets::LargeWinogradConvolutionLayer3x3Dataset(),
519*c217d954SCole Faust                                                framework::dataset::make("DataType", { DataType::F16 })),
520*c217d954SCole Faust                                        ActivationFunctionsDataset),
521*c217d954SCole Faust                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
522*c217d954SCole Faust 
523*c217d954SCole Faust {
524*c217d954SCole Faust     // Validate output
525*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_convolution_layer_f16, tolerance_num_f16);
526*c217d954SCole Faust }
527*c217d954SCole Faust TEST_SUITE_END() // Conv3x3
528*c217d954SCole Faust TEST_SUITE_END() // FP16
529*c217d954SCole Faust #endif           /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
530*c217d954SCole Faust TEST_SUITE_END() // WinogradLayer
531*c217d954SCole Faust 
532*c217d954SCole Faust #ifdef ARM_COMPUTE_ENABLE_FIXED_FORMAT_KERNELS
533*c217d954SCole Faust TEST_SUITE(FIXED_FORMAT_KERNELS)
534*c217d954SCole Faust TEST_SUITE(VariableWeightUtils)
535*c217d954SCole Faust 
536*c217d954SCole Faust // UC2_1_* tests: the user requests a specific fixed format, but there is no kernel that supports it.
537*c217d954SCole Faust 
538*c217d954SCole Faust template <typename ConvolutionClass>
539*c217d954SCole Faust using HasOptImplFixtureNoFastMath = HasOptImplFixture<ConvolutionClass, /*enable_fast_math*/ false>;
540*c217d954SCole Faust 
541*c217d954SCole Faust template <typename ConvolutionClass>
542*c217d954SCole Faust using HasOptImplFixtureFastMath = HasOptImplFixture<ConvolutionClass, /*enable_fast_math*/ true>;
543*c217d954SCole Faust 
544*c217d954SCole Faust // UC2_1
545*c217d954SCole Faust 
546*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC2_1_CpuGemmConv2d, HasOptImplFixtureNoFastMath<cpu::CpuGemmConv2d>, framework::DatasetMode::ALL,
547*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
548*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::OHWIo2 })))
549*c217d954SCole Faust {
550*c217d954SCole Faust     ARM_COMPUTE_EXPECT(!_kernel_found, framework::LogLevel::ERRORS);
551*c217d954SCole Faust }
552*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC2_1_NEGEMMConvolutionLayer, HasOptImplFixtureNoFastMath<NEGEMMConvolutionLayer>, framework::DatasetMode::ALL,
553*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
554*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::OHWIo2 })))
555*c217d954SCole Faust {
556*c217d954SCole Faust     ARM_COMPUTE_EXPECT(!_kernel_found, framework::LogLevel::ERRORS);
557*c217d954SCole Faust }
558*c217d954SCole Faust 
559*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC2_1_CpuGemmConv2d_FastMath, HasOptImplFixtureFastMath<cpu::CpuGemmConv2d>, framework::DatasetMode::ALL,
560*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
561*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::OHWIo2 })))
562*c217d954SCole Faust {
563*c217d954SCole Faust     ARM_COMPUTE_EXPECT(!_kernel_found, framework::LogLevel::ERRORS);
564*c217d954SCole Faust }
565*c217d954SCole Faust 
566*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC2_1_NEGEMMConvolutionLayer_FastMath, HasOptImplFixtureFastMath<NEGEMMConvolutionLayer>, framework::DatasetMode::ALL,
567*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
568*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::OHWIo2 })))
569*c217d954SCole Faust {
570*c217d954SCole Faust     ARM_COMPUTE_EXPECT(!_kernel_found, framework::LogLevel::ERRORS);
571*c217d954SCole Faust }
572*c217d954SCole Faust 
573*c217d954SCole Faust // UC2_2_* tests: the user requests a specific fixed format, and a
574*c217d954SCole Faust // kernel that support that fixed format is found.
575*c217d954SCole Faust 
576*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC2_2_CpuGemmConv2d, HasOptImplFixtureNoFastMath<cpu::CpuGemmConv2d>, framework::DatasetMode::ALL,
577*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
578*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::OHWIo4 })))
579*c217d954SCole Faust {
580*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_kernel_found, framework::LogLevel::ERRORS);
581*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format == arm_compute::WeightFormat::OHWIo4, framework::LogLevel::ERRORS);
582*c217d954SCole Faust }
583*c217d954SCole Faust 
584*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC2_2_NEGEMMConvolutionLayer, HasOptImplFixtureNoFastMath<NEGEMMConvolutionLayer>, framework::DatasetMode::ALL,
585*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
586*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::OHWIo4 })))
587*c217d954SCole Faust {
588*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_kernel_found, framework::LogLevel::ERRORS);
589*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format == arm_compute::WeightFormat::OHWIo4, framework::LogLevel::ERRORS);
590*c217d954SCole Faust }
591*c217d954SCole Faust 
592*c217d954SCole Faust #if defined(ARM_COMPUTE_ENABLE_BF16)
593*c217d954SCole Faust 
594*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC2_2_CpuGemmConv2d_FastMath, HasOptImplFixtureFastMath<cpu::CpuGemmConv2d>, framework::DatasetMode::ALL,
595*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
596*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::OHWIo8i4_bf16 })))
597*c217d954SCole Faust {
598*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_kernel_found, framework::LogLevel::ERRORS);
599*c217d954SCole Faust     ARM_COMPUTE_EXPECT_EQUAL(_computed_weight_format, arm_compute::WeightFormat::OHWIo8i4_bf16, framework::LogLevel::ERRORS);
600*c217d954SCole Faust }
601*c217d954SCole Faust 
602*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC2_2_NEGEMMConvolutionLayer_FastMath, HasOptImplFixtureFastMath<NEGEMMConvolutionLayer>, framework::DatasetMode::ALL,
603*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
604*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::OHWIo8i4_bf16 })))
605*c217d954SCole Faust {
606*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_kernel_found, framework::LogLevel::ERRORS);
607*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format == arm_compute::WeightFormat::OHWIo8i4_bf16, framework::LogLevel::ERRORS);
608*c217d954SCole Faust }
609*c217d954SCole Faust 
610*c217d954SCole Faust #endif // ARM_COMPUTE_ENABLE_BF16
611*c217d954SCole Faust 
612*c217d954SCole Faust // UC3_1_* tests: the user queries for ANY fixed format, but there is
613*c217d954SCole Faust // no kernel that support the use case specified by the user (for
614*c217d954SCole Faust // example, there is no fixed format kernel for the datatype of the
615*c217d954SCole Faust // problem).
616*c217d954SCole Faust 
617*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC3_1_CpuGemmConv2d, HasOptImplFixtureNoFastMath<cpu::CpuGemmConv2d>, framework::DatasetMode::ALL,
618*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::S32 }),
619*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::ANY })))
620*c217d954SCole Faust {
621*c217d954SCole Faust     ARM_COMPUTE_EXPECT(!_kernel_found, framework::LogLevel::ERRORS);
622*c217d954SCole Faust }
623*c217d954SCole Faust 
624*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC3_1_NEGEMMConvolutionLayer, HasOptImplFixtureNoFastMath<NEGEMMConvolutionLayer>, framework::DatasetMode::ALL,
625*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::S32 }),
626*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::ANY })))
627*c217d954SCole Faust {
628*c217d954SCole Faust     ARM_COMPUTE_EXPECT(!_kernel_found, framework::LogLevel::ERRORS);
629*c217d954SCole Faust }
630*c217d954SCole Faust 
631*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC3_1_CpuGemmConv2d_FastMath, HasOptImplFixtureFastMath<cpu::CpuGemmConv2d>, framework::DatasetMode::ALL,
632*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::S32 }),
633*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::ANY })))
634*c217d954SCole Faust {
635*c217d954SCole Faust     ARM_COMPUTE_EXPECT(!_kernel_found, framework::LogLevel::ERRORS);
636*c217d954SCole Faust }
637*c217d954SCole Faust 
638*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC3_1_NEGEMMConvolutionLayer_FastMath, HasOptImplFixtureFastMath<NEGEMMConvolutionLayer>, framework::DatasetMode::ALL,
639*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::S32 }),
640*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::ANY })))
641*c217d954SCole Faust {
642*c217d954SCole Faust     ARM_COMPUTE_EXPECT(!_kernel_found, framework::LogLevel::ERRORS);
643*c217d954SCole Faust }
644*c217d954SCole Faust 
645*c217d954SCole Faust // UC3_2_* tests: the user queries for ANY fixed format. The search
646*c217d954SCole Faust // succeeded and the fixed format found is prompted back for
647*c217d954SCole Faust // consumption by the user. Note that we just test the
648*c217d954SCole Faust // _computed_weight_format to be anything but not the formats that are
649*c217d954SCole Faust // not fixed formats (ANY and UNSPECIFIED). This is because the weight
650*c217d954SCole Faust // format that the runtime produces depends on the size of the vector
651*c217d954SCole Faust // units of the hardware where the tests is executed. For example, a
652*c217d954SCole Faust // format like OHWIo4 for FP32 data returned for 128-bit NEON hardware
653*c217d954SCole Faust // is replaced by OHWIo8 when running on 256-bit SVE.
654*c217d954SCole Faust 
655*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC3_2_CpuGemmConv2d, HasOptImplFixtureNoFastMath<cpu::CpuGemmConv2d>, framework::DatasetMode::ALL,
656*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
657*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::ANY })))
658*c217d954SCole Faust {
659*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_kernel_found, framework::LogLevel::ERRORS);
660*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format != arm_compute::WeightFormat::ANY, framework::LogLevel::ERRORS);
661*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format != arm_compute::WeightFormat::UNSPECIFIED, framework::LogLevel::ERRORS);
662*c217d954SCole Faust }
663*c217d954SCole Faust 
664*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC3_2_NEGEMMConvolutionLayer, HasOptImplFixtureNoFastMath<NEGEMMConvolutionLayer>, framework::DatasetMode::ALL,
665*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
666*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::ANY })))
667*c217d954SCole Faust {
668*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format != arm_compute::WeightFormat::ANY, framework::LogLevel::ERRORS);
669*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format != arm_compute::WeightFormat::UNSPECIFIED, framework::LogLevel::ERRORS);
670*c217d954SCole Faust }
671*c217d954SCole Faust 
672*c217d954SCole Faust #if defined(ARM_COMPUTE_ENABLE_BF16)
673*c217d954SCole Faust 
674*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC3_2_CpuGemmConv2d_FastMath, HasOptImplFixtureFastMath<cpu::CpuGemmConv2d>, framework::DatasetMode::ALL,
675*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
676*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::ANY })))
677*c217d954SCole Faust {
678*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_kernel_found, framework::LogLevel::ERRORS);
679*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format != arm_compute::WeightFormat::ANY, framework::LogLevel::ERRORS);
680*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format != arm_compute::WeightFormat::UNSPECIFIED, framework::LogLevel::ERRORS);
681*c217d954SCole Faust     ARM_COMPUTE_EXPECT(arm_compute::is_fixed_format_fast_math(_computed_weight_format), framework::LogLevel::ERRORS);
682*c217d954SCole Faust }
683*c217d954SCole Faust 
684*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(UC3_2_NEGEMMConvolutionLayer_FastMath, HasOptImplFixtureFastMath<NEGEMMConvolutionLayer>, framework::DatasetMode::ALL,
685*c217d954SCole Faust                        combine(framework::dataset::make("DataType", { DataType::F32 }),
686*c217d954SCole Faust                                framework::dataset::make("QueryWeightFormat", { arm_compute::WeightFormat::ANY })))
687*c217d954SCole Faust {
688*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_kernel_found, framework::LogLevel::ERRORS);
689*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format != arm_compute::WeightFormat::ANY, framework::LogLevel::ERRORS);
690*c217d954SCole Faust     ARM_COMPUTE_EXPECT(_computed_weight_format != arm_compute::WeightFormat::UNSPECIFIED, framework::LogLevel::ERRORS);
691*c217d954SCole Faust     ARM_COMPUTE_EXPECT(arm_compute::is_fixed_format_fast_math(_computed_weight_format), framework::LogLevel::ERRORS);
692*c217d954SCole Faust }
693*c217d954SCole Faust 
694*c217d954SCole Faust #endif // ARM_COMPUTE_ENABLE_BF16
695*c217d954SCole Faust 
696*c217d954SCole Faust namespace
697*c217d954SCole Faust {
698*c217d954SCole Faust using TestCaseType          = std::tuple<TensorShape, TensorShape, arm_compute::WeightFormat>;
699*c217d954SCole Faust auto prepare_weights_shapes = framework::dataset::make("TensorShape",
700*c217d954SCole Faust {
701*c217d954SCole Faust     // OHWIo<interleave_by>i<block_by>
702*c217d954SCole Faust     //
703*c217d954SCole Faust     // OHWI --> O'HWI', where:
704*c217d954SCole Faust     //
705*c217d954SCole Faust     //   O'= smallest multiple of <interleave_by> such that O<=O'
706*c217d954SCole Faust     //   I'= smallest multiple of <block_by> such that I<=I'
707*c217d954SCole Faust     //
708*c217d954SCole Faust 
709*c217d954SCole Faust     // Change N for OHWIo4
710*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 1U }, { 1U, 1U, 1U, 4U }, arm_compute::WeightFormat::OHWIo4 }),
711*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 2U }, { 1U, 1U, 1U, 4U }, arm_compute::WeightFormat::OHWIo4 }),
712*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 3U }, { 1U, 1U, 1U, 4U }, arm_compute::WeightFormat::OHWIo4 }),
713*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 4U }, { 1U, 1U, 1U, 4U }, arm_compute::WeightFormat::OHWIo4 }),
714*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 5U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo4 }),
715*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 6U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo4 }),
716*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 7U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo4 }),
717*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 8U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo4 }),
718*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 9U }, { 1U, 1U, 1U, 12U }, arm_compute::WeightFormat::OHWIo4 }),
719*c217d954SCole Faust     // // Change N for OHWIo8
720*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 1U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo8 }),
721*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 2U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo8 }),
722*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 3U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo8 }),
723*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 4U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo8 }),
724*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 5U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo8 }),
725*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 6U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo8 }),
726*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 7U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo8 }),
727*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 8U }, { 1U, 1U, 1U, 8U }, arm_compute::WeightFormat::OHWIo8 }),
728*c217d954SCole Faust     TestCaseType({ { 1U, 1U, 1U, 9U }, { 1U, 1U, 1U, 16U }, arm_compute::WeightFormat::OHWIo8 }),
729*c217d954SCole Faust     // // Change N for OHWIo4 when H, W and C are not 1
730*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 1U }, { 3, 4, 2, 4 }, arm_compute::WeightFormat::OHWIo4 }),
731*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 2U }, { 3, 4, 2, 4 }, arm_compute::WeightFormat::OHWIo4 }),
732*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 3U }, { 3, 4, 2, 4 }, arm_compute::WeightFormat::OHWIo4 }),
733*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 4U }, { 3, 4, 2, 4 }, arm_compute::WeightFormat::OHWIo4 }),
734*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 5U }, { 3, 4, 2, 8 }, arm_compute::WeightFormat::OHWIo4 }),
735*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 6U }, { 3, 4, 2, 8 }, arm_compute::WeightFormat::OHWIo4 }),
736*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 7U }, { 3, 4, 2, 8 }, arm_compute::WeightFormat::OHWIo4 }),
737*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 8U }, { 3, 4, 2, 8 }, arm_compute::WeightFormat::OHWIo4 }),
738*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 9U }, { 3, 4, 2, 12 }, arm_compute::WeightFormat::OHWIo4 }),
739*c217d954SCole Faust 
740*c217d954SCole Faust     // // Fix N and move HWI around, with different data layouts and formats
741*c217d954SCole Faust     TestCaseType({ { 2U, 4U, 3U, 5U }, { 2, 4, 3, 8 }, arm_compute::WeightFormat::OHWIo4 }),
742*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 5U }, { 3, 4, 2, 8 }, arm_compute::WeightFormat::OHWIo4 }),
743*c217d954SCole Faust     TestCaseType({ { 2U, 4U, 3U, 9U }, { 2, 4, 3, 16 }, arm_compute::WeightFormat::OHWIo8 }),
744*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 2U, 9U }, { 3, 4, 2, 16 }, arm_compute::WeightFormat::OHWIo8 }),
745*c217d954SCole Faust     TestCaseType({ { 1024U, 1U, 1U, 1001U }, { 1024, 1, 1, 1008 }, arm_compute::WeightFormat::OHWIo8 }),
746*c217d954SCole Faust 
747*c217d954SCole Faust     // // Adding <block_by> on I (=C)
748*c217d954SCole Faust     TestCaseType({ { 1U, 4U, 3U, 5U }, { 2, 4, 3, 8 }, arm_compute::WeightFormat::OHWIo4i2 }),
749*c217d954SCole Faust     TestCaseType({ { 2U, 4U, 3U, 5U }, { 2, 4, 3, 8 }, arm_compute::WeightFormat::OHWIo4i2 }),
750*c217d954SCole Faust     TestCaseType({ { 3U, 4U, 3U, 5U }, { 4, 4, 3, 8 }, arm_compute::WeightFormat::OHWIo4i2 }),
751*c217d954SCole Faust 
752*c217d954SCole Faust     // ---------
753*c217d954SCole Faust     TestCaseType({ { 2, 2, 1, 5 }, { 2, 2, 1, 8 }, arm_compute::WeightFormat::OHWIo4 }),
754*c217d954SCole Faust     TestCaseType({ { 1, 2, 2, 5 }, { 1, 2, 2, 8 }, arm_compute::WeightFormat::OHWIo4 }),
755*c217d954SCole Faust 
756*c217d954SCole Faust });
757*c217d954SCole Faust } // unnamed namespace
758*c217d954SCole Faust 
DATA_TEST_CASE(PrepareWeightShape,framework::DatasetMode::ALL,prepare_weights_shapes,shapes)759*c217d954SCole Faust DATA_TEST_CASE(PrepareWeightShape, framework::DatasetMode::ALL,
760*c217d954SCole Faust                prepare_weights_shapes, shapes)
761*c217d954SCole Faust {
762*c217d954SCole Faust     const TensorShape               input_shape    = std::get<0>(shapes);
763*c217d954SCole Faust     const TensorShape               expected_shape = std::get<1>(shapes);
764*c217d954SCole Faust     const arm_compute::WeightFormat wf             = std::get<2>(shapes);
765*c217d954SCole Faust     const DataType                  DT             = DataType::F32;
766*c217d954SCole Faust     const DataLayout                DL             = DataLayout::NHWC;
767*c217d954SCole Faust     const auto                      TI             = TensorInfo(input_shape, 1 /*num_channels, deprecated*/, DT, DL);
768*c217d954SCole Faust     const TensorInfo                computed_info  = ::arm_compute::test::validation::prepare_weights(TI, wf);
769*c217d954SCole Faust     ARM_COMPUTE_EXPECT_EQUAL(computed_info.tensor_shape(), expected_shape, framework::LogLevel::ERRORS);
770*c217d954SCole Faust }
771*c217d954SCole Faust 
772*c217d954SCole Faust TEST_SUITE_END() // VariableWeightUtils
773*c217d954SCole Faust 
774*c217d954SCole Faust TEST_SUITE(ExperimentalCpuAPIVariableWeightWithFixtures)
775*c217d954SCole Faust 
776*c217d954SCole Faust template <typename ScalarType>
777*c217d954SCole Faust using VarWidth = VariableWeightsFixture<cpu::CpuGemmConv2d, Tensor, Accessor, ScalarType, /*enable_fast_math*/ false>;
778*c217d954SCole Faust 
779*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmallFloat, VarWidth<float>, framework::DatasetMode::ALL,
780*c217d954SCole Faust                        combine(combine(datasets::SmallConvolutionLayerDataset(),
781*c217d954SCole Faust                                        framework::dataset::make("DataLayout", { DataLayout::NHWC })),
782*c217d954SCole Faust                                framework::dataset::make("ACL Scalar type", { DataType::F32 })))
783*c217d954SCole Faust {
784*c217d954SCole Faust     // Validate output
785*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
786*c217d954SCole Faust }
787*c217d954SCole Faust 
788*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmallHalf, VarWidth<half>, framework::DatasetMode::ALL,
789*c217d954SCole Faust                        combine(combine(datasets::SmallConvolutionLayerDataset(),
790*c217d954SCole Faust                                        framework::dataset::make("DataLayout", { DataLayout::NHWC })),
791*c217d954SCole Faust                                framework::dataset::make("ACL Scalar type", { DataType::F16 })))
792*c217d954SCole Faust {
793*c217d954SCole Faust     // Validate output
794*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f16, 0.f, half(abs_tolerance_f16));
795*c217d954SCole Faust }
796*c217d954SCole Faust 
797*c217d954SCole Faust #if defined(ARM_COMPUTE_ENABLE_BF16)
798*c217d954SCole Faust template <typename ScalarType>
799*c217d954SCole Faust using VarWidthFastMath = VariableWeightsFixture<cpu::CpuGemmConv2d, Tensor, Accessor, ScalarType, /*enable_fast_math*/ true>;
800*c217d954SCole Faust 
801*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmallFloatFastMath, VarWidthFastMath<float>, framework::DatasetMode::ALL,
802*c217d954SCole Faust                        combine(combine(datasets::SmallConvolutionLayerDataset(),
803*c217d954SCole Faust                                        framework::dataset::make("DataLayout", { DataLayout::NHWC })),
804*c217d954SCole Faust                                framework::dataset::make("ACL Scalar type", { DataType::F32 })))
805*c217d954SCole Faust {
806*c217d954SCole Faust     // Validate output
807*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
808*c217d954SCole Faust }
809*c217d954SCole Faust #endif // ARM_COMPUTE_ENABLE_BF16
810*c217d954SCole Faust 
811*c217d954SCole Faust TEST_SUITE_END() // ExperimentalCpuAPIVariableWeightWithFixtures
812*c217d954SCole Faust 
813*c217d954SCole Faust TEST_SUITE(ExperimentalNEAPIVariableWeightWithFixtures)
814*c217d954SCole Faust 
815*c217d954SCole Faust template <typename ScalarType>
816*c217d954SCole Faust using NEGEMMVarWidth = VariableWeightsFixtureNEInterface<NEGEMMConvolutionLayer, Tensor, Accessor, ScalarType, /*enable_fast_math*/ false>;
817*c217d954SCole Faust 
818*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(NEGEMMRunSmallFloat, NEGEMMVarWidth<float>, framework::DatasetMode::ALL,
819*c217d954SCole Faust                        combine(combine(datasets::SmallConvolutionLayerDataset(),
820*c217d954SCole Faust                                        framework::dataset::make("DataLayout", { DataLayout::NHWC })),
821*c217d954SCole Faust                                framework::dataset::make("ACL Scalar type", { DataType::F32 })))
822*c217d954SCole Faust {
823*c217d954SCole Faust     // Validate output
824*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
825*c217d954SCole Faust }
826*c217d954SCole Faust 
827*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(NEGEMMRunSmallHalf, NEGEMMVarWidth<half>, framework::DatasetMode::ALL,
828*c217d954SCole Faust                        combine(combine(datasets::SmallConvolutionLayerDataset(),
829*c217d954SCole Faust                                        framework::dataset::make("DataLayout", { DataLayout::NHWC })),
830*c217d954SCole Faust                                framework::dataset::make("ACL Scalar type", { DataType::F16 })))
831*c217d954SCole Faust {
832*c217d954SCole Faust     // Validate output
833*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f16, 0.f, half(abs_tolerance_f16));
834*c217d954SCole Faust }
835*c217d954SCole Faust 
836*c217d954SCole Faust #if defined(ARM_COMPUTE_ENABLE_BF16)
837*c217d954SCole Faust template <typename ScalarType>
838*c217d954SCole Faust using NEGEMMVarWidthFastMath = VariableWeightsFixtureNEInterface<NEGEMMConvolutionLayer, Tensor, Accessor, ScalarType, /*enable_fast_math*/ true>;
839*c217d954SCole Faust 
840*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(NEGEMMRunSmallFloatFastMath, NEGEMMVarWidthFastMath<float>, framework::DatasetMode::ALL,
841*c217d954SCole Faust                        combine(combine(datasets::SmallConvolutionLayerDataset(),
842*c217d954SCole Faust                                        framework::dataset::make("DataLayout", { DataLayout::NHWC })),
843*c217d954SCole Faust                                framework::dataset::make("ACL Scalar type", { DataType::F32 })))
844*c217d954SCole Faust {
845*c217d954SCole Faust     // Validate output
846*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
847*c217d954SCole Faust }
848*c217d954SCole Faust #endif // ARM_COMPUTE_ENABLE_BF16
849*c217d954SCole Faust 
850*c217d954SCole Faust TEST_SUITE_END() // ExperimentalNEAPIVariableWeightWithFixtures
851*c217d954SCole Faust TEST_SUITE_END() // FIXED_FORMAT_KERNELS
852*c217d954SCole Faust 
853*c217d954SCole Faust #endif // ARM_COMPUTE_ENABLE_FIXED_FORMAT_KERNELS
854*c217d954SCole Faust 
855*c217d954SCole Faust TEST_SUITE(GEMMConvolutionLayer)
856*c217d954SCole Faust template <typename T>
857*c217d954SCole Faust using NEGEMMConvolutionLayerFixture = ConvolutionValidationFixture<Tensor, Accessor, NEConvolutionLayer, T>;
858*c217d954SCole Faust template <typename T>
859*c217d954SCole Faust using NEGEMMConvolutionLayerMixedDataLayoutFixture = ConvolutionValidationFixture<Tensor, Accessor, NEConvolutionLayer, T, true>;
860*c217d954SCole Faust 
861*c217d954SCole Faust /** Test case for memory injection in @ref cpu::CpuGemmConv2d.
862*c217d954SCole Faust  *
863*c217d954SCole Faust  * Configure the operator once and inject memory at run-time in multiple executions.
864*c217d954SCole Faust  *
865*c217d954SCole Faust  * Checks performed in order:
866*c217d954SCole Faust  * - Both runs compute the same output
867*c217d954SCole Faust  */
TEST_CASE(MemoryInjection,framework::DatasetMode::ALL)868*c217d954SCole Faust TEST_CASE(MemoryInjection, framework::DatasetMode::ALL)
869*c217d954SCole Faust {
870*c217d954SCole Faust     auto        conv        = std::make_unique<cpu::CpuGemmConv2d>();
871*c217d954SCole Faust     const auto  src_info    = TensorInfo(TensorShape(1U, 5U, 2U), 1, DataType::F32, DataLayout::NCHW);
872*c217d954SCole Faust     const auto  weight_info = TensorInfo(TensorShape(1U, 3U, 2U, 3U), 1, DataType::F32, DataLayout::NCHW);
873*c217d954SCole Faust     const auto  bias_info   = TensorInfo(TensorShape(3U), 1, DataType::F32, DataLayout::NCHW);
874*c217d954SCole Faust     auto        dst_info    = TensorInfo(TensorShape(1U, 7U, 3U), 1, DataType::F32, DataLayout::NCHW);
875*c217d954SCole Faust     const auto  conv_info   = PadStrideInfo(1, 1, 0, 0, 2, 2, DimensionRoundingType::FLOOR);
876*c217d954SCole Faust     WeightsInfo weights_info(false, 3U, 3U, 1U);
877*c217d954SCole Faust     conv->configure(&src_info, &weight_info, &bias_info, &dst_info, conv_info, weights_info);
878*c217d954SCole Faust 
879*c217d954SCole Faust     // tensors are newly created every call of this lambda function
880*c217d954SCole Faust     auto src    = create_tensor<Tensor>(src_info);
881*c217d954SCole Faust     auto weight = create_tensor<Tensor>(weight_info);
882*c217d954SCole Faust     auto bias   = create_tensor<Tensor>(bias_info);
883*c217d954SCole Faust     src.allocator()->allocate();
884*c217d954SCole Faust     weight.allocator()->allocate();
885*c217d954SCole Faust     bias.allocator()->allocate();
886*c217d954SCole Faust 
887*c217d954SCole Faust     ITensorPack run_pack{ { TensorType::ACL_SRC_0, &src }, { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
888*c217d954SCole Faust     ITensorPack prep_pack{ { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
889*c217d954SCole Faust 
890*c217d954SCole Faust     auto mg = MemoryGroup{};
891*c217d954SCole Faust     auto ws = manage_workspace<Tensor>(conv->workspace(), mg, run_pack, prep_pack);
892*c217d954SCole Faust 
893*c217d954SCole Faust     auto run_conv = [&]() -> Tensor
894*c217d954SCole Faust     {
895*c217d954SCole Faust         auto dst = create_tensor<Tensor>(dst_info);
896*c217d954SCole Faust         dst.allocator()->allocate();
897*c217d954SCole Faust         run_pack.add_tensor(TensorType::ACL_DST, &dst);
898*c217d954SCole Faust 
899*c217d954SCole Faust         library->fill_tensor_value(Accessor(src), 1.f);
900*c217d954SCole Faust         library->fill_tensor_value(Accessor(weight), 2.f);
901*c217d954SCole Faust         library->fill_tensor_value(Accessor(bias), 3.f);
902*c217d954SCole Faust         // This operator is configured once and captured by this lambda.
903*c217d954SCole Faust         conv->prepare(prep_pack);
904*c217d954SCole Faust         conv->run(run_pack);
905*c217d954SCole Faust         return dst;
906*c217d954SCole Faust     };
907*c217d954SCole Faust     auto result_0 = run_conv();
908*c217d954SCole Faust     auto result_1 = run_conv();
909*c217d954SCole Faust     for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
910*c217d954SCole Faust     {
911*c217d954SCole Faust         ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
912*c217d954SCole Faust     }
913*c217d954SCole Faust }
914*c217d954SCole Faust 
915*c217d954SCole Faust /** Test case for memory injection in @ref NEGEMMConvolutionLayer.
916*c217d954SCole Faust  *
917*c217d954SCole Faust  * Make sure @ref NEGEMMConvolutionLayer still works through injecting the memory at configure time using the old API.
918*c217d954SCole Faust  *
919*c217d954SCole Faust  * Checks performed in order:
920*c217d954SCole Faust  * - Both runs compute the same output
921*c217d954SCole Faust  */
TEST_CASE(MultipleExecutionWithConfigure,framework::DatasetMode::ALL)922*c217d954SCole Faust TEST_CASE(MultipleExecutionWithConfigure, framework::DatasetMode::ALL)
923*c217d954SCole Faust {
924*c217d954SCole Faust     auto        conv        = std::make_unique<NEGEMMConvolutionLayer>();
925*c217d954SCole Faust     const auto  src_info    = TensorInfo(TensorShape(1U, 5U, 2U), 1, DataType::F32, DataLayout::NCHW);
926*c217d954SCole Faust     const auto  weight_info = TensorInfo(TensorShape(1U, 3U, 2U, 3U), 1, DataType::F32, DataLayout::NCHW);
927*c217d954SCole Faust     const auto  bias_info   = TensorInfo(TensorShape(3U), 1, DataType::F32, DataLayout::NCHW);
928*c217d954SCole Faust     auto        dst_info    = TensorInfo(TensorShape(1U, 7U, 3U), 1, DataType::F32, DataLayout::NCHW);
929*c217d954SCole Faust     const auto  conv_info   = PadStrideInfo(1, 1, 0, 0, 2, 2, DimensionRoundingType::FLOOR);
930*c217d954SCole Faust     WeightsInfo weights_info(false, 3U, 3U, 1U);
931*c217d954SCole Faust     auto        run_conv = [&]()
932*c217d954SCole Faust     {
933*c217d954SCole Faust         auto src    = create_tensor<Tensor>(src_info);
934*c217d954SCole Faust         auto weight = create_tensor<Tensor>(weight_info);
935*c217d954SCole Faust         auto bias   = create_tensor<Tensor>(bias_info);
936*c217d954SCole Faust         auto dst    = create_tensor<Tensor>(dst_info);
937*c217d954SCole Faust         conv->configure(&src, &weight, &bias, &dst, conv_info, weights_info);
938*c217d954SCole Faust         src.allocator()->allocate();
939*c217d954SCole Faust         weight.allocator()->allocate();
940*c217d954SCole Faust         bias.allocator()->allocate();
941*c217d954SCole Faust         dst.allocator()->allocate();
942*c217d954SCole Faust         library->fill_tensor_value(Accessor(src), 1.f);
943*c217d954SCole Faust         library->fill_tensor_value(Accessor(weight), 2.f);
944*c217d954SCole Faust         library->fill_tensor_value(Accessor(bias), 3.f);
945*c217d954SCole Faust         conv->run();
946*c217d954SCole Faust         return dst;
947*c217d954SCole Faust     };
948*c217d954SCole Faust     auto result_0 = run_conv();
949*c217d954SCole Faust     auto result_1 = run_conv();
950*c217d954SCole Faust     for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
951*c217d954SCole Faust     {
952*c217d954SCole Faust         ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
953*c217d954SCole Faust     }
954*c217d954SCole Faust }
955*c217d954SCole Faust 
956*c217d954SCole Faust TEST_SUITE(Float)
957*c217d954SCole Faust #if defined(ARM_COMPUTE_ENABLE_BF16)
TEST_SUITE(BFLOAT16)958*c217d954SCole Faust TEST_SUITE(BFLOAT16)
959*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
960*c217d954SCole Faust                                                                                                                     framework::dataset::make("ReshapeWeights", { true })), framework::dataset::make("DataType", DataType::BFLOAT16)), framework::dataset::make("DataLayout", { DataLayout::NHWC })),
961*c217d954SCole Faust                                                                                                             ActivationFunctionsDataset))
962*c217d954SCole Faust {
963*c217d954SCole Faust     // Validate output
964*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
965*c217d954SCole Faust }
966*c217d954SCole Faust TEST_SUITE_END() // BFLOAT16
967*c217d954SCole Faust #endif           /* defined(ARM_COMPUTE_ENABLE_BF16) */
968*c217d954SCole Faust 
969*c217d954SCole Faust #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
TEST_SUITE(FP16)970*c217d954SCole Faust TEST_SUITE(FP16)
971*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerFixture<half>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
972*c217d954SCole Faust                                                                                                                    framework::dataset::make("ReshapeWeights", { true })), framework::dataset::make("DataType", DataType::F16)), framework::dataset::make("DataLayout", { DataLayout::NCHW })), ActivationFunctionsDataset))
973*c217d954SCole Faust {
974*c217d954SCole Faust     // Validate output
975*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num, abs_tolerance_f16);
976*c217d954SCole Faust }
977*c217d954SCole Faust TEST_SUITE_END() // FP16
978*c217d954SCole Faust #endif           /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
979*c217d954SCole Faust 
TEST_SUITE(FP32)980*c217d954SCole Faust TEST_SUITE(FP32)
981*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
982*c217d954SCole Faust                                                                                                                     framework::dataset::make("ReshapeWeights", { true })), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
983*c217d954SCole Faust                                                                                                             ActivationFunctionsDataset))
984*c217d954SCole Faust {
985*c217d954SCole Faust     // Validate output
986*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
987*c217d954SCole Faust }
988*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, NEGEMMConvolutionLayerMixedDataLayoutFixture<float>, framework::DatasetMode::ALL,
989*c217d954SCole Faust                        combine(combine(combine(combine(combine(combine(combine(combine(combine(
990*c217d954SCole Faust                                                                                            framework::dataset::make("Input", TensorShape(23U, 27U, 5U)),
991*c217d954SCole Faust                                                                                            framework::dataset::make("Weights", TensorShape(3U, 3U, 5U, 2U))),
992*c217d954SCole Faust                                                                                        framework::dataset::make("Bias", TensorShape(2U))),
993*c217d954SCole Faust                                                                                framework::dataset::make("Output", TensorShape(11U, 25U, 2U))),
994*c217d954SCole Faust                                                                        framework::dataset::make("PadStrideInfo", PadStrideInfo(2, 1, 0, 0))),
995*c217d954SCole Faust                                                                framework::dataset::make("Dilation", Size2D(1, 1))),
996*c217d954SCole Faust                                                        framework::dataset::make("ReshapeWeights", { true })),
997*c217d954SCole Faust                                                framework::dataset::make("DataType", DataType::F32)),
998*c217d954SCole Faust                                        framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
999*c217d954SCole Faust                                ActivationFunctionsDataset))
1000*c217d954SCole Faust {
1001*c217d954SCole Faust     // Validate output
1002*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
1003*c217d954SCole Faust }
1004*c217d954SCole Faust TEST_SUITE_END() // FP32
1005*c217d954SCole Faust TEST_SUITE_END() // Float
1006*c217d954SCole Faust 
1007*c217d954SCole Faust template <typename T>
1008*c217d954SCole Faust using NEGEMMConvolutionLayerQuantizedFixture = ConvolutionValidationQuantizedFixture<Tensor, Accessor, NEConvolutionLayer, T>;
1009*c217d954SCole Faust template <typename T>
1010*c217d954SCole Faust using NEGEMMConvolutionLayerQuantizedMixedDataLayoutFixture = ConvolutionValidationQuantizedFixture<Tensor, Accessor, NEConvolutionLayer, T, true>;
1011*c217d954SCole Faust 
1012*c217d954SCole Faust template <typename T>
1013*c217d954SCole Faust using NEGEMMConvolutionLayerQuantizedPerChannelFixture = ConvolutionValidationQuantizedPerChannelFixture<Tensor, Accessor, NEConvolutionLayer, T, int8_t>;
1014*c217d954SCole Faust 
1015*c217d954SCole Faust const auto QuantizedActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
1016*c217d954SCole Faust {
1017*c217d954SCole Faust     ActivationLayerInfo(),
1018*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
1019*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 6.f)
1020*c217d954SCole Faust });
1021*c217d954SCole Faust TEST_SUITE(Quantized)
TEST_SUITE(QASYMM8)1022*c217d954SCole Faust TEST_SUITE(QASYMM8)
1023*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
1024*c217d954SCole Faust                                                                                                                        framework::dataset::make("ReshapeWeights", { true })), framework::dataset::make("DataType", DataType::QASYMM8)), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
1025*c217d954SCole Faust                                                                                                                        framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255.f, 10) })), QuantizedActivationFunctionsDataset))
1026*c217d954SCole Faust {
1027*c217d954SCole Faust     // Validate output
1028*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_qasymm8);
1029*c217d954SCole Faust }
1030*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, NEGEMMConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::ALL,
1031*c217d954SCole Faust                        combine(combine(combine(combine(combine(combine(combine(combine(combine(combine(
1032*c217d954SCole Faust                                                                                                    framework::dataset::make("Input", TensorShape(23U, 27U, 5U)),
1033*c217d954SCole Faust                                                                                                    framework::dataset::make("Weights", TensorShape(3U, 3U, 5U, 2U))),
1034*c217d954SCole Faust                                                                                                framework::dataset::make("Bias", TensorShape(2U))),
1035*c217d954SCole Faust                                                                                        framework::dataset::make("Output", TensorShape(11U, 25U, 2U))),
1036*c217d954SCole Faust                                                                                framework::dataset::make("PadStrideInfo", PadStrideInfo(2, 1, 0, 0))),
1037*c217d954SCole Faust                                                                        framework::dataset::make("Dilation", Size2D(1, 1))),
1038*c217d954SCole Faust                                                                framework::dataset::make("ReshapeWeights", { true })),
1039*c217d954SCole Faust                                                        framework::dataset::make("DataType", DataType::QASYMM8)),
1040*c217d954SCole Faust                                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
1041*c217d954SCole Faust                                        framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255.f, 10) })),
1042*c217d954SCole Faust                                QuantizedActivationFunctionsDataset))
1043*c217d954SCole Faust {
1044*c217d954SCole Faust     // Validate output
1045*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_qasymm8);
1046*c217d954SCole Faust }
1047*c217d954SCole Faust TEST_SUITE_END() // QASYMM8
1048*c217d954SCole Faust 
TEST_SUITE(QASYMM8_SIGNED)1049*c217d954SCole Faust TEST_SUITE(QASYMM8_SIGNED)
1050*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerQuantizedFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
1051*c217d954SCole Faust                                                                                                                       framework::dataset::make("ReshapeWeights", { true })), framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)), framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
1052*c217d954SCole Faust                                                                                                                       framework::dataset::make("QuantizationInfo", { QuantizationInfo(0.01f, -10) })), QuantizedActivationFunctionsDataset))
1053*c217d954SCole Faust {
1054*c217d954SCole Faust     // Validate output
1055*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_qasymm8);
1056*c217d954SCole Faust }
1057*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, NEGEMMConvolutionLayerQuantizedFixture<int8_t>, framework::DatasetMode::ALL,
1058*c217d954SCole Faust                        combine(combine(combine(combine(combine(combine(combine(combine(combine(combine(
1059*c217d954SCole Faust                                                                                                    framework::dataset::make("Input", TensorShape(23U, 27U, 5U)),
1060*c217d954SCole Faust                                                                                                    framework::dataset::make("Weights", TensorShape(3U, 3U, 5U, 2U))),
1061*c217d954SCole Faust                                                                                                framework::dataset::make("Bias", TensorShape(2U))),
1062*c217d954SCole Faust                                                                                        framework::dataset::make("Output", TensorShape(11U, 25U, 2U))),
1063*c217d954SCole Faust                                                                                framework::dataset::make("PadStrideInfo", PadStrideInfo(2, 1, 0, 0))),
1064*c217d954SCole Faust                                                                        framework::dataset::make("Dilation", Size2D(1, 1))),
1065*c217d954SCole Faust                                                                framework::dataset::make("ReshapeWeights", { true })),
1066*c217d954SCole Faust                                                        framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)),
1067*c217d954SCole Faust                                                framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
1068*c217d954SCole Faust                                        framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255.f, 10) })),
1069*c217d954SCole Faust                                QuantizedActivationFunctionsDataset))
1070*c217d954SCole Faust {
1071*c217d954SCole Faust     // Validate output
1072*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_qasymm8);
1073*c217d954SCole Faust }
1074*c217d954SCole Faust TEST_SUITE_END() // QASYMM8_SIGNED
1075*c217d954SCole Faust 
TEST_SUITE(QSYMM8_PER_CHANNEL)1076*c217d954SCole Faust TEST_SUITE(QSYMM8_PER_CHANNEL)
1077*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerQuantizedPerChannelFixture<uint8_t>, framework::DatasetMode::ALL,
1078*c217d954SCole Faust                        combine(combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
1079*c217d954SCole Faust                                                                        framework::dataset::make("ReshapeWeights", { true })),
1080*c217d954SCole Faust                                                                framework::dataset::make("DataType", { DataType::QASYMM8 })),
1081*c217d954SCole Faust                                                        framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
1082*c217d954SCole Faust                                                QuantizationData),
1083*c217d954SCole Faust                                        QuantizedActivationFunctionsDataset),
1084*c217d954SCole Faust                                framework::dataset::make("WeightsDataType", { DataType::QSYMM8_PER_CHANNEL })))
1085*c217d954SCole Faust {
1086*c217d954SCole Faust     // Validate output
1087*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_qasymm8);
1088*c217d954SCole Faust }
1089*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmallSigned, NEGEMMConvolutionLayerQuantizedPerChannelFixture<int8_t>, framework::DatasetMode::ALL,
1090*c217d954SCole Faust                        combine(combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
1091*c217d954SCole Faust                                                                        framework::dataset::make("ReshapeWeights", { true })),
1092*c217d954SCole Faust                                                                framework::dataset::make("DataType", { DataType::QASYMM8_SIGNED })),
1093*c217d954SCole Faust                                                        framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })),
1094*c217d954SCole Faust                                                QuantizationData),
1095*c217d954SCole Faust                                        QuantizedActivationFunctionsDataset),
1096*c217d954SCole Faust                                framework::dataset::make("WeightsDataType", { DataType::QSYMM8_PER_CHANNEL })))
1097*c217d954SCole Faust {
1098*c217d954SCole Faust     // Validate output
1099*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_qasymm8);
1100*c217d954SCole Faust }
1101*c217d954SCole Faust TEST_SUITE_END() // QSYMM8_PER_CHANNEL
1102*c217d954SCole Faust TEST_SUITE_END() // Quantized
1103*c217d954SCole Faust 
1104*c217d954SCole Faust TEST_SUITE_END() // GEMMConvolutionLayer
1105*c217d954SCole Faust 
1106*c217d954SCole Faust TEST_SUITE(DirectGEMMConv2d)
1107*c217d954SCole Faust template <typename T>
1108*c217d954SCole Faust using NEDirectGEMMConv2dLayerFixture = ConvolutionValidationFixture<Tensor, Accessor, NEGEMMConv2d, T>;
1109*c217d954SCole Faust 
1110*c217d954SCole Faust /** Test case for memory injection in @ref cpu::CpuGemmDirectConv2d.
1111*c217d954SCole Faust  *
1112*c217d954SCole Faust  * Configure the operator once and inject memory at run-time in multiple executions.
1113*c217d954SCole Faust  *
1114*c217d954SCole Faust  * Checks performed in order:
1115*c217d954SCole Faust  * - Both runs compute the same output
1116*c217d954SCole Faust  */
TEST_CASE(MemoryInjection,framework::DatasetMode::ALL)1117*c217d954SCole Faust TEST_CASE(MemoryInjection, framework::DatasetMode::ALL)
1118*c217d954SCole Faust {
1119*c217d954SCole Faust     auto       conv        = std::make_unique<cpu::CpuGemmDirectConv2d>();
1120*c217d954SCole Faust     const auto src_info    = TensorInfo(TensorShape(1U, 5U, 2U), 1, DataType::F32, DataLayout::NHWC);
1121*c217d954SCole Faust     const auto weight_info = TensorInfo(TensorShape(1U, 3U, 2U, 3U), 1, DataType::F32, DataLayout::NHWC);
1122*c217d954SCole Faust     const auto bias_info   = TensorInfo(TensorShape(3U), 1, DataType::F32, DataLayout::NHWC);
1123*c217d954SCole Faust     auto       dst_info    = TensorInfo(TensorShape(1U, 7U, 3U), 1, DataType::F32, DataLayout::NHWC);
1124*c217d954SCole Faust     const auto conv_info   = Conv2dInfo{};
1125*c217d954SCole Faust     conv->configure(&src_info, &weight_info, &bias_info, &dst_info, conv_info);
1126*c217d954SCole Faust 
1127*c217d954SCole Faust     // tensors are newly created every call of this lambda function
1128*c217d954SCole Faust     auto src    = create_tensor<Tensor>(src_info);
1129*c217d954SCole Faust     auto weight = create_tensor<Tensor>(weight_info);
1130*c217d954SCole Faust     auto bias   = create_tensor<Tensor>(bias_info);
1131*c217d954SCole Faust     src.allocator()->allocate();
1132*c217d954SCole Faust     weight.allocator()->allocate();
1133*c217d954SCole Faust     bias.allocator()->allocate();
1134*c217d954SCole Faust 
1135*c217d954SCole Faust     ITensorPack run_pack{ { TensorType::ACL_SRC_0, &src }, { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
1136*c217d954SCole Faust     ITensorPack prep_pack{ { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
1137*c217d954SCole Faust 
1138*c217d954SCole Faust     auto mg = MemoryGroup{};
1139*c217d954SCole Faust     auto ws = manage_workspace<Tensor>(conv->workspace(), mg, run_pack, prep_pack);
1140*c217d954SCole Faust 
1141*c217d954SCole Faust     auto run_conv = [&]() -> Tensor
1142*c217d954SCole Faust     {
1143*c217d954SCole Faust         auto dst = create_tensor<Tensor>(dst_info);
1144*c217d954SCole Faust         dst.allocator()->allocate();
1145*c217d954SCole Faust         run_pack.add_tensor(TensorType::ACL_DST, &dst);
1146*c217d954SCole Faust 
1147*c217d954SCole Faust         library->fill_tensor_value(Accessor(src), 1.f);
1148*c217d954SCole Faust         library->fill_tensor_value(Accessor(weight), 2.f);
1149*c217d954SCole Faust         library->fill_tensor_value(Accessor(bias), 3.f);
1150*c217d954SCole Faust         // This operator is configured once and captured by this lambda.
1151*c217d954SCole Faust         conv->prepare(prep_pack);
1152*c217d954SCole Faust         conv->run(run_pack);
1153*c217d954SCole Faust         return dst;
1154*c217d954SCole Faust     };
1155*c217d954SCole Faust     auto result_0 = run_conv();
1156*c217d954SCole Faust     auto result_1 = run_conv();
1157*c217d954SCole Faust     for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
1158*c217d954SCole Faust     {
1159*c217d954SCole Faust         ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
1160*c217d954SCole Faust     }
1161*c217d954SCole Faust }
1162*c217d954SCole Faust 
1163*c217d954SCole Faust /** Test case for memory injection in @ref NEGEMMConv2d.
1164*c217d954SCole Faust  *
1165*c217d954SCole Faust  * Make sure @ref NEGEMMConv2d still works through injecting the memory at configure time using the old API.
1166*c217d954SCole Faust  *
1167*c217d954SCole Faust  * Checks performed in order:
1168*c217d954SCole Faust  * - Both runs compute the same output
1169*c217d954SCole Faust  */
TEST_CASE(MultipleExecutionWithConfigure,framework::DatasetMode::ALL)1170*c217d954SCole Faust TEST_CASE(MultipleExecutionWithConfigure, framework::DatasetMode::ALL)
1171*c217d954SCole Faust {
1172*c217d954SCole Faust     auto       conv        = std::make_unique<NEGEMMConv2d>();
1173*c217d954SCole Faust     const auto src_info    = TensorInfo(TensorShape(1U, 5U, 2U), 1, DataType::F32, DataLayout::NHWC);
1174*c217d954SCole Faust     const auto weight_info = TensorInfo(TensorShape(1U, 3U, 2U, 3U), 1, DataType::F32, DataLayout::NHWC);
1175*c217d954SCole Faust     const auto bias_info   = TensorInfo(TensorShape(3U), 1, DataType::F32, DataLayout::NHWC);
1176*c217d954SCole Faust     auto       dst_info    = TensorInfo(TensorShape(1U, 7U, 3U), 1, DataType::F32, DataLayout::NHWC);
1177*c217d954SCole Faust     const auto conv_info   = Conv2dInfo{};
1178*c217d954SCole Faust     auto       run_conv    = [&]()
1179*c217d954SCole Faust     {
1180*c217d954SCole Faust         auto src    = create_tensor<Tensor>(src_info);
1181*c217d954SCole Faust         auto weight = create_tensor<Tensor>(weight_info);
1182*c217d954SCole Faust         auto bias   = create_tensor<Tensor>(bias_info);
1183*c217d954SCole Faust         auto dst    = create_tensor<Tensor>(dst_info);
1184*c217d954SCole Faust         conv->configure(&src, &weight, &bias, &dst, conv_info);
1185*c217d954SCole Faust         src.allocator()->allocate();
1186*c217d954SCole Faust         weight.allocator()->allocate();
1187*c217d954SCole Faust         bias.allocator()->allocate();
1188*c217d954SCole Faust         dst.allocator()->allocate();
1189*c217d954SCole Faust         library->fill_tensor_value(Accessor(src), 1.f);
1190*c217d954SCole Faust         library->fill_tensor_value(Accessor(weight), 2.f);
1191*c217d954SCole Faust         library->fill_tensor_value(Accessor(bias), 3.f);
1192*c217d954SCole Faust         conv->run();
1193*c217d954SCole Faust         return dst;
1194*c217d954SCole Faust     };
1195*c217d954SCole Faust     auto result_0 = run_conv();
1196*c217d954SCole Faust     auto result_1 = run_conv();
1197*c217d954SCole Faust     for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
1198*c217d954SCole Faust     {
1199*c217d954SCole Faust         ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
1200*c217d954SCole Faust     }
1201*c217d954SCole Faust }
1202*c217d954SCole Faust 
1203*c217d954SCole Faust TEST_SUITE(Float)
TEST_SUITE(FP32)1204*c217d954SCole Faust TEST_SUITE(FP32)
1205*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEDirectGEMMConv2dLayerFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
1206*c217d954SCole Faust                                                                                                                      framework::dataset::make("ReshapeWeights", { true })), framework::dataset::make("DataType", DataType::F32)), framework::dataset::make("DataLayout", { DataLayout::NHWC })), ActivationFunctionsDataset))
1207*c217d954SCole Faust {
1208*c217d954SCole Faust     // Validate output
1209*c217d954SCole Faust     validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
1210*c217d954SCole Faust }
1211*c217d954SCole Faust TEST_SUITE_END() // FP32
1212*c217d954SCole Faust TEST_SUITE_END() // Float
1213*c217d954SCole Faust 
1214*c217d954SCole Faust #ifdef __aarch64__
1215*c217d954SCole Faust template <typename T>
1216*c217d954SCole Faust using NEDirectGEMMConv2dLayerQuantizedFixture = ConvolutionValidationQuantizedFixture<Tensor, Accessor, NEGEMMConv2d, T>;
1217*c217d954SCole Faust 
1218*c217d954SCole Faust template <typename T>
1219*c217d954SCole Faust using NEDirectGEMMConv2dLayerQuantizedPerChannelFixture = ConvolutionValidationQuantizedPerChannelFixture<Tensor, Accessor, NEGEMMConv2d, T, int8_t>;
1220*c217d954SCole Faust 
1221*c217d954SCole Faust const auto QuantizedActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
1222*c217d954SCole Faust {
1223*c217d954SCole Faust     ActivationLayerInfo(),
1224*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
1225*c217d954SCole Faust     ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 6.f)
1226*c217d954SCole Faust });
1227*c217d954SCole Faust TEST_SUITE(Quantized)
TEST_SUITE(QASYMM8)1228*c217d954SCole Faust TEST_SUITE(QASYMM8)
1229*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEDirectGEMMConv2dLayerQuantizedFixture<uint8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
1230*c217d954SCole Faust                                                                                                                         framework::dataset::make("ReshapeWeights", { true })), framework::dataset::make("DataType", DataType::QASYMM8)), framework::dataset::make("DataLayout", { DataLayout::NHWC })),
1231*c217d954SCole Faust                                                                                                                         framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255.f, 10) })), QuantizedActivationFunctionsDataset))
1232*c217d954SCole Faust {
1233*c217d954SCole Faust     // Validate output
1234*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_qasymm8);
1235*c217d954SCole Faust }
1236*c217d954SCole Faust TEST_SUITE_END() // QASYMM8
1237*c217d954SCole Faust 
TEST_SUITE(QASYMM8_SIGNED)1238*c217d954SCole Faust TEST_SUITE(QASYMM8_SIGNED)
1239*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmall, NEDirectGEMMConv2dLayerQuantizedFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
1240*c217d954SCole Faust                                                                                                                        framework::dataset::make("ReshapeWeights", { true })), framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)), framework::dataset::make("DataLayout", { DataLayout::NHWC })),
1241*c217d954SCole Faust                                                                                                                        framework::dataset::make("QuantizationInfo", { QuantizationInfo(0.01f, -10) })), QuantizedActivationFunctionsDataset))
1242*c217d954SCole Faust {
1243*c217d954SCole Faust     // Validate output
1244*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_qasymm8);
1245*c217d954SCole Faust }
1246*c217d954SCole Faust TEST_SUITE_END() // QASYMM8_SIGNED
1247*c217d954SCole Faust 
TEST_SUITE(QSYMM8_PER_CHANNEL)1248*c217d954SCole Faust TEST_SUITE(QSYMM8_PER_CHANNEL)
1249*c217d954SCole Faust FIXTURE_DATA_TEST_CASE(RunSmallSigned, NEDirectGEMMConv2dLayerQuantizedPerChannelFixture<int8_t>, framework::DatasetMode::ALL,
1250*c217d954SCole Faust                        combine(combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
1251*c217d954SCole Faust                                                                        framework::dataset::make("ReshapeWeights", { true })),
1252*c217d954SCole Faust                                                                framework::dataset::make("DataType", { DataType::QASYMM8_SIGNED })),
1253*c217d954SCole Faust                                                        framework::dataset::make("DataLayout", { DataLayout::NHWC })),
1254*c217d954SCole Faust                                                QuantizationData),
1255*c217d954SCole Faust                                        QuantizedActivationFunctionsDataset),
1256*c217d954SCole Faust                                framework::dataset::make("WeightsDataType", { DataType::QSYMM8_PER_CHANNEL })))
1257*c217d954SCole Faust {
1258*c217d954SCole Faust     // Validate output
1259*c217d954SCole Faust     validate(Accessor(_target), _reference, tolerance_qasymm8);
1260*c217d954SCole Faust }
1261*c217d954SCole Faust TEST_SUITE_END() // QSYMM8_PER_CHANNEL
1262*c217d954SCole Faust TEST_SUITE_END() // Quantized
1263*c217d954SCole Faust #endif           // __aarch64__
1264*c217d954SCole Faust 
1265*c217d954SCole Faust TEST_SUITE_END() // DirectGEMMConv2d
1266*c217d954SCole Faust 
1267*c217d954SCole Faust TEST_SUITE_END() // Neon
1268*c217d954SCole Faust } // namespace validation
1269*c217d954SCole Faust } // namespace test
1270*c217d954SCole Faust } // namespace arm_compute
1271