[neurun] Make {pre|post}Visit of TemplTensorBuilder recursive (#7064)
author김용섭/On-Device Lab(SR)/Engineer/삼성전자 <yons.kim@samsung.com>
Tue, 3 Sep 2019 04:52:29 +0000 (13:52 +0900)
committer이한종/On-Device Lab(SR)/Engineer/삼성전자 <hanjoung.lee@samsung.com>
Tue, 3 Sep 2019 04:52:29 +0000 (13:52 +0900)
Make {pre|post}Visit of TemplTensorBuilder recursive to support for more
than two consecutive concat layers

Signed-off-by: Yongseop Kim <yons.kim@samsung.com>
runtimes/neurun/backend/acl_common/TemplTensorBuilder.h

index 6bb0e00..4c723f9 100644 (file)
@@ -417,60 +417,42 @@ void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor, T_Object>::preVisit(
     return;
   }
 
-  // NOTE. Handling subtensors can be done if they are on a concat or
-  // two consecutive concats(double concats).
-  // More than two consecutive concats cannot be done for now.
-  // TODO Enable handle concats recursively
-  auto def_handler = [this](const model::OperandIndex &ind) {
-    bool is_subtensor = _subtensor_info_map.find(ind) != _subtensor_info_map.end();
-    bool is_parent = _parent_def.find(ind) != _parent_def.end();
-    if (!is_subtensor && !is_parent)
-    {
-      _mem_mgr->startLifetime(ind);
-      return;
-    }
-
-    auto test_and_set_as_parent = [this](const model::OperandIndex &ind) {
-      assert(_parent_def.find(ind) != _parent_def.end());
-      if (_parent_def[ind])
-        _parent_def[ind] = 0;
-    };
-
-    auto test_and_def_as_parent = [this](const model::OperandIndex &ind) {
-      assert(_parent_def.find(ind) != _parent_def.end());
-      if (_parent_def[ind])
-      {
-        _parent_def[ind] = 0;
-        _mem_mgr->startLifetime(ind);
-      }
-    };
-
-    // TODO Elaborate below code. How to clean these conditions/branches?
-    if (is_subtensor && is_parent)
-    {
-      test_and_set_as_parent(ind);
-      test_and_def_as_parent(_subtensor_info_map.at(ind).parent());
-    }
-    else if (is_subtensor)
-    {
-      const model::OperandIndex &parent_ind = _subtensor_info_map.at(ind).parent();
+  std::function<void(const model::OperandIndex &ind)> def_handler =
+      [this, &def_handler](const model::OperandIndex &ind) {
+        bool is_subtensor = _subtensor_info_map.find(ind) != _subtensor_info_map.end();
+        bool is_parent = _parent_def.find(ind) != _parent_def.end();
+        if (!is_subtensor && !is_parent)
+        {
+          _mem_mgr->startLifetime(ind);
+          return;
+        }
 
-      // Its parent is a subtensor?
-      if (_subtensor_info_map.find(parent_ind) != _subtensor_info_map.end())
-      {
-        test_and_set_as_parent(parent_ind);
-        test_and_def_as_parent(_subtensor_info_map.at(parent_ind).parent());
-      }
-      else
-      {
-        test_and_def_as_parent(parent_ind);
-      }
-    }
-    else if (is_parent)
-    {
-      test_and_def_as_parent(ind);
-    }
-  };
+        if (is_parent)
+        {
+          if (_parent_def[ind] == 0)
+            return;
+
+          _parent_def[ind] = 0;
+
+          if (is_subtensor)
+          {
+            const auto &it = _parent_def.find(ind);
+            _parent_def.erase(it);
+            def_handler(ind);
+          }
+          else
+          {
+            _mem_mgr->startLifetime(ind);
+          }
+        }
+        else if (is_subtensor)
+        {
+          const model::OperandIndex &parent_ind = _subtensor_info_map.at(ind).parent();
+          if (_parent_def[parent_ind] == 0)
+            return;
+          def_handler(parent_ind);
+        }
+      };
 
   // See #5642
   model::OperandIndexMap<bool> outputs_map;
@@ -510,64 +492,41 @@ void TemplTensorBuilder<T_ITensor, T_Tensor, T_SubTensor, T_Object>::postVisit(
     return;
   }
 
-  // NOTE. Handling subtensors can be done if they are on a concat or
-  // two consecutive concats(double concats).
-  // More than two consecutive concats cannot be done for now.
-  // TODO Enable handle concats recursively
-  auto use_handler = [this](const model::OperandIndex &ind) {
-    bool is_subtensor = _subtensor_info_map.find(ind) != _subtensor_info_map.end();
-    bool is_parent = _parent_uses.find(ind) != _parent_uses.end();
-    if (!is_subtensor && !is_parent)
-    {
-      _mem_mgr->finishLifetime(ind);
-      return;
-    }
-
-    auto decr_as_parent = [this](const model::OperandIndex &ind) {
-      assert(_parent_uses.find(ind) != _parent_uses.end());
-      assert(_parent_uses[ind] > 0);
-      --_parent_uses[ind];
-    };
-
-    auto decr_test_and_use_as_parent = [this](const model::OperandIndex &ind) {
-      assert(_parent_uses.find(ind) != _parent_uses.end());
-      assert(_parent_uses[ind] > 0);
-      if (--_parent_uses[ind] == 0)
-        _mem_mgr->finishLifetime(ind);
-    };
-
-    // TODO Elaborate below code. How to clean these conditions/branches?
-    if (is_subtensor && is_parent)
-    {
-      decr_as_parent(ind);
-      if (_parent_uses[ind] == 0)
-      {
-        decr_test_and_use_as_parent(_subtensor_info_map.at(ind).parent());
-      }
-    }
-    else if (is_subtensor)
-    {
-      const model::OperandIndex &parent_ind = _subtensor_info_map.at(ind).parent();
+  std::function<void(const model::OperandIndex &ind)> use_handler =
+      [this, &use_handler](const model::OperandIndex &ind) {
+        bool is_subtensor = _subtensor_info_map.find(ind) != _subtensor_info_map.end();
+        bool is_parent = _parent_uses.find(ind) != _parent_uses.end();
+        if (!is_subtensor && !is_parent)
+        {
+          _mem_mgr->finishLifetime(ind);
+          return;
+        }
 
-      // Its parent is a subtensor?
-      if (_subtensor_info_map.find(parent_ind) != _subtensor_info_map.end())
-      {
-        decr_as_parent(parent_ind);
-        if (_parent_uses[parent_ind] == 0)
+        // This handler shall be executed by the linear executor so that
+        // The parent operand will always be done after the subtensor
+        if (is_parent)
         {
-          decr_test_and_use_as_parent(_subtensor_info_map.at(parent_ind).parent());
+          --_parent_uses[ind];
+          assert(_parent_uses[ind] == 0);
+
+          if (is_subtensor)
+          {
+            const auto &it = _parent_uses.find(ind);
+            _parent_uses.erase(it);
+            use_handler(ind);
+          }
+          else
+          {
+            _mem_mgr->finishLifetime(ind);
+          }
         }
-      }
-      else
-      {
-        decr_test_and_use_as_parent(parent_ind);
-      }
-    }
-    else if (is_parent)
-    {
-      decr_test_and_use_as_parent(ind);
-    }
-  };
+        else if (is_subtensor)
+        {
+          const model::OperandIndex &parent_ind = _subtensor_info_map.at(ind).parent();
+          --_parent_uses[parent_ind];
+          assert(_parent_uses[parent_ind] > 0);
+        }
+      };
 
   // See #5642
   const auto &inputs = node.getInputs();