From 7d25fc3df6577ad0ae613b296b2bcb39c83418e2 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 08:48:11 +0900 Subject: [PATCH] [NNOP] First version of MaxPoolingFloat32 (#563) * add softmax unittest * fix typoes (IFM_H -> IFM_C) * modify dims (batch_size and input_size) * Fix softmax unnittest according to comments -remove empty lines -add empty lines to the end of codes -resolve the conflict related with #472. -modify equality between two floats by using nfw::util::fp32::epsilon_equal Signed-off-by: SungJin Choi * add header files for softmax unittest Signed-off-by: SungJin Choi * add new line add new line at the end of file * [NNOP] First version of MaxPoolingFloat32 Signed-off-by: SungJin Choi * initialize data with increasing value Signed-off-by: SungJin Choi * Move maxpool kernel to cl folder * add maxpool acl kernel operator prototypes * add new line * change maxpool names as #574 * change names to align function prototype with NN runtime. --- include/kernel/acl/Pooling.h | 22 +++++++++ src/kernel/acl/CMakeLists.txt | 2 + src/kernel/acl/src/cl/Pooling.cpp | 88 ++++++++++++++++++++++++++++++++++ src/kernel/acl/src/cl/Pooling.test.cpp | 45 +++++++++++++++++ src/kernel/acl/src/util.cpp | 8 ++++ src/kernel/acl/src/util.h | 1 + 6 files changed, 166 insertions(+) create mode 100644 include/kernel/acl/Pooling.h create mode 100644 src/kernel/acl/src/cl/Pooling.cpp create mode 100644 src/kernel/acl/src/cl/Pooling.test.cpp diff --git a/include/kernel/acl/Pooling.h b/include/kernel/acl/Pooling.h new file mode 100644 index 0000000..492d44b --- /dev/null +++ b/include/kernel/acl/Pooling.h @@ -0,0 +1,22 @@ +#ifndef __NNFW_KERNEL_ACL_POOLING_H__ +#define __NNFW_KERNEL_ACL_POOLING_H__ + +#include + +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, + 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 + +#endif // __NNFW_KERNEL_ACL_POOLING_H__ diff --git a/src/kernel/acl/CMakeLists.txt b/src/kernel/acl/CMakeLists.txt index 03f41e9..04a322c 100644 --- a/src/kernel/acl/CMakeLists.txt +++ b/src/kernel/acl/CMakeLists.txt @@ -29,6 +29,7 @@ set(KERNELACL_SRCS "src/Init_acl.cpp" "src/shape.cpp" "src/cl/Conv2D.cpp" "src/cl/FullyConnected.cpp" + "src/cl/Pooling.cpp" "src/cl/Reshape.cpp" ) @@ -51,6 +52,7 @@ set(KERNELACL_TEST_SRCS "src/util.cpp" "src/gtest_env.cpp" "src/cl/Conv2D.test.cpp" "src/cl/FullyConnected.test.cpp" + "src/cl/Pooling.test.cpp" "src/cl/Reshape.test.cpp" ) diff --git a/src/kernel/acl/src/cl/Pooling.cpp b/src/kernel/acl/src/cl/Pooling.cpp new file mode 100644 index 0000000..0664a62 --- /dev/null +++ b/src/kernel/acl/src/cl/Pooling.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include "../IO_accessor.h" + +#include + +namespace android { +namespace nn { + +// TODO remove from this source and use it from runtime +uint32_t getSizeOfDimension(const Shape& shape, uint32_t dimensionIdx); + +} // namespace nn +} // namespace android + +namespace nnfw { +namespace kernel { +namespace acl { + +arm_compute::TensorShape fromNNShape(const android::nn::Shape& shape); + +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, + 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 = fromNNShape(inputShape); + arm_compute::TensorShape output_shape = 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::MAX, + 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 new file mode 100644 index 0000000..898f39a --- /dev/null +++ b/src/kernel/acl/src/cl/Pooling.test.cpp @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include + +#include "../util.h" + +using namespace nnfw::kernel::acl; + +TEST(KernelACL_TC, maxPoolFloat32_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 = maxPoolFloat32(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[] = { 9.0f }; + bret = util::compareData(outputData, expectData, outputShape); + EXPECT_EQ(bret, true); +} diff --git a/src/kernel/acl/src/util.cpp b/src/kernel/acl/src/util.cpp index fae19d2..366acba 100644 --- a/src/kernel/acl/src/util.cpp +++ b/src/kernel/acl/src/util.cpp @@ -12,6 +12,14 @@ void initData(float* data, int num, float value) } } +void initData_Increasing(float* data, int num, float value) +{ + for (int i = 0; i < num; i++) { + *(data + i) = value; + value++; + } +} + // compareData // return true if result == expected with the shape info, // otherwise false diff --git a/src/kernel/acl/src/util.h b/src/kernel/acl/src/util.h index dbb63ee..d5d0d41 100644 --- a/src/kernel/acl/src/util.h +++ b/src/kernel/acl/src/util.h @@ -7,6 +7,7 @@ namespace util { void initData(float* data, int num, float value); bool compareData(const float* result, const float* expected, const android::nn::Shape& shape); +void initData_Increasing(float* data, int num, float value); } // namespace util } // namespace acl -- 2.7.4