[Realizer] Implement remap realizer
authorJihoon Lee <jhoon.it.lee@samsung.com>
Tue, 12 Oct 2021 12:41:43 +0000 (21:41 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Thu, 14 Oct 2021 07:49:21 +0000 (16:49 +0900)
This patch introduce remap realizer which remaps identifier inside a
graph representation. Please refer to the test to see what this realizer
does.

**Self evaluation:**
1. Build test: [X]Passed [ ]Failed [ ]Skipped
2. Run test: [X]Passed [ ]Failed [ ]Skipped

Signed-off-by: Jihoon Lee <jhoon.it.lee@samsung.com>
jni/Android.mk
nntrainer/compiler/meson.build
nntrainer/compiler/remap_realizer.cpp [new file with mode: 0644]
nntrainer/compiler/remap_realizer.h [new file with mode: 0644]
nntrainer/layers/layer_node.cpp
nntrainer/layers/layer_node.h
test/unittest/compiler/unittest_realizer.cpp

index e92d2fb..0f092b6 100644 (file)
@@ -193,6 +193,7 @@ NNTRAINER_SRCS := $(NNTRAINER_ROOT)/nntrainer/models/neuralnet.cpp \
                   $(NNTRAINER_ROOT)/nntrainer/compiler/ini_interpreter.cpp \
                   $(NNTRAINER_ROOT)/nntrainer/compiler/flatten_realizer.cpp \
                   $(NNTRAINER_ROOT)/nntrainer/compiler/recurrent_realizer.cpp \
+                  $(NNTRAINER_ROOT)/nntrainer/compiler/remap_realizer.cpp \
                   $(NNTRAINER_ROOT)/nntrainer/app_context.cpp
 
 ifeq ($(ENABLE_TFLITE_INTERPRETER), 1)
index 1f5b7a1..ad735df 100644 (file)
@@ -1,7 +1,8 @@
 compiler_sources = [
   'ini_interpreter.cpp',
   'flatten_realizer.cpp',
-  'recurrent_realizer.cpp'
+  'recurrent_realizer.cpp',
+  'remap_realizer.cpp'
 ]
 
 compiler_headers = []
diff --git a/nntrainer/compiler/remap_realizer.cpp b/nntrainer/compiler/remap_realizer.cpp
new file mode 100644 (file)
index 0000000..7f55613
--- /dev/null
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: Apache-2.0
+/**
+ * Copyright (C) 2021 Jihoon Lee <jhoon.it.lee@samsung.com>
+ *
+ * @file remap_realizer.h
+ * @date 12 October 2021
+ * @brief NNTrainer graph realizer which realizes identifer to a new identifier
+ * @see        https://github.com/nnstreamer/nntrainer
+ * @author Jihoon Lee <jhoon.it.lee@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+#include <remap_realizer.h>
+
+#include <layer_node.h>
+namespace nntrainer {
+
+RemapRealizer::RemapRealizer(
+  std::function<void(std::string &)> remap_function) :
+  remap_fn(remap_function) {
+  if (!remap_fn) {
+    throw std::invalid_argument("remap function is not given!");
+  }
+}
+
+RemapRealizer::~RemapRealizer() {}
+
+GraphRepresentation
+RemapRealizer::realize(const GraphRepresentation &reference) {
+  GraphRepresentation processed(reference.begin(), reference.end());
+  for (auto &node : processed) {
+    node->remapIdentifiers(remap_fn);
+  }
+  return processed;
+}
+
+} // namespace nntrainer
diff --git a/nntrainer/compiler/remap_realizer.h b/nntrainer/compiler/remap_realizer.h
new file mode 100644 (file)
index 0000000..8aaa235
--- /dev/null
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: Apache-2.0
+/**
+ * Copyright (C) 2021 Jihoon Lee <jhoon.it.lee@samsung.com>
+ *
+ * @file remap_realizer.h
+ * @date 12 October 2021
+ * @brief NNTrainer graph realizer which realizes identifer to a new identifier
+ * @see        https://github.com/nnstreamer/nntrainer
+ * @author Jihoon Lee <jhoon.it.lee@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+#ifndef __REMAP_REALIZER_H__
+#define __REMAP_REALIZER_H__
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include <realizer.h>
+
+namespace nntrainer {
+
+/**
+ * @brief Graph realizer class which remaps identifiers inside the graph
+ * representation, remap_function will be applied for all the layers identifier
+ * visible
+ *
+ */
+class RemapRealizer final : public GraphRealizer {
+public:
+  RemapRealizer(std::function<void(std::string &)> remap_function);
+  /**
+   * @brief Destroy the Graph Realizer object
+   *
+   */
+  ~RemapRealizer();
+
+  /**
+   * @brief graph realizer creates a new graph based on the reference
+   *
+   */
+  GraphRepresentation realize(const GraphRepresentation &reference) override;
+
+private:
+  std::function<void(std::string &)> remap_fn;
+};
+
+} // namespace nntrainer
+
+#endif // __REMAP_REALIZER_H__
index 60013a1..b6495c8 100644 (file)
@@ -599,6 +599,32 @@ void LayerNode::printPreset(std::ostream &out, PrintPreset preset) {
   print(out, flags);
 }
 
