diff options
Diffstat (limited to 'runtimes/neurun/core/include/backend/IConstantInitializer.h')
-rw-r--r-- | runtimes/neurun/core/include/backend/IConstantInitializer.h | 260 |
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__ |