From 8e0dad33101bb0e837a2559a86384a7bdfb8c4d0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EC=B5=9C=EC=84=B1=EC=A7=84/=EB=8F=99=EC=9E=91=EC=A0=9C?= =?utf8?q?=EC=96=B4Lab=28SR=29/Principal=20Engineer/=EC=82=BC=EC=84=B1?= =?utf8?q?=EC=A0=84=EC=9E=90?= Date: Thu, 12 Apr 2018 13:31:53 +0900 Subject: [PATCH] [NNOP]Introduce average pooling (#610) --- include/kernel/acl/Pooling.h | 8 +++++ src/kernel/acl/src/cl/Pooling.cpp | 64 +++++++++++++++++++++++++++++++++- src/kernel/acl/src/cl/Pooling.test.cpp | 36 +++++++++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/include/kernel/acl/Pooling.h b/include/kernel/acl/Pooling.h index 492d44b..4867b14 100644 --- a/include/kernel/acl/Pooling.h +++ b/include/kernel/acl/Pooling.h @@ -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 diff --git a/src/kernel/acl/src/cl/Pooling.cpp b/src/kernel/acl/src/cl/Pooling.cpp index 97377bb..00bc49f 100644 --- a/src/kernel/acl/src/cl/Pooling.cpp +++ b/src/kernel/acl/src/cl/Pooling.cpp @@ -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> 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(); + 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(); + + 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(input, inputData, inputShape); + + for (const auto &fn : fns) + { + fn->run(); + } + + arm_compute::CLScheduler::get().sync(); + + TensorAccess(output, outputData, outputShape); + + return true; +} + } // namespace acl } // namespace kernel } // namespace nnfw diff --git a/src/kernel/acl/src/cl/Pooling.test.cpp b/src/kernel/acl/src/cl/Pooling.test.cpp index 898f39a..83da161 100644 --- a/src/kernel/acl/src/cl/Pooling.test.cpp +++ b/src/kernel/acl/src/cl/Pooling.test.cpp @@ -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); +} -- 2.7.4