From 11614e6dbfa30636d094723181a91c76a747ec22 Mon Sep 17 00:00:00 2001 From: zhanglirong1999 <56445728+zhanglirong1999@users.noreply.github.com> Date: Thu, 26 Oct 2023 17:44:23 +0800 Subject: [PATCH] [oneDNN] Fix adaptive Pooling (#58361) --- paddle/phi/backends/onednn/onednn_reuse.h | 58 +++++++++--- test/cpp/fluid/mkldnn/CMakeLists.txt | 15 +++ .../mkldnn/test_mkldnn_pool_adaptive_op.cc | 91 +++++++++++++++++++ 3 files changed, 149 insertions(+), 15 deletions(-) create mode 100644 test/cpp/fluid/mkldnn/test_mkldnn_pool_adaptive_op.cc diff --git a/paddle/phi/backends/onednn/onednn_reuse.h b/paddle/phi/backends/onednn/onednn_reuse.h index 6252bbc54c933..a9246e8a75303 100644 --- a/paddle/phi/backends/onednn/onednn_reuse.h +++ b/paddle/phi/backends/onednn/onednn_reuse.h @@ -1519,8 +1519,11 @@ class PoolingOneDNNHandler } if (adaptive) { - ComputeAdaptivePoolParameters( - src_tz, &copied_kernel_size, &copied_strides); + ComputeAdaptivePoolParameters(src_tz, + onednn_paddings[0], + onednn_paddings[1], + &copied_kernel_size, + &copied_strides); } bool is_test = dev_ctx.HasDnnAttr("is_test") @@ -1612,8 +1615,11 @@ class PoolingOneDNNHandler } if (adaptive) { - ComputeAdaptivePoolParameters( - diff_src_tz, &copied_kernel_size, &copied_strides); + ComputeAdaptivePoolParameters(src_tz, + onednn_paddings[0], + onednn_paddings[1], + &copied_kernel_size, + &copied_strides); } memory::dims dilation = {0, 0}; @@ -1672,23 +1678,45 @@ class PoolingOneDNNHandler return mem_p; } - static void ComputeAdaptivePoolParameters(const std::vector& src_tz, - std::vector* kernel_size, - std::vector* strides) { + static void ComputeAdaptivePoolParameters( + const std::vector& src_tz, + const std::vector& padding_l, + const std::vector& padding_r, + std::vector* kernel_size, + std::vector* strides) { // https://github.com/oneapi-src/oneDNN/tree/bkocot/adaptive-pooling/rfcs/20200818-adaptive-pooling auto IH = static_cast(src_tz[src_tz.size() - 2]); auto IW = static_cast(src_tz[src_tz.size() - 1]); auto OH = static_cast(kernel_size->at(0)); auto OW = static_cast(kernel_size->at(1)); - strides->at(0) = - static_cast(floor((IH * 2.0) / OH) - floor(IH / OH)); - strides->at(1) = - static_cast(floor((IW * 2.0) / OW) - floor(IW / OW)); - kernel_size->at(0) = - static_cast(ceil((IH * 2.0) / OH) - floor(IH / OH)); - kernel_size->at(1) = - static_cast(ceil((IW * 2.0) / OW) - floor(IW / OW)); + /* + The previous calculation formula is given by OneDNN rfc, but in some odd + cases(mod(I/O)>=O/2) there will be problems with the calculation results. + Now change the formula to the general calculation formula of + AdaptivePool when in mod(I/O)>=O/2 case: + stride=floor(input_size/output_size) + kernel_size=input_size-(output_size-1)*stride + */ + int mod_H = IH - floor(IH / OH) * OH; + int mod_W = IW - floor(IW / OW) * OW; + if (2 * mod_H < OH && 2 * mod_W < OW) { + strides->at(0) = + static_cast(floor((IH * 2.0) / OH) - floor(IH / OH)); + strides->at(1) = + static_cast(floor((IW * 2.0) / OW) - floor(IW / OW)); + kernel_size->at(0) = + static_cast(ceil((IH * 2.0) / OH) - floor(IH / OH)); + kernel_size->at(1) = + static_cast(ceil((IW * 2.0) / OW) - floor(IW / OW)); + } else { + strides->at(0) = static_cast(floor(IH / OH)); + strides->at(1) = static_cast(floor(IW / OW)); + kernel_size->at(0) = static_cast( + IH + padding_l[0] + padding_r[0] - floor((OH - 1) * strides->at(0))); + kernel_size->at(1) = static_cast( + IW + padding_l[1] + padding_r[1] - floor((OW - 1) * strides->at(1))); + } } private: diff --git a/test/cpp/fluid/mkldnn/CMakeLists.txt b/test/cpp/fluid/mkldnn/CMakeLists.txt index 3d5883dabfbf8..f83fd91963be2 100644 --- a/test/cpp/fluid/mkldnn/CMakeLists.txt +++ b/test/cpp/fluid/mkldnn/CMakeLists.txt @@ -83,3 +83,18 @@ else() cc_test_old(test_mkldnn_op_nhwc SRCS test_mkldnn_op_nhwc.cc DEPS ${paddle_lib} python) endif() + +cc_test( + test_mkldnn_pool_adaptive_op + SRCS test_mkldnn_pool_adaptive_op.cc + DEPS fleet_executor + conditional_block_op + standalone_executor + executor + op_registry + generated_static_op + generated_op + phi + scope + device_context + enforce) diff --git a/test/cpp/fluid/mkldnn/test_mkldnn_pool_adaptive_op.cc b/test/cpp/fluid/mkldnn/test_mkldnn_pool_adaptive_op.cc new file mode 100644 index 0000000000000..3e1a9230ec231 --- /dev/null +++ b/test/cpp/fluid/mkldnn/test_mkldnn_pool_adaptive_op.cc @@ -0,0 +1,91 @@ +/* Copyright (c) 2023 PaddlePaddle Authors. 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 + +#include + +#include "paddle/fluid/framework/lod_tensor.h" +#include "paddle/fluid/framework/naive_executor.h" +#include "paddle/fluid/framework/op_registry.h" +#include "paddle/fluid/framework/operator.h" +#include "paddle/fluid/framework/scope.h" +#include "paddle/phi/common/place.h" +#include "paddle/phi/core/enforce.h" +#include "paddle/phi/core/kernel_registry.h" + +namespace paddle { +namespace inference { +namespace tensorrt { + +template +void AddVarToScope(const std::string var_name, + paddle::framework::Scope* scope, + const paddle::framework::DDim& dims) { + std::random_device seed; + std::default_random_engine engine(seed()); + std::uniform_real_distribution dist(0, 100); + + phi::DenseTensor tmp_tensor; + auto* tmp_data = + tmp_tensor.mutable_data(dims, paddle::platform::CPUPlace()); + auto* tensor = scope->Var(var_name)->GetMutable(); + tensor->mutable_data(dims, paddle::platform::CPUPlace()); + for (auto i = 0; i < tensor->numel(); ++i) { + tmp_data[i] = static_cast(dist(engine)); + } + paddle::framework::TensorCopySync( + tmp_tensor, paddle::platform::CPUPlace(), tensor); +} +void test_pool2d(bool adaptive, bool ceil_mode, std::string pool_type = "max") { + framework::Scope scope; + paddle::platform::CPUPlace cpu_place; + + // Prepare Op description + framework::OpDesc desc; + desc.SetType("pool2d"); + desc.SetInput("X", {"pool2d-X"}); + desc.SetOutput("Out", {"pool2d-Out"}); + AddVarToScope("pool2d-X", &scope, {1, 3, 9, 12}); + AddVarToScope("pool2d-Out", &scope, {1, 3, 2, 2}); + std::vector ksize({2, 2}); + std::vector strides({1, 1}); + std::vector paddings({0, 0}); + std::string pooling_t = pool_type; + + desc.SetAttr("pooling_type", pooling_t); + desc.SetAttr("ksize", ksize); + desc.SetAttr("strides", strides); + desc.SetAttr("paddings", paddings); + desc.SetAttr("adaptive", adaptive); + desc.SetAttr("ceil_mode", ceil_mode); + desc.SetAttr("use_mkldnn", true); + + auto op = paddle::framework::OpRegistry::CreateOp(desc); + + op->Run(scope, cpu_place); +} + +TEST(Pool2dOpConverter, normal) { test_pool2d(false, false); } +TEST(Pool2dOpConverter, adaptive) { test_pool2d(true, false); } + +TEST(Pool2dOpConverter, max_ceil_test) { test_pool2d(false, true); } +TEST(Pool2dOpConverter, avg_ceil_test) { test_pool2d(true, true, "avg"); } + +} // namespace tensorrt +} // namespace inference +} // namespace paddle + +USE_OP_ITSELF(pool2d); +PD_DECLARE_KERNEL(pool2d, OneDNN, ONEDNN); +PD_DECLARE_KERNEL(pool2d, CPU, ALL_LAYOUT);