Compute Library
 23.08
ConvolutionLayer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2021, 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"
31 #include "tests/CL/CLAccessor.h"
33 #include "tests/datasets/LargeConvolutionLayerDataset.h"
34 #include "tests/datasets/SmallConvolutionLayerDataset.h"
35 #include "tests/datasets/TinyConvolutionLayerDataset.h"
37 #include "tests/framework/Macros.h"
40 #include "tests/validation/fixtures/ConvolutionLayerFixture.h"
41 
42 /** Synced with tests/validation/dynamic_fusion/gpu/cl/DirectConv2d.cpp
43  * Please check there for any differences in the coverage
44  */
45 namespace arm_compute
46 {
47 namespace test
48 {
49 namespace validation
50 {
51 namespace
52 {
53 class SmallConvolutionLayerDatasetCases final : public datasets::ConvolutionLayerDataset
54 {
55 public:
56  SmallConvolutionLayerDatasetCases()
57  {
58  // 1D Kernel
59  add_config(TensorShape(1U, 130U, 2000U), TensorShape(1U, 1U, 2000U, 2000U), TensorShape(2000U), TensorShape(1U, 130U, 2000U), PadStrideInfo(1, 1, 0, 0));
60  }
61 };
62 
63 RelativeTolerance<float> tolerance_f32(0.1f); /**< Tolerance value for comparing reference's output against implementation's output for DataType::F32 */
64 RelativeTolerance<half_float::half> tolerance_f16(half_float::half(0.2)); /**< Tolerance value for comparing reference's output against implementation's output for DataType::F16 */
65 constexpr AbsoluteTolerance<float> tolerance_qasymm8(1); /**< Tolerance value for comparing reference's output against implementation's output for quantized data types */
66 constexpr float tolerance_num = 0.07f; /**< Tolerance number */
67 
68 /** CNN data types */
69 const auto CNNDataTypes = framework::dataset::make("DataType",
70 {
75 });
76 
77 /** Grouped CNN data types */
78 const auto GroupedCNNDataTypes = framework::dataset::make("DataType",
79 {
82 });
83 
84 const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
85 {
86  ActivationLayerInfo(),
87  ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
88  ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 0.5f),
89  ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 0.5f)
90 });
91 const auto ActivationFunctionsSmallDataset = framework::dataset::make("ActivationInfo",
92 {
93  ActivationLayerInfo(),
94  ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 0.5f)
95 });
96 
97 bool is_post_op_list_valid_in_gemmconv(const TensorShape &input_shape, const TensorShape &weights_shape, const TensorShape &output_shape, DataType data_type, DataLayout data_layout,
98  const PadStrideInfo &conv_info, const experimental::PostOpList<ITensorInfo *> &post_ops)
99 {
103 
104  const auto dilation = Size2D(1U, 1U);
105  const unsigned int num_groups = 1U;
106 
107  TensorInfo input_info(input_shape, 1, data_type, data_layout);
109 
111 
112  WeightsInfo w_info(false, weights_info.dimension(idx_width), weights_info.dimension(idx_height), weights_info.dimension(idx_kernels));
113 
114  const auto status = CLGEMMConvolutionLayer::validate(&input_info.clone()->set_is_resizable(true),
115  &weights_info.clone()->set_is_resizable(true), nullptr, &output_info.clone()->set_is_resizable(true),
116  conv_info, w_info, dilation, ActivationLayerInfo(), num_groups, post_ops);
117  return bool(status);
118 }
119 } // namespace
120 
121 TEST_SUITE(CL)
122 TEST_SUITE(ConvolutionLayer)
123 
124 // *INDENT-OFF*
125 // clang-format off
126 DATA_TEST_CASE(ValidateConvolutionMethod, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(zip(
127  framework::dataset::make("InputInfo", { TensorInfo(TensorShape(17U, 31U, 2U), 1, DataType::F32), // Select GEMM
128  TensorInfo(TensorShape(17U, 31U, 2U), 1, DataType::F32), // Select GEMM
129  TensorInfo(TensorShape(23U, 27U, 5U, 4U), 1, DataType::F32), // Select GEMM
130  TensorInfo(TensorShape(23U, 27U, 31U, 4U), 1, DataType::F32), // Select WINOGRAD
131  TensorInfo(TensorShape(3U, 3U, 2U, 1U), 1, DataType::F32), // Select GEMM
132  TensorInfo(TensorShape(33U, 27U, 7U, 4U), 1, DataType::F32), // Select GEMM
133  TensorInfo(TensorShape(17U, 31U, 32U), 1, DataType::F32), // Select WINOGRAD
134  TensorInfo(TensorShape(17U, 31U, 2U), 1, DataType::F32), // Select GEMM
135  TensorInfo(TensorShape(17U, 31U, 2U), 1, DataType::QASYMM8_SIGNED), // Select GEMM
136  }),
137  framework::dataset::make("WeightsInfo", { TensorInfo(TensorShape(5U, 5U, 2U, 19U), 1, DataType::F32),
138  TensorInfo(TensorShape(5U, 5U, 2U, 19U), 1, DataType::F32),
139  TensorInfo(TensorShape(3U, 3U, 5U, 21U), 1, DataType::F32),
140  TensorInfo(TensorShape(3U, 3U, 31U, 21U), 1, DataType::F32),
141  TensorInfo(TensorShape(3U, 3U, 5U, 21U), 1, DataType::F32),
142  TensorInfo(TensorShape(5U, 5U, 7U, 16U), 1, DataType::F16),
143  TensorInfo(TensorShape(5U, 5U, 32U, 19U), 1, DataType::F32),
144  TensorInfo(TensorShape(5U, 5U, 2U, 19U), 1, DataType::F32),
145  TensorInfo(TensorShape(5U, 5U, 2U, 19U), 1, DataType::QASYMM8_SIGNED),
146  })),
147  framework::dataset::make("OutputInfo", { TensorInfo(TensorShape(15U, 15U, 19U), 1, DataType::F32),
148  TensorInfo(TensorShape(15U, 15U, 19U), 1, DataType::F32),
149  TensorInfo(TensorShape(21U, 25U, 21U, 4U), 1, DataType::F32),
150  TensorInfo(TensorShape(21U, 25U, 21U, 4U), 1, DataType::F32),
151  TensorInfo(TensorShape(11U, 25U, 21U), 1, DataType::F32),
152  TensorInfo(TensorShape(11U, 12U, 16U, 4U), 1, DataType::F32),
153  TensorInfo(TensorShape(17U, 31U, 19U), 1, DataType::F32),
154  TensorInfo(TensorShape(17U, 31U, 19U), 1, DataType::F32),
155  TensorInfo(TensorShape(17U, 31U, 19U), 1, DataType::QASYMM8_SIGNED),
156  })),
157  framework::dataset::make("ConvInfo", { PadStrideInfo(1, 2, 1, 1),
158  PadStrideInfo(1, 2, 1, 1),
159  PadStrideInfo(1, 1, 0, 0),
160  PadStrideInfo(1, 1, 0, 0),
161  PadStrideInfo(2, 1, 0, 0),
162  PadStrideInfo(3, 2, 1, 0),
163  PadStrideInfo(1, 1, 2, 2),
164  PadStrideInfo(1, 1, 2, 2),
165  PadStrideInfo(1, 1, 2, 2),
166  })),
176  })),
177  framework::dataset::make("Dilation", { Size2D(1U, 1U),
178  Size2D(1U, 1U),
179  Size2D(1U, 1U),
180  Size2D(1U, 1U),
181  Size2D(1U, 1U),
182  Size2D(1U, 1U),
183  Size2D(1U, 1U),
184  Size2D(2U, 1U),
185  Size2D(2U, 1U),
186  })),
187  framework::dataset::make("EnableFastMath", { false, false, false, false, false, false, true, true, true })),
197  })),
198  input_info, weights_info, output_info, conv_info, gpu_target, dilation, enable_fast_math, expected)
199 {
201  &weights_info.clone()->set_is_resizable(true),
202  &output_info.clone()->set_is_resizable(true), conv_info,
203  WeightsInfo(),
204  ActivationLayerInfo(),
205  gpu_target,
206  dilation,
207  enable_fast_math);
209 }
210 
211 DATA_TEST_CASE(ValidatePostOpSupportInConvolutionMethod, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(zip(
212  framework::dataset::make("InputInfo", { TensorInfo(TensorShape(2U, 17U, 31U), 1, DataType::F32, DataLayout::NHWC), // Select GEMM
213  TensorInfo(TensorShape(17U, 31U, 32U), 1, DataType::F32, DataLayout::NCHW), // Select WINOGRAD
214  TensorInfo(TensorShape(27U, 27U, 48U), 1, DataType::F32, DataLayout::NCHW), // Select Direct
215  TensorInfo(TensorShape(27U, 27U, 48U), 1, DataType::F32, DataLayout::NCHW), // Select FFT
216  }),
217  framework::dataset::make("WeightsInfo", { TensorInfo(TensorShape(2U, 1U, 1U, 19U), 1, DataType::F32, DataLayout::NHWC),
218  TensorInfo(TensorShape(5U, 5U, 32U, 19U), 1, DataType::F32, DataLayout::NCHW),
219  TensorInfo(TensorShape(5U, 5U, 48U, 128U), 1, DataType::F32, DataLayout::NCHW),
220  TensorInfo(TensorShape(11U, 11U, 48U, 24), 1, DataType::F32, DataLayout::NCHW),
221  })),
226  })),
227  framework::dataset::make("ConvInfo", { PadStrideInfo(1U, 1U, 0U, 0U),
228  PadStrideInfo(1U, 1U, 2U, 2U),
229  PadStrideInfo(1U, 1U, 2U, 2U),
230  PadStrideInfo(1U, 1U, 5U, 5U),
231  })),
232  framework::dataset::make("EnableFastMath", { false, true, false, false})),
237  })),
238  framework::dataset::make("PostOpSupported",{ true, false, false, false
239  })),
240  input_info, weights_info, output_info, conv_info, enable_fast_math, expected_method, post_op_supported)
241 {
244  const int idx_kernels = get_data_layout_dimension_index(input_info.data_layout(), DataLayoutDimension::BATCHES);
245 
246  const auto dilation = Size2D(1U, 1U);
247  const unsigned int num_groups = 1U;
248 
249  WeightsInfo w_info(false, weights_info.dimension(idx_width), weights_info.dimension(idx_height), weights_info.dimension(idx_kernels));
250 
251  experimental::PostOpList<ITensorInfo*> post_ops{};
252  post_ops.push_back_op<experimental::PostOpAct<ITensorInfo*>>(ActivationLayerInfo{ActivationLayerInfo::ActivationFunction::LINEAR, 0.5F, 0.0F});
253 
254  ConvolutionMethod actual_method = CLConvolutionLayer::get_convolution_method(&input_info.clone()->set_is_resizable(true),
255  &weights_info.clone()->set_is_resizable(true),
256  &output_info.clone()->set_is_resizable(true), conv_info,
257  WeightsInfo(),
258  ActivationLayerInfo(),
260  dilation,
261  enable_fast_math);
262  ARM_COMPUTE_EXPECT(actual_method == expected_method, framework::LogLevel::ERRORS);
263  const auto is_valid = CLConvolutionLayer::validate(&input_info.clone()->set_is_resizable(true),
264  &weights_info.clone()->set_is_resizable(true),
265  nullptr,
266  &output_info.clone()->set_is_resizable(true),
267  conv_info,
268  w_info,
269  dilation,
270  ActivationLayerInfo(),
271  enable_fast_math,
272  num_groups,
273  post_ops);
274  ARM_COMPUTE_EXPECT( bool(is_valid) == post_op_supported, framework::LogLevel::ERRORS);
275 }
276 // clang-format on
277 // *INDENT-ON*
278 TEST_SUITE_END() // ConvolutionLayer
279 
280 TEST_SUITE(GEMMConvolutionLayer)
281 template <typename T>
282 using CLGEMMConvolutionLayerFixture = ConvolutionValidationFixture<CLTensor, CLAccessor, CLGEMMConvolutionLayer, T>;
283 template <typename T>
285 template <typename T>
286 using CLConvolutionValidationWithPaddingFixture = ConvolutionValidationWithPaddingFixture<CLTensor, CLAccessor, CLGEMMConvolutionLayer, T>;
287 
288 TEST_SUITE(ValidateFusedPostOpsConfigs)
289 TEST_SUITE(Invalid)
290 TEST_CASE(UnsupportedPostOpSequence, framework::DatasetMode::ALL)
291 {
292  const auto data_type = DataType::F32;
293  const auto data_layout = DataLayout::NHWC;
294  const auto conv_info = PadStrideInfo(1, 1, 0, 0);
295  const auto input_shape = TensorShape(16U, 14U, 12U, 2U);
296  const auto weights_shape = TensorShape(16U, 1U, 1U, 24U);
297 
299 
300  const TensorShape post_op_arg0_shape(output_shape);
301  TensorInfo post_op_arg_info(post_op_arg0_shape, 1, data_type);
302  auto post_op_arg1_info = post_op_arg_info.clone();
303 
304  // Unsupported sequence of post ops
307  &post_op_arg_info,
308  1,
311  post_op_arg1_info.get(),
312  0,
314 
316 }
318 {
319  const auto data_type = DataType::F32;
320  const auto data_layout = DataLayout::NCHW;
321  const auto conv_info = PadStrideInfo(1, 1, 0, 0);
322  const auto input_shape = TensorShape(14U, 12U, 16U, 2U);
323  const auto weights_shape = TensorShape(1U, 1U, 16U, 24U);
324 
326 
327  const TensorShape post_op_arg0_shape(output_shape);
328  TensorInfo post_op_arg_info(post_op_arg0_shape, 1, data_type);
329 
332  &post_op_arg_info,
333  1,
335 
337 }
338 TEST_CASE(OnlyFloatingTypeIsSupported, framework::DatasetMode::ALL)
339 {
340  const auto data_type = DataType::QASYMM8;
341  const auto data_layout = DataLayout::NHWC;
342  const auto conv_info = PadStrideInfo(1, 1, 0, 0);
343  const auto input_shape = TensorShape(16U, 14U, 12U, 2U);
344  const auto weights_shape = TensorShape(16U, 1U, 1U, 24U);
345 
347 
348  const TensorShape post_op_arg0_shape(output_shape);
349  TensorInfo post_op_arg_info(post_op_arg0_shape, 1, data_type);
350 
353  &post_op_arg_info,
354  1,
356 
358 }
359 TEST_CASE(OnlyConv1x1Stride1IsSupported_UnsupportedKernelSize, framework::DatasetMode::ALL)
360 {
361  const auto data_type = DataType::F32;
362  const auto data_layout = DataLayout::NHWC;
363  const auto conv_info = PadStrideInfo(1, 1, 0, 0);
364  const auto input_shape = TensorShape(16U, 14U, 12U, 2U);
365  const auto weights_shape = TensorShape(16U, 3U, 3U, 24U);
366 
368 
369  const TensorShape post_op_arg0_shape(output_shape);
370  TensorInfo post_op_arg_info(post_op_arg0_shape, 1, data_type);
371 
374  &post_op_arg_info,
375  1,
377 
379 }
380 TEST_CASE(OnlyConv1x1Stride1IsSupported_UnsupportedStride, framework::DatasetMode::ALL)
381 {
382  const auto data_type = DataType::F32;
383  const auto data_layout = DataLayout::NHWC;
384  const auto conv_info = PadStrideInfo(3, 3, 0, 0);
385  const auto input_shape = TensorShape(16U, 14U, 12U, 2U);
386  const auto weights_shape = TensorShape(16U, 1U, 1U, 24U);
387 
389 
390  const TensorShape post_op_arg0_shape(output_shape);
391  TensorInfo post_op_arg_info(post_op_arg0_shape, 1, data_type);
392 
395  &post_op_arg_info,
396  1,
398 
400 }
401 TEST_SUITE_END() // Invalid
402 TEST_SUITE(Valid)
403 TEST_CASE(EmptyPostOpList, framework::DatasetMode::ALL)
404 {
405  const auto data_type = DataType::F32;
407  const auto conv_info = PadStrideInfo(1, 1, 0, 0);
408  const auto input_shape = TensorShape(16U, 14U, 12U, 2U);
409  const auto weights_shape = TensorShape(16U, 1U, 1U, 24U);
410 
412 
414 
416 }
418 {
419  const auto data_type = DataType::F32;
420  const auto data_layout = DataLayout::NHWC;
421  const auto conv_info = PadStrideInfo(1, 1, 0, 0);
422  const auto input_shape = TensorShape(16U, 14U, 12U, 2U);
423  const auto weights_shape = TensorShape(16U, 1U, 1U, 24U);
424 
426 
427  TensorShape post_op_arg0_shape(output_shape);
428  post_op_arg0_shape[1] = 1; // Broadcast in "Y" (second) dimension
429  TensorInfo post_op_arg_info(post_op_arg0_shape, 1, data_type);
430 
433  &post_op_arg_info,
434  1,
436 
438 }
439 TEST_SUITE_END() // Valid
440 TEST_SUITE_END() // ValidateFusedPostOps
441 TEST_SUITE(Float)
442 TEST_SUITE(FP16)
443 
444 FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMConvolutionLayerFixture<half>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
445  framework::dataset::make("ReshapeWeights", { true })),
446  framework::dataset::make("DataType",
447  DataType::F16)),
449  ActivationFunctionsSmallDataset))
450 {
451  // Validate output
452  validate(CLAccessor(_target), _reference, tolerance_f16, tolerance_num);
453 }
454 TEST_SUITE_END() // FP16
455 
456 TEST_SUITE(FP32)
457 
458 FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMConvolutionLayerFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
459  framework::dataset::make("ReshapeWeights", { true })),
460  framework::dataset::make("DataType",
461  DataType::F32)),
463  ActivationFunctionsSmallDataset))
464 {
465  // Validate output
466  validate(CLAccessor(_target), _reference, tolerance_f32);
467 }
470  framework::dataset::make("Input", TensorShape(23U, 27U, 5U)),
471  framework::dataset::make("Weights", TensorShape(3U, 3U, 5U, 2U))),
473  framework::dataset::make("Output", TensorShape(11U, 25U, 2U))),
474  framework::dataset::make("PadStrideInfo", PadStrideInfo(2, 1, 0, 0))),
475  framework::dataset::make("Dilation", Size2D(1, 1))),
476  framework::dataset::make("ReshapeWeights", { true })),
479  ActivationFunctionsSmallDataset))
480 {
481  // Validate output
482  validate(CLAccessor(_target), _reference, tolerance_f32);
483 }
485  combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerPrePaddingDataset(),
486  framework::dataset::make("ReshapeWeights", { true })),
489  framework::dataset::make("ActivationInfo", { ActivationLayerInfo() })),
490 framework::dataset::make("PrePadLayer", { PaddingList({ { 1, 1 }, { 1, 1 } }) })))
491 {
492  // Validate output
493  validate(CLAccessor(_target), _reference, tolerance_f32);
494 }
495 
496 TEST_SUITE_END() // FP32
497 TEST_SUITE_END() // Float
498 
499 template <typename T>
500 using CLGEMMConvolutionLayerQuantizedFixture = ConvolutionValidationQuantizedFixture<CLTensor, CLAccessor, CLGEMMConvolutionLayer, T>;
501 template <typename T>
503 template <typename T>
504 using CLGEMMConvolutionLayerQuantizedPerChannelFixture = ConvolutionValidationQuantizedPerChannelFixture<CLTensor, CLAccessor, CLGEMMConvolutionLayer, T, int8_t>;
505 
506 const auto QuantizedActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
507 {
509  ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU),
510  ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 6.f)
511 });
513 {
515  ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU, 6.f)
516 });
517 
518 TEST_SUITE(Quantized)
519 
520 const auto QuantizationData = framework::dataset::make("QuantizationInfo",
521 {
522  QuantizationInfo(0.5f, 10),
523  QuantizationInfo(0.3f, 3),
524  QuantizationInfo(1.1f, 10),
525 });
526 TEST_SUITE(QASYMM8)
527 
528 FIXTURE_DATA_TEST_CASE(RunSmallCases, CLGEMMConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::ALL,
529  combine(combine(combine(combine(combine(SmallConvolutionLayerDatasetCases(),
530  framework::dataset::make("ReshapeWeights", { true })),
535 {
536  // Validate output
537  validate(CLAccessor(_target), _reference, tolerance_qasymm8);
538 }
539 
540 FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::ALL,
541  combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
542  framework::dataset::make("ReshapeWeights", { true })),
547 {
548  // Validate output
549  validate(CLAccessor(_target), _reference, tolerance_qasymm8);
550 }
553  framework::dataset::make("Input", TensorShape(23U, 27U, 5U)),
554  framework::dataset::make("Weights", TensorShape(3U, 3U, 5U, 2U))),
556  framework::dataset::make("Output", TensorShape(11U, 25U, 2U))),
557  framework::dataset::make("PadStrideInfo", PadStrideInfo(2, 1, 0, 0))),
558  framework::dataset::make("Dilation", Size2D(1, 1))),
559  framework::dataset::make("ReshapeWeights", { true })),
564 {
565  // Validate output
566  validate(CLAccessor(_target), _reference, tolerance_qasymm8);
567 }
568 TEST_SUITE_END() // QASYMM8
569 TEST_SUITE(QASYMM8_SIGNED)
570 FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMConvolutionLayerQuantizedFixture<int8_t>, framework::DatasetMode::ALL,
571  combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
572  framework::dataset::make("ReshapeWeights", { true })),
577 {
578  // Validate output
579  validate(CLAccessor(_target), _reference, tolerance_qasymm8);
580 }
583  framework::dataset::make("Input", TensorShape(23U, 27U, 5U)),
584  framework::dataset::make("Weights", TensorShape(3U, 3U, 5U, 2U))),
586  framework::dataset::make("Output", TensorShape(11U, 25U, 2U))),
587  framework::dataset::make("PadStrideInfo", PadStrideInfo(2, 1, 0, 0))),
588  framework::dataset::make("Dilation", Size2D(1, 1))),
589  framework::dataset::make("ReshapeWeights", { true })),
594 {
595  // Validate output
596  validate(CLAccessor(_target), _reference, tolerance_qasymm8);
597 }
598 TEST_SUITE_END() // QASYMM8_SIGNED
599 TEST_SUITE(QSYMM8_PER_CHANNEL)
600 
602  combine(combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
603  framework::dataset::make("ReshapeWeights", { true })),
609 {
610  // Validate output
611  validate(CLAccessor(_target), _reference, tolerance_qasymm8);
612 }
613 
615  combine(combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
616  framework::dataset::make("ReshapeWeights", { true })),
622 {
623  // Validate output
624  validate(CLAccessor(_target), _reference, tolerance_qasymm8);
625 }
626 TEST_SUITE_END() // QSYMM8_PER_CHANNEL
627 TEST_SUITE_END() // Quantized
628 
629 TEST_SUITE_END() // GEMMConvolutionLayer
630 
631 template <typename T>
632 using CLGEMMGroupedConvolutionLayerFixture = ConvolutionValidationFixture<CLTensor, CLAccessor, CLGEMMConvolutionLayer, T>;
633 
634 TEST_SUITE(GroupedGEMMConvolutionLayer)
635 
636 TEST_SUITE(Float)
637 TEST_SUITE(FP32)
638 
639 FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMGroupedConvolutionLayerFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallGroupedConvolutionLayerDataset(),
640  framework::dataset::make("ReshapeWeights", { true })),
642  framework::dataset::make("DataLayout", { DataLayout::NCHW })),
643  ActivationFunctionsSmallDataset))
644 {
645  // Validate output
646  validate(CLAccessor(_target), _reference, tolerance_f32, tolerance_num);
647 }
648 
649 FIXTURE_DATA_TEST_CASE(RunLarge, CLGEMMGroupedConvolutionLayerFixture<float>, framework::DatasetMode::NIGHTLY,
650  combine(combine(combine(combine(datasets::LargeGroupedConvolutionLayerDataset(),
651  framework::dataset::make("ReshapeWeights", { true })),
653  framework::dataset::make("DataLayout", { DataLayout::NCHW })),
655 {
656  // Validate output
657  validate(CLAccessor(_target), _reference, tolerance_f32, tolerance_num);
658 }
659 TEST_SUITE_END() // FP32
660 
661 TEST_SUITE(FP16)
662 
663 FIXTURE_DATA_TEST_CASE(RunSmall, CLGEMMGroupedConvolutionLayerFixture<half>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallGroupedConvolutionLayerDataset(),
664  framework::dataset::make("ReshapeWeights", { true })),
666  framework::dataset::make("DataLayout", { DataLayout::NCHW })),
667  ActivationFunctionsSmallDataset))
668 {
669  // Validate output
670  validate(CLAccessor(_target), _reference, tolerance_f32, tolerance_num);
671 }
672 
674  combine(combine(combine(combine(datasets::LargeGroupedConvolutionLayerDataset(),
675  framework::dataset::make("ReshapeWeights", { true })),
677  framework::dataset::make("DataLayout", { DataLayout::NCHW })),
679 {
680  // Validate output
681  validate(CLAccessor(_target), _reference, tolerance_f32, tolerance_num);
682 }
683 TEST_SUITE_END() // FP16
684 TEST_SUITE_END() // Float
685 
686 TEST_SUITE_END() // GroupedGEMMConvolutionLayer
687 TEST_SUITE_END() // CL
688 } // namespace validation
689 } // namespace test
690 } // namespace arm_compute
arm_compute::DataLayout::NCHW
@ NCHW
Num samples, channels, height, width.
Datasets.h
arm_compute::test::validation::TEST_SUITE_END
TEST_SUITE_END() FIXTURE_DATA_TEST_CASE(RunSmall
[CLActivationLayer Test snippet]
Definition: DequantizationLayer.cpp:111
arm_compute::DataType::QSYMM8_PER_CHANNEL
@ QSYMM8_PER_CHANNEL
quantized, symmetric per channel fixed-point 8-bit number
arm_compute::TensorInfo::clone
std::unique_ptr< ITensorInfo > clone() const override
Definition: TensorInfo.cpp:316
PaddingCalculator.h
arm_compute::test::validation::TEST_CASE
TEST_CASE(FusedActivation, framework::DatasetMode::ALL)
Validate fused activation expecting the following behaviours:
Definition: ArithmeticAddition.cpp:93
arm_compute::test::validation::input_info
input_info
Definition: DirectConvolutionLayer.cpp:547
arm_compute::test::validation::FIXTURE_DATA_TEST_CASE
FIXTURE_DATA_TEST_CASE(RunSmall, CLAbsLayerFixture< half >, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F16)))
Definition: AbsLayer.cpp:50
arm_compute::ConvolutionMethod::FFT
@ FFT
Convolution using FFT.
arm_compute::test::validation::DATA_TEST_CASE
DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(framework::dataset::make("InputInfo", { TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::F32), TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::QASYMM8), TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QASYMM8), TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::QSYMM16), TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::QSYMM16), TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::QSYMM16), }), framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F16), TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::F32), TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::F32), TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::QASYMM8), TensorInfo(TensorShape(27U, 13U, 2U), 1, DataType::QASYMM8), TensorInfo(TensorShape(30U, 11U, 2U), 1, DataType::F32), TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::QSYMM16, QuantizationInfo(1.f/32768.f, 0)), TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::QSYMM16, QuantizationInfo(1.f/32768.f, 0)), TensorInfo(TensorShape(32U, 13U, 2U), 1, DataType::QSYMM16, QuantizationInfo(1.f/32768.f, 0)), })), framework::dataset::make("ActivationInfo", { ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU), ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU), ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU), ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LU_BOUNDED_RELU), ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::TANH), ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU), ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::TANH), ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LOGISTIC), ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::SQRT), })), framework::dataset::make("Expected", { false, true, true, true, false, false, true, true, false })), input_info, output_info, act_info, expected)
Definition: ActivationLayer.cpp:100
arm_compute::test::validation::QuantizedActivationFunctionsDataset
const auto QuantizedActivationFunctionsDataset
Input data sets.
Definition: ConvolutionLayer.cpp:506
arm_compute::QuantizationInfo
Quantization information.
Definition: QuantizationInfo.h:68
arm_compute::test::validation::idx_height
const int idx_height
Definition: Scale.cpp:263
arm_compute::PaddingList
std::vector< PaddingInfo > PaddingList
List of padding information.
Definition: Types.h:413
arm_compute::test::validation::CLGEMMConvolutionLayerQuantizedMixedDataLayoutFixture
ConvolutionValidationQuantizedFixture< CLTensor, CLAccessor, CLGEMMConvolutionLayer, T, true > CLGEMMConvolutionLayerQuantizedMixedDataLayoutFixture
Definition: ConvolutionLayer.cpp:502
arm_compute::test::validation::combine
combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32)))
Definition: AbsLayer.cpp:65
arm_compute::DataLayout
DataLayout
[DataLayout enum definition]
Definition: CoreTypes.h:109
arm_compute::test::validation::output_shape
const auto output_shape
Definition: ConvolutionLayer.cpp:411
arm_compute::DataLayout::NHWC
@ NHWC
Num samples, height, width, channels.
arm_compute::test::validation::weights_info
weights_info
Definition: BatchNormalizationLayer.cpp:165
arm_compute::test::validation::CLGEMMConvolutionLayerMixedDataLayoutFixture
ConvolutionValidationFixture< CLTensor, CLAccessor, CLGEMMConvolutionLayer, T, true > CLGEMMConvolutionLayerMixedDataLayoutFixture
Definition: ConvolutionLayer.cpp:284
arm_compute::DataType::QASYMM8
@ QASYMM8
quantized, asymmetric fixed-point 8-bit number unsigned
arm_compute::TensorShape
Shape of a tensor.
Definition: TensorShape.h:39
arm_compute::CLConvolutionLayer::validate
static Status validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info, const WeightsInfo &weights_info=WeightsInfo(), const Size2D &dilation=Size2D(1U, 1U), const ActivationLayerInfo &act_info=ActivationLayerInfo(), bool enable_fast_math=false, unsigned int num_groups=1, const experimental::PostOpList< ITensorInfo * > &post_ops=experimental::PostOpList< ITensorInfo * > {})
Static function to check if given info will lead to a valid configuration of CLConvolutionLayer.
Definition: CLConvolutionLayer.cpp:129
arm_compute::test::validation::tolerance_f16
RelativeTolerance< half_float::half > tolerance_f16(half_float::half(0.1))
Tolerance value for comparing reference's output against implementation's output for DataType::F16.
arm_compute::test::validation::QuantizationData
const auto QuantizationData
Definition: ConvolutionLayer.cpp:520
Types.h
arm_compute::test::validation::tolerance_num
constexpr float tolerance_num
Tolerance number.
Definition: Add.cpp:104
CLConvolutionLayer.h
arm_compute::Size2D
Class for specifying the size of an image or rectangle.
Definition: Size2D.h:34
arm_compute::test::validation::CLGEMMGroupedConvolutionLayerFixture< half >
CLGEMMGroupedConvolutionLayerFixture< half >
Definition: ConvolutionLayer.cpp:663
PostOps.h
arm_compute::CLTensor
Basic implementation of the OpenCL tensor interface.
Definition: CLTensor.h:41
arm_compute::test::validation::idx_width
const int idx_width
Definition: Scale.cpp:262
arm_compute::test::validation::is_valid
bool is_valid
Definition: DirectConv2d.cpp:166
arm_compute::DataLayoutDimension::WIDTH
@ WIDTH
width
arm_compute::test::validation::data_layout
const auto data_layout
Definition: ConvolutionLayer.cpp:406
arm_compute::ConvolutionMethod
ConvolutionMethod
Available ConvolutionMethod.
Definition: Types.h:92
CLGEMMConvolutionLayer.h
arm_compute::ActivationLayerInfo
Activation Layer Information class.
Definition: ActivationLayerInfo.h:55
arm_compute::GPUTarget::BIFROST
@ BIFROST
CLAccessor.h
arm_compute::test::validation::validate
validate(CLAccessor(output_state), expected_output)
arm_compute::half
half_float::half half
16-bit floating point type
Definition: CoreTypes.h:35
arm_compute::utils::cast::U
U
Definition: SaturateCast.h:64
arm_compute::test::validation::CLGEMMConvolutionLayerQuantizedPerChannelFixture
ConvolutionValidationQuantizedPerChannelFixture< CLTensor, CLAccessor, CLGEMMConvolutionLayer, T, int8_t > CLGEMMConvolutionLayerQuantizedPerChannelFixture
Definition: ConvolutionLayer.cpp:504
arm_compute::test::validation::output_info
output_info
Definition: DirectConvolutionLayer.cpp:547
arm_compute::test::framework::DatasetMode::ALL
@ ALL
arm_compute::test::CLAccessor
Accessor implementation for CLTensor objects.
Definition: CLAccessor.h:36
arm_compute::test::validation::ARM_COMPUTE_EXPECT
ARM_COMPUTE_EXPECT(has_error==expected, framework::LogLevel::ERRORS)
arm_compute::DataLayoutDimension::HEIGHT
@ HEIGHT
height
arm_compute::test::validation::ActivationFunctionsDataset
const auto ActivationFunctionsDataset
Definition: MatMul.cpp:73
arm_compute::CLGEMMConvolutionLayer::validate
static Status validate(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *biases, const ITensorInfo *output, const PadStrideInfo &conv_info, const WeightsInfo &weights_info=WeightsInfo(), const Size2D &dilation=Size2D(1U, 1U), const ActivationLayerInfo &act_info=ActivationLayerInfo(), unsigned int num_groups=1, const experimental::PostOpList< ITensorInfo * > &post_ops=experimental::PostOpList< ITensorInfo * > {})
Static function to check if given info will lead to a valid configuration of CLGEMMConvolutionLayer.
Definition: CLGEMMConvolutionLayer.cpp:117
arm_compute::test::framework::DatasetMode::NIGHTLY
@ NIGHTLY
Asserts.h
arm_compute::test::validation::post_ops
experimental::PostOpList< ITensorInfo * > post_ops
Definition: ConvolutionLayer.cpp:413
arm_compute::DataType::QASYMM8_SIGNED
@ QASYMM8_SIGNED
quantized, asymmetric fixed-point 8-bit number signed
arm_compute::ConvertPolicy::SATURATE
@ SATURATE
Saturate.
arm_compute::ConvolutionMethod::WINOGRAD
@ WINOGRAD
Convolution using Winograd.
arm_compute::test::validation::CLConvolutionValidationWithPaddingFixture
ConvolutionValidationWithPaddingFixture< CLTensor, CLAccessor, CLGEMMConvolutionLayer, T > CLConvolutionValidationWithPaddingFixture
Definition: ConvolutionLayer.cpp:286
Macros.h
arm_compute::ConvolutionMethod::GEMM
@ GEMM
Convolution using GEMM.
arm_compute::GPUTarget::MIDGARD
@ MIDGARD
arm_compute::PadStrideInfo
Definition: CoreTypes.h:138
arm_compute::ConvolutionMethod::DIRECT
@ DIRECT
Direct convolution.
arm_compute::test::framework::dataset::make
std::enable_if< is_container< T >::value, ContainerDataset< T > >::type make(std::string name, T &&values)
Helper function to create a ContainerDataset.
Definition: ContainerDataset.h:160
arm_compute::test::validation::data_type
data_type
Definition: Cast.cpp:223
arm_compute::CLConvolutionLayer::get_convolution_method
static ConvolutionMethod get_convolution_method(const ITensorInfo *input, const ITensorInfo *weights, const ITensorInfo *output, const PadStrideInfo &conv_info, const WeightsInfo &weights_info, const ActivationLayerInfo &act_info, const GPUTarget gpu_target, const Size2D &dilation=Size2D(1U, 1U), bool enable_fast_math=false)
Static function to check if given info will return the convolution called by CLConvolutionLayer.
Definition: CLConvolutionLayer.cpp:164
Validation.h
arm_compute::test::validation::input_shape
const auto input_shape
Validate test suite is to test ARM_COMPUTE_RETURN_ON_* macros we use to check the validity of given a...
Definition: ConvolutionLayer.cpp:408
arm_compute::test::validation::tolerance_f32
RelativeTolerance< float > tolerance_f32(0.01f)
Tolerance value for comparing reference's output against implementation's output for DataType::F32.
arm_compute::get_data_layout_dimension_index
size_t get_data_layout_dimension_index(const DataLayout &data_layout, const DataLayoutDimension &data_layout_dimension)
Get the index of the given dimension.
Definition: Helpers.inl:203
arm_compute::experimental::PostOpEltwiseAdd
Definition: PostOps.h:81
ShapeCalculator.h
arm_compute::TensorInfo
Store the tensor's metadata.
Definition: TensorInfo.h:42
arm_compute::test::validation::num_groups
const unsigned int num_groups
Definition: Im2Col.cpp:153
arm_compute::test::validation::zip
zip(zip(framework::dataset::make("Weights", { TensorInfo(TensorShape(32U, 13U, 2U, 2U), 1, DataType::F32), TensorInfo(TensorShape(32U, 13U, 2U, 2U), 1, DataType::F32), TensorInfo(TensorShape(32U, 13U, 2U, 1U), 1, DataType::F32), }), framework::dataset::make("MVBGInfo",{ TensorInfo(TensorShape(2U), 1, DataType::F32), TensorInfo(TensorShape(2U), 1, DataType::F16), TensorInfo(TensorShape(5U), 1, DataType::F32), })), framework::dataset::make("Expected", { true, false, false}))
arm_compute
Copyright (c) 2017-2023 Arm Limited.
Definition: introduction.dox:24
arm_compute::test::validation::conv_info
const auto conv_info
Definition: ConvolutionLayer.cpp:407
arm_compute::test::validation::TEST_SUITE
TEST_SUITE(QASYMM8_to_F32) FIXTURE_DATA_TEST_CASE(RunSmall
arm_compute::DataType::F16
@ F16
16-bit floating-point number
CLTensor.h
arm_compute::test::validation::weights_shape
const auto weights_shape
Definition: ConvolutionLayer.cpp:409
arm_compute::GPUTarget::G71
@ G71
arm_compute::test::validation::expected
expected
Definition: BatchNormalizationLayer.cpp:166
arm_compute::DataLayoutDimension::BATCHES
@ BATCHES
batches
arm_compute::DataType::F32
@ F32
32-bit floating-point number
arm_compute::test::validation::QuantizedActivationFunctionsSmallDataset
const auto QuantizedActivationFunctionsSmallDataset
Definition: ConvolutionLayer.cpp:512
arm_compute::misc::shape_calculator::compute_deep_convolution_shape
TensorShape compute_deep_convolution_shape(const TensorShape &input_shape, DataLayout input_data_layout, const TensorShape &weights_shape, const PadStrideInfo &conv_info)
Calculate the deep convolution shape output shape of a tensor.
Definition: ShapeCalculator.h:715
CLTensorAllocator.h
arm_compute::test::framework::DatasetMode
DatasetMode
Possible dataset modes.
Definition: DatasetModes.h:40
arm_compute::DataType
DataType
Available data types.
Definition: CoreTypes.h:82
arm_compute::CLGEMMConvolutionLayer
Basic function to compute the convolution layer.
Definition: CLGEMMConvolutionLayer.h:48
arm_compute::experimental::PostOpList
A sequence of PostOps that can be appended to the end of other operators.
Definition: IPostOp.h:119
arm_compute::test::framework::LogLevel::ERRORS
@ ERRORS