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
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,
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
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);
+}