From 35ea9a7521b4b858a6bcc33a244b6e7f94b6e3a3 Mon Sep 17 00:00:00 2001 From: Michele Di Giorgio Date: Fri, 23 Aug 2019 12:02:06 +0100 Subject: COMPMID-2317: Add new QASYMM16 data type Change-Id: I9fbbba633f10d542474a08b1898150b9799b7ae5 Signed-off-by: Michele Di Giorgio Reviewed-on: https://review.mlplatform.org/c/1805 Comments-Addressed: Arm Jenkins Reviewed-by: Michalis Spyrou Tested-by: Arm Jenkins --- arm_compute/core/PixelValue.h | 5 +- arm_compute/core/QuantizationInfo.h | 87 +++++++++++++++++++--- arm_compute/core/Types.h | 1 + arm_compute/core/Utils.h | 6 ++ src/core/Utils.cpp | 1 + src/runtime/CL/functions/CLLSTMLayerQuantized.cpp | 4 +- .../NEON/functions/NELSTMLayerQuantized.cpp | 2 +- tests/Utils.h | 1 + utils/TypePrinter.h | 3 + utils/Utils.h | 1 + 10 files changed, 96 insertions(+), 15 deletions(-) diff --git a/arm_compute/core/PixelValue.h b/arm_compute/core/PixelValue.h index 4a07fa6c5d..e237498920 100644 --- a/arm_compute/core/PixelValue.h +++ b/arm_compute/core/PixelValue.h @@ -43,7 +43,7 @@ public: * * @param[in] v int value. * @param[in] datatype DataType that @p v have to be stored - * @param[in] qinfo (Optional) QuantizationInfo to apply in case of QASYMM8 datatype to @p v + * @param[in] qinfo (Optional) QuantizationInfo to apply in case of quantized data types to @p v */ PixelValue(uint64_t v, DataType datatype, QuantizationInfo qinfo = QuantizationInfo()) : PixelValue() @@ -68,6 +68,9 @@ public: case DataType::S16: value.s16 = static_cast(v); break; + case DataType::QASYMM16: + value.u16 = quantize_qasymm16(static_cast(v), qinfo); + break; case DataType::QSYMM16: value.s16 = quantize_qsymm16(static_cast(v), qinfo); break; diff --git a/arm_compute/core/QuantizationInfo.h b/arm_compute/core/QuantizationInfo.h index 1517d48381..5e6e5b349c 100644 --- a/arm_compute/core/QuantizationInfo.h +++ b/arm_compute/core/QuantizationInfo.h @@ -32,8 +32,9 @@ namespace arm_compute { -using qasymm8_t = uint8_t; /**< 8 bit quantized asymmetric scalar value */ -using qsymm16_t = int16_t; /**< 16 bit quantized symmetric scalar value */ +using qasymm8_t = uint8_t; /**< 8 bit quantized asymmetric scalar value */ +using qsymm16_t = int16_t; /**< 16 bit quantized symmetric scalar value */ +using qasymm16_t = uint16_t; /**< 16 bit quantized asymmetric scalar value */ /** Quantization info when assuming per layer quantization */ struct UniformQuantizationInfo @@ -204,7 +205,7 @@ inline bool operator!=(const UniformQuantizationInfo &lhs, const UniformQuantiza return !(operator==(lhs, rhs)); } -/** Quantize a value given a asymmetric quantization scheme +/** Quantize a value given a 8-bit asymmetric quantization scheme * * @param[in] value Value to quantize * @param[in] qinfo Quantization information to use for quantizing @@ -219,7 +220,7 @@ inline uint8_t quantize_qasymm8(float value, const UniformQuantizationInfo &qinf return quantized; } -/** Quantize a value given a asymmetric quantization scheme +/** Quantize a value given a 8-bit asymmetric quantization scheme * * @param[in] value Value to quantize * @param[in] qinfo Quantization information to use for quantizing @@ -235,7 +236,7 @@ inline uint8_t quantize_qasymm8(float value, const QuantizationInfo &qinfo, Roun return quantized; } -/** Quantize a value given a symmetric quantization scheme +/** Quantize a value given a 8-bit symmetric quantization scheme * * @param[in] value Value to quantize * @param[in] qinfo Quantization information to use for quantizing @@ -249,7 +250,7 @@ inline int8_t quantize_qsymm8(float value, const QuantizationInfo &qinfo) return quantized; } -/** Dequantize a value given a asymmetric quantization scheme +/** Dequantize a value given a 8-bit asymmetric quantization scheme * * @param[in] value Value to dequantize * @param[in] qinfo Quantization information to use for dequantizing @@ -261,7 +262,7 @@ inline float dequantize_qasymm8(uint8_t value, const UniformQuantizationInfo &qi return (static_cast(value) - qinfo.offset) * qinfo.scale; } -/** Dequantize a value given a asymmetric quantization scheme +/** Dequantize a value given a 8-bit asymmetric quantization scheme * * @param[in] value Value to dequantize * @param[in] qinfo Quantization information to use for dequantizing @@ -274,7 +275,7 @@ inline float dequantize_qasymm8(uint8_t value, const QuantizationInfo &qinfo) return (static_cast(value) - uqinfo.offset) * uqinfo.scale; } -/** Dequantize a value given an asymmetric quantization scheme +/** Dequantize a value given an 8-bit asymmetric quantization scheme * * @param[in] value Value to dequantize * @param[in] scale Scale to use for dequantization @@ -287,7 +288,7 @@ inline float dequantize(uint8_t value, float scale, int32_t offset) return (static_cast(value) - offset) * scale; } -/** Dequantize a value given a symmetric quantization scheme +/** Dequantize a value given a 8-bit symmetric quantization scheme * * @param[in] value Value to dequantize * @param[in] qinfo Quantization information to use for dequantizing @@ -299,7 +300,7 @@ inline float dequantize_qsymm8(int8_t value, const UniformQuantizationInfo &qinf return value * qinfo.scale; } -/** Dequantize a value given a symmetric quantization scheme +/** Dequantize a value given a 8-bit symmetric quantization scheme * * @param[in] value Value to dequantize * @param[in] scale Scale to use for dequantization @@ -311,7 +312,7 @@ inline float dequantize(int8_t value, float scale) return value * scale; } -/** Dequantize a value given a symmetric quantization scheme +/** Dequantize a value given a 16-bit symmetric quantization scheme * * @param[in] value Value to dequantize * @param[in] scale Scale to use for dequantization @@ -323,6 +324,19 @@ inline float dequantize(int16_t value, float scale) return value * scale; } +/** Dequantize a value given a 16-bit asymmetric quantization scheme + * + * @param[in] value Value to dequantize + * @param[in] scale Scale to use for dequantization + * @param[in] offset Zero-offset to use for dequantization + * + * @return Dequantized value + */ +inline float dequantize(uint16_t value, float scale, int32_t offset) +{ + return (static_cast(value) - offset) * scale; +} + /** Quantize a value given a 16-bit symmetric quantization scheme * * @param[in] value Value to quantize @@ -373,5 +387,56 @@ inline float dequantize_qsymm16(int16_t value, const QuantizationInfo &qinfo) { return dequantize_qsymm16(value, qinfo.uniform()); } + +/** Quantize a value given a 16-bit asymmetric quantization scheme + * + * @param[in] value Value to quantize + * @param[in] qinfo Quantization information to use for quantizing + * @param[in] rounding_policy (Optional) Rounding policy to use. Default: nearest up + * + * @return Quantized value + */ +inline uint16_t quantize_qasymm16(float value, const UniformQuantizationInfo &qinfo, RoundingPolicy rounding_policy = RoundingPolicy::TO_NEAREST_UP) +{ + int quantized = arm_compute::round(value / qinfo.scale, rounding_policy) + qinfo.offset; + quantized = arm_compute::utility::clamp(quantized); + return quantized; +} + +/** Dequantize a value given a 16-bit asymmetric quantization scheme + * + * @param[in] value Value to dequantize + * @param[in] qinfo Quantization information to use for dequantizing + * + * @return Dequantized value + */ +inline float dequantize_qasymm16(uint16_t value, const UniformQuantizationInfo &qinfo) +{ + return (static_cast(value) - qinfo.offset) * qinfo.scale; +} + +/** Quantize a value given a 16-bit asymmetric quantization scheme + * + * @param[in] value Value to quantize + * @param[in] qinfo Quantization information to use for quantizing + * + * @return Quantized value + */ +inline uint16_t quantize_qasymm16(float value, const QuantizationInfo &qinfo) +{ + return quantize_qasymm16(value, qinfo.uniform()); +} + +/** Dequantize a value given a 16-bit asymmetric quantization scheme + * + * @param[in] value Value to dequantize + * @param[in] qinfo Quantization information to use for dequantizing + * + * @return Dequantized value + */ +inline float dequantize_qasymm16(uint16_t value, const QuantizationInfo &qinfo) +{ + return dequantize_qasymm16(value, qinfo.uniform()); +} } // namespace arm_compute #endif /*__ARM_COMPUTE_QUANTIZATION_INFO_H__ */ diff --git a/arm_compute/core/Types.h b/arm_compute/core/Types.h index 59e39958b6..7f60638d05 100644 --- a/arm_compute/core/Types.h +++ b/arm_compute/core/Types.h @@ -83,6 +83,7 @@ enum class DataType U16, /**< unsigned 16-bit number */ S16, /**< signed 16-bit number */ QSYMM16, /**< quantized, symmetric fixed-point 16-bit number */ + QASYMM16, /**< quantized, asymmetric fixed-point 16-bit number */ U32, /**< unsigned 32-bit number */ S32, /**< signed 32-bit number */ U64, /**< unsigned 64-bit number */ diff --git a/arm_compute/core/Utils.h b/arm_compute/core/Utils.h index eb4cf05ae9..6ffab4b9ea 100644 --- a/arm_compute/core/Utils.h +++ b/arm_compute/core/Utils.h @@ -120,6 +120,7 @@ inline size_t data_size_from_type(DataType data_type) case DataType::U16: case DataType::S16: case DataType::QSYMM16: + case DataType::QASYMM16: case DataType::F16: return 2; case DataType::F32: @@ -195,6 +196,7 @@ inline size_t element_size_from_data_type(DataType dt) case DataType::U16: case DataType::S16: case DataType::QSYMM16: + case DataType::QASYMM16: case DataType::F16: return 2; case DataType::U32: @@ -532,7 +534,9 @@ inline DataType get_promoted_data_type(DataType dt) case DataType::QSYMM8: case DataType::QASYMM8: case DataType::QSYMM8_PER_CHANNEL: + case DataType::QASYMM8_PER_CHANNEL: case DataType::QSYMM16: + case DataType::QASYMM16: case DataType::F16: case DataType::U32: case DataType::S32: @@ -1017,6 +1021,7 @@ inline bool is_data_type_quantized(DataType dt) case DataType::QSYMM8_PER_CHANNEL: case DataType::QASYMM8_PER_CHANNEL: case DataType::QSYMM16: + case DataType::QASYMM16: return true; default: return false; @@ -1035,6 +1040,7 @@ inline bool is_data_type_quantized_asymmetric(DataType dt) { case DataType::QASYMM8: case DataType::QASYMM8_PER_CHANNEL: + case DataType::QASYMM16: return true; default: return false; diff --git a/src/core/Utils.cpp b/src/core/Utils.cpp index d5d9d10e6b..122373f5c6 100644 --- a/src/core/Utils.cpp +++ b/src/core/Utils.cpp @@ -163,6 +163,7 @@ const std::string &arm_compute::string_from_data_type(DataType dt) { DataType::QASYMM8_PER_CHANNEL, "QASYMM8_PER_CHANNEL" }, { DataType::QASYMM8, "QASYMM8" }, { DataType::QSYMM16, "QSYMM16" }, + { DataType::QASYMM16, "QASYMM16" }, }; return dt_map[dt]; diff --git a/src/runtime/CL/functions/CLLSTMLayerQuantized.cpp b/src/runtime/CL/functions/CLLSTMLayerQuantized.cpp index e0006a77d0..da19cc1cc3 100644 --- a/src/runtime/CL/functions/CLLSTMLayerQuantized.cpp +++ b/src/runtime/CL/functions/CLLSTMLayerQuantized.cpp @@ -345,7 +345,7 @@ void CLLSTMLayerQuantized::run() _tanh_output_state.run(); _mul_output_state_tmp_output_gate.run(); - // Requantize output state from QSYMM16 to QASYMM16 + // Requantize output state from QSYMM16 to QASYMM8 _dequantize.run(); _quantize.run(); } @@ -394,4 +394,4 @@ void CLLSTMLayerQuantized::prepare() } } -} // namespace arm_compute \ No newline at end of file +} // namespace arm_compute diff --git a/src/runtime/NEON/functions/NELSTMLayerQuantized.cpp b/src/runtime/NEON/functions/NELSTMLayerQuantized.cpp index 6cfa9887ff..96c776141a 100644 --- a/src/runtime/NEON/functions/NELSTMLayerQuantized.cpp +++ b/src/runtime/NEON/functions/NELSTMLayerQuantized.cpp @@ -324,7 +324,7 @@ void NELSTMLayerQuantized::run() _tanh_output_state.run(); _mul3.run(); - // Requantize output state from QSYMM16 to QASYMM16 + // Requantize output state from QSYMM16 to QASYMM8 _dequantize.run(); _quantize.run(); } diff --git a/tests/Utils.h b/tests/Utils.h index 81bc2663de..f88b01dc40 100644 --- a/tests/Utils.h +++ b/tests/Utils.h @@ -361,6 +361,7 @@ void store_value_with_data_type(void *ptr, T value, DataType data_type) *reinterpret_cast(ptr) = value; break; case DataType::U16: + case DataType::QASYMM16: *reinterpret_cast(ptr) = value; break; case DataType::S16: diff --git a/utils/TypePrinter.h b/utils/TypePrinter.h index 904115360a..41bfd1d6c8 100644 --- a/utils/TypePrinter.h +++ b/utils/TypePrinter.h @@ -646,6 +646,9 @@ inline ::std::ostream &operator<<(::std::ostream &os, const DataType &data_type) case DataType::QSYMM16: os << "QSYMM16"; break; + case DataType::QASYMM16: + os << "QASYMM16"; + break; case DataType::U32: os << "U32"; break; diff --git a/utils/Utils.h b/utils/Utils.h index 8605f4e3e1..ec08896257 100644 --- a/utils/Utils.h +++ b/utils/Utils.h @@ -173,6 +173,7 @@ inline std::string get_typestring(DataType data_type) case DataType::QSYMM8_PER_CHANNEL: return no_endianness + "i" + support::cpp11::to_string(sizeof(int8_t)); case DataType::U16: + case DataType::QASYMM16: return endianness + "u" + support::cpp11::to_string(sizeof(uint16_t)); case DataType::S16: case DataType::QSYMM16: -- cgit v1.2.1