Introduce DepthwiseConv2D to support MobileNet (#967)
author김정현/동작제어Lab(SR)/Senior Engineer/삼성전자 <jh0822.kim@samsung.com>
Mon, 30 Apr 2018 05:32:00 +0000 (14:32 +0900)
committer서상민/동작제어Lab(SR)/Senior Engineer/삼성전자 <sangmin7.seo@samsung.com>
Mon, 30 Apr 2018 05:32:00 +0000 (14:32 +0900)
This commit introduces DepthwiseConv2D layer to support Mobilenet
with a simple test case.

Signed-off-by: Junghyun Kim <jh0822.kim@samsung.com>
include/kernel/acl/DepthwiseConv2D.h [new file with mode: 0644]
libs/kernel/acl/CMakeLists.txt
libs/kernel/acl/src/DepthwiseConv2D.h [new file with mode: 0644]
libs/kernel/acl/src/DepthwiseConv2D.test.h [new file with mode: 0644]
libs/kernel/acl/src/cl/DepthwiseConv2D.cpp [new file with mode: 0644]
libs/kernel/acl/src/cl/DepthwiseConv2D.test.cpp [new file with mode: 0644]

diff --git a/include/kernel/acl/DepthwiseConv2D.h b/include/kernel/acl/DepthwiseConv2D.h
new file mode 100644 (file)
index 0000000..b0fc199
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NNFW_KERNEL_ACL_DEPTHWISECONV2D_H__
+#define __NNFW_KERNEL_ACL_DEPTHWISECONV2D_H__
+
+#include <OperationsUtils.h>
+
+namespace nnfw {
+namespace kernel {
+namespace acl {
+
+bool depthwiseConvFloat32(const float* inputData, const android::nn::Shape& inputShape,
+                          const float* filterData, const android::nn::Shape& filterShape,
+                          const float* biasData, const android::nn::Shape& biasShape,
+                          int32_t padding_left, int32_t padding_right,
+                          int32_t padding_top, int32_t padding_bottom,
+                          int32_t stride_width, int32_t stride_height,
+                          int32_t depth_multiplier, int32_t activation,
+                          float* outputData, const android::nn::Shape& outputShape);
+
+} // namespace acl
+} // namespace kernel
+} // namespace nnfw
+
+#endif // __NNFW_KERNEL_ACL_DEPTHWISECONV2D_H__
index f45e40e..cbb6a82 100644 (file)
@@ -28,6 +28,7 @@ set(KERNELACL_SRCS "src/Init_acl.cpp"
                    "src/shape.cpp"
                    "src/support.cpp"
                    "src/cl/Conv2D.cpp"
+                   "src/cl/DepthwiseConv2D.cpp"
                    "src/cl/FullyConnected.cpp"
                    "src/cl/Pooling.cpp"
                    "src/cl/Reshape.cpp"
@@ -60,6 +61,7 @@ install(TARGETS ${LIB_KERNELACL} DESTINATION lib)
 set(KERNELACL_TEST_SRCS "src/util.cpp"
                         "src/gtest_env.cpp"
                         "src/cl/Conv2D.test.cpp"
+                        "src/cl/DepthwiseConv2D.test.cpp"
                         "src/cl/FullyConnected.test.cpp"
                         "src/cl/Pooling.test.cpp"
                         "src/cl/Reshape.test.cpp"
diff --git a/libs/kernel/acl/src/DepthwiseConv2D.h b/libs/kernel/acl/src/DepthwiseConv2D.h
new file mode 100644 (file)
index 0000000..703874c
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NNFW_KERNEL_ACL_DEPTHWISECONV2D_COMMON_H__
+#define __NNFW_KERNEL_ACL_DEPTHWISECONV2D_COMMON_H__
+
+#include <OperationsUtils.h>
+#include <arm_compute/core/TensorShape.h>
+#include <arm_compute/core/TensorInfo.h>
+#include <arm_compute/runtime/IFunction.h>
+
+#include "shape.h"
+#include "IO_accessor.h"
+
+namespace nnfw {
+namespace kernel {
+namespace acl {
+
+namespace common {
+
+typedef std::function<void (void)> sync_scheduler_f;
+
+template<class TensorT, class LayerT, class ActT>
+bool depthwiseConvFloat32(const float* inputData, const android::nn::Shape& inputShape,
+                          const float* filterData, const android::nn::Shape& filterShape,
+                          const float* biasData, const android::nn::Shape& biasShape,
+                          int32_t padding_left, int32_t padding_right,
+                          int32_t padding_top, int32_t padding_bottom,
+                          int32_t stride_width, int32_t stride_height,
+                          int32_t depth_multiplier, int32_t activation,
+                          float* outputData, const android::nn::Shape& outputShape,
+                          sync_scheduler_f sync_scheduler) {
+  auto inputShapeACL = util::fromNNShape(inputShape);
+  auto weightsShapeACL = util::fromNNShape(filterShape);
+  auto biasShapeACL = util::fromNNShape(biasShape);
+  auto outputShapeACL = util::fromNNShape(outputShape);
+
+  TensorT input(arm_compute::TensorInfo(inputShapeACL, arm_compute::Format::F32));
+  TensorT weights(arm_compute::TensorInfo(inputShapeACL, arm_compute::Format::F32));
+  TensorT bias(arm_compute::TensorInfo(biasShapeACL, arm_compute::Format::F32));
+  TensorT output(arm_compute::TensorInfo(outputShapeACL, arm_compute::Format::F32));
+
+  arm_compute::PadStrideInfo psinfo = arm_compute::PadStrideInfo(stride_width, stride_height,
+                                              padding_left, padding_right,
+                                              padding_top, padding_bottom,
+                                              arm_compute::DimensionRoundingType::FLOOR);
+
+  auto l = std::make_shared<LayerT>();
+  l->configure(input.ptr(), weights.ptr(), bias.ptr(), output.ptr(), psinfo);
+
+  std::vector<std::shared_ptr<arm_compute::IFunction>> fns;
+
+  fns.emplace_back(l);
+
+  if (ANEURALNETWORKS_FUSED_RELU == activation)
+  {
+    auto relu_f = std::make_shared<ActT>();
+
+    const arm_compute::ActivationLayerInfo relu_info{arm_compute::ActivationLayerInfo::ActivationFunction::RELU};
+
+    // Do in-place update
+    relu_f->configure(output.ptr(), nullptr, relu_info);
+
+    fns.emplace_back(relu_f);
+  }
+
+  input.allocate();
+  output.allocate();
+  bias.allocate();
+  weights.allocate();
+
+  // TODO: Do we need 2D tensor accessor for the input feature?
+  TensorAccess<InputAccessor>(input.ref(), inputData, inputShape);
+  TensorAccess<BiasAccessor>(bias.ref(), biasData, biasShape);
+  TensorAccess<WeightAccessor>(weights.ref(), filterData, filterShape);
+
+  for (const auto &fn : fns)
+  {
+    fn->run();
+  }
+
+  sync_scheduler();
+
+  TensorAccess<OutputAccessor>(output.ref(), outputData, outputShape);
+
+  return true;
+}
+
+} // namespace common
+
+} // namespace acl
+} // namespace kernel
+} // namespace nnfw
+
+#endif // __NNFW_KERNEL_ACL_DEPTHWISECONV2D_COMMON_H__
diff --git a/libs/kernel/acl/src/DepthwiseConv2D.test.h b/libs/kernel/acl/src/DepthwiseConv2D.test.h
new file mode 100644 (file)
index 0000000..d19d382
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <OperationsUtils.h>
+#include <kernel/acl/nnfw_kernel_acl.h>
+#include <kernel/acl/DepthwiseConv2D.h>
+
+// TODO: fix include path in CMakeFiles
+#include "util.h"
+
+#ifndef ACL_TEST
+#error "ACL_TEST should be defined first!"
+#endif // ACL_TEST
+
+#ifndef ACL_CORE_FUNC_NAME
+#error "ACL_CORE_FUNC_NAME should be defined first!"
+#endif // ACL_CORE_FUNC_NAME
+
+using namespace nnfw::kernel::acl;
+
+ACL_TEST(KernelACL_TC, dwise_conv2d_1) {
+  uint32_t input_n = 1;
+  uint32_t input_h = 3;
+  uint32_t input_w = 3;
+  uint32_t input_c = 1;
+  uint32_t filter_h = 3;
+  uint32_t filter_w = 3;
+  uint32_t filter_c = 1;
+  uint32_t out_h = 1;
+  uint32_t out_w = 1;
+
+  int32_t padding_left = 0;
+  int32_t padding_right = 0;
+  int32_t padding_top = 0;
+  int32_t padding_bottom = 0;
+  int32_t stride_width = 1;
+  int32_t stride_height = 1;
+  int32_t depth_multiplier = 1;
+
+  util::TensorWrapper input({input_n, input_h, input_w, input_c});
+  util::TensorWrapper weights({1, filter_h, filter_w, filter_c});
+  util::TensorWrapper bias({filter_c});
+  util::TensorWrapper output({1, out_h, out_w, filter_c});
+
+  int32_t activation = static_cast<int32_t>(FusedActivationFunc::RELU);
+
+  input.initValue([&](uint32_t n, uint32_t c, uint32_t h, uint32_t w) {
+    uint32_t N = input_n;
+    uint32_t H = input_h;
+    uint32_t W = input_w;
+    uint32_t C = input_c;
+
+    return n*H*W*C + h*W*C + w*C + c;
+  });
+  weights.initValue([&](uint32_t n, uint32_t c, uint32_t h, uint32_t w) {
+    uint32_t N = 1;
+    uint32_t H = filter_h;
+    uint32_t W = filter_w;
+    uint32_t C = filter_c;
+
+    return n*H*W*C + h*W*C + w*C + c;
+  });
+  bias.initValue([](uint32_t w) {
+    return 0.f;
+  });
+  output.initValue([](uint32_t n, uint32_t c, uint32_t h, uint32_t w) {
+    return 0.f;
+  });
+
+  bool bret = ACL_CORE_FUNC_NAME(input.ptr<float>(), input.shape(),
+      weights.ptr<float>(), weights.shape(),
+      bias.ptr<float>(), bias.shape(),
+      padding_left, padding_right,
+      padding_top, padding_bottom,
+      stride_width, stride_height,
+      depth_multiplier, activation,
+      output.ptr<float>(), output.shape());
+
+  EXPECT_EQ(bret, true);
+
+  util::TensorWrapper expected({1, out_h, out_w, filter_c});
+  expected.initValue([&](uint32_t n, uint32_t c, uint32_t h, uint32_t w) {
+    return 204.f;
+  });
+
+  EXPECT_EQ(output, expected);
+}
diff --git a/libs/kernel/acl/src/cl/DepthwiseConv2D.cpp b/libs/kernel/acl/src/cl/DepthwiseConv2D.cpp
new file mode 100644 (file)
index 0000000..d916429
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <OperationsUtils.h>
+#include <arm_compute/core/TensorShape.h>
+#include <arm_compute/core/TensorInfo.h>
+
+#include <cassert>
+
+// TODO: fix include path in CMakeFiles
+#include "../IO_accessor.h"
+#include "../shape.h"
+#include "../CLUniqueTensor.h"
+#include "../DepthwiseConv2D.h"
+
+namespace nnfw {
+namespace kernel {
+namespace acl {
+
+static void sync_scheduler() {
+  arm_compute::CLScheduler::get().sync();
+}
+
+bool depthwiseConvFloat32(const float* inputData, const android::nn::Shape& inputShape,
+                          const float* filterData, const android::nn::Shape& filterShape,
+                          const float* biasData, const android::nn::Shape& biasShape,
+                          int32_t padding_left, int32_t padding_right,
+                          int32_t padding_top, int32_t padding_bottom,
+                          int32_t stride_width, int32_t stride_height,
+                          int32_t depth_multiplier, int32_t activation,
+                          float* outputData, const android::nn::Shape& outputShape) {
+  return common::depthwiseConvFloat32<CLUniqueTensor, arm_compute::CLDepthwiseConvolutionLayer,
+  arm_compute::CLActivationLayer>(inputData, inputShape,
+      filterData, filterShape,
+      biasData, biasShape,
+      padding_left, padding_right,
+      padding_top, padding_bottom,
+      stride_width, stride_height,
+      depth_multiplier, activation,
+      outputData, outputShape,
+      sync_scheduler);
+}
+
+} // namespace acl
+} // namespace kernel
+} // namespace nnfw
+
diff --git a/libs/kernel/acl/src/cl/DepthwiseConv2D.test.cpp b/libs/kernel/acl/src/cl/DepthwiseConv2D.test.cpp
new file mode 100644 (file)
index 0000000..6955633
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ACL_CORE_FUNC_NAME depthwiseConvFloat32
+#define ACL_TEST(tc, t) TEST(tc, cl_##t)
+
+#include "../DepthwiseConv2D.test.h"