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 --- tests/AssetsLibrary.h | 23 +++++++++++++- tests/Utils.h | 5 ++- tests/validation/Helpers.cpp | 14 ++++++++- tests/validation/NEON/DepthConvertLayer.cpp | 40 ++++++++++++++++++++++++ tests/validation/reference/DepthConvertLayer.cpp | 25 +++++++++++++-- tests/validation/reference/DepthConvertLayer.h | 7 +++-- 6 files changed, 106 insertions(+), 8 deletions(-) (limited to 'tests') diff --git a/tests/AssetsLibrary.h b/tests/AssetsLibrary.h index c4892748f4..e625c37505 100644 --- a/tests/AssetsLibrary.h +++ b/tests/AssetsLibrary.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 ARM Limited. + * Copyright (c) 2017-2020 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -712,6 +712,13 @@ void AssetsLibrary::fill_tensor_uniform(T &&tensor, std::random_device::result_t fill(tensor, distribution_s64, seed_offset); break; } + case DataType::BFLOAT16: + { + // It doesn't make sense to check [-inf, inf], so hard code it to a big number + std::uniform_real_distribution distribution_bf16(-1000.f, 1000.f); + fill(tensor, distribution_bf16, seed_offset); + break; + } case DataType::F16: { // It doesn't make sense to check [-inf, inf], so hard code it to a big number @@ -810,6 +817,14 @@ void AssetsLibrary::fill_tensor_uniform_ranged(T fill(tensor, distribution_s32, seed_offset); break; } + case DataType::BFLOAT16: + { + // It doesn't make sense to check [-inf, inf], so hard code it to a big number + const auto converted_pairs = detail::convert_range_pair(excluded_range_pairs); + RangedUniformDistribution distribution_bf16(-1000.f, 1000.f, converted_pairs); + fill(tensor, distribution_bf16, seed_offset); + break; + } case DataType::F16: { // It doesn't make sense to check [-inf, inf], so hard code it to a big number @@ -896,6 +911,12 @@ void AssetsLibrary::fill_tensor_uniform(T &&tensor, std::random_device::result_t fill(tensor, distribution_s64, seed_offset); break; } + case DataType::BFLOAT16: + { + std::uniform_real_distribution distribution_bf16(low, high); + fill(tensor, distribution_bf16, seed_offset); + break; + } case DataType::F16: { std::uniform_real_distribution distribution_f16(low, high); diff --git a/tests/Utils.h b/tests/Utils.h index 154d265cf9..3dc317f528 100644 --- a/tests/Utils.h +++ b/tests/Utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 ARM Limited. + * Copyright (c) 2017-2020 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -383,6 +383,9 @@ void store_value_with_data_type(void *ptr, T value, DataType data_type) case DataType::S64: *reinterpret_cast(ptr) = value; break; + case DataType::BFLOAT16: + *reinterpret_cast(ptr) = bfloat16(value); + break; case DataType::F16: *reinterpret_cast(ptr) = value; break; diff --git a/tests/validation/Helpers.cpp b/tests/validation/Helpers.cpp index afefee77be..4da9742c2a 100644 --- a/tests/validation/Helpers.cpp +++ b/tests/validation/Helpers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 ARM Limited. + * Copyright (c) 2017-2020 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -212,6 +212,18 @@ SimpleTensor convert_from_symmetric(const SimpleTensor &src) return dst; } +SimpleTensor convert_from_bfloat16(const SimpleTensor &src) +{ + SimpleTensor dst{ src.shape(), DataType::F32, 1, QuantizationInfo(), src.data_layout() }; + return dst; +} + +SimpleTensor convert_to_bfloat(const SimpleTensor &src) +{ + SimpleTensor dst{ src.shape(), DataType::BFLOAT16, 1, QuantizationInfo(), src.data_layout() }; + return dst; +} + template void matrix_multiply(const SimpleTensor &a, const SimpleTensor &b, SimpleTensor &out) { diff --git a/tests/validation/NEON/DepthConvertLayer.cpp b/tests/validation/NEON/DepthConvertLayer.cpp index b7de8fd9bc..163f539659 100644 --- a/tests/validation/NEON/DepthConvertLayer.cpp +++ b/tests/validation/NEON/DepthConvertLayer.cpp @@ -56,12 +56,14 @@ const auto DepthConvertLayerU16toU8Dataset = combine(framework::dataset::ma const auto DepthConvertLayerU16toU32Dataset = combine(framework::dataset::make("DataType", DataType::U16), framework::dataset::make("DataType", DataType::U32)); const auto DepthConvertLayerS16toU8Dataset = combine(framework::dataset::make("DataType", DataType::S16), framework::dataset::make("DataType", DataType::U8)); const auto DepthConvertLayerS16toS32Dataset = combine(framework::dataset::make("DataType", DataType::S16), framework::dataset::make("DataType", DataType::S32)); +const auto DepthConvertLayerBF16toF32Dataset = combine(framework::dataset::make("DataType", DataType::BFLOAT16), framework::dataset::make("DataType", DataType::F32)); const auto DepthConvertLayerF16toU8Dataset = combine(framework::dataset::make("DataType", DataType::F16), framework::dataset::make("DataType", DataType::U8)); const auto DepthConvertLayerF16toF32Dataset = combine(framework::dataset::make("DataType", DataType::F16), framework::dataset::make("DataType", DataType::F32)); const auto DepthConvertLayerF16toS32Dataset = combine(framework::dataset::make("DataType", DataType::F16), framework::dataset::make("DataType", DataType::S32)); const auto DepthConvertLayerF32toF16Dataset = combine(framework::dataset::make("DataType", DataType::F32), framework::dataset::make("DataType", DataType::F16)); const auto DepthConvertLayerF32toS32Dataset = combine(framework::dataset::make("DataType", DataType::F32), framework::dataset::make("DataType", DataType::S32)); const auto DepthConvertLayerF32toU8Dataset = combine(framework::dataset::make("DataType", DataType::F32), framework::dataset::make("DataType", DataType::U8)); +const auto DepthConvertLayerF32toBF16Dataset = combine(framework::dataset::make("DataType", DataType::F32), framework::dataset::make("DataType", DataType::BFLOAT16)); const auto DepthConvertLayerS32toF32Dataset = combine(framework::dataset::make("DataType", DataType::S32), framework::dataset::make("DataType", DataType::F32)); const auto DepthConvertLayerS32toQASYMM8Dataset = combine(framework::dataset::make("DataType", DataType::S32), framework::dataset::make("DataType", DataType::QASYMM8)); @@ -127,6 +129,8 @@ using NEDepthConvertLayerToU8Fixture = DepthConvertLayerValidationFixture using NEDepthConvertLayerToU32Fixture = DepthConvertLayerValidationFixture; template +using NEDepthConvertLayerToBF16Fixture = DepthConvertLayerValidationFixture; +template using NEDepthConvertLayerToF16Fixture = DepthConvertLayerValidationFixture; template using NEDepthConvertLayerToF32Fixture = DepthConvertLayerValidationFixture; @@ -340,6 +344,42 @@ FIXTURE_DATA_TEST_CASE(RunLarge, NEDepthConvertLayerToS32Fixture, frame } TEST_SUITE_END() // S16_to_S32 +#if defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) || defined(ARM_COMPUTE_FORCE_BF16) +TEST_SUITE(BFLOAT16_to_F32) +FIXTURE_DATA_TEST_CASE(RunSmall, NEDepthConvertLayerToF32Fixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), DepthConvertLayerBF16toF32Dataset), + framework::dataset::make("ConvertPolicy", { ConvertPolicy::SATURATE, ConvertPolicy::WRAP })), + DepthConvertLayerZeroShiftDataset)) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEDepthConvertLayerToF32Fixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), DepthConvertLayerBF16toF32Dataset), + framework::dataset::make("ConvertPolicy", { ConvertPolicy::SATURATE, ConvertPolicy::WRAP })), + DepthConvertLayerZeroShiftDataset)) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() // BFLOAT16_to_F32 + +TEST_SUITE(F32_to_BFLOAT16) +FIXTURE_DATA_TEST_CASE(RunSmall, NEDepthConvertLayerToBF16Fixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(datasets::SmallShapes(), DepthConvertLayerF32toBF16Dataset), + framework::dataset::make("ConvertPolicy", { ConvertPolicy::SATURATE, ConvertPolicy::WRAP })), + DepthConvertLayerZeroShiftDataset)) +{ + // Validate output + validate(Accessor(_target), _reference); +} +FIXTURE_DATA_TEST_CASE(RunLarge, NEDepthConvertLayerToBF16Fixture, framework::DatasetMode::NIGHTLY, combine(combine(combine(datasets::LargeShapes(), DepthConvertLayerF32toBF16Dataset), + framework::dataset::make("ConvertPolicy", { ConvertPolicy::SATURATE, ConvertPolicy::WRAP })), + DepthConvertLayerZeroShiftDataset)) +{ + // Validate output + validate(Accessor(_target), _reference); +} +TEST_SUITE_END() // F32_to_BFLOAT16 +#endif /* defined(__ARM_FEATURE_BF16_VECTOR_ARITHMETIC) || defined(ARM_COMPUTE_FORCE_BF16) */ + #ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC TEST_SUITE(F16_to_QASYMM8) FIXTURE_DATA_TEST_CASE(RunSmall, NEDepthConvertLayerToQASYMM8Fixture, framework::DatasetMode::PRECOMMIT, combine(combine(combine(combine(datasets::SmallShapes(), diff --git a/tests/validation/reference/DepthConvertLayer.cpp b/tests/validation/reference/DepthConvertLayer.cpp index 7da0011fbb..57eeb7f6f3 100644 --- a/tests/validation/reference/DepthConvertLayer.cpp +++ b/tests/validation/reference/DepthConvertLayer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 ARM Limited. + * Copyright (c) 2017-2020 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -63,14 +63,14 @@ SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, Con return result; } -template < typename T1, typename T2, typename std::enable_if < is_floating_point::value &&!std::is_same::value, int >::type > +template < typename T1, typename T2, typename std::enable_if < is_floating_point::value &&(!std::is_same::value &&!std::is_same::value), int >::type > SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift) { SimpleTensor result(src.shape(), dt_out); ARM_COMPUTE_ERROR_ON(shift != 0); ARM_COMPUTE_UNUSED(policy, shift); - if(!is_floating_point::value) + if(!std::is_same::value && !is_floating_point::value) { // Always saturate on floats for(int i = 0; i < src.num_elements(); ++i) @@ -89,6 +89,21 @@ SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, Con return result; } +template < typename T1, typename T2, typename std::enable_if < std::is_same::value || std::is_same::value, int >::type > +SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift) +{ + SimpleTensor result(src.shape(), dt_out); + ARM_COMPUTE_ERROR_ON(shift != 0); + ARM_COMPUTE_UNUSED(policy, shift); + + for(int i = 0; i < src.num_elements(); ++i) + { + result[i] = static_cast(src[i]); + } + + return result; +} + // U8 template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); @@ -143,6 +158,9 @@ template SimpleTensor depth_convert(const SimpleTensor &src, template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); +// BFLOAT16 +template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); + // F16 template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); @@ -160,6 +178,7 @@ template SimpleTensor depth_convert(const SimpleTensor &src, Dat template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); +template SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); } // namespace reference } // namespace validation diff --git a/tests/validation/reference/DepthConvertLayer.h b/tests/validation/reference/DepthConvertLayer.h index f9f849b3f7..9513d07c34 100644 --- a/tests/validation/reference/DepthConvertLayer.h +++ b/tests/validation/reference/DepthConvertLayer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 ARM Limited. + * Copyright (c) 2017-2020 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -38,7 +38,10 @@ namespace reference template < typename T1, typename T2, typename std::enable_if < std::is_integral::value &&!std::is_same::value, int >::type = 0 > SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); -template < typename T1, typename T2, typename std::enable_if < is_floating_point::value &&!std::is_same::value, int >::type = 0 > +template < typename T1, typename T2, typename std::enable_if < is_floating_point::value &&(!std::is_same::value &&!std::is_same::value), int >::type = 0 > +SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); + +template < typename T1, typename T2, typename std::enable_if < std::is_same::value || std::is_same::value, int >::type = 0 > SimpleTensor depth_convert(const SimpleTensor &src, DataType dt_out, ConvertPolicy policy, uint32_t shift); } // namespace reference } // namespace validation -- cgit v1.2.1