From 4cf0fe385b934de95c022cae4a2c400d0d52377d Mon Sep 17 00:00:00 2001 From: Narumol Prangnawarat Date: Fri, 18 Dec 2020 16:13:06 +0000 Subject: IVGCVSW-5625 Add support for Float16 to Delegate * Float16 unit tests for Reshape * Remove unsupported data type from Pad Signed-off-by: Narumol Prangnawarat Change-Id: Ib1804bb6e708a0552fb40d05fe8a6511936f9793 --- delegate/CMakeLists.txt | 11 +++++- delegate/src/Pad.hpp | 3 -- delegate/src/test/PadTestHelper.hpp | 2 +- delegate/src/test/RedefineTestHelper.hpp | 25 +----------- delegate/src/test/ReshapeTest.cpp | 68 ++++++++++++++++++++++++++++++++ delegate/src/test/TestUtils.cpp | 67 ++++++++++++++++++++++++++++++- delegate/src/test/TestUtils.hpp | 13 ++++++ 7 files changed, 159 insertions(+), 30 deletions(-) (limited to 'delegate') diff --git a/delegate/CMakeLists.txt b/delegate/CMakeLists.txt index c052be2e51..9f64353d9a 100644 --- a/delegate/CMakeLists.txt +++ b/delegate/CMakeLists.txt @@ -93,6 +93,15 @@ target_compile_options(flatbuffer_headers INTERFACE -Wno-sign-conversion) target_link_libraries(armnnDelegate PUBLIC flatbuffer_headers) +# Add libraries from armnn third-party libraries +# Third-party header files are not warning clean +# We can't change compilation flags on header files directly, so we need to add them to an interface library first +add_library(thirdparty_headers INTERFACE) +target_include_directories(thirdparty_headers INTERFACE $ + $) + +target_compile_options(thirdparty_headers INTERFACE -Wno-old-style-cast) + option(BUILD_UNIT_TESTS "Build unit tests" ON) if(BUILD_UNIT_TESTS) set(armnnDelegate_unittest_sources) @@ -140,7 +149,7 @@ if(BUILD_UNIT_TESTS) target_include_directories(DelegateUnitTests PRIVATE third-party) # Add half library from armnn third-party libraries - target_include_directories(DelegateUnitTests PRIVATE ${ARMNN_SOURCE_DIR}/third-party) + target_link_libraries(DelegateUnitTests PRIVATE thirdparty_headers) target_link_libraries(DelegateUnitTests PRIVATE armnnDelegate) target_link_libraries(DelegateUnitTests PRIVATE Armnn::armnnUtils) diff --git a/delegate/src/Pad.hpp b/delegate/src/Pad.hpp index 6149819950..431b8d33f2 100644 --- a/delegate/src/Pad.hpp +++ b/delegate/src/Pad.hpp @@ -98,9 +98,6 @@ TfLiteStatus VisitPadOperator(DelegateData& delegateData, case kTfLiteInt8: descriptor.m_PadValue = tflite::GetTensorData(&tfLitepaddingValue)[0]; break; - case kTfLiteInt16: - descriptor.m_PadValue = tflite::GetTensorData(&tfLitepaddingValue)[0]; - break; default: TF_LITE_MAYBE_KERNEL_LOG( tfLiteContext, diff --git a/delegate/src/test/PadTestHelper.hpp b/delegate/src/test/PadTestHelper.hpp index 7221dedb20..025d13df67 100644 --- a/delegate/src/test/PadTestHelper.hpp +++ b/delegate/src/test/PadTestHelper.hpp @@ -73,7 +73,7 @@ std::vector CreatePadTfLiteModel( buffers.push_back( CreateBuffer(flatBufferBuilder, flatBufferBuilder.CreateVector(reinterpret_cast(paddingDim.data()), - sizeof(int32_t) * paddingDim.size()))); + sizeof(int32_t) * paddingDim.size()))); buffers.push_back(CreateBuffer(flatBufferBuilder, flatBufferBuilder.CreateVector({}))); std::vector operatorInputs; diff --git a/delegate/src/test/RedefineTestHelper.hpp b/delegate/src/test/RedefineTestHelper.hpp index ca8246c3a6..6f061572b4 100644 --- a/delegate/src/test/RedefineTestHelper.hpp +++ b/delegate/src/test/RedefineTestHelper.hpp @@ -136,7 +136,7 @@ void RedefineTest(tflite::BuiltinOperator redefineOperatorCode, tflite::TensorType tensorType, const std::vector& backends, const std::vector& inputShape, - const std::vector& outputShape, + std::vector& outputShape, std::vector& inputValues, std::vector& expectedOutputValues, std::vector& targetShape, @@ -186,28 +186,7 @@ void RedefineTest(tflite::BuiltinOperator redefineOperatorCode, CHECK(tfLiteInterpreter->Invoke() == kTfLiteOk); CHECK(armnnDelegateInterpreter->Invoke() == kTfLiteOk); - auto tfLiteDelegateOutputId = tfLiteInterpreter->outputs()[0]; - auto tfLiteDelegateOutputData = tfLiteInterpreter->typed_tensor(tfLiteDelegateOutputId); - auto tfLiteDelegateOutputTensor = tfLiteInterpreter->tensor(tfLiteDelegateOutputId); - auto armnnDelegateOutputId = armnnDelegateInterpreter->outputs()[0]; - auto armnnDelegateOutputData = armnnDelegateInterpreter->typed_tensor(armnnDelegateOutputId); - auto armnnDelegateOutputTensor = armnnDelegateInterpreter->tensor(armnnDelegateOutputId); - - CHECK(outputShape.size() == tfLiteDelegateOutputTensor->dims->size); - CHECK(outputShape.size() == armnnDelegateOutputTensor->dims->size); - - for (size_t i = 0; i < static_cast(tfLiteDelegateOutputTensor->dims->size); i++) - { - CHECK(outputShape[i] == armnnDelegateOutputTensor->dims->data[i]); - CHECK(tfLiteDelegateOutputTensor->dims->data[i] == armnnDelegateOutputTensor->dims->data[i]); - } - - for (size_t i = 0; i < expectedOutputValues.size(); i++) - { - CHECK(expectedOutputValues[i] == armnnDelegateOutputData[i]); - CHECK(tfLiteDelegateOutputData[i] == expectedOutputValues[i]); - CHECK(tfLiteDelegateOutputData[i] == armnnDelegateOutputData[i]); - } + armnnDelegate::CompareOutputData(tfLiteInterpreter, armnnDelegateInterpreter, outputShape, expectedOutputValues); } } // anonymous namespace \ No newline at end of file diff --git a/delegate/src/test/ReshapeTest.cpp b/delegate/src/test/ReshapeTest.cpp index 715fed6279..11449e29b8 100644 --- a/delegate/src/test/ReshapeTest.cpp +++ b/delegate/src/test/ReshapeTest.cpp @@ -12,6 +12,10 @@ #include +#include + +using Half = half_float::half; + namespace armnnDelegate { @@ -41,6 +45,34 @@ void ReshapeSimpleTest(std::vector& backends, bool useOption = useOption); } +using namespace half_float::literal; + +void ReshapeSimpleFloat16Test(std::vector& backends, bool useOption = true) +{ + // Set input data + std::vector inputShape { 1, 3, 4, 1 }; + std::vector outputShape { 1, 3, 2, 2 }; + std::vector targetShape { 1, 3, 2, 2 }; + + std::vector inputValues = { 5._h, -8._h, -10._h, 7._h, + 8._h, 12._h, -15._h, 2._h, + 3._h, -4._h, -1._h, -11._h }; + + std::vector expectedOutputValues = { 5._h, -8._h, -10._h, 7._h, + 8._h, 12._h, -15._h, 2._h, + 3._h, -4._h, -1._h, -11._h }; + + RedefineTest(tflite::BuiltinOperator_RESHAPE, + ::tflite::TensorType_FLOAT16, + backends, + inputShape, + outputShape, + inputValues, + expectedOutputValues, + targetShape, + useOption); +} + void ReshapeReduceDimTest(std::vector& backends, bool useOption = true) { // Set input data @@ -242,6 +274,12 @@ TEST_CASE ("Reshape_Uint8_GpuAcc_Test") ReshapeUint8Test(backends); } +TEST_CASE ("Reshape_Float16_GpuAcc_Test") +{ + std::vector backends = { armnn::Compute::GpuAcc }; + ReshapeSimpleFloat16Test(backends); +} + TEST_CASE ("Reshape_Simple_ShapeTensor_GpuAcc_Test") { std::vector backends = { armnn::Compute::GpuAcc }; @@ -278,6 +316,12 @@ TEST_CASE ("Reshape_Uint8_ShapeTensor_GpuAcc_Test") ReshapeUint8Test(backends, false); } +TEST_CASE ("Reshape_Float16_ShapeTensor_GpuAcc_Test") +{ + std::vector backends = { armnn::Compute::GpuAcc }; + ReshapeSimpleFloat16Test(backends, false); +} + } // TEST_SUITE("Reshape_GpuAccTests") TEST_SUITE("Reshape_CpuAccTests") @@ -319,6 +363,12 @@ TEST_CASE ("Reshape_Uint8_CpuAcc_Test") ReshapeUint8Test(backends); } +TEST_CASE ("Reshape_Float16_CpuAcc_Test") +{ + std::vector backends = { armnn::Compute::CpuAcc }; + ReshapeSimpleFloat16Test(backends); +} + TEST_CASE ("Reshape_Simple_ShapeTensor_CpuAcc_Test") { std::vector backends = { armnn::Compute::CpuAcc }; @@ -355,6 +405,12 @@ TEST_CASE ("Reshape_Uint8_ShapeTensor_CpuAcc_Test") ReshapeUint8Test(backends, false); } +TEST_CASE ("Reshape_Float16_ShapeTensor_CpuAcc_Test") +{ + std::vector backends = { armnn::Compute::CpuAcc }; + ReshapeSimpleFloat16Test(backends, false); +} + } // TEST_SUITE("Reshape_CpuAccTests") TEST_SUITE("Reshape_CpuRefTests") @@ -402,6 +458,12 @@ TEST_CASE ("Reshape_Int16_CpuRef_Test") ReshapeInt16Test(backends); } +TEST_CASE ("Reshape_Float16_CpuRef_Test") +{ + std::vector backends = { armnn::Compute::CpuRef }; + ReshapeSimpleFloat16Test(backends); +} + TEST_CASE ("Reshape_Simple_ShapeTensor_CpuRef_Test") { std::vector backends = { armnn::Compute::CpuRef }; @@ -444,6 +506,12 @@ TEST_CASE ("Reshape_Int16_ShapeTensor_CpuRef_Test") ReshapeInt16Test(backends, false); } +TEST_CASE ("Reshape_Float16_ShapeTensor_CpuRef_Test") +{ + std::vector backends = { armnn::Compute::CpuRef }; + ReshapeSimpleFloat16Test(backends, false); +} + } // TEST_SUITE("Reshape_CpuRefTests") } // namespace armnnDelegate \ No newline at end of file diff --git a/delegate/src/test/TestUtils.cpp b/delegate/src/test/TestUtils.cpp index 31c05a678d..2787147639 100644 --- a/delegate/src/test/TestUtils.cpp +++ b/delegate/src/test/TestUtils.cpp @@ -8,8 +8,6 @@ namespace armnnDelegate { - - void CompareData(bool tensor1[], bool tensor2[], size_t tensorSize) { auto compareBool = [](auto a, auto b) {return (((a == 0) && (b == 0)) || ((a != 0) && (b != 0)));}; @@ -63,4 +61,69 @@ void CompareData(int8_t tensor1[], int8_t tensor2[], size_t tensorSize) } } +void CompareData(Half tensor1[], Half tensor2[], size_t tensorSize) +{ + for (size_t i = 0; i < tensorSize; i++) + { + CHECK(tensor1[i] == doctest::Approx( tensor2[i] )); + } +} + +void CompareData(TfLiteFloat16 tensor1[], TfLiteFloat16 tensor2[], size_t tensorSize) +{ + for (size_t i = 0; i < tensorSize; i++) + { + CHECK(tensor1[i].data == tensor2[i].data); + } +} + +void CompareData(TfLiteFloat16 tensor1[], Half tensor2[], size_t tensorSize) +{ + for (size_t i = 0; i < tensorSize; i++) + { + CHECK(tensor1[i].data == half_float::detail::float2half(tensor2[i])); + } +} + +template <> +void CompareOutputData(std::unique_ptr& tfLiteInterpreter, + std::unique_ptr& armnnDelegateInterpreter, + std::vector& expectedOutputShape, + std::vector& expectedOutputValues, + unsigned int outputIndex) +{ + auto tfLiteDelegateOutputId = tfLiteInterpreter->outputs()[outputIndex]; + auto tfLiteDelegateOutputTensor = tfLiteInterpreter->tensor(tfLiteDelegateOutputId); + auto tfLiteDelegateOutputData = tfLiteInterpreter->typed_tensor(tfLiteDelegateOutputId); + auto armnnDelegateOutputId = armnnDelegateInterpreter->outputs()[outputIndex]; + auto armnnDelegateOutputTensor = armnnDelegateInterpreter->tensor(armnnDelegateOutputId); + auto armnnDelegateOutputData = armnnDelegateInterpreter->typed_tensor(armnnDelegateOutputId); + + CHECK(expectedOutputShape.size() == tfLiteDelegateOutputTensor->dims->size); + CHECK(expectedOutputShape.size() == armnnDelegateOutputTensor->dims->size); + + for (size_t i = 0; i < expectedOutputShape.size(); i++) + { + CHECK(armnnDelegateOutputTensor->dims->data[i] == expectedOutputShape[i]); + CHECK(tfLiteDelegateOutputTensor->dims->data[i] == expectedOutputShape[i]); + CHECK(tfLiteDelegateOutputTensor->dims->data[i] == armnnDelegateOutputTensor->dims->data[i]); + } + + armnnDelegate::CompareData(armnnDelegateOutputData, expectedOutputValues.data(), expectedOutputValues.size()); + armnnDelegate::CompareData(tfLiteDelegateOutputData, expectedOutputValues.data(), expectedOutputValues.size()); + armnnDelegate::CompareData(tfLiteDelegateOutputData, armnnDelegateOutputData, expectedOutputValues.size()); +} + +template <> +void FillInput(std::unique_ptr& interpreter, int inputIndex, std::vector& inputValues) +{ + auto tfLiteDelegateInputId = interpreter->inputs()[inputIndex]; + auto tfLiteDelageInputData = interpreter->typed_tensor(tfLiteDelegateInputId); + for (unsigned int i = 0; i < inputValues.size(); ++i) + { + tfLiteDelageInputData[i].data = half_float::detail::float2half(inputValues[i]); + + } +} + } // namespace armnnDelegate \ No newline at end of file diff --git a/delegate/src/test/TestUtils.hpp b/delegate/src/test/TestUtils.hpp index b165920762..ad7600d27e 100644 --- a/delegate/src/test/TestUtils.hpp +++ b/delegate/src/test/TestUtils.hpp @@ -5,10 +5,15 @@ #pragma once +#include #include #include +#include + +using Half = half_float::half; + namespace armnnDelegate { @@ -43,6 +48,14 @@ void CompareData(uint8_t tensor1[], uint8_t tensor2[], size_t tensorSize); /// Can be used to compare int16_t data coming from a tflite interpreter with a tolerance of 1 void CompareData(int16_t tensor1[], int16_t tensor2[], size_t tensorSize); +/// Can be used to compare Half (Float16) data with a tolerance of limit_of_float*100 +void CompareData(Half tensor1[], Half tensor2[], size_t tensorSize); + +/// Can be used to compare TfLiteFloat16 data coming from a tflite interpreter +void CompareData(TfLiteFloat16 tensor1[], TfLiteFloat16 tensor2[], size_t tensorSize); + +/// Can be used to compare Half (Float16) data and TfLiteFloat16 data coming from a tflite interpreter +void CompareData(TfLiteFloat16 tensor1[], Half tensor2[], size_t tensorSize); /// Can be used to compare the output tensor shape and values /// from armnnDelegateInterpreter and tfLiteInterpreter. -- cgit v1.2.1