Compute Library
 22.02
CpuElementwiseKernel.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2022 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  */
25 
27 #include "src/core/CPP/Validate.h"
32 
33 #include <arm_neon.h>
34 
35 namespace arm_compute
36 {
37 namespace cpu
38 {
39 namespace kernels
40 {
41 namespace
42 {
43 struct ElementwiseSelectorData
44 {
46  const CPUInfo &ci;
47 };
48 
51 struct ElementwiseKernel
52 {
53  const char *name;
54  const ElementwiseSelector is_selected;
55  UKernelType *ukernel;
56 };
57 
58 template <ArithmeticOperation op>
59 CpuElementwiseKernel::UKernelInfo configure_arithm_func(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
60 {
61  ARM_COMPUTE_UNUSED(src1, dst);
62  static ElementwiseKernel kernels[] =
63  {
64 #if defined(ARM_COMPUTE_ENABLE_SVE)
65  {
66  "sve_fp32_elementwise",
67  [](const ElementwiseSelectorData & data) { return data.dt == DataType::F32 && data.ci.has_sve(); },
68  REGISTER_FP32_SVE((arm_compute::cpu::sve_fp32_elementwise_binary<op>))
69  },
70  {
71  "sve_s32_elementwise",
72  [](const ElementwiseSelectorData & data) { return data.dt == DataType::S32 && data.ci.has_sve(); },
73  REGISTER_INTEGER_SVE((arm_compute::cpu::sve_s32_elementwise_binary<op>))
74  },
75  {
76  "sve_s16_elementwise",
77  [](const ElementwiseSelectorData & data) { return data.dt == DataType::S16 && data.ci.has_sve(); },
78  REGISTER_INTEGER_SVE((arm_compute::cpu::sve_s16_elementwise_binary<op>))
79  },
80  {
81  "sve_fp16_elementwise",
82  [](const ElementwiseSelectorData & data) { return data.dt == DataType::F16 && data.ci.has_sve(); },
83  REGISTER_FP16_SVE((arm_compute::cpu::sve_fp16_elementwise_binary<op>))
84  },
85 #endif /* defined(ARM_COMPUTE_ENABLE_SVE) */
86 #if defined(ARM_COMPUTE_ENABLE_NEON)
87  {
88  "neon_fp32_elementwise",
89 
90  [](const ElementwiseSelectorData & data) { return data.dt == DataType::F32; },
91  REGISTER_FP32_NEON((arm_compute::cpu::neon_fp32_elementwise_binary<op>))
92  },
93  {
94  "neon_s32_elementwise",
95  [](const ElementwiseSelectorData & data) { return data.dt == DataType::S32; },
96  REGISTER_INTEGER_NEON((arm_compute::cpu::neon_s32_elementwise_binary<op>))
97  },
98 #if defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
99  {
100  "neon_fp16_elementwise",
101  [](const ElementwiseSelectorData & data) { return data.dt == DataType::F16 && data.ci.has_fp16(); },
102  REGISTER_FP16_NEON((arm_compute::cpu::neon_fp16_elementwise_binary<op>))
103  },
104 #endif /* defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) */
105  {
106  "neon_s16_elementwise",
107  [](const ElementwiseSelectorData & data) { return data.dt == DataType::S16; },
108  REGISTER_INTEGER_NEON((arm_compute::cpu::neon_s16_elementwise_binary<op>))
109  },
110 #endif /* defined(ARM_COMPUTE_ENABLE_NEON) */
111 #if defined(ARM_COMPUTE_ENABLE_SVE2)
112  {
113  "sve2_qu8_elementwise",
114  [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8 && data.ci.has_sve2(); },
115  REGISTER_QASYMM8_SVE2((arm_compute::cpu::sve2_qasymm8_elementwise_binary<op>))
116  },
117  {
118  "sve2_qs8_elementwise",
119  [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED && data.ci.has_sve2(); },
120  REGISTER_QASYMM8_SIGNED_SVE2((arm_compute::cpu::sve2_qasymm8_signed_elementwise_binary<op>))
121  },
122 #endif /* defined(ARM_COMPUTE_ENABLE_SVE2) */
123 #if defined(ARM_COMPUTE_ENABLE_NEON) || defined(ARM_COMPUTE_ENABLE_SVE)
124  {
125  "neon_qu8_elementwise",
126  [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8; },
127  REGISTER_QASYMM8_NEON((arm_compute::cpu::neon_qasymm8_elementwise_binary<op>))
128  },
129  {
130  "neon_qs8_elementwise",
131  [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED; },
132  REGISTER_QASYMM8_SIGNED_NEON((arm_compute::cpu::neon_qasymm8_signed_elementwise_binary<op>))
133  },
134 #endif /* defined(ARM_COMPUTE_ENABLE_NEON) || defined(ARM_COMPUTE_ENABLE_SVE) */
135  };
136 
137  for(const auto &uk : kernels)
138  {
139  if(uk.is_selected({ src0->data_type(), CPUInfo::get() }))
140  {
141  return { uk.name, uk.ukernel };
142  }
143  }
144 
145  return { "", nullptr };
146 }
147 
148 template <ComparisonOperation op>
149 CpuElementwiseKernel::UKernelInfo configure_comp_func(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
150 {
151  ARM_COMPUTE_UNUSED(src1, dst);
152  static ElementwiseKernel kernels[] =
153  {
154 #if defined(ARM_COMPUTE_ENABLE_SVE)
155  {
156  "sve_u8_comparison",
157  [](const ElementwiseSelectorData & data) { return data.dt == DataType::U8 && data.ci.has_sve(); },
158  REGISTER_INTEGER_SVE(arm_compute::cpu::sve_u8_comparison_elementwise_binary<op>)
159  },
160  {
161  "sve_fp32_comparison",
162  [](const ElementwiseSelectorData & data) { return data.dt == DataType::F32 && data.ci.has_sve(); },
163  REGISTER_FP32_SVE(arm_compute::cpu::sve_fp32_comparison_elementwise_binary<op>)
164  },
165  {
166  "sve_s16_comparison",
167  [](const ElementwiseSelectorData & data) { return data.dt == DataType::S16 && data.ci.has_sve(); },
168  REGISTER_INTEGER_SVE(arm_compute::cpu::sve_s16_comparison_elementwise_binary<op>)
169  },
170  {
171  "sve_s32_comparison",
172  [](const ElementwiseSelectorData & data) { return data.dt == DataType::S32 && data.ci.has_sve(); },
173  REGISTER_INTEGER_SVE(arm_compute::cpu::sve_s32_comparison_elementwise_binary<op>)
174  },
175 #endif /* defined(ARM_COMPUTE_ENABLE_SVE) */
176 #if defined(ARM_COMPUTE_ENABLE_NEON)
177  {
178  "neon_u8_comparison",
179  [](const ElementwiseSelectorData & data) { return data.dt == DataType::U8; },
180  REGISTER_INTEGER_NEON(arm_compute::cpu::neon_u8_comparison_elementwise_binary<op>)
181  },
182  {
183  "neon_fp32_comparison",
184  [](const ElementwiseSelectorData & data) { return data.dt == DataType::F32; },
185  REGISTER_FP32_NEON(arm_compute::cpu::neon_fp32_comparison_elementwise_binary<op>)
186  },
187  {
188  "neon_s16_comparison",
189  [](const ElementwiseSelectorData & data) { return data.dt == DataType::S16; },
190  REGISTER_INTEGER_NEON(arm_compute::cpu::neon_s16_comparison_elementwise_binary<op>)
191  },
192  {
193  "neon_s32_comparison",
194  [](const ElementwiseSelectorData & data) { return data.dt == DataType::S32; },
195  REGISTER_INTEGER_NEON(arm_compute::cpu::neon_s32_comparison_elementwise_binary<op>)
196  },
197 #endif /* defined(ARM_COMPUTE_ENABLE_NEON) */
198 #if defined(ARM_COMPUTE_ENABLE_SVE2)
199  {
200  "sve2_qu8_comparison",
201  [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8 && data.ci.has_sve2(); },
202  REGISTER_QASYMM8_SVE2(arm_compute::cpu::sve2_qasymm8_comparison_elementwise_binary<op>)
203  },
204  {
205  "sve2_qs8_comparison",
206  [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED && data.ci.has_sve2(); },
207  REGISTER_QASYMM8_SIGNED_SVE2(arm_compute::cpu::sve2_qasymm8_signed_comparison_elementwise_binary<op>)
208  },
209 #endif /* defined(ARM_COMPUTE_ENABLE_SVE2) */
210 #if defined(ARM_COMPUTE_ENABLE_NEON) || defined(ARM_COMPUTE_ENABLE_SVE)
211  {
212  "neon_qu8_comparison",
213  [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8; },
214  REGISTER_QASYMM8_NEON(arm_compute::cpu::neon_qasymm8_comparison_elementwise_binary<op>)
215  },
216  {
217  "neon_qs8_comparison",
218  [](const ElementwiseSelectorData & data) { return data.dt == DataType::QASYMM8_SIGNED; },
219  REGISTER_QASYMM8_SIGNED_NEON(arm_compute::cpu::neon_qasymm8_signed_comparison_elementwise_binary<op>)
220  },
221 #endif /* defined(ARM_COMPUTE_ENABLE_NEON ||ARM_COMPUTE_ENABLE_SVE) */
222 #if defined(ARM_COMPUTE_ENABLE_SVE)
223  {
224  "sve_fp16_comparison",
225  [](const ElementwiseSelectorData & data) { return data.dt == DataType::F16 && data.ci.has_sve(); },
226  REGISTER_FP16_SVE(arm_compute::cpu::sve_fp16_comparison_elementwise_binary<op>)
227  },
228 #endif /* defined(ARM_COMPUTE_ENABLE_SVE) */
229 #if defined(ARM_COMPUTE_ENABLE_NEON) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
230  {
231  "neon_fp16_comparison",
232  [](const ElementwiseSelectorData & data) { return data.dt == DataType::F16 && data.ci.has_fp16(); },
233  REGISTER_FP16_NEON(arm_compute::cpu::neon_fp16_comparison_elementwise_binary<op>)
234  },
235 #endif /* defined(ARM_COMPUTE_ENABLE_NEON) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) */
236  };
237 
238  for(const auto &uk : kernels)
239  {
240  if(uk.is_selected({ src0->data_type(), CPUInfo::get() }))
241  {
242  return { uk.name, uk.ukernel };
243  }
244  }
245 
246  return { "", nullptr };
247 }
248 } // namespace
249 
250 Status CpuElementwiseKernel::validate_arguments_common(const ITensorInfo &src0, const ITensorInfo &src1, const ITensorInfo &dst)
251 {
254 
255  const TensorShape out_shape = TensorShape::broadcast_shape(src0.tensor_shape(), src1.tensor_shape());
256 
257  ARM_COMPUTE_RETURN_ERROR_ON_MSG(out_shape.total_size() == 0, "Inputs are not broadcast compatible");
258 
259  // Validate in case of configured dst
260  if(dst.total_size() > 0)
261  {
262  ARM_COMPUTE_RETURN_ERROR_ON_MSG(detail::have_different_dimensions(out_shape, dst.tensor_shape(), 0),
263  "Wrong shape for output");
264  }
265 
266  return Status{};
267 }
268 
269 void CpuElementwiseKernel::configure_common(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
270 {
271  ARM_COMPUTE_ERROR_ON_NULLPTR(src0, src1, dst);
272 
273  const auto uk = get_implementation(src0, src1, dst);
274 
275  _run_method = uk.ukernel;
276  _name = std::string("CpuElementwiseKernel").append("/").append(uk.name);
277 
278  // If any of shapes is dynamic, expect a configured window and dst at run-time.
279  if(src0->is_dynamic() || src1->is_dynamic())
280  {
281  return;
282  }
283 
284  auto shape_and_window = compute_output_shape_and_window(src0->tensor_shape(), src1->tensor_shape());
285  auto_init_if_empty(*dst, shape_and_window.first, 1, src0->data_type());
286  ICpuKernel::configure(shape_and_window.second);
287 }
288 
289 void CpuElementwiseKernel::run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info)
290 {
291  ARM_COMPUTE_UNUSED(info);
292  ARM_COMPUTE_ERROR_ON(_run_method == nullptr);
293 
294  auto src0 = tensors.get_const_tensor(TensorType::ACL_SRC_0);
295  auto src1 = tensors.get_const_tensor(TensorType::ACL_SRC_1);
296  auto dst = tensors.get_tensor(TensorType::ACL_DST);
297 
298  _run_method(src0, src1, dst, window);
299 }
300 
301 const char *CpuElementwiseKernel::name() const
302 {
303  return _name.c_str();
304 }
305 
306 /** Arithmetic operators (min, max, squared_diff) */
308 {
309  ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*src0, *src1, *dst));
310  _op = op;
311  configure_common(src0, src1, dst);
312 }
313 
314 Status CpuArithmeticKernel::validate_arguments(const ITensorInfo &src0, const ITensorInfo &src1, const ITensorInfo &dst)
315 {
317  // Validate in case of configured dst
318  if(dst.total_size() > 0)
319  {
321  }
322  return validate_arguments_common(src0, src1, dst);
323 }
324 
326 {
327  ARM_COMPUTE_UNUSED(op);
328  ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src0, src1, dst);
329  ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*src0, *src1, *dst));
330  return Status{};
331 }
332 
333 CpuElementwiseKernel::UKernelInfo CpuArithmeticKernel::get_implementation(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
334 {
335  switch(_op)
336  {
338  return configure_arithm_func<ArithmeticOperation::MAX>(src0, src1, dst);
340  return configure_arithm_func<ArithmeticOperation::MIN>(src0, src1, dst);
342  return configure_arithm_func<ArithmeticOperation::SQUARED_DIFF>(src0, src1, dst);
344  return configure_arithm_func<ArithmeticOperation::PRELU>(src0, src1, dst);
346  return configure_arithm_func<ArithmeticOperation::DIV>(src0, src1, dst);
348  return configure_arithm_func<ArithmeticOperation::POWER>(src0, src1, dst);
349  default:
350  ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
351  }
352  return { "", nullptr };
353 }
354 
355 /** The division operator */
356 
358 {
359  ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*src0, *src1, *dst));
361  configure_common(src0, src1, dst);
362 }
363 
364 Status CpuDivisionKernel::validate_arguments(const ITensorInfo &src0, const ITensorInfo &src1, const ITensorInfo &dst)
365 {
367  return CpuArithmeticKernel::validate_arguments(src0, src1, dst);
368 }
369 
371 {
372  ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src0, src1, dst);
373  ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*src0, *src1, *dst));
374  return Status{};
375 }
376 
377 /** The power operator */
378 void CpuPowerKernel::configure(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
379 {
380  ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*src0, *src1, *dst));
382  configure_common(src0, src1, dst);
383 }
384 
385 Status CpuPowerKernel::validate_arguments(const ITensorInfo &src0, const ITensorInfo &src1, const ITensorInfo &dst)
386 {
388  return CpuArithmeticKernel::validate_arguments(src0, src1, dst);
389 }
390 
392 {
393  ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src0, src1, dst);
394  ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*src0, *src1, *dst));
395  return Status{};
396 }
397 
398 /** Comparison operators (equal, not equal, less than, greater than, less than or equal, greater than or equal) */
400 {
401  ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*src0, *src1, *dst));
402  _op = op;
403  configure_common(src0, src1, dst);
404 }
405 
406 Status CpuComparisonKernel::validate_arguments(const ITensorInfo &src0, const ITensorInfo &src1, const ITensorInfo &dst)
407 {
409  // Validate in case of configured dst
410  if(dst.total_size() > 0)
411  {
413  }
414  return validate_arguments_common(src0, src1, dst);
415 }
416 
418 {
419  ARM_COMPUTE_UNUSED(op);
420  ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(src0, src1, dst);
421  ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*src0, *src1, *dst));
422  return Status{};
423 }
424 
425 CpuElementwiseKernel::UKernelInfo CpuComparisonKernel::get_implementation(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
426 {
427  switch(_op)
428  {
430  return configure_comp_func<ComparisonOperation::Equal>(src0, src1, dst);
432  return configure_comp_func<ComparisonOperation::NotEqual>(src0, src1, dst);
434  return configure_comp_func<ComparisonOperation::Greater>(src0, src1, dst);
436  return configure_comp_func<ComparisonOperation::GreaterEqual>(src0, src1, dst);
438  return configure_comp_func<ComparisonOperation::Less>(src0, src1, dst);
440  return configure_comp_func<ComparisonOperation::LessEqual>(src0, src1, dst);
441  default:
442  ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
443  }
444  return { "", nullptr };
445 }
446 } // namespace kernels
447 } // namespace cpu
448 } // namespace arm_compute
ArithmeticOperation
Available element-wise operations.
Definition: Types.h:476
void configure(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
Configure kernel.
void configure(ArithmeticOperation op, const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
Configure kernel.
#define ARM_COMPUTE_RETURN_ERROR_ON_CPU_F16_UNSUPPORTED(tensor)
Definition: Validate.h:115
#define REGISTER_FP16_NEON(func_name)
Definition: Registrars.h:48
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
Definition: Error.h:352
1 channel, 1 U8 per channel
#define REGISTER_FP32_NEON(func_name)
Definition: Registrars.h:74
#define ARM_COMPUTE_RETURN_ON_ERROR(status)
Checks if a status contains an error and returns it.
Definition: Error.h:204
1 channel, 1 F32 per channel
#define REGISTER_FP32_SVE(func_name)
Definition: Registrars.h:75
static TensorShape broadcast_shape(const Shapes &... shapes)
If shapes are broadcast compatible, return the broadcasted shape.
Definition: TensorShape.h:211
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:466
#define REGISTER_QASYMM8_SIGNED_NEON(func_name)
Definition: Registrars.h:96
static Status validate(const ITensorInfo *src0, const ITensorInfo *src1, const ITensorInfo *dst)
Static function to check if given info will lead to a valid configuration.
Store the tensor&#39;s metadata.
Definition: ITensorInfo.h:40
#define ARM_COMPUTE_ERROR_THROW_ON(status)
Definition: Error.h:455
Status class.
Definition: Error.h:52
void configure(ComparisonOperation op, const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
Configure kernel.
const char * name() const override
Name of the kernel.
decltype(strategy::transforms) typedef type
Copyright (c) 2017-2021 Arm Limited.
1 channel, 1 F16 per channel
static Status validate(ArithmeticOperation op, const ITensorInfo *src0, const ITensorInfo *src1, const ITensorInfo *dst)
Static function to check if given info will lead to a valid configuration.
#define REGISTER_INTEGER_NEON(func_name)
Definition: Registrars.h:165
DataType dt
#define ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(...)
Definition: Validate.h:159
1 channel, 1 S32 per channel
void run_op(ITensorPack &tensors, const Window &window, const ThreadInfo &info) override
Execute the kernel on the passed window.
const ITensor * get_const_tensor(int id) const
Get constant tensor of a given id.
Definition: ITensorPack.cpp:54
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
Definition: Error.h:152
void configure(const ITensorInfo *src0, const ITensorInfo *src1, ITensorInfo *dst)
Configure kernel.
#define REGISTER_QASYMM8_NEON(func_name)
Definition: Registrars.h:117
quantized, asymmetric fixed-point 8-bit number unsigned
#define REGISTER_INTEGER_SVE(func_name)
Definition: Registrars.h:166
bool auto_init_if_empty(ITensorInfo &info, const TensorShape &shape, int num_channels, DataType data_type, QuantizationInfo quantization_info=QuantizationInfo())
Auto initialize the tensor info (shape, number of channels and data type) if the current assignment i...
bool have_different_dimensions(const Dimensions< T > &dim1, const Dimensions< T > &dim2, unsigned int upper_dim)
Definition: Validate.h:47
#define REGISTER_QASYMM8_SIGNED_SVE2(func_name)
Definition: Registrars.h:98
const ElementwiseSelector is_selected
ComparisonOperation
Supported comparison operations.
Definition: Types.h:173
y*x if x < 0, x otherwise
1 channel, 1 S16 per channel
static Status validate(const ITensorInfo *src0, const ITensorInfo *src1, const ITensorInfo *dst)
Static function to check if given info will lead to a valid configuration.
ScaleKernelInfo info(interpolation_policy, default_border_mode, PixelValue(), sampling_policy, false)
ITensor * get_tensor(int id)
Get tensor of a given id from the pac.
Definition: ITensorPack.cpp:64
Information about executing thread and CPU.
Definition: CPPTypes.h:169
virtual size_t total_size() const =0
Returns the total size of the tensor in bytes.
#define REGISTER_FP16_SVE(func_name)
Definition: Registrars.h:49
void(const ITensor *, const ITensor *, ITensor *, const Window &) ElementwiseFunction
#define ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(...)
Definition: Validate.h:541
#define ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(t, c,...)
Definition: Validate.h:788
#define ARM_COMPUTE_RETURN_ERROR_ON_MSG(cond, msg)
If the condition is true, an error is returned.
Definition: Error.h:244
Tensor packing service.
Definition: ITensorPack.h:39
#define ARM_COMPUTE_ERROR_ON_NULLPTR(...)
Definition: Validate.h:157
const CPUInfo & ci
quantized, asymmetric fixed-point 8-bit number signed
UKernelType * ukernel
#define REGISTER_QASYMM8_SVE2(func_name)
Definition: Registrars.h:119
DataType
Available data types.
Definition: Types.h:79
const char * name
Describe a multidimensional execution window.
Definition: Window.h:39
static Status validate(ComparisonOperation op, const ITensorInfo *src0, const ITensorInfo *src1, const ITensorInfo *dst)
Static function to check if given info will lead to a valid configuration.