[NNOP]Introduce average pooling (#610)
author최성진/동작제어Lab(SR)/Principal Engineer/삼성전자 <lotieye.choi@samsung.com>
Thu, 12 Apr 2018 04:31:53 +0000 (13:31 +0900)
committer박세희/동작제어Lab(SR)/Principal Engineer/삼성전자 <saehie.park@samsung.com>
Thu, 12 Apr 2018 04:31:53 +0000 (13:31 +0900)
include/kernel/acl/Pooling.h
src/kernel/acl/src/cl/Pooling.cpp
src/kernel/acl/src/cl/Pooling.test.cpp

index 492d44b..4867b14 100644 (file)
@@ -15,6 +15,14 @@ bool maxPoolFloat32(const float* inputData, const android::nn::Shape& inputShape
                  int32_t activation,
                  float* outputData, const android::nn::Shape& outputShape);
 
+bool averagePoolFloat32(const float* inputData, const android::nn::Shape& inputShape,
+                 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 filter_width, int32_t filter_height,
+                 int32_t activation,
+                 float* outputData, const android::nn::Shape& outputShape);
+
 } // namespace acl
 } // namespace kernel
 } // namespace nnfw
index 97377bb..00bc49f 100644 (file)
@@ -10,7 +10,6 @@ namespace nnfw {
 namespace kernel {
 namespace acl {
 
-
 bool maxPoolFloat32(const float* inputData, const android::nn::Shape& inputShape,
                  int32_t padding_left, int32_t padding_right,
                  int32_t padding_top, int32_t padding_bottom,
@@ -74,6 +73,69 @@ bool maxPoolFloat32(const float* inputData, const android::nn::Shape& inputShape
   return true;
 }
 
+bool averagePoolFloat32(const float* inputData, const android::nn::Shape& inputShape,
+                 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 filter_width, int32_t filter_height,
+                 int32_t activation,
+                 float* outputData, const android::nn::Shape& outputShape)
+{
+  arm_compute::TensorShape input_shape = util::fromNNShape(inputShape);
+  arm_compute::TensorShape output_shape = util::fromNNShape(outputShape);
+
+  assert(activation == ANEURALNETWORKS_FUSED_NONE || activation == ANEURALNETWORKS_FUSED_RELU);
+
+  std::vector<std::shared_ptr<arm_compute::IFunction>> fns;
+
+  arm_compute::PadStrideInfo pad_info = arm_compute::PadStrideInfo(stride_width, stride_height,
+                                              padding_left, padding_right,
+                                              padding_top, padding_bottom,
+                                              arm_compute::DimensionRoundingType::FLOOR);
+                                           
+  arm_compute::PoolingLayerInfo maxpool_info = arm_compute::PoolingLayerInfo(arm_compute::PoolingType::AVG,
+                                                        arm_compute::Size2D(filter_width,filter_height),
+                                                        pad_info, false);
+
+  arm_compute::CLTensor input, output;
+
+  input.allocator()->init(arm_compute::TensorInfo(input_shape, arm_compute::Format::F32));
+  output.allocator()->init(arm_compute::TensorInfo(output_shape, arm_compute::Format::F32));
+
+  auto pool_f = std::make_shared<arm_compute::CLPoolingLayer>();
+  pool_f->configure(&input, &output, maxpool_info);
+
+  fns.emplace_back(pool_f);
+
+  input.allocator()->allocate();
+  output.allocator()->allocate();
+
+  if (ANEURALNETWORKS_FUSED_RELU == activation)
+  {
+    auto relu_f = std::make_shared<arm_compute::CLActivationLayer>();
+
+    const arm_compute::ActivationLayerInfo relu_info{arm_compute::ActivationLayerInfo::ActivationFunction::RELU};
+
+    // Do in-place update
+    relu_f->configure(&output, nullptr, relu_info);
+
+    fns.emplace_back(relu_f);
+  }
+
+  TensorAccess<InputAccessor>(input, inputData, inputShape);
+
+  for (const auto &fn : fns)
+  {
+    fn->run();
+  }
+
+  arm_compute::CLScheduler::get().sync();
+
+  TensorAccess<OutputAccessor>(output, outputData, outputShape);
+
+  return true;
+}
+
 } // namespace acl
 } // namespace kernel
 } // namespace nnfw
index 898f39a..83da161 100644 (file)
@@ -43,3 +43,39 @@ TEST(KernelACL_TC, maxPoolFloat32_3x3to1x1)
   bret = util::compareData(outputData, expectData, outputShape);
   EXPECT_EQ(bret, true);
 }
+
+TEST(KernelACL_TC, averagePoolFloat32_3x3to1x1)
+{
+  float inputData[9];
+  const android::nn::Shape inputShape = { OperandType::FLOAT32, {1,3,3,1}, 1.0, 0 };
+  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 filter_width = 3;
+  int32_t filter_height = 3;
+
+  float outputData[1];
+  const android::nn::Shape outputShape = { OperandType::FLOAT32, {1,1,1,1}, 1.0, 0 };
+  bool bret;
+
+  util::initData_Increasing(inputData, sizeof(inputData) / sizeof(inputData[0]), 1.0);
+  util::initData(outputData, sizeof(outputData) / sizeof(outputData[0]), 0.0);
+
+  int32_t activation = ANEURALNETWORKS_FUSED_NONE;
+
+  bret = averagePoolFloat32(inputData, inputShape,
+                    padding_left, padding_right,
+                    padding_top, padding_bottom,
+                    stride_width, stride_height,
+                    filter_width, filter_height,
+                    activation,
+                    outputData, outputShape);
+  EXPECT_EQ(bret, true);
+
+  float expectData[] = { 5.0f };
+  bret = util::compareData(outputData, expectData, outputShape);
+  EXPECT_EQ(bret, true);
+}