summaryrefslogtreecommitdiff
path: root/runtimes/neurun/core/include/backend/IConstantInitializer.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtimes/neurun/core/include/backend/IConstantInitializer.h')
-rw-r--r--runtimes/neurun/core/include/backend/IConstantInitializer.h260
1 files changed, 260 insertions, 0 deletions
diff --git a/runtimes/neurun/core/include/backend/IConstantInitializer.h b/runtimes/neurun/core/include/backend/IConstantInitializer.h
new file mode 100644
index 000000000..8393e0fd8
--- /dev/null
+++ b/runtimes/neurun/core/include/backend/IConstantInitializer.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2019 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 __NEURUN_BACKEND_ICONSTANT_INITIALIZER_H__
+#define __NEURUN_BACKEND_ICONSTANT_INITIALIZER_H__
+
+#include <unordered_map>
+#include <functional>
+
+#include "ITensorBuilder.h"
+#include "model/Layout.h"
+#include "model/Operand.h"
+#include "model/Operands.h"
+#include "model/OperationVisitor.h"
+#include "model/Subgraph.h"
+#include "util/logging.h"
+#include "util/Utils.h"
+
+namespace
+{
+template <typename T>
+static void Init(const neurun::model::Operand &model_obj, neurun::backend::operand::IObject &obj,
+ const bool copy,
+ const neurun::model::Layout frontend_layout = neurun::model::Layout::UNKNOWN)
+{
+ const auto shape = model_obj.shape();
+ auto base = reinterpret_cast<const T *>(model_obj.data().base());
+
+ obj.access([&](::neurun::backend::operand::ITensor &tensor) {
+ switch (shape.rank())
+ {
+ case 1:
+ {
+ auto vec_size = shape.dim(0);
+ for (int32_t n = 0; n < vec_size; ++n)
+ {
+ const T *from = reinterpret_cast<const T *>(base) + n;
+ const auto value = *from;
+
+ T *into = reinterpret_cast<T *>(tensor.buffer()) + n;
+
+ *into = value;
+ }
+ break;
+ }
+ case 2:
+ {
+ const int32_t copy_len = shape.dim(1);
+
+ for (auto i = 0; i < shape.dim(0); ++i)
+ {
+ neurun::util::Coordinates coords{i, 0};
+ memcpy(tensor.buffer() + tensor.calcOffset(coords), base + i * copy_len,
+ copy_len * sizeof(T));
+ }
+ break;
+ }
+ case 3:
+ {
+ const int32_t width = shape.dim(1);
+ const int32_t copy_len = shape.dim(2);
+
+ for (auto i = 0; i < shape.dim(0); ++i)
+ {
+ for (auto j = 0; j < shape.dim(1); ++j)
+ {
+ neurun::util::Coordinates coords{i, j, 0};
+ memcpy(tensor.buffer() + tensor.calcOffset(coords),
+ base + i * width * copy_len + j * copy_len, copy_len * sizeof(T));
+ }
+ }
+ break;
+ }
+ case 4:
+ {
+ const int32_t height = shape.dim(1);
+ const int32_t width = shape.dim(2);
+ const int32_t copy_len = shape.dim(3);
+ for (auto i = 0; i < shape.dim(0); ++i)
+ {
+ for (auto j = 0; j < shape.dim(1); ++j)
+ {
+ for (auto k = 0; k < shape.dim(2); ++k)
+ {
+ if (copy)
+ {
+ neurun::util::Coordinates coords{i, j, k, 0};
+ memcpy(tensor.buffer() + tensor.calcOffset(coords),
+ base + i * height * width * copy_len + j * width * copy_len + k * copy_len,
+ copy_len * sizeof(T));
+ }
+ else
+ {
+ for (auto l = 0; l < shape.dim(3); ++l)
+ {
+ const auto coords = neurun::util::convertCoordinates(
+ {i, j, k, l}, frontend_layout, tensor.layout());
+ T *into = reinterpret_cast<T *>(tensor.buffer() + tensor.calcOffset(coords));
+ T value = *(base + i * height * width * copy_len + j * width * copy_len +
+ k * copy_len + l);
+ *into = value;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ default:
+ throw std::runtime_error{"Not yet supported"};
+ }
+ });
+}
+
+template <typename T>
+void copyInit(const neurun::model::Operand &model_obj, neurun::backend::operand::IObject &obj)
+{
+ Init<T>(model_obj, obj, true);
+}
+
+template <typename T>
+void permuteInit(const neurun::model::Operand &model_obj, neurun::backend::operand::IObject &obj,
+ const neurun::model::Layout frontend_layout)
+{
+ Init<T>(model_obj, obj, false, frontend_layout);
+}
+
+} // namespace
+
+namespace neurun
+{
+namespace backend
+{
+
+class IConstantInitializer : model::OperationVisitor
+{
+public:
+ virtual ~IConstantInitializer() = default;
+
+public:
+ virtual void run() = 0;
+
+public:
+ using Initializer = std::function<void(const model::Operand &, backend::operand::IObject &)>;
+
+ void generate(const model::Subgraph &subg, const model::Operands &operands)
+ {
+ _current_subg_layout = subg.getLayout();
+ subg.accept(*this);
+ for (const auto &e : subg.operations())
+ {
+ for (const auto &ind : e.node->getInputs())
+ {
+ const auto &obj = operands.at(ind);
+ if (obj.isConstant() && !exist(ind))
+ {
+ registerPermuteInitializer(ind, obj);
+ }
+ }
+ }
+ }
+
+protected:
+#define OP(InternalName, IsNnApi) \
+ virtual void visit(const model::operation::InternalName &) override { /* DO NOTHING */}
+#include "model/Operations.lst"
+#undef OP
+
+protected:
+ void registerCopyInitializer(const model::OperandIndex &index, const model::Operand &obj)
+ {
+ // For only CONSTANTS
+ if (!obj.isConstant())
+ return;
+
+ VERBOSE(FillOperandData) << "Fill data for operand " << index.value() << std::endl;
+
+ const auto type = obj.typeInfo().type();
+ using neurun::model::DataType;
+
+ switch (type)
+ {
+ case DataType::FLOAT32:
+ _init_map[index] = copyInit<float>;
+ break;
+ case DataType::INT32:
+ _init_map[index] = copyInit<int32_t>;
+ break;
+ case DataType::UINT32:
+ _init_map[index] = copyInit<uint32_t>;
+ break;
+ case DataType::BOOL8:
+ case DataType::QUANT8_ASYMM:
+ _init_map[index] = copyInit<uint8_t>;
+ break;
+ default:
+ throw std::runtime_error("Not supported, yet");
+ break;
+ }
+ }
+
+protected:
+ void registerPermuteInitializer(const model::OperandIndex &index, const model::Operand &obj)
+ {
+ // For only CONSTANTS
+ if (!obj.isConstant())
+ return;
+
+ VERBOSE(FillOperandData) << "Fill data for operand " << index.value() << std::endl;
+
+ const auto type = obj.typeInfo().type();
+ using neurun::model::DataType;
+ using namespace std::placeholders;
+
+ switch (type)
+ {
+ case DataType::FLOAT32:
+ _init_map[index] = std::bind(permuteInit<float>, _1, _2, _current_subg_layout);
+ break;
+ case DataType::INT32:
+ _init_map[index] = std::bind(permuteInit<int32_t>, _1, _2, _current_subg_layout);
+ break;
+ case DataType::UINT32:
+ _init_map[index] = std::bind(permuteInit<uint32_t>, _1, _2, _current_subg_layout);
+ break;
+ case DataType::BOOL8:
+ case DataType::QUANT8_ASYMM:
+ _init_map[index] = std::bind(permuteInit<uint8_t>, _1, _2, _current_subg_layout);
+ break;
+ default:
+ throw std::runtime_error("Not supported, yet");
+ break;
+ }
+ }
+
+private:
+ bool exist(const model::OperandIndex &ind) { return _init_map.find(ind) != _init_map.end(); }
+
+protected:
+ std::unordered_map<model::OperandIndex, Initializer> _init_map;
+ model::Layout _current_subg_layout;
+};
+
+} // namespace backend
+} // namespace neurun
+
+#endif // __NEURUN_BACKEND_ICONSTANT_INITIALIZER_H__