summaryrefslogtreecommitdiff
path: root/runtimes/neurun/src/compiler/ConstantInitializer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtimes/neurun/src/compiler/ConstantInitializer.cc')
-rw-r--r--runtimes/neurun/src/compiler/ConstantInitializer.cc188
1 files changed, 188 insertions, 0 deletions
diff --git a/runtimes/neurun/src/compiler/ConstantInitializer.cc b/runtimes/neurun/src/compiler/ConstantInitializer.cc
new file mode 100644
index 000000000..d6d58e273
--- /dev/null
+++ b/runtimes/neurun/src/compiler/ConstantInitializer.cc
@@ -0,0 +1,188 @@
+/*
+ * 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.
+ */
+
+#include "ConstantInitializer.h"
+
+#include "backend/interface/operand/IObject.h"
+#include "backend/interface/IConfig.h"
+#include "backend/BackendManager.h"
+#include "model/operation/FullyConnectedNode.h"
+#include "util/feature/nhwc/Reader.h"
+#include "util/feature/nhwc/View.h"
+#include "util/feature/nchw/View.h"
+#include "misc/feature/IndexIterator.h"
+#include "util/logging.h"
+
+namespace neurun
+{
+namespace compiler
+{
+
+ConstantInitializer::ConstantInitializer(const graph::Graph &graph, Plan &plan)
+ : _graph{graph}, _plan{plan}
+{
+}
+
+void ConstantInitializer::operator()()
+{
+ // Fill operand data
+ _plan.operands().iterate([&](int ind, neurun::backend::operand::IObject &obj) {
+ neurun::model::operand::Index index(ind);
+ const auto &model_obj = _graph.operands().at(index);
+
+ // For only CONSTANTS
+ if (model_obj.getUsage() != neurun::model::operand::OperandUsage::CONSTANT)
+ return;
+
+ // Only float32 is supported
+ auto type = model_obj.typeInfo().type();
+ if (type != ::neurun::model::operand::DataType::TENSOR_FLOAT32)
+ throw std::runtime_error{"Unsupported data type. Only TENSOR_FLOAT32 is supported."};
+
+ VERBOSE(FillOperandData) << "Fill data for operand " << ind << std::endl;
+
+ auto layout =
+ model_obj.lower_info()->def_backends().getOnlyElement()->config()->getOperandLayout();
+ const auto shape = model_obj.shape();
+ auto base = reinterpret_cast<const float *>(model_obj.data().base());
+ auto size = model_obj.data().size();
+
+ obj.access([&](::neurun::backend::operand::ITensor &tensor) {
+ switch (shape.rank())
+ {
+ case 1:
+ {
+ auto vec_size = shape.asVector();
+ for (int32_t n = 0; n < vec_size; ++n)
+ {
+ const float *from = reinterpret_cast<const float *>(base) + n;
+ const auto value = *from;
+
+ float *into = reinterpret_cast<float *>(tensor.buffer()) + n;
+
+ *into = value;
+ }
+ break;
+ }
+ case 2:
+ {
+ // NOTE This is a WORKAROUND which supports FullyConnected weight only
+ // For FullyConnected, we must know the IFM shape to deduce 2D weight shape from 4D
+ // IFM.
+ // This is because of NHWC/NCHW layout, the order of mapping will be different.
+ // TODO Support general case - explicitly insert Reshape op for IFM as 2D
+
+ // Find corresponding FullyConnected IFM
+ auto operation_index = _graph.operands().at(index).getUses().list().front();
+ auto operation = &_graph.operations().at(operation_index);
+ auto fc_operation =
+ dynamic_cast<const neurun::model::operation::FullyConnectedNode *>(operation);
+
+ if (fc_operation == nullptr)
+ break;
+
+ auto ifm_index = fc_operation->getInputs().at(
+ neurun::model::operation::FullyConnectedNode::Input::INPUT);
+ const auto &ifm = _graph.operands().at(ifm_index);
+ const auto ifm_shape = ifm.shape().asFeature();
+ const auto num_output = shape.dim(0);
+
+ const ::nnfw::misc::feature::Shape ker_shape{num_output, ifm_shape.C, ifm_shape.H,
+ ifm_shape.W};
+ const util::feature::nhwc::Reader<float> from{ker_shape, base, size};
+
+ if (layout == neurun::graph::operand::Layout::NHWC)
+ {
+ ::nnfw::misc::feature::iterate(ker_shape)
+ << [&](uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) {
+ const auto value = from.at(nth, ch, row, col);
+
+ uint32_t offset = 0;
+
+ // NNAPI uses NHWC ordering
+ offset += nth * ifm_shape.H * ifm_shape.W * ifm_shape.C;
+ offset += row * ifm_shape.W * ifm_shape.C;
+ offset += col * ifm_shape.C;
+ offset += ch;
+
+ float *into = reinterpret_cast<float *>(tensor.buffer()) + offset;
+
+ *into = value;
+ };
+ }
+ else
+ {
+ assert(layout == neurun::graph::operand::Layout::NCHW);
+
+ ::nnfw::misc::feature::iterate(ker_shape)
+ << [&](uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) {
+ const auto value = from.at(nth, ch, row, col);
+
+ uint32_t offset = 0;
+
+ // 'NCHW' ordering
+ offset += nth * ifm_shape.C * ifm_shape.H * ifm_shape.W;
+ offset += ch * ifm_shape.H * ifm_shape.W;
+ offset += row * ifm_shape.W;
+ offset += col;
+
+ float *into = reinterpret_cast<float *>(tensor.buffer()) + offset;
+
+ *into = value;
+ };
+ }
+
+ break;
+ }
+ case 4:
+ {
+ auto ker_shape = shape.asFeature();
+ auto from = util::feature::nhwc::Reader<float>{ker_shape, base, size};
+
+ if (layout == neurun::graph::operand::Layout::NHWC)
+ {
+ auto into = util::feature::nhwc::View<float>{
+ ker_shape, reinterpret_cast<float *>(tensor.buffer()), size};
+
+ ::nnfw::misc::feature::iterate(ker_shape)
+ << [&](uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) {
+ const auto value = from.at(nth, ch, row, col);
+ into.at(nth, ch, row, col) = value;
+ };
+ }
+ else
+ {
+ assert(layout == neurun::graph::operand::Layout::NCHW);
+
+ auto into = util::feature::nchw::View<float>{&tensor};
+
+ ::nnfw::misc::feature::iterate(ker_shape)
+ << [&](uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) {
+ const auto value = from.at(nth, ch, row, col);
+ into.at(nth, ch, row, col) = value;
+ };
+ }
+ break;
+ }
+ default:
+ throw std::runtime_error{"Not yet supported"};
+ }
+ });
+ });
+}
+
+} // namespace codegen
+} // namespace neurun