Manage operand stack and operation stack for interpretation (#5020)
author오형석/On-Device Lab(SR)/Staff Engineer/삼성전자 <hseok82.oh@samsung.com>
Tue, 23 Apr 2019 08:31:17 +0000 (17:31 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Tue, 23 Apr 2019 08:31:17 +0000 (17:31 +0900)
- Introduce operand ready checker
- Introduce operation stack to save prepared operation
- Manage operand stack and operation stack and show log

Signed-off-by: Hyeongseok Oh <hseok82.oh@samsung.com>
runtimes/neurun/core/src/exec/interp/Interpreter.cc

index 536b19c..f452697 100644 (file)
@@ -17,6 +17,7 @@
 #include "Interpreter.h"
 
 #include <stack>
+#include <unordered_set>
 
 #include "model/operand/IndexMap.h"
 #include "util/logging.h"
@@ -58,7 +59,64 @@ void Interpreter::run()
       });
 
   // Execution
-  throw std::runtime_error("NYI: interpreter run");
+  std::unordered_set<model::operand::Index> ready_check;
+  while (!operand_stack.empty())
+  {
+    const auto current_operand_index = operand_stack.top();
+    operand_stack.pop();
+    VERBOSE(INTERPRETER) << "Poped operand " << current_operand_index.value()
+                         << " is checked ready to use" << std::endl;
+
+    assert(ready_check.find(current_operand_index) == ready_check.end());
+    ready_check.insert(current_operand_index);
+
+    // Find prepared operations by scan use of current operand
+    std::stack<model::OperationIndex> operation_stack;
+    const auto use_operators = _env->model().operands.at(current_operand_index).getUses();
+    for (auto use_operator : use_operators.list())
+    {
+      // Assumption: all parameters are ready to use
+      bool operator_ready = true;
+      for (auto input_index : _env->model().operations.at(use_operator).getInputs())
+      {
+        if (ready_check.find(input_index) == ready_check.end())
+        {
+          operator_ready = false;
+          break;
+        }
+      }
+
+      if (operator_ready)
+      {
+        VERBOSE(INTERPRETER) << "Ready to execute operation " << use_operator.value() << std::endl;
+        operation_stack.push(use_operator);
+      }
+    }
+
+    while (!operation_stack.empty())
+    {
+      const auto current_operation_index = operation_stack.top();
+      operation_stack.pop();
+      VERBOSE(INTERPRETER) << "Poped operation: " << current_operation_index.value() << "("
+                           << _env->model().operations.at(current_operation_index).getName() << ")"
+                           << std::endl;
+
+      // execution
+      // 1. Prepare output tensor
+      // 2. Call operation kernel
+      // 3. Push each output into operand stack
+
+      const auto def_operands = _env->model().operations.at(current_operation_index).getOutputs();
+      for (auto def_operand : def_operands)
+      {
+        VERBOSE(INTERPRETER) << "Buffer: Push to operand stack " << def_operand.value()
+                             << std::endl;
+        operand_stack.push(def_operand);
+      }
+    }
+  }
+
+  throw std::runtime_error{"NYI: buffer alloc and kernel call in operation stack loop"};
 }
 
 } // namespace interp