Compute Library
 22.05
ConvolutionLayer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2021 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"
35 #include "tests/NEON/Accessor.h"
37 #include "tests/datasets/LargeConvolutionLayerDataset.h"
38 #include "tests/datasets/SmallConvolutionLayerDataset.h"
39 #include "tests/datasets/TinyConvolutionLayerDataset.h"
41 #include "tests/framework/Macros.h"
44 #include "tests/validation/fixtures/ConvolutionLayerFixture.h"
45 #include "tests/validation/fixtures/WinogradConvolutionLayerFixture.h"
46 
47 namespace arm_compute
48 {
49 namespace test
50 {
51 namespace validation
52 {
53 namespace detail
54 {
55 template <>
57  Tensor *src, const Tensor *weights, const Tensor *bias, Tensor *dst,
59  const Size2D &dilation, const ActivationLayerInfo &act_info, unsigned int num_groups)
60 {
61  ARM_COMPUTE_UNUSED(weights_info);
62 
63  Conv2dInfo conv_info(info, dilation, act_info, false, num_groups);
64  func.configure(src, weights, bias, dst, conv_info);
65 }
66 } // namespace detail
67 namespace
68 {
69 const RelativeTolerance<float> rel_tolerance_f32(0.01f); /**< Relative tolerance for FP32 types */
70 const RelativeTolerance<float> rel_tolerance_winograd_3x3_f32(0.05f); /**< Relative tolerance for FP32 types */
71 const AbsoluteTolerance<float> abs_tolerance_f32(0.002f); /**< Absolute tolerance for FP32 types */
72 const AbsoluteTolerance<float> abs_tolerance_1xN_f32(0.0041f); /**< Absolute tolerance for FP32 types */
73 
74 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
75 const AbsoluteTolerance<half> tolerance_convolution_layer_f16(half(0.4f));
76 constexpr float tolerance_num_f16 = 0.15f;
77 #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
78 
79 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
80 const RelativeTolerance<half_float::half> rel_tolerance_f16(half_float::half(0.2f)); /**< Relative tolerance value for FP16 types */
81 const AbsoluteTolerance<float> abs_tolerance_f16(0.2f); /**< Absolute tolerance for FP16 types */
82 constexpr float tolerance_num = 0.07f; /**< Tolerance number for the FP16 implementation */
83 #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
84 constexpr AbsoluteTolerance<float> tolerance_qasymm8(0.0); /**< Tolerance value for comparing reference's output against implementation's output for quantized data types */
85 
86 /** CNN data types */
87 const auto CNNDataTypes = framework::dataset::make("DataType",
88 {
89 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
91 #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
94 });
95 const auto ActivationFunctionsDataset = framework::dataset::make("ActivationInfo",
96 {
100 });
101 
102 const auto QuantizationData = framework::dataset::make("QuantizationInfo",
103 {
104  QuantizationInfo(0.5f, 10),
105  QuantizationInfo(0.3f, 3),
106  QuantizationInfo(1.f, 10),
107  QuantizationInfo(1.1f, 10),
108 });
109 } // namespace
110 
112 TEST_SUITE(ConvolutionLayer)
113 
114 // *INDENT-OFF*
115 // clang-format off
116 DATA_TEST_CASE(ValidateConvolutionMethod, framework::DatasetMode::ALL, zip(zip(zip(zip(zip(
117  framework::dataset::make("InputInfo", { TensorInfo(TensorShape(18U, 18U, 32U), 1, DataType::F32),
118  TensorInfo(TensorShape(23U, 27U, 32U, 4U), 1, DataType::F32),
119  TensorInfo(TensorShape(3U, 3U, 2U, 1U), 1, DataType::F32),
120  TensorInfo(TensorShape(33U, 27U, 7U, 4U), 1, DataType::F32)
121  }),
122  framework::dataset::make("WeightsInfo", { TensorInfo(TensorShape(3U, 3U, 32U, 21U), 1, DataType::F32),
123  TensorInfo(TensorShape(5U, 5U, 32U, 21U), 1, DataType::F32),
124  TensorInfo(TensorShape(3U, 3U, 5U, 21U), 1, DataType::F32),
125  TensorInfo(TensorShape(5U, 5U, 7U, 16U), 1, DataType::F16)
126  })),
127  framework::dataset::make("OutputInfo", { TensorInfo(TensorShape(16U, 16U, 21U), 1, DataType::F32),
128  TensorInfo(TensorShape(19U, 23U, 21U, 4U), 1, DataType::F32),
129  TensorInfo(TensorShape(11U, 25U, 21U), 1, DataType::F32),
130  TensorInfo(TensorShape(11U, 12U, 16U, 4U), 1, DataType::F32)
131  })),
132  framework::dataset::make("ConvInfo", { PadStrideInfo(1, 1, 0, 0),
133  PadStrideInfo(1, 1, 0, 0),
134  PadStrideInfo(2, 1, 0, 0),
135  PadStrideInfo(3, 2, 1, 0)
136  })),
137  framework::dataset::make("FastMath", { true,
138  true,
139  false,
140  false
141  })),
144 {
145  ConvolutionMethod is_valid = NEConvolutionLayer::get_convolution_method(&input_info.clone()->set_is_resizable(true),
146  &weights_info.clone()->set_is_resizable(true),
147  &output_info.clone()->set_is_resizable(true), conv_info, WeightsInfo(), Size2D(1U, 1U), ActivationLayerInfo(), fast_math);
149 }
150 // clang-format on
151 // *INDENT-ON*
152 TEST_SUITE_END() // ConvolutionLayer
153 
154 TEST_SUITE(WinogradLayer)
155 template <typename T>
156 using NEWinogradConvolutionLayerFixture = WinogradConvolutionLayerFastMathValidationFixture<Tensor, Accessor, NEWinogradConvolutionLayer, T>;
157 template <typename T>
158 using NEWinogradConvolutionLayerMixedDataLayoutFixture = WinogradConvolutionLayerFastMathValidationFixture<Tensor, Accessor, NEWinogradConvolutionLayer, T, T, true, true>;
159 
160 template <typename T>
161 using NEWinogradConvolutionLayerNoBiasFixture = WinogradConvolutionLayerFastMathValidationFixture<Tensor, Accessor, NEWinogradConvolutionLayer, T, T, false>;
162 
163 /** Test case for memory injection in @ref cpu::CpuWinogradConv2d.
164  *
165  * Configure the operator once and inject memory at run-time in multiple executions.
166  *
167  * Checks performed in order:
168  * - Both runs compute the same output
169  */
171 {
172  auto winograd = std::make_unique<cpu::CpuWinogradConv2d>();
173  const auto src_info = TensorInfo(TensorShape(8U, 8U, 32U), 1, DataType::F32);
174  const auto w_info = TensorInfo(TensorShape(1U), 1, DataType::F32);
175  const auto b_info = TensorInfo(TensorShape(1U, 3U, 32U, 1U), 1, DataType::F32);
176  auto dst_info = TensorInfo(TensorShape(8U, 6U, 1U), 1, DataType::F32);
177  const PadStrideInfo pad_info{};
178 
179  winograd->configure(&src_info, &b_info, &w_info, &dst_info, pad_info);
180 
181  // telhs are newly created every call of this lambda function
182  auto a = create_tensor<Tensor>(src_info);
183  auto b = create_tensor<Tensor>(b_info);
184  auto c = create_tensor<Tensor>(w_info);
185  a.allocator()->allocate();
186  b.allocator()->allocate();
187  c.allocator()->allocate();
188 
190  ITensorPack prep_pack{ { TensorType::ACL_SRC_1, &b }, { TensorType::ACL_SRC_2, &c } };
191 
192  auto mg = MemoryGroup{};
193  auto ws = manage_workspace<Tensor>(winograd->workspace(), mg, run_pack, prep_pack);
194  auto run_conv = [&]() -> Tensor
195  {
196  auto dst = create_tensor<Tensor>(dst_info);
197  dst.allocator()->allocate();
198 
199  run_pack.add_tensor(TensorType::ACL_DST, &dst);
200  library->fill_tensor_value(Accessor(a), 1.f);
201  library->fill_tensor_value(Accessor(b), 2.f);
202  library->fill_tensor_value(Accessor(c), 3.f);
203 
204  // This operator is configured once and captured by this lambda.
205  winograd->prepare(prep_pack);
206  winograd->run(run_pack);
207  return dst;
208  };
209 
210  auto result_0 = run_conv();
211  auto result_1 = run_conv();
212 
213  for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
214  {
215  ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
216  }
217 }
218 
219 /** Test case for memory injection in @ref NEWinogradConvolutionLayer.
220  *
221  * Make sure @ref NEWinogradConvolutionLayer still works through injecting the memory at configure time using the old API.
222  *
223  * Checks performed in order:
224  * - Both runs compute the same output
225  */
226 TEST_CASE(MultipleExecutionWithConfigure, framework::DatasetMode::ALL)
227 {
228  auto gemm = std::make_unique<NEWinogradConvolutionLayer>();
229  const auto src_info = TensorInfo(TensorShape(8U, 8U, 32U), 1, DataType::F32);
230  const auto w_info = TensorInfo(TensorShape(1U), 1, DataType::F32);
231  const auto b_info = TensorInfo(TensorShape(1U, 3U, 32U, 1U), 1, DataType::F32);
232  auto dst_info = TensorInfo(TensorShape(8U, 6U, 1U), 1, DataType::F32);
233  const PadStrideInfo pad_info{};
234 
235  auto run_conv = [&]()
236  {
237  auto src = create_tensor<Tensor>(src_info);
238  auto w = create_tensor<Tensor>(w_info);
239  auto b = create_tensor<Tensor>(b_info);
240  auto dst = create_tensor<Tensor>(dst_info);
241 
242  gemm->configure(&src, &b, &w, &dst, pad_info);
243 
244  src.allocator()->allocate();
245  b.allocator()->allocate();
246  w.allocator()->allocate();
247  dst.allocator()->allocate();
248 
249  library->fill_tensor_value(Accessor(src), 1.f);
250  library->fill_tensor_value(Accessor(b), 2.f);
251  library->fill_tensor_value(Accessor(w), 3.f);
252  gemm->run();
253  return dst;
254  };
255 
256  auto result_0 = run_conv();
257  auto result_1 = run_conv();
258 
259  for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
260  {
261  ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
262  }
263 }
264 
265 TEST_SUITE(FP32)
266 
267 TEST_SUITE(Conv1x3)
268 FIXTURE_DATA_TEST_CASE(RunSmall, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
269  combine(combine(combine(datasets::SmallWinogradConvolutionLayer1x3Dataset(),
270  framework::dataset::make("DataType", { DataType::F32 })),
271  ActivationFunctionsDataset),
273 {
274  // Validate output
275  validate(Accessor(_target), _reference, abs_tolerance_f32);
276 }
279  framework::dataset::make("Input", TensorShape(8U, 8U, 32U)),
280  framework::dataset::make("Weight", TensorShape(1U, 3U, 32U, 1U))),
282  framework::dataset::make("Output", TensorShape(8U, 6U, 1U))),
283  framework::dataset::make("PadStrideInfo", PadStrideInfo(1, 1, 0, 0))),
284  framework::dataset::make("Dilation", Size2D(1U, 1U))),
285  framework::dataset::make("DataType", { DataType::F32 })),
286  ActivationFunctionsDataset),
288 {
289  // Validate output
290  validate(Accessor(_target), _reference, abs_tolerance_f32);
291 }
293  combine(combine(combine(datasets::LargeWinogradConvolutionLayer1x3Dataset(),
294  framework::dataset::make("DataType", { DataType::F32 })),
295  ActivationFunctionsDataset),
297 {
298  // Validate output
299  validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
300 }
301 
302 TEST_SUITE_END() // Conv1x3
303 
304 TEST_SUITE(Conv3x1)
305 FIXTURE_DATA_TEST_CASE(RunSmall, NEWinogradConvolutionLayerFixture<float>, framework::DatasetMode::PRECOMMIT,
306  combine(combine(combine(datasets::SmallWinogradConvolutionLayer3x1Dataset(),
307  framework::dataset::make("DataType", { DataType::F32 })),
308  ActivationFunctionsDataset),
310 {
311  // Validate output
312  validate(Accessor(_target), _reference, abs_tolerance_f32);
313 }
315  combine(combine(combine(datasets::LargeWinogradConvolutionLayer3x1Dataset(),
316  framework::dataset::make("DataType", { DataType::F32 })),
317  ActivationFunctionsDataset),
319 {
320  // Validate output
321  validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
322 }
323 
324 TEST_SUITE_END() // Conv3x1
325 
326 TEST_SUITE(Conv1x5)
328  combine(combine(combine(datasets::SmallWinogradConvolutionLayer1x5Dataset(),
329  framework::dataset::make("DataType", { DataType::F32 })),
330  ActivationFunctionsDataset),
332 {
333  // Validate output
334  validate(Accessor(_target), _reference, abs_tolerance_f32);
335 }
337  combine(combine(combine(datasets::LargeWinogradConvolutionLayer1x5Dataset(),
338  framework::dataset::make("DataType", { DataType::F32 })),
339  ActivationFunctionsDataset),
341 {
342  // Validate output
343  validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
344 }
345 
346 TEST_SUITE_END() // Conv1x5
347 
348 TEST_SUITE(Conv5x1)
350  combine(combine(combine(datasets::SmallWinogradConvolutionLayer5x1Dataset(),
351  framework::dataset::make("DataType", { DataType::F32 })),
352  ActivationFunctionsDataset),
354 {
355  // Validate output
356  validate(Accessor(_target), _reference, abs_tolerance_f32);
357 }
359  combine(combine(combine(datasets::LargeWinogradConvolutionLayer5x1Dataset(),
360  framework::dataset::make("DataType", { DataType::F32 })),
361  ActivationFunctionsDataset),
363 {
364  // Validate output
365  validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
366 }
367 
368 TEST_SUITE_END() // Conv5x1
369 
370 TEST_SUITE(Conv7x1)
372  combine(combine(combine(datasets::SmallWinogradConvolutionLayer7x1Dataset(),
373  framework::dataset::make("DataType", { DataType::F32 })),
374  ActivationFunctionsDataset),
376 {
377  // Validate output
378  validate(Accessor(_target), _reference, abs_tolerance_f32);
379 }
380 
382  combine(combine(combine(datasets::LargeWinogradConvolutionLayer7x1Dataset(),
383  framework::dataset::make("DataType", { DataType::F32 })),
384  ActivationFunctionsDataset),
386 {
387  // Validate output
388  validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
389 }
390 TEST_SUITE_END() // Conv7x1
391 
392 TEST_SUITE(Conv1x7)
394  combine(combine(combine(datasets::SmallWinogradConvolutionLayer1x7Dataset(),
395  framework::dataset::make("DataType", { DataType::F32 })),
396  ActivationFunctionsDataset),
398 {
399  // Validate output
400  validate(Accessor(_target), _reference, abs_tolerance_f32);
401 }
402 
404  combine(combine(combine(datasets::LargeWinogradConvolutionLayer7x1Dataset(),
405  framework::dataset::make("DataType", { DataType::F32 })),
406  ActivationFunctionsDataset),
408 {
409  // Validate output
410  validate(Accessor(_target), _reference, abs_tolerance_1xN_f32);
411 }
412 TEST_SUITE_END() // Conv1x7
413 
414 TEST_SUITE(Conv3x3)
416  combine(combine(combine(datasets::SmallWinogradConvolutionLayer3x3Dataset(),
417  framework::dataset::make("DataType", { DataType::F32 })),
418  ActivationFunctionsDataset),
420 
421 {
422  // Validate output
423  validate(Accessor(_target), _reference, abs_tolerance_f32);
424 }
426  combine(combine(combine(datasets::LargeWinogradConvolutionLayer3x3Dataset(),
427  framework::dataset::make("DataType", { DataType::F32 })),
428  ActivationFunctionsDataset),
430 
431 {
432  // Validate output
433  // floating point arithmetic the Winograd results will not be exactly the same as direct convolution, especially for big shapes
434  validate(Accessor(_target), _reference, rel_tolerance_winograd_3x3_f32, 0.f, float(abs_tolerance_f32));
435 }
436 TEST_SUITE_END() // Conv3x3
437 
438 TEST_SUITE(Conv5x5)
440  combine(combine(combine(datasets::SmallWinogradConvolutionLayer5x5Dataset(),
441  framework::dataset::make("DataType", { DataType::F32 })),
442  ActivationFunctionsDataset),
444 
445 {
446  // Validate output
447  validate(Accessor(_target), _reference, abs_tolerance_f32);
448 }
450  combine(combine(combine(datasets::LargeWinogradConvolutionLayer5x5Dataset(),
451  framework::dataset::make("DataType", { DataType::F32 })),
452  ActivationFunctionsDataset),
454 
455 {
456  // Validate output
457  validate(Accessor(_target), _reference, abs_tolerance_f32);
458 }
459 
460 TEST_SUITE_END() // Conv5x5
461 
462 FIXTURE_DATA_TEST_CASE(RunSmallNoBias, NEWinogradConvolutionLayerNoBiasFixture<float>, framework::DatasetMode::PRECOMMIT,
463  combine(combine(combine(framework::dataset::concat(datasets::SmallWinogradConvolutionLayer3x3Dataset(),
464  datasets::SmallWinogradConvolutionLayer5x5Dataset()),
465  framework::dataset::make("DataType", { DataType::F32 })),
466  ActivationFunctionsDataset),
467 
469 {
470  // Validate output
471  validate(Accessor(_target), _reference, abs_tolerance_f32);
472 }
473 
474 TEST_SUITE_END() // FP32
475 
476 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
477 TEST_SUITE(FP16)
478 using CLWinogradConvolutionLayerFastMathFixture16 = WinogradConvolutionLayerFastMathValidationFixture<Tensor, Accessor, NEWinogradConvolutionLayer, half, float>;
479 
480 TEST_SUITE(Conv3x3)
481 FIXTURE_DATA_TEST_CASE(RunSmall, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::PRECOMMIT,
482  combine(combine(combine(datasets::SmallWinogradConvolutionLayer3x3Dataset(),
483  framework::dataset::make("DataType", { DataType::F16 })),
484  ActivationFunctionsDataset),
486 
487 {
488  // Validate output
489  validate(Accessor(_target), _reference, tolerance_convolution_layer_f16, tolerance_num_f16);
490 }
491 
492 FIXTURE_DATA_TEST_CASE(RunLarge, CLWinogradConvolutionLayerFastMathFixture16, framework::DatasetMode::NIGHTLY,
493  combine(combine(combine(datasets::LargeWinogradConvolutionLayer3x3Dataset(),
494  framework::dataset::make("DataType", { DataType::F16 })),
495  ActivationFunctionsDataset),
497 
498 {
499  // Validate output
500  validate(Accessor(_target), _reference, tolerance_convolution_layer_f16, tolerance_num_f16);
501 }
502 TEST_SUITE_END() // Conv3x3
503 TEST_SUITE_END() // FP16
504 #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
505 TEST_SUITE_END() // WinogradLayer
506 
507 TEST_SUITE(GEMMConvolutionLayer)
508 template <typename T>
509 using NEGEMMConvolutionLayerFixture = ConvolutionValidationFixture<Tensor, Accessor, NEConvolutionLayer, T>;
510 template <typename T>
511 using NEGEMMConvolutionLayerMixedDataLayoutFixture = ConvolutionValidationFixture<Tensor, Accessor, NEConvolutionLayer, T, true>;
512 
513 /** Test case for memory injection in @ref cpu::CpuGemmConv2d.
514  *
515  * Configure the operator once and inject memory at run-time in multiple executions.
516  *
517  * Checks performed in order:
518  * - Both runs compute the same output
519  */
520 TEST_CASE(MemoryInjection, framework::DatasetMode::ALL)
521 {
522  auto conv = std::make_unique<cpu::CpuGemmConv2d>();
524  const auto weight_info = TensorInfo(TensorShape(1U, 3U, 2U, 3U), 1, DataType::F32, DataLayout::NCHW);
525  const auto bias_info = TensorInfo(TensorShape(3U), 1, DataType::F32, DataLayout::NCHW);
526  auto dst_info = TensorInfo(TensorShape(1U, 7U, 3U), 1, DataType::F32, DataLayout::NCHW);
527  const auto conv_info = PadStrideInfo(1, 1, 0, 0, 2, 2, DimensionRoundingType::FLOOR);
528  WeightsInfo weights_info(false, 3U, 3U, 1U);
529  conv->configure(&src_info, &weight_info, &bias_info, &dst_info, conv_info, weights_info);
530 
531  // tensors are newly created every call of this lambda function
532  auto src = create_tensor<Tensor>(src_info);
533  auto weight = create_tensor<Tensor>(weight_info);
534  auto bias = create_tensor<Tensor>(bias_info);
535  src.allocator()->allocate();
536  weight.allocator()->allocate();
537  bias.allocator()->allocate();
538 
539  ITensorPack run_pack{ { TensorType::ACL_SRC_0, &src }, { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
540  ITensorPack prep_pack{ { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
541 
542  auto mg = MemoryGroup{};
543  auto ws = manage_workspace<Tensor>(conv->workspace(), mg, run_pack, prep_pack);
544 
545  auto run_conv = [&]() -> Tensor
546  {
547  auto dst = create_tensor<Tensor>(dst_info);
548  dst.allocator()->allocate();
549  run_pack.add_tensor(TensorType::ACL_DST, &dst);
550 
551  library->fill_tensor_value(Accessor(src), 1.f);
552  library->fill_tensor_value(Accessor(weight), 2.f);
553  library->fill_tensor_value(Accessor(bias), 3.f);
554  // This operator is configured once and captured by this lambda.
555  conv->prepare(prep_pack);
556  conv->run(run_pack);
557  return dst;
558  };
559  auto result_0 = run_conv();
560  auto result_1 = run_conv();
561  for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
562  {
563  ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
564  }
565 }
566 
567 /** Test case for memory injection in @ref NEGEMMConvolutionLayer.
568  *
569  * Make sure @ref NEGEMMConvolutionLayer still works through injecting the memory at configure time using the old API.
570  *
571  * Checks performed in order:
572  * - Both runs compute the same output
573  */
574 TEST_CASE(MultipleExecutionWithConfigure, framework::DatasetMode::ALL)
575 {
576  auto conv = std::make_unique<NEGEMMConvolutionLayer>();
578  const auto weight_info = TensorInfo(TensorShape(1U, 3U, 2U, 3U), 1, DataType::F32, DataLayout::NCHW);
579  const auto bias_info = TensorInfo(TensorShape(3U), 1, DataType::F32, DataLayout::NCHW);
580  auto dst_info = TensorInfo(TensorShape(1U, 7U, 3U), 1, DataType::F32, DataLayout::NCHW);
581  const auto conv_info = PadStrideInfo(1, 1, 0, 0, 2, 2, DimensionRoundingType::FLOOR);
582  WeightsInfo weights_info(false, 3U, 3U, 1U);
583  auto run_conv = [&]()
584  {
585  auto src = create_tensor<Tensor>(src_info);
586  auto weight = create_tensor<Tensor>(weight_info);
587  auto bias = create_tensor<Tensor>(bias_info);
588  auto dst = create_tensor<Tensor>(dst_info);
589  conv->configure(&src, &weight, &bias, &dst, conv_info, weights_info);
590  src.allocator()->allocate();
591  weight.allocator()->allocate();
592  bias.allocator()->allocate();
593  dst.allocator()->allocate();
594  library->fill_tensor_value(Accessor(src), 1.f);
595  library->fill_tensor_value(Accessor(weight), 2.f);
596  library->fill_tensor_value(Accessor(bias), 3.f);
597  conv->run();
598  return dst;
599  };
600  auto result_0 = run_conv();
601  auto result_1 = run_conv();
602  for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
603  {
604  ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
605  }
606 }
607 
608 TEST_SUITE(Float)
609 #if defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) || defined(ARM_COMPUTE_FORCE_BF16)
611 FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
612  framework::dataset::make("ReshapeWeights", { true })),
614  framework::dataset::make("DataLayout", { DataLayout::NHWC })),
615  ActivationFunctionsDataset))
616 {
617  // Validate output
618  validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
619 }
620 TEST_SUITE_END() // BFLOAT16
621 #endif /* defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) || defined(ARM_COMPUTE_FORCE_BF16) */
622 
623 #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
624 TEST_SUITE(FP16)
625 FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerFixture<half>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
626  framework::dataset::make("ReshapeWeights", { true })),
628  framework::dataset::make("DataLayout", { DataLayout::NCHW })),
629  ActivationFunctionsDataset))
630 {
631  // Validate output
632  validate(Accessor(_target), _reference, rel_tolerance_f16, tolerance_num, abs_tolerance_f16);
633 }
634 TEST_SUITE_END() // FP16
635 #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */
636 
637 TEST_SUITE(FP32)
638 FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
639  framework::dataset::make("ReshapeWeights", { true })),
642  ActivationFunctionsDataset))
643 {
644  // Validate output
645  validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
646 }
649  framework::dataset::make("Input", TensorShape(23U, 27U, 5U)),
650  framework::dataset::make("Weights", TensorShape(3U, 3U, 5U, 2U))),
652  framework::dataset::make("Output", TensorShape(11U, 25U, 2U))),
653  framework::dataset::make("PadStrideInfo", PadStrideInfo(2, 1, 0, 0))),
654  framework::dataset::make("Dilation", Size2D(1, 1))),
655  framework::dataset::make("ReshapeWeights", { true })),
658  ActivationFunctionsDataset))
659 {
660  // Validate output
661  validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
662 }
663 TEST_SUITE_END() // FP32
664 TEST_SUITE_END() // Float
665 
666 template <typename T>
667 using NEGEMMConvolutionLayerQuantizedFixture = ConvolutionValidationQuantizedFixture<Tensor, Accessor, NEConvolutionLayer, T>;
668 template <typename T>
669 using NEGEMMConvolutionLayerQuantizedMixedDataLayoutFixture = ConvolutionValidationQuantizedFixture<Tensor, Accessor, NEConvolutionLayer, T, true>;
670 
671 template <typename T>
672 using NEGEMMConvolutionLayerQuantizedPerChannelFixture = ConvolutionValidationQuantizedPerChannelFixture<Tensor, Accessor, NEConvolutionLayer, T, int8_t>;
673 
675 {
679 });
680 TEST_SUITE(Quantized)
682 FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
683  framework::dataset::make("ReshapeWeights", { true })),
686  framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255.f, 10) })),
688 {
689  // Validate output
690  validate(Accessor(_target), _reference, tolerance_qasymm8);
691 }
692 FIXTURE_DATA_TEST_CASE(RunMixedDataLayout, NEGEMMConvolutionLayerQuantizedFixture<uint8_t>, framework::DatasetMode::ALL,
694  framework::dataset::make("Input", TensorShape(23U, 27U, 5U)),
695  framework::dataset::make("Weights", TensorShape(3U, 3U, 5U, 2U))),
697  framework::dataset::make("Output", TensorShape(11U, 25U, 2U))),
698  framework::dataset::make("PadStrideInfo", PadStrideInfo(2, 1, 0, 0))),
699  framework::dataset::make("Dilation", Size2D(1, 1))),
700  framework::dataset::make("ReshapeWeights", { true })),
703  framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255.f, 10) })),
705 {
706  // Validate output
707  validate(Accessor(_target), _reference, tolerance_qasymm8);
708 }
709 TEST_SUITE_END() // QASYMM8
710 
712 FIXTURE_DATA_TEST_CASE(RunSmall, NEGEMMConvolutionLayerQuantizedFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
713  framework::dataset::make("ReshapeWeights", { true })),
716  framework::dataset::make("QuantizationInfo", { QuantizationInfo(0.01f, -10) })),
718 {
719  // Validate output
720  validate(Accessor(_target), _reference, tolerance_qasymm8);
721 }
724  framework::dataset::make("Input", TensorShape(23U, 27U, 5U)),
725  framework::dataset::make("Weights", TensorShape(3U, 3U, 5U, 2U))),
727  framework::dataset::make("Output", TensorShape(11U, 25U, 2U))),
728  framework::dataset::make("PadStrideInfo", PadStrideInfo(2, 1, 0, 0))),
729  framework::dataset::make("Dilation", Size2D(1, 1))),
730  framework::dataset::make("ReshapeWeights", { true })),
733  framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255.f, 10) })),
735 {
736  // Validate output
737  validate(Accessor(_target), _reference, tolerance_qasymm8);
738 }
739 TEST_SUITE_END() // QASYMM8_SIGNED
740 
743  combine(combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
744  framework::dataset::make("ReshapeWeights", { true })),
750 {
751  // Validate output
752  validate(Accessor(_target), _reference, tolerance_qasymm8);
753 }
755  combine(combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
756  framework::dataset::make("ReshapeWeights", { true })),
762 {
763  // Validate output
764  validate(Accessor(_target), _reference, tolerance_qasymm8);
765 }
766 TEST_SUITE_END() // QSYMM8_PER_CHANNEL
767 TEST_SUITE_END() // Quantized
768 
769 TEST_SUITE_END() // GEMMConvolutionLayer
770 
771 TEST_SUITE(DirectGEMMConv2d)
772 template <typename T>
773 using NEDirectGEMMConv2dLayerFixture = ConvolutionValidationFixture<Tensor, Accessor, NEGEMMConv2d, T>;
774 
775 /** Test case for memory injection in @ref cpu::CpuGemmDirectConv2d.
776  *
777  * Configure the operator once and inject memory at run-time in multiple executions.
778  *
779  * Checks performed in order:
780  * - Both runs compute the same output
781  */
782 TEST_CASE(MemoryInjection, framework::DatasetMode::ALL)
783 {
784  auto conv = std::make_unique<cpu::CpuGemmDirectConv2d>();
786  const auto weight_info = TensorInfo(TensorShape(1U, 3U, 2U, 3U), 1, DataType::F32, DataLayout::NHWC);
787  const auto bias_info = TensorInfo(TensorShape(3U), 1, DataType::F32, DataLayout::NHWC);
788  auto dst_info = TensorInfo(TensorShape(1U, 7U, 3U), 1, DataType::F32, DataLayout::NHWC);
789  const auto conv_info = Conv2dInfo{};
790  conv->configure(&src_info, &weight_info, &bias_info, &dst_info, conv_info);
791 
792  // tensors are newly created every call of this lambda function
793  auto src = create_tensor<Tensor>(src_info);
794  auto weight = create_tensor<Tensor>(weight_info);
795  auto bias = create_tensor<Tensor>(bias_info);
796  src.allocator()->allocate();
797  weight.allocator()->allocate();
798  bias.allocator()->allocate();
799 
800  ITensorPack run_pack{ { TensorType::ACL_SRC_0, &src }, { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
801  ITensorPack prep_pack{ { TensorType::ACL_SRC_1, &weight }, { TensorType::ACL_SRC_2, &bias } };
802 
803  auto mg = MemoryGroup{};
804  auto ws = manage_workspace<Tensor>(conv->workspace(), mg, run_pack, prep_pack);
805 
806  auto run_conv = [&]() -> Tensor
807  {
808  auto dst = create_tensor<Tensor>(dst_info);
809  dst.allocator()->allocate();
810  run_pack.add_tensor(TensorType::ACL_DST, &dst);
811 
812  library->fill_tensor_value(Accessor(src), 1.f);
813  library->fill_tensor_value(Accessor(weight), 2.f);
814  library->fill_tensor_value(Accessor(bias), 3.f);
815  // This operator is configured once and captured by this lambda.
816  conv->prepare(prep_pack);
817  conv->run(run_pack);
818  return dst;
819  };
820  auto result_0 = run_conv();
821  auto result_1 = run_conv();
822  for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
823  {
824  ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
825  }
826 }
827 
828 /** Test case for memory injection in @ref NEGEMMConv2d.
829  *
830  * Make sure @ref NEGEMMConv2d still works through injecting the memory at configure time using the old API.
831  *
832  * Checks performed in order:
833  * - Both runs compute the same output
834  */
835 TEST_CASE(MultipleExecutionWithConfigure, framework::DatasetMode::ALL)
836 {
837  auto conv = std::make_unique<NEGEMMConv2d>();
839  const auto weight_info = TensorInfo(TensorShape(1U, 3U, 2U, 3U), 1, DataType::F32, DataLayout::NHWC);
840  const auto bias_info = TensorInfo(TensorShape(3U), 1, DataType::F32, DataLayout::NHWC);
841  auto dst_info = TensorInfo(TensorShape(1U, 7U, 3U), 1, DataType::F32, DataLayout::NHWC);
842  const auto conv_info = Conv2dInfo{};
843  auto run_conv = [&]()
844  {
845  auto src = create_tensor<Tensor>(src_info);
846  auto weight = create_tensor<Tensor>(weight_info);
847  auto bias = create_tensor<Tensor>(bias_info);
848  auto dst = create_tensor<Tensor>(dst_info);
849  conv->configure(&src, &weight, &bias, &dst, conv_info);
850  src.allocator()->allocate();
851  weight.allocator()->allocate();
852  bias.allocator()->allocate();
853  dst.allocator()->allocate();
854  library->fill_tensor_value(Accessor(src), 1.f);
855  library->fill_tensor_value(Accessor(weight), 2.f);
856  library->fill_tensor_value(Accessor(bias), 3.f);
857  conv->run();
858  return dst;
859  };
860  auto result_0 = run_conv();
861  auto result_1 = run_conv();
862  for(size_t i = 0; i < result_0.info()->tensor_shape().total_size(); ++i)
863  {
864  ARM_COMPUTE_EXPECT(((float *)result_0.buffer())[i] == ((float *)result_1.buffer())[i], framework::LogLevel::ERRORS);
865  }
866 }
867 
868 TEST_SUITE(Float)
869 TEST_SUITE(FP32)
870 FIXTURE_DATA_TEST_CASE(RunSmall, NEDirectGEMMConv2dLayerFixture<float>, framework::DatasetMode::ALL, combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
871  framework::dataset::make("ReshapeWeights", { true })),
873  framework::dataset::make("DataLayout", { DataLayout::NHWC })),
874  ActivationFunctionsDataset))
875 {
876  // Validate output
877  validate(Accessor(_target), _reference, rel_tolerance_f32, 0.f, float(abs_tolerance_f32));
878 }
879 TEST_SUITE_END() // FP32
880 TEST_SUITE_END() // Float
881 
882 #ifdef __aarch64__
883 template <typename T>
884 using NEDirectGEMMConv2dLayerQuantizedFixture = ConvolutionValidationQuantizedFixture<Tensor, Accessor, NEGEMMConv2d, T>;
885 
886 template <typename T>
887 using NEDirectGEMMConv2dLayerQuantizedPerChannelFixture = ConvolutionValidationQuantizedPerChannelFixture<Tensor, Accessor, NEGEMMConv2d, T, int8_t>;
888 
890 {
894 });
895 TEST_SUITE(Quantized)
897 FIXTURE_DATA_TEST_CASE(RunSmall, NEDirectGEMMConv2dLayerQuantizedFixture<uint8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
898  framework::dataset::make("ReshapeWeights", { true })),
900  framework::dataset::make("DataLayout", { DataLayout::NHWC })),
901  framework::dataset::make("QuantizationInfo", { QuantizationInfo(2.f / 255.f, 10) })),
903 {
904  // Validate output
905  validate(Accessor(_target), _reference, tolerance_qasymm8);
906 }
907 TEST_SUITE_END() // QASYMM8
908 
910 FIXTURE_DATA_TEST_CASE(RunSmall, NEDirectGEMMConv2dLayerQuantizedFixture<int8_t>, framework::DatasetMode::ALL, combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
911  framework::dataset::make("ReshapeWeights", { true })),
913  framework::dataset::make("DataLayout", { DataLayout::NHWC })),
914  framework::dataset::make("QuantizationInfo", { QuantizationInfo(0.01f, -10) })),
916 {
917  // Validate output
918  validate(Accessor(_target), _reference, tolerance_qasymm8);
919 }
920 TEST_SUITE_END() // QASYMM8_SIGNED
921 
923 FIXTURE_DATA_TEST_CASE(RunSmallSigned, NEDirectGEMMConv2dLayerQuantizedPerChannelFixture<int8_t>, framework::DatasetMode::ALL,
924  combine(combine(combine(combine(combine(combine(datasets::SmallConvolutionLayerDataset(),
925  framework::dataset::make("ReshapeWeights", { true })),
927  framework::dataset::make("DataLayout", { DataLayout::NHWC })),
931 {
932  // Validate output
933  validate(Accessor(_target), _reference, tolerance_qasymm8);
934 }
935 TEST_SUITE_END() // QSYMM8_PER_CHANNEL
936 TEST_SUITE_END() // Quantized
937 #endif // __aarch64__
938 
939 TEST_SUITE_END() // DirectGEMMConv2d
940 
941 TEST_SUITE_END() // Neon
942 } // namespace validation
943 } // namespace test
944 } // namespace arm_compute
SimpleTensor< float > w
Definition: DFT.cpp:156
Shape of a tensor.
Definition: TensorShape.h:39
Class reprensenting an absolute tolerance value.
Definition: Validation.h:61
constexpr float tolerance_num_f16
F16 Tolerance number.
Definition: cl_gemm.cpp:75
ConvolutionValidationQuantizedFixture< Tensor, Accessor, NEConvolutionLayer, T, true > NEGEMMConvolutionLayerQuantizedMixedDataLayoutFixture
SimpleTensor< float > b
Definition: DFT.cpp:157
ConvolutionValidationFixture< Tensor, Accessor, NEConvolutionLayer, T, true > NEGEMMConvolutionLayerMixedDataLayoutFixture
half_float::half half
16-bit floating point type
Definition: Types.h:48
1 channel, 1 F32 per channel
ARM_COMPUTE_EXPECT(has_error==expected, framework::LogLevel::ERRORS)
ConvolutionValidationQuantizedPerChannelFixture< Tensor, Accessor, NEConvolutionLayer, T, int8_t > NEGEMMConvolutionLayerQuantizedPerChannelFixture
std::enable_if< is_container< T >::value, ContainerDataset< T > >::type make(std::string name, T &&values)
Helper function to create a ContainerDataset.
ConvolutionMethod
Available ConvolutionMethod.
Definition: Types.h:134
Activation Layer Information class.
Definition: Types.h:1625
WinogradConvolutionLayerFastMathValidationFixture< Tensor, Accessor, NEWinogradConvolutionLayer, T, T, false > NEWinogradConvolutionLayerNoBiasFixture
SimpleTensor< float > src
Definition: DFT.cpp:155
Copyright (c) 2017-2022 Arm Limited.
1 channel, 1 F16 per channel
Convolution Layer Weights Information class.
Definition: Types.h:1844
16-bit brain floating-point number
Quantization information.
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)
Accessor implementation for Tensor objects.
Definition: Accessor.h:35
DatasetMode
Possible dataset modes.
Definition: DatasetModes.h:40
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
std::unique_ptr< AssetsLibrary > library
Definition: main.cpp:76
TEST_SUITE_END() FIXTURE_DATA_TEST_CASE(RunSmall
[CLActivationLayer Test snippet]
quantized, asymmetric fixed-point 8-bit number unsigned
const unsigned int num_groups
Definition: Im2Col.cpp:153
const auto QuantizedActivationFunctionsDataset
Input data sets.
Basic implementation of the tensor interface.
Definition: Tensor.h:37
Padding and stride information class.
Definition: Types.h:669
validate(CLAccessor(output_state), expected_output)
UniqueGemmCommon< Top, Tret > gemm(const GemmArgs &args, const OutputStage &os)
Descriptor used by the 2d Convolution function.
Num samples, channels, height, width.
TensorInfo src_info(src_shape, 1, data_type)
quantized, symmetric per channel fixed-point 8-bit number
Convolution using Winograd.
FIXTURE_DATA_TEST_CASE(RunSmall, CLAbsLayerFixture< half >, framework::DatasetMode::PRECOMMIT, combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F16)))
Definition: AbsLayer.cpp:50
ScaleKernelInfo info(interpolation_policy, default_border_mode, PixelValue(), sampling_policy, false)
static ConvolutionMethod get_convolution_method(const ITensorInfo *input, const ITensorInfo *weights, 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)
Static function to check if given info will return the convolution called by NEConvolutionLayer.
WinogradConvolutionLayerFastMathValidationFixture< Tensor, Accessor, NEWinogradConvolutionLayer, T, T, true, true > NEWinogradConvolutionLayerMixedDataLayoutFixture
Class reprensenting a relative tolerance value.
Definition: Validation.h:97
Class for specifying the size of an image or rectangle.
Definition: Size2D.h:34
Num samples, height, width, channels.
Tensor packing service.
Definition: ITensorPack.h:39
Store the tensor&#39;s metadata.
Definition: TensorInfo.h:43
JoinDataset< T, U > concat(T &&dataset1, U &&dataset2)
Helper function to create a JoinDataset.
Definition: JoinDataset.h:160
TEST_CASE(FusedActivation, framework::DatasetMode::ALL)
Validate fused activation expecting the following behaviours:
quantized, asymmetric fixed-point 8-bit number signed
Basic function to compute the convolution layer.
Definition: NEGEMMConv2d.h:49
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}))
TEST_SUITE(QASYMM8_to_F32) FIXTURE_DATA_TEST_CASE(RunSmall
DataType
Available data types.
Definition: Types.h:79
constexpr float abs_tolerance_f32(0.0001f)
F32 Absolute tolerance value for comparing reference&#39;s output against implementation&#39;s output for flo...
combine(datasets::SmallShapes(), framework::dataset::make("DataType", DataType::F32)))
Definition: AbsLayer.cpp:65
Convolution using GEMM.
void configure_conv_function< NEGEMMConv2d, Tensor >(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)
const int32_t * bias