blob: de475ab68fe1fdbc3c98828a4f6e508652154415 [file] [log] [blame]
Laurent Carlier749294b2020-06-01 09:03:17 +01001//
telsoa014fcda012018-03-09 14:13:49 +00002// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5#pragma once
6
7#include <array>
Matthew Bentham47bfac42019-03-25 12:30:56 +00008#include <functional>
David Beckdcb751f2018-10-03 11:42:42 +01009#include <memory>
janeil01c4946c72019-11-07 09:32:28 +000010#include <stdint.h>
Keith Davise813d672021-04-22 10:10:34 +010011#include <chrono>
Jim Flynn44db7c32019-03-22 15:58:39 +000012#include "BackendId.hpp"
13#include "Exceptions.hpp"
Derek Lambertif90c56d2020-01-10 17:14:08 +000014#include "Deprecated.hpp"
telsoa014fcda012018-03-09 14:13:49 +000015
16namespace armnn
17{
18
Matthew Jacksondba634f2019-08-15 15:14:18 +010019constexpr unsigned int MaxNumOfTensorDimensions = 5U;
telsoa014fcda012018-03-09 14:13:49 +000020
Ryan OShea2bbfaa72020-02-12 16:15:27 +000021/// The lowest performance data capture interval we support is 10 miliseconds.
Colm Donelan02705242019-11-14 14:19:07 +000022constexpr unsigned int LOWEST_CAPTURE_PERIOD = 10000u;
23
Keith Davise813d672021-04-22 10:10:34 +010024/// Variable to control expire rate of priority queue
25constexpr unsigned int EXPIRE_RATE = 3U;
26
telsoa014fcda012018-03-09 14:13:49 +000027/// @enum Status enumeration
28/// @var Status::Successful
29/// @var Status::Failure
30enum class Status
31{
32 Success = 0,
33 Failure = 1
34};
35
36enum class DataType
37{
Keith Davise813d672021-04-22 10:10:34 +010038 Float16 = 0,
39 Float32 = 1,
Derek Lambertif90c56d2020-01-10 17:14:08 +000040 QAsymmU8 = 2,
ruoyan0120e984f2018-12-12 18:11:25 +000041 Signed32 = 3,
Keith Davise813d672021-04-22 10:10:34 +010042 Boolean = 4,
Derek Lambertif90c56d2020-01-10 17:14:08 +000043 QSymmS16 = 5,
Derek Lambertid466a542020-01-22 15:37:29 +000044 QuantizedSymm8PerAxis ARMNN_DEPRECATED_ENUM_MSG("Per Axis property inferred by number of scales in TensorInfo") = 6,
Keith Davise813d672021-04-22 10:10:34 +010045 QSymmS8 = 7,
Ryan OShea9add1202020-02-07 10:06:33 +000046 QAsymmS8 = 8,
Narumol Prangnawaratc3bf6ef2020-02-28 12:45:21 +000047 BFloat16 = 9,
Inki Daed4619e22020-09-10 15:33:54 +090048 Signed64 = 10,
Derek Lambertif90c56d2020-01-10 17:14:08 +000049
Derek Lamberti41e92b02020-01-21 13:43:21 +000050 QuantisedAsymm8 ARMNN_DEPRECATED_ENUM_MSG("Use DataType::QAsymmU8 instead.") = QAsymmU8,
51 QuantisedSymm16 ARMNN_DEPRECATED_ENUM_MSG("Use DataType::QSymmS16 instead.") = QSymmS16
telsoa014fcda012018-03-09 14:13:49 +000052};
53
Derek Lamberti0cff1632018-09-18 16:02:25 +010054enum class DataLayout
55{
56 NCHW = 1,
57 NHWC = 2
58};
59
Keith Davise813d672021-04-22 10:10:34 +010060enum class QosExecPriority
61{
62 Low = 0,
63 Medium = 1,
64 High = 2
65};
66
telsoa014fcda012018-03-09 14:13:49 +000067enum class ActivationFunction
68{
69 Sigmoid = 0,
70 TanH = 1,
71 Linear = 2,
72 ReLu = 3,
Colm Donelan03fbeaf2020-02-26 15:39:23 +000073 BoundedReLu = 4, ///< min(a, max(b, input)) ReLu1 & ReLu6.
telsoa014fcda012018-03-09 14:13:49 +000074 SoftReLu = 5,
75 LeakyReLu = 6,
76 Abs = 7,
77 Sqrt = 8,
David Monahan3b3c3812020-02-25 09:03:29 +000078 Square = 9,
Colm Donelan03fbeaf2020-02-26 15:39:23 +000079 Elu = 10,
80 HardSwish = 11
telsoa014fcda012018-03-09 14:13:49 +000081};
82
Narumol Prangnawarat8d001d42019-09-09 15:01:18 +010083enum class ArgMinMaxFunction
84{
85 Min = 0,
86 Max = 1
87};
88
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +010089enum class ComparisonOperation
90{
91 Equal = 0,
92 Greater = 1,
93 GreaterOrEqual = 2,
94 Less = 3,
95 LessOrEqual = 4,
96 NotEqual = 5
97};
98
James Conroyaba90cd2020-11-06 16:28:18 +000099enum class LogicalBinaryOperation
100{
101 LogicalAnd = 0,
102 LogicalOr = 1
103};
104
josh minor4a3c6102020-01-06 16:40:46 -0600105enum class UnaryOperation
106{
James Conroyaba90cd2020-11-06 16:28:18 +0000107 Abs = 0,
108 Exp = 1,
109 Sqrt = 2,
110 Rsqrt = 3,
111 Neg = 4,
112 LogicalNot = 5
josh minor4a3c6102020-01-06 16:40:46 -0600113};
114
telsoa014fcda012018-03-09 14:13:49 +0000115enum class PoolingAlgorithm
116{
117 Max = 0,
118 Average = 1,
119 L2 = 2
120};
121
Sadik Armagan0c3ea5b2021-02-03 09:29:30 +0000122enum class ReduceOperation
123{
124 Sum = 0,
125 Max = 1,
126 Mean = 2,
127 Min = 3
128};
129
Teresa Charlina9075df2019-06-27 15:41:57 +0100130enum class ResizeMethod
131{
132 Bilinear = 0,
133 NearestNeighbor = 1
134};
135
Teresa Charlin11f6ace2020-06-23 18:30:57 +0100136enum class Dimensionality
137{
138 NotSpecified = 0,
139 Specified = 1,
140 Scalar = 2
141};
142
telsoa014fcda012018-03-09 14:13:49 +0000143///
144/// The padding method modifies the output of pooling layers.
145/// In both supported methods, the values are ignored (they are
telsoa01c577f2c2018-08-31 09:22:23 +0100146/// not even zeroes, which would make a difference for max pooling
telsoa014fcda012018-03-09 14:13:49 +0000147/// a tensor with negative values). The difference between
telsoa01c577f2c2018-08-31 09:22:23 +0100148/// IgnoreValue and Exclude is that the former counts the padding
telsoa014fcda012018-03-09 14:13:49 +0000149/// fields in the divisor of Average and L2 pooling, while
150/// Exclude does not.
151///
152enum class PaddingMethod
153{
telsoa01c577f2c2018-08-31 09:22:23 +0100154 /// The padding fields count, but are ignored
David Beckdcb751f2018-10-03 11:42:42 +0100155 IgnoreValue = 0,
telsoa01c577f2c2018-08-31 09:22:23 +0100156 /// The padding fields don't count and are ignored
David Beckdcb751f2018-10-03 11:42:42 +0100157 Exclude = 1
telsoa014fcda012018-03-09 14:13:49 +0000158};
159
160enum class NormalizationAlgorithmChannel
161{
162 Across = 0,
163 Within = 1
164};
165
166enum class NormalizationAlgorithmMethod
167{
David Beckdcb751f2018-10-03 11:42:42 +0100168 /// Krichevsky 2012: Local Brightness Normalization
169 LocalBrightness = 0,
170 /// Jarret 2009: Local Contrast Normalization
telsoa01c577f2c2018-08-31 09:22:23 +0100171 LocalContrast = 1
telsoa014fcda012018-03-09 14:13:49 +0000172};
173
174enum class OutputShapeRounding
175{
176 Floor = 0,
177 Ceiling = 1
178};
179
Teresa Charlincdc01492020-06-09 18:00:20 +0100180///
181/// The ShapeInferenceMethod modify how the output shapes are treated.
182/// When ValidateOnly is selected, the output shapes are inferred from the input parameters of the layer
183/// and any mismatch is reported.
184/// When InferAndValidate is selected 2 actions must be performed: (1)infer output shape from inputs and (2)validate the
185/// shapes as in ValidateOnly. This option has been added to work with tensors which rank or dimension sizes are not
186/// specified explicitly, however this information can be calculated from the inputs.
187///
188enum class ShapeInferenceMethod
189{
190 /// Validate all output shapes
191 ValidateOnly = 0,
192 /// Infer missing output shapes and validate all output shapes
193 InferAndValidate = 1
194};
195
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100196/// Define the Memory Source to reduce copies
197enum class MemorySource : uint32_t
198{
199 Undefined = 0,
200 Malloc = 1,
201 DmaBuf = 2,
202 DmaBufProtected = 4
203};
204
David Beck9efb57d2018-11-05 13:40:33 +0000205/// Each backend should implement an IBackend.
206class IBackend
207{
208protected:
209 IBackend() {}
210 virtual ~IBackend() {}
211
212public:
213 virtual const BackendId& GetId() const = 0;
214};
215
216using IBackendSharedPtr = std::shared_ptr<IBackend>;
217using IBackendUniquePtr = std::unique_ptr<IBackend, void(*)(IBackend* backend)>;
218
Sadik Armaganf0a6dec2021-03-25 07:46:55 +0000219/// BackendCapability class
220enum class BackendCapability : uint32_t
221{
222 /// Constant weights can be accessed through the descriptors,
223 /// On the other hand, non-const weights can be accessed through inputs.
224 NonConstWeights,
225
Sadik Armaganaede8ca2021-03-31 16:12:13 +0100226 /// Asynchronous Execution.
227 AsyncExecution,
228
Sadik Armaganf0a6dec2021-03-25 07:46:55 +0000229 // add new enum values here
230};
231
David Beckdcb751f2018-10-03 11:42:42 +0100232/// Device specific knowledge to be passed to the optimizer.
telsoa01c577f2c2018-08-31 09:22:23 +0100233class IDeviceSpec
telsoa014fcda012018-03-09 14:13:49 +0000234{
telsoa01c577f2c2018-08-31 09:22:23 +0100235protected:
Matteo Martincigh9c5d33a2019-02-07 17:52:41 +0000236 IDeviceSpec() {}
237 virtual ~IDeviceSpec() {}
Narumol Prangnawarat87106762019-05-03 15:54:39 +0100238public:
239 virtual const BackendIdSet& GetSupportedBackends() const = 0;
telsoa014fcda012018-03-09 14:13:49 +0000240};
241
242/// Type of identifiers for bindable layers (inputs, outputs).
243using LayerBindingId = int;
244
245class PermutationVector
246{
247public:
248 using ValueType = unsigned int;
249 using SizeType = unsigned int;
250 using ArrayType = std::array<ValueType, MaxNumOfTensorDimensions>;
251 using ConstIterator = typename ArrayType::const_iterator;
252
telsoa01c577f2c2018-08-31 09:22:23 +0100253 /// @param dimMappings - Indicates how to translate tensor elements from a given source into the target destination,
telsoa014fcda012018-03-09 14:13:49 +0000254 /// when source and target potentially have different memory layouts.
255 ///
telsoa01c577f2c2018-08-31 09:22:23 +0100256 /// E.g. For a 4-d tensor laid out in a memory with the format (Batch Element, Height, Width, Channels),
telsoa014fcda012018-03-09 14:13:49 +0000257 /// which is to be passed as an input to ArmNN, each source dimension is mapped to the corresponding
258 /// ArmNN dimension. The Batch dimension remains the same (0 -> 0). The source Height dimension is mapped
259 /// to the location of the ArmNN Height dimension (1 -> 2). Similar arguments are made for the Width and
260 /// Channels (2 -> 3 and 3 -> 1). This will lead to @ref m_DimMappings pointing to the following array:
261 /// [ 0, 2, 3, 1 ].
262 ///
263 /// Note that the mapping should be reversed if considering the case of ArmNN 4-d outputs (Batch Element,
264 /// Channels, Height, Width) being written to a destination with the format mentioned above. We now have
265 /// 0 -> 0, 2 -> 1, 3 -> 2, 1 -> 3, which, when reordered, lead to the following @ref m_DimMappings contents:
266 /// [ 0, 3, 1, 2 ].
267 ///
268 PermutationVector(const ValueType *dimMappings, SizeType numDimMappings);
269
270 PermutationVector(std::initializer_list<ValueType> dimMappings);
271
272 ValueType operator[](SizeType i) const { return m_DimMappings.at(i); }
273
274 SizeType GetSize() const { return m_NumDimMappings; }
275
276 ConstIterator begin() const { return m_DimMappings.begin(); }
Colm Donelan41e764c2021-05-27 16:43:25 +0100277 /**
278 *
279 * @return pointer one past the end of the number of mapping not the length of m_DimMappings.
280 */
281 ConstIterator end() const { return m_DimMappings.begin() + m_NumDimMappings; }
telsoa014fcda012018-03-09 14:13:49 +0000282
283 bool IsEqual(const PermutationVector& other) const
284 {
Matthew Jacksondba634f2019-08-15 15:14:18 +0100285 if (m_NumDimMappings != other.m_NumDimMappings) return false;
286 for (unsigned int i = 0; i < m_NumDimMappings; ++i)
287 {
288 if (m_DimMappings[i] != other.m_DimMappings[i]) return false;
289 }
290 return true;
telsoa014fcda012018-03-09 14:13:49 +0000291 }
292
293 bool IsInverse(const PermutationVector& other) const
294 {
295 bool isInverse = (GetSize() == other.GetSize());
296 for (SizeType i = 0; isInverse && (i < GetSize()); ++i)
297 {
298 isInverse = (m_DimMappings[other.m_DimMappings[i]] == i);
299 }
300 return isInverse;
301 }
302
303private:
304 ArrayType m_DimMappings;
305 /// Number of valid entries in @ref m_DimMappings
306 SizeType m_NumDimMappings;
307};
308
janeil013fec1ea2019-11-07 09:47:20 +0000309namespace profiling { class ProfilingGuid; }
310
telsoa01c577f2c2018-08-31 09:22:23 +0100311/// Define LayerGuid type.
janeil013fec1ea2019-11-07 09:47:20 +0000312using LayerGuid = profiling::ProfilingGuid;
surmeh01bceff2f2018-03-29 16:29:27 +0100313
Nattapat Chaimanowong6e948202019-03-22 14:01:46 +0000314class ITensorHandle;
315
Nattapat Chaimanowong317cae52019-03-28 10:29:12 +0000316/// Define the type of callback for the Debug layer to call
317/// @param guid - guid of layer connected to the input of the Debug layer
318/// @param slotIndex - index of the output slot connected to the input of the Debug layer
319/// @param tensorHandle - TensorHandle for the input tensor to the Debug layer
320using DebugCallbackFunction = std::function<void(LayerGuid guid, unsigned int slotIndex, ITensorHandle* tensorHandle)>;
Nattapat Chaimanowong6e948202019-03-22 14:01:46 +0000321
Keith Davise813d672021-04-22 10:10:34 +0100322/// Define a timer and associated inference ID for recording execution times
323using HighResolutionClock = std::chrono::high_resolution_clock::time_point;
324using InferenceTimingPair = std::pair<HighResolutionClock, HighResolutionClock>;
janeil01c4946c72019-11-07 09:32:28 +0000325
326namespace profiling
327{
328
Narumol Prangnawaratdbdd1b42019-11-15 17:38:44 +0000329static constexpr uint64_t MIN_STATIC_GUID = 1llu << 63;
330
janeil01c4946c72019-11-07 09:32:28 +0000331class ProfilingGuid
332{
333public:
Sadik Armagan3184c902020-03-18 10:57:30 +0000334 ProfilingGuid() : m_Guid(0) {}
335
janeil01c4946c72019-11-07 09:32:28 +0000336 ProfilingGuid(uint64_t guid) : m_Guid(guid) {}
337
338 operator uint64_t() const { return m_Guid; }
339
340 bool operator==(const ProfilingGuid& other) const
341 {
342 return m_Guid == other.m_Guid;
343 }
344
345 bool operator!=(const ProfilingGuid& other) const
346 {
347 return m_Guid != other.m_Guid;
348 }
349
350 bool operator<(const ProfilingGuid& other) const
351 {
352 return m_Guid < other.m_Guid;
353 }
354
355 bool operator<=(const ProfilingGuid& other) const
356 {
357 return m_Guid <= other.m_Guid;
358 }
359
360 bool operator>(const ProfilingGuid& other) const
361 {
362 return m_Guid > other.m_Guid;
363 }
364
365 bool operator>=(const ProfilingGuid& other) const
366 {
367 return m_Guid >= other.m_Guid;
368 }
369
370protected:
371 uint64_t m_Guid;
372};
373
374/// Strongly typed guids to distinguish between those generated at runtime, and those that are statically defined.
375struct ProfilingDynamicGuid : public ProfilingGuid
376{
377 using ProfilingGuid::ProfilingGuid;
378};
379
380struct ProfilingStaticGuid : public ProfilingGuid
381{
382 using ProfilingGuid::ProfilingGuid;
383};
384
385} // namespace profiling
386
Finn Williamsb454c5c2021-02-09 15:56:23 +0000387/// This list uses X macro technique.
388/// See https://en.wikipedia.org/wiki/X_Macro for more info
389#define LIST_OF_LAYER_TYPE \
390 X(Activation) \
391 X(Addition) \
392 X(ArgMinMax) \
393 X(BatchNormalization) \
394 X(BatchToSpaceNd) \
395 X(Comparison) \
396 X(Concat) \
397 X(Constant) \
398 X(ConvertBf16ToFp32) \
399 X(ConvertFp16ToFp32) \
400 X(ConvertFp32ToBf16) \
401 X(ConvertFp32ToFp16) \
402 X(Convolution2d) \
403 X(Debug) \
404 X(DepthToSpace) \
405 X(DepthwiseConvolution2d) \
406 X(Dequantize) \
407 X(DetectionPostProcess) \
408 X(Division) \
409 X(ElementwiseUnary) \
410 X(FakeQuantization) \
411 X(Fill) \
412 X(Floor) \
413 X(FullyConnected) \
414 X(Gather) \
415 X(Input) \
416 X(InstanceNormalization) \
417 X(L2Normalization) \
418 X(LogicalBinary) \
419 X(LogSoftmax) \
420 X(Lstm) \
421 X(QLstm) \
422 X(Map) \
423 X(Maximum) \
424 X(Mean) \
425 X(MemCopy) \
426 X(MemImport) \
427 X(Merge) \
428 X(Minimum) \
429 X(Multiplication) \
430 X(Normalization) \
431 X(Output) \
432 X(Pad) \
433 X(Permute) \
434 X(Pooling2d) \
435 X(PreCompiled) \
436 X(Prelu) \
437 X(Quantize) \
438 X(QuantizedLstm) \
439 X(Reshape) \
440 X(Rank) \
441 X(Resize) \
442 X(Reduce) \
443 X(Slice) \
444 X(Softmax) \
445 X(SpaceToBatchNd) \
446 X(SpaceToDepth) \
447 X(Splitter) \
448 X(Stack) \
449 X(StandIn) \
450 X(StridedSlice) \
451 X(Subtraction) \
452 X(Switch) \
453 X(Transpose) \
454 X(TransposeConvolution2d) \
mathad01b392e982021-04-07 12:07:30 +0100455 X(Unmap) \
456 X(Cast)
Finn Williamsb454c5c2021-02-09 15:56:23 +0000457/// When adding a new layer, adapt also the LastLayer enum value in the
458/// enum class LayerType below
459enum class LayerType
460{
461#define X(name) name,
462 LIST_OF_LAYER_TYPE
463#undef X
464 FirstLayer = Activation,
mathad01b392e982021-04-07 12:07:30 +0100465 LastLayer = Cast
Finn Williamsb454c5c2021-02-09 15:56:23 +0000466};
467
468const char* GetLayerTypeAsCString(LayerType type);
469
David Beck9df2d952018-10-10 15:11:44 +0100470} // namespace armnn
janeil01c4946c72019-11-07 09:32:28 +0000471
472
473namespace std
474{
Ryan OShea2bbfaa72020-02-12 16:15:27 +0000475/// make ProfilingGuid hashable
janeil01c4946c72019-11-07 09:32:28 +0000476template<>
477struct hash<armnn::profiling::ProfilingGuid>
478{
479 std::size_t operator()(armnn::profiling::ProfilingGuid const& guid) const noexcept
480 {
481 return hash<uint64_t>()(uint64_t(guid));
482 }
483};
484
Ryan OShea2bbfaa72020-02-12 16:15:27 +0000485/// make ProfilingDynamicGuid hashable
janeil01c4946c72019-11-07 09:32:28 +0000486template<>
487struct hash<armnn::profiling::ProfilingDynamicGuid>
488{
489 std::size_t operator()(armnn::profiling::ProfilingDynamicGuid const& guid) const noexcept
490 {
491 return hash<uint64_t>()(uint64_t(guid));
492 }
493};
494
Ryan OShea2bbfaa72020-02-12 16:15:27 +0000495/// make ProfilingStaticGuid hashable
janeil01c4946c72019-11-07 09:32:28 +0000496template<>
497struct hash<armnn::profiling::ProfilingStaticGuid>
498{
499 std::size_t operator()(armnn::profiling::ProfilingStaticGuid const& guid) const noexcept
500 {
501 return hash<uint64_t>()(uint64_t(guid));
502 }
503};
janeil013fec1ea2019-11-07 09:47:20 +0000504} // namespace std