From 3808b42d4e9be84f069c226727eaecd768ad1006 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EB=B0=95=EC=A2=85=ED=98=84/=EB=8F=99=EC=9E=91=EC=A0=9C?= =?utf8?q?=EC=96=B4Lab=28SR=29/Senior=20Engineer/=EC=82=BC=EC=84=B1?= =?utf8?q?=EC=A0=84=EC=9E=90?= Date: Thu, 5 Apr 2018 11:01:17 +0900 Subject: [PATCH] Introduce 'nnfw::util::fp32' namespace (#445) This commit introduces 'nnfw::util::fp32' namespace which includes various helps for handling floating-pointer numbers. Signed-off-by: Jonghyun Park --- include/util/fp32.h | 40 ++++++++++++++++++++++++++++++++++ tools/nnapi_test/src/nnapi_test.cc | 27 +++-------------------- tools/nnapi_unittests/tests/conv_1.cpp | 6 ++++- 3 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 include/util/fp32.h diff --git a/include/util/fp32.h b/include/util/fp32.h new file mode 100644 index 0000000..c916865 --- /dev/null +++ b/include/util/fp32.h @@ -0,0 +1,40 @@ +#ifndef __NNFW_UTIL_FP32_H__ +#define __NNFW_UTIL_FP32_H__ + +#include +#include + +namespace nnfw +{ +namespace util +{ +namespace fp32 +{ + +inline float relative_diff(float lhs, float rhs) +{ + const auto diff = std::fabs(lhs - rhs); + const auto base = std::max(std::fabs(lhs), std::fabs(rhs)); + + return diff / base; +} + +bool epsilon_equal(float expected, float obtained) +{ + if (std::isnan(expected) && std::isnan(obtained)) + { + return true; + } + + // Let's use relative epsilon comparision + const auto diff = std::fabs(expected - obtained); + const auto max = std::max(std::fabs(expected), std::fabs(obtained)); + + return diff <= max * FLT_EPSILON; +} + +} // namespace fp32 +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_FP32_H__ diff --git a/tools/nnapi_test/src/nnapi_test.cc b/tools/nnapi_test/src/nnapi_test.cc index b5c71d0..c7d0009 100644 --- a/tools/nnapi_test/src/nnapi_test.cc +++ b/tools/nnapi_test/src/nnapi_test.cc @@ -2,6 +2,7 @@ #include "tensorflow/contrib/lite/model.h" #include "util/environment.h" +#include "util/fp32.h" #include #include @@ -12,14 +13,6 @@ using namespace tflite; using namespace tflite::ops::builtin; -inline float diff_ratio(float lhs, float rhs) -{ - const auto diff = std::fabs(lhs - rhs); - const auto max = std::max(std::fabs(lhs), std::fabs(rhs)); - - return diff / max; -} - inline void check(const TfLiteStatus &status) { assert(status != kTfLiteError); } std::unique_ptr build_interpreter(const FlatBufferModel &model, bool use_nnapi) @@ -177,21 +170,7 @@ int main(const int argc, char **argv) assert(pure->inputs() == delegated->inputs()); assert(pure->outputs() == delegated->outputs()); - auto compare_fn = [](float expected, float obtained) - { - if ( std::isnan(expected) && std::isnan(obtained) ) - { - return true; - } - - // Let's use relative epsilon comparision - const auto diff = std::fabs(expected - obtained); - const auto max = std::max(std::fabs(expected), std::fabs(obtained)); - - return diff <= max * FLT_EPSILON; - }; - - TfLiteTensorComparator comparator(compare_fn); + TfLiteTensorComparator comparator(nnfw::util::fp32::epsilon_equal); for (const auto &id : pure->outputs()) { @@ -212,7 +191,7 @@ int main(const int argc, char **argv) std::cout << " Diff at offset " << diff.offset << std::endl; std::cout << " expected: " << diff.expected << std::endl; std::cout << " obtained: " << diff.obtained << std::endl; - std::cout << " relative diff: " << diff_ratio(diff.expected, diff.obtained) << std::endl; + std::cout << " relative diff: " << nnfw::util::fp32::relative_diff(diff.expected, diff.obtained) << std::endl; } } diff --git a/tools/nnapi_unittests/tests/conv_1.cpp b/tools/nnapi_unittests/tests/conv_1.cpp index 458ac21..d82f727 100644 --- a/tools/nnapi_unittests/tests/conv_1.cpp +++ b/tools/nnapi_unittests/tests/conv_1.cpp @@ -8,6 +8,7 @@ #include "util/feature/RandomObject.h" #include "util/feature/Reader.h" #include "util/kernel/RandomObject.h" +#include "util/fp32.h" #include #include @@ -289,11 +290,14 @@ int main(int argc, char **argv) const auto value_from_interp = interp_output.at(ch, row, col); const auto value_from_NNAPI = nnapi_output.at(ch, row, col); - if (value_from_interp != value_from_NNAPI) + if (!nnfw::util::fp32::epsilon_equal(value_from_interp, value_from_NNAPI)) { + const auto rdiff = nnfw::util::fp32::relative_diff(value_from_interp, value_from_NNAPI); + std::cerr << "Diff at (ch: " << ch << ", row: " << row << ", col: " << col << ")" << std::endl; std::cerr << " Value from interpreter: " << value_from_interp << std::endl; std::cerr << " Value from NNAPI: " << value_from_NNAPI << std::endl; + std::cerr << " Relative difference: " << rdiff << std::endl; } } } -- 2.7.4