[neurun] Initialize use & def information (#2543)
author오형석/동작제어Lab(SR)/Staff Engineer/삼성전자 <hseok82.oh@samsung.com>
Fri, 31 Aug 2018 07:34:09 +0000 (16:34 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Fri, 31 Aug 2018 07:34:09 +0000 (16:34 +0900)
Initialize use & def information in model finishing phase
Add test code to check initialized use&def information

Signed-off-by: Hyeongseok Oh <hseok82.oh@samsung.com>
runtimes/neurun/src/graph/Graph.cc
runtimes/neurun/src/graph/Graph.h
runtimes/neurun/test/graph/operand/UseDef.cc [new file with mode: 0644]

index b0bc637..abdabc7 100644 (file)
@@ -94,6 +94,9 @@ void Graph::finishBuilding(void)
   assert(_phase == Phase::BUILDING);
   _phase = Phase::MODEL;
 
+  // Initialize operand use-def
+  initializeUseDef();
+
   // Call graph verifications for the MODEL phase
   {
     verifier::DAGChecker dag_checker;
@@ -135,6 +138,27 @@ std::unique_ptr<linear::Linear> Graph::linearize(void)
   return std::move(linear);
 }
 
+void Graph::initializeUseDef()
+{
+  std::function<void(const operation::Index &index, const operation::Node &node)> initUseDef =
+      [&](const operation::Index &index, const operation::Node &node) -> void {
+
+    auto outputs = node.getOutputs();
+    for (auto output : outputs.list())
+    {
+      operands().at(output).appendDef(index);
+    }
+
+    auto inputs = node.getInputs();
+    for (auto input : inputs.list())
+    {
+      operands().at(input).appendUse(index);
+    }
+  };
+
+  operations().iterate(initUseDef);
+}
+
 } // namespace graph
 } // namespace neurun
 
index 82355df..f05bdba 100644 (file)
@@ -76,6 +76,9 @@ public:
   std::unique_ptr<linear::Linear> linearize(void);
   bool isBuildingPhase(void) { return _phase == Phase::BUILDING; }
 
+private:
+  void initializeUseDef();
+
   // Accessors
 public:
   const operand::IndexSet &getInputs() const { return _inputs; }
diff --git a/runtimes/neurun/test/graph/operand/UseDef.cc b/runtimes/neurun/test/graph/operand/UseDef.cc
new file mode 100644 (file)
index 0000000..e89eeb6
--- /dev/null
@@ -0,0 +1,101 @@
+#include <gtest/gtest.h>
+
+#include "graph/Graph.h"
+#include "graph/verifier/IVerifier.h"
+#include "nnfw/std/memory.h"
+#include "graph/operand/Index.h"
+#include "graph/operation/Index.h"
+
+#include <typeindex>
+
+using IOIndex = neurun::graph::operand::IO::Index;
+using Index = neurun::graph::operand::Index;
+using IndexSet = neurun::graph::operand::IndexSet;
+
+namespace
+{
+
+class MockNode : public neurun::graph::operation::Node
+{
+public:
+  MockNode(Index input, Index output)
+  {
+    setInputs({input});
+    setOutputs({output});
+  }
+
+public:
+  virtual void accept(neurun::graph::operation::NodeVisitor &&) const override {}
+};
+
+class MultiInputMockNode : public neurun::graph::operation::Node
+{
+public:
+  MultiInputMockNode(IndexSet inputs, Index output)
+  {
+    setInputs(inputs);
+    setOutputs({output});
+  }
+
+public:
+  virtual void accept(neurun::graph::operation::NodeVisitor &&) const override {}
+};
+
+} // namespace anonymous
+
+TEST(graph_operand_usedef, usedef_test)
+{
+  neurun::graph::Graph graph;
+  neurun::graph::verifier::DAGChecker verifier;
+
+  neurun::graph::operand::Shape shape{1u};
+  neurun::graph::operand::TypeInfo type{ANEURALNETWORKS_TENSOR_INT32, 0, 0};
+  shape.dim(0) = 3;
+
+  // Model Input/Output
+  auto input_operand = graph.addOperand(shape, type);
+  auto output_operand = graph.addOperand(shape, type);
+
+  graph.addInput(input_operand);
+  graph.operands().at(input_operand).setAsModelInput();
+  graph.addOutput(output_operand);
+
+  // MockNode1
+  auto operand_index1 = graph.addOperand(shape, type);
+  auto mocknode_index1 =
+      graph.addOperation(nnfw::make_unique<MockNode>(input_operand, operand_index1));
+  graph.operands().at(operand_index1).setAsOperationOutput();
+
+  // MockNode2
+  auto operand_index2 = graph.addOperand(shape, type);
+  auto mocknode_index2 =
+      graph.addOperation(nnfw::make_unique<MockNode>(input_operand, operand_index2));
+  graph.operands().at(operand_index2).setAsOperationOutput();
+  // MultiInputMockNode
+  auto multiinput_index = graph.addOperation(nnfw::make_unique<MultiInputMockNode>(
+      IndexSet{operand_index1, operand_index2}, output_operand));
+  graph.operands().at(output_operand).setAsOperationOutput();
+
+  ASSERT_EQ(verifier.verify(graph), true);
+  graph.finishBuilding();
+
+  const auto &operations = graph.operations();
+  // Check def
+  ASSERT_EQ(graph.operands().at(operand_index1).getDef().contains(mocknode_index1), true);
+  ASSERT_EQ(graph.operands().at(operand_index2).getDef().contains(mocknode_index2), true);
+  ASSERT_EQ(graph.operands().at(output_operand).getDef().contains(multiinput_index), true);
+
+  ASSERT_EQ(graph.operands().at(operand_index1).getDef().contains(mocknode_index2), false);
+  ASSERT_EQ(graph.operands().at(operand_index1).getDef().contains(multiinput_index), false);
+
+  // Check use
+  ASSERT_EQ(graph.operands().at(input_operand).getUses().contains(mocknode_index1), true);
+  ASSERT_EQ(graph.operands().at(input_operand).getUses().contains(mocknode_index2), true);
+  ASSERT_EQ(graph.operands().at(input_operand).getUses().contains(multiinput_index), false);
+  ASSERT_EQ(graph.operands().at(operand_index1).getUses().contains(multiinput_index), true);
+  ASSERT_EQ(graph.operands().at(operand_index2).getUses().contains(multiinput_index), true);
+
+  ASSERT_EQ(graph.operands().at(input_operand).getUses().size(), 2);
+  ASSERT_EQ(graph.operands().at(operand_index1).getUses().size(), 1);
+  ASSERT_EQ(graph.operands().at(output_operand).getUses().size(), 0);
+}