ArmNN
 22.02
Decoders.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #pragma once
7 
8 #include "BaseIterator.hpp"
9 
12 
13 #include <armnn/utility/Assert.hpp>
14 
15 namespace armnn
16 {
17 
18 namespace
19 {
20 
21 inline std::unique_ptr<Decoder<float>> MakeSigned32PerAxisDecoder(const TensorInfo& info, const void* data)
22 {
23  return std::make_unique<ScaledInt32PerAxisDecoder>(static_cast<const int32_t*>(data), info);
24 }
25 
26 inline std::unique_ptr<Decoder<float>> MakeSigned32Decoder(const TensorInfo& info, const void* data)
27 {
28  if(info.HasMultipleQuantizationScales())
29  {
30  // NOTE: If we have multiple quantization scales, we create a ScaledInt32PerAxisDecoder.
31  // This will be used to decode per-axis quantized convolution biases.
32  return MakeSigned32PerAxisDecoder(info, data);
33  }
34  else
35  {
36  if (info.GetQuantizationDim().has_value())
37  {
38  // NOTE: Even though we only have a single quantization scale, if the quantization
39  // dimension is set, the tensor has per-axis quantization and we need to create a
40  // ScaledInt32PerAxisDecoder
41  return MakeSigned32PerAxisDecoder(info, data);
42  }
43 
44  const float scale = info.GetQuantizationScale();
45  if (scale == 0.f)
46  {
47  // NOTE:: If no quantization scale is set, we create an Int32Decoder, which simply
48  // casts the int value to float. This will be used for any INT32 data other than
49  // convolution biases.
50  return std::make_unique<Int32Decoder>(static_cast<const int32_t*>(data));
51  }
52 
53  // NOTE: If we only have a single (non-zero) quantization scale and no quantization
54  // dimension is specified, we need to create a ScaledInt32Decoder. This will be used
55  // to decode per-tensor quantized convolution biases.
56  return std::make_unique<ScaledInt32Decoder>(static_cast<const int32_t*>(data), scale);
57  }
58 }
59 
60 } // anonymous namespace
61 
62 template<typename T>
63 inline std::unique_ptr<Decoder<T>> MakeDecoder(const TensorInfo& info, const void* data = nullptr);
64 
65 template<>
66 inline std::unique_ptr<Decoder<float>> MakeDecoder(const TensorInfo& info, const void* data)
67 {
68  switch(info.GetDataType())
69  {
70  case DataType::QAsymmS8:
71  {
72  return std::make_unique<QASymmS8Decoder>(
73  static_cast<const int8_t*>(data),
74  info.GetQuantizationScale(),
75  info.GetQuantizationOffset());
76  }
77  case DataType::QAsymmU8:
78  {
79  return std::make_unique<QASymm8Decoder>(
80  static_cast<const uint8_t*>(data),
81  info.GetQuantizationScale(),
82  info.GetQuantizationOffset());
83  }
84  case DataType::QSymmS16:
85  {
86  return std::make_unique<QSymm16Decoder>(
87  static_cast<const int16_t*>(data),
88  info.GetQuantizationScale(),
89  info.GetQuantizationOffset());
90  }
91  case DataType::BFloat16:
92  {
93  return std::make_unique<BFloat16Decoder>(static_cast<const BFloat16*>(data));
94  }
95  case DataType::Float16:
96  {
97  return std::make_unique<Float16Decoder>(static_cast<const Half*>(data));
98  }
99  case DataType::Float32:
100  {
101  return std::make_unique<Float32Decoder>(static_cast<const float*>(data));
102  }
103  case DataType::Signed32:
104  {
105  return MakeSigned32Decoder(info, data);
106  }
107  case DataType::QSymmS8:
108  {
109  if (info.HasPerAxisQuantization())
110  {
111  std::pair<unsigned int, std::vector<float>> params = armnnUtils::GetPerAxisParams(info);
112  return std::make_unique<QSymm8PerAxisDecoder>(static_cast<const int8_t*>(data), info);
113  }
114  else
115  {
116  return std::make_unique<QSymmS8Decoder>(
117  static_cast<const int8_t*>(data),
118  info.GetQuantizationScale(),
119  info.GetQuantizationOffset());
120  }
121  }
123  {
124  return std::make_unique<BooleanDecoder>(static_cast<const uint8_t*>(data));
125  }
126  default:
127  {
128  ARMNN_ASSERT_MSG(false, "Unsupported Data Type!");
129  break;
130  }
131  }
132  return nullptr;
133 }
134 
135 template<>
136 inline std::unique_ptr<Decoder<bool>> MakeDecoder(const TensorInfo& info, const void* data)
137 {
138  switch(info.GetDataType())
139  {
140  case DataType::Boolean:
141  {
142  return std::make_unique<BooleanDecoderBool>(static_cast<const uint8_t*>(data));
143  }
144  default:
145  {
146  ARMNN_ASSERT_MSG(false, "Unsupported Data Type!");
147  break;
148  }
149  }
150  return nullptr;
151 }
152 
153 template<>
154 inline std::unique_ptr<Decoder<int32_t>> MakeDecoder(const TensorInfo& info, const void* data)
155 {
156  switch(info.GetDataType())
157  {
158  case DataType::Signed32:
159  {
160  return std::make_unique<Int32ToInt32tDecoder>(static_cast<const int32_t*>(data));
161  }
162  default:
163  {
164  ARMNN_ASSERT_MSG(false, "Unsupported Data Type!");
165  break;
166  }
167  }
168  return nullptr;
169 }
170 
171 } //namespace armnn
bool HasPerAxisQuantization() const
Definition: Tensor.cpp:448
std::pair< unsigned int, std::vector< float > > GetPerAxisParams(const armnn::TensorInfo &info)
Copyright (c) 2021 ARM Limited and Contributors.
std::unique_ptr< Decoder< T > > MakeDecoder(const TensorInfo &info, const void *data=nullptr)
Definition: Decoders.hpp:66
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
int32_t GetQuantizationOffset() const
Definition: Tensor.cpp:480
float GetQuantizationScale() const
Definition: Tensor.cpp:463
DataType GetDataType() const
Definition: Tensor.hpp:198
half_float::half Half
Definition: Half.hpp:18