From e8291acc1d9e89c9274d31f0d5bb4779eb95588c Mon Sep 17 00:00:00 2001 From: Georgios Pinitas Date: Wed, 26 Feb 2020 09:58:13 +0000 Subject: COMPMID-3152: Initial Bfloat16 support Signed-off-by: Georgios Pinitas Change-Id: Ie6959e37e13731c86b2ee29392a99a293450a1b4 Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/2824 Tested-by: Arm Jenkins Comments-Addressed: Arm Jenkins Reviewed-by: Michalis Spyrou --- support/Bfloat16.h | 140 +++++++++++++++++++++++++++++++++++++++++++++ support/ToolchainSupport.h | 14 ++++- 2 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 support/Bfloat16.h (limited to 'support') diff --git a/support/Bfloat16.h b/support/Bfloat16.h new file mode 100644 index 0000000000..d897e42643 --- /dev/null +++ b/support/Bfloat16.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2020 ARM Limited. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef ARM_COMPUTE_BFLOAT16_H +#define ARM_COMPUTE_BFLOAT16_H + +#include + +namespace arm_compute +{ +namespace +{ +/** Convert float to bfloat16 + * + * @param[in] v Floating-point value to convert to bfloat + * + * @return Converted value + */ +inline uint16_t float_to_bf16(const float v) +{ + const uint32_t *fromptr = reinterpret_cast(&v); +#if defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) || defined(ARM_COMPUTE_FORCE_BF16) + uint16_t res; + + __asm __volatile( + "ldr s0, [%[fromptr]]\n" + ".inst 0x1e634000\n" // BFCVT h0, s0 + "str h0, [%[toptr]]\n" + : + : [fromptr] "r"(fromptr), [toptr] "r"(&res) + : "v0", "memory"); +#else /* defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) || defined(ARM_COMPUTE_FORCE_BF16) */ + uint16_t res = (*fromptr >> 16); + const uint16_t error = (*fromptr & 0x0000ffff); + uint16_t bf_l = res & 0x0001; + if((error > 0x8000) || ((error == 0x8000) && (bf_l != 0))) + { + res += 1; + } +#endif /* defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) || defined(ARM_COMPUTE_FORCE_BF16) */ + return res; +} + +/** Convert bfloat16 to float + * + * @param[in] v Bfloat16 value to convert to float + * + * @return Converted value + */ +inline float bf16_to_float(const uint16_t &v) +{ + const uint32_t lv = (v << 16); + const float *fp = reinterpret_cast(&lv); + + return *fp; +} +} + +/** Brain floating point representation class */ +class bfloat16 +{ +public: + /** Default Constructor */ + bfloat16() + : value(0) + { + } + /** Constructor + * + * @param[in] v Floating-point value + */ + explicit bfloat16(float v) + : value(float_to_bf16(v)) + { + } + /** Assignment operator + * + * @param[in] v Floating point value to assign + * + * @return The updated object + */ + bfloat16 &operator=(float v) + { + value = float_to_bf16(v); + return *this; + } + /** Floating point conversion operator + * + * @return Floating point representation of the value + */ + operator float() const + { + return bf16_to_float(value); + } + /** Lowest representative value + * + * @return Returns the lowest finite value representable by bfloat16 + */ + static bfloat16 lowest() + { + bfloat16 val; + val.value = 0xFF7F; + return val; + } + /** Largest representative value + * + * @return Returns the largest finite value representable by bfloat16 + */ + static bfloat16 max() + { + bfloat16 val; + val.value = 0x7F7F; + return val; + } + +private: + uint16_t value; +}; +} // namespace arm_compute +#endif /* ARM_COMPUTE_BFLOAT16_H */ \ No newline at end of file diff --git a/support/ToolchainSupport.h b/support/ToolchainSupport.h index f90d65c9d9..923a9cbfe0 100644 --- a/support/ToolchainSupport.h +++ b/support/ToolchainSupport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 ARM Limited. + * Copyright (c) 2017-2020 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -39,6 +39,7 @@ #include #endif // __ARM_FEATURE_FP16_VECTOR_ARITHMETIC +#include "support/Bfloat16.h" #include "support/Half.h" namespace arm_compute @@ -428,6 +429,12 @@ inline __fp16 lowest<__fp16>() } #endif /* __ARM_FEATURE_FP16_VECTOR_ARITHMETIC */ +template <> +inline bfloat16 lowest() +{ + return bfloat16::lowest(); +} + // std::isfinite template ::value>::type> inline bool isfinite(T value) @@ -439,6 +446,11 @@ inline bool isfinite(half_float::half value) { return half_float::isfinite(value); } + +inline bool isfinite(bfloat16 value) +{ + return std::isfinite(float(value)); +} } // namespace cpp11 namespace cpp14 -- cgit v1.2.1