+void LayerNode::remapIdentifiers(std::function<void(std::string &)> remap_fn) {
+  NNTR_THROW_IF(isFinalized(), std::invalid_argument)
+    << "cannot remap identifiers after finalized";
+
+  auto &name = std::get<props::Name>(*layer_node_props);
+  if (!name.empty()) {
+    remap_fn(name.get());
+  }
+
+  auto &shared_from = std::get<props::SharedFrom>(*layer_node_props);
+  if (!shared_from.empty()) {
+    remap_fn(shared_from.get());
+  }
+
+  auto &input_layers =
+    std::get<std::vector<props::InputLayer>>(*layer_node_props);
+
+  for (auto &input_layer : input_layers) {
+    remap_fn(input_layer);
+  }
+
+  for (auto &output_layer : output_layers) {
+    remap_fn(output_layer);
+  }
+}
+
 void LayerNode::printShapeInfo(std::ostream &out) {
   for (unsigned int idx = 0; idx < getNumInputs(); ++idx) {
     out << "input " << run_context->getInput(idx).getDim();
index 5db3e32..9afb3a4 100644 (file)
@@ -624,6 +624,13 @@ public:
   void printPreset(std::ostream &out,
                    PrintPreset preset = PrintPreset::PRINT_SUMMARY);
 
+  /**
+   * @brief remap identifier inside layer node
+   *
+   * @param remap_fn function to remap
+   */
+  void remapIdentifiers(std::function<void(std::string &)> remap_fn);
+
 private:
   std::unique_ptr<nntrainer::Layer>
     layer; /**< The actual object in the graph node */
index 214c74d..5c54f78 100644 (file)
@@ -17,6 +17,7 @@
 #include <flatten_realizer.h>
 #include <realizer.h>
 #include <recurrent_realizer.h>
+#include <remap_realizer.h>
 
 #include <compiler_test_util.h>
 
@@ -61,3 +62,17 @@ TEST(RecurrentRealizer, recurrent_p) {
 
   realizeAndEqual(r, {input1}, {input1});
 }
+
+TEST(RemapRealizer, remap_p) {
+
+  RemapRealizer r([](std::string &name) { name = "scoped/" + name; });
+
+  LayerRepresentation input1 = {
+    "fully_connected", {"name=layer1", "flatten=true", "input_layers=1,2"}};
+
+  LayerRepresentation expected1 = {
+    "fully_connected",
+    {"name=scoped/layer1", "flatten=true", "input_layers=scoped/1,scoped/2"}};
+
+  realizeAndEqual(r, {input1}, {expected1});
+}