From 6eb3f314b8df62fb62542b2730d539c459a0d6d6 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: Wed, 4 Apr 2018 15:42:02 +0900 Subject: [PATCH] Introduce TfLiteFeatureView (#412) This commit implements TfLiteFeatureView in NN API Unittest (conv_1). Signed-off-by: Jonghyun Park --- tools/nnapi_unittests/tests/conv_1.cpp | 69 +++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/tools/nnapi_unittests/tests/conv_1.cpp b/tools/nnapi_unittests/tests/conv_1.cpp index 25b140e..7841c2a 100644 --- a/tools/nnapi_unittests/tests/conv_1.cpp +++ b/tools/nnapi_unittests/tests/conv_1.cpp @@ -6,12 +6,72 @@ #include "env.h" #include "util/feature/RandomObject.h" +#include "util/feature/Reader.h" #include +#include using namespace tflite; using namespace tflite::ops::builtin; +class TfLiteOutputIndex +{ +public: + TfLiteOutputIndex(int index) : _index(index) + { + + } + +public: + int asInt(void) const { return _index; } + +private: + int _index; +}; + +template class TfLiteFeatureView; + +template<> class TfLiteFeatureView : public nnfw::util::feature::Reader +{ +public: + TfLiteFeatureView(tflite::Interpreter &interp, const TfLiteOutputIndex &index); + +public: + float at(uint32_t ch, uint32_t row, uint32_t col) const; + +private: + nnfw::util::feature::Shape _shape; + float *_base; +}; + +TfLiteFeatureView::TfLiteFeatureView(tflite::Interpreter &interp, const TfLiteOutputIndex &index) +{ + const auto tensor_index = interp.outputs().at(index.asInt()); + auto tensor_ptr = interp.tensor(tensor_index); + + assert(tensor_ptr->type == kTfLiteFloat32); + assert(tensor_ptr->dims->size == 4); + assert(tensor_ptr->dims->data[0] == 1); + + _shape.C = tensor_ptr->dims->data[3]; + _shape.H = tensor_ptr->dims->data[1]; + _shape.W = tensor_ptr->dims->data[2]; + + _base = interp.typed_tensor(tensor_index); +} + +float TfLiteFeatureView::at(uint32_t ch, uint32_t row, uint32_t col) const +{ + uint32_t element_offset = 0; + + // TensorFlow Lite assumes that NHWC ordering for tessor + element_offset += row * _shape.W * _shape.C; + element_offset += col * _shape.C; + element_offset += ch; + + return *(_base + element_offset); +} + int main(int argc, char **argv) { #define INT_VALUE(NAME, VALUE) IntVar NAME##_Value(#NAME, VALUE); @@ -192,7 +252,8 @@ int main(int argc, char **argv) // Compare OFM { - uint32_t off = 0; + const TfLiteFeatureView interp_output{pure, TfLiteOutputIndex{0}}; + const TfLiteFeatureView nnapi_output{delegated, TfLiteOutputIndex{0}}; for (uint32_t row = 0; row < OFM_H; ++row) { @@ -200,8 +261,8 @@ int main(int argc, char **argv) { for (uint32_t ch = 0; ch < kernel.shape().N; ++ch) { - const auto value_from_interp = pure.typed_output_tensor(0)[off]; - const auto value_from_NNAPI = delegated.typed_output_tensor(0)[off]; + 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) { @@ -209,8 +270,6 @@ int main(int argc, char **argv) std::cerr << " Value from interpreter: " << value_from_interp << std::endl; std::cerr << " Value from NNAPI: " << value_from_NNAPI << std::endl; } - - off += 1; } } } -- 2.7.4