ACL NEON Div Node (#5948)
authorNikita Sizov/AI Tools Lab /SRR/Professional/삼성전자 <n.sizov@samsung.com>
Wed, 31 Jul 2019 10:07:29 +0000 (13:07 +0300)
committer이춘석/On-Device Lab(SR)/Staff Engineer/삼성전자 <chunseok.lee@samsung.com>
Wed, 31 Jul 2019 10:07:29 +0000 (19:07 +0900)
Add support of DivNode for ACL NEON

Signed-off-by: Sizov Nikita <n.sizov@samsung.com>
runtimes/neurun/backend/acl_neon/KernelGenerator.cc
runtimes/neurun/backend/acl_neon/ShapeFixer.cc
runtimes/neurun/backend/acl_neon/ShapeFixer.h
tests/nnapi/nnapi_gtest.skip.armv7l-linux.acl_neon

index 39e1173..e7d7eda 100644 (file)
@@ -872,8 +872,29 @@ void KernelGenerator::visit(const model::operation::AddNode &node)
 
 void KernelGenerator::visit(const model::operation::DivNode &node)
 {
-  (void)node;
-  throw std::runtime_error("Not supported, yet");
+  const auto ofm_index{node.getOutputs().at(0)};
+  const auto lhs_index{node.getInputs().at(model::operation::DivNode::Input::LHS)};
+  const auto rhs_index{node.getInputs().at(model::operation::DivNode::Input::RHS)};
+
+  const auto activation = node.param().activation;
+
+  auto ofm_alloc = _tensor_builder->at(ofm_index).get();
+  auto lhs_alloc = _tensor_builder->at(lhs_index).get();
+  auto rhs_alloc = _tensor_builder->at(rhs_index).get();
+
+  std::unique_ptr<::arm_compute::IFunction> fn;
+
+  auto l = nnfw::cpp14::make_unique<::arm_compute::NEElementwiseDivision>();
+
+  l->configure(lhs_alloc->handle(), rhs_alloc->handle(), ofm_alloc->handle());
+
+  fn = std::move(l);
+
+  auto acl_fn = asAclFunction(std::move(fn));
+
+  _execution_builder->append(std::move(acl_fn));
+
+  ActivationBuilder{*_execution_builder}.append(activation, ofm_alloc->handle());
 }
 
 void KernelGenerator::visit(const model::operation::ExpNode &node)
index 18455f6..c3d158e 100644 (file)
@@ -209,6 +209,23 @@ void ShapeFixer::visit(const model::operation::AddNode &node)
   }
 }
 
+void ShapeFixer::visit(const model::operation::DivNode &node)
+{
+  const auto lhs_index{node.getInputs().at(model::operation::DivNode::Input::LHS)};
+  const auto rhs_index{node.getInputs().at(model::operation::DivNode::Input::RHS)};
+
+  if (!(_ctx.at(lhs_index).shape() == _ctx.at(rhs_index).shape()))
+  {
+    const auto broadcast_rank =
+        std::max(_ctx.at(lhs_index).shape().rank(), _ctx.at(rhs_index).shape().rank());
+
+    // TODO remove const_cast later. For example, _ctx may need to be a non const variable or
+    //      a node to extend shape may be inserted in front of this operation
+    const_cast<::neurun::model::Shape &>(_ctx.at(lhs_index).shape()).extendRank(broadcast_rank);
+    const_cast<::neurun::model::Shape &>(_ctx.at(rhs_index).shape()).extendRank(broadcast_rank);
+  }
+}
+
 } // namespace acl_neon
 } // namespace backend
 } // namespace neurun
index 5d1758b..e038d37 100644 (file)
@@ -58,6 +58,7 @@ public:
   void visit(const model::operation::SquaredDifferenceNode &) override;
   void visit(const model::operation::SubNode &) override;
   void visit(const model::operation::AddNode &) override;
+  void visit(const model::operation::DivNode &) override;
   void visit(const model::operation::ComparisonNode &) override;
 
 private:
index be9e02c..fe4625d 100644 (file)
@@ -51,7 +51,6 @@ GeneratedTests.space_to_depth*
 GeneratedTests.svdf*
 GeneratedTests.tanh_
 GeneratedTests.batch_to_space*
-GeneratedTests.div_*
 GeneratedTests.space_to_batch*
 GeneratedTests.strided_slice*
 GeneratedTests.transpose*