Compute Library
 20.02.1
QuantizationInfo.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 ARM Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #ifndef ARM_COMPUTE_QUANTIZATION_INFO_H
25 #define ARM_COMPUTE_QUANTIZATION_INFO_H
26 
28 #include "utils/misc/Utility.h"
29 
30 #include <cstddef>
31 #include <type_traits>
32 #include <vector>
33 
34 namespace arm_compute
35 {
36 using qasymm8_signed_t = int8_t; /**< 8 bit signed quantized asymmetric scalar value */
37 using qasymm8_t = uint8_t; /**< 8 bit quantized asymmetric scalar value */
38 using qsymm16_t = int16_t; /**< 16 bit quantized symmetric scalar value */
39 using qasymm16_t = uint16_t; /**< 16 bit quantized asymmetric scalar value */
40 
41 /** Quantization info when assuming per layer quantization */
43 {
44  /** Default constructor */
46  : scale(0.f), offset(0)
47  {
48  }
49  /** Constructor
50  *
51  * @param[in] scale Quantization scale
52  * @param[in] offset Quantization offset
53  */
56  {
57  }
58  /** Checks if the scale and offset are both zero */
59  bool empty() const
60  {
61  return (scale == 0) && (offset == 0);
62  }
63 
64  float scale;
65  int32_t offset;
66 };
67 
68 /** Quantization information */
70 {
71 public:
72  /** Default constructor */
73  QuantizationInfo() noexcept
74  : _scale(),
75  _offset()
76  {
77  }
78  /** Construct quantization info.
79  *
80  * @note Used for symmetric quantization
81  *
82  * @param[in] scale Scale.
83  */
85  : _scale(1, scale), _offset()
86  {
87  }
88  /** Construct quantization info.
89  *
90  * @note Used for asymmetric quantization
91  *
92  * @param[in] scale Scale.
93  * @param[in] offset Offset.
94  */
96  : _scale(1, scale), _offset(1, offset)
97  {
98  }
99  /** Construct quantization info.
100  *
101  * @note Used for symmetric per channel quantization
102  *
103  * @param[in] scale Scale.
104  */
105  QuantizationInfo(std::vector<float> scale)
106  : _scale(scale), _offset()
107  {
108  }
109  /** Construct quantization info.
110  *
111  * @note Used for asymmetric per channel quantization
112  *
113  * @param[in] scale Scale.
114  * @param[in] offset Offset.
115  */
116  QuantizationInfo(std::vector<float> scale, std::vector<int32_t> offset)
117  : _scale(scale), _offset(offset)
118  {
119  }
120  /** Scale vector accessor
121  *
122  * @return A reference to quantization scale metadata
123  */
124  const std::vector<float> &scale() const
125  {
126  return _scale;
127  }
128  /** Offset vector accessor
129  *
130  * @return A reference to quantization offset metadata
131  */
132  const std::vector<int32_t> &offset() const
133  {
134  return _offset;
135  }
136  /** Indicates whether this QuantizationInfo has valid settings or not
137  *
138  * @return True if the this has invalid settings.
139  */
140  bool empty() const
141  {
142  return _scale.empty() && _offset.empty();
143  }
144  /** Return per layer quantization info
145  *
146  * @return Uniform quantization information in case of empty information zero is returned in the respective fields
147  */
149  {
151  uqinfo.scale = _scale.empty() ? 0 : _scale[0];
152  uqinfo.offset = _offset.empty() ? 0 : _offset[0];
153 
154  return uqinfo;
155  }
156 
157 private:
158  std::vector<float> _scale; /**< Vector containing scaling factors */
159  std::vector<int32_t> _offset; /**< Vector containing zero offsets */
160 };
161 
162 /** Check whether two quantization info are equal.
163  *
164  * @param[in] lhs RHS quantization info.
165  * @param[in] rhs LHS quantization info.
166  *
167  * @return True if the given quantization info is the same.
168  */
169 inline bool operator==(const QuantizationInfo &lhs, const QuantizationInfo &rhs)
170 {
171  return (lhs.scale() == rhs.scale()) && (lhs.offset() == rhs.offset());
172 }
173 
174 /** Check whether two quantization info are not equal.
175  *
176  * @param[in] lhs RHS quantization info.
177  * @param[in] rhs LHS quantization info.
178  *
179  * @return True if the given quantization info is the same.
180  */
181 inline bool operator!=(const QuantizationInfo &lhs, const QuantizationInfo &rhs)
182 {
183  return !(operator==(lhs, rhs));
184 }
185 
186 /** Check whether two quantization info are equal.
187  *
188  * @param[in] lhs RHS quantization info.
189  * @param[in] rhs LHS quantization info.
190  *
191  * @return True if the given quantization info is the same.
192  */
193 inline bool operator==(const UniformQuantizationInfo &lhs, const UniformQuantizationInfo &rhs)
194 {
195  return (lhs.scale == rhs.scale) && (lhs.offset == rhs.offset);
196 }
197 
198 /** Check whether two quantization info are not equal.
199  *
200  * @param[in] lhs RHS quantization info.
201  * @param[in] rhs LHS quantization info.
202  *
203  * @return True if the given quantization info is the same.
204  */
205 inline bool operator!=(const UniformQuantizationInfo &lhs, const UniformQuantizationInfo &rhs)
206 {
207  return !(operator==(lhs, rhs));
208 }
209 template <typename QUANTIZED_TYPE = uint8_t>
211 {
212  static_assert(std::is_same<QUANTIZED_TYPE, uint8_t>::value
213  || std::is_same<QUANTIZED_TYPE, int8_t>::value,
214  "quantized type should be either uint8_t or int8_t.");
215 
216  /** Quantize a value given a 8-bit asymmetric quantization scheme
217  *
218  * @param[in] value Value to quantize
219  * @param[in] qinfo Quantization information to use for quantizing
220  * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
221  *
222  * @return Quantized value
223  */
225  {
227  const int quantized = arm_compute::round(value / qinfo.scale, rounding_policy) + qinfo.offset;
228  return static_cast<QUANTIZED_TYPE>(arm_compute::utility::clamp<decltype(quantized), QUANTIZED_TYPE>(quantized));
229  }
230 
231  /** Quantize a value given a 8-bit asymmetric quantization scheme
232  *
233  * @param[in] value Value to quantize
234  * @param[in] qinfo Quantization information to use for quantizing
235  * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
236  *
237  * @return Quantized value
238  */
239  static inline QUANTIZED_TYPE quantize(float value, const QuantizationInfo &qinfo, RoundingPolicy rounding_policy = RoundingPolicy::TO_NEAREST_UP)
240  {
241  const UniformQuantizationInfo uqinfo = qinfo.uniform();
242  ARM_COMPUTE_ERROR_ON(uqinfo.scale == 0);
243  const int quantized = arm_compute::round(value / uqinfo.scale, rounding_policy) + uqinfo.offset;
244  return static_cast<QUANTIZED_TYPE>(arm_compute::utility::clamp<decltype(quantized), QUANTIZED_TYPE>(quantized));
245  }
246 
247  /** Dequantize a value given a 8-bit asymmetric quantization scheme
248  *
249  * @param[in] value Value to dequantize
250  * @param[in] qinfo Quantization information to use for dequantizing
251  *
252  * @return Dequantized value
253  */
254  static inline float dequantize(QUANTIZED_TYPE value, const UniformQuantizationInfo &qinfo)
255  {
256  return (static_cast<int>(value) - qinfo.offset) * qinfo.scale;
257  }
258 
259  /** Dequantize a value given a 8-bit asymmetric quantization scheme
260  *
261  * @param[in] value Value to dequantize
262  * @param[in] qinfo Quantization information to use for dequantizing
263  *
264  * @return Dequantized value
265  */
266  static inline float dequantize(QUANTIZED_TYPE value, const QuantizationInfo &qinfo)
267  {
268  const UniformQuantizationInfo uqinfo = qinfo.uniform();
269  return (static_cast<int>(value) - uqinfo.offset) * uqinfo.scale;
270  }
271 };
272 
273 /** Quantize a value given an unsigned 8-bit asymmetric quantization scheme
274  *
275  * @param[in] value Value to quantize
276  * @param[in] qinfo Quantization information to use for quantizing
277  * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
278  *
279  * @return Quantized value
280  */
281 template <typename INFO_TYPE>
283 {
285 }
286 
287 /** Quantize a value given a signed 8-bit asymmetric quantization scheme
288  *
289  * @param[in] value Value to quantize
290  * @param[in] qinfo Quantization information to use for quantizing
291  * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
292  *
293  * @return Quantized value
294  */
295 template <typename INFO_TYPE>
297 {
299 }
300 
301 /** Quantize a value given a 8-bit symmetric quantization scheme
302  *
303  * @param[in] value Value to quantize
304  * @param[in] qinfo Quantization information to use for quantizing
305  *
306  * @return Quantized value
307  */
308 inline int8_t quantize_qsymm8(float value, const QuantizationInfo &qinfo)
309 {
311  quantized = std::max(-128, std::min(quantized, 127));
312  return quantized;
313 }
314 
315 /** Quantize a value given a 8-bit symmetric per channel quantization scheme
316  *
317  * @param[in] value Value to quantize
318  * @param[in] qinfo Quantization information to use for quantizing
319  * @param[in] channel_id channel index into the scale vector of quantization info
320  *
321  * @return Quantized value
322  */
323 inline int8_t quantize_qsymm8_per_channel(float value, const QuantizationInfo &qinfo, size_t channel_id = 0)
324 {
325  int quantized = arm_compute::round(value / qinfo.scale()[channel_id], RoundingPolicy::TO_NEAREST_UP);
326  quantized = std::max(-128, std::min(quantized, 127));
327  return quantized;
328 }
329 
330 /** Dequantize a value given an unsigned 8-bit asymmetric quantization scheme
331  *
332  * @param[in] value Value to dequantize
333  * @param[in] qinfo Quantization information to use for dequantizing
334  *
335  * @return Dequantized value
336  */
337 template <typename INFO_TYPE>
338 inline float dequantize_qasymm8(uint8_t value, const INFO_TYPE &qinfo)
339 {
341 }
342 
343 /** Dequantize a value given a signed 8-bit asymmetric quantization scheme
344  *
345  * @param[in] value Value to dequantize
346  * @param[in] qinfo Quantization information to use for dequantizing
347  *
348  * @return Dequantized value
349  */
350 template <typename INFO_TYPE>
351 inline float dequantize_qasymm8_signed(int8_t value, const INFO_TYPE &qinfo)
352 {
354 }
355 
356 /** Dequantize a value given an 8-bit asymmetric quantization scheme
357  *
358  * @param[in] value Value to dequantize
359  * @param[in] scale Scale to use for dequantization
360  * @param[in] offset Zero-offset to use for dequantization
361  *
362  * @return Dequantized value
363  */
364 inline float dequantize(uint8_t value, float scale, int32_t offset)
365 {
366  return (static_cast<int>(value) - offset) * scale;
367 }
368 
369 /** Dequantize a value given a 8-bit symmetric quantization scheme
370  *
371  * @param[in] value Value to dequantize
372  * @param[in] qinfo Quantization information to use for dequantizing
373  *
374  * @return Dequantized value
375  */
376 inline float dequantize_qsymm8(int8_t value, const UniformQuantizationInfo &qinfo)
377 {
378  return value * qinfo.scale;
379 }
380 
381 /** Dequantize a value given a 8-bit symmetric quantization scheme
382  *
383  * @param[in] value Value to dequantize
384  * @param[in] scale Scale to use for dequantization
385  *
386  * @return Dequantized value
387  */
388 inline float dequantize(int8_t value, float scale)
389 {
390  return value * scale;
391 }
392 
393 /** Dequantize a value given a 16-bit symmetric quantization scheme
394  *
395  * @param[in] value Value to dequantize
396  * @param[in] scale Scale to use for dequantization
397  *
398  * @return Dequantized value
399  */
400 inline float dequantize(int16_t value, float scale)
401 {
402  return value * scale;
403 }
404 
405 /** Dequantize a value given a 16-bit asymmetric quantization scheme
406  *
407  * @param[in] value Value to dequantize
408  * @param[in] scale Scale to use for dequantization
409  * @param[in] offset Zero-offset to use for dequantization
410  *
411  * @return Dequantized value
412  */
413 inline float dequantize(uint16_t value, float scale, int32_t offset)
414 {
415  return (static_cast<int>(value) - offset) * scale;
416 }
417 
418 /** Quantize a value given a 16-bit symmetric quantization scheme
419  *
420  * @param[in] value Value to quantize
421  * @param[in] qinfo Quantization information to use for quantizing
422  * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
423  *
424  * @return Quantized value
425  */
427 {
428  int quantized = arm_compute::round(value / qinfo.scale, rounding_policy);
429  quantized = arm_compute::utility::clamp<int, int16_t>(quantized);
430  return quantized;
431 }
432 
433 /** Dequantize a value given a 16-bit symmetric quantization scheme
434  *
435  * @param[in] value Value to dequantize
436  * @param[in] qinfo Quantization information to use for dequantizing
437  *
438  * @return Dequantized value
439  */
440 inline float dequantize_qsymm16(int16_t value, const UniformQuantizationInfo &qinfo)
441 {
442  return value * qinfo.scale;
443 }
444 
445 /** Quantize a value given a 16-bit symmetric quantization scheme
446  *
447  * @param[in] value Value to quantize
448  * @param[in] qinfo Quantization information to use for quantizing
449  *
450  * @return Quantized value
451  */
452 inline int16_t quantize_qsymm16(float value, const QuantizationInfo &qinfo)
453 {
454  return quantize_qsymm16(value, qinfo.uniform());
455 }
456 
457 /** Dequantize a value given a 16-bit symmetric quantization scheme
458  *
459  * @param[in] value Value to dequantize
460  * @param[in] qinfo Quantization information to use for dequantizing
461  *
462  * @return Dequantized value
463  */
464 inline float dequantize_qsymm16(int16_t value, const QuantizationInfo &qinfo)
465 {
466  return dequantize_qsymm16(value, qinfo.uniform());
467 }
468 
469 /** Quantize a value given a 16-bit asymmetric quantization scheme
470  *
471  * @param[in] value Value to quantize
472  * @param[in] qinfo Quantization information to use for quantizing
473  * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up
474  *
475  * @return Quantized value
476  */
478 {
479  int quantized = arm_compute::round(value / qinfo.scale, rounding_policy) + qinfo.offset;
480  quantized = arm_compute::utility::clamp<int, uint16_t>(quantized);
481  return quantized;
482 }
483 
484 /** Dequantize a value given a 16-bit asymmetric quantization scheme
485  *
486  * @param[in] value Value to dequantize
487  * @param[in] qinfo Quantization information to use for dequantizing
488  *
489  * @return Dequantized value
490  */
491 inline float dequantize_qasymm16(uint16_t value, const UniformQuantizationInfo &qinfo)
492 {
493  return (static_cast<int>(value) - qinfo.offset) * qinfo.scale;
494 }
495 
496 /** Quantize a value given a 16-bit asymmetric quantization scheme
497  *
498  * @param[in] value Value to quantize
499  * @param[in] qinfo Quantization information to use for quantizing
500  *
501  * @return Quantized value
502  */
503 inline uint16_t quantize_qasymm16(float value, const QuantizationInfo &qinfo)
504 {
505  return quantize_qasymm16(value, qinfo.uniform());
506 }
507 
508 /** Dequantize a value given a 16-bit asymmetric quantization scheme
509  *
510  * @param[in] value Value to dequantize
511  * @param[in] qinfo Quantization information to use for dequantizing
512  *
513  * @return Dequantized value
514  */
515 inline float dequantize_qasymm16(uint16_t value, const QuantizationInfo &qinfo)
516 {
517  return dequantize_qasymm16(value, qinfo.uniform());
518 }
519 } // namespace arm_compute
520 #endif /* ARM_COMPUTE_QUANTIZATION_INFO_H */
QuantizationInfo() noexcept
Default constructor.
__global uchar * offset(const Image *img, int x, int y)
Get the pointer position of a Image.
Definition: helpers.h:510
const std::vector< int32_t > & offset() const
Offset vector accessor.
int8_t quantize_qsymm8(float value, const QuantizationInfo &qinfo)
Quantize a value given a 8-bit symmetric quantization scheme.
int16_t quantize_qsymm16(float value, const UniformQuantizationInfo &qinfo, RoundingPolicy rounding_policy=RoundingPolicy::TO_NEAREST_UP)
Quantize a value given a 16-bit symmetric quantization scheme.
Rounds to nearest value; half rounds away from zero.
float dequantize_qasymm8(uint8_t value, const INFO_TYPE &qinfo)
Dequantize a value given an unsigned 8-bit asymmetric quantization scheme.
bool operator!=(const Dimensions< T > &lhs, const Dimensions< T > &rhs)
Check that given dimensions are not equal.
Definition: Dimensions.h:267
UniformQuantizationInfo(float scale, int32_t offset)
Constructor.
uint8_t quantize_qasymm8(float value, const INFO_TYPE &qinfo, RoundingPolicy rounding_policy=RoundingPolicy::TO_NEAREST_UP)
Quantize a value given an unsigned 8-bit asymmetric quantization scheme.
QuantizationInfo(float scale, int offset)
Construct quantization info.
#define ARM_COMPUTE_ERROR_ON(cond)
If the condition is true then an error message is printed and an exception thrown.
Definition: Error.h:466
Quantization info when assuming per layer quantization.
QuantizationInfo(std::vector< float > scale)
Construct quantization info.
bool operator==(const Dimensions< T > &lhs, const Dimensions< T > &rhs)
Check that given dimensions are equal.
Definition: Dimensions.h:255
Copyright (c) 2017-2020 ARM Limited.
DataType clamp(const DataType &n, const DataType &lower=std::numeric_limits< RangeType >::lowest(), const DataType &upper=std::numeric_limits< RangeType >::max())
Performs clamping among a lower and upper value.
Definition: Utility.h:99
float dequantize_qasymm16(uint16_t value, const UniformQuantizationInfo &qinfo)
Dequantize a value given a 16-bit asymmetric quantization scheme.
Quantization information.
int8_t quantize_qasymm8_signed(float value, const INFO_TYPE &qinfo, RoundingPolicy rounding_policy=RoundingPolicy::TO_NEAREST_UP)
Quantize a value given a signed 8-bit asymmetric quantization scheme.
float dequantize_qsymm16(int16_t value, const UniformQuantizationInfo &qinfo)
Dequantize a value given a 16-bit symmetric quantization scheme.
static QUANTIZED_TYPE quantize(float value, const QuantizationInfo &qinfo, RoundingPolicy rounding_policy=RoundingPolicy::TO_NEAREST_UP)
Quantize a value given a 8-bit asymmetric quantization scheme.
QuantizationInfo(std::vector< float > scale, std::vector< int32_t > offset)
Construct quantization info.
UniformQuantizationInfo uniform() const
Return per layer quantization info.
RoundingPolicy
Rounding method.
Definition: Rounding.h:30
const std::vector< float > & scale() const
Scale vector accessor.
uint16_t qasymm16_t
16 bit quantized asymmetric scalar value
int round(float x, RoundingPolicy rounding_policy)
Return a rounded value of x.
Definition: Rounding.cpp:35
static float dequantize(QUANTIZED_TYPE value, const QuantizationInfo &qinfo)
Dequantize a value given a 8-bit asymmetric quantization scheme.
UniformQuantizationInfo()
Default constructor.
bool empty() const
Indicates whether this QuantizationInfo has valid settings or not.
int8_t quantize_qsymm8_per_channel(float value, const QuantizationInfo &qinfo, size_t channel_id=0)
Quantize a value given a 8-bit symmetric per channel quantization scheme.
const QuantizationInfo qinfo
Definition: Im2Col.cpp:150
uint8_t qasymm8_t
8 bit quantized asymmetric scalar value
int8_t qasymm8_signed_t
8 bit signed quantized asymmetric scalar value
QuantizationInfo(float scale)
Construct quantization info.
float dequantize_qasymm8_signed(int8_t value, const INFO_TYPE &qinfo)
Dequantize a value given a signed 8-bit asymmetric quantization scheme.
static float dequantize(QUANTIZED_TYPE value, const UniformQuantizationInfo &qinfo)
Dequantize a value given a 8-bit asymmetric quantization scheme.
float dequantize_qsymm8(int8_t value, const UniformQuantizationInfo &qinfo)
Dequantize a value given a 8-bit symmetric quantization scheme.
float dequantize(uint8_t value, float scale, int32_t offset)
Dequantize a value given an 8-bit asymmetric quantization scheme.
bool empty() const
Checks if the scale and offset are both zero.
int16_t qsymm16_t
16 bit quantized symmetric scalar value
Definition: NESymm.h:33
static QUANTIZED_TYPE quantize(float value, const UniformQuantizationInfo &qinfo, RoundingPolicy rounding_policy=RoundingPolicy::TO_NEAREST_UP)
Quantize a value given a 8-bit asymmetric quantization scheme.
uint16_t quantize_qasymm16(float value, const UniformQuantizationInfo &qinfo, RoundingPolicy rounding_policy=RoundingPolicy::TO_NEAREST_UP)
Quantize a value given a 16-bit asymmetric quantization scheme.