1 /*
2 * Copyright (c) 2017-2023 Arm Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24 #include "arm_compute/core/Types.h"
25 #include "arm_compute/runtime/CL/CLTensor.h"
26 #include "arm_compute/runtime/CL/CLTensorAllocator.h"
27 #include "arm_compute/runtime/CL/functions/CLDirectConvolutionLayer.h"
28 #include "tests/CL/CLAccessor.h"
29 #include "tests/PaddingCalculator.h"
30 #include "tests/datasets/DirectConvolutionLayerDataset.h"
31 #include "tests/datasets/ShapeDatasets.h"
32 #include "tests/framework/Asserts.h"
33 #include "tests/framework/Macros.h"
34 #include "tests/framework/datasets/Datasets.h"
35 #include "tests/validation/Validation.h"
36 #include "tests/validation/fixtures/DirectConvolutionLayerFixture.h"
37
38 /** Synced with tests/validation/dynamic_fusion/gpu/cl/DirectConv2d.cpp
39 * Please check there for any differences in the coverage
40 */
41 namespace arm_compute
42 {
43 namespace test
44 {
45 namespace validation
46 {
47 namespace
48 {
49 RelativeTolerance<half> tolerance_fp16(half(0.2)); /**< Tolerance for floating point tests */
50 RelativeTolerance<float> tolerance_fp32(0.05f); /**< Tolerance for floating point tests */
51 constexpr float abs_tolerance_f32(0.0001f); /**< Absolute tolerance for FP32 tests*/
52
53 constexpr float tolerance_num = 0.07f; /**< Tolerance number */
54 constexpr AbsoluteTolerance<uint8_t> tolerance_qasymm8(1); /**< Tolerance for quantized tests */
55
56 const auto data_strides = combine(framework::dataset::make("StrideX", 1, 3), framework::dataset::make("StrideY", 1, 3));
57 const auto data_strides_small = combine(framework::dataset::make("StrideX", 1), framework::dataset::make("StrideY", 1));
58 const auto data_ksize_one = combine(framework::dataset::make("PadX", 0, 1), combine(framework::dataset::make("PadY", 0, 1), framework::dataset::make("KernelSize", 1)));
59 const auto data_ksize_one_small = combine(framework::dataset::make("PadX", 0), combine(framework::dataset::make("PadY", 0), framework::dataset::make("KernelSize", 1)));
60 const auto data_ksize_three = combine(framework::dataset::make("PadX", 0, 2), combine(framework::dataset::make("PadY", 0, 2), framework::dataset::make("KernelSize", 3)));
61 const auto data_ksize_five = combine(framework::dataset::make("PadX", 0, 3), combine(framework::dataset::make("PadY", 0, 3), framework::dataset::make("KernelSize", 5)));
62 const auto data_ksize_nine = combine(framework::dataset::make("PadX", 0, 3), combine(framework::dataset::make("PadY", 0, 3), framework::dataset::make("KernelSize", 9)));
63 const auto data_ksize_nine_small = combine(framework::dataset::make("PadX", 0, 1), combine(framework::dataset::make("PadY", 0, 1), framework::dataset::make("KernelSize", 9)));
64
65 const auto data_all_kernels = concat(concat(data_ksize_one, data_ksize_three), data_ksize_five);
66
67 const auto data = combine(datasets::SmallDirectConvolutionShapes(), combine(data_strides, data_all_kernels));
68 const auto data9x9 = combine(datasets::SmallDirectConvolutionShapes(), combine(data_strides, data_ksize_nine));
69 const auto data_small = combine(datasets::SmallDirectConvolutionShapes(), combine(data_strides_small, data_ksize_one_small));
70 const auto data_small9x9 = combine(datasets::SmallDirectConvolutionShapes(), combine(data_strides_small, data_ksize_nine_small));
71
72 /** Direct convolution nightly data set. */
73 const auto data_nightly = combine(data, framework::dataset::make("NumKernels", { 1, 4 }));
74 const auto data_nightly_9x9 = combine(data9x9, framework::dataset::make("NumKernels", { 1, 4 }));
75 const auto data_nightly_usecase = combine(framework::dataset::make("InputShape", { TensorShape{ 3U, 800U, 800U } }),
76 combine(framework::dataset::make("StrideX", { 1 }),
77 combine(framework::dataset::make("StrideY", { 1 }),
78 combine(framework::dataset::make("PadX", { 4 }),
79 combine(framework::dataset::make("PadY", { 4 }),
80 combine(framework::dataset::make("KernelSize", 9),
81 framework::dataset::make("NumKernels", { 16 })))))));
82
83 /** Direct convolution precommit data set. */
84 const auto data_precommit = combine(data_small, framework::dataset::make("NumKernels", { 1 }));
85 const auto data_precommit_9x9 = combine(data_small9x9, framework::dataset::make("NumKernels", { 1 }));
86
87 /** Activation function Dataset*/
88 const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
89 { ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 0.5f) });
90 } // namespace
91
92 TEST_SUITE(CL)
TEST_SUITE(DirectConvolutionLayer)93 TEST_SUITE(DirectConvolutionLayer)
94
95 /** Check whether the configuration of a Direct Convolution layer with no
96 * bias leads to a successful execution.
97 */
98 TEST_CASE(NoBias, framework::DatasetMode::PRECOMMIT)
99 {
100 const auto src_shape = TensorShape(27U, 13U, 2U);
101 const auto weights_shape = TensorShape(3U, 3U, 2U, 4U);
102 const auto bias_shape = TensorShape(4U);
103 const auto dst_shape = TensorShape(25U, 11U, 4U);
104 constexpr auto dt = DataType::F32;
105
106 auto src = create_tensor<CLTensor>(src_shape, dt);
107 auto weights = create_tensor<CLTensor>(weights_shape, dt);
108 auto dst = create_tensor<CLTensor>(dst_shape, dt);
109
110 const auto conv_info = PadStrideInfo(1, 1, 0, 0);
111
112 // Create Direct Convolution function
113 CLDirectConvolutionLayer conv{};
114 conv.configure(&src, &weights, nullptr, &dst, conv_info);
115
116 src.allocator()->allocate();
117 weights.allocator()->allocate();
118 dst.allocator()->allocate();
119
120 library->fill_tensor_value(CLAccessor(src), 1.f);
121 library->fill_tensor_value(CLAccessor(weights), 1.f);
122
123 conv.run();
124
125 // Compute reference to compare
126 SimpleTensor<float> ref_src{ src_shape, dt };
127 SimpleTensor<float> ref_weights{ weights_shape, dt };
128 SimpleTensor<float> ref_bias{ bias_shape, dt };
129 library->fill_tensor_value(ref_src, 1.f);
130 library->fill_tensor_value(ref_weights, 1.f);
131 // No bias
132 library->fill_tensor_value(ref_bias, 0.f);
133 auto ref_dst = reference::convolution_layer<float>(ref_src, ref_weights, ref_bias, dst_shape, conv_info);
134
135 validate(CLAccessor(dst), ref_dst);
136 }
137
138 /** Check whether the case of rectangle kernels i.e. when width and height of the weight_shape are not equal
139 * would lead to successful run
140 */
TEST_CASE(NonSquareKernel,framework::DatasetMode::PRECOMMIT)141 TEST_CASE(NonSquareKernel, framework::DatasetMode::PRECOMMIT)
142 {
143 auto src_shape = TensorShape(33U, 27U, 3U);
144 auto weights_shape = TensorShape(5U, 7U, 3U, 4U); // non-square kernel
145 const auto bias_shape = TensorShape(4U);
146 auto dst_shape = TensorShape(11U, 12U, 4U);
147 constexpr auto dt = DataType::F32;
148
149 TensorShape src_shape_nhwc(src_shape);
150 TensorShape weights_shape_nhwc(weights_shape);
151 TensorShape dst_shape_nhwc(dst_shape);
152
153 // Non-square shapes are only allowed for NHWC
154 permute(src_shape_nhwc, PermutationVector(2U, 0U, 1U));
155 permute(weights_shape_nhwc, PermutationVector(2U, 0U, 1U));
156 permute(dst_shape_nhwc, PermutationVector(2U, 0U, 1U));
157
158 auto src = create_tensor<CLTensor>(src_shape_nhwc, dt, 1, QuantizationInfo(), DataLayout::NHWC);
159 auto weights = create_tensor<CLTensor>(weights_shape_nhwc, dt, 1, QuantizationInfo(), DataLayout::NHWC);
160 auto dst = create_tensor<CLTensor>(dst_shape_nhwc, dt, 1, QuantizationInfo(), DataLayout::NHWC);
161 const auto conv_info = PadStrideInfo(3, 2, 1, 1, 2, 0, DimensionRoundingType::FLOOR);
162
163 // Create direct convolution function
164 CLDirectConvolutionLayer conv{};
165 conv.configure(&src, &weights, nullptr, &dst, conv_info);
166
167 src.allocator()->allocate();
168 weights.allocator()->allocate();
169 dst.allocator()->allocate();
170
171 library->fill_tensor_value(CLAccessor(src), 1.f);
172 library->fill_tensor_value(CLAccessor(weights), 1.f);
173
174 conv.run();
175
176 // Compute reference to compare
177 SimpleTensor<float> ref_src{ src_shape, dt };
178 SimpleTensor<float> ref_weights{ weights_shape, dt };
179 SimpleTensor<float> ref_bias{ bias_shape, dt };
180 library->fill_tensor_value(ref_src, 1.f);
181 library->fill_tensor_value(ref_weights, 1.f);
182 // No bias
183 library->fill_tensor_value(ref_bias, 0.f);
184 auto ref_dst = reference::convolution_layer<float>(ref_src, ref_weights, ref_bias, dst_shape, conv_info);
185
186 validate(CLAccessor(dst), ref_dst);
187 }
188 // *INDENT-OFF*
189 // clang-format off
190 DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(
191 framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid: Mismatching data type input/weights
192 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid: Mismatching input feature maps
193 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid weights dimensions
194 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Unsupported biases size
195 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Unsupported biases dimensions
196 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), // Invalid output size
197 TensorInfo(TensorShape(32U, 16U, 2U), 1, DataType::F32),
198 }),
199 framework::dataset::make("WeightsInfo",{ TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F16),
200 TensorInfo(TensorShape(3U, 3U, 3U, 4U), 1, DataType::F32),
201 TensorInfo(TensorShape(3U, 3U, 2U, 4U, 3U), 1, DataType::F32),
202 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
203 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
204 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32),
205 TensorInfo(TensorShape(1U, 1U, 2U, 4U), 1, DataType::F32),
206 })),
207 framework::dataset::make("BiasesInfo",{ TensorInfo(TensorShape(4U), 1, DataType::F32),
208 TensorInfo(TensorShape(4U), 1, DataType::F32),
209 TensorInfo(TensorShape(4U), 1, DataType::F32),
210 TensorInfo(TensorShape(3U), 1, DataType::F32),
211 TensorInfo(TensorShape(4U, 2U), 1, DataType::F32),
212 TensorInfo(TensorShape(4U), 1, DataType::F32),
213 TensorInfo(TensorShape(4U), 1, DataType::F32),
214 })),
215 framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
216 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
217 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
218 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
219 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32),
220 TensorInfo(TensorShape(26U, 11U, 4U), 1, DataType::F32),
221 TensorInfo(TensorShape(32U, 16U, 4U), 1, DataType::F32),
222 })),
223 framework::dataset::make("ConvInfo", { PadStrideInfo(1, 1, 0, 0),
224 PadStrideInfo(1, 1, 0, 0),
225 PadStrideInfo(1, 1, 0, 0),
226 PadStrideInfo(1, 1, 0, 0),
227 PadStrideInfo(1, 1, 0, 0),
228 PadStrideInfo(1, 1, 0, 0),
229 PadStrideInfo(1, 1, 0, 0),
230 })),
231 framework::dataset::make("ActivationInfo",
232 {
233 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
234 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
235 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
236 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
237 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
238 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
239 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)
240 })),
241 framework::dataset::make("Expected", { false, false, false, false, false, false, true })),
242 input_info, weights_info, biases_info, output_info, conv_info, act_info, expected)
243 {
244 bool is_valid = bool(CLDirectConvolutionLayer::validate(&input_info.clone()->set_is_resizable(false), &weights_info.clone()->set_is_resizable(false), &biases_info.clone()->set_is_resizable(false), &output_info.clone()->set_is_resizable(false), conv_info, act_info));
245 ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS);
246 }
247 // clang-format on
248 // *INDENT-ON*
249
250 template <typename T>
251 using CLDirectConvolutionLayerFixture = DirectConvolutionValidationFixture<CLTensor, CLAccessor, CLDirectConvolutionLayer, T>;
252 template <typename T>
253 using CLDirectConvolutionLayerMixedDataLayoutFixture = DirectConvolutionValidationFixture<CLTensor, CLAccessor, CLDirectConvolutionLayer, T, true>;
254 template <typename T>
255 using CLDirectConvolutionValidationWithTensorShapesFixture = DirectConvolutionValidationWithTensorShapesFixture<CLTensor, CLAccessor, CLDirectConvolutionLayer, T>;
256 template <typename T>
257 using CLDirectConvolutionLayerQuantizedFixture = DirectConvolutionValidationQuantizedFixture<CLTensor, CLAccessor, CLDirectConvolutionLayer, T>;
258 template <typename T>
259 using CLDirectConvolutionLayerQuantizedMixedDataLayoutFixture = DirectConvolutionValidationQuantizedFixture<CLTensor, CLAccessor, CLDirectConvolutionLayer, T, true>;
260 template <typename T>
261 using CLDirectConvolutionValidationWithTensorShapesQuantizedFixture = DirectConvolutionValidationWithTensorShapesQuantizedFixture<CLTensor, CLAccessor, CLDirectConvolutionLayer, T>;
262
263 TEST_SUITE(NHWC)
264 // *INDENT-OFF*
265 // clang-format off
266 DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(
267 framework::dataset::make("InputInfo", {
268 TensorInfo(TensorShape(2U, 27U, 13U), 1, DataType::F32, DataLayout::NHWC), // Arbitrary weight sizes for NHWC are supported
269 TensorInfo(TensorShape(2U, 27U, 13U), 1, DataType::F32, DataLayout::NHWC), // Non-rectangular weights dimensions for NHWC are supported
270 TensorInfo(TensorShape(2U, 27U, 13U), 1, DataType::F32, DataLayout::NHWC), // Strides > 2 for any kernel sizes for NHWC are supported
271 }),
272 framework::dataset::make("WeightsInfo",{
273 TensorInfo(TensorShape(2U, 13U, 13U, 4U), 1, DataType::F32, DataLayout::NHWC),
274 TensorInfo(TensorShape(2U, 5U, 3U, 4U), 1, DataType::F32, DataLayout::NHWC),
275 TensorInfo(TensorShape(2U, 3U, 3U, 4U), 1, DataType::F32, DataLayout::NHWC),
276 })),
277 framework::dataset::make("BiasesInfo",{
278 TensorInfo(TensorShape(4U), 1, DataType::F32, DataLayout::NHWC),
279 TensorInfo(TensorShape(4U), 1, DataType::F32, DataLayout::NHWC),
280 TensorInfo(TensorShape(4U), 1, DataType::F32, DataLayout::NHWC),
281 })),
282 framework::dataset::make("OutputInfo",{
283 TensorInfo(TensorShape(4U, 15U, 1U), 1, DataType::F32, DataLayout::NHWC),
284 TensorInfo(TensorShape(4U, 23U, 11U), 1, DataType::F32, DataLayout::NHWC),
285 TensorInfo(TensorShape(4U, 9U, 4U), 1, DataType::F32, DataLayout::NHWC),
286 })),
287 framework::dataset::make("ConvInfo", {
288 PadStrideInfo(1, 1, 0, 0),
289 PadStrideInfo(1, 1, 0, 0),
290 PadStrideInfo(3, 3, 0, 0),
291 })),
292 framework::dataset::make("ActivationInfo",
293 {
294 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
295 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
296 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
297 })),
298 framework::dataset::make("Expected", { true, true, true })),
299 input_info, weights_info, biases_info, output_info, conv_info, act_info, expected)
300 {
301 bool is_valid = bool(CLDirectConvolutionLayer::validate(&input_info.clone()->set_is_resizable(false), &weights_info.clone()->set_is_resizable(false), &biases_info.clone()->set_is_resizable(false), &output_info.clone()->set_is_resizable(false), conv_info, act_info));
302 ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS);
303 }
304 TEST_SUITE(FP16)
305 FIXTURE_DATA_TEST_CASE(RunSmall, CLDirectConvolutionLayerFixture<half>, framework::DatasetMode::PRECOMMIT,
306 combine(combine(combine(zip(zip(zip(zip(zip(zip(
307 framework::dataset::make("InputShape", { TensorShape(27U, 13U, 23U),
308 TensorShape(19U, 5U, 16U, 4U),
309 TensorShape(13U, 5U, 17U, 2U),
310 TensorShape(32U, 37U, 13U) } ),
311 framework::dataset::make("StrideX", { 1, 3, 1, 1 })),
312 framework::dataset::make("StrideY", { 1, 3, 2, 1 })),
313 framework::dataset::make("PadX", { 1, 3, 0, 4 })),
314 framework::dataset::make("PadY", { 1, 3, 0, 4 })),
315 framework::dataset::make("KernelSize", { 3, 8, 1, 9 })),
316 framework::dataset::make("NumKernels", { 17, 3, 1, 19 })),
317 framework::dataset::make("DataType", DataType::F16)),
318 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU) )),
319 framework::dataset::make("DataLayout", DataLayout::NHWC)))
320 {
321 validate(CLAccessor(_target), _reference, tolerance_fp16, tolerance_num);
322 }
323
324 FIXTURE_DATA_TEST_CASE(RunLarge, CLDirectConvolutionLayerFixture<half>, framework::DatasetMode::NIGHTLY,
325 combine(combine(combine(zip(zip(zip(zip(zip(zip(
326 framework::dataset::make("InputShape", { TensorShape(800U, 800U, 3U) } ),
327 framework::dataset::make("StrideX", { 1 })),
328 framework::dataset::make("StrideY", { 1 })),
329 framework::dataset::make("PadX", { 1 })),
330 framework::dataset::make("PadY", { 1 })),
331 framework::dataset::make("KernelSize", { 9 })),
332 framework::dataset::make("NumKernels", { 3 })),
333 framework::dataset::make("DataType", DataType::F16)),
334 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::IDENTITY) )),
335 framework::dataset::make("DataLayout", DataLayout::NHWC)))
336 {
337 validate(CLAccessor(_target), _reference, tolerance_fp16, tolerance_num);
338 }
339
340 TEST_SUITE_END() // FP16
341
TEST_SUITE(FP32)342 TEST_SUITE(FP32)
343 FIXTURE_DATA_TEST_CASE(RunSmall, CLDirectConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
344 combine(combine(combine(zip(zip(zip(zip(zip(zip(
345 framework::dataset::make("InputShape", { TensorShape(27U, 13U, 23U),
346 TensorShape(19U, 5U, 16U, 4U),
347 TensorShape(13U, 5U, 17U, 2U),
348 TensorShape(32U, 37U, 13U) } ),
349 framework::dataset::make("StrideX", { 1, 3, 1, 1 })),
350 framework::dataset::make("StrideY", { 1, 3, 2, 1 })),
351 framework::dataset::make("PadX", { 1, 3, 0, 4 })),
352 framework::dataset::make("PadY", { 1, 3, 0, 4 })),
353 framework::dataset::make("KernelSize", { 3, 8, 1, 9 })),
354 framework::dataset::make("NumKernels", { 17, 3, 1, 19 })),
355 framework::dataset::make("DataType", DataType::F32)),
356 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU) )),
357 framework::dataset::make("DataLayout", DataLayout::NHWC)))
358 {
359 validate(CLAccessor(_target), _reference, tolerance_fp32, 0.0, abs_tolerance_f32);
360 }
361 FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, CLDirectConvolutionLayerMixedDataLayoutFixture<float>, framework::DatasetMode::PRECOMMIT,
362 combine(combine(combine(zip(zip(zip(zip(zip(zip(
363 framework::dataset::make("InputShape", { TensorShape(27U, 13U, 23U),
364 TensorShape(19U, 5U, 16U, 4U),
365 TensorShape(13U, 5U, 17U, 2U),
366 TensorShape(32U, 37U, 13U) } ),
367 framework::dataset::make("StrideX", { 1 })),
368 framework::dataset::make("StrideY", { 2 })),
369 framework::dataset::make("PadX", { 1 })),
370 framework::dataset::make("PadY", { 3 })),
371 framework::dataset::make("KernelSize", { 3 })),
372 framework::dataset::make("NumKernels", { 3 })),
373 framework::dataset::make("DataType", DataType::F32)),
374 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU) )),
375 framework::dataset::make("DataLayout", DataLayout::NHWC)))
376 {
377 validate(CLAccessor(_target), _reference, tolerance_fp32, 0.0, abs_tolerance_f32);
378 }
379 FIXTURE_DATA_TEST_CASE(RunLarge, CLDirectConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY,
380 combine(combine(combine(zip(zip(zip(zip(zip(zip(
381 framework::dataset::make("InputShape", { TensorShape(800U, 800U, 3U) } ),
382 framework::dataset::make("StrideX", { 1 })),
383 framework::dataset::make("StrideY", { 1 })),
384 framework::dataset::make("PadX", { 1 })),
385 framework::dataset::make("PadY", { 1 })),
386 framework::dataset::make("KernelSize", { 9 })),
387 framework::dataset::make("NumKernels", { 3 })),
388 framework::dataset::make("DataType", DataType::F32)),
389 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::IDENTITY) )),
390 framework::dataset::make("DataLayout", DataLayout::NHWC)))
391 {
392 validate(CLAccessor(_target), _reference, tolerance_fp32, 0.0, abs_tolerance_f32);
393 }
394 TEST_SUITE_END() // FP32
395
TEST_SUITE(Quantized)396 TEST_SUITE(Quantized)
397 TEST_SUITE(QASYMM8)
398 FIXTURE_DATA_TEST_CASE(RunSmall, CLDirectConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::PRECOMMIT,
399 combine(combine(combine(combine(zip(zip(zip(zip(zip(zip(
400 framework::dataset::make("InputShape", { TensorShape(27U, 13U, 23U),
401 TensorShape(19U, 5U, 16U, 4U),
402 TensorShape(13U, 5U, 17U, 2U),
403 TensorShape(32U, 37U, 13U) } ),
404 framework::dataset::make("StrideX", { 1, 3, 1, 1 })),
405 framework::dataset::make("StrideY", { 1, 3, 2, 1 })),
406 framework::dataset::make("PadX", { 1, 3, 0, 4 })),
407 framework::dataset::make("PadY", { 1, 3, 0, 4 })),
408 framework::dataset::make("KernelSize", { 3, 8, 1, 9 })),
409 framework::dataset::make("NumKernels", { 7, 3, 1, 3 })),
410 framework::dataset::make("DataType", DataType::QASYMM8)),
411 framework::dataset::make("QuantizationInfo", QuantizationInfo(1.1f / 255, 10))),
412 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU) )),
413 framework::dataset::make("DataLayout", DataLayout::NHWC)))
414 {
415 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
416 }
417 FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, CLDirectConvolutionLayerQuantizedMixedDataLayoutFixture<uint8_t>, framework::DatasetMode::PRECOMMIT,
418 combine(combine(combine(combine(zip(zip(zip(zip(zip(zip(
419 framework::dataset::make("InputShape", { TensorShape(27U, 13U, 23U),
420 TensorShape(19U, 5U, 16U, 4U),
421 TensorShape(13U, 5U, 17U, 2U),
422 TensorShape(32U, 37U, 13U) } ),
423 framework::dataset::make("StrideX", { 1 })),
424 framework::dataset::make("StrideY", { 2 })),
425 framework::dataset::make("PadX", { 1 })),
426 framework::dataset::make("PadY", { 1 })),
427 framework::dataset::make("KernelSize", { 3 })),
428 framework::dataset::make("NumKernels", { 3 })),
429 framework::dataset::make("DataType", DataType::QASYMM8)),
430 framework::dataset::make("QuantizationInfo", QuantizationInfo(1.1f / 255, 10))),
431 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU) )),
432 framework::dataset::make("DataLayout", DataLayout::NHWC)))
433 {
434 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
435 }
436 FIXTURE_DATA_TEST_CASE(RunLarge, CLDirectConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::NIGHTLY,
437 combine(combine(combine(combine(zip(zip(zip(zip(zip(zip(
438 framework::dataset::make("InputShape", { TensorShape(800U, 800U, 3U) } ),
439 framework::dataset::make("StrideX", { 1 })),
440 framework::dataset::make("StrideY", { 1 })),
441 framework::dataset::make("PadX", { 1 })),
442 framework::dataset::make("PadY", { 1 })),
443 framework::dataset::make("KernelSize", { 9 })),
444 framework::dataset::make("NumKernels", { 3 })),
445 framework::dataset::make("DataType", DataType::QASYMM8)),
446 framework::dataset::make("QuantizationInfo", QuantizationInfo(2.f / 255, 10))),
447 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU) )),
448 framework::dataset::make("DataLayout", DataLayout::NHWC)))
449 {
450 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
451 }
452
453 TEST_SUITE_END() // QASYMM8
TEST_SUITE(QASYMM8_SIGNED)454 TEST_SUITE(QASYMM8_SIGNED)
455 FIXTURE_DATA_TEST_CASE(RunSmall, CLDirectConvolutionLayerQuantizedFixture<int8_t>, framework::DatasetMode::PRECOMMIT,
456 combine(combine(combine(combine(zip(zip(zip(zip(zip(zip(
457 framework::dataset::make("InputShape", { TensorShape(27U, 13U, 23U),
458 TensorShape(19U, 5U, 16U, 4U),
459 TensorShape(13U, 5U, 17U, 2U),
460 TensorShape(32U, 37U, 13U) } ),
461 framework::dataset::make("StrideX", { 1, 3, 1, 1 })),
462 framework::dataset::make("StrideY", { 1, 3, 2, 1 })),
463 framework::dataset::make("PadX", { 1, 3, 0, 4 })),
464 framework::dataset::make("PadY", { 1, 3, 0, 4 })),
465 framework::dataset::make("KernelSize", { 3, 8, 1, 9 })),
466 framework::dataset::make("NumKernels", { 7, 3, 1, 3 })),
467 framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)),
468 framework::dataset::make("QuantizationInfo", QuantizationInfo(2.f / 255, 10))),
469 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU) )),
470 framework::dataset::make("DataLayout", DataLayout::NHWC)))
471 {
472 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
473 }
474 FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, CLDirectConvolutionLayerQuantizedMixedDataLayoutFixture<int8_t>, framework::DatasetMode::PRECOMMIT,
475 combine(combine(combine(combine(zip(zip(zip(zip(zip(zip(
476 framework::dataset::make("InputShape", { TensorShape(27U, 13U, 23U),
477 TensorShape(19U, 5U, 16U, 4U),
478 TensorShape(13U, 5U, 17U, 2U),
479 TensorShape(32U, 37U, 13U) } ),
480 framework::dataset::make("StrideX", { 1 })),
481 framework::dataset::make("StrideY", { 1 })),
482 framework::dataset::make("PadX", { 1 })),
483 framework::dataset::make("PadY", { 1 })),
484 framework::dataset::make("KernelSize", { 3 })),
485 framework::dataset::make("NumKernels", { 3 })),
486 framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)),
487 framework::dataset::make("QuantizationInfo", QuantizationInfo(2.f / 255, 10))),
488 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU) )),
489 framework::dataset::make("DataLayout", DataLayout::NHWC)))
490 {
491 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
492 }
493 FIXTURE_DATA_TEST_CASE(RunLarge, CLDirectConvolutionLayerQuantizedFixture<int8_t>, framework::DatasetMode::NIGHTLY,
494 combine(combine(combine(combine(zip(zip(zip(zip(zip(zip(
495 framework::dataset::make("InputShape", { TensorShape(800U, 800U, 3U) } ),
496 framework::dataset::make("StrideX", { 1 })),
497 framework::dataset::make("StrideY", { 1 })),
498 framework::dataset::make("PadX", { 1 })),
499 framework::dataset::make("PadY", { 1 })),
500 framework::dataset::make("KernelSize", { 9 })),
501 framework::dataset::make("NumKernels", { 3 })),
502 framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)),
503 framework::dataset::make("QuantizationInfo", QuantizationInfo(2.f / 255, 10))),
504 framework::dataset::make("ActivationInfo", ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU) )),
505 framework::dataset::make("DataLayout", DataLayout::NHWC)))
506 {
507 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
508 }
509 TEST_SUITE_END() // QASYMM8_SIGNED
TEST_SUITE_END()510 TEST_SUITE_END() // Quantized
511 TEST_SUITE_END() // NHWC
512
513 TEST_SUITE(NCHW)
514 DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(
515 framework::dataset::make("InputInfo", {
516 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, DataLayout::NCHW), // Unsupported kernel width
517 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, DataLayout::NCHW), // Non-rectangular weights dimensions are unsupported
518 TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32, DataLayout::NCHW) // Unsupported stride
519 }),
520 framework::dataset::make("WeightsInfo",{
521 TensorInfo(TensorShape(11U, 11U, 2U, 4U), 1, DataType::F32, DataLayout::NCHW),
522 TensorInfo(TensorShape(5U, 3U, 2U, 4U), 1, DataType::F32, DataLayout::NCHW),
523 TensorInfo(TensorShape(3U, 3U, 2U, 4U), 1, DataType::F32, DataLayout::NCHW)
524 })),
525 framework::dataset::make("BiasesInfo",{
526 TensorInfo(TensorShape(4U), 1, DataType::F32, DataLayout::NCHW),
527 TensorInfo(TensorShape(4U), 1, DataType::F32, DataLayout::NCHW),
528 TensorInfo(TensorShape(4U), 1, DataType::F32, DataLayout::NCHW)
529 })),
530 framework::dataset::make("OutputInfo",{
531 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, DataLayout::NCHW),
532 TensorInfo(TensorShape(23U, 11U, 4U), 1, DataType::F32, DataLayout::NCHW),
533 TensorInfo(TensorShape(25U, 11U, 4U), 1, DataType::F32, DataLayout::NCHW)
534 })),
535 framework::dataset::make("ConvInfo", {
536 PadStrideInfo(1, 1, 0, 0),
537 PadStrideInfo(1, 1, 0, 0),
538 PadStrideInfo(3, 3, 0, 0)
539 })),
540 framework::dataset::make("ActivationInfo",
541 {
542 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
543 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
544 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU)
545 })),
546 framework::dataset::make("Expected", { false, false, false})),
547 input_info, weights_info, biases_info, output_info, conv_info, act_info, expected)
548 {
549 bool is_valid = bool(CLDirectConvolutionLayer::validate(&input_info.clone()->set_is_resizable(false), &weights_info.clone()->set_is_resizable(false), &biases_info.clone()->set_is_resizable(false), &output_info.clone()->set_is_resizable(false), conv_info, act_info));
550 ARM_COMPUTE_EXPECT(is_valid == expected, framework::LogLevel::ERRORS);
551 }
552 // clang-format on
553 // *INDENT-ON*
554
555 TEST_SUITE(Float)
TEST_SUITE(FP16)556 TEST_SUITE(FP16)
557 FIXTURE_DATA_TEST_CASE(RunSmall, CLDirectConvolutionLayerFixture<half>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit, framework::dataset::make("DataType", DataType::F16)),
558 ActivationFunctionsDataset),
559 framework::dataset::make("DataLayout", DataLayout::NCHW)))
560 {
561 // Validate output
562 validate(CLAccessor(_target), _reference, tolerance_fp16, tolerance_num);
563 }
564 FIXTURE_DATA_TEST_CASE(RunLarge, CLDirectConvolutionLayerFixture<half>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_nightly, framework::dataset::make("DataType", DataType::F16)),
565 ActivationFunctionsDataset),
566 framework::dataset::make("DataLayout", DataLayout::NCHW)))
567 {
568 // Validate output
569 validate(CLAccessor(_target), _reference, tolerance_fp16, tolerance_num);
570 }
571 TEST_SUITE_END() // FP16
572
TEST_SUITE(FP32)573 TEST_SUITE(FP32)
574 FIXTURE_DATA_TEST_CASE(RunSmall, CLDirectConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit, framework::dataset::make("DataType",
575 DataType::F32)),
576 ActivationFunctionsDataset),
577 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
578 {
579 validate(CLAccessor(_target), _reference, tolerance_fp32, 0.0, abs_tolerance_f32);
580 }
581 FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, CLDirectConvolutionLayerMixedDataLayoutFixture<float>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(data_precommit,
582 framework::dataset::make("DataType",
583 DataType::F32)),
584 ActivationFunctionsDataset),
585 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
586 {
587 validate(CLAccessor(_target), _reference, tolerance_fp32, 0.0, abs_tolerance_f32);
588 }
589 FIXTURE_DATA_TEST_CASE(RunLarge, CLDirectConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(combine(data_nightly, framework::dataset::make("DataType", DataType::F32)),
590 ActivationFunctionsDataset),
591 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
592 {
593 validate(CLAccessor(_target), _reference, tolerance_fp32, 0.0, abs_tolerance_f32);
594 }
595 TEST_SUITE_END() // FP32
596
TEST_SUITE(FP32_CustomDataset)597 TEST_SUITE(FP32_CustomDataset)
598 FIXTURE_DATA_TEST_CASE(Run, CLDirectConvolutionValidationWithTensorShapesFixture<float>, framework::DatasetMode::NIGHTLY, combine(combine(datasets::DirectConvolutionLayerDataset(),
599 framework::dataset::make("DataType", DataType::F32)),
600 ActivationFunctionsDataset))
601 {
602 // Validate output
603 validate(CLAccessor(_target), _reference, tolerance_fp32, 0.0, abs_tolerance_f32);
604 }
605 TEST_SUITE_END() // FP32_CustomDataset
606 TEST_SUITE_END() // Float
607
608 const auto QuantizedActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
609 {
610 ActivationLayerInfo(),
611 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
612 ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 6.f)
613 });
614 TEST_SUITE(Quantized)
TEST_SUITE(QASYMM8)615 TEST_SUITE(QASYMM8)
616 FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, CLDirectConvolutionLayerQuantizedMixedDataLayoutFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(data_precommit,
617 framework::dataset::make("DataType", DataType::QASYMM8)),
618 framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255, 10) })),
619 QuantizedActivationFunctionsDataset),
620 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
621 {
622 // Validate output
623 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
624 }
625 FIXTURE_DATA_TEST_CASE(RunSmall, CLDirectConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(data_precommit,
626 framework::dataset::make("DataType", DataType::QASYMM8)),
627 framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255, 10), QuantizationInfo(1.1f, 10) })),
628 QuantizedActivationFunctionsDataset),
629 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
630 {
631 // Validate output
632 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
633 }
634 FIXTURE_DATA_TEST_CASE(RunSmall9x9, CLDirectConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(data_precommit_9x9,
635 framework::dataset::make("DataType",
636 DataType::QASYMM8)),
637 framework::dataset::make("QuantizationInfo", { QuantizationInfo(3.f / 255, 10), QuantizationInfo(1.1f, 10) })),
638 QuantizedActivationFunctionsDataset),
639 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
640 {
641 // Validate output
642 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
643 }
644 FIXTURE_DATA_TEST_CASE(RunLarge, CLDirectConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(data_nightly, framework::dataset::make("DataType",
645 DataType::QASYMM8)),
646 framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255, 10), QuantizationInfo(1.1f, 10) })),
647 QuantizedActivationFunctionsDataset),
648 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
649 {
650 // Validate output
651 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
652 }
653 FIXTURE_DATA_TEST_CASE(RunLarge9x9, CLDirectConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(combine(combine(combine(data_nightly_9x9,
654 framework::dataset::make("DataType",
655 DataType::QASYMM8)),
656 framework::dataset::make("QuantizationInfo", { QuantizationInfo(3.f / 255, 10), QuantizationInfo(1.1f, 10) })),
657 QuantizedActivationFunctionsDataset),
658 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
659 {
660 // Validate output
661 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
662 }
663
664 TEST_SUITE_END() // QASYMM8
665
TEST_SUITE(QASYMM8_CustomDataset)666 TEST_SUITE(QASYMM8_CustomDataset)
667 FIXTURE_DATA_TEST_CASE(Run, CLDirectConvolutionValidationWithTensorShapesQuantizedFixture<uint8_t>, framework::DatasetMode::NIGHTLY,
668 combine(combine(combine(combine(datasets::DirectConvolutionLayerDataset(),
669 framework::dataset::make("DataType", DataType::QASYMM8)),
670 framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255, 127), QuantizationInfo(1.1f, 10) })),
671 QuantizedActivationFunctionsDataset),
672 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
673 {
674 // Validate output
675 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
676 }
677 TEST_SUITE_END() // QASYMM8_CustomDataset
678
TEST_SUITE(QASYMM8_SIGNED)679 TEST_SUITE(QASYMM8_SIGNED)
680
681 FIXTURE_DATA_TEST_CASE(RunSmall, CLDirectConvolutionLayerQuantizedFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(data_precommit, framework::dataset::make("DataType",
682 DataType::QASYMM8_SIGNED)),
683 framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255, 10), QuantizationInfo(1.1f, -10) })),
684 QuantizedActivationFunctionsDataset),
685 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
686 {
687 // Validate output
688 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
689 }
690 FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, CLDirectConvolutionLayerQuantizedMixedDataLayoutFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(data_precommit,
691 framework::dataset::make("DataType",
692 DataType::QASYMM8_SIGNED)),
693 framework::dataset::make("QuantizationInfo", { QuantizationInfo(1.1f, -10) })),
694 QuantizedActivationFunctionsDataset),
695 framework::dataset::make("DataLayout", { DataLayout::NCHW, DataLayout::NHWC })))
696 {
697 // Validate output
698 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
699 }
700 FIXTURE_DATA_TEST_CASE(RunSmall9x9, CLDirectConvolutionLayerQuantizedFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(data_precommit_9x9,
701 framework::dataset::make("DataType",
702 DataType::QASYMM8_SIGNED)),
703 framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255, 10), QuantizationInfo(1.1f, 10) })),
704 QuantizedActivationFunctionsDataset),
705 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
706 {
707 // Validate output
708 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
709 }
710
711 FIXTURE_DATA_TEST_CASE(RunCustomDataset, CLDirectConvolutionValidationWithTensorShapesQuantizedFixture<int8_t>, framework::DatasetMode::NIGHTLY,
712 combine(combine(combine(combine(datasets::DirectConvolutionLayerDataset(),
713 framework::dataset::make("DataType", DataType::QASYMM8_SIGNED)),
714 framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255, 127), QuantizationInfo(1.1f, 10) })),
715 QuantizedActivationFunctionsDataset),
716 framework::dataset::make("DataLayout", { DataLayout::NCHW })))
717 {
718 // Validate output
719 validate(CLAccessor(_target), _reference, tolerance_qasymm8);
720 }
721
722 TEST_SUITE_END() // QASYMM8_SIGNED
723 TEST_SUITE_END() // Quantized
724 TEST_SUITE_END() // NCHW
725 TEST_SUITE_END() // DirectConvolutionLayer
726 TEST_SUITE_END() // CL
727
728 } // namespace validation
729 } // namespace test
730 } // namespace arm_compute
731