diff options
Diffstat (limited to 'include/util')
35 files changed, 2416 insertions, 0 deletions
diff --git a/include/util/EnvVar.h b/include/util/EnvVar.h new file mode 100644 index 000000000..5512fedbd --- /dev/null +++ b/include/util/EnvVar.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_ENV_VAR__ +#define __NNFW_UTIL_ENV_VAR__ + +#include <algorithm> +#include <array> +#include <cstdlib> +#include <string> + + +namespace nnfw +{ +namespace util +{ + +class EnvVar +{ +public: + EnvVar(const std::string &key) + { + const char *value = std::getenv(key.c_str()); + if (value == nullptr) + { + // An empty string is considered as an empty value + _value = ""; + } + else + { + _value = value; + } + } + + std::string asString(const std::string &def) const + { + if (_value.empty()) + return def; + return _value; + } + + bool asBool(bool def) const + { + if (_value.empty()) + return def; + static const std::array<std::string, 5> false_list{"0", "OFF", "FALSE", "N", "NO"}; + return std::find(false_list.begin(), false_list.end(), _value); + } + + int asInt(int def) const + { + if (_value.empty()) + return def; + return std::stoi(_value); + } + +private: + std::string _value; +}; + +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_ENV_VAR__ diff --git a/include/util/benchmark.h b/include/util/benchmark.h new file mode 100644 index 000000000..b07656c88 --- /dev/null +++ b/include/util/benchmark.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_BENCHMARK_H__ +#define __NNFW_UTIL_BENCHMARK_H__ + +#include <chrono> + +namespace nnfw +{ +namespace util +{ +// Benckmark support +namespace benchmark +{ + +template <typename T> class Accumulator +{ +public: + Accumulator(T &ref) : _ref(ref) + { + // DO NOTHING + } + +public: + T &operator()(void) { return _ref; } + +private: + T &_ref; +}; + +template <typename T, typename Callable> +Accumulator<T> &operator<<(Accumulator<T> &&acc, Callable cb) +{ + auto begin = std::chrono::steady_clock::now(); + cb(); + auto end = std::chrono::steady_clock::now(); + + acc() += std::chrono::duration_cast<T>(end - begin); + + return acc; +} + +template <typename T> Accumulator<T> measure(T &out) { return Accumulator<T>(out); } + +} // namespace benchmark +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_BENCHMARK_H__ diff --git a/include/util/environment.h b/include/util/environment.h new file mode 100644 index 000000000..84df65f95 --- /dev/null +++ b/include/util/environment.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __UTIL_ENVIRONMENT_H__ +#define __UTIL_ENVIRONMENT_H__ + +namespace nnfw +{ +namespace util +{ + +int get_env_int(const char *name, int defaultValue = 0); +bool get_env_bool(const char *name, bool defaultValue = false); +} +} + +#include <string> + +namespace nnfw +{ +namespace util +{ +namespace env +{ + +template <typename T> struct Accessor +{ + virtual ~Accessor() = default; + + virtual bool access(T &out) const = 0; +}; + +class IntAccessor : public Accessor<int> +{ +public: + IntAccessor(const std::string &tag); + +public: + bool access(int &out) const override; + +private: + std::string _tag; +}; + +class FloatAccessor : public Accessor<float> +{ +public: + FloatAccessor(const std::string &tag); + +public: + bool access(float &out) const override; + +private: + std::string _tag; +}; + +} // namespace env +} // namespace util +} // namespace nnfw + +#endif // __UTIL_ENVIRONMENT_H__ diff --git a/include/util/feature/Index.h b/include/util/feature/Index.h new file mode 100644 index 000000000..83b51f8a6 --- /dev/null +++ b/include/util/feature/Index.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_FEATURE_INDEX_H__ +#define __NNFW_UTIL_FEATURE_INDEX_H__ + +#include <cstdint> + +namespace nnfw +{ +namespace util +{ +namespace feature +{ + +class Index +{ +public: + Index() = default; + +public: + Index(int32_t ch, int32_t row, int32_t col) : _batch{1}, _ch{ch}, _row{row}, _col{col} + { + // DO NOTHING + } + Index(int32_t batch, int32_t ch, int32_t row, int32_t col) : _batch{batch}, _ch{ch}, _row{row}, _col{col} + { + // DO NOTHING + } + +public: + int32_t batch(void) const { return _batch; } + int32_t ch(void) const { return _ch; } + int32_t row(void) const { return _row; } + int32_t col(void) const { return _col; } + +public: + int32_t &batch(void) { return _batch; } + int32_t &ch(void) { return _ch; } + int32_t &row(void) { return _row; } + int32_t &col(void) { return _col; } + +private: + int32_t _batch; + int32_t _ch; + int32_t _row; + int32_t _col; +}; + +} // namespace feature +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_FEATURE_INDEX_H__ diff --git a/include/util/feature/IndexIterator.h b/include/util/feature/IndexIterator.h new file mode 100644 index 000000000..e2a7196e8 --- /dev/null +++ b/include/util/feature/IndexIterator.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_FEATURE_INDEX_ITERATOR_H__ +#define __NNFW_UTIL_FEATURE_INDEX_ITERATOR_H__ + +#include "util/feature/Shape.h" + +namespace nnfw +{ +namespace util +{ +namespace feature +{ + +class IndexIterator +{ +public: + IndexIterator(const Shape &shape) : _shape{shape} + { + // DO NOTHING + } + +public: + template <typename Callable> IndexIterator &iter(Callable cb) + { + for (int32_t batch = 0; batch < _shape.N; ++batch) + { + for (int32_t ch = 0; ch < _shape.C; ++ch) + { + for (int32_t row = 0; row < _shape.H; ++row) + { + for (int32_t col = 0; col < _shape.W; ++col) + { + cb(batch, ch, row, col); + } + } + } + } + + return (*this); + } + +private: + const Shape _shape; +}; + +static inline IndexIterator iterate(const Shape &shape) { return IndexIterator{shape}; } + +template <typename Callable> IndexIterator &operator<<(IndexIterator &&it, Callable cb) +{ + return it.iter(cb); +} + +} // namespace feature +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_FEATURE_INDEX_ITERATOR_H__ diff --git a/include/util/feature/Object.h b/include/util/feature/Object.h new file mode 100644 index 000000000..ce66c2437 --- /dev/null +++ b/include/util/feature/Object.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_FEATURE_OBJECT_H__ +#define __NNFW_UTIL_FEATURE_OBJECT_H__ + +#include "util/feature/Shape.h" +#include "util/feature/Index.h" +#include "util/feature/Reader.h" + +#include <vector> + +namespace nnfw +{ +namespace util +{ +namespace feature +{ + +template <typename T> class Object final : public Reader<T> +{ +public: + using Generator = std::function<T(const Shape &shape, const Index &index)>; + +public: + Object(const Shape &shape, const Generator &fn) : _shape{shape} + { + _value.resize(_shape.C * _shape.H * _shape.W); + + for (int32_t ch = 0; ch < _shape.C; ++ch) + { + for (int32_t row = 0; row < _shape.H; ++row) + { + for (int32_t col = 0; col < _shape.W; ++col) + { + _value.at(offsetOf(ch, row, col)) = fn(_shape, Index{ch, row, col}); + } + } + } + } + +public: + const Shape &shape(void) const { return _shape; } + +public: + T at(uint32_t ch, uint32_t row, uint32_t col) const override + { + return _value.at(offsetOf(ch, row, col)); + } + +private: + uint32_t offsetOf(uint32_t ch, uint32_t row, uint32_t col) const + { + return ch * _shape.H * _shape.W + row * _shape.W + col; + } + +private: + Shape _shape; + std::vector<T> _value; +}; + +} // namespace feature +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_FEATURE_OBJECT_H__ diff --git a/include/util/feature/Reader.h b/include/util/feature/Reader.h new file mode 100644 index 000000000..f870f7d11 --- /dev/null +++ b/include/util/feature/Reader.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_FEATURE_READER_H__ +#define __NNFW_UTIL_FEATURE_READER_H__ + +#include <cstdint> + +namespace nnfw +{ +namespace util +{ +namespace feature +{ + +template <typename T> struct Reader +{ + virtual ~Reader() = default; + + virtual T at(uint32_t ch, uint32_t row, uint32_t col) const = 0; + virtual T at(uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) const = 0; +}; + +} // namespace feature +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_FEATURE_READER_H__ diff --git a/include/util/feature/Shape.h b/include/util/feature/Shape.h new file mode 100644 index 000000000..2a2c59eed --- /dev/null +++ b/include/util/feature/Shape.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_FEATURE_SHAPE_H__ +#define __NNFW_UTIL_FEATURE_SHAPE_H__ + +#include <cstdint> + +namespace nnfw +{ +namespace util +{ +namespace feature +{ + +struct Shape +{ + int32_t N; // Batch + int32_t C; // Depth + int32_t H; // Height + int32_t W; // Width + + Shape() = default; + Shape(int32_t depth, int32_t height, int32_t width) : N{1}, C{depth}, H{height}, W{width} + { + // DO NOTHING + } + Shape(int32_t batch, int32_t depth, int32_t height, int32_t width) : N{batch}, C{depth}, H{height}, W{width} + { + // DO NOTHING + } +}; + +} // namespace feature +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_FEATURE_H__ diff --git a/include/util/feature/TextFormatter.h b/include/util/feature/TextFormatter.h new file mode 100644 index 000000000..de5c4c13a --- /dev/null +++ b/include/util/feature/TextFormatter.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_FEATURE_TEXT_FORMATTER_H__ +#define __NNFW_UTIL_FEATURE_TEXT_FORMATTER_H__ + +#include "util/feature/Shape.h" +#include "util/feature/Reader.h" + +#include <ostream> +#include <iomanip> +#include <limits> + +namespace nnfw +{ +namespace util +{ +namespace feature +{ + +template <typename T> class TextFormatter +{ +public: + TextFormatter(const Shape &shape, const Reader<T> &data) : _shape(shape), _data(data) + { + // DO NOTHING + } + +public: + const Shape &shape(void) const { return _shape; } + const Reader<T> &data(void) const { return _data; } + +private: + const Shape &_shape; + const Reader<T> &_data; +}; + +template <typename T> std::ostream &operator<<(std::ostream &os, const TextFormatter<T> &fmt) +{ + const auto &shape = fmt.shape(); + + for (uint32_t ch = 0; ch < shape.C; ++ch) + { + os << " Channel " << ch << ":" << std::endl; + for (uint32_t row = 0; row < shape.H; ++row) + { + os << " "; + for (uint32_t col = 0; col < shape.W; ++col) + { + const auto value = fmt.data().at(ch, row, col); + os << std::right; + os << std::fixed; + os << std::setw(std::numeric_limits<T>::digits10 + 2); + os << std::setprecision(5); + os << value; + os << " "; + } + os << std::endl; + } + } + + return os; +} + +} // namespace feature +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_FEATURE_TEXT_FORMATTER_H__ diff --git a/include/util/fp32.h b/include/util/fp32.h new file mode 100644 index 000000000..604435470 --- /dev/null +++ b/include/util/fp32.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_FP32_H__ +#define __NNFW_UTIL_FP32_H__ + +#include <cmath> +#include <cfloat> +#include <algorithm> +#include <cstdint> + +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; +} + +inline bool epsilon_equal(float expected, float obtained, uint32_t tolerance = 1) +{ + 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 * tolerance); +} + +inline bool absolute_epsilon_equal(float expected, float obtained, float tolerance = 0.001) +{ + if (std::isnan(expected) && std::isnan(obtained)) + { + return true; + } + + // Let's use absolute epsilon comparision + const auto diff = std::fabs(expected - obtained); + + return diff <= tolerance; +} + +} // namespace fp32 +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_FP32_H__ diff --git a/include/util/kernel/IndexIterator.h b/include/util/kernel/IndexIterator.h new file mode 100644 index 000000000..d01656447 --- /dev/null +++ b/include/util/kernel/IndexIterator.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_KERNEL_INDEX_ITERATOR_H__ +#define __NNFW_UTIL_KERNEL_INDEX_ITERATOR_H__ + +#include "util/kernel/Shape.h" + +namespace nnfw +{ +namespace util +{ +namespace kernel +{ + +class IndexIterator +{ +public: + IndexIterator(const Shape &shape) : _shape{shape} + { + // DO NOTHING + } + +public: + template <typename Callable> IndexIterator &iter(Callable cb) + { + for (int32_t nth = 0; nth < _shape.N; ++nth) + { + for (int32_t ch = 0; ch < _shape.C; ++ch) + { + for (int32_t row = 0; row < _shape.H; ++row) + { + for (int32_t col = 0; col < _shape.W; ++col) + { + cb(nth, ch, row, col); + } + } + } + } + + return (*this); + } + +private: + const Shape _shape; +}; + +inline IndexIterator iterate(const Shape &shape) { return IndexIterator{shape}; } + +template <typename Callable> IndexIterator &operator<<(IndexIterator &&it, Callable cb) +{ + return it.iter(cb); +} + +} // namespace kernel +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_FEATURE_INDEX_ITERATOR_H__ diff --git a/include/util/kernel/RandomObject.h b/include/util/kernel/RandomObject.h new file mode 100644 index 000000000..d6fca9a66 --- /dev/null +++ b/include/util/kernel/RandomObject.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_KERNEL_RANDOM_OBJECT_H__ +#define __NNFW_UTIL_KERNEL_RANDOM_OBJECT_H__ + +#include "util/kernel/Shape.h" +#include "util/kernel/Reader.h" + +#include <vector> + +namespace nnfw +{ +namespace util +{ +namespace kernel +{ + +template <typename T> class RandomObject final : public Reader<T> +{ +public: + RandomObject(const Shape &shape) : _shape{shape} + { + const uint32_t size = _shape.N * _shape.C * _shape.H * _shape.W; + + // TODO Use random number + for (uint32_t off = 0; off < size; ++off) + { + _value.emplace_back(static_cast<float>(off)); + } + } + +public: + const Shape &shape(void) const { return _shape; } + +public: + T at(uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) const override + { + uint32_t index = 0; + + index += nth * _shape.C * _shape.H * _shape.W; + index += ch * _shape.H * _shape.W; + index += row * _shape.W; + index += col; + + return _value.at(index); + } + +private: + const Shape _shape; + std::vector<T> _value; +}; + +} // namespace kernel +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_KERNEL_RANDOM_OBJECT_H__ diff --git a/include/util/kernel/Reader.h b/include/util/kernel/Reader.h new file mode 100644 index 000000000..9d8f33ad6 --- /dev/null +++ b/include/util/kernel/Reader.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_KERNEL_READER_H__ +#define __NNFW_UTIL_KERNEL_READER_H__ + +#include <cstdint> + +namespace nnfw +{ +namespace util +{ +namespace kernel +{ + +template <typename T> struct Reader +{ + virtual ~Reader() = default; + + virtual T at(uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) const = 0; +}; + +} // namespace kernel +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_KERNEL_READER_H__ diff --git a/include/util/kernel/Shape.h b/include/util/kernel/Shape.h new file mode 100644 index 000000000..bd2332989 --- /dev/null +++ b/include/util/kernel/Shape.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_KERNEL_SHAPE_H__ +#define __NNFW_UTIL_KERNEL_SHAPE_H__ + +#include <cstdint> + +namespace nnfw +{ +namespace util +{ +namespace kernel +{ + +struct Shape +{ + int32_t N; + int32_t C; + int32_t H; + int32_t W; + + Shape() = default; + Shape(int32_t count, int32_t depth, int32_t height, int32_t width) + : N{count}, C{depth}, H{height}, W{width} + { + // DO NOTHING + } +}; + +} // namespace kernel +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_KERNEL_SHAPE_H__ diff --git a/include/util/matrix/IndexIterator.h b/include/util/matrix/IndexIterator.h new file mode 100644 index 000000000..b6fccff45 --- /dev/null +++ b/include/util/matrix/IndexIterator.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_MATRIX_INDEX_ITERATOR_H__ +#define __NNFW_UTIL_MATRIX_INDEX_ITERATOR_H__ + +#include "util/matrix/Shape.h" + +namespace nnfw +{ +namespace util +{ +namespace matrix +{ + +class IndexIterator +{ +public: + IndexIterator(const Shape &shape) : _shape{shape} + { + // DO NOTHING + } + +public: + template <typename Callable> IndexIterator &iter(Callable cb) + { + for (uint32_t row = 0; row < _shape.H; ++row) + { + for (uint32_t col = 0; col < _shape.W; ++col) + { + cb(row, col); + } + } + + return (*this); + } + +private: + const Shape _shape; +}; + +inline IndexIterator iterate(const Shape &shape) { return IndexIterator{shape}; } + +template <typename Callable> IndexIterator &operator<<(IndexIterator &&it, Callable cb) +{ + return it.iter(cb); +} + +} // namespace matrix +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_MATRIX_INDEX_ITERATOR_H__ diff --git a/include/util/matrix/Reader.h b/include/util/matrix/Reader.h new file mode 100644 index 000000000..526eaf5cd --- /dev/null +++ b/include/util/matrix/Reader.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_MATRIX_READER_H__ +#define __NNFW_UTIL_MATRIX_READER_H__ + +#include <cstdint> + +namespace nnfw +{ +namespace util +{ +namespace matrix +{ + +template <typename T> struct Reader +{ + virtual ~Reader() = default; + + virtual T at(uint32_t row, uint32_t col) const = 0; +}; + +} // namespace matrix +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_MATRIX_READER_H__ diff --git a/include/util/matrix/Shape.h b/include/util/matrix/Shape.h new file mode 100644 index 000000000..e2c20b4ca --- /dev/null +++ b/include/util/matrix/Shape.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// for 2D tensor +#ifndef __NNFW_UTIL_MATRIX_SHAPE_H__ +#define __NNFW_UTIL_MATRIX_SHAPE_H__ + +#include <cstdint> + +namespace nnfw +{ +namespace util +{ +namespace matrix +{ + +struct Shape +{ + int32_t H; // Height + int32_t W; // Width + + Shape() = default; + Shape(int32_t height, int32_t width) : H{height}, W{width} + { + // DO NOTHING + } +}; + +} // namespace feature +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_MATRIX_SHAPE_H__ diff --git a/include/util/profiling/profile_buffer.h b/include/util/profiling/profile_buffer.h new file mode 100644 index 000000000..8785a40d3 --- /dev/null +++ b/include/util/profiling/profile_buffer.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_CONTRIB_LITE_PROFILING_PROFILE_BUFFER_H_ +#define TENSORFLOW_CONTRIB_LITE_PROFILING_PROFILE_BUFFER_H_ + +#include <cstddef> +#include <cstdint> + +#include "util/profiling/time.h" + +namespace tflite { +namespace profiling { + +// A profiling event. +struct ProfileEvent { + // Describes the type of event. + // The event_metadata field may contain additional data for interpreting + // the event. + enum class EventType { + // Default event type, the metadata field has no special significance. + DEFAULT = 0, + // The event is an operator invocation and the event_metadata field is the + // index of operator node. + OPERATOR_INVOKE_EVENT = 1 + }; + + // Label of the event. This usually describes the event. + const char* tag; + // Timestamp in microseconds when the event began. + uint64_t begin_timestamp_us; + // Timestamp in microseconds when the event ended. + uint64_t end_timestamp_us; + // The field containing the type of event. This must be one of the event types + // in EventType. + EventType event_type; + // Extra data describing the details of the event. + uint32_t event_metadata; +}; +} // namespace profiling +} // namespace tflite + +#ifdef TFLITE_PROFILING_ENABLED + +#include <sys/time.h> +#include <vector> + +namespace tflite { +namespace profiling { +constexpr uint32_t kInvalidEventHandle = static_cast<uint32_t>(~0) - 1; + +// A ring buffer of profile events. +// This class is not thread safe. +class ProfileBuffer { + public: + ProfileBuffer(uint32_t max_num_entries, bool enabled) + : enabled_(enabled), current_index_(0), event_buffer_(max_num_entries) {} + + // Adds an event to the buffer with begin timestamp set to the current + // timestamp. Returns a handle to event that can be used to call EndEvent. If + // buffer is disabled this has no affect. + // The tag of the event should remain valid till the buffer is valid. + uint32_t BeginEvent(const char* tag, ProfileEvent::EventType event_type, + uint32_t event_metadata) { + if (!enabled_) { + return kInvalidEventHandle; + } + uint64_t timestamp = time::NowMicros(); + int index = current_index_ % event_buffer_.size(); + event_buffer_[index].tag = tag; + event_buffer_[index].event_type = event_type; + event_buffer_[index].event_metadata = event_metadata; + event_buffer_[index].begin_timestamp_us = timestamp; + event_buffer_[index].end_timestamp_us = 0; + current_index_++; + return index; + } + + // Sets the enabled state of buffer to |enabled| + void SetEnabled(bool enabled) { enabled_ = enabled; } + + // Sets the end timestamp for event for the handle to current time. + // If the buffer is disabled or previous event has been overwritten this + // operation has not effect. + void EndEvent(uint32_t event_handle) { + if (!enabled_ || event_handle == kInvalidEventHandle || + event_handle > current_index_) { + return; + } + const uint32_t max_size = event_buffer_.size(); + if (current_index_ > (max_size + event_handle)) { + // Ignore, buffer has already overflowed. + return; + } + + int event_index = event_handle % max_size; + event_buffer_[event_index].end_timestamp_us = time::NowMicros(); + } + + // Returns the size of the buffer. + size_t Size() const { + return (current_index_ >= event_buffer_.size()) ? event_buffer_.size() + : current_index_; + } + + // Resets the buffer. + void Reset() { + enabled_ = false; + current_index_ = 0; + } + + // Returns the profile event at the given index. If the index is invalid a + // nullptr is returned. The return event may get overwritten if more events + // are added to buffer. + const struct ProfileEvent* const At(int index) const { + size_t size = Size(); + if (index >= size) { + return nullptr; + } + const uint32_t max_size = event_buffer_.size(); + uint32_t start = + (current_index_ > max_size) ? current_index_ % max_size : max_size; + index = (index + start) % max_size; + return &event_buffer_[index]; + } + + private: + bool enabled_; + uint32_t current_index_; + std::vector<ProfileEvent> event_buffer_; +}; +} // namespace profiling +} // namespace tflite +#endif // TFLITE_PROFILING_ENABLED +#endif // TENSORFLOW_CONTRIB_LITE_PROFILING_PROFILE_BUFFER_H_ diff --git a/include/util/profiling/profiler.h b/include/util/profiling/profiler.h new file mode 100644 index 000000000..0d68b8f4b --- /dev/null +++ b/include/util/profiling/profiler.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_CONTRIB_LITE_PROFILING_PROFILER_H_ +#define TENSORFLOW_CONTRIB_LITE_PROFILING_PROFILER_H_ + +#include <vector> + +#include "util/profiling/profile_buffer.h" + +#ifdef TFLITE_PROFILING_ENABLED + +namespace tflite { +namespace profiling { +class ScopedProfile; +class ScopedOperatorProfile; + +// Controls whether profiling is enabled or disabled and collects profiles. +// TFLite is used on platforms that don't have posix threads, so the profiler is +// kept as simple as possible. It is designed to be used only on a single +// thread. +// +// Profiles are collected using Scoped*Profile objects that begin and end a +// profile event. +// An example usage is shown in the example below: +// +// Say Worker class has a DoWork method and we are interested in profiling +// the overall execution time for DoWork and time spent in Task1 and Task2 +// functions. +// +// class Worker { +// public: +// void DoWork() { +// ScopedProfile(&controller, "DoWork"); +// Task1(); +// Task2(); +// ..... +// } +// +// void Task1() { +// ScopedProfile(&controller, "Task1"); +// .... +// } +// +// void Task2() { +// ScopedProfile(&controller, "Task2"); +// } +// +// Profiler profiler; +// } +// +// We instrument the functions that need to be profiled. +// +// Profile can be collected by enable profiling and then getting profile +// events. +// +// void ProfileWorker() { +// Worker worker; +// worker.profiler.EnableProfiling(); +// worker.DoWork(); +// worker.profiler.DisableProfiling(); +// // Profiling is complete, extract profiles. +// auto profile_events = worker.profiler.GetProfiles(); +// } +// +// +class Profiler { + public: + Profiler() : buffer_(1024, false) {} + + void StartProfiling() { buffer_.SetEnabled(true); } + void StopProfiling() { buffer_.SetEnabled(false); } + void Reset() { buffer_.Reset(); } + std::vector<const ProfileEvent*> GetProfileEvents() { + std::vector<const ProfileEvent*> profile_events; + profile_events.reserve(buffer_.Size()); + for (size_t i = 0; i < buffer_.Size(); i++) { + profile_events.push_back(buffer_.At(i)); + } + return profile_events; + } + + private: + friend class ScopedProfile; + friend class ScopedOperatorProfile; + ProfileBuffer* GetProfileBuffer() { return &buffer_; } + ProfileBuffer buffer_; +}; + +class ScopedProfile { + public: + // Adds a profile event to profile that begins with the construction + // of object and ends when the object goes out of scope. + // The lifetime of tag should be at least the lifetime of profiler. + + ScopedProfile(Profiler* profiler, const char* tag) + : buffer_(nullptr), event_handle_(0) { + if (profiler) { + buffer_ = profiler->GetProfileBuffer(); + event_handle_ = + buffer_->BeginEvent(tag, ProfileEvent::EventType::DEFAULT, 0); + } + } + ~ScopedProfile() { + if (buffer_) { + buffer_->EndEvent(event_handle_); + } + } + + private: + ProfileBuffer* buffer_; + int32_t event_handle_; +}; + +class ScopedOperatorProfile { + public: + // Adds a profile event to profile that begins with the construction + // of object and ends when the object goes out of scope. + // The lifetime of tag should be at least the lifetime of profiler. + ScopedOperatorProfile(Profiler* profiler, const char* tag, int node_index) + : buffer_(nullptr), event_handle_(0) { + if (profiler) { + buffer_ = profiler->GetProfileBuffer(); + event_handle_ = buffer_->BeginEvent( + tag, ProfileEvent::EventType::OPERATOR_INVOKE_EVENT, node_index); + } + } + + ~ScopedOperatorProfile() { + if (buffer_) { + buffer_->EndEvent(event_handle_); + } + } + + private: + ProfileBuffer* buffer_; + int32_t event_handle_; +}; + +} // namespace profiling +} // namespace tflite + +#define VARNAME_UNIQ(name, ctr) name##ctr + +#define SCOPED_OPERATOR_PROFILE(profiler, node_index) \ + tflite::profiling::ScopedOperatorProfile VARNAME_UNIQ( \ + _profile_, __COUNTER__)((profiler), "OpInvoke", (node_index)) +#else + +namespace tflite { +namespace profiling { +// A noop version of profiler when profiling is disabled. +class Profiler { + public: + Profiler() {} + void StartProfiling() {} + void StopProfiling() {} + void Reset() {} + std::vector<const ProfileEvent*> GetProfileEvents() { return {}; } +}; +} // namespace profiling +} // namespace tflite + +#define SCOPED_OPERATOR_PROFILE(profiler, node_index) + +#endif // TFLITE_PROFILING_ENABLED + +#endif // TENSORFLOW_CONTRIB_LITE_PROFILING_PROFILER_H_ diff --git a/include/util/profiling/profiling.h b/include/util/profiling/profiling.h new file mode 100644 index 000000000..3365dc8d6 --- /dev/null +++ b/include/util/profiling/profiling.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_PROFILING_H__ +#define __NNFW_UTIL_PROFILING_H__ + +#include <iostream> + +namespace tflite { +namespace profiling { +class Profiler; // forward declaration +} +} + +namespace profiling +{ + +class Sync +{ +public: + Sync() : _enabled{false} + { + auto env = std::getenv("PURE_ARM_COMPUTE_SYNC_ENABLE"); + + if (env && std::atoi(env) != 0) + { + _enabled = true; + } + } + +public: + bool enabled(void) const { return _enabled; } + +private: + bool _enabled; +}; + +} // namespace profiling + +namespace profiling +{ + +class Context +{ +public: + Context() : _sync(), _profiler(nullptr) {} + +public: + const Sync &sync(void) const { return _sync; } + tflite::profiling::Profiler* getProfiler() { return _profiler; } + void setProfiler(tflite::profiling::Profiler* p) { _profiler = p; } + +private: + Sync _sync; + tflite::profiling::Profiler* _profiler; + +public: + static Context &get(void) + { + static Context ctx{}; + return ctx; + } +}; + +} // namespace profiling +#endif // __NNFW_UTIL_PROFILING_H__ diff --git a/include/util/profiling/time.h b/include/util/profiling/time.h new file mode 100644 index 000000000..da3289359 --- /dev/null +++ b/include/util/profiling/time.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_CONTRIB_LITE_PROFILING_TIME_H_ +#define TENSORFLOW_CONTRIB_LITE_PROFILING_TIME_H_ + +#include <cstdint> + +namespace tflite { +namespace profiling { +namespace time { +uint64_t NowMicros(); +} // namespace time +} // namespace profiling +} // namespace tflite +#endif // TENSORFLOW_CONTRIB_LITE_PROFILING_TIME_H_ diff --git a/include/util/tensor/Comparator.h b/include/util/tensor/Comparator.h new file mode 100644 index 000000000..f0ab4ab20 --- /dev/null +++ b/include/util/tensor/Comparator.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_COMPARATOR_H__ +#define __NNFW_UTIL_TENSOR_COMPARATOR_H__ + +#include "util/tensor/Index.h" +#include "util/tensor/Shape.h" +#include "util/tensor/Reader.h" +#include "util/tensor/Diff.h" + +#include <functional> + +#include <vector> + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +class Comparator +{ +public: + Comparator(const std::function<bool (float lhs, float rhs)> &fn) : _compare_fn{fn} + { + // DO NOTHING + } + +public: + struct Observer + { + virtual void notify(const Index &index, float expected, float obtained) = 0; + }; + +public: + // NOTE Observer should live longer than comparator + std::vector<Diff<float>> compare(const Shape &shape, + const Reader<float> &expected, + const Reader<float> &obtained, + Observer *observer = nullptr) const; + +private: + std::function<bool (float lhs, float rhs)> _compare_fn; +}; + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_COMPARATOR_H__ diff --git a/include/util/tensor/Diff.h b/include/util/tensor/Diff.h new file mode 100644 index 000000000..25a9bafcf --- /dev/null +++ b/include/util/tensor/Diff.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_DIFF_H__ +#define __NNFW_UTIL_TENSOR_DIFF_H__ + +#include "util/tensor/Index.h" + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +template<typename T> struct Diff +{ + Index index; + + T expected; + T obtained; + + Diff(const Index &i) : index(i) + { + // DO NOTHING + } + + Diff(const Index &i, const T &e, const T &o) : index(i), expected{e}, obtained{o} + { + // DO NOTHING + } +}; + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_DIFF_H__ diff --git a/include/util/tensor/Index.h b/include/util/tensor/Index.h new file mode 100644 index 000000000..bc41d3c8e --- /dev/null +++ b/include/util/tensor/Index.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_INDEX_H__ +#define __NNFW_UTIL_TENSOR_INDEX_H__ + +#include <cstdint> +#include <cstddef> + +#include <vector> +#include <initializer_list> + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +struct Index +{ +public: + Index(size_t rank) { _offsets.resize(rank); } + +public: + Index(std::initializer_list<int32_t> offsets) : _offsets{offsets} + { + // DO NOTHING + } + +public: + size_t rank(void) const { return _offsets.size(); } + +public: + int32_t at(size_t n) const { return _offsets.at(n); } + int32_t &at(size_t n) { return _offsets.at(n); } + +private: + std::vector<int32_t> _offsets; +}; + +// This is used to convert NNAPI tensor index to ARM tensor index or vice versa +inline static Index copy_reverse(const Index &origin) +{ + size_t rank = origin.rank(); + Index target(rank); + for (int i = 0; i < rank; i++) + target.at(i) = origin.at(rank-1 -i); + return target; +} + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_INDEX_H__ diff --git a/include/util/tensor/IndexEnumerator.h b/include/util/tensor/IndexEnumerator.h new file mode 100644 index 000000000..30325cbfa --- /dev/null +++ b/include/util/tensor/IndexEnumerator.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_INDEX_ENUMERATOR_H__ +#define __NNFW_UTIL_TENSOR_INDEX_ENUMERATOR_H__ + +#include "util/tensor/Shape.h" +#include "util/tensor/Index.h" + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +class IndexEnumerator +{ +public: + explicit IndexEnumerator(const Shape &shape) : _shape(shape), _index(shape.rank()), _cursor(0) + { + const size_t rank = _shape.rank(); + + for (size_t axis = 0; axis < rank; ++axis) + { + _index.at(axis) = 0; + } + + for (_cursor = 0; _cursor < rank; ++_cursor) + { + if (_index.at(_cursor) < _shape.dim(_cursor)) + { + break; + } + } + } + +public: + IndexEnumerator(IndexEnumerator &&) = delete; + IndexEnumerator(const IndexEnumerator &) = delete; + +public: + bool valid(void) const { return _cursor < _shape.rank(); } + +public: + const Index &curr(void) const { return _index; } + +public: + void advance(void) + { + const size_t rank = _shape.rank(); + + // Find axis to be updated + while((_cursor < rank) && !(_index.at(_cursor) + 1 < _shape.dim(_cursor))) + { + ++_cursor; + } + + if(_cursor == rank) + { + return; + } + + // Update index + _index.at(_cursor) += 1; + + for (size_t axis = 0; axis < _cursor; ++axis) + { + _index.at(axis) = 0; + } + + // Update cursor + _cursor = 0; + } + +public: + const Shape _shape; + +private: + size_t _cursor; + Index _index; +}; + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_INDEX_ENUMERATOR_H__ diff --git a/include/util/tensor/IndexFormatter.h b/include/util/tensor/IndexFormatter.h new file mode 100644 index 000000000..8014a42b6 --- /dev/null +++ b/include/util/tensor/IndexFormatter.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_INDEX_FORMATTER_H__ +#define __NNFW_UTIL_TENSOR_INDEX_FORMATTER_H__ + +#include "util/tensor/Index.h" + +#include <ostream> + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +class IndexFormatter +{ +public: + IndexFormatter(const nnfw::util::tensor::Index &index) : _index(index) + { + // DO NOTHING + } + +public: + const nnfw::util::tensor::Index &index(void) const { return _index; } + +private: + const nnfw::util::tensor::Index &_index; +}; + +std::ostream &operator<<(std::ostream &os, const IndexFormatter &fmt); + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_INDEX_FORMATTER_H__ diff --git a/include/util/tensor/IndexIterator.h b/include/util/tensor/IndexIterator.h new file mode 100644 index 000000000..cbe895166 --- /dev/null +++ b/include/util/tensor/IndexIterator.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_INDEX_ITERATOR_H__ +#define __NNFW_UTIL_TENSOR_INDEX_ITERATOR_H__ + +#include "util/tensor/Shape.h" +#include "util/tensor/Index.h" +#include "util/tensor/IndexEnumerator.h" + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +class IndexIterator +{ +public: + IndexIterator(const Shape &shape) : _shape(shape) + { + // DO NOTHING + } + +public: + // Allow move, but disallow copy + IndexIterator(IndexIterator &&) = default; + IndexIterator(const IndexIterator &) = delete; + +public: + template <typename Callable> IndexIterator &iter(Callable fn) + { + for (IndexEnumerator e{_shape}; e.valid(); e.advance()) + { + fn(e.curr()); + } + + return (*this); + } + +private: + const Shape &_shape; +}; + +inline IndexIterator iterate(const Shape &shape) { return IndexIterator{shape}; } + +template <typename Callable> IndexIterator &operator<<(IndexIterator &&it, Callable cb) +{ + return it.iter(cb); +} + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_INDEX_ITERATOR_H__ diff --git a/include/util/tensor/NonIncreasingStride.h b/include/util/tensor/NonIncreasingStride.h new file mode 100644 index 000000000..ff013ffa2 --- /dev/null +++ b/include/util/tensor/NonIncreasingStride.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_NON_INCREASING_STRIDE_H__ +#define __NNFW_UTIL_TENSOR_NON_INCREASING_STRIDE_H__ + +#include "util/tensor/Shape.h" +#include "util/tensor/Index.h" + +#include <vector> + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +// As its name suggests, stride[N-1] >= stride[N] holds for all N < rank in NonIncreasingStride. +class NonIncreasingStride +{ +public: + void init(const Shape &shape) + { + _stride.resize(shape.rank()); + _stride.at(shape.rank() - 1) = 1; + + for (uint32_t axis = shape.rank() - 1; axis > 0; --axis) + { + _stride.at(axis - 1) = _stride.at(axis) * shape.dim(axis); + } + } + +public: + uint32_t at(uint32_t axis) const { return _stride.at(axis); } + +public: + uint32_t offset(const Index &index) const; + +private: + std::vector<uint32_t> _stride; +}; + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_NON_INCREASING_STRIDE_H__ diff --git a/include/util/tensor/Object.h b/include/util/tensor/Object.h new file mode 100644 index 000000000..7afd089ea --- /dev/null +++ b/include/util/tensor/Object.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_OBJECT_H__ +#define __NNFW_UTIL_TENSOR_OBJECT_H__ + +#include "util/tensor/Shape.h" +#include "util/tensor/Index.h" +#include "util/tensor/IndexIterator.h" +#include "util/tensor/NonIncreasingStride.h" +#include "util/tensor/Reader.h" + +#include <vector> + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +template <typename T> class Object final : public Reader<T> +{ +public: + using Generator = std::function<T(const Shape &shape, const Index &index)>; + +public: + Object(const Shape &shape, const Generator &fn) : _shape{shape} + { + // Set 'stride' + _stride.init(shape); + + // Pre-allocate buffer + _values.resize(_shape.dim(0) * _stride.at(0)); + + // Set 'value' + iterate(_shape) << + [this, &fn](const Index &index) { _values.at(_stride.offset(index)) = fn(_shape, index); }; + } + +public: + const Shape &shape(void) const { return _shape; } + +public: + T at(const Index &index) const override { return _values.at(_stride.offset(index)); } + +private: + Shape _shape; + NonIncreasingStride _stride; + +private: + std::vector<T> _values; +}; + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_FEATURE_OBJECT_H__ diff --git a/include/util/tensor/Reader.h b/include/util/tensor/Reader.h new file mode 100644 index 000000000..654214880 --- /dev/null +++ b/include/util/tensor/Reader.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_READER_H__ +#define __NNFW_UTIL_TENSOR_READER_H__ + +#include "util/tensor/Index.h" + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +template <typename T> struct Reader +{ + virtual ~Reader() = default; + + virtual T at(const Index &index) const = 0; +}; + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_READER_H__ diff --git a/include/util/tensor/Shape.h b/include/util/tensor/Shape.h new file mode 100644 index 000000000..a4401c1ed --- /dev/null +++ b/include/util/tensor/Shape.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_SHAPE_H__ +#define __NNFW_UTIL_TENSOR_SHAPE_H__ + +#include <cstdint> +#include <cstddef> +#include <deque> +#include <initializer_list> +#include <ostream> +#include <string> + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +class Shape +{ +public: + Shape(size_t rank) { _dimensions.resize(rank); } + +public: + Shape(const std::initializer_list<int32_t> &dimensions) : _dimensions{dimensions} + { + // DO NOTHING + } + + Shape(const Shape &origin) = default; + +public: + void prepend(int32_t d) { _dimensions.emplace_front(d); } + void append(int32_t d) { _dimensions.emplace_back(d); } + +public: + size_t rank(void) const { return _dimensions.size(); } + +public: + int32_t dim(size_t n) const { return _dimensions.at(n); } + int32_t &dim(size_t n) { return _dimensions.at(n); } + +public: + size_t element_nums() const + { + size_t nums = 1; + for (auto d : _dimensions) + { + nums *= d; + } + return nums; + } + +private: + std::deque<int32_t> _dimensions; + +public: + static Shape from(const std::string &s); +}; + +bool operator==(const Shape &, const Shape &); + +std::ostream &operator<<(std::ostream &os, const Shape &shape); + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_SHAPE_H__ diff --git a/include/util/tensor/Zipper.h b/include/util/tensor/Zipper.h new file mode 100644 index 000000000..5d40736f3 --- /dev/null +++ b/include/util/tensor/Zipper.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_TENSOR_ZIPPER_H__ +#define __NNFW_UTIL_TENSOR_ZIPPER_H__ + +#include "util/tensor/Index.h" +#include "util/tensor/IndexIterator.h" +#include "util/tensor/Reader.h" + +namespace nnfw +{ +namespace util +{ +namespace tensor +{ + +template <typename T> class Zipper +{ +public: + Zipper(const Shape &shape, const Reader<T> &lhs, const Reader<T> &rhs) + : _shape{shape}, _lhs{lhs}, _rhs{rhs} + { + // DO NOTHING + } + +public: + template <typename Callable> void zip(Callable cb) const + { + iterate(_shape) << + [this, &cb](const Index &index) { cb(index, _lhs.at(index), _rhs.at(index)); }; + } + +private: + const Shape &_shape; + const Reader<T> &_lhs; + const Reader<T> &_rhs; +}; + +template <typename T, typename Callable> +const Zipper<T> &operator<<(const Zipper<T> &zipper, Callable cb) +{ + zipper.zip(cb); + return zipper; +} + +template <typename T> Zipper<T> zip(const Shape &shape, const Reader<T> &lhs, const Reader<T> &rhs) +{ + return Zipper<T>{shape, lhs, rhs}; +} + +} // namespace tensor +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_TENSOR_ZIPPER_H__ diff --git a/include/util/vector.h b/include/util/vector.h new file mode 100644 index 000000000..02f78257c --- /dev/null +++ b/include/util/vector.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_VECTOR_H__ +#define __NNFW_UTIL_VECTOR_H__ + +#include <vector> + +template <typename T> bool operator==(const std::vector<T> &lhs, const std::vector<T> &rhs) +{ + if (lhs.size() != rhs.size()) + { + return false; + } + + for (size_t ind = 0; ind < lhs.size(); ++ind) + { + if (lhs.at(ind) != rhs.at(ind)) + { + return false; + } + } + + return true; +} + +#endif // __NNFW_UTIL_VECTOR_H__ diff --git a/include/util/vector/Object.h b/include/util/vector/Object.h new file mode 100644 index 000000000..407c06dc6 --- /dev/null +++ b/include/util/vector/Object.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_VECTOR_OBJECT_H__ +#define __NNFW_UTIL_VECTOR_OBJECT_H__ + +#include "util/vector/Reader.h" + +#include <vector> +#include <functional> + +namespace nnfw +{ +namespace util +{ +namespace vector +{ + +template <typename T> class Object final : public Reader<T> +{ +public: + using Generator = std::function<T(int32_t size, int32_t offset)>; + +public: + Object(int32_t size, const Generator &gen) : _size{size} + { + _value.resize(_size); + + for (int32_t offset = 0; offset < size; ++offset) + { + _value.at(offset) = gen(size, offset); + } + } + +public: + int32_t size(void) const { return _size; } + +public: + T at(uint32_t nth) const override { return _value.at(nth); } + +private: + const int32_t _size; + std::vector<T> _value; +}; + +} // namespace vector +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_VECTOR_OBJECT_H__ diff --git a/include/util/vector/Reader.h b/include/util/vector/Reader.h new file mode 100644 index 000000000..a3c5cb359 --- /dev/null +++ b/include/util/vector/Reader.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __NNFW_UTIL_VECTOR_READER_H__ +#define __NNFW_UTIL_VECTOR_READER_H__ + +#include <cstdint> + +namespace nnfw +{ +namespace util +{ +namespace vector +{ + +template <typename T> struct Reader +{ + virtual ~Reader() = default; + + virtual T at(uint32_t nth) const = 0; +}; + +} // namespace vector +} // namespace util +} // namespace nnfw + +#endif // __NNFW_UTIL_VECTOR_READER_H__ |