Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1 | /* |
Mohammed Suhail Munshi | d538d16 | 2023-02-16 16:22:32 +0000 | [diff] [blame] | 2 | * Copyright (c) 2016-2023 Arm Limited. |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 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 | */ |
Michalis Spyrou | f464337 | 2019-11-29 16:17:13 +0000 | [diff] [blame] | 24 | #ifndef ARM_COMPUTE_TYPES_H |
| 25 | #define ARM_COMPUTE_TYPES_H |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 26 | |
| 27 | #include "arm_compute/core/Coordinates.h" |
Georgios Pinitas | 4c5469b | 2019-05-21 13:32:43 +0100 | [diff] [blame] | 28 | #include "arm_compute/core/QuantizationInfo.h" |
Isabella Gottardi | 6e464c3 | 2018-01-26 12:32:45 +0000 | [diff] [blame] | 29 | #include "arm_compute/core/Size2D.h" |
Adnan AlSinan | e4563a0 | 2021-09-01 15:32:03 +0100 | [diff] [blame] | 30 | #include "arm_compute/core/Size3D.h" |
Georgios Pinitas | 8795ffb | 2017-12-01 16:13:40 +0000 | [diff] [blame] | 31 | #include "arm_compute/core/Strides.h" |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 32 | #include "arm_compute/core/TensorShape.h" |
SiCongLi | 579ca84 | 2021-10-18 09:38:33 +0100 | [diff] [blame] | 33 | #include "arm_compute/core/experimental/IPostOp.h" |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 34 | #include "arm_compute/core/utils/misc/Macros.h" |
Georgios Pinitas | e8291ac | 2020-02-26 09:58:13 +0000 | [diff] [blame] | 35 | #include "support/Bfloat16.h" |
Georgios Pinitas | 583137c | 2017-08-31 18:12:42 +0100 | [diff] [blame] | 36 | #include "support/Half.h" |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 37 | |
Michel Iwaniec | 5dfeae6 | 2017-11-29 10:48:23 +0000 | [diff] [blame] | 38 | #include <cmath> |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 39 | #include <cstddef> |
| 40 | #include <cstdint> |
Isabella Gottardi | a7acb3c | 2019-01-08 13:48:44 +0000 | [diff] [blame] | 41 | #include <map> |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 42 | #include <string> |
| 43 | #include <utility> |
| 44 | |
| 45 | namespace arm_compute |
| 46 | { |
Georgios Pinitas | 583137c | 2017-08-31 18:12:42 +0100 | [diff] [blame] | 47 | /** 16-bit floating point type */ |
| 48 | using half = half_float::half; |
| 49 | |
Georgios Pinitas | 8795ffb | 2017-12-01 16:13:40 +0000 | [diff] [blame] | 50 | /** Permutation vector */ |
| 51 | using PermutationVector = Strides; |
Georgios Pinitas | 77589b5 | 2018-08-21 14:41:35 +0100 | [diff] [blame] | 52 | /** Bidirectional strides */ |
| 53 | using BiStrides = Coordinates; |
Georgios Pinitas | 8795ffb | 2017-12-01 16:13:40 +0000 | [diff] [blame] | 54 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 55 | /** Image colour formats */ |
| 56 | enum class Format |
| 57 | { |
Daniil Efremov | 02bf80d | 2017-11-22 00:26:51 +0700 | [diff] [blame] | 58 | UNKNOWN, /**< Unknown image format */ |
| 59 | U8, /**< 1 channel, 1 U8 per channel */ |
| 60 | S16, /**< 1 channel, 1 S16 per channel */ |
| 61 | U16, /**< 1 channel, 1 U16 per channel */ |
| 62 | S32, /**< 1 channel, 1 S32 per channel */ |
| 63 | U32, /**< 1 channel, 1 U32 per channel */ |
Georgios Pinitas | e8291ac | 2020-02-26 09:58:13 +0000 | [diff] [blame] | 64 | BFLOAT16, /**< 16-bit brain floating-point number */ |
Daniil Efremov | 02bf80d | 2017-11-22 00:26:51 +0700 | [diff] [blame] | 65 | F16, /**< 1 channel, 1 F16 per channel */ |
| 66 | F32, /**< 1 channel, 1 F32 per channel */ |
| 67 | UV88, /**< 2 channel, 1 U8 per channel */ |
| 68 | RGB888, /**< 3 channels, 1 U8 per channel */ |
| 69 | RGBA8888, /**< 4 channels, 1 U8 per channel */ |
| 70 | YUV444, /**< A 3 plane of 8 bit 4:4:4 sampled Y, U, V planes */ |
| 71 | YUYV422, /**< A single plane of 32-bit macro pixel of Y0, U0, Y1, V0 bytes */ |
| 72 | NV12, /**< A 2 plane YUV format of Luma (Y) and interleaved UV data at 4:2:0 sampling */ |
| 73 | NV21, /**< A 2 plane YUV format of Luma (Y) and interleaved VU data at 4:2:0 sampling */ |
| 74 | IYUV, /**< A 3 plane of 8-bit 4:2:0 sampled Y, U, V planes */ |
| 75 | UYVY422 /**< A single plane of 32-bit macro pixel of U0, Y0, V0, Y1 byte */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 76 | }; |
| 77 | |
| 78 | /** Available data types */ |
| 79 | enum class DataType |
| 80 | { |
Georgios Pinitas | 8217c8e | 2019-11-11 18:24:22 +0000 | [diff] [blame] | 81 | UNKNOWN, /**< Unknown data type */ |
| 82 | U8, /**< unsigned 8-bit number */ |
| 83 | S8, /**< signed 8-bit number */ |
| 84 | QSYMM8, /**< quantized, symmetric fixed-point 8-bit number */ |
| 85 | QASYMM8, /**< quantized, asymmetric fixed-point 8-bit number unsigned */ |
| 86 | QASYMM8_SIGNED, /**< quantized, asymmetric fixed-point 8-bit number signed */ |
| 87 | QSYMM8_PER_CHANNEL, /**< quantized, symmetric per channel fixed-point 8-bit number */ |
| 88 | U16, /**< unsigned 16-bit number */ |
| 89 | S16, /**< signed 16-bit number */ |
| 90 | QSYMM16, /**< quantized, symmetric fixed-point 16-bit number */ |
| 91 | QASYMM16, /**< quantized, asymmetric fixed-point 16-bit number */ |
| 92 | U32, /**< unsigned 32-bit number */ |
| 93 | S32, /**< signed 32-bit number */ |
| 94 | U64, /**< unsigned 64-bit number */ |
| 95 | S64, /**< signed 64-bit number */ |
Georgios Pinitas | e8291ac | 2020-02-26 09:58:13 +0000 | [diff] [blame] | 96 | BFLOAT16, /**< 16-bit brain floating-point number */ |
Georgios Pinitas | 8217c8e | 2019-11-11 18:24:22 +0000 | [diff] [blame] | 97 | F16, /**< 16-bit floating-point number */ |
| 98 | F32, /**< 32-bit floating-point number */ |
| 99 | F64, /**< 64-bit floating-point number */ |
| 100 | SIZET /**< size_t */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 101 | }; |
| 102 | |
Daniil Efremov | 02bf80d | 2017-11-22 00:26:51 +0700 | [diff] [blame] | 103 | /** Available Sampling Policies */ |
| 104 | enum class SamplingPolicy |
| 105 | { |
| 106 | CENTER, /**< Samples are taken at pixel center */ |
| 107 | TOP_LEFT /**< Samples are taken at pixel top left corner */ |
| 108 | }; |
| 109 | |
Vidhya Sudhan Loganathan | d646ae1 | 2018-11-19 15:18:20 +0000 | [diff] [blame] | 110 | /** [DataLayout enum definition] **/ |
| 111 | |
Georgios Pinitas | 4074c99 | 2018-01-30 18:13:46 +0000 | [diff] [blame] | 112 | /** Supported tensor data layouts */ |
| 113 | enum class DataLayout |
| 114 | { |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 115 | UNKNOWN, /**< Unknown data layout */ |
| 116 | NCHW, /**< Num samples, channels, height, width */ |
Adnan AlSinan | e4563a0 | 2021-09-01 15:32:03 +0100 | [diff] [blame] | 117 | NHWC, /**< Num samples, height, width, channels */ |
Giorgio Arena | c9fe9fc | 2021-10-06 12:54:29 +0100 | [diff] [blame] | 118 | NCDHW, /**< Num samples, channels, depth, height, width */ |
Adnan AlSinan | e4563a0 | 2021-09-01 15:32:03 +0100 | [diff] [blame] | 119 | NDHWC /**< Num samples, depth, height, width, channels */ |
Georgios Pinitas | 4074c99 | 2018-01-30 18:13:46 +0000 | [diff] [blame] | 120 | }; |
Vidhya Sudhan Loganathan | d646ae1 | 2018-11-19 15:18:20 +0000 | [diff] [blame] | 121 | /** [DataLayout enum definition] **/ |
Georgios Pinitas | 4074c99 | 2018-01-30 18:13:46 +0000 | [diff] [blame] | 122 | |
Isabella Gottardi | d17a677 | 2018-02-27 17:41:55 +0000 | [diff] [blame] | 123 | /** Supported tensor data layout dimensions */ |
| 124 | enum class DataLayoutDimension |
| 125 | { |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 126 | CHANNEL, /**< channel */ |
| 127 | HEIGHT, /**< height */ |
| 128 | WIDTH, /**< width */ |
Giorgio Arena | c9fe9fc | 2021-10-06 12:54:29 +0100 | [diff] [blame] | 129 | DEPTH, /**< depth */ |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 130 | BATCHES /**< batches */ |
Isabella Gottardi | d17a677 | 2018-02-27 17:41:55 +0000 | [diff] [blame] | 131 | }; |
| 132 | |
Georgios Pinitas | 7900a9e | 2018-11-23 11:44:58 +0000 | [diff] [blame] | 133 | /** Available ConvolutionMethod*/ |
| 134 | enum class ConvolutionMethod |
| 135 | { |
Georgios Pinitas | c0b6f76 | 2020-11-02 01:37:17 +0000 | [diff] [blame] | 136 | GEMM, /**< Convolution using GEMM */ |
| 137 | GEMM_CONV2D, /**< Direct 2D GEMM convolution */ |
| 138 | DIRECT, /**< Direct convolution */ |
Gian Marco Iodice | a5cb79f | 2022-12-28 13:53:51 +0000 | [diff] [blame] | 139 | INDIRECT, /**< Indirect convolution */ |
Georgios Pinitas | c0b6f76 | 2020-11-02 01:37:17 +0000 | [diff] [blame] | 140 | WINOGRAD, /**< Convolution using Winograd */ |
| 141 | FFT /**< Convolution using FFT */ |
Georgios Pinitas | 7900a9e | 2018-11-23 11:44:58 +0000 | [diff] [blame] | 142 | }; |
| 143 | |
Manuel Bottini | 05069f0 | 2019-09-26 17:18:26 +0100 | [diff] [blame] | 144 | /** Available DepthwiseConvolutionFunction*/ |
| 145 | enum class DepthwiseConvolutionFunction |
| 146 | { |
| 147 | OPTIMIZED, /**< Optimized Depthwise Convolution */ |
| 148 | GENERIC, /**< Generic Depthwise Convolution */ |
| 149 | }; |
| 150 | |
giuros01 | 46a49a0 | 2019-04-01 13:50:22 +0100 | [diff] [blame] | 151 | /** Available DeconvolutionMethod*/ |
| 152 | enum class DeconvolutionMethod |
| 153 | { |
Gunes Bayir | ec0113d | 2022-11-09 09:26:27 +0000 | [diff] [blame] | 154 | GEMM, /**< Deconvolution using GEMM */ |
| 155 | DIRECT, /**< Direct deconvolution */ |
| 156 | UPSCALE_CONV2D /**< Deconvolution with Upscaling */ |
giuros01 | 46a49a0 | 2019-04-01 13:50:22 +0100 | [diff] [blame] | 157 | }; |
| 158 | |
Manuel Bottini | 2732cca | 2019-05-28 11:44:41 +0100 | [diff] [blame] | 159 | /** Available FuseBatchNormalizationType*/ |
| 160 | enum class FuseBatchNormalizationType |
| 161 | { |
| 162 | CONVOLUTION, /**< For Convolution weights */ |
| 163 | DEPTHWISECONVOLUTION /**< For Depthwise Convolution weights*/ |
| 164 | }; |
| 165 | |
Usama Arif | 89890c6 | 2019-03-19 10:57:05 +0000 | [diff] [blame] | 166 | /** Padding mode to use for PadLayer */ |
| 167 | enum class PaddingMode |
| 168 | { |
| 169 | CONSTANT, |
| 170 | REFLECT, |
| 171 | SYMMETRIC |
| 172 | }; |
| 173 | |
Georgios Pinitas | 7900a9e | 2018-11-23 11:44:58 +0000 | [diff] [blame] | 174 | /** Supported comparison operations */ |
| 175 | enum class ComparisonOperation |
| 176 | { |
| 177 | Equal, /**< Equal comparison ( \f$ x == y \f$ ) */ |
| 178 | NotEqual, /**< NotEqual comparison ( \f$ x != y \f$ ) */ |
| 179 | Greater, /**< Greater comparison ( \f$ x > y \f$ ) */ |
| 180 | GreaterEqual, /**< Greater equal comparison ( \f$ x >= y \f$ ) */ |
| 181 | Less, /**< Less comparison ( \f$ x < y \f$ ) */ |
| 182 | LessEqual /**< Less equal comparison ( \f$ x <= y \f$ ) */ |
| 183 | }; |
| 184 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 185 | /** Container for valid region of a window */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 186 | struct ValidRegion |
| 187 | { |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 188 | /** Default constructor */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 189 | ValidRegion() |
| 190 | : anchor{}, shape{} |
| 191 | { |
| 192 | } |
| 193 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 194 | /** Allow instances of this class to be copy constructed */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 195 | ValidRegion(const ValidRegion &) = default; |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 196 | /** Allow instances of this class to be move constructed */ |
| 197 | ValidRegion(ValidRegion &&) = default; |
| 198 | /** Allow instances of this class to be copied */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 199 | ValidRegion &operator=(const ValidRegion &) = default; |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 200 | /** Allow instances of this class to be moved */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 201 | ValidRegion &operator=(ValidRegion &&) = default; |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 202 | /** Default destructor */ |
| 203 | ~ValidRegion() = default; |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 204 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 205 | /** Constructor for a valid region with default number of dimensions |
| 206 | * |
| 207 | * @param[in] an_anchor Anchor for the start of the valid region. |
| 208 | * @param[in] a_shape Shape of the valid region. |
| 209 | * |
| 210 | */ |
Diego Lopez Recas | bcbc970 | 2017-12-18 11:28:27 +0000 | [diff] [blame] | 211 | ValidRegion(const Coordinates &an_anchor, const TensorShape &a_shape) |
| 212 | : anchor{ an_anchor }, shape{ a_shape } |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 213 | { |
Diego Lopez Recas | bcbc970 | 2017-12-18 11:28:27 +0000 | [diff] [blame] | 214 | anchor.set_num_dimensions(std::max(anchor.num_dimensions(), shape.num_dimensions())); |
| 215 | } |
| 216 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 217 | /** Constructor for a valid region with specified number of dimensions |
| 218 | * |
| 219 | * @param[in] an_anchor Anchor for the start of the valid region. |
| 220 | * @param[in] a_shape Shape of the valid region. |
| 221 | * @param[in] num_dimensions Number of dimensions (must be >= number of dimensions of anchor and shape). |
| 222 | * |
| 223 | */ |
Diego Lopez Recas | bcbc970 | 2017-12-18 11:28:27 +0000 | [diff] [blame] | 224 | ValidRegion(const Coordinates &an_anchor, const TensorShape &a_shape, size_t num_dimensions) |
| 225 | : anchor{ an_anchor }, shape{ a_shape } |
| 226 | { |
| 227 | ARM_COMPUTE_ERROR_ON(num_dimensions < std::max(anchor.num_dimensions(), shape.num_dimensions())); |
| 228 | anchor.set_num_dimensions(num_dimensions); |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 229 | } |
| 230 | |
| 231 | /** Return the start of the valid region for the given dimension @p d */ |
| 232 | int start(unsigned int d) const |
| 233 | { |
| 234 | return anchor[d]; |
| 235 | } |
| 236 | |
| 237 | /** Return the end of the valid region for the given dimension @p d */ |
| 238 | int end(unsigned int d) const |
| 239 | { |
| 240 | return anchor[d] + shape[d]; |
| 241 | } |
| 242 | |
Diego Lopez Recas | 35ceeb2 | 2017-12-04 18:56:10 +0000 | [diff] [blame] | 243 | /** Accessor to set the value of anchor and shape for one of the dimensions. |
| 244 | * |
| 245 | * @param[in] dimension Dimension for which the value is set. |
| 246 | * @param[in] start Value to be set in anchor for the dimension. |
| 247 | * @param[in] size Value to be set in shape for the dimension. |
| 248 | * |
| 249 | * @return *this. |
| 250 | */ |
| 251 | ValidRegion &set(size_t dimension, int start, size_t size) |
| 252 | { |
| 253 | anchor.set(dimension, start); |
| 254 | shape.set(dimension, size); |
| 255 | return *this; |
| 256 | } |
| 257 | |
SiCong Li | b63b119 | 2022-01-28 18:24:39 +0000 | [diff] [blame] | 258 | /** Check whether two valid regions are equal. |
| 259 | * |
| 260 | * @param[in] lhs LHS valid region |
| 261 | * @param[in] rhs RHS valid region |
| 262 | * |
| 263 | * @return True if the valid regions are the same. |
| 264 | */ |
| 265 | inline friend bool operator==(const ValidRegion &lhs, const ValidRegion &rhs); |
| 266 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 267 | Coordinates anchor; /**< Anchor for the start of the valid region. */ |
| 268 | TensorShape shape; /**< Shape of the valid region. */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 269 | }; |
SiCong Li | b63b119 | 2022-01-28 18:24:39 +0000 | [diff] [blame] | 270 | inline bool operator==(const ValidRegion &lhs, const ValidRegion &rhs) |
| 271 | { |
| 272 | return (lhs.anchor == rhs.anchor) && (lhs.shape == rhs.shape); |
| 273 | } |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 274 | |
| 275 | /** Methods available to handle borders */ |
| 276 | enum class BorderMode |
| 277 | { |
| 278 | UNDEFINED, /**< Borders are left undefined */ |
| 279 | CONSTANT, /**< Pixels outside the image are assumed to have a constant value */ |
| 280 | REPLICATE /**< Pixels outside the image are assumed to have the same value as the closest image pixel */ |
| 281 | }; |
| 282 | |
| 283 | /** Container for 2D border size */ |
| 284 | struct BorderSize |
| 285 | { |
| 286 | /** Empty border, i.e. no border */ |
Pablo Marquez Tello | 383de02 | 2021-03-18 11:31:13 +0000 | [diff] [blame] | 287 | constexpr BorderSize() noexcept |
| 288 | : top{ 0 }, |
| 289 | right{ 0 }, |
| 290 | bottom{ 0 }, |
| 291 | left{ 0 } |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 292 | { |
| 293 | } |
| 294 | |
| 295 | /** Border with equal size around the 2D plane */ |
Pablo Marquez Tello | 383de02 | 2021-03-18 11:31:13 +0000 | [diff] [blame] | 296 | explicit constexpr BorderSize(unsigned int size) noexcept |
| 297 | : top{ size }, |
| 298 | right{ size }, |
| 299 | bottom{ size }, |
| 300 | left{ size } |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 301 | { |
| 302 | } |
| 303 | |
| 304 | /** Border with same size for top/bottom and left/right */ |
| 305 | constexpr BorderSize(unsigned int top_bottom, unsigned int left_right) |
| 306 | : top{ top_bottom }, right{ left_right }, bottom{ top_bottom }, left{ left_right } |
| 307 | { |
| 308 | } |
| 309 | |
| 310 | /** Border with different sizes */ |
| 311 | constexpr BorderSize(unsigned int top, unsigned int right, unsigned int bottom, unsigned int left) |
| 312 | : top{ top }, right{ right }, bottom{ bottom }, left{ left } |
| 313 | { |
| 314 | } |
| 315 | |
| 316 | /** Check if the entire border is zero */ |
| 317 | constexpr bool empty() const |
| 318 | { |
| 319 | return top == 0 && right == 0 && bottom == 0 && left == 0; |
| 320 | } |
| 321 | |
| 322 | /** Check if the border is the same size on all sides */ |
| 323 | constexpr bool uniform() const |
| 324 | { |
| 325 | return top == right && top == bottom && top == left; |
| 326 | } |
| 327 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 328 | /** Scale this border size. |
| 329 | * |
| 330 | * @param[in] scale Scale to multiply border size by. |
| 331 | * |
| 332 | * @return *this. |
| 333 | */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 334 | BorderSize &operator*=(float scale) |
| 335 | { |
| 336 | top *= scale; |
| 337 | right *= scale; |
| 338 | bottom *= scale; |
| 339 | left *= scale; |
| 340 | |
| 341 | return *this; |
| 342 | } |
| 343 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 344 | /** Scale a copy of this border size. |
| 345 | * |
| 346 | * @param[in] scale Scale to multiply border size by. |
| 347 | * |
| 348 | * @return a scaled copy of this. |
| 349 | */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 350 | BorderSize operator*(float scale) |
| 351 | { |
| 352 | BorderSize size = *this; |
| 353 | size *= scale; |
| 354 | |
| 355 | return size; |
| 356 | } |
| 357 | |
Giorgio Arena | 1e2af2a | 2020-10-15 17:39:41 +0100 | [diff] [blame] | 358 | /** Check equality with another BorderSize struct |
| 359 | * |
| 360 | * @param[in] rhs other struct to check against |
| 361 | * |
| 362 | * @return true if they are equal |
| 363 | */ |
SiCong Li | b63b119 | 2022-01-28 18:24:39 +0000 | [diff] [blame] | 364 | bool operator==(const BorderSize &rhs) const |
Giorgio Arena | 1e2af2a | 2020-10-15 17:39:41 +0100 | [diff] [blame] | 365 | { |
| 366 | return (top == rhs.top) && (right == rhs.right) && (bottom == rhs.bottom) && (left == rhs.left); |
| 367 | } |
| 368 | |
| 369 | /** Check non-equality with another BorderSize struct |
| 370 | * |
| 371 | * @param[in] rhs other struct to check against |
| 372 | * |
| 373 | * @return true if they are different |
| 374 | */ |
SiCong Li | b63b119 | 2022-01-28 18:24:39 +0000 | [diff] [blame] | 375 | bool operator!=(const BorderSize &rhs) const |
Giorgio Arena | 1e2af2a | 2020-10-15 17:39:41 +0100 | [diff] [blame] | 376 | { |
| 377 | return !(*this == rhs); |
| 378 | } |
| 379 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 380 | /** Limit this border size. |
| 381 | * |
| 382 | * @param[in] limit Border size to limit this border size to. |
| 383 | */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 384 | void limit(const BorderSize &limit) |
| 385 | { |
| 386 | top = std::min(top, limit.top); |
| 387 | right = std::min(right, limit.right); |
| 388 | bottom = std::min(bottom, limit.bottom); |
| 389 | left = std::min(left, limit.left); |
| 390 | } |
| 391 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 392 | unsigned int top; /**< top of the border */ |
| 393 | unsigned int right; /**< right of the border */ |
| 394 | unsigned int bottom; /**< bottom of the border */ |
| 395 | unsigned int left; /**< left of the border */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 396 | }; |
| 397 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 398 | /** Container for 2D padding size */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 399 | using PaddingSize = BorderSize; |
| 400 | |
SiCongLi | 1af5416 | 2021-10-06 15:25:57 +0100 | [diff] [blame] | 401 | /** Policy to handle integer overflow |
| 402 | * @note: This is ignored by floating point operations where the overflow behavior adheres to the IEEE-754 standard |
| 403 | * which states that in case of overflow ±infinity is returned for the round-to-nearest modes (and follows the |
| 404 | * rounding rules for the directed rounding modes) by default. |
| 405 | */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 406 | enum class ConvertPolicy |
| 407 | { |
| 408 | WRAP, /**< Wrap around */ |
| 409 | SATURATE /**< Saturate */ |
| 410 | }; |
| 411 | |
| 412 | /** Interpolation method */ |
| 413 | enum class InterpolationPolicy |
| 414 | { |
| 415 | NEAREST_NEIGHBOR, /**< Output values are defined to match the source pixel whose center is nearest to the sample position */ |
| 416 | BILINEAR, /**< Output values are defined by bilinear interpolation between the pixels */ |
| 417 | AREA, /**< Output values are determined by averaging the source pixels whose areas fall under the area of the destination pixel, projected onto the source image */ |
| 418 | }; |
| 419 | |
| 420 | /** Bilinear Interpolation method used by LKTracker */ |
| 421 | enum class BilinearInterpolation |
| 422 | { |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 423 | BILINEAR_OLD_NEW, /**< Old-new method */ |
| 424 | BILINEAR_SCHARR /**< Scharr method */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 425 | }; |
| 426 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 427 | /** Rectangle type */ |
| 428 | struct Rectangle |
| 429 | { |
| 430 | uint16_t x; /**< Top-left x coordinate */ |
| 431 | uint16_t y; /**< Top-left y coordinate */ |
| 432 | uint16_t width; /**< Width of the rectangle */ |
| 433 | uint16_t height; /**< Height of the rectangle */ |
| 434 | }; |
| 435 | |
| 436 | /** Coordinate type */ |
| 437 | struct Coordinates2D |
| 438 | { |
| 439 | int32_t x; /**< X coordinates */ |
| 440 | int32_t y; /**< Y coordinates */ |
| 441 | }; |
| 442 | |
| 443 | /** Coordinate type */ |
| 444 | struct Coordinates3D |
| 445 | { |
| 446 | uint32_t x; /**< X coordinates */ |
| 447 | uint32_t y; /**< Y coordinates */ |
| 448 | uint32_t z; /**< Z coordinates */ |
| 449 | }; |
| 450 | |
Giuseppe Rossini | d7647d4 | 2018-07-17 18:13:13 +0100 | [diff] [blame] | 451 | /** Padding information as a pair of unsigned int start/end */ |
| 452 | using PaddingInfo = std::pair<uint32_t, uint32_t>; |
| 453 | |
| 454 | /** List of padding information */ |
| 455 | using PaddingList = std::vector<PaddingInfo>; |
| 456 | |
giuros01 | 3175fcf | 2018-11-21 09:59:17 +0000 | [diff] [blame] | 457 | /** Information to produce a tiled version of a Tensor */ |
| 458 | using Multiples = std::vector<uint32_t>; |
| 459 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 460 | /** Available channels */ |
| 461 | enum class Channel |
| 462 | { |
| 463 | UNKNOWN, /** Unknown channel format */ |
| 464 | C0, /**< First channel (used by formats with unknown channel types). */ |
| 465 | C1, /**< Second channel (used by formats with unknown channel types). */ |
| 466 | C2, /**< Third channel (used by formats with unknown channel types). */ |
| 467 | C3, /**< Fourth channel (used by formats with unknown channel types). */ |
| 468 | R, /**< Red channel. */ |
| 469 | G, /**< Green channel. */ |
| 470 | B, /**< Blue channel. */ |
| 471 | A, /**< Alpha channel. */ |
| 472 | Y, /**< Luma channel. */ |
| 473 | U, /**< Cb/U channel. */ |
| 474 | V /**< Cr/V/Value channel. */ |
| 475 | }; |
| 476 | |
Georgios Pinitas | d976958 | 2017-08-03 10:19:40 +0100 | [diff] [blame] | 477 | /** Available reduction operations */ |
| 478 | enum class ReductionOperation |
| 479 | { |
Michalis Spyrou | 7930db4 | 2018-11-22 17:36:28 +0000 | [diff] [blame] | 480 | ARG_IDX_MAX, /**< Index of the max value */ |
Manuel Bottini | b412fab | 2018-12-10 17:40:23 +0000 | [diff] [blame] | 481 | ARG_IDX_MIN, /**< Index of the min value */ |
| 482 | MEAN_SUM, /**< Mean of sum */ |
| 483 | PROD, /**< Product */ |
| 484 | SUM_SQUARE, /**< Sum of squares */ |
Usama Arif | a4a08ad | 2019-05-20 12:38:33 +0100 | [diff] [blame] | 485 | SUM, /**< Sum */ |
| 486 | MIN, /**< Min */ |
Usama Arif | 28f0dd9 | 2019-05-20 13:44:34 +0100 | [diff] [blame] | 487 | MAX, /**< Max */ |
Georgios Pinitas | d976958 | 2017-08-03 10:19:40 +0100 | [diff] [blame] | 488 | }; |
| 489 | |
giuros01 | 164a272 | 2018-11-20 18:34:46 +0000 | [diff] [blame] | 490 | /** Available element-wise operations */ |
| 491 | enum class ArithmeticOperation |
| 492 | { |
| 493 | ADD, /**< (x + y) */ |
| 494 | SUB, /**< (x - y) */ |
| 495 | DIV, /**< (x / y) */ |
| 496 | MIN, /**< Min(x, y) */ |
| 497 | MAX, /**< Max(x, y) */ |
| 498 | SQUARED_DIFF, /**< (x - y)^2 */ |
Usama Arif | 81e671e | 2019-05-13 13:33:14 +0100 | [diff] [blame] | 499 | POWER, /**< x ^ y */ |
giuros01 | 1e6e1b8 | 2019-05-14 16:12:53 +0100 | [diff] [blame] | 500 | PRELU, /**< y*x if x < 0, x otherwise */ |
giuros01 | 164a272 | 2018-11-20 18:34:46 +0000 | [diff] [blame] | 501 | }; |
| 502 | |
Michalis Spyrou | e936262 | 2018-11-23 17:41:37 +0000 | [diff] [blame] | 503 | /** Available element wise unary operations */ |
| 504 | enum class ElementWiseUnary |
| 505 | { |
Sang-Hoon Park | 75eea33 | 2020-11-13 13:44:13 +0000 | [diff] [blame] | 506 | RSQRT, /**< Reverse square root */ |
| 507 | EXP, /**< Exponential */ |
| 508 | NEG, /**< Negate */ |
| 509 | LOG, /**< Natural Logarithm */ |
| 510 | ABS, /**< Absolute value */ |
| 511 | SIN, /**< Sine */ |
| 512 | ROUND, /**< Round */ |
| 513 | LOGICAL_NOT, /**< Logical Not */ |
Michalis Spyrou | e936262 | 2018-11-23 17:41:37 +0000 | [diff] [blame] | 514 | }; |
| 515 | |
Manuel Bottini | 63bb7ca | 2020-12-02 13:22:14 +0000 | [diff] [blame] | 516 | /** Available bitwise operations */ |
| 517 | enum class BitwiseOperation |
| 518 | { |
| 519 | AND, /**< Bitwise AND operation */ |
| 520 | NOT, /**< Bitwise NOT operation */ |
| 521 | OR, /**< Bitwise OR operation */ |
| 522 | XOR, /**< Bitwise XOR operation */ |
| 523 | }; |
| 524 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 525 | /** The normalization type used for the normalization layer */ |
| 526 | enum class NormType |
| 527 | { |
| 528 | IN_MAP_1D, /**< Normalization applied within the same map in 1D region */ |
| 529 | IN_MAP_2D, /**< Normalization applied within the same map in 2D region */ |
| 530 | CROSS_MAP /**< Normalization applied cross maps */ |
| 531 | }; |
| 532 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 533 | /** Detection window used for the object detection. The detection window keeps the following information: |
| 534 | * |
| 535 | * -# Geometry of the rectangular window (x/y of top-left corner and width/height) |
| 536 | * -# Index of the class used for evaluating which class the detection window belongs to |
| 537 | * -# Confidence value (score) obtained with the classifier |
| 538 | */ |
| 539 | struct DetectionWindow |
| 540 | { |
| 541 | uint16_t x{ 0 }; /**< Top-left x coordinate */ |
| 542 | uint16_t y{ 0 }; /**< Top-left y coordinate */ |
| 543 | uint16_t width{ 0 }; /**< Width of the detection window */ |
| 544 | uint16_t height{ 0 }; /**< Height of the detection window */ |
| 545 | uint16_t idx_class{ 0 }; /**< Index of the class */ |
| 546 | float score{ 0.f }; /**< Confidence value for the detection window */ |
| 547 | }; |
| 548 | |
| 549 | /** Dimension rounding type when down-scaling on CNNs |
| 550 | * @note Used in pooling and convolution layer |
| 551 | */ |
| 552 | enum class DimensionRoundingType |
| 553 | { |
| 554 | FLOOR, /**< Floor rounding */ |
| 555 | CEIL /**< Ceil rounding */ |
| 556 | }; |
| 557 | |
| 558 | /** Available pooling types */ |
| 559 | enum class PoolingType |
| 560 | { |
| 561 | MAX, /**< Max Pooling */ |
Georgios Pinitas | cdf5145 | 2017-08-31 14:21:36 +0100 | [diff] [blame] | 562 | AVG, /**< Average Pooling */ |
| 563 | L2 /**< L2 Pooling */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 564 | }; |
| 565 | |
Michalis Spyrou | 2709d61 | 2018-09-19 09:46:47 +0100 | [diff] [blame] | 566 | /** Available non maxima suppression types */ |
| 567 | enum class NMSType |
| 568 | { |
| 569 | LINEAR, /**< Linear NMS */ |
| 570 | GAUSSIAN, /**< Gaussian NMS */ |
| 571 | ORIGINAL /**< Original NMS */ |
| 572 | }; |
| 573 | |
| 574 | /** BoxWithNonMaximaSuppressionLimit Information class */ |
| 575 | class BoxNMSLimitInfo final |
| 576 | { |
| 577 | public: |
| 578 | /** Constructor |
| 579 | * |
| 580 | * @param[in] score_thresh (Optional) Score threshold. |
| 581 | * @param[in] nms (Optional) NMS value |
| 582 | * @param[in] detections (Optional) Number of detections |
| 583 | * @param[in] soft_nms_enabled (Optional) Enable SoftNMS |
| 584 | * @param[in] soft_nms_method (Optional) Soft NMS method |
| 585 | * @param[in] soft_nms_sigma (Optional) Soft NMS sigma value |
| 586 | * @param[in] soft_nms_min_score_thres (Optional) Soft NMS minimum score threshold |
Manuel Bottini | 5209be5 | 2019-02-13 16:34:56 +0000 | [diff] [blame] | 587 | * @param[in] suppress_size (Optional) Filter out boxes based on their size. Defaults to false |
| 588 | * @param[in] min_size (Optional) Smaller boxes than min_size will be filtered out. Defaults to 1 |
| 589 | * @param[in] im_width (Optional) Boxes whose centers (on the x axis) is beyond im_width will be filtered. Defaults to 1 |
| 590 | * @param[in] im_height (Optional) Boxes whose centers (on the y axis) is beyond im_height will be filtered. Defaults to 1 |
Michalis Spyrou | 2709d61 | 2018-09-19 09:46:47 +0100 | [diff] [blame] | 591 | */ |
| 592 | BoxNMSLimitInfo(float score_thresh = 0.05f, float nms = 0.3f, |
| 593 | int detections = 100, bool soft_nms_enabled = false, |
| 594 | NMSType soft_nms_method = NMSType::LINEAR, |
Manuel Bottini | 5209be5 | 2019-02-13 16:34:56 +0000 | [diff] [blame] | 595 | float soft_nms_sigma = 0.5f, float soft_nms_min_score_thres = 0.001f, bool suppress_size = false, float min_size = 1.0f, float im_width = 1.0f, float im_height = 1.0f) |
Michalis Spyrou | 2709d61 | 2018-09-19 09:46:47 +0100 | [diff] [blame] | 596 | : _score_thresh(score_thresh), _nms(nms), _detections_per_im(detections), _soft_nms_enabled(soft_nms_enabled), _soft_nms_method(soft_nms_method), _soft_nms_sigma(soft_nms_sigma), |
Manuel Bottini | 5209be5 | 2019-02-13 16:34:56 +0000 | [diff] [blame] | 597 | _soft_nms_min_score_thres(soft_nms_min_score_thres), _suppress_size(suppress_size), _min_size(min_size), _im_width(im_width), _im_height(im_height) |
Michalis Spyrou | 2709d61 | 2018-09-19 09:46:47 +0100 | [diff] [blame] | 598 | { |
| 599 | } |
| 600 | /** Get the score threshold */ |
| 601 | float score_thresh() const |
| 602 | { |
| 603 | return _score_thresh; |
| 604 | } |
| 605 | /** Get the NMS */ |
| 606 | float nms() const |
| 607 | { |
| 608 | return _nms; |
| 609 | } |
| 610 | /** Get the number of detections */ |
| 611 | int detections_per_im() const |
| 612 | { |
| 613 | return _detections_per_im; |
| 614 | } |
| 615 | /** Check if soft NMS is enabled */ |
| 616 | bool soft_nms_enabled() const |
| 617 | { |
| 618 | return _soft_nms_enabled; |
| 619 | } |
| 620 | /** Get soft NMS method */ |
| 621 | NMSType soft_nms_method() const |
| 622 | { |
| 623 | return _soft_nms_method; |
| 624 | } |
| 625 | /** Get soft NMS sigma */ |
| 626 | float soft_nms_sigma() const |
| 627 | { |
| 628 | return _soft_nms_sigma; |
| 629 | } |
| 630 | /** Get soft nms min score threshold */ |
| 631 | float soft_nms_min_score_thres() const |
| 632 | { |
| 633 | return _soft_nms_min_score_thres; |
| 634 | } |
Manuel Bottini | 5209be5 | 2019-02-13 16:34:56 +0000 | [diff] [blame] | 635 | /** Get if NMS will suppress boxes based on their size/position */ |
| 636 | bool suppress_size() const |
| 637 | { |
| 638 | return _suppress_size; |
| 639 | } |
| 640 | /** Get size suppression threshold */ |
| 641 | float min_size() const |
| 642 | { |
| 643 | return _min_size; |
| 644 | } |
| 645 | /** Get image width (NMS may suppress boxes whose center sits beyond the image width) */ |
| 646 | float im_width() const |
| 647 | { |
| 648 | return _im_width; |
| 649 | } |
| 650 | /** Get image height (NMS may suppress boxes whose center sits beyond the image height) */ |
| 651 | float im_height() const |
| 652 | { |
| 653 | return _im_height; |
| 654 | } |
Michalis Spyrou | 2709d61 | 2018-09-19 09:46:47 +0100 | [diff] [blame] | 655 | |
| 656 | private: |
| 657 | float _score_thresh; |
| 658 | float _nms; |
| 659 | int _detections_per_im; |
| 660 | bool _soft_nms_enabled; |
| 661 | NMSType _soft_nms_method; |
| 662 | float _soft_nms_sigma; |
| 663 | float _soft_nms_min_score_thres; |
Manuel Bottini | 5209be5 | 2019-02-13 16:34:56 +0000 | [diff] [blame] | 664 | bool _suppress_size; |
| 665 | float _min_size; |
| 666 | float _im_width; |
| 667 | float _im_height; |
Michalis Spyrou | 2709d61 | 2018-09-19 09:46:47 +0100 | [diff] [blame] | 668 | }; |
| 669 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 670 | /** Padding and stride information class */ |
| 671 | class PadStrideInfo |
| 672 | { |
| 673 | public: |
| 674 | /** Constructor |
| 675 | * |
| 676 | * @param[in] stride_x (Optional) Stride, in elements, across x. Defaults to 1. |
| 677 | * @param[in] stride_y (Optional) Stride, in elements, across y. Defaults to 1. |
| 678 | * @param[in] pad_x (Optional) Padding, in elements, across x. Defaults to 0. |
| 679 | * @param[in] pad_y (Optional) Padding, in elements, across y. Defaults to 0. |
| 680 | * @param[in] round (Optional) Dimensions rounding. Defaults to @ref FLOOR. |
| 681 | */ |
| 682 | PadStrideInfo(unsigned int stride_x = 1, unsigned int stride_y = 1, |
| 683 | unsigned int pad_x = 0, unsigned int pad_y = 0, |
| 684 | DimensionRoundingType round = DimensionRoundingType::FLOOR) |
| 685 | : _stride(std::make_pair(stride_x, stride_y)), |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 686 | _pad_left(pad_x), |
| 687 | _pad_top(pad_y), |
| 688 | _pad_right(pad_x), |
| 689 | _pad_bottom(pad_y), |
| 690 | _round_type(round) |
| 691 | { |
| 692 | } |
| 693 | /** Constructor |
| 694 | * |
| 695 | * @param[in] stride_x Stride, in elements, across x. |
| 696 | * @param[in] stride_y Stride, in elements, across y. |
| 697 | * @param[in] pad_left Padding across x on the left, in elements. |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 698 | * @param[in] pad_right Padding across x on the right, in elements. |
Freddie Liardet | ded3663 | 2021-09-03 15:08:23 +0100 | [diff] [blame] | 699 | * @param[in] pad_top Padding across y on the top, in elements. |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 700 | * @param[in] pad_bottom Padding across y on the bottom, in elements. |
| 701 | * @param[in] round Dimensions rounding. |
| 702 | */ |
| 703 | PadStrideInfo(unsigned int stride_x, unsigned int stride_y, |
| 704 | unsigned int pad_left, unsigned int pad_right, |
| 705 | unsigned int pad_top, unsigned int pad_bottom, |
| 706 | DimensionRoundingType round) |
| 707 | : _stride(std::make_pair(stride_x, stride_y)), |
| 708 | _pad_left(pad_left), |
| 709 | _pad_top(pad_top), |
| 710 | _pad_right(pad_right), |
| 711 | _pad_bottom(pad_bottom), |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 712 | _round_type(round) |
| 713 | { |
| 714 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 715 | /** Get the stride. |
| 716 | * |
| 717 | * @return a pair: stride x, stride y. |
| 718 | */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 719 | std::pair<unsigned int, unsigned int> stride() const |
| 720 | { |
| 721 | return _stride; |
| 722 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 723 | /** Check whether the padding is symmetric. |
| 724 | * |
| 725 | * @return True if the padding is symmetric. |
| 726 | */ |
Anthony Barbier | 21f67d6 | 2018-02-16 15:17:48 +0000 | [diff] [blame] | 727 | bool padding_is_symmetric() const |
| 728 | { |
| 729 | return (_pad_left == _pad_right) && (_pad_top == _pad_bottom); |
| 730 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 731 | /** Get the padding. |
| 732 | * |
| 733 | * @note This should only be used when the padding is symmetric. |
| 734 | * |
| 735 | * @return a pair: padding left/right, padding top/bottom |
| 736 | */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 737 | std::pair<unsigned int, unsigned int> pad() const |
| 738 | { |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 739 | //this accessor should be used only when padding is symmetric |
Anthony Barbier | 21f67d6 | 2018-02-16 15:17:48 +0000 | [diff] [blame] | 740 | ARM_COMPUTE_ERROR_ON(!padding_is_symmetric()); |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 741 | return std::make_pair(_pad_left, _pad_top); |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 742 | } |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 743 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 744 | /** Get the left padding */ |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 745 | unsigned int pad_left() const |
| 746 | { |
| 747 | return _pad_left; |
| 748 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 749 | /** Get the right padding */ |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 750 | unsigned int pad_right() const |
| 751 | { |
| 752 | return _pad_right; |
| 753 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 754 | /** Get the top padding */ |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 755 | unsigned int pad_top() const |
| 756 | { |
| 757 | return _pad_top; |
| 758 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 759 | /** Get the bottom padding */ |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 760 | unsigned int pad_bottom() const |
| 761 | { |
| 762 | return _pad_bottom; |
| 763 | } |
| 764 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 765 | /** Get the rounding type */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 766 | DimensionRoundingType round() const |
| 767 | { |
| 768 | return _round_type; |
| 769 | } |
| 770 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 771 | /** Check whether this has any padding */ |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 772 | bool has_padding() const |
| 773 | { |
| 774 | return (_pad_left != 0 || _pad_top != 0 || _pad_right != 0 || _pad_bottom != 0); |
| 775 | } |
| 776 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 777 | private: |
| 778 | std::pair<unsigned int, unsigned int> _stride; |
Pablo Marquez Tello | 16789a1 | 2022-07-25 14:41:26 +0100 | [diff] [blame] | 779 | unsigned int _pad_left; |
| 780 | unsigned int _pad_top; |
| 781 | unsigned int _pad_right; |
| 782 | unsigned int _pad_bottom; |
Jaroslaw Rzepecki | a1ed41f | 2017-10-13 11:13:58 +0100 | [diff] [blame] | 783 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 784 | DimensionRoundingType _round_type; |
| 785 | }; |
| 786 | |
SiCong Li | f44bbc5 | 2022-08-29 18:25:51 +0100 | [diff] [blame] | 787 | /** Padding information for 2D operations like Conv2d */ |
| 788 | struct Padding2D |
| 789 | { |
| 790 | Padding2D() = default; |
| 791 | Padding2D(size_t left, size_t right, size_t top, size_t bottom) |
| 792 | : left(left), right(right), top(top), bottom(bottom) |
| 793 | { |
| 794 | } |
| 795 | size_t left = { 0 }; /**< Padding across the width dimension on the left, in elements. */ |
| 796 | size_t right = { 0 }; /**< Padding across the width dimension on the right, in elements. */ |
| 797 | size_t top = { 0 }; /**< Padding across the height dimension on the top, in elements. */ |
| 798 | size_t bottom = { 0 }; /**< Padding across the height dimension on the bottom, in elements. */ |
| 799 | }; |
| 800 | |
Adnan AlSinan | e4563a0 | 2021-09-01 15:32:03 +0100 | [diff] [blame] | 801 | /** Padding information for 3D operations like Conv3d */ |
| 802 | struct Padding3D |
| 803 | { |
Freddie Liardet | ebefe52 | 2021-11-25 16:19:28 +0000 | [diff] [blame] | 804 | Padding3D() noexcept |
Giorgio Arena | c9fe9fc | 2021-10-06 12:54:29 +0100 | [diff] [blame] | 805 | { |
| 806 | } |
| 807 | |
| 808 | Padding3D(size_t pad_x, size_t pad_y, size_t pad_z) |
| 809 | : left(pad_x), right(pad_x), top(pad_y), bottom(pad_y), front(pad_z), back(pad_z) |
| 810 | { |
| 811 | } |
| 812 | |
| 813 | Padding3D(size_t left, size_t right, size_t top, size_t bottom, size_t front, size_t back) |
| 814 | : left(left), right(right), top(top), bottom(bottom), front(front), back(back) |
| 815 | { |
| 816 | } |
| 817 | |
Adnan AlSinan | e4563a0 | 2021-09-01 15:32:03 +0100 | [diff] [blame] | 818 | size_t left = { 0 }; /**< Padding across the width dimenstion on the left, in elements. */ |
| 819 | size_t right = { 0 }; /**< Padding across the width dimenstion on the right, in elements. */ |
| 820 | size_t top = { 0 }; /**< Padding across the height dimenstion on the top, in elements. */ |
| 821 | size_t bottom = { 0 }; /**< Padding across the height dimenstion on the bottom, in elements. */ |
| 822 | size_t front = { 0 }; /**< Padding across the depth dimenstion on the front, in elements. */ |
| 823 | size_t back = { 0 }; /**< Padding across the depth dimenstion on the back, in elements. */ |
| 824 | }; |
| 825 | |
Michalis Spyrou | 6c7c38e | 2018-08-29 16:28:11 +0100 | [diff] [blame] | 826 | /** PriorBox layer info */ |
| 827 | class PriorBoxLayerInfo final |
| 828 | { |
| 829 | public: |
| 830 | /** Default Constructor */ |
| 831 | PriorBoxLayerInfo() |
| 832 | : _min_sizes(), |
| 833 | _variances(), |
| 834 | _offset(), |
| 835 | _flip(true), |
| 836 | _clip(false), |
| 837 | _max_sizes(), |
| 838 | _aspect_ratios(), |
| 839 | _img_size(), |
| 840 | _steps() |
| 841 | { |
| 842 | } |
| 843 | /** Constructor |
| 844 | * |
| 845 | * @param[in] min_sizes Min sizes vector. |
Michalis Spyrou | 721c4cb | 2018-09-04 15:27:25 +0100 | [diff] [blame] | 846 | * @param[in] variances Variances vector. |
Michalis Spyrou | 6c7c38e | 2018-08-29 16:28:11 +0100 | [diff] [blame] | 847 | * @param[in] offset Offset value. |
| 848 | * @param[in] flip (Optional) Flip the aspect ratios. |
| 849 | * @param[in] clip (Optional) Clip coordinates so that they're within [0,1]. |
| 850 | * @param[in] max_sizes (Optional) Max sizes vector. |
| 851 | * @param[in] aspect_ratios (Optional) Aspect ratios of the boxes. |
| 852 | * @param[in] img_size (Optional) Image size. |
| 853 | * @param[in] steps (Optional) Step values. |
| 854 | */ |
| 855 | PriorBoxLayerInfo(const std::vector<float> &min_sizes, const std::vector<float> &variances, float offset, bool flip = true, bool clip = false, |
Pablo Tello | 3252143 | 2018-11-15 14:43:10 +0000 | [diff] [blame] | 856 | const std::vector<float> &max_sizes = {}, const std::vector<float> &aspect_ratios = {}, |
| 857 | const Coordinates2D &img_size = Coordinates2D{ 0, 0 }, const std::array<float, 2> &steps = { { 0.f, 0.f } }) |
Michalis Spyrou | 6c7c38e | 2018-08-29 16:28:11 +0100 | [diff] [blame] | 858 | : _min_sizes(min_sizes), |
| 859 | _variances(variances), |
| 860 | _offset(offset), |
| 861 | _flip(flip), |
| 862 | _clip(clip), |
| 863 | _max_sizes(max_sizes), |
Michalis Spyrou | 721c4cb | 2018-09-04 15:27:25 +0100 | [diff] [blame] | 864 | _aspect_ratios(), |
Michalis Spyrou | 6c7c38e | 2018-08-29 16:28:11 +0100 | [diff] [blame] | 865 | _img_size(img_size), |
| 866 | _steps(steps) |
| 867 | { |
| 868 | _aspect_ratios.push_back(1.); |
| 869 | for(unsigned int i = 0; i < aspect_ratios.size(); ++i) |
| 870 | { |
| 871 | float ar = aspect_ratios[i]; |
| 872 | bool already_exist = false; |
| 873 | for(auto ar_new : _aspect_ratios) |
| 874 | { |
| 875 | if(fabs(ar - ar_new) < 1e-6) |
| 876 | { |
| 877 | already_exist = true; |
| 878 | break; |
| 879 | } |
| 880 | } |
| 881 | if(!already_exist) |
| 882 | { |
| 883 | _aspect_ratios.push_back(ar); |
| 884 | if(flip) |
| 885 | { |
| 886 | _aspect_ratios.push_back(1.f / ar); |
| 887 | } |
| 888 | } |
| 889 | } |
| 890 | } |
| 891 | /** Get min sizes. */ |
| 892 | std::vector<float> min_sizes() const |
| 893 | { |
| 894 | return _min_sizes; |
| 895 | } |
| 896 | /** Get min variances. */ |
| 897 | std::vector<float> variances() const |
| 898 | { |
| 899 | return _variances; |
| 900 | } |
| 901 | /** Get the step coordinates */ |
| 902 | std::array<float, 2> steps() const |
| 903 | { |
| 904 | return _steps; |
| 905 | } |
| 906 | /** Get the image size coordinates */ |
| 907 | Coordinates2D img_size() const |
| 908 | { |
| 909 | return _img_size; |
| 910 | } |
| 911 | /** Get the offset */ |
| 912 | float offset() const |
| 913 | { |
| 914 | return _offset; |
| 915 | } |
| 916 | /** Get the flip value */ |
| 917 | bool flip() const |
| 918 | { |
| 919 | return _flip; |
| 920 | } |
| 921 | /** Get the clip value */ |
| 922 | bool clip() const |
| 923 | { |
| 924 | return _clip; |
| 925 | } |
| 926 | /** Get max sizes. */ |
| 927 | std::vector<float> max_sizes() const |
| 928 | { |
| 929 | return _max_sizes; |
| 930 | } |
| 931 | /** Get aspect ratios. */ |
| 932 | std::vector<float> aspect_ratios() const |
| 933 | { |
| 934 | return _aspect_ratios; |
| 935 | } |
| 936 | |
| 937 | private: |
Pablo Marquez Tello | 16789a1 | 2022-07-25 14:41:26 +0100 | [diff] [blame] | 938 | std::vector<float> _min_sizes; |
| 939 | std::vector<float> _variances; |
| 940 | float _offset; |
| 941 | bool _flip; |
| 942 | bool _clip; |
| 943 | std::vector<float> _max_sizes; |
| 944 | std::vector<float> _aspect_ratios; |
| 945 | Coordinates2D _img_size; |
Michalis Spyrou | 6c7c38e | 2018-08-29 16:28:11 +0100 | [diff] [blame] | 946 | std::array<float, 2> _steps; |
| 947 | }; |
| 948 | |
Isabella Gottardi | a7acb3c | 2019-01-08 13:48:44 +0000 | [diff] [blame] | 949 | // Bounding Box [xmin, ymin, xmax, ymax] |
| 950 | using BBox = std::array<float, 4>; |
| 951 | // LabelBBox used for map label and bounding box |
| 952 | using LabelBBox = std::map<int, std::vector<BBox>>; |
| 953 | |
Isabella Gottardi | 05e5644 | 2018-11-16 11:26:52 +0000 | [diff] [blame] | 954 | /** Available Detection Output code types */ |
| 955 | enum class DetectionOutputLayerCodeType |
| 956 | { |
| 957 | CORNER, /**< Use box corners */ |
| 958 | CENTER_SIZE, /**< Use box centers and size */ |
| 959 | CORNER_SIZE, /**< Use box centers and size */ |
| 960 | TF_CENTER /**< Use box centers and size but flip x and y co-ordinates */ |
| 961 | }; |
| 962 | |
| 963 | /** Detection Output layer info */ |
| 964 | class DetectionOutputLayerInfo final |
| 965 | { |
| 966 | public: |
| 967 | /** Default Constructor */ |
| 968 | DetectionOutputLayerInfo() |
| 969 | : _num_classes(), |
| 970 | _share_location(), |
| 971 | _code_type(DetectionOutputLayerCodeType::CORNER), |
| 972 | _keep_top_k(), |
| 973 | _nms_threshold(), |
| 974 | _top_k(), |
| 975 | _background_label_id(), |
| 976 | _confidence_threshold(), |
| 977 | _variance_encoded_in_target(false), |
| 978 | _eta(), |
| 979 | _num_loc_classes() |
| 980 | { |
| 981 | _num_loc_classes = _share_location ? 1 : _num_classes; |
| 982 | } |
| 983 | /** Constructor |
| 984 | * |
| 985 | * @param[in] num_classes Number of classes to be predicted. |
| 986 | * @param[in] share_location If true, bounding box are shared among different classes. |
| 987 | * @param[in] code_type Type of coding method for bbox. |
| 988 | * @param[in] keep_top_k Number of total bounding boxes to be kept per image after NMS step. |
| 989 | * @param[in] nms_threshold Threshold to be used in NMS. |
| 990 | * @param[in] top_k (Optional) Number of boxes per image with top confidence scores that are fed into the NMS algorithm. Default set to -1. |
| 991 | * @param[in] background_label_id (Optional) Background label ID. If there is no background class, set it as -1. |
| 992 | * @param[in] confidence_threshold (Optional) Only consider detections whose confidences are larger than a threshold. Default set to -FLT_MAX. |
| 993 | * @param[in] variance_encoded_in_target (Optional) If true, variance is encoded in target. Otherwise we need to adjust the predicted offset accordingly.Default set to false. |
| 994 | * @param[in] eta (Optional) Eta. |
| 995 | */ |
| 996 | DetectionOutputLayerInfo(int num_classes, bool share_location, DetectionOutputLayerCodeType code_type, int keep_top_k, float nms_threshold, int top_k = -1, int background_label_id = -1, |
| 997 | float confidence_threshold = std::numeric_limits<float>::lowest(), bool variance_encoded_in_target = false, float eta = 1) |
| 998 | : _num_classes(num_classes), |
| 999 | _share_location(share_location), |
| 1000 | _code_type(code_type), |
| 1001 | _keep_top_k(keep_top_k), |
| 1002 | _nms_threshold(nms_threshold), |
| 1003 | _top_k(top_k), |
| 1004 | _background_label_id(background_label_id), |
| 1005 | _confidence_threshold(confidence_threshold), |
| 1006 | _variance_encoded_in_target(variance_encoded_in_target), |
| 1007 | _eta(eta), |
| 1008 | _num_loc_classes() |
| 1009 | { |
| 1010 | _num_loc_classes = _share_location ? 1 : _num_classes; |
| 1011 | } |
| 1012 | /** Get num classes. */ |
| 1013 | int num_classes() const |
| 1014 | { |
| 1015 | return _num_classes; |
| 1016 | } |
| 1017 | /** Get share location. */ |
| 1018 | bool share_location() const |
| 1019 | { |
| 1020 | return _share_location; |
| 1021 | } |
| 1022 | /** Get detection output code type. */ |
| 1023 | DetectionOutputLayerCodeType code_type() const |
| 1024 | { |
| 1025 | return _code_type; |
| 1026 | } |
| 1027 | /** Get if variance encoded in target. */ |
| 1028 | bool variance_encoded_in_target() const |
| 1029 | { |
| 1030 | return _variance_encoded_in_target; |
| 1031 | } |
| 1032 | /** Get the number of total bounding boxes to be kept per image. */ |
| 1033 | int keep_top_k() const |
| 1034 | { |
| 1035 | return _keep_top_k; |
| 1036 | } |
| 1037 | /** Get nms threshold. */ |
| 1038 | float nms_threshold() const |
| 1039 | { |
| 1040 | return _nms_threshold; |
| 1041 | } |
| 1042 | /** Get eta. */ |
| 1043 | float eta() const |
| 1044 | { |
| 1045 | return _eta; |
| 1046 | } |
| 1047 | /** Get background label ID. */ |
| 1048 | int background_label_id() const |
| 1049 | { |
| 1050 | return _background_label_id; |
| 1051 | } |
| 1052 | /** Get confidence threshold. */ |
| 1053 | float confidence_threshold() const |
| 1054 | { |
| 1055 | return _confidence_threshold; |
| 1056 | } |
| 1057 | /** Get top K. */ |
| 1058 | int top_k() const |
| 1059 | { |
| 1060 | return _top_k; |
| 1061 | } |
| 1062 | /** Get number of location classes. */ |
| 1063 | int num_loc_classes() const |
| 1064 | { |
| 1065 | return _num_loc_classes; |
| 1066 | } |
| 1067 | |
| 1068 | private: |
| 1069 | int _num_classes; |
| 1070 | bool _share_location; |
| 1071 | DetectionOutputLayerCodeType _code_type; |
| 1072 | int _keep_top_k; |
| 1073 | float _nms_threshold; |
| 1074 | int _top_k; |
| 1075 | int _background_label_id; |
| 1076 | float _confidence_threshold; |
| 1077 | bool _variance_encoded_in_target; |
| 1078 | float _eta; |
| 1079 | int _num_loc_classes; |
| 1080 | }; |
| 1081 | |
Isabella Gottardi | a7acb3c | 2019-01-08 13:48:44 +0000 | [diff] [blame] | 1082 | /** Detection Output layer info */ |
| 1083 | class DetectionPostProcessLayerInfo final |
| 1084 | { |
| 1085 | public: |
| 1086 | /** Default Constructor */ |
| 1087 | DetectionPostProcessLayerInfo() |
| 1088 | : _max_detections(), |
| 1089 | _max_classes_per_detection(), |
| 1090 | _nms_score_threshold(), |
| 1091 | _iou_threshold(), |
| 1092 | _num_classes(), |
| 1093 | _scales_values(), |
| 1094 | _use_regular_nms(), |
Giuseppe Rossini | d985378 | 2019-10-25 11:11:44 +0100 | [diff] [blame] | 1095 | _detection_per_class(), |
| 1096 | _dequantize_scores() |
Isabella Gottardi | a7acb3c | 2019-01-08 13:48:44 +0000 | [diff] [blame] | 1097 | { |
| 1098 | } |
| 1099 | /** Constructor |
| 1100 | * |
| 1101 | * @param[in] max_detections Number of total detection. |
| 1102 | * @param[in] max_classes_per_detection Number of total classes to be kept after NMS step. Used in the Fast Non-Max-Suppression |
| 1103 | * @param[in] nms_score_threshold Threshold to be used in NMS |
| 1104 | * @param[in] iou_threshold Threshold to be used during the intersection over union. |
| 1105 | * @param[in] num_classes Number of classes. |
| 1106 | * @param[in] scales_values Scales values used for decode center size boxes. |
Giuseppe Rossini | d985378 | 2019-10-25 11:11:44 +0100 | [diff] [blame] | 1107 | * @param[in] use_regular_nms (Optional) Boolean to determinate if use regular or fast nms. Defaults to false. |
| 1108 | * @param[in] detection_per_class (Optional) Number of detection per class. Used in the Regular Non-Max-Suppression. Defaults to 100. |
| 1109 | * @param[in] dequantize_scores (Optional) If the scores need to be dequantized. Defaults to true. |
Isabella Gottardi | a7acb3c | 2019-01-08 13:48:44 +0000 | [diff] [blame] | 1110 | */ |
| 1111 | DetectionPostProcessLayerInfo(unsigned int max_detections, unsigned int max_classes_per_detection, float nms_score_threshold, float iou_threshold, unsigned int num_classes, |
Giuseppe Rossini | d985378 | 2019-10-25 11:11:44 +0100 | [diff] [blame] | 1112 | std::array<float, 4> scales_values, bool use_regular_nms = false, unsigned int detection_per_class = 100, bool dequantize_scores = true) |
Isabella Gottardi | a7acb3c | 2019-01-08 13:48:44 +0000 | [diff] [blame] | 1113 | : _max_detections(max_detections), |
| 1114 | _max_classes_per_detection(max_classes_per_detection), |
| 1115 | _nms_score_threshold(nms_score_threshold), |
| 1116 | _iou_threshold(iou_threshold), |
| 1117 | _num_classes(num_classes), |
| 1118 | _scales_values(scales_values), |
| 1119 | _use_regular_nms(use_regular_nms), |
Giuseppe Rossini | d985378 | 2019-10-25 11:11:44 +0100 | [diff] [blame] | 1120 | _detection_per_class(detection_per_class), |
| 1121 | _dequantize_scores(dequantize_scores) |
Isabella Gottardi | a7acb3c | 2019-01-08 13:48:44 +0000 | [diff] [blame] | 1122 | { |
| 1123 | } |
| 1124 | /** Get max detections. */ |
| 1125 | unsigned int max_detections() const |
| 1126 | { |
| 1127 | return _max_detections; |
| 1128 | } |
| 1129 | /** Get max_classes per detection. Used in the Fast Non-Max-Suppression.*/ |
| 1130 | unsigned int max_classes_per_detection() const |
| 1131 | { |
| 1132 | return _max_classes_per_detection; |
| 1133 | } |
| 1134 | /** Get detection per class. Used in the Regular Non-Max-Suppression */ |
| 1135 | unsigned int detection_per_class() const |
| 1136 | { |
| 1137 | return _detection_per_class; |
| 1138 | } |
| 1139 | /** Get nms threshold. */ |
| 1140 | float nms_score_threshold() const |
| 1141 | { |
| 1142 | return _nms_score_threshold; |
| 1143 | } |
| 1144 | /** Get intersection over union threshold. */ |
| 1145 | float iou_threshold() const |
| 1146 | { |
| 1147 | return _iou_threshold; |
| 1148 | } |
| 1149 | /** Get num classes. */ |
| 1150 | unsigned int num_classes() const |
| 1151 | { |
| 1152 | return _num_classes; |
| 1153 | } |
| 1154 | /** Get if use regular nms. */ |
| 1155 | bool use_regular_nms() const |
| 1156 | { |
| 1157 | return _use_regular_nms; |
| 1158 | } |
| 1159 | /** Get y scale value. */ |
| 1160 | float scale_value_y() const |
| 1161 | { |
| 1162 | // Saved as [y,x,h,w] |
| 1163 | return _scales_values[0]; |
| 1164 | } |
| 1165 | /** Get x scale value. */ |
| 1166 | float scale_value_x() const |
| 1167 | { |
| 1168 | // Saved as [y,x,h,w] |
| 1169 | return _scales_values[1]; |
| 1170 | } |
| 1171 | /** Get h scale value. */ |
| 1172 | float scale_value_h() const |
| 1173 | { |
| 1174 | // Saved as [y,x,h,w] |
| 1175 | return _scales_values[2]; |
| 1176 | } |
| 1177 | /** Get w scale value. */ |
| 1178 | float scale_value_w() const |
| 1179 | { |
| 1180 | // Saved as [y,x,h,w] |
| 1181 | return _scales_values[3]; |
| 1182 | } |
Giuseppe Rossini | d985378 | 2019-10-25 11:11:44 +0100 | [diff] [blame] | 1183 | /** Get dequantize_scores value. */ |
| 1184 | bool dequantize_scores() const |
| 1185 | { |
| 1186 | return _dequantize_scores; |
| 1187 | } |
Isabella Gottardi | a7acb3c | 2019-01-08 13:48:44 +0000 | [diff] [blame] | 1188 | |
| 1189 | private: |
Pablo Marquez Tello | 16789a1 | 2022-07-25 14:41:26 +0100 | [diff] [blame] | 1190 | unsigned int _max_detections; |
| 1191 | unsigned int _max_classes_per_detection; |
| 1192 | float _nms_score_threshold; |
| 1193 | float _iou_threshold; |
| 1194 | unsigned int _num_classes; |
Isabella Gottardi | a7acb3c | 2019-01-08 13:48:44 +0000 | [diff] [blame] | 1195 | std::array<float, 4> _scales_values; |
Pablo Marquez Tello | 16789a1 | 2022-07-25 14:41:26 +0100 | [diff] [blame] | 1196 | bool _use_regular_nms; |
| 1197 | unsigned int _detection_per_class; |
| 1198 | bool _dequantize_scores; |
Isabella Gottardi | a7acb3c | 2019-01-08 13:48:44 +0000 | [diff] [blame] | 1199 | }; |
| 1200 | |
Sang-Hoon Park | 0cb3da6 | 2020-01-15 12:39:56 +0000 | [diff] [blame] | 1201 | /** Pooling Layer Information struct*/ |
| 1202 | struct PoolingLayerInfo |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1203 | { |
Georgios Pinitas | 4c2dd54 | 2017-11-13 12:58:41 +0000 | [diff] [blame] | 1204 | /** Default Constructor */ |
| 1205 | PoolingLayerInfo() |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1206 | : pool_type(PoolingType::MAX), |
| 1207 | pool_size(Size2D()), |
| 1208 | data_layout(DataLayout::UNKNOWN), |
| 1209 | pad_stride_info(PadStrideInfo()), |
| 1210 | exclude_padding(false), |
| 1211 | is_global_pooling(false), |
Adnan AlSinan | 227db8d | 2023-02-14 14:24:09 +0000 | [diff] [blame] | 1212 | fp_mixed_precision(false), |
Adnan AlSinan | bbf2e74 | 2023-02-22 12:15:14 +0000 | [diff] [blame^] | 1213 | use_inf_as_limit(true), |
| 1214 | use_kernel_indices(false) |
Georgios Pinitas | 4c2dd54 | 2017-11-13 12:58:41 +0000 | [diff] [blame] | 1215 | { |
| 1216 | } |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1217 | /** Constructor |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1218 | * |
Sang-Hoon Park | 2aa7fd0 | 2019-09-18 13:39:00 +0100 | [diff] [blame] | 1219 | * @param[in] pool_type Pooling type @ref PoolingType. |
| 1220 | * @param[in] pool_size Pooling size, in elements, across x and y. |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1221 | * @param[in] data_layout Data layout used by the layer @ref DataLayout |
| 1222 | * @param[in] pad_stride_info (Optional) Padding and stride information @ref PadStrideInfo |
| 1223 | * @param[in] exclude_padding (Optional) Strategy when accounting padding in calculations. |
| 1224 | * True will exclude padding while false will not (Used in AVG/L2 pooling to determine the pooling area). |
| 1225 | * Defaults to false; |
| 1226 | * @param[in] fp_mixed_precision (Optional) Use wider accumulators (32 bit instead of 16 for FP16) to improve accuracy. |
Adnan AlSinan | 227db8d | 2023-02-14 14:24:09 +0000 | [diff] [blame] | 1227 | * @param[in] use_inf_as_limit (Optional) Use inf to represent the limits of datatypes range, instead of using "lowest" property of the data type. |
Adnan AlSinan | bbf2e74 | 2023-02-22 12:15:14 +0000 | [diff] [blame^] | 1228 | * @param[in] use_kernel_indices (Optional) Use kernel indices instead of using source indices while computing indices tensor. |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1229 | */ |
Georgios Pinitas | 4c2dd54 | 2017-11-13 12:58:41 +0000 | [diff] [blame] | 1230 | explicit PoolingLayerInfo(PoolingType pool_type, |
| 1231 | unsigned int pool_size, |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1232 | DataLayout data_layout, |
Sang-Hoon Park | 2aa7fd0 | 2019-09-18 13:39:00 +0100 | [diff] [blame] | 1233 | PadStrideInfo pad_stride_info = PadStrideInfo(), |
| 1234 | bool exclude_padding = false, |
Adnan AlSinan | 227db8d | 2023-02-14 14:24:09 +0000 | [diff] [blame] | 1235 | bool fp_mixed_precision = false, |
Adnan AlSinan | bbf2e74 | 2023-02-22 12:15:14 +0000 | [diff] [blame^] | 1236 | bool use_inf_as_limit = true, |
| 1237 | bool use_kernel_indices = false) |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1238 | : pool_type(pool_type), |
| 1239 | pool_size(Size2D(pool_size, pool_size)), |
| 1240 | data_layout(data_layout), |
| 1241 | pad_stride_info(pad_stride_info), |
| 1242 | exclude_padding(exclude_padding), |
| 1243 | is_global_pooling(false), |
Adnan AlSinan | 227db8d | 2023-02-14 14:24:09 +0000 | [diff] [blame] | 1244 | fp_mixed_precision(fp_mixed_precision), |
Adnan AlSinan | bbf2e74 | 2023-02-22 12:15:14 +0000 | [diff] [blame^] | 1245 | use_inf_as_limit(use_inf_as_limit), |
| 1246 | use_kernel_indices(use_kernel_indices) |
Isabella Gottardi | 6e464c3 | 2018-01-26 12:32:45 +0000 | [diff] [blame] | 1247 | { |
| 1248 | } |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1249 | |
| 1250 | /** Constructor |
Isabella Gottardi | 6e464c3 | 2018-01-26 12:32:45 +0000 | [diff] [blame] | 1251 | * |
Sang-Hoon Park | 2aa7fd0 | 2019-09-18 13:39:00 +0100 | [diff] [blame] | 1252 | * @param[in] pool_type Pooling type @ref PoolingType. |
| 1253 | * @param[in] pool_size Pooling size, in elements, across x and y. |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1254 | * @param[in] data_layout Data layout used by the layer @ref DataLayout |
Sang-Hoon Park | 2aa7fd0 | 2019-09-18 13:39:00 +0100 | [diff] [blame] | 1255 | * @param[in] pad_stride_info (Optional) Padding and stride information @ref PadStrideInfo |
| 1256 | * @param[in] exclude_padding (Optional) Strategy when accounting padding in calculations. |
| 1257 | * True will exclude padding while false will not (Used in AVG/L2 pooling to determine the pooling area). |
| 1258 | * Defaults to false; |
| 1259 | * @param[in] fp_mixed_precision (Optional) Use wider accumulators (32 bit instead of 16 for FP16) to improve accuracy. |
Adnan AlSinan | 227db8d | 2023-02-14 14:24:09 +0000 | [diff] [blame] | 1260 | * @param[in] use_inf_as_limit (Optional) Use inf to represent the limits of datatypes range, instead of using "lowest" property of the data type. |
Adnan AlSinan | bbf2e74 | 2023-02-22 12:15:14 +0000 | [diff] [blame^] | 1261 | * @param[in] use_kernel_indices (Optional) Use kernel indices instead of using source indices while computing indices tensor. |
Isabella Gottardi | 6e464c3 | 2018-01-26 12:32:45 +0000 | [diff] [blame] | 1262 | */ |
| 1263 | explicit PoolingLayerInfo(PoolingType pool_type, |
| 1264 | Size2D pool_size, |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1265 | DataLayout data_layout, |
Sang-Hoon Park | 2aa7fd0 | 2019-09-18 13:39:00 +0100 | [diff] [blame] | 1266 | PadStrideInfo pad_stride_info = PadStrideInfo(), |
| 1267 | bool exclude_padding = false, |
Adnan AlSinan | 227db8d | 2023-02-14 14:24:09 +0000 | [diff] [blame] | 1268 | bool fp_mixed_precision = false, |
Adnan AlSinan | bbf2e74 | 2023-02-22 12:15:14 +0000 | [diff] [blame^] | 1269 | bool use_inf_as_limit = true, |
| 1270 | bool use_kernel_indices = false) |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1271 | : pool_type(pool_type), |
| 1272 | pool_size(pool_size), |
| 1273 | data_layout(data_layout), |
| 1274 | pad_stride_info(pad_stride_info), |
| 1275 | exclude_padding(exclude_padding), |
| 1276 | is_global_pooling(false), |
Adnan AlSinan | 227db8d | 2023-02-14 14:24:09 +0000 | [diff] [blame] | 1277 | fp_mixed_precision(fp_mixed_precision), |
Adnan AlSinan | bbf2e74 | 2023-02-22 12:15:14 +0000 | [diff] [blame^] | 1278 | use_inf_as_limit(use_inf_as_limit), |
| 1279 | use_kernel_indices(use_kernel_indices) |
Georgios Pinitas | 4c2dd54 | 2017-11-13 12:58:41 +0000 | [diff] [blame] | 1280 | { |
| 1281 | } |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1282 | |
| 1283 | /** Constructor |
Georgios Pinitas | 4c2dd54 | 2017-11-13 12:58:41 +0000 | [diff] [blame] | 1284 | * |
| 1285 | * @note This constructor is used for global pooling |
| 1286 | * |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1287 | * @param[in] pool_type Pooling type @ref PoolingType. |
| 1288 | * @param[in] data_layout Data layout used by the layer @ref DataLayout |
Georgios Pinitas | 4c2dd54 | 2017-11-13 12:58:41 +0000 | [diff] [blame] | 1289 | */ |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1290 | explicit PoolingLayerInfo(PoolingType pool_type, DataLayout data_layout) |
| 1291 | : pool_type(pool_type), |
| 1292 | pool_size(Size2D()), |
| 1293 | data_layout(data_layout), |
| 1294 | pad_stride_info(PadStrideInfo(1, 1, 0, 0)), |
| 1295 | exclude_padding(false), |
| 1296 | is_global_pooling(true), |
Adnan AlSinan | 227db8d | 2023-02-14 14:24:09 +0000 | [diff] [blame] | 1297 | fp_mixed_precision(false), |
Adnan AlSinan | bbf2e74 | 2023-02-22 12:15:14 +0000 | [diff] [blame^] | 1298 | use_inf_as_limit(true), |
| 1299 | use_kernel_indices(false) |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1300 | { |
| 1301 | } |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1302 | |
Sang-Hoon Park | 0cb3da6 | 2020-01-15 12:39:56 +0000 | [diff] [blame] | 1303 | PoolingType pool_type; |
| 1304 | Size2D pool_size; |
Sang-Hoon Park | 11fedda | 2020-01-15 14:44:04 +0000 | [diff] [blame] | 1305 | DataLayout data_layout; |
Sang-Hoon Park | 0cb3da6 | 2020-01-15 12:39:56 +0000 | [diff] [blame] | 1306 | PadStrideInfo pad_stride_info; |
| 1307 | bool exclude_padding; |
| 1308 | bool is_global_pooling; |
| 1309 | bool fp_mixed_precision; |
Adnan AlSinan | 227db8d | 2023-02-14 14:24:09 +0000 | [diff] [blame] | 1310 | bool use_inf_as_limit; |
Adnan AlSinan | bbf2e74 | 2023-02-22 12:15:14 +0000 | [diff] [blame^] | 1311 | bool use_kernel_indices; |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1312 | }; |
| 1313 | |
ramelg01 | 3751569 | 2022-02-26 22:06:20 +0000 | [diff] [blame] | 1314 | /** Pooling Layer Information struct*/ |
| 1315 | struct Pooling3dLayerInfo |
| 1316 | { |
| 1317 | /** Default Constructor */ |
Michalis Spyrou | 50e48aa | 2022-04-21 16:42:56 +0100 | [diff] [blame] | 1318 | Pooling3dLayerInfo() noexcept |
ramelg01 | 3751569 | 2022-02-26 22:06:20 +0000 | [diff] [blame] | 1319 | : pool_type(PoolingType::MAX), |
| 1320 | pool_size(Size3D()), |
| 1321 | stride(Size3D()), |
| 1322 | padding(Padding3D()), |
| 1323 | exclude_padding(false), |
| 1324 | is_global_pooling(false), |
| 1325 | fp_mixed_precision(false), |
| 1326 | round_type(DimensionRoundingType::FLOOR) |
| 1327 | { |
| 1328 | } |
| 1329 | /** Constructor |
| 1330 | * |
| 1331 | * @param[in] pool_type Pooling type @ref PoolingType. |
| 1332 | * @param[in] pool_size Pooling size, in elements, across x, y and z. |
| 1333 | * @param[in] stride (Optional) stride information @ref Size3D |
| 1334 | * @param[in] padding (Optional) padding information @ref Padding3D |
| 1335 | * @param[in] exclude_padding (Optional) Strategy when accounting padding in calculations. |
| 1336 | * True will exclude padding while false will not (Used in AVG/L2 pooling to determine the pooling area). |
| 1337 | * Defaults to false; |
| 1338 | * @param[in] fp_mixed_precision (Optional) Use wider accumulators (32 bit instead of 16 for FP16) to improve accuracy. |
| 1339 | * @param[in] round_type (Optional) Dimensions rounding. Defaults to @ref FLOOR |
| 1340 | */ |
| 1341 | explicit Pooling3dLayerInfo(PoolingType pool_type, |
| 1342 | unsigned int pool_size, |
| 1343 | Size3D stride = Size3D(1U, 1U, 1U), |
| 1344 | Padding3D padding = Padding3D(), |
| 1345 | bool exclude_padding = false, |
| 1346 | bool fp_mixed_precision = false, |
| 1347 | DimensionRoundingType round_type = DimensionRoundingType::FLOOR) |
| 1348 | : pool_type(pool_type), |
| 1349 | pool_size(Size3D(pool_size, pool_size, pool_size)), |
| 1350 | stride(stride), |
| 1351 | padding(padding), |
| 1352 | exclude_padding(exclude_padding), |
| 1353 | is_global_pooling(false), |
| 1354 | fp_mixed_precision(fp_mixed_precision), |
| 1355 | round_type(round_type) |
| 1356 | { |
| 1357 | } |
| 1358 | |
| 1359 | /** Constructor |
| 1360 | * |
| 1361 | * @param[in] pool_type Pooling type @ref PoolingType. |
| 1362 | * @param[in] pool_size Pooling size, in elements, across x, y and z. |
| 1363 | * @param[in] stride (Optional) stride information @ref Size3D |
| 1364 | * @param[in] padding (Optional) padding information @ref Padding3D |
| 1365 | * @param[in] exclude_padding (Optional) Strategy when accounting padding in calculations. |
| 1366 | * True will exclude padding while false will not (Used in AVG/L2 pooling to determine the pooling area). |
| 1367 | * Defaults to false; |
| 1368 | * @param[in] fp_mixed_precision (Optional) Use wider accumulators (32 bit instead of 16 for FP16) to improve accuracy. |
| 1369 | * @param[in] round_type (Optional) Dimensions rounding. Defaults to @ref FLOOR |
| 1370 | */ |
| 1371 | explicit Pooling3dLayerInfo(PoolingType pool_type, |
| 1372 | Size3D pool_size, |
| 1373 | Size3D stride = Size3D(1U, 1U, 1U), |
| 1374 | Padding3D padding = Padding3D(), |
| 1375 | bool exclude_padding = false, |
| 1376 | bool fp_mixed_precision = false, |
| 1377 | DimensionRoundingType round_type = DimensionRoundingType::FLOOR) |
| 1378 | : pool_type(pool_type), |
| 1379 | pool_size(pool_size), |
| 1380 | stride(stride), |
| 1381 | padding(padding), |
| 1382 | exclude_padding(exclude_padding), |
| 1383 | is_global_pooling(false), |
| 1384 | fp_mixed_precision(fp_mixed_precision), |
| 1385 | round_type(round_type) |
| 1386 | { |
| 1387 | } |
| 1388 | |
| 1389 | /** Constructor |
| 1390 | * |
| 1391 | * @note This constructor is used for global pooling |
| 1392 | * |
| 1393 | * @param[in] pool_type Pooling type @ref PoolingType. |
| 1394 | */ |
| 1395 | explicit Pooling3dLayerInfo(PoolingType pool_type) |
| 1396 | : pool_type(pool_type), |
| 1397 | pool_size(Size3D()), |
| 1398 | stride(Size3D(1U, 1U, 1U)), |
| 1399 | padding(Padding3D(0, 0, 0)), |
| 1400 | exclude_padding(false), |
| 1401 | is_global_pooling(true), |
| 1402 | fp_mixed_precision(false), |
| 1403 | round_type(DimensionRoundingType::FLOOR) |
| 1404 | { |
| 1405 | } |
| 1406 | |
| 1407 | PoolingType pool_type; |
| 1408 | Size3D pool_size; |
| 1409 | Size3D stride; |
| 1410 | Padding3D padding; |
| 1411 | bool exclude_padding; |
| 1412 | bool is_global_pooling; |
| 1413 | bool fp_mixed_precision; |
| 1414 | DimensionRoundingType round_type; |
| 1415 | }; |
| 1416 | |
Georgios Pinitas | 7b7858d | 2017-06-21 16:44:24 +0100 | [diff] [blame] | 1417 | /** ROI Pooling Layer Information class */ |
giuros01 | 1887081 | 2018-09-13 09:31:40 +0100 | [diff] [blame] | 1418 | class ROIPoolingLayerInfo final |
Georgios Pinitas | 7b7858d | 2017-06-21 16:44:24 +0100 | [diff] [blame] | 1419 | { |
| 1420 | public: |
giuros01 | 1887081 | 2018-09-13 09:31:40 +0100 | [diff] [blame] | 1421 | /** Constructor |
Georgios Pinitas | 7b7858d | 2017-06-21 16:44:24 +0100 | [diff] [blame] | 1422 | * |
giuros01 | 1887081 | 2018-09-13 09:31:40 +0100 | [diff] [blame] | 1423 | * @param[in] pooled_width Pooled width of the layer. |
| 1424 | * @param[in] pooled_height Pooled height of the layer. |
| 1425 | * @param[in] spatial_scale Spatial scale to be applied to the ROI coordinates and dimensions. |
| 1426 | * @param[in] sampling_ratio Number of samples to include in each pooling region (if set to zero, a ceil(roi_dims/pooling_dims)) |
Georgios Pinitas | 7b7858d | 2017-06-21 16:44:24 +0100 | [diff] [blame] | 1427 | */ |
giuros01 | 1887081 | 2018-09-13 09:31:40 +0100 | [diff] [blame] | 1428 | ROIPoolingLayerInfo(unsigned int pooled_width, unsigned int pooled_height, float spatial_scale, unsigned int sampling_ratio = 0) |
| 1429 | : _pooled_width(pooled_width), _pooled_height(pooled_height), _spatial_scale(spatial_scale), _sampling_ratio(sampling_ratio) |
Georgios Pinitas | 7b7858d | 2017-06-21 16:44:24 +0100 | [diff] [blame] | 1430 | { |
| 1431 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1432 | /** Get the pooled width of the layer */ |
Georgios Pinitas | 7b7858d | 2017-06-21 16:44:24 +0100 | [diff] [blame] | 1433 | unsigned int pooled_width() const |
| 1434 | { |
| 1435 | return _pooled_width; |
| 1436 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1437 | /** Get the pooled height of the layer */ |
Georgios Pinitas | 7b7858d | 2017-06-21 16:44:24 +0100 | [diff] [blame] | 1438 | unsigned int pooled_height() const |
| 1439 | { |
| 1440 | return _pooled_height; |
| 1441 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1442 | /** Get the spatial scale */ |
Georgios Pinitas | 7b7858d | 2017-06-21 16:44:24 +0100 | [diff] [blame] | 1443 | float spatial_scale() const |
| 1444 | { |
| 1445 | return _spatial_scale; |
| 1446 | } |
giuros01 | 1887081 | 2018-09-13 09:31:40 +0100 | [diff] [blame] | 1447 | /** Get sampling ratio */ |
| 1448 | unsigned int sampling_ratio() const |
| 1449 | { |
| 1450 | return _sampling_ratio; |
| 1451 | } |
Georgios Pinitas | 7b7858d | 2017-06-21 16:44:24 +0100 | [diff] [blame] | 1452 | |
| 1453 | private: |
| 1454 | unsigned int _pooled_width; |
| 1455 | unsigned int _pooled_height; |
| 1456 | float _spatial_scale; |
giuros01 | 1887081 | 2018-09-13 09:31:40 +0100 | [diff] [blame] | 1457 | unsigned int _sampling_ratio; |
Georgios Pinitas | 7b7858d | 2017-06-21 16:44:24 +0100 | [diff] [blame] | 1458 | }; |
| 1459 | |
Manuel Bottini | 5209be5 | 2019-02-13 16:34:56 +0000 | [diff] [blame] | 1460 | /** Generate Proposals Information class */ |
| 1461 | class GenerateProposalsInfo |
| 1462 | { |
| 1463 | public: |
| 1464 | /** Constructor |
| 1465 | * |
| 1466 | * @param[in] im_width Width of the original image |
| 1467 | * @param[in] im_height Height of the original image |
| 1468 | * @param[in] im_scale Scale applied to the original image |
| 1469 | * @param[in] spatial_scale (Optional)Scale applied to the feature map. Defaults to 1.0 |
| 1470 | * @param[in] pre_nms_topN (Optional)Number of the best scores to be selected from the transformations. Defaults to 6000. |
| 1471 | * @param[in] post_nms_topN (Optional)Number of the best scores to be selected from the NMS operation. Defaults to 300. |
| 1472 | * @param[in] nms_thres (Optional)NMS overlap threshold. Defaults to 0.7. |
| 1473 | * @param[in] min_size (Optional)Size used to validate the anchors produced. Defaults to 16. |
| 1474 | * @param[in] values_per_roi (Optional)Values used to represent a ROI(Region of interest). Defaults to 4. |
| 1475 | */ |
| 1476 | GenerateProposalsInfo(float im_width, float im_height, float im_scale, float spatial_scale = 1.0, int pre_nms_topN = 6000, int post_nms_topN = 300, float nms_thres = 0.7, float min_size = 16.0, |
| 1477 | size_t values_per_roi = 4) |
| 1478 | : _im_height(im_height), _im_width(im_width), _im_scale(im_scale), _spatial_scale(spatial_scale), _pre_nms_topN(pre_nms_topN), _post_nms_topN(post_nms_topN), _nms_thres(nms_thres), |
| 1479 | _min_size(min_size), _values_per_roi(values_per_roi) |
| 1480 | { |
| 1481 | } |
| 1482 | |
| 1483 | /* Get the original height */ |
| 1484 | float im_height() const |
| 1485 | { |
| 1486 | return _im_height; |
| 1487 | } |
| 1488 | /* Get the original width */ |
| 1489 | float im_width() const |
| 1490 | { |
| 1491 | return _im_width; |
| 1492 | } |
| 1493 | /* Get the image scale */ |
| 1494 | float im_scale() const |
| 1495 | { |
| 1496 | return _im_scale; |
| 1497 | } |
| 1498 | /* Get the value of how many best scores to select (before NMS) */ |
| 1499 | int pre_nms_topN() const |
| 1500 | { |
| 1501 | return _pre_nms_topN; |
| 1502 | } |
| 1503 | /* Get the value of how many best scores to select (after NMS) */ |
| 1504 | int post_nms_topN() const |
| 1505 | { |
| 1506 | return _post_nms_topN; |
| 1507 | } |
| 1508 | /* Get the NMS overlap threshold */ |
| 1509 | float nms_thres() const |
| 1510 | { |
| 1511 | return _nms_thres; |
| 1512 | } |
| 1513 | /* Get the minimal size */ |
| 1514 | float min_size() const |
| 1515 | { |
| 1516 | return _min_size; |
| 1517 | } |
| 1518 | /* Get the spatial scale to be applied to the feature maps */ |
| 1519 | float spatial_scale() const |
| 1520 | { |
| 1521 | return _spatial_scale; |
| 1522 | } |
| 1523 | /* Get the values used to represent a ROI(Region of interest)*/ |
| 1524 | size_t values_per_roi() const |
| 1525 | { |
| 1526 | return _values_per_roi; |
| 1527 | } |
| 1528 | |
| 1529 | private: |
| 1530 | float _im_height; |
| 1531 | float _im_width; |
| 1532 | float _im_scale; |
| 1533 | float _spatial_scale; |
| 1534 | int _pre_nms_topN; |
| 1535 | int _post_nms_topN; |
| 1536 | float _nms_thres; |
| 1537 | float _min_size; |
| 1538 | size_t _values_per_roi; |
| 1539 | }; |
| 1540 | |
| 1541 | /** ComputeAnchors information class */ |
| 1542 | class ComputeAnchorsInfo |
| 1543 | { |
| 1544 | public: |
| 1545 | /** Constructor |
| 1546 | * |
| 1547 | * @param[in] feat_width Feature map width |
| 1548 | * @param[in] feat_height Feature map height |
| 1549 | * @param[in] spatial_scale Feature map scale |
| 1550 | * @param[in] values_per_roi (Optional)Values used to represent a ROI(Region Of Interest). Defaults to 4 |
| 1551 | */ |
| 1552 | ComputeAnchorsInfo(float feat_width, float feat_height, float spatial_scale, size_t values_per_roi = 4) |
| 1553 | : _feat_height(feat_height), |
| 1554 | _feat_width(feat_width), |
| 1555 | _spatial_scale(spatial_scale), |
| 1556 | _values_per_roi(values_per_roi) |
| 1557 | { |
| 1558 | } |
| 1559 | |
| 1560 | /* Get the height of the feature map */ |
| 1561 | float feat_height() const |
| 1562 | { |
| 1563 | return _feat_height; |
| 1564 | } |
| 1565 | |
| 1566 | /* Get the width of the feature map */ |
| 1567 | float feat_width() const |
| 1568 | { |
| 1569 | return _feat_width; |
| 1570 | } |
| 1571 | |
| 1572 | /* Get the scale of the feature map */ |
| 1573 | float spatial_scale() const |
| 1574 | { |
| 1575 | return _spatial_scale; |
| 1576 | } |
| 1577 | |
| 1578 | /* Get the values used to represent a ROI(Region Of Interest)*/ |
| 1579 | size_t values_per_roi() const |
| 1580 | { |
| 1581 | return _values_per_roi; |
| 1582 | } |
| 1583 | |
| 1584 | private: |
| 1585 | float _feat_height; |
| 1586 | float _feat_width; |
| 1587 | float _spatial_scale; |
| 1588 | size_t _values_per_roi; |
| 1589 | }; |
| 1590 | |
giuros01 | c04a0e8 | 2018-10-03 12:44:35 +0100 | [diff] [blame] | 1591 | /** Bounding Box Transform information class */ |
giuros01 | d696cb6 | 2018-11-16 10:39:59 +0000 | [diff] [blame] | 1592 | class BoundingBoxTransformInfo final |
giuros01 | c04a0e8 | 2018-10-03 12:44:35 +0100 | [diff] [blame] | 1593 | { |
| 1594 | public: |
| 1595 | /** Constructor |
| 1596 | * |
giuros01 | d696cb6 | 2018-11-16 10:39:59 +0000 | [diff] [blame] | 1597 | * @param[in] img_width Width of the original image |
| 1598 | * @param[in] img_height Height, of the original image |
| 1599 | * @param[in] scale Scale of the original image |
| 1600 | * @param[in] apply_scale (Optional)Re-apply scaling after transforming the boxes. Defaults to false |
| 1601 | * @param[in] weights (Optional)Weights [wx, wy, ww, wh] for the deltas. Defaults to all ones |
| 1602 | * @param[in] correct_transform_coords (Optional)Correct bounding box transform coordinates. Defaults to false |
| 1603 | * @param[in] bbox_xform_clip (Optional)Minimum bounding box width and height after bounding box transformation in log-space. Defaults to log(1000/16) |
giuros01 | c04a0e8 | 2018-10-03 12:44:35 +0100 | [diff] [blame] | 1604 | */ |
giuros01 | d696cb6 | 2018-11-16 10:39:59 +0000 | [diff] [blame] | 1605 | BoundingBoxTransformInfo(float img_width, float img_height, float scale, bool apply_scale = false, const std::array<float, 4> weights = { { 1.f, 1.f, 1.f, 1.f } }, bool correct_transform_coords = |
| 1606 | false, |
| 1607 | float bbox_xform_clip = |
| 1608 | 4.135166556742356f) |
| 1609 | : _img_width(img_width), _img_height(img_height), _scale(scale), _apply_scale(apply_scale), _correct_transform_coords(correct_transform_coords), _weights(weights), _bbox_xform_clip(bbox_xform_clip) |
giuros01 | c04a0e8 | 2018-10-03 12:44:35 +0100 | [diff] [blame] | 1610 | { |
| 1611 | } |
| 1612 | |
| 1613 | std::array<float, 4> weights() const |
| 1614 | { |
| 1615 | return _weights; |
| 1616 | } |
| 1617 | |
| 1618 | float bbox_xform_clip() const |
| 1619 | { |
| 1620 | return _bbox_xform_clip; |
| 1621 | } |
| 1622 | |
| 1623 | float img_height() const |
| 1624 | { |
| 1625 | return _img_height; |
| 1626 | } |
| 1627 | |
| 1628 | float img_width() const |
| 1629 | { |
| 1630 | return _img_width; |
| 1631 | } |
| 1632 | |
| 1633 | float scale() const |
| 1634 | { |
| 1635 | return _scale; |
| 1636 | } |
| 1637 | |
| 1638 | bool apply_scale() const |
| 1639 | { |
| 1640 | return _apply_scale; |
| 1641 | } |
| 1642 | |
giuros01 | d696cb6 | 2018-11-16 10:39:59 +0000 | [diff] [blame] | 1643 | bool correct_transform_coords() const |
| 1644 | { |
| 1645 | return _correct_transform_coords; |
| 1646 | } |
| 1647 | |
giuros01 | c04a0e8 | 2018-10-03 12:44:35 +0100 | [diff] [blame] | 1648 | private: |
Pablo Marquez Tello | 16789a1 | 2022-07-25 14:41:26 +0100 | [diff] [blame] | 1649 | float _img_width; |
| 1650 | float _img_height; |
| 1651 | float _scale; |
| 1652 | bool _apply_scale; |
| 1653 | bool _correct_transform_coords; |
giuros01 | c04a0e8 | 2018-10-03 12:44:35 +0100 | [diff] [blame] | 1654 | std::array<float, 4> _weights; |
Pablo Marquez Tello | 16789a1 | 2022-07-25 14:41:26 +0100 | [diff] [blame] | 1655 | float _bbox_xform_clip; |
giuros01 | c04a0e8 | 2018-10-03 12:44:35 +0100 | [diff] [blame] | 1656 | }; |
| 1657 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1658 | /** Activation Layer Information class */ |
| 1659 | class ActivationLayerInfo |
| 1660 | { |
| 1661 | public: |
| 1662 | /** Available activation functions */ |
| 1663 | enum class ActivationFunction |
| 1664 | { |
Georgios Pinitas | 64ebe5b | 2017-09-01 17:44:24 +0100 | [diff] [blame] | 1665 | LOGISTIC, /**< Logistic ( \f$ f(x) = \frac{1}{1 + e^{-x}} \f$ ) */ |
| 1666 | TANH, /**< Hyperbolic tangent ( \f$ f(x) = a \cdot tanh(b \cdot x) \f$ ) */ |
| 1667 | RELU, /**< Rectifier ( \f$ f(x) = max(0,x) \f$ ) */ |
| 1668 | BOUNDED_RELU, /**< Upper Bounded Rectifier ( \f$ f(x) = min(a, max(0,x)) \f$ ) */ |
| 1669 | LU_BOUNDED_RELU, /**< Lower and Upper Bounded Rectifier ( \f$ f(x) = min(a, max(b,x)) \f$ ) */ |
Manuel Bottini | 581c898 | 2019-02-07 10:31:57 +0000 | [diff] [blame] | 1670 | LEAKY_RELU, /**< Leaky Rectifier ( \f$ f(x) = \begin{cases} \alpha x & \quad \text{if } x \text{ < 0}\\ x & \quad \text{if } x \geq \text{ 0 } \end{cases} \f$ ) */ |
Georgios Pinitas | 64ebe5b | 2017-09-01 17:44:24 +0100 | [diff] [blame] | 1671 | SOFT_RELU, /**< Soft Rectifier ( \f$ f(x)= log(1+e^x) \f$ ) */ |
Georgios Pinitas | fb0fdcd | 2019-08-22 17:10:04 +0100 | [diff] [blame] | 1672 | ELU, /**< Exponential Linear Unit ( \f$ f(x) = \begin{cases} \alpha (exp(x) - 1) & \quad \text{if } x \text{ < 0}\\ x & \quad \text{if } x \geq \text{ 0 } \end{cases} \f$ ) */ |
Georgios Pinitas | 64ebe5b | 2017-09-01 17:44:24 +0100 | [diff] [blame] | 1673 | ABS, /**< Absolute ( \f$ f(x)= |x| \f$ ) */ |
| 1674 | SQUARE, /**< Square ( \f$ f(x)= x^2 \f$ )*/ |
| 1675 | SQRT, /**< Square root ( \f$ f(x) = \sqrt{x} \f$ )*/ |
Usama Arif | 6a98a6e | 2019-05-10 17:07:27 +0100 | [diff] [blame] | 1676 | LINEAR, /**< Linear ( \f$ f(x)= ax + b \f$ ) */ |
morgolock | 07df3d4 | 2020-02-27 11:46:28 +0000 | [diff] [blame] | 1677 | IDENTITY, /**< Identity ( \f$ f(x)= x \f$ ) */ |
Jonathan Deakin | d6b8a71 | 2022-08-23 11:44:18 +0100 | [diff] [blame] | 1678 | HARD_SWISH, /**< Hard-swish ( \f$ f(x) = (x \text{ReLU6}(x+3))/6 = x \min(\max(0,x+3),6)/6 \f$ ) */ |
SiCong Li | f44bbc5 | 2022-08-29 18:25:51 +0100 | [diff] [blame] | 1679 | SWISH, /**< Swish ( \f$ f(x) = \frac{x}{1 + e^{-ax}} = x \text{logistic}(ax) \f$ ) */ |
Murray Kornelsen | 926f502 | 2022-07-13 21:22:39 -0400 | [diff] [blame] | 1680 | GELU /**< GELU ( \f$ f(x) = x * 1/2 * 1 + erf(x / \sqrt{2}) \f$ ) */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1681 | }; |
| 1682 | |
Pablo Marquez Tello | d75cd8a | 2022-05-26 14:19:39 +0100 | [diff] [blame] | 1683 | /** Lookup table */ |
| 1684 | using LookupTable256 = std::array<qasymm8_t, 256>; |
| 1685 | |
Giorgio Arena | 1167487 | 2018-02-07 15:38:12 +0000 | [diff] [blame] | 1686 | ActivationLayerInfo() = default; |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1687 | /** Default Constructor |
| 1688 | * |
| 1689 | * @param[in] f The activation function to use. |
| 1690 | * @param[in] a (Optional) The alpha parameter used by some activation functions |
Georgios Pinitas | 64ebe5b | 2017-09-01 17:44:24 +0100 | [diff] [blame] | 1691 | * (@ref ActivationFunction::BOUNDED_RELU, @ref ActivationFunction::LU_BOUNDED_RELU, @ref ActivationFunction::LINEAR, @ref ActivationFunction::TANH). |
| 1692 | * @param[in] b (Optional) The beta parameter used by some activation functions (@ref ActivationFunction::LINEAR, @ref ActivationFunction::LU_BOUNDED_RELU, @ref ActivationFunction::TANH). |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1693 | */ |
| 1694 | ActivationLayerInfo(ActivationFunction f, float a = 0.0f, float b = 0.0f) |
Giorgio Arena | 1167487 | 2018-02-07 15:38:12 +0000 | [diff] [blame] | 1695 | : _act(f), _a(a), _b(b), _enabled(true) |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1696 | { |
| 1697 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1698 | /** Get the type of activation function */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1699 | ActivationFunction activation() const |
| 1700 | { |
| 1701 | return _act; |
| 1702 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1703 | /** Get the alpha value */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1704 | float a() const |
| 1705 | { |
| 1706 | return _a; |
| 1707 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1708 | /** Get the beta value */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1709 | float b() const |
| 1710 | { |
| 1711 | return _b; |
| 1712 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1713 | /** Check if initialised */ |
Giorgio Arena | 1167487 | 2018-02-07 15:38:12 +0000 | [diff] [blame] | 1714 | bool enabled() const |
| 1715 | { |
| 1716 | return _enabled; |
| 1717 | } |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1718 | |
Viet-Hoa Do | b042e39 | 2022-06-21 15:56:15 +0100 | [diff] [blame] | 1719 | #ifdef __aarch64__ |
Pablo Marquez Tello | d75cd8a | 2022-05-26 14:19:39 +0100 | [diff] [blame] | 1720 | const LookupTable256 &lut() const |
| 1721 | { |
| 1722 | return _lut; |
| 1723 | } |
| 1724 | |
Viet-Hoa Do | 29db3d2 | 2022-08-10 11:56:49 +0100 | [diff] [blame] | 1725 | void init_lut(DataType data_type, const UniformQuantizationInfo &qi_in, const UniformQuantizationInfo &qi_out) |
Pablo Marquez Tello | d75cd8a | 2022-05-26 14:19:39 +0100 | [diff] [blame] | 1726 | { |
Viet-Hoa Do | b042e39 | 2022-06-21 15:56:15 +0100 | [diff] [blame] | 1727 | if(_act == ActivationFunction::HARD_SWISH) |
| 1728 | { |
Pablo Marquez Tello | 16789a1 | 2022-07-25 14:41:26 +0100 | [diff] [blame] | 1729 | if(data_type == DataType::QASYMM8) |
| 1730 | { |
| 1731 | qasymm8_hard_swish_populate_table(_lut, qi_in, qi_out); |
| 1732 | } |
| 1733 | else |
| 1734 | { |
| 1735 | qasymm8_signed_hard_swish_populate_table(_lut, qi_in, qi_out); |
| 1736 | } |
Viet-Hoa Do | b042e39 | 2022-06-21 15:56:15 +0100 | [diff] [blame] | 1737 | } |
| 1738 | else if(_act == ActivationFunction::LEAKY_RELU) |
| 1739 | { |
| 1740 | qasymm8_leaky_relu_populate_table(_lut, qi_in, qi_out, _a); |
| 1741 | } |
Viet-Hoa Do | 29db3d2 | 2022-08-10 11:56:49 +0100 | [diff] [blame] | 1742 | else if(_act == ActivationFunction::LOGISTIC) |
| 1743 | { |
| 1744 | if(data_type == DataType::QASYMM8) |
| 1745 | { |
| 1746 | qasymm8_logistic_populate_table(_lut, qi_in, qi_out); |
| 1747 | } |
| 1748 | else |
| 1749 | { |
| 1750 | qasymm8_signed_logistic_populate_table(_lut, qi_in, qi_out); |
| 1751 | } |
| 1752 | } |
Viet-Hoa Do | b042e39 | 2022-06-21 15:56:15 +0100 | [diff] [blame] | 1753 | } |
| 1754 | #endif // __aarch64__ |
| 1755 | |
| 1756 | static inline bool is_lut_supported(ActivationFunction act_func, DataType data_type) |
| 1757 | { |
| 1758 | #ifdef __aarch64__ |
Viet-Hoa Do | 29db3d2 | 2022-08-10 11:56:49 +0100 | [diff] [blame] | 1759 | switch(act_func) |
| 1760 | { |
| 1761 | case ActivationFunction::HARD_SWISH: |
Pablo Marquez Tello | 16789a1 | 2022-07-25 14:41:26 +0100 | [diff] [blame] | 1762 | return data_type == DataType::QASYMM8 || data_type == DataType::QASYMM8_SIGNED; |
Viet-Hoa Do | 29db3d2 | 2022-08-10 11:56:49 +0100 | [diff] [blame] | 1763 | case ActivationFunction::LEAKY_RELU: |
| 1764 | return data_type == DataType::QASYMM8; |
Viet-Hoa Do | 29db3d2 | 2022-08-10 11:56:49 +0100 | [diff] [blame] | 1765 | case ActivationFunction::LOGISTIC: |
Pablo Marquez Tello | 16789a1 | 2022-07-25 14:41:26 +0100 | [diff] [blame] | 1766 | return data_type == DataType::QASYMM8 || data_type == DataType::QASYMM8_SIGNED; |
Viet-Hoa Do | 29db3d2 | 2022-08-10 11:56:49 +0100 | [diff] [blame] | 1767 | default: |
| 1768 | return false; |
| 1769 | } |
Viet-Hoa Do | b042e39 | 2022-06-21 15:56:15 +0100 | [diff] [blame] | 1770 | #else // __aarch64__ |
| 1771 | ARM_COMPUTE_UNUSED(act_func); |
| 1772 | ARM_COMPUTE_UNUSED(data_type); |
| 1773 | return false; |
| 1774 | #endif // __aarch64__ |
Pablo Marquez Tello | d75cd8a | 2022-05-26 14:19:39 +0100 | [diff] [blame] | 1775 | } |
| 1776 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1777 | private: |
Usama Arif | 6a98a6e | 2019-05-10 17:07:27 +0100 | [diff] [blame] | 1778 | ActivationFunction _act = { ActivationLayerInfo::ActivationFunction::IDENTITY }; |
Giorgio Arena | 1167487 | 2018-02-07 15:38:12 +0000 | [diff] [blame] | 1779 | float _a = {}; |
| 1780 | float _b = {}; |
| 1781 | bool _enabled = { false }; |
Pablo Marquez Tello | d75cd8a | 2022-05-26 14:19:39 +0100 | [diff] [blame] | 1782 | |
Viet-Hoa Do | b042e39 | 2022-06-21 15:56:15 +0100 | [diff] [blame] | 1783 | #ifdef __aarch64__ |
| 1784 | LookupTable256 _lut = {}; |
| 1785 | |
| 1786 | static inline void qasymm8_hard_swish_populate_table(LookupTable256 &lut, const UniformQuantizationInfo &qi_in, const UniformQuantizationInfo &qi_out) |
Pablo Marquez Tello | d75cd8a | 2022-05-26 14:19:39 +0100 | [diff] [blame] | 1787 | { |
| 1788 | for(size_t i = 0; i < lut.size(); ++i) |
| 1789 | { |
| 1790 | lut[i] = qasymm8_hard_swish(i, qi_in, qi_out); |
| 1791 | } |
| 1792 | } |
Viet-Hoa Do | b042e39 | 2022-06-21 15:56:15 +0100 | [diff] [blame] | 1793 | |
Pablo Marquez Tello | 16789a1 | 2022-07-25 14:41:26 +0100 | [diff] [blame] | 1794 | static inline void qasymm8_signed_hard_swish_populate_table(LookupTable256 &lut, const UniformQuantizationInfo &qi_in, const UniformQuantizationInfo &qi_out) |
| 1795 | { |
| 1796 | for(size_t i = 0; i < lut.size(); ++i) |
| 1797 | { |
| 1798 | lut[i] = qasymm8_signed_hard_swish(i, qi_in, qi_out); |
| 1799 | } |
| 1800 | } |
| 1801 | |
Viet-Hoa Do | b042e39 | 2022-06-21 15:56:15 +0100 | [diff] [blame] | 1802 | static inline void qasymm8_leaky_relu_populate_table(LookupTable256 &lut, const UniformQuantizationInfo &qi_in, const UniformQuantizationInfo &qi_out, float alpha) |
| 1803 | { |
| 1804 | for(size_t i = 0; i < lut.size(); ++i) |
| 1805 | { |
| 1806 | lut[i] = qasymm8_leaky_relu(i, qi_in, qi_out, alpha); |
| 1807 | } |
| 1808 | } |
Viet-Hoa Do | 29db3d2 | 2022-08-10 11:56:49 +0100 | [diff] [blame] | 1809 | |
| 1810 | static inline void qasymm8_logistic_populate_table(LookupTable256 &lut, const UniformQuantizationInfo &qi_in, const UniformQuantizationInfo &qi_out) |
| 1811 | { |
| 1812 | for(size_t i = 0; i < lut.size(); ++i) |
| 1813 | { |
| 1814 | lut[i] = qasymm8_logistic(i, qi_in, qi_out); |
| 1815 | } |
| 1816 | } |
| 1817 | |
| 1818 | static inline void qasymm8_signed_logistic_populate_table(LookupTable256 &lut, const UniformQuantizationInfo &qi_in, const UniformQuantizationInfo &qi_out) |
| 1819 | { |
| 1820 | for(size_t i = 0; i < lut.size(); ++i) |
| 1821 | { |
| 1822 | lut[i] = qasymm8_signed_logistic(static_cast<int8_t>(i), qi_in, qi_out); |
| 1823 | } |
| 1824 | } |
Viet-Hoa Do | b042e39 | 2022-06-21 15:56:15 +0100 | [diff] [blame] | 1825 | #endif // __aarch64__ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1826 | }; |
| 1827 | |
Giorgio Arena | 1856ff7 | 2020-02-07 13:46:45 +0000 | [diff] [blame] | 1828 | /** Fully connected layer info */ |
| 1829 | struct FullyConnectedLayerInfo |
| 1830 | { |
Michele Di Giorgio | c3f459d | 2021-05-05 15:42:20 +0100 | [diff] [blame] | 1831 | /* Fused-activation parameters */ |
| 1832 | ActivationLayerInfo activation_info{}; /**< Fused activation to apply after the matrix multiplication. */ |
| 1833 | /* Information about weights */ |
| 1834 | DataLayout weights_trained_layout{ DataLayout::NCHW }; /**< Layout that the weights have been trained with. */ |
| 1835 | bool transpose_weights{ true }; /**< Transpose weights if true. */ |
| 1836 | bool are_weights_reshaped{ false }; /**< Reshape the weights tensor if false. */ |
| 1837 | bool retain_internal_weights{ false }; /**< Retain internal reshaped weights. */ |
cfRod | f2c022e | 2021-11-05 11:29:53 +0000 | [diff] [blame] | 1838 | bool enable_fast_math{ false }; /**< Enable fast math computation. */ |
Michele Di Giorgio | c3f459d | 2021-05-05 15:42:20 +0100 | [diff] [blame] | 1839 | /* Other parameters */ |
| 1840 | bool fp_mixed_precision{ false }; /**< Use wider accumulators (32 bit instead of 16 for FP16) to improve accuracy. */ |
Giorgio Arena | 1856ff7 | 2020-02-07 13:46:45 +0000 | [diff] [blame] | 1841 | |
| 1842 | /** Sets the weights trained data layout |
| 1843 | * |
| 1844 | * @param[in] layout Data layout that the weights were trained with |
| 1845 | * |
| 1846 | * @return Updated object |
| 1847 | */ |
| 1848 | FullyConnectedLayerInfo &set_weights_trained_layout(DataLayout layout) |
| 1849 | { |
| 1850 | weights_trained_layout = layout; |
| 1851 | return *this; |
| 1852 | } |
| 1853 | /** Sets the transpose weights flag |
| 1854 | * |
| 1855 | * @param[in] should_transpose_weights Boolean flag indicating if weights should be transposed |
| 1856 | * |
| 1857 | * @return Updated object |
| 1858 | */ |
| 1859 | FullyConnectedLayerInfo &set_transpose_weights(bool should_transpose_weights) |
| 1860 | { |
| 1861 | transpose_weights = should_transpose_weights; |
| 1862 | return *this; |
| 1863 | } |
| 1864 | }; |
| 1865 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1866 | /** Normalization Layer Information class */ |
| 1867 | class NormalizationLayerInfo |
| 1868 | { |
| 1869 | public: |
| 1870 | /** Default Constructor |
| 1871 | * |
Michele Di Giorgio | 9d3a831 | 2018-11-20 12:31:24 +0000 | [diff] [blame] | 1872 | * @param[in] type The normalization type. Can be @ref NormType::IN_MAP_1D, @ref NormType::IN_MAP_2D or @ref NormType::CROSS_MAP |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1873 | * @param[in] norm_size The normalization size is the number of elements to normalize across. Defaults to 5. |
Georgios Pinitas | 41caa62 | 2017-11-16 14:37:08 +0000 | [diff] [blame] | 1874 | * @param[in] alpha (Optional) Alpha parameter used by normalization equation. Defaults to 0.0001. |
| 1875 | * @param[in] beta (Optional) Beta parameter used by normalization equation. Defaults to 0.5. |
| 1876 | * @param[in] kappa (Optional) Kappa parameter used by [Krichevksy 2012] Across Channel Local Brightness Normalization equation. |
| 1877 | * @param[in] is_scaled (Optional) Boolean that specifies if alpha will be scaled by the normalization size or not. |
| 1878 | * Should be false to follow [Krichevksy 2012]. |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1879 | */ |
Georgios Pinitas | 41caa62 | 2017-11-16 14:37:08 +0000 | [diff] [blame] | 1880 | NormalizationLayerInfo(NormType type, uint32_t norm_size = 5, float alpha = 0.0001f, float beta = 0.5f, float kappa = 1.f, bool is_scaled = true) |
| 1881 | : _type(type), _norm_size(norm_size), _alpha(alpha), _beta(beta), _kappa(kappa), _is_scaled(is_scaled) |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1882 | { |
| 1883 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1884 | /** Get the normalization type */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1885 | NormType type() const |
| 1886 | { |
| 1887 | return _type; |
| 1888 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1889 | /** Get the normalization size */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1890 | uint32_t norm_size() const |
| 1891 | { |
| 1892 | return _norm_size; |
| 1893 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1894 | /** Get the alpha value */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1895 | float alpha() const |
| 1896 | { |
| 1897 | return _alpha; |
| 1898 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1899 | /** Get the beta value */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1900 | float beta() const |
| 1901 | { |
| 1902 | return _beta; |
| 1903 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1904 | /** Get the kappa value */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1905 | float kappa() const |
| 1906 | { |
| 1907 | return _kappa; |
| 1908 | } |
Michele Di Giorgio | 9d3a831 | 2018-11-20 12:31:24 +0000 | [diff] [blame] | 1909 | /** Get the is_scaled value */ |
| 1910 | bool is_scaled() const |
| 1911 | { |
| 1912 | return _is_scaled; |
| 1913 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1914 | /** Check if normalization is cross map */ |
Georgios Pinitas | 41caa62 | 2017-11-16 14:37:08 +0000 | [diff] [blame] | 1915 | bool is_cross_map() const |
| 1916 | { |
| 1917 | return _type == NormType::CROSS_MAP; |
| 1918 | } |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 1919 | /** Check if normalization is not cross map */ |
Georgios Pinitas | 41caa62 | 2017-11-16 14:37:08 +0000 | [diff] [blame] | 1920 | bool is_in_map() const |
| 1921 | { |
| 1922 | return !is_cross_map(); |
| 1923 | } |
| 1924 | /** Return the scaling factor of the normalization function. |
| 1925 | * |
| 1926 | * If is_scaled is set to false then [Krichevksy 2012] normalization scaling is performed, |
| 1927 | * where alpha is returned plainly, else alpha is scaled by the total number of elements used for the normalization. |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1928 | * |
| 1929 | * @return The normalization scaling factor. |
| 1930 | */ |
| 1931 | float scale_coeff() const |
| 1932 | { |
| 1933 | const uint32_t size = (_type == NormType::IN_MAP_2D) ? _norm_size * _norm_size : _norm_size; |
Georgios Pinitas | 41caa62 | 2017-11-16 14:37:08 +0000 | [diff] [blame] | 1934 | return (_is_scaled) ? (_alpha / size) : _alpha; |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1935 | } |
| 1936 | |
| 1937 | private: |
| 1938 | NormType _type; |
| 1939 | uint32_t _norm_size; |
| 1940 | float _alpha; |
| 1941 | float _beta; |
| 1942 | float _kappa; |
Georgios Pinitas | 41caa62 | 2017-11-16 14:37:08 +0000 | [diff] [blame] | 1943 | bool _is_scaled; |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 1944 | }; |
| 1945 | |
thecha01 | 2bfadd9 | 2020-08-12 17:25:51 +0100 | [diff] [blame] | 1946 | class StridedSliceLayerInfo |
| 1947 | { |
| 1948 | public: |
| 1949 | /** Default Constructor |
| 1950 | * |
| 1951 | * @param[in] begin_mask (Optional) If the ith bit of begin_mask is set, starts[i] is ignored and the fullest possible range in that dimension is used instead. |
| 1952 | * @param[in] end_mask (Optional) If the ith bit of end_mask is set, ends[i] is ignored and the fullest possible range in that dimension is used instead. |
| 1953 | * @param[in] shrink_axis_mask (Optional) If the ith bit of shrink_axis_mask is set, it implies that the ith specification shrinks the dimensionality by 1. |
| 1954 | */ |
| 1955 | StridedSliceLayerInfo(int32_t begin_mask = 0, int32_t end_mask = 0, int32_t shrink_axis_mask = 0) |
| 1956 | : _begin_mask(begin_mask), _end_mask(end_mask), _shrink_axis_mask(shrink_axis_mask) |
| 1957 | { |
| 1958 | } |
| 1959 | |
| 1960 | /* Get the begin mask value */ |
| 1961 | int32_t begin_mask() const |
| 1962 | { |
| 1963 | return _begin_mask; |
| 1964 | } |
| 1965 | |
| 1966 | /* Get the end mask value */ |
| 1967 | int32_t end_mask() const |
| 1968 | { |
| 1969 | return _end_mask; |
| 1970 | } |
| 1971 | |
| 1972 | /* Get the shrink axis mask value */ |
| 1973 | int32_t shrink_axis_mask() const |
| 1974 | { |
| 1975 | return _shrink_axis_mask; |
| 1976 | } |
| 1977 | |
| 1978 | private: |
| 1979 | int32_t _begin_mask; |
| 1980 | int32_t _end_mask; |
| 1981 | int32_t _shrink_axis_mask; |
| 1982 | }; |
| 1983 | |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 1984 | /** Memory layouts for the weights tensor. |
| 1985 | * |
| 1986 | * * UNSPECIFIED is used to select kernels that do not run in |
| 1987 | * variable weights mode. |
| 1988 | * |
| 1989 | * * ANY is used to query the kernel database to retrieve any of the |
| 1990 | * kernels that runs in variable weights mode. Once a kernel is |
| 1991 | * found, the specific format expected by the kernel can be |
| 1992 | * retrieved by the user for reordering the weights tensor |
| 1993 | * accordingly. |
| 1994 | * |
| 1995 | * The other values OHWIo{interleave_by}i{block_by} describe the |
| 1996 | * memory layout of a 4D tensor with layout OHWI that has been |
| 1997 | * transformed into a 4D tensor with dimensions O'HWI' where: |
| 1998 | * |
| 1999 | * O' = first multiple of {interleave_by} s.t. O<=O' |
| 2000 | * I' = first multiple of {block_by} s.t. I<=I' |
| 2001 | * |
| 2002 | * The total size of the dst tensor is O' x H x W x I' |
| 2003 | * |
| 2004 | * The access function of the tensor with layout |
| 2005 | * OHWIo{interleave_by}i{block_by} and size O'HWI' is a 6-parameter |
| 2006 | * access function, where the 6 parameters are computed as follows: |
| 2007 | * |
| 2008 | * x5 = floor(o/{interleave_by}) RANGE [0, O'/{interleave_by} -1] SIZE: O'/{interleave_by} |
| 2009 | * |
| 2010 | * x4 = h RANGE [0, H-1] SIZE: H |
| 2011 | * x3 = w RANGE [0, W-1] SIZE: W |
| 2012 | * x2 = floor(i/{block_by}) RANGE [0, I'/{block_by} -1] SIZE: I'/{block_by} |
| 2013 | * x1 = o%{interleave_by} RANGE [0, {interleave_by} -1] SIZE: {interleave_by} |
| 2014 | * x0 = i%{block_by} RANGE [0, {block_by} -1] SIZE: {block_by} |
| 2015 | * TOTAL SIZE: O' * H * W * I' |
| 2016 | * |
| 2017 | * 4D 6D |
| 2018 | * ----------------- ----------------------------------- |
| 2019 | * value(o, h, w, i) = x5 * H * W * I' * {interleave_by} |
| 2020 | * + x4 * W * I' * {interleave_by} |
| 2021 | * + x3 * I' * {interleave_by} |
| 2022 | * + x2 * {interleave_by} * {block_by} |
| 2023 | * + x1 * {block_by} |
| 2024 | * + x0 |
| 2025 | * |
| 2026 | * Notice that in arm_gemm the 4D tensor of dimension O'HWI' created |
| 2027 | * for the OHWIo{interleave_by}i{block_by} format is in reality seen |
| 2028 | * as a 2D tensor, where the number of rows is O'/{interleave_by} |
| 2029 | * and the number of columns is {interleave_by} * H * W * I'. |
| 2030 | * |
| 2031 | * The postfix *_bf16 is for the memory layout needed for the |
| 2032 | * fast-mode kernels, in which the weights are passed in bfloat16 |
| 2033 | * format. |
| 2034 | */ |
| 2035 | enum class WeightFormat |
| 2036 | { |
| 2037 | UNSPECIFIED = 0x1, |
| 2038 | ANY = 0x2, |
| 2039 | OHWI = 0x100100, |
| 2040 | OHWIo2 = 0x100200, |
| 2041 | OHWIo4 = 0x100400, |
| 2042 | OHWIo8 = 0x100800, |
| 2043 | OHWIo16 = 0x101000, |
| 2044 | OHWIo32 = 0x102000, |
| 2045 | OHWIo64 = 0x104000, |
| 2046 | OHWIo128 = 0x108000, |
| 2047 | OHWIo4i2 = 0x200400, |
| 2048 | OHWIo4i2_bf16 = 0x200410, |
| 2049 | OHWIo8i2 = 0x200800, |
| 2050 | OHWIo8i2_bf16 = 0x200810, |
| 2051 | OHWIo16i2 = 0x201000, |
| 2052 | OHWIo16i2_bf16 = 0x201010, |
| 2053 | OHWIo32i2 = 0x202000, |
| 2054 | OHWIo32i2_bf16 = 0x202010, |
| 2055 | OHWIo64i2 = 0x204000, |
| 2056 | OHWIo64i2_bf16 = 0x204010, |
| 2057 | OHWIo4i4 = 0x400400, |
| 2058 | OHWIo4i4_bf16 = 0x400410, |
| 2059 | OHWIo8i4 = 0x400800, |
| 2060 | OHWIo8i4_bf16 = 0x400810, |
| 2061 | OHWIo16i4 = 0x401000, |
| 2062 | OHWIo16i4_bf16 = 0x401010, |
| 2063 | OHWIo32i4 = 0x402000, |
| 2064 | OHWIo32i4_bf16 = 0x402010, |
| 2065 | OHWIo64i4 = 0x404000, |
| 2066 | OHWIo64i4_bf16 = 0x404010, |
| 2067 | OHWIo2i8 = 0x800200, |
| 2068 | OHWIo4i8 = 0x800400, |
| 2069 | OHWIo8i8 = 0x800800, |
| 2070 | OHWIo16i8 = 0x801000, |
| 2071 | OHWIo32i8 = 0x802000, |
| 2072 | OHWIo64i8 = 0x804000 |
| 2073 | }; |
| 2074 | // OHWIo<interleave_by>i<block_by> |
| 2075 | inline int interleave_by(const WeightFormat wf) |
| 2076 | { |
Pablo Marquez Tello | 93581a5 | 2022-07-21 13:55:27 +0100 | [diff] [blame] | 2077 | return (static_cast<int>(wf) >> 8) & 0xFFF; |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2078 | } |
| 2079 | inline int block_by(const WeightFormat wf) |
| 2080 | { |
Pablo Marquez Tello | 93581a5 | 2022-07-21 13:55:27 +0100 | [diff] [blame] | 2081 | return (static_cast<int>(wf) >> 20) & 0xF; |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2082 | } |
Pablo Marquez Tello | 93581a5 | 2022-07-21 13:55:27 +0100 | [diff] [blame] | 2083 | inline bool is_fixed_format(const WeightFormat &wf) |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2084 | { |
| 2085 | return wf != WeightFormat::UNSPECIFIED && wf != WeightFormat::ANY; |
| 2086 | } |
Pablo Marquez Tello | 93581a5 | 2022-07-21 13:55:27 +0100 | [diff] [blame] | 2087 | inline bool is_fixed_format_fast_math(const WeightFormat &wf) |
| 2088 | { |
| 2089 | return (static_cast<int>(wf) >> 4) & 0x1; |
| 2090 | } |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2091 | |
Gian Marco Iodice | 559d771 | 2017-08-08 08:38:09 +0100 | [diff] [blame] | 2092 | /** Convolution Layer Weights Information class. This class stores the necessary information to compute convolution layer when the weights are already reshaped */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2093 | class WeightsInfo |
| 2094 | { |
| 2095 | public: |
Gian Marco Iodice | 4e28869 | 2017-06-27 11:41:59 +0100 | [diff] [blame] | 2096 | /** Default constructor */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2097 | WeightsInfo() |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2098 | : _are_reshaped(false), _kernel_width(0), _kernel_height(0), _num_kernels(0), _retain_internal_weights(false), _weight_format(arm_compute::WeightFormat::UNSPECIFIED) |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2099 | { |
| 2100 | } |
| 2101 | /** Constructor |
| 2102 | * |
Michele Di Giorgio | b62280a | 2018-05-31 17:31:05 +0100 | [diff] [blame] | 2103 | * @param[in] are_reshaped True if the weights have been reshaped |
| 2104 | * @param[in] kernel_width Kernel width. |
| 2105 | * @param[in] kernel_height Kernel height. |
| 2106 | * @param[in] num_kernels Number of convolution kernels. |
| 2107 | * @param[in] retain_internal_weights (Optional) True if internal reshaped weights must be retained. Used for reconfiguration purposes. Default is false. |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2108 | * @param[in] weight_format (Optional) arm_gemm:WeightFormat enumeration requested by the user. Default is arm_compute::WeightFormat::UNSPECIFIED. |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2109 | */ |
Francesco Petrogalli | 553f695 | 2022-06-30 10:22:01 +0000 | [diff] [blame] | 2110 | WeightsInfo(bool are_reshaped, unsigned int kernel_width, unsigned int kernel_height, unsigned int num_kernels, bool retain_internal_weights = false, |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2111 | arm_compute::WeightFormat weight_format = arm_compute::WeightFormat::UNSPECIFIED) |
Francesco Petrogalli | 553f695 | 2022-06-30 10:22:01 +0000 | [diff] [blame] | 2112 | : _are_reshaped(are_reshaped), _kernel_width(kernel_width), _kernel_height(kernel_height), _num_kernels(num_kernels), _retain_internal_weights(retain_internal_weights), _weight_format(weight_format) |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2113 | { |
| 2114 | } |
Gian Marco Iodice | 4e28869 | 2017-06-27 11:41:59 +0100 | [diff] [blame] | 2115 | /** Flag which specifies if the weights tensor has been reshaped. |
| 2116 | * |
| 2117 | * @return True if the weights tensors has been reshaped |
| 2118 | */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2119 | bool are_reshaped() const |
| 2120 | { |
| 2121 | return _are_reshaped; |
| 2122 | }; |
Gian Marco Iodice | 559d771 | 2017-08-08 08:38:09 +0100 | [diff] [blame] | 2123 | /** Return the number of convolution kernels |
| 2124 | * |
| 2125 | * @return The number of convolution kernels |
| 2126 | */ |
| 2127 | unsigned int num_kernels() const |
| 2128 | { |
| 2129 | return _num_kernels; |
| 2130 | }; |
Gian Marco Iodice | 4e28869 | 2017-06-27 11:41:59 +0100 | [diff] [blame] | 2131 | /** Return the width and height of the kernel |
| 2132 | * |
| 2133 | * @return The width and height of the kernel |
| 2134 | */ |
| 2135 | std::pair<unsigned int, unsigned int> kernel_size() const |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2136 | { |
Gian Marco Iodice | 4e28869 | 2017-06-27 11:41:59 +0100 | [diff] [blame] | 2137 | return std::make_pair(_kernel_width, _kernel_height); |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2138 | } |
Michele Di Giorgio | b62280a | 2018-05-31 17:31:05 +0100 | [diff] [blame] | 2139 | bool retain_internal_weights() const |
| 2140 | { |
| 2141 | return _retain_internal_weights; |
| 2142 | } |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2143 | arm_compute::WeightFormat weight_format() const |
Francesco Petrogalli | 553f695 | 2022-06-30 10:22:01 +0000 | [diff] [blame] | 2144 | { |
| 2145 | return _weight_format; |
| 2146 | } |
Milos Puzovic | 13b623e | 2022-07-27 17:53:21 +0000 | [diff] [blame] | 2147 | void set_weight_format(arm_compute::WeightFormat weight_format) |
| 2148 | { |
| 2149 | _weight_format = weight_format; |
| 2150 | } |
| 2151 | |
Francesco Petrogalli | 553f695 | 2022-06-30 10:22:01 +0000 | [diff] [blame] | 2152 | unsigned int kernel_width() const |
| 2153 | { |
| 2154 | return _kernel_width; |
| 2155 | } |
| 2156 | unsigned int kernel_height() const |
| 2157 | { |
| 2158 | return _kernel_height; |
| 2159 | } |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2160 | |
| 2161 | private: |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2162 | bool _are_reshaped; |
| 2163 | unsigned int _kernel_width; |
| 2164 | unsigned int _kernel_height; |
| 2165 | unsigned int _num_kernels; |
| 2166 | bool _retain_internal_weights; |
| 2167 | arm_compute::WeightFormat _weight_format; |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2168 | }; |
| 2169 | |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2170 | /** GEMM reshape information class. This class stores the necessary information about matrix A and matrix B reshape. |
| 2171 | * |
Michele Di Giorgio | 93b75e0 | 2021-06-21 12:00:43 +0100 | [diff] [blame] | 2172 | * The matrix A can only be reshaped through @ref opencl::kernels::ClGemmReshapeLhsMatrixKernel or @ref cpu::kernels::CpuGemmInterleave4x4Kernel |
Georgios Pinitas | 856f66e | 2021-04-22 21:13:21 +0100 | [diff] [blame] | 2173 | * Note: Optionally just for @ref opencl::kernels::ClGemmReshapeLhsMatrixKernel is it possible to set mult_interleave4x4_height, the multiplication factor for the height of the 4x4 interleaved block |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2174 | * |
Michele Di Giorgio | 93b75e0 | 2021-06-21 12:00:43 +0100 | [diff] [blame] | 2175 | * The matrix B can only be reshaped through @ref opencl::kernels::ClGemmReshapeRhsMatrixKernel or @ref cpu::kernels::CpuGemmTranspose1xWKernel |
Georgios Pinitas | 856f66e | 2021-04-22 21:13:21 +0100 | [diff] [blame] | 2176 | * Note: Optionally just for @ref opencl::kernels::ClGemmReshapeRhsMatrixKernel is it possible to set mult_transpose1xW_width, the multiplication factor for the width of the 1xW transposed block |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2177 | * |
| 2178 | */ |
| 2179 | class GEMMReshapeInfo final |
| 2180 | { |
| 2181 | public: |
| 2182 | /** Default constructor */ |
| 2183 | GEMMReshapeInfo() |
Georgios Pinitas | b0f342e | 2019-05-21 13:32:43 +0100 | [diff] [blame] | 2184 | : _m(1), _n(1), _k(1), _mult_transpose1xW_width(1), _mult_interleave4x4_height(1), _depth_output_gemm3d(0), _reinterpret_input_as_3d(false), _broadcast_bias(false) |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2185 | { |
| 2186 | } |
| 2187 | /** Constructor |
| 2188 | * |
| 2189 | * @param[in] m Number of matrix A rows |
| 2190 | * @param[in] n Number of matrix B columns |
| 2191 | * @param[in] k Number of matrix A columns or matrix B rows |
| 2192 | * @param[in] mult_transpose1xW_width (Optional) Multiplication factor for the width of the 1xW transposed block |
| 2193 | * @param[in] mult_interleave4x4_height (Optional) Multiplication factor for the height of the 4x4 interleaved block |
Gian Marco Iodice | 3139f03 | 2018-11-05 14:26:32 +0000 | [diff] [blame] | 2194 | * @param[in] depth_output_gemm3d (Optional) Depth (third dimension) of the output tensor to be used with the GEMM3D kernel. |
| 2195 | * If 0 the output will not be reinterpreted as 3D. Default 0 |
Gian Marco Iodice | 68a3f56 | 2018-07-26 11:44:03 +0100 | [diff] [blame] | 2196 | * @param[in] reinterpret_input_as_3d (Optional) Reinterpret the input as 3D tensor. (i.e. this flag should be set to true when GEMM is used |
Georgios Pinitas | b0f342e | 2019-05-21 13:32:43 +0100 | [diff] [blame] | 2197 | * to perform 1x1 convolutions with the NHWC data layout) |
| 2198 | * @param[in] broadcast_bias (Optional) Broadcast the shape of the bias tensor from a vector to a matrix. |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2199 | */ |
Georgios Pinitas | b0f342e | 2019-05-21 13:32:43 +0100 | [diff] [blame] | 2200 | GEMMReshapeInfo(int m, int n, int k, int mult_transpose1xW_width = 1, int mult_interleave4x4_height = 1, int depth_output_gemm3d = 0, bool reinterpret_input_as_3d = false, bool broadcast_bias = false) |
Gian Marco Iodice | 68a3f56 | 2018-07-26 11:44:03 +0100 | [diff] [blame] | 2201 | : _m(m), _n(n), _k(k), _mult_transpose1xW_width(mult_transpose1xW_width), _mult_interleave4x4_height(mult_interleave4x4_height), _depth_output_gemm3d(depth_output_gemm3d), |
Georgios Pinitas | b0f342e | 2019-05-21 13:32:43 +0100 | [diff] [blame] | 2202 | _reinterpret_input_as_3d(reinterpret_input_as_3d), _broadcast_bias(broadcast_bias) |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2203 | { |
| 2204 | } |
| 2205 | /** Number of matrix A rows |
| 2206 | * |
| 2207 | * @return the number of matrix A rows |
| 2208 | */ |
| 2209 | int m() const |
| 2210 | { |
| 2211 | return _m; |
| 2212 | } |
| 2213 | /** Number of matrix B columns |
| 2214 | * |
| 2215 | * @return the number of matrix B columns |
| 2216 | */ |
| 2217 | int n() const |
| 2218 | { |
| 2219 | return _n; |
| 2220 | } |
| 2221 | /** Number of matrix A columns or matrix B rows |
| 2222 | * |
| 2223 | * @return the number of matrix A columns or matrix B rows |
| 2224 | */ |
| 2225 | int k() const |
| 2226 | { |
| 2227 | return _k; |
| 2228 | } |
| 2229 | /** Multiplication factor for the width of the 1xW transposed block |
| 2230 | * |
| 2231 | * @return the multiplication factor for the width of the 1xW transposed block |
| 2232 | */ |
| 2233 | int mult_transpose1xW_width() const |
| 2234 | { |
| 2235 | return _mult_transpose1xW_width; |
| 2236 | } |
| 2237 | /** Multiplication factor for the height of the 4x4 interleaved block |
| 2238 | * |
| 2239 | * @return the multiplication factor for the height of the 4x4 interleaved block |
| 2240 | */ |
| 2241 | int mult_interleave4x4_height() const |
| 2242 | { |
| 2243 | return _mult_interleave4x4_height; |
| 2244 | } |
Isabella Gottardi | 8e74f44 | 2018-03-01 16:42:00 +0000 | [diff] [blame] | 2245 | /** Depth (third dimension) of the output tensor to be used with the GEMM3D kernel |
| 2246 | * |
| 2247 | * @note GEMM3D kernel is used when the output has to be reinterpret as 3D tensor. In that case: |
| 2248 | * m = depth_output_gemm3d * output_height |
| 2249 | * |
| 2250 | * @return the depth of the output tensor to be used with the GEMM3D kernel |
| 2251 | */ |
| 2252 | int depth_output_gemm3d() const |
| 2253 | { |
| 2254 | return _depth_output_gemm3d; |
| 2255 | } |
Gian Marco Iodice | 68a3f56 | 2018-07-26 11:44:03 +0100 | [diff] [blame] | 2256 | /** Flag which specifies if the input tensor has to be reinterpreted as 3D |
| 2257 | * |
| 2258 | * @return True if the input tensor has to be reinterpreted as 3D tensor |
| 2259 | */ |
| 2260 | bool reinterpret_input_as_3d() const |
| 2261 | { |
| 2262 | return _reinterpret_input_as_3d; |
| 2263 | }; |
Georgios Pinitas | b0f342e | 2019-05-21 13:32:43 +0100 | [diff] [blame] | 2264 | /** Flag which specifies whether to broadcast the shape of the bias tensor. |
| 2265 | * |
| 2266 | * @return True if the shape of the bias tensor is to be broadcasted. |
| 2267 | */ |
| 2268 | bool broadcast_bias() const |
| 2269 | { |
| 2270 | return _broadcast_bias; |
| 2271 | }; |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2272 | |
| 2273 | private: |
SiCong Li | ebd8fb4 | 2020-08-18 11:03:14 +0100 | [diff] [blame] | 2274 | int _m; |
| 2275 | int _n; |
| 2276 | int _k; |
| 2277 | int _mult_transpose1xW_width; |
| 2278 | int _mult_interleave4x4_height; |
| 2279 | int _depth_output_gemm3d; |
| 2280 | bool _reinterpret_input_as_3d; |
| 2281 | bool _broadcast_bias; |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2282 | }; |
| 2283 | |
Michalis Spyrou | 60c3b0e | 2021-04-08 12:02:58 +0100 | [diff] [blame] | 2284 | struct ConvolutionInfo |
| 2285 | { |
| 2286 | ConvolutionInfo() = default; |
| 2287 | ConvolutionInfo(const PadStrideInfo &pad_stride_info, unsigned int depth_multiplier, const ActivationLayerInfo &act_info, const Size2D &dilation) |
| 2288 | : pad_stride_info(pad_stride_info), depth_multiplier(depth_multiplier), act_info(act_info), dilation(dilation) |
| 2289 | { |
| 2290 | } |
| 2291 | PadStrideInfo pad_stride_info{}; /**< Convolution info (Pads, strides,...) */ |
| 2292 | unsigned int depth_multiplier{ 1 }; /**< Multiplier to apply to input's depth to retrieve the output depth. Defaults to 1 */ |
| 2293 | ActivationLayerInfo act_info{}; /**< Fused activation to apply after convolution. */ |
| 2294 | Size2D dilation{ Size2D(1, 1) }; /**< Dilation, in elements, across x and y. Defaults to (1, 1). */ |
| 2295 | }; |
| 2296 | |
Gian Marco Iodice | 4b90865 | 2018-10-18 10:21:02 +0100 | [diff] [blame] | 2297 | /** GEMMLowp output stage type */ |
| 2298 | enum class GEMMLowpOutputStageType |
| 2299 | { |
Manuel Bottini | 959c26d | 2019-12-02 16:22:35 +0000 | [diff] [blame] | 2300 | NONE, /**< No quantization */ |
| 2301 | QUANTIZE_DOWN, /**< Quantize using an integer multiplication */ |
| 2302 | QUANTIZE_DOWN_FIXEDPOINT, /**< Quantize using a fixed point multiplication */ |
| 2303 | QUANTIZE_DOWN_FLOAT /**< Quantize using a floating point multiplication */ |
Gian Marco Iodice | 4b90865 | 2018-10-18 10:21:02 +0100 | [diff] [blame] | 2304 | }; |
| 2305 | |
| 2306 | /** GEMMLowp output stage info */ |
| 2307 | struct GEMMLowpOutputStageInfo |
| 2308 | { |
Giorgio Arena | 1856ff7 | 2020-02-07 13:46:45 +0000 | [diff] [blame] | 2309 | GEMMLowpOutputStageType type{ GEMMLowpOutputStageType::NONE }; /**< GEMMLowp output stage type */ |
| 2310 | int32_t gemmlowp_offset{ 0 }; /**< GEMMLowp output stage offset used for quantizing to QASYMM8 */ |
| 2311 | int32_t gemmlowp_multiplier{ 0 }; /**< GEMMLowp output stage multiplier used for quantizing to QASYMM8 */ |
| 2312 | int32_t gemmlowp_shift{ 0 }; /**< GEMMLowp output stage shift used for quantizing to uint8 */ |
| 2313 | int32_t gemmlowp_min_bound{ std::numeric_limits<int32_t>::lowest() }; /**< GEMMLowp min value used to saturate down the output result before converting back to QASYMM8 */ |
| 2314 | int32_t gemmlowp_max_bound{ std::numeric_limits<int32_t>::max() }; /**< GEMMLowp max value used to saturate down the output result before converting back to QASYMM8 */ |
| 2315 | std::vector<int32_t> gemmlowp_multipliers{}; /**< GEMMLowp output stage multiplier used for quantizing to QASYMM8 */ |
| 2316 | std::vector<int32_t> gemmlowp_shifts{}; /**< GEMMLowp output stage multiplier used for quantizing to QASYMM8 */ |
Sheri Zhang | 1b14c75 | 2020-03-09 14:29:52 +0000 | [diff] [blame] | 2317 | float gemmlowp_real_multiplier{ 0 }; /**< GEMMLowp output stage real multiplier used for quantizing to QASYMM8 */ |
Giorgio Arena | 1856ff7 | 2020-02-07 13:46:45 +0000 | [diff] [blame] | 2318 | bool is_quantized_per_channel{ false }; /**< GEMMLowp quantized per-channel flag */ |
| 2319 | DataType output_data_type{ DataType::UNKNOWN }; /**< Output tensor data type to use if the output is not initialized */ |
Gian Marco Iodice | 4b90865 | 2018-10-18 10:21:02 +0100 | [diff] [blame] | 2320 | }; |
| 2321 | |
Gian Marco Iodice | 5ba5e09 | 2018-12-06 17:13:09 +0000 | [diff] [blame] | 2322 | /** GEMM LHS (Left Hand Side) matrix information */ |
| 2323 | struct GEMMLHSMatrixInfo |
| 2324 | { |
morgolock | aba2f91 | 2020-05-05 16:28:19 +0100 | [diff] [blame] | 2325 | GEMMLHSMatrixInfo() = default; |
| 2326 | GEMMLHSMatrixInfo(unsigned int m, unsigned int k, unsigned int v, bool trans, bool inter) |
| 2327 | : m0(m), k0(k), v0(v), transpose(trans), interleave(inter) |
| 2328 | { |
| 2329 | } |
Gian Marco Iodice | 5ba5e09 | 2018-12-06 17:13:09 +0000 | [diff] [blame] | 2330 | unsigned int m0{ 1 }; /**< Number of rows processed by the matrix multiplication */ |
| 2331 | unsigned int k0{ 1 }; /**< Number of partial accumulations performed by the matrix multiplication */ |
| 2332 | unsigned int v0{ 1 }; /**< Number of vertical blocks of size (m0xk0) stored on the same output row */ |
| 2333 | bool transpose{ true }; /**< True if the (m0xk0) block has to be transposed before been stored */ |
| 2334 | bool interleave{ true }; /**< True if the v0 (m0xk0) blocks have to be interleaved in the output row */ |
| 2335 | }; |
| 2336 | |
Gian Marco Iodice | 3b0a265 | 2018-12-07 11:18:09 +0000 | [diff] [blame] | 2337 | /** GEMM RHS (Right Hand Side) matrix information */ |
| 2338 | struct GEMMRHSMatrixInfo |
| 2339 | { |
morgolock | aba2f91 | 2020-05-05 16:28:19 +0100 | [diff] [blame] | 2340 | GEMMRHSMatrixInfo() = default; |
Gian Marco Iodice | e3a849a | 2020-06-10 17:59:30 +0100 | [diff] [blame] | 2341 | GEMMRHSMatrixInfo(unsigned int n, unsigned int k, unsigned int h, bool trans, bool inter, bool export_to_cl_img) |
| 2342 | : n0(n), k0(k), h0(h), transpose(trans), interleave(inter), export_to_cl_image(export_to_cl_img) |
morgolock | aba2f91 | 2020-05-05 16:28:19 +0100 | [diff] [blame] | 2343 | { |
| 2344 | } |
Gian Marco Iodice | dd717c3 | 2020-05-28 10:22:03 +0100 | [diff] [blame] | 2345 | unsigned int n0{ 1 }; /**< Number of columns processed by the matrix multiplication */ |
| 2346 | unsigned int k0{ 1 }; /**< Number of partial accumulations performed by the matrix multiplication */ |
| 2347 | unsigned int h0{ 1 }; /**< Number of horizontal blocks of size (k0xn0) stored on the same output row */ |
| 2348 | bool transpose{ true }; /**< True if the (k0xn0) block has to be transposed before been stored */ |
| 2349 | bool interleave{ true }; /**< True if the h0 (k0xn0) blocks have to be interleaved in the output row */ |
| 2350 | bool export_to_cl_image{ false }; /**< True if the reshaped rhs has to be exported to cl_image. n0 must be equal to 4 */ |
Gian Marco Iodice | 3b0a265 | 2018-12-07 11:18:09 +0000 | [diff] [blame] | 2351 | }; |
| 2352 | |
SiCongLi | 579ca84 | 2021-10-18 09:38:33 +0100 | [diff] [blame] | 2353 | class ITensorInfo; |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2354 | /** GEMM information class. This class stores the necessary information to compute GEMM functions |
| 2355 | * |
| 2356 | * This object also contains the information about how matrix A and matrix B have been reshaped |
| 2357 | * |
| 2358 | */ |
Chunosov | 5124be5 | 2017-11-22 20:42:13 +0700 | [diff] [blame] | 2359 | class GEMMInfo |
| 2360 | { |
| 2361 | public: |
| 2362 | /** Default constructor */ |
Georgios Pinitas | 37d080f | 2019-06-21 18:43:12 +0100 | [diff] [blame] | 2363 | GEMMInfo() noexcept |
| 2364 | : _is_a_reshaped(false), |
| 2365 | _is_b_reshaped(false), |
| 2366 | _reshape_b_only_on_first_run(true), |
| 2367 | _depth_output_gemm3d(0), |
| 2368 | _reinterpret_input_as_3d(false), |
| 2369 | _retain_internal_weights(false), |
| 2370 | _gemmlowp_output_stage(), |
Georgios Pinitas | 4ee8b15 | 2021-07-16 16:16:43 +0100 | [diff] [blame] | 2371 | _fast_math(false), |
Georgios Pinitas | 37d080f | 2019-06-21 18:43:12 +0100 | [diff] [blame] | 2372 | _fp_mixed_precision(false), |
| 2373 | _broadcast_bias(false), |
Adnan AlSinan | c584958 | 2022-05-05 11:13:19 +0100 | [diff] [blame] | 2374 | _pretranspose_A(false), |
| 2375 | _pretranspose_B(false), |
SiCongLi | 579ca84 | 2021-10-18 09:38:33 +0100 | [diff] [blame] | 2376 | _activation_info(), |
Francesco.Petrogalli@arm.com | 5fcf22d | 2022-04-05 10:31:08 +0000 | [diff] [blame] | 2377 | _post_ops(), |
Francesco Petrogalli | 553f695 | 2022-06-30 10:22:01 +0000 | [diff] [blame] | 2378 | _fixed_format(false), |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2379 | _weight_format(arm_compute::WeightFormat::UNSPECIFIED) |
Chunosov | 5124be5 | 2017-11-22 20:42:13 +0700 | [diff] [blame] | 2380 | { |
| 2381 | } |
| 2382 | /** Constructor |
| 2383 | * |
| 2384 | * @param[in] is_a_reshaped True if the matrix A has been reshaped |
| 2385 | * @param[in] is_b_reshaped True if the matrix B has been reshaped |
| 2386 | * @param[in] reshape_b_only_on_first_run Reshape matrix B only for the first run |
Isabella Gottardi | 8e74f44 | 2018-03-01 16:42:00 +0000 | [diff] [blame] | 2387 | * @param[in] depth_output_gemm3d (Optional) Depth (third dimension) of the output tensor to be used with the GEMM3D kernel |
Gian Marco Iodice | 3139f03 | 2018-11-05 14:26:32 +0000 | [diff] [blame] | 2388 | * If 0 the output will not be reinterpreted as 3D. Default 0 |
Gian Marco Iodice | 68a3f56 | 2018-07-26 11:44:03 +0100 | [diff] [blame] | 2389 | * @param[in] reinterpret_input_as_3d (Optional) Reinterpret the input as 3D tensor. (i.e. this flag should be set to true when GEMM is used |
| 2390 | * to perform 1x1 convolutions with the NHWC data layout) |
Michele Di Giorgio | ba1ffe9 | 2018-08-22 14:28:30 +0100 | [diff] [blame] | 2391 | * @param[in] retain_internal_weights (Optional) Retain the weights tensor from previous run |
Gian Marco Iodice | 4b90865 | 2018-10-18 10:21:02 +0100 | [diff] [blame] | 2392 | * @param[in] gemmlowp_output_stage (Optional) GEMMLowp Output stage info |
Vidhya Sudhan Loganathan | a25d16c | 2018-11-16 11:33:12 +0000 | [diff] [blame] | 2393 | * @param[in] fp_mixed_precision (Optional) Use wider accumulators (32 bit instead of 16 for FP16) to improve accuracy. |
Georgios Pinitas | 4ee8b15 | 2021-07-16 16:16:43 +0100 | [diff] [blame] | 2394 | * @param[in] fast_math (Optional) Use a data type of shorter width to improve performance |
Georgios Pinitas | b0f342e | 2019-05-21 13:32:43 +0100 | [diff] [blame] | 2395 | * @param[in] broadcast_bias (Optional) Broadcast the shape of the bias tensor from a vector to a matrix. |
Gian Marco Iodice | f3622be | 2019-07-29 14:27:16 +0100 | [diff] [blame] | 2396 | * @param[in] activation_info (Optional) Activation to apply after the matrix multiplication |
SiCongLi | 579ca84 | 2021-10-18 09:38:33 +0100 | [diff] [blame] | 2397 | * @param[in] post_ops (Optional) A sequence of post operations that are performed after the main operation. |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2398 | * @param[in] fixed_format (Optional) Specify the selection of fixed format kernels for variable weights support in GEMM. These kernels expect the weights tensor to be in amemory format that is fixed by the kernel itself. For more information, see arm_compute::WeightFormat. |
| 2399 | * @param[in] weight_format (Optional) arm_gemm:WeightFormat enumeration requested by the user. Default is arm_compute::WeightFormat::UNSPECIFIED. |
Chunosov | 5124be5 | 2017-11-22 20:42:13 +0700 | [diff] [blame] | 2400 | */ |
Gian Marco Iodice | 3139f03 | 2018-11-05 14:26:32 +0000 | [diff] [blame] | 2401 | GEMMInfo(bool is_a_reshaped, bool is_b_reshaped, bool reshape_b_only_on_first_run, int depth_output_gemm3d = 0, bool reinterpret_input_as_3d = false, bool retain_internal_weights = false, |
Georgios Pinitas | 4ee8b15 | 2021-07-16 16:16:43 +0100 | [diff] [blame] | 2402 | GEMMLowpOutputStageInfo gemmlowp_output_stage = GEMMLowpOutputStageInfo(), bool fp_mixed_precision = false, bool fast_math = false, bool broadcast_bias = false, |
Francesco.Petrogalli@arm.com | 5fcf22d | 2022-04-05 10:31:08 +0000 | [diff] [blame] | 2403 | const ActivationLayerInfo &activation_info = ActivationLayerInfo(), const experimental::PostOpList<ITensorInfo *> &post_ops = experimental::PostOpList<ITensorInfo *>(), |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2404 | bool fixed_format = false, arm_compute::WeightFormat weight_format = arm_compute::WeightFormat::UNSPECIFIED) noexcept |
Georgios Pinitas | 37d080f | 2019-06-21 18:43:12 +0100 | [diff] [blame] | 2405 | : _is_a_reshaped(is_a_reshaped), |
| 2406 | _is_b_reshaped(is_b_reshaped), |
| 2407 | _reshape_b_only_on_first_run(reshape_b_only_on_first_run), |
| 2408 | _depth_output_gemm3d(depth_output_gemm3d), |
| 2409 | _reinterpret_input_as_3d(reinterpret_input_as_3d), |
| 2410 | _retain_internal_weights(retain_internal_weights), |
| 2411 | _gemmlowp_output_stage(gemmlowp_output_stage), |
Georgios Pinitas | 4ee8b15 | 2021-07-16 16:16:43 +0100 | [diff] [blame] | 2412 | _fast_math(fast_math), |
Georgios Pinitas | 37d080f | 2019-06-21 18:43:12 +0100 | [diff] [blame] | 2413 | _fp_mixed_precision(fp_mixed_precision), |
| 2414 | _broadcast_bias(broadcast_bias), |
Adnan AlSinan | c584958 | 2022-05-05 11:13:19 +0100 | [diff] [blame] | 2415 | _pretranspose_A(false), |
| 2416 | _pretranspose_B(false), |
SiCongLi | 579ca84 | 2021-10-18 09:38:33 +0100 | [diff] [blame] | 2417 | _activation_info(activation_info), |
Francesco.Petrogalli@arm.com | 5fcf22d | 2022-04-05 10:31:08 +0000 | [diff] [blame] | 2418 | _post_ops(post_ops), |
Francesco Petrogalli | 553f695 | 2022-06-30 10:22:01 +0000 | [diff] [blame] | 2419 | _fixed_format(fixed_format), |
| 2420 | _weight_format(weight_format) |
Chunosov | 5124be5 | 2017-11-22 20:42:13 +0700 | [diff] [blame] | 2421 | { |
| 2422 | } |
| 2423 | /** Flag which specifies if the matrix A has been reshaped |
| 2424 | * |
| 2425 | * @return True if the matrix A has been reshaped |
| 2426 | */ |
| 2427 | bool is_a_reshaped() const |
| 2428 | { |
| 2429 | return _is_a_reshaped; |
| 2430 | }; |
| 2431 | /** Flag which specifies if the matrix B has been reshaped |
| 2432 | * |
| 2433 | * @return True if the matrix B has been reshaped |
| 2434 | */ |
| 2435 | bool is_b_reshaped() const |
| 2436 | { |
| 2437 | return _is_b_reshaped; |
| 2438 | }; |
| 2439 | /** Flag which specifies if the reshape of matrix B should executed only for the first |
| 2440 | * |
| 2441 | * @note This flag could be set to TRUE when GEMM is used to accelerate convolution layer |
| 2442 | * |
| 2443 | * @return True if the reshaped of matrix B happens only for the first run |
| 2444 | */ |
| 2445 | bool reshape_b_only_on_first_run() const |
| 2446 | { |
| 2447 | return _reshape_b_only_on_first_run; |
| 2448 | }; |
Isabella Gottardi | 8e74f44 | 2018-03-01 16:42:00 +0000 | [diff] [blame] | 2449 | /** Depth of the output when GEMM output is reinterpreted as 3D tensor |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2450 | * |
Isabella Gottardi | 8e74f44 | 2018-03-01 16:42:00 +0000 | [diff] [blame] | 2451 | * @return the depth of the output tensor |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2452 | */ |
Isabella Gottardi | 8e74f44 | 2018-03-01 16:42:00 +0000 | [diff] [blame] | 2453 | int depth_output_gemm3d() const |
Gian Marco | 36a0a46 | 2018-01-12 10:21:40 +0000 | [diff] [blame] | 2454 | { |
Isabella Gottardi | 8e74f44 | 2018-03-01 16:42:00 +0000 | [diff] [blame] | 2455 | return _depth_output_gemm3d; |
| 2456 | }; |
Gian Marco Iodice | 68a3f56 | 2018-07-26 11:44:03 +0100 | [diff] [blame] | 2457 | /** Flag which specifies if the input tensor has to be reinterpreted as 3D |
| 2458 | * |
| 2459 | * @return True if the input tensor has to be reinterpreted as 3D tensor |
| 2460 | */ |
| 2461 | bool reinterpret_input_as_3d() const |
| 2462 | { |
| 2463 | return _reinterpret_input_as_3d; |
| 2464 | }; |
Michele Di Giorgio | ba1ffe9 | 2018-08-22 14:28:30 +0100 | [diff] [blame] | 2465 | /** Flag which specifies if the weights tensor has to be retained from previous run |
| 2466 | * |
| 2467 | * @return True if the weights tensor has to be retained |
| 2468 | */ |
| 2469 | bool retain_internal_weights() const |
| 2470 | { |
| 2471 | return _retain_internal_weights; |
| 2472 | }; |
Gian Marco Iodice | 4b90865 | 2018-10-18 10:21:02 +0100 | [diff] [blame] | 2473 | /** GEMMLowp output stage |
| 2474 | * |
| 2475 | * @return the GEMMLowp output stage info |
| 2476 | */ |
| 2477 | GEMMLowpOutputStageInfo gemmlowp_output_stage() const |
| 2478 | { |
| 2479 | return _gemmlowp_output_stage; |
| 2480 | }; |
Georgios Pinitas | dbdea0d | 2019-10-16 19:21:40 +0100 | [diff] [blame] | 2481 | /** Sets GEMMLowp output stage |
| 2482 | * |
| 2483 | * @param[in] output_stage Output stage to set |
| 2484 | */ |
| 2485 | void set_gemmlowp_output_stage(GEMMLowpOutputStageInfo &output_stage) |
| 2486 | { |
| 2487 | _gemmlowp_output_stage = output_stage; |
| 2488 | }; |
Vidhya Sudhan Loganathan | a25d16c | 2018-11-16 11:33:12 +0000 | [diff] [blame] | 2489 | /** Flag which specifies if a wider accumulator should be used. |
| 2490 | * |
| 2491 | * @return True if a wider accumulator has to be used |
| 2492 | */ |
| 2493 | bool fp_mixed_precision() const |
| 2494 | { |
| 2495 | return _fp_mixed_precision; |
| 2496 | }; |
Georgios Pinitas | 4ee8b15 | 2021-07-16 16:16:43 +0100 | [diff] [blame] | 2497 | /** Flag which specifies if a shorter accumulator to be used. |
| 2498 | * |
| 2499 | * @return True if a shorter accumulator has to be used |
| 2500 | */ |
| 2501 | bool fast_math() const |
| 2502 | { |
| 2503 | return _fast_math; |
| 2504 | }; |
cfRod | f2c022e | 2021-11-05 11:29:53 +0000 | [diff] [blame] | 2505 | /** Set fast math flag |
| 2506 | * |
| 2507 | * @param[in] fast_math Flag to set |
| 2508 | */ |
| 2509 | void set_fast_math(bool fast_math) |
| 2510 | { |
| 2511 | _fast_math = fast_math; |
| 2512 | } |
Georgios Pinitas | b0f342e | 2019-05-21 13:32:43 +0100 | [diff] [blame] | 2513 | /** Flag which specifies whether to broadcast the shape of the bias tensor. |
| 2514 | * |
| 2515 | * @return True if the shape of the bias tensor is to be broadcasted. |
| 2516 | */ |
| 2517 | bool broadcast_bias() const |
| 2518 | { |
| 2519 | return _broadcast_bias; |
| 2520 | }; |
Adnan AlSinan | c584958 | 2022-05-05 11:13:19 +0100 | [diff] [blame] | 2521 | /** Flag which specifies whether A should be pre-transposed if supported. |
| 2522 | * |
| 2523 | * @return True if A should be pre-transposed else false. |
| 2524 | */ |
| 2525 | bool pretranspose_A() const |
| 2526 | { |
| 2527 | return _pretranspose_A; |
| 2528 | }; |
| 2529 | /** Set pre-transpose A flag |
| 2530 | * |
| 2531 | * @param[in] flag Flag to set |
| 2532 | */ |
| 2533 | void set_pretranspose_A(bool flag) |
| 2534 | { |
| 2535 | _pretranspose_A = flag; |
| 2536 | } |
Georgios Pinitas | 37d080f | 2019-06-21 18:43:12 +0100 | [diff] [blame] | 2537 | /** Flag which specifies whether b should be pre-transposed if supported. |
| 2538 | * |
| 2539 | * @return True if b should be pre-transposed else false. |
| 2540 | */ |
ramelg01 | cbbb038 | 2021-09-17 17:36:57 +0100 | [diff] [blame] | 2541 | bool pretranspose_B() const |
Georgios Pinitas | 37d080f | 2019-06-21 18:43:12 +0100 | [diff] [blame] | 2542 | { |
ramelg01 | cbbb038 | 2021-09-17 17:36:57 +0100 | [diff] [blame] | 2543 | return _pretranspose_B; |
Georgios Pinitas | 37d080f | 2019-06-21 18:43:12 +0100 | [diff] [blame] | 2544 | }; |
| 2545 | /** Set pre-transpose b flag |
| 2546 | * |
| 2547 | * @param[in] flag Flag to set |
| 2548 | */ |
ramelg01 | cbbb038 | 2021-09-17 17:36:57 +0100 | [diff] [blame] | 2549 | void set_pretranspose_B(bool flag) |
Georgios Pinitas | 37d080f | 2019-06-21 18:43:12 +0100 | [diff] [blame] | 2550 | { |
ramelg01 | cbbb038 | 2021-09-17 17:36:57 +0100 | [diff] [blame] | 2551 | _pretranspose_B = flag; |
Georgios Pinitas | 37d080f | 2019-06-21 18:43:12 +0100 | [diff] [blame] | 2552 | } |
Gian Marco Iodice | f3622be | 2019-07-29 14:27:16 +0100 | [diff] [blame] | 2553 | /** Activation layer to apply after the matrix multiplication |
| 2554 | * |
| 2555 | * @return ActivationLayerInfo object |
| 2556 | */ |
| 2557 | ActivationLayerInfo activation_info() const |
| 2558 | { |
| 2559 | return _activation_info; |
| 2560 | } |
SiCongLi | 2e5fd63 | 2020-03-02 15:39:15 +0000 | [diff] [blame] | 2561 | /** Set activation layer info |
| 2562 | * |
| 2563 | * @param[in] activation_info ActivationLayerInfo object to set |
| 2564 | */ |
| 2565 | void set_activation_info(const ActivationLayerInfo &activation_info) |
| 2566 | { |
| 2567 | _activation_info = activation_info; |
| 2568 | } |
SiCongLi | 579ca84 | 2021-10-18 09:38:33 +0100 | [diff] [blame] | 2569 | /** Post operations to apply after the matrix multiplication |
| 2570 | * |
| 2571 | * @return experimental::PostOpList object |
| 2572 | */ |
| 2573 | const experimental::PostOpList<ITensorInfo *> &post_ops() const |
| 2574 | { |
| 2575 | return _post_ops; |
| 2576 | } |
| 2577 | /** Set post ops |
| 2578 | * |
| 2579 | * @param[in] post_ops experimental::PostOpList object to set |
| 2580 | */ |
| 2581 | void set_post_ops(const experimental::PostOpList<ITensorInfo *> &post_ops) |
| 2582 | { |
| 2583 | _post_ops = post_ops; |
| 2584 | } |
Francesco.Petrogalli@arm.com | 5fcf22d | 2022-04-05 10:31:08 +0000 | [diff] [blame] | 2585 | /** Flag which specifies if the GEMM operation is running fixed-format kernels. |
| 2586 | * |
| 2587 | * @return True if the GEMM operation is running fixed-format kernel else false. |
| 2588 | */ |
| 2589 | bool fixed_format() const |
| 2590 | { |
| 2591 | return _fixed_format; |
| 2592 | } |
Chunosov | 5124be5 | 2017-11-22 20:42:13 +0700 | [diff] [blame] | 2593 | |
Milos Puzovic | 13b623e | 2022-07-27 17:53:21 +0000 | [diff] [blame] | 2594 | /** Set fixed-format flag |
| 2595 | * |
| 2596 | * @param[in] fixed_format sets whether or not to use fixed-format kernels |
| 2597 | */ |
| 2598 | void set_fixed_format(bool fixed_format) |
| 2599 | { |
| 2600 | _fixed_format = fixed_format; |
| 2601 | } |
| 2602 | |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2603 | arm_compute::WeightFormat weight_format() const |
Francesco Petrogalli | 553f695 | 2022-06-30 10:22:01 +0000 | [diff] [blame] | 2604 | { |
| 2605 | return _weight_format; |
| 2606 | } |
| 2607 | |
Milos Puzovic | 13b623e | 2022-07-27 17:53:21 +0000 | [diff] [blame] | 2608 | /** Set weight format to be used |
| 2609 | * |
| 2610 | * @param[in] weight_format arm_compute::WeightFormat enumeration |
| 2611 | */ |
| 2612 | void set_weight_format(arm_compute::WeightFormat weight_format) |
| 2613 | { |
| 2614 | _weight_format = weight_format; |
| 2615 | } |
| 2616 | |
Chunosov | 5124be5 | 2017-11-22 20:42:13 +0700 | [diff] [blame] | 2617 | private: |
SiCongLi | 579ca84 | 2021-10-18 09:38:33 +0100 | [diff] [blame] | 2618 | bool _is_a_reshaped; |
| 2619 | bool _is_b_reshaped; |
| 2620 | bool _reshape_b_only_on_first_run; |
| 2621 | int _depth_output_gemm3d; |
| 2622 | bool _reinterpret_input_as_3d; |
| 2623 | bool _retain_internal_weights; |
| 2624 | GEMMLowpOutputStageInfo _gemmlowp_output_stage; |
| 2625 | bool _fast_math; |
| 2626 | bool _fp_mixed_precision; |
| 2627 | bool _broadcast_bias; |
Adnan AlSinan | c584958 | 2022-05-05 11:13:19 +0100 | [diff] [blame] | 2628 | bool _pretranspose_A; |
SiCongLi | 579ca84 | 2021-10-18 09:38:33 +0100 | [diff] [blame] | 2629 | bool _pretranspose_B; |
| 2630 | ActivationLayerInfo _activation_info; |
| 2631 | experimental::PostOpList<ITensorInfo *> _post_ops; |
Francesco.Petrogalli@arm.com | 5fcf22d | 2022-04-05 10:31:08 +0000 | [diff] [blame] | 2632 | bool _fixed_format; |
Ramy Elgammal | 9178002 | 2022-07-20 14:57:37 +0100 | [diff] [blame] | 2633 | arm_compute::WeightFormat _weight_format; |
Chunosov | 5124be5 | 2017-11-22 20:42:13 +0700 | [diff] [blame] | 2634 | }; |
| 2635 | |
Gian Marco Iodice | 247f52c | 2018-03-22 11:24:56 +0000 | [diff] [blame] | 2636 | /** Winograd information */ |
| 2637 | struct WinogradInfo |
| 2638 | { |
| 2639 | /** Default constructor |
| 2640 | * |
| 2641 | * @param[in] output_tile_sz Width and height of the output tile |
| 2642 | * @param[in] kernel_sz Width and height of the kernel |
| 2643 | * @param[in] input_dims Width and height of the input tensor before the convolution is applied |
| 2644 | * @param[in] conv_info Convolution info (Pads, strides) |
| 2645 | * @param[in] data_layout Data layout to use for the output tensor once the convolution has been applied |
| 2646 | */ |
| 2647 | WinogradInfo(Size2D output_tile_sz, Size2D kernel_sz, Size2D input_dims, PadStrideInfo conv_info, DataLayout data_layout) |
| 2648 | : output_tile_size(output_tile_sz), kernel_size(kernel_sz), input_dimensions(input_dims), convolution_info(conv_info), output_data_layout(data_layout) |
| 2649 | { |
| 2650 | } |
| 2651 | |
| 2652 | Size2D output_tile_size{}; /**< Width and height of the output tile */ |
| 2653 | Size2D kernel_size{}; /**< Width and height of the kernel*/ |
| 2654 | Size2D input_dimensions{}; /**< Width and height of the input tensor before the convolution is applied */ |
| 2655 | PadStrideInfo convolution_info{}; /**< Convolution info (Pads, strides,...) */ |
| 2656 | DataLayout output_data_layout{ DataLayout::NCHW }; /**< Data layout to use for the output tensor once the convolution has been applied (NCHW or NHWC) */ |
| 2657 | }; |
| 2658 | |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2659 | /** IO formatting information class*/ |
| 2660 | struct IOFormatInfo |
| 2661 | { |
| 2662 | /** Precision type used when printing floating point numbers */ |
| 2663 | enum class PrecisionType |
| 2664 | { |
| 2665 | Default, /**< Default precision to the one that the current stream has */ |
| 2666 | Custom, /**< Custom precision specified by the user using the precision parameter */ |
| 2667 | Full /**< The maximum precision of the floating point representation */ |
| 2668 | }; |
| 2669 | |
| 2670 | /** Specifies the area to be printed, used by Tensor objects */ |
| 2671 | enum class PrintRegion |
| 2672 | { |
| 2673 | ValidRegion, /**< Prints the valid region of the Tensor object */ |
| 2674 | NoPadding, /**< Prints the Tensor object without the padding */ |
| 2675 | Full /**< Print the tensor object including padding */ |
| 2676 | }; |
| 2677 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 2678 | /** Construct a set of IO formatting information. |
| 2679 | * |
| 2680 | * @param[in] print_region Area to be printed. Used by Tensor objects. Default: ValidRegion. |
| 2681 | * @param[in] precision_type Precision type for floating point numbers. Default: stream default. |
| 2682 | * @param[in] precision Precision value for float point numbers. Default: 10. |
| 2683 | * @param[in] align_columns Whether to align columns when printed. Default: true. |
| 2684 | * @param[in] element_delim Delimeter between elements. Default: " ". |
| 2685 | * @param[in] row_delim Delimenter between rows. Default: "\n". |
| 2686 | */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2687 | IOFormatInfo(PrintRegion print_region = PrintRegion::ValidRegion, |
| 2688 | PrecisionType precision_type = PrecisionType::Default, |
| 2689 | unsigned int precision = 10, |
| 2690 | bool align_columns = true, |
| 2691 | std::string element_delim = " ", |
| 2692 | std::string row_delim = "\n") |
| 2693 | : print_region(print_region), |
| 2694 | precision_type(precision_type), |
| 2695 | precision(precision), |
| 2696 | element_delim(element_delim), |
| 2697 | row_delim(row_delim), |
| 2698 | align_columns(align_columns) |
| 2699 | { |
| 2700 | } |
| 2701 | |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 2702 | /** Area to be printed by Tensor objects */ |
| 2703 | PrintRegion print_region; |
| 2704 | /** Floating point precision type */ |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2705 | PrecisionType precision_type; |
Alex Gilday | c357c47 | 2018-03-21 13:54:09 +0000 | [diff] [blame] | 2706 | /** Floating point precision */ |
| 2707 | unsigned int precision; |
| 2708 | /** Element delimeter */ |
| 2709 | std::string element_delim; |
| 2710 | /** Row delimeter */ |
| 2711 | std::string row_delim; |
| 2712 | /** Align columns */ |
| 2713 | bool align_columns; |
Anthony Barbier | 6ff3b19 | 2017-09-04 18:44:23 +0100 | [diff] [blame] | 2714 | }; |
Mohammed Suhail Munshi | d538d16 | 2023-02-16 16:22:32 +0000 | [diff] [blame] | 2715 | |
| 2716 | /** Class for holding information related to matrix multiplication function |
| 2717 | */ |
| 2718 | class MatMulInfo |
| 2719 | { |
| 2720 | public: |
| 2721 | /* Get Adjoint LHS flag value */ |
| 2722 | bool adj_lhs() const |
| 2723 | { |
| 2724 | return _adj_lhs; |
| 2725 | } |
| 2726 | /* Get Adjoint RHS flag value */ |
| 2727 | bool adj_rhs() const |
| 2728 | { |
| 2729 | return _adj_rhs; |
| 2730 | } |
| 2731 | /* Get Fused Activation Layer Info */ |
| 2732 | ActivationLayerInfo fused_activation() const |
| 2733 | { |
| 2734 | return _fused_act; |
| 2735 | } |
| 2736 | /* Set Adjoint LHS flag */ |
| 2737 | MatMulInfo& adj_lhs(bool adj_lhs) |
| 2738 | { |
| 2739 | _adj_lhs = adj_lhs; |
| 2740 | return *this; |
| 2741 | } |
| 2742 | /* Set Adjoint RHS flag */ |
| 2743 | MatMulInfo& adj_rhs(bool adj_rhs) |
| 2744 | { |
| 2745 | _adj_rhs = adj_rhs; |
| 2746 | return *this; |
| 2747 | } |
| 2748 | /* Set Fused Activation Layer Info */ |
| 2749 | MatMulInfo& fused_activation(const ActivationLayerInfo& act_info) |
| 2750 | { |
| 2751 | _fused_act = act_info; |
| 2752 | return *this; |
| 2753 | } |
| 2754 | private: |
| 2755 | bool _adj_lhs{false}; |
| 2756 | bool _adj_rhs{false}; |
| 2757 | ActivationLayerInfo _fused_act{}; // disabled by default |
| 2758 | }; |
Georgios Pinitas | d8734b5 | 2017-12-22 15:27:52 +0000 | [diff] [blame] | 2759 | } // namespace arm_compute |
Michalis Spyrou | f464337 | 2019-11-29 16:17:13 +0000 | [diff] [blame] | 2760 | #endif /* ARM_COMPUTE_TYPES_H */ |