From 1aa6777890b78a95aff7c3e790a348e3f2395477 Mon Sep 17 00:00:00 2001 From: Aurelius84 Date: Tue, 22 Feb 2022 14:59:32 +0800 Subject: [PATCH] [Phi] Migrate unfold_op into phi (#39778) * [Phi] Migrate unfold_op into phi * fix im2col CPUContext template instantial * fix unfold_op.h header include problem * fix unittest * fix PT->PD --- paddle/fluid/imperative/prepared_operator.h | 4 +- paddle/fluid/operators/fold_op.cc | 1 - paddle/fluid/operators/math/im2col.cc | 59 ++++--- paddle/fluid/operators/unfold_op.cc | 137 +-------------- paddle/fluid/operators/unfold_op.cu | 26 --- paddle/fluid/operators/unfold_op.h | 121 ------------- paddle/phi/infermeta/unary.cc | 159 ++++++++++++++++++ paddle/phi/infermeta/unary.h | 7 + paddle/phi/kernels/CMakeLists.txt | 2 +- paddle/phi/kernels/cpu/unfold_grad_kernel.cc | 21 +++ paddle/phi/kernels/cpu/unfold_kernel.cc | 20 +++ paddle/phi/kernels/funcs/unfold_functor.h | 33 ++++ paddle/phi/kernels/gpu/unfold_grad_kernel.cu | 21 +++ paddle/phi/kernels/gpu/unfold_kernel.cu | 20 +++ .../kernels/impl/unfold_grad_kernel_impl.h | 72 ++++++++ paddle/phi/kernels/impl/unfold_kernel_impl.h | 65 +++++++ paddle/phi/kernels/unfold_grad_kernel.h | 32 ++++ paddle/phi/kernels/unfold_kernel.h | 31 ++++ paddle/phi/ops/compat/unfold_sig.cc | 28 +++ 19 files changed, 558 insertions(+), 301 deletions(-) delete mode 100644 paddle/fluid/operators/unfold_op.cu delete mode 100644 paddle/fluid/operators/unfold_op.h create mode 100644 paddle/phi/kernels/cpu/unfold_grad_kernel.cc create mode 100644 paddle/phi/kernels/cpu/unfold_kernel.cc create mode 100644 paddle/phi/kernels/funcs/unfold_functor.h create mode 100644 paddle/phi/kernels/gpu/unfold_grad_kernel.cu create mode 100644 paddle/phi/kernels/gpu/unfold_kernel.cu create mode 100644 paddle/phi/kernels/impl/unfold_grad_kernel_impl.h create mode 100644 paddle/phi/kernels/impl/unfold_kernel_impl.h create mode 100644 paddle/phi/kernels/unfold_grad_kernel.h create mode 100644 paddle/phi/kernels/unfold_kernel.h create mode 100644 paddle/phi/ops/compat/unfold_sig.cc diff --git a/paddle/fluid/imperative/prepared_operator.h b/paddle/fluid/imperative/prepared_operator.h index 589c8edd446..714e4297986 100644 --- a/paddle/fluid/imperative/prepared_operator.h +++ b/paddle/fluid/imperative/prepared_operator.h @@ -442,7 +442,9 @@ void BuildDygraphPtenKernelContext( vector_int_attr.end()); kernel_ctx->EmplaceBackAttr(vector_int64_attr); } - // TODO(YuanRisheng) Need support vector attr + } else if (attr_defs[i].type_index == + std::type_index(typeid(std::vector))) { + kernel_ctx->EmplaceBackAttr(BOOST_GET_CONST(std::vector, attr)); } else { PADDLE_THROW(platform::errors::Unimplemented( "Unsupported cast op attribute `%s` when construct " diff --git a/paddle/fluid/operators/fold_op.cc b/paddle/fluid/operators/fold_op.cc index 7b97663c387..40ec9aef190 100644 --- a/paddle/fluid/operators/fold_op.cc +++ b/paddle/fluid/operators/fold_op.cc @@ -13,7 +13,6 @@ * limitations under the License. */ #include "paddle/fluid/operators/fold_op.h" -#include "paddle/fluid/operators/unfold_op.h" namespace paddle { namespace operators { diff --git a/paddle/fluid/operators/math/im2col.cc b/paddle/fluid/operators/math/im2col.cc index 8efd35ca108..8fc6c52122a 100644 --- a/paddle/fluid/operators/math/im2col.cc +++ b/paddle/fluid/operators/math/im2col.cc @@ -22,6 +22,10 @@ class CPUDeviceContext; } // namespace platform } // namespace paddle +namespace phi { +class CPUContext; +} // namespace phi + namespace paddle { namespace operators { namespace math { @@ -31,12 +35,12 @@ namespace math { * col = * [input_channels, filter_height, filter_width, output_height, output_width] */ -template -class Im2ColFunctor { +template +class Im2ColFunctor { public: - void operator()(const platform::CPUDeviceContext& context, - const framework::Tensor& im, const std::vector& dilation, + void operator()(const DeviceContext& context, const framework::Tensor& im, + const std::vector& dilation, const std::vector& stride, const std::vector& padding, framework::Tensor* col, const DataLayout data_layout) { @@ -73,12 +77,11 @@ class Im2ColFunctor -class Col2ImFunctor { +template +class Col2ImFunctor { public: - void operator()(const platform::CPUDeviceContext& context, - const framework::Tensor& col, + void operator()(const DeviceContext& context, const framework::Tensor& col, const std::vector& dilation, const std::vector& stride, const std::vector& padding, framework::Tensor* im, @@ -155,22 +158,30 @@ template class Im2ColFunctor; template class Im2ColFunctor; +template class Im2ColFunctor; +template class Im2ColFunctor; template class Col2ImFunctor; template class Col2ImFunctor; +template class Col2ImFunctor; +template class Col2ImFunctor; /* * im = [input_channels, input_height, input_width] * col = * [output_height, output_width, input_channels, filter_height, filter_width] */ -template -class Im2ColFunctor { +template +class Im2ColFunctor { public: - void operator()(const platform::CPUDeviceContext& context, - const framework::Tensor& im, const std::vector& dilation, + void operator()(const DeviceContext& context, const framework::Tensor& im, + const std::vector& dilation, const std::vector& stride, const std::vector& padding, framework::Tensor* col, const DataLayout data_layout) { @@ -235,12 +246,11 @@ class Im2ColFunctor -class Col2ImFunctor { +template +class Col2ImFunctor { public: - void operator()(const platform::CPUDeviceContext& context, - const framework::Tensor& col, + void operator()(const DeviceContext& context, const framework::Tensor& col, const std::vector& dilation, const std::vector& stride, const std::vector& padding, framework::Tensor* im, @@ -316,11 +326,18 @@ template class Im2ColFunctor; template class Im2ColFunctor; +template class Im2ColFunctor; +template class Im2ColFunctor; template class Col2ImFunctor; template class Col2ImFunctor; - +template class Col2ImFunctor; +template class Col2ImFunctor; } // namespace math } // namespace operators } // namespace paddle diff --git a/paddle/fluid/operators/unfold_op.cc b/paddle/fluid/operators/unfold_op.cc index 0a8cd6e65f9..c45b839d5b4 100644 --- a/paddle/fluid/operators/unfold_op.cc +++ b/paddle/fluid/operators/unfold_op.cc @@ -12,7 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "paddle/fluid/operators/unfold_op.h" +#include "paddle/fluid/framework/infershape_utils.h" +#include "paddle/fluid/framework/op_registry.h" +#include "paddle/phi/infermeta/unary.h" namespace paddle { namespace operators { @@ -60,126 +62,6 @@ feature map, a series of such columns will be formed. class UnfoldOp : public framework::OperatorWithKernel { public: using framework::OperatorWithKernel::OperatorWithKernel; - void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE_EQ( - ctx->HasInput("X"), true, - platform::errors::NotFound("Input(X) of UnfoldOp should not be null")); - PADDLE_ENFORCE_EQ( - ctx->HasOutput("Y"), true, - platform::errors::NotFound("Output(Y) of UnfoldOp should not be null")); - auto in_dims = ctx->GetInputDim("X"); - std::vector kernel_sizes = - ctx->Attrs().Get>("kernel_sizes"); - std::vector strides = ctx->Attrs().Get>("strides"); - std::vector paddings = ctx->Attrs().Get>("paddings"); - std::vector dilations = - ctx->Attrs().Get>("dilations"); - - // Only [N, C, H, W] input supported now - PADDLE_ENFORCE_EQ( - in_dims.size(), 4, - platform::errors::InvalidArgument( - "Input should be 4-D tensor of format [N, C, H, W], but get %u", - in_dims.size())); - PADDLE_ENFORCE_EQ( - in_dims.size() - kernel_sizes.size(), 2U, - platform::errors::InvalidArgument( - "The dims of X should be larger than that of kernel_sizes " - "by a number of 2, due to the batch size and input channel dim. " - "But recieved dims(X:%u) - dims(kernel_sizes:%u) != 2", - in_dims.size(), kernel_sizes.size())); - PADDLE_ENFORCE_EQ( - strides.size(), kernel_sizes.size(), - platform::errors::InvalidArgument( - "The dims of strides should be the same with that of kernel_sizes. " - "But recieved dims(strides: %u) != dims(kernel_sizes: %u).", - strides.size(), kernel_sizes.size())); - PADDLE_ENFORCE_EQ( - paddings.size(), 2 * strides.size(), - platform::errors::InvalidArgument( - "The dims of paddings should be 2 times of that of strides. " - "But recieved dims(paddings: %u) != 2*dims(strides: %u).", - paddings.size(), strides.size())); - PADDLE_ENFORCE_EQ( - strides.size(), dilations.size(), - platform::errors::InvalidArgument( - "The dims of strides should be the same with that of dilations. " - "But recieved dims(strides: %u) != dims(dilations: %u).", - strides.size(), dilations.size())); - - // check kernel_sizes - PADDLE_ENFORCE_GT(kernel_sizes[0], 0, - platform::errors::InvalidArgument( - "The `kernel_sizes` should be greater than zero, " - "but recieved kernel_height: %d kernel_width: %d.", - kernel_sizes[0], kernel_sizes[1])); - PADDLE_ENFORCE_GT(kernel_sizes[1], 0, - platform::errors::InvalidArgument( - "The `kernel_sizes` should be greater than zero, " - "but recieved kernel_height: %d kernel_width: %d.", - kernel_sizes[0], kernel_sizes[1])); - // check strides - PADDLE_ENFORCE_GT(strides[0], 0, - platform::errors::InvalidArgument( - "The `strides` should be greater than zero, " - "but recieved strides_height: %d strides_width: %d.", - strides[0], strides[1])); - PADDLE_ENFORCE_GT(strides[1], 0, - platform::errors::InvalidArgument( - "The `strides` should be greater than zero, " - "but recieved strides_height: %d strides_width: %d.", - strides[0], strides[1])); - // check dilations - PADDLE_ENFORCE_GT( - dilations[0], 0, - platform::errors::InvalidArgument( - "The `dilations` should be greater than zero, " - "but recieved dilations_height: %d dilations_width: %d.", - dilations[0], dilations[1])); - PADDLE_ENFORCE_GT( - dilations[1], 0, - platform::errors::InvalidArgument( - "The `dilations` should be greater than zero, " - "but recieved dilations_height: %d dilations_width: %d.", - dilations[0], dilations[1])); - - std::vector out_dims; - out_dims.push_back(in_dims[0]); - int output_channels = in_dims[1] * kernel_sizes[0] * kernel_sizes[1]; - out_dims.push_back(output_channels); - - int output_height = - CalcOutputSize(in_dims[2], kernel_sizes[0], dilations[0], paddings[0], - paddings[2], strides[0]); - int output_width = CalcOutputSize(in_dims[3], kernel_sizes[1], dilations[1], - paddings[1], paddings[3], strides[1]); - if (ctx->IsRuntime()) { - // only check output height and width in runtime - PADDLE_ENFORCE_GT( - output_height, 0, - platform::errors::InvalidArgument( - "The sliding blocks calculated from input spatial size " - "(%d, %d), kernel_sizes (%d, %d), strides (%d, %d), " - "dilations (%d, %d), is (%d, %d), which should be a " - "positive integer.", - in_dims[2], in_dims[3], kernel_sizes[0], kernel_sizes[1], - strides[0], strides[1], dilations[0], dilations[1], output_height, - output_width)); - PADDLE_ENFORCE_GT( - output_width, 0, - platform::errors::InvalidArgument( - "The sliding blocks calculated from input spatial size " - "(%d, %d), kernel_sizes (%d, %d), strides (%d, %d), " - "dilations (%d, %d), is (%d, %d), which should be a " - "positive integer.", - in_dims[2], in_dims[3], kernel_sizes[0], kernel_sizes[1], - strides[0], strides[1], dilations[0], dilations[1], output_height, - output_width)); - } - int output_col_length = output_height * output_width; - out_dims.push_back(output_col_length); - ctx->SetOutputDim("Y", phi::make_ddim(out_dims)); - } protected: framework::OpKernelType GetExpectedKernelType( @@ -237,16 +119,11 @@ DECLARE_NO_NEED_BUFFER_VARS_INFERER(UnfoldGradOpNoNeedBufferVarsInferer, "X"); } // namespace paddle namespace ops = paddle::operators; +DELCARE_INFER_SHAPE_FUNCTOR(unfold, UnfoldInferShapeFunctor, + PT_INFER_META(phi::UnfoldInferMeta)); REGISTER_OPERATOR(unfold, ops::UnfoldOp, ops::UnfoldOpMaker, ops::UnfoldGradMaker, - ops::UnfoldGradMaker); + ops::UnfoldGradMaker, + UnfoldInferShapeFunctor); REGISTER_OPERATOR(unfold_grad, ops::UnfoldGradOp, ops::UnfoldGradOpNoNeedBufferVarsInferer); - -REGISTER_OP_CPU_KERNEL( - unfold, ops::UnfoldOpKernel, - ops::UnfoldOpKernel); -REGISTER_OP_CPU_KERNEL( - unfold_grad, - ops::UnfoldGradOpKernel, - ops::UnfoldGradOpKernel); diff --git a/paddle/fluid/operators/unfold_op.cu b/paddle/fluid/operators/unfold_op.cu deleted file mode 100644 index 46584506d43..00000000000 --- a/paddle/fluid/operators/unfold_op.cu +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (c) 2019 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. -Indicesou 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 "paddle/fluid/operators/unfold_op.h" - -namespace ops = paddle::operators; - -REGISTER_OP_CUDA_KERNEL( - unfold, ops::UnfoldOpKernel, - ops::UnfoldOpKernel); - -REGISTER_OP_CUDA_KERNEL( - unfold_grad, - ops::UnfoldGradOpKernel, - ops::UnfoldGradOpKernel); diff --git a/paddle/fluid/operators/unfold_op.h b/paddle/fluid/operators/unfold_op.h deleted file mode 100644 index f35bce3abff..00000000000 --- a/paddle/fluid/operators/unfold_op.h +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (c) 2019 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. */ - -#pragma once - -#include -#include - -#include "paddle/fluid/framework/op_registry.h" -#include "paddle/fluid/operators/math/im2col.h" -#include "paddle/phi/kernels/funcs/math_function.h" - -namespace paddle { -namespace operators { - -using Tensor = framework::Tensor; - -inline int CalcOutputSize(int input_size, int filter_size, int dilation, - int padding1, int padding2, int stride) { - const int dkernel = dilation * (filter_size - 1) + 1; - int output_size = (input_size + padding1 + padding2 - dkernel) / stride + 1; - return output_size; -} - -template -class UnfoldOpKernel : public framework::OpKernel { - public: - void Compute(const framework::ExecutionContext& ctx) const override { - const Tensor* input = ctx.Input("X"); - const int batch_size = static_cast(input->dims()[0]); - Tensor* output = ctx.Output("Y"); - output->mutable_data(ctx.GetPlace()); - - std::vector kernel_sizes = ctx.Attr>("kernel_sizes"); - std::vector strides = ctx.Attr>("strides"); - std::vector paddings = ctx.Attr>("paddings"); - std::vector dilations = ctx.Attr>("dilations"); - - math::Im2ColFunctor im2col; - auto& dev_ctx = ctx.template device_context(); - - auto input_dims = input->dims(); - - int output_height = - CalcOutputSize(input_dims[2], kernel_sizes[0], dilations[0], - paddings[0], paddings[2], strides[0]); - int output_width = - CalcOutputSize(input_dims[3], kernel_sizes[1], dilations[1], - paddings[1], paddings[3], strides[1]); - - framework::DDim input_shape({input_dims[1], input_dims[2], input_dims[3]}); - framework::DDim output_matrix_shape({input_dims[1], kernel_sizes[0], - kernel_sizes[1], output_height, - output_width}); - - for (int i = 0; i < batch_size; i++) { - Tensor in_batch = input->Slice(i, i + 1).Resize(input_shape); - Tensor out_batch = output->Slice(i, i + 1).Resize(output_matrix_shape); - im2col(dev_ctx, in_batch, dilations, strides, paddings, &out_batch); - } - } -}; - -template -class UnfoldGradOpKernel : public framework::OpKernel { - public: - void Compute(const framework::ExecutionContext& ctx) const override { - const Tensor* output_grad = ctx.Input(framework::GradVarName("Y")); - Tensor* input_grad = ctx.Output(framework::GradVarName("X")); - input_grad->mutable_data(ctx.GetPlace()); - - if ((!output_grad) || (!input_grad)) return; - - std::vector kernel_sizes = ctx.Attr>("kernel_sizes"); - std::vector strides = ctx.Attr>("strides"); - std::vector paddings = ctx.Attr>("paddings"); - std::vector dilations = ctx.Attr>("dilations"); - - const int batch_size = static_cast(input_grad->dims()[0]); - - auto input_dims = input_grad->dims(); - - int output_height = - CalcOutputSize(input_dims[2], kernel_sizes[0], dilations[0], - paddings[0], paddings[2], strides[0]); - int output_width = - CalcOutputSize(input_dims[3], kernel_sizes[1], dilations[1], - paddings[1], paddings[3], strides[1]); - - framework::DDim input_shape({input_dims[1], input_dims[2], input_dims[3]}); - framework::DDim output_matrix_shape({input_dims[1], kernel_sizes[0], - kernel_sizes[1], output_height, - output_width}); - - math::Col2ImFunctor col2im; - auto& dev_ctx = ctx.template device_context(); - - phi::funcs::SetConstant set_zero; - set_zero(dev_ctx, input_grad, static_cast(0)); - for (int i = 0; i < batch_size; i++) { - Tensor out_grad_batch = - output_grad->Slice(i, i + 1).Resize(output_matrix_shape); - Tensor in_grad_batch = input_grad->Slice(i, i + 1).Resize(input_shape); - col2im(dev_ctx, out_grad_batch, dilations, strides, paddings, - &in_grad_batch); - } - } -}; -} // namespace operators -} // namespace paddle diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index 66a91e0ca53..fda395e6d95 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -18,6 +18,7 @@ limitations under the License. */ #include "paddle/phi/common/data_type.h" #include "paddle/phi/core/enforce.h" #include "paddle/phi/core/infermeta_utils.h" +#include "paddle/phi/kernels/funcs/unfold_functor.h" namespace phi { @@ -537,6 +538,164 @@ void TraceInferMeta( out->set_dims(phi::make_ddim(sizes)); } +void UnfoldInferMeta(const MetaTensor& x, + const std::vector& kernel_sizes, + const std::vector& strides, + const std::vector& paddings, + const std::vector& dilations, + MetaTensor* out, + MetaConfig config) { + auto in_dims = x.dims(); + // Only [N, C, H, W] input supported now + PADDLE_ENFORCE_EQ( + in_dims.size(), + 4, + phi::errors::InvalidArgument( + "Input should be 4-D tensor of format [N, C, H, W], but get %u", + in_dims.size())); + PADDLE_ENFORCE_EQ( + in_dims.size() - kernel_sizes.size(), + 2U, + phi::errors::InvalidArgument( + "The dims of X should be larger than that of kernel_sizes " + "by a number of 2, due to the batch size and input channel dim. " + "But recieved dims(X:%u) - dims(kernel_sizes:%u) != 2", + in_dims.size(), + kernel_sizes.size())); + PADDLE_ENFORCE_EQ( + strides.size(), + kernel_sizes.size(), + phi::errors::InvalidArgument( + "The dims of strides should be the same with that of kernel_sizes. " + "But recieved dims(strides: %u) != dims(kernel_sizes: %u).", + strides.size(), + kernel_sizes.size())); + PADDLE_ENFORCE_EQ( + paddings.size(), + 2 * strides.size(), + phi::errors::InvalidArgument( + "The dims of paddings should be 2 times of that of strides. " + "But recieved dims(paddings: %u) != 2*dims(strides: %u).", + paddings.size(), + strides.size())); + PADDLE_ENFORCE_EQ( + strides.size(), + dilations.size(), + phi::errors::InvalidArgument( + "The dims of strides should be the same with that of dilations. " + "But recieved dims(strides: %u) != dims(dilations: %u).", + strides.size(), + dilations.size())); + + // check kernel_sizes + PADDLE_ENFORCE_GT(kernel_sizes[0], + 0, + phi::errors::InvalidArgument( + "The `kernel_sizes` should be greater than zero, " + "but recieved kernel_height: %d kernel_width: %d.", + kernel_sizes[0], + kernel_sizes[1])); + PADDLE_ENFORCE_GT(kernel_sizes[1], + 0, + phi::errors::InvalidArgument( + "The `kernel_sizes` should be greater than zero, " + "but recieved kernel_height: %d kernel_width: %d.", + kernel_sizes[0], + kernel_sizes[1])); + // check strides + PADDLE_ENFORCE_GT(strides[0], + 0, + phi::errors::InvalidArgument( + "The `strides` should be greater than zero, " + "but recieved strides_height: %d strides_width: %d.", + strides[0], + strides[1])); + PADDLE_ENFORCE_GT(strides[1], + 0, + phi::errors::InvalidArgument( + "The `strides` should be greater than zero, " + "but recieved strides_height: %d strides_width: %d.", + strides[0], + strides[1])); + // check dilations + PADDLE_ENFORCE_GT( + dilations[0], + 0, + phi::errors::InvalidArgument( + "The `dilations` should be greater than zero, " + "but recieved dilations_height: %d dilations_width: %d.", + dilations[0], + dilations[1])); + PADDLE_ENFORCE_GT( + dilations[1], + 0, + phi::errors::InvalidArgument( + "The `dilations` should be greater than zero, " + "but recieved dilations_height: %d dilations_width: %d.", + dilations[0], + dilations[1])); + + std::vector out_dims; + out_dims.push_back(in_dims[0]); + int output_channels = in_dims[1] * kernel_sizes[0] * kernel_sizes[1]; + out_dims.push_back(output_channels); + + int output_height = phi::funcs::CalcOutputSize(in_dims[2], + kernel_sizes[0], + dilations[0], + paddings[0], + paddings[2], + strides[0]); + int output_width = phi::funcs::CalcOutputSize(in_dims[3], + kernel_sizes[1], + dilations[1], + paddings[1], + paddings[3], + strides[1]); + if (config.is_runtime) { + // only check output height and width in runtime + PADDLE_ENFORCE_GT( + output_height, + 0, + phi::errors::InvalidArgument( + "The sliding blocks calculated from input spatial size " + "(%d, %d), kernel_sizes (%d, %d), strides (%d, %d), " + "dilations (%d, %d), is (%d, %d), which should be a " + "positive integer.", + in_dims[2], + in_dims[3], + kernel_sizes[0], + kernel_sizes[1], + strides[0], + strides[1], + dilations[0], + dilations[1], + output_height, + output_width)); + PADDLE_ENFORCE_GT( + output_width, + 0, + phi::errors::InvalidArgument( + "The sliding blocks calculated from input spatial size " + "(%d, %d), kernel_sizes (%d, %d), strides (%d, %d), " + "dilations (%d, %d), is (%d, %d), which should be a " + "positive integer.", + in_dims[2], + in_dims[3], + kernel_sizes[0], + kernel_sizes[1], + strides[0], + strides[1], + dilations[0], + dilations[1], + output_height, + output_width)); + } + int output_col_length = output_height * output_width; + out_dims.push_back(output_col_length); + out->set_dims(phi::make_ddim(out_dims)); +} + } // namespace phi PD_REGISTER_INFER_META_FN(copy_to, phi::CopyToInferMeta); diff --git a/paddle/phi/infermeta/unary.h b/paddle/phi/infermeta/unary.h index 2ab425d42cd..c6d5d250d98 100644 --- a/paddle/phi/infermeta/unary.h +++ b/paddle/phi/infermeta/unary.h @@ -93,4 +93,11 @@ void SplitInferMeta(const MetaTensor& x_meta, void TraceInferMeta( const MetaTensor& x, int offset, int axis1, int axis2, MetaTensor* out); +void UnfoldInferMeta(const MetaTensor& x, + const std::vector& kernel_sizes, + const std::vector& strides, + const std::vector& paddings, + const std::vector& dilations, + MetaTensor* out, + MetaConfig config = MetaConfig()); } // namespace phi diff --git a/paddle/phi/kernels/CMakeLists.txt b/paddle/phi/kernels/CMakeLists.txt index 4f78a6500f4..f819eb3de3e 100644 --- a/paddle/phi/kernels/CMakeLists.txt +++ b/paddle/phi/kernels/CMakeLists.txt @@ -10,7 +10,7 @@ add_subdirectory(funcs) set_property(GLOBAL PROPERTY PTEN_KERNELS "") set(COMMON_KERNEL_DEPS dense_tensor sparse_coo_tensor sparse_csr_tensor kernel_context kernel_factory arg_map_context convert_utils lod_utils) -set(COMMON_KERNEL_DEPS ${COMMON_KERNEL_DEPS} eigen_function blas math_function) +set(COMMON_KERNEL_DEPS ${COMMON_KERNEL_DEPS} eigen_function blas math_function im2col) # remove this dep after removing fluid deps on tensor creation set(COMMON_KERNEL_DEPS ${COMMON_KERNEL_DEPS} pten_api_utils) set(COMMON_KERNEL_DEPS ${COMMON_KERNEL_DEPS} infermeta) diff --git a/paddle/phi/kernels/cpu/unfold_grad_kernel.cc b/paddle/phi/kernels/cpu/unfold_grad_kernel.cc new file mode 100644 index 00000000000..c97005dd845 --- /dev/null +++ b/paddle/phi/kernels/cpu/unfold_grad_kernel.cc @@ -0,0 +1,21 @@ +// Copyright (c) 2022 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 "paddle/phi/kernels/unfold_grad_kernel.h" +#include "paddle/phi/backends/cpu/cpu_context.h" +#include "paddle/phi/core/kernel_registry.h" +#include "paddle/phi/kernels/impl/unfold_grad_kernel_impl.h" + +PD_REGISTER_KERNEL( + unfold_grad, CPU, ALL_LAYOUT, phi::UnfoldGradKernel, float, double) {} diff --git a/paddle/phi/kernels/cpu/unfold_kernel.cc b/paddle/phi/kernels/cpu/unfold_kernel.cc new file mode 100644 index 00000000000..e38d8acd098 --- /dev/null +++ b/paddle/phi/kernels/cpu/unfold_kernel.cc @@ -0,0 +1,20 @@ +// Copyright (c) 2022 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 "paddle/phi/kernels/unfold_kernel.h" +#include "paddle/phi/backends/cpu/cpu_context.h" +#include "paddle/phi/core/kernel_registry.h" +#include "paddle/phi/kernels/impl/unfold_kernel_impl.h" + +PD_REGISTER_KERNEL(unfold, CPU, ALL_LAYOUT, phi::UnfoldKernel, float, double) {} diff --git a/paddle/phi/kernels/funcs/unfold_functor.h b/paddle/phi/kernels/funcs/unfold_functor.h new file mode 100644 index 00000000000..2bd5437a7f1 --- /dev/null +++ b/paddle/phi/kernels/funcs/unfold_functor.h @@ -0,0 +1,33 @@ +// Copyright (c) 2022 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. + +#pragma once + +namespace phi { +namespace funcs { + +//////// CalcOutputSize Functor /////// +inline int CalcOutputSize(int input_size, + int filter_size, + int dilation, + int padding1, + int padding2, + int stride) { + const int dkernel = dilation * (filter_size - 1) + 1; + int output_size = (input_size + padding1 + padding2 - dkernel) / stride + 1; + return output_size; +} + +} // namespace funcs +} // namespace phi diff --git a/paddle/phi/kernels/gpu/unfold_grad_kernel.cu b/paddle/phi/kernels/gpu/unfold_grad_kernel.cu new file mode 100644 index 00000000000..3740f59603b --- /dev/null +++ b/paddle/phi/kernels/gpu/unfold_grad_kernel.cu @@ -0,0 +1,21 @@ +// Copyright (c) 2022 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 "paddle/phi/backends/gpu/gpu_context.h" +#include "paddle/phi/core/kernel_registry.h" +#include "paddle/phi/kernels/impl/unfold_grad_kernel_impl.h" +#include "paddle/phi/kernels/unfold_grad_kernel.h" + +PD_REGISTER_KERNEL( + unfold_grad, GPU, ALL_LAYOUT, phi::UnfoldGradKernel, float, double) {} diff --git a/paddle/phi/kernels/gpu/unfold_kernel.cu b/paddle/phi/kernels/gpu/unfold_kernel.cu new file mode 100644 index 00000000000..4f72a6f794e --- /dev/null +++ b/paddle/phi/kernels/gpu/unfold_kernel.cu @@ -0,0 +1,20 @@ +// Copyright (c) 2022 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 "paddle/phi/backends/gpu/gpu_context.h" +#include "paddle/phi/core/kernel_registry.h" +#include "paddle/phi/kernels/impl/unfold_kernel_impl.h" +#include "paddle/phi/kernels/unfold_kernel.h" + +PD_REGISTER_KERNEL(unfold, GPU, ALL_LAYOUT, phi::UnfoldKernel, float, double) {} diff --git a/paddle/phi/kernels/impl/unfold_grad_kernel_impl.h b/paddle/phi/kernels/impl/unfold_grad_kernel_impl.h new file mode 100644 index 00000000000..5556654ee7c --- /dev/null +++ b/paddle/phi/kernels/impl/unfold_grad_kernel_impl.h @@ -0,0 +1,72 @@ +// Copyright (c) 2022 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. + +#pragma once + +#include +#include "paddle/fluid/operators/math/im2col.h" +#include "paddle/phi/core/dense_tensor.h" +#include "paddle/phi/kernels/funcs/math_function.h" +#include "paddle/phi/kernels/funcs/unfold_functor.h" + +namespace phi { + +template +void UnfoldGradKernel(const Context& ctx, + const DenseTensor& x, + const DenseTensor& out_grad, + const std::vector& kernel_sizes, + const std::vector& strides, + const std::vector& paddings, + const std::vector& dilations, + DenseTensor* x_grad) { + ctx.template Alloc(x_grad); + + if (!x_grad) return; + + auto x_dims = x_grad->dims(); + const int batch_size = static_cast(x_dims[0]); + + int out_height = phi::funcs::CalcOutputSize(x_dims[2], + kernel_sizes[0], + dilations[0], + paddings[0], + paddings[2], + strides[0]); + int out_width = phi::funcs::CalcOutputSize(x_dims[3], + kernel_sizes[1], + dilations[1], + paddings[1], + paddings[3], + strides[1]); + + DDim x_shape = make_ddim({x_dims[1], x_dims[2], x_dims[3]}); + DDim out_matrix_shape = make_ddim( + {x_dims[1], kernel_sizes[0], kernel_sizes[1], out_height, out_width}); + + paddle::operators::math:: + Col2ImFunctor + col2im; + + phi::funcs::SetConstant set_zero; + set_zero(ctx, x_grad, static_cast(0)); + for (int i = 0; i < batch_size; i++) { + DenseTensor out_grad_batch = + out_grad.Slice(i, i + 1).Resize(out_matrix_shape); + DenseTensor x_grad_batch = x_grad->Slice(i, i + 1).Resize(x_shape); + col2im(ctx, out_grad_batch, dilations, strides, paddings, &x_grad_batch); + } +} + +} // namespace phi diff --git a/paddle/phi/kernels/impl/unfold_kernel_impl.h b/paddle/phi/kernels/impl/unfold_kernel_impl.h new file mode 100644 index 00000000000..e914f6cacbd --- /dev/null +++ b/paddle/phi/kernels/impl/unfold_kernel_impl.h @@ -0,0 +1,65 @@ +// Copyright (c) 2022 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. + +#pragma once + +#include +#include "paddle/fluid/operators/math/im2col.h" +#include "paddle/phi/core/dense_tensor.h" +#include "paddle/phi/kernels/funcs/math_function.h" +#include "paddle/phi/kernels/funcs/unfold_functor.h" + +namespace phi { + +template +void UnfoldKernel(const Context& ctx, + const DenseTensor& x, + const std::vector& kernel_sizes, + const std::vector& strides, + const std::vector& paddings, + const std::vector& dilations, + DenseTensor* out) { + const int batch_size = static_cast(x.dims()[0]); + ctx.template Alloc(out); + + paddle::operators::math:: + Im2ColFunctor + im2col; + auto x_dims = x.dims(); + + int out_height = phi::funcs::CalcOutputSize(x_dims[2], + kernel_sizes[0], + dilations[0], + paddings[0], + paddings[2], + strides[0]); + int out_width = phi::funcs::CalcOutputSize(x_dims[3], + kernel_sizes[1], + dilations[1], + paddings[1], + paddings[3], + strides[1]); + + DDim x_shape = make_ddim({x_dims[1], x_dims[2], x_dims[3]}); + DDim out_matrix_shape = make_ddim( + {x_dims[1], kernel_sizes[0], kernel_sizes[1], out_height, out_width}); + + for (int i = 0; i < batch_size; i++) { + DenseTensor in_batch = x.Slice(i, i + 1).Resize(x_shape); + DenseTensor out_batch = out->Slice(i, i + 1).Resize(out_matrix_shape); + im2col(ctx, in_batch, dilations, strides, paddings, &out_batch); + } +} + +} // namespace phi diff --git a/paddle/phi/kernels/unfold_grad_kernel.h b/paddle/phi/kernels/unfold_grad_kernel.h new file mode 100644 index 00000000000..6578cf8c650 --- /dev/null +++ b/paddle/phi/kernels/unfold_grad_kernel.h @@ -0,0 +1,32 @@ +// Copyright (c) 2022 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. + +#pragma once + +#include "paddle/phi/core/dense_tensor.h" +#include "paddle/phi/core/device_context.h" + +namespace phi { + +template +void UnfoldGradKernel(const Context& ctx, + const DenseTensor& x, + const DenseTensor& out_grad, + const std::vector& kernel_sizes, + const std::vector& strides, + const std::vector& paddings, + const std::vector& dilations, + DenseTensor* x_grad); + +} // namespace phi diff --git a/paddle/phi/kernels/unfold_kernel.h b/paddle/phi/kernels/unfold_kernel.h new file mode 100644 index 00000000000..d26805e9786 --- /dev/null +++ b/paddle/phi/kernels/unfold_kernel.h @@ -0,0 +1,31 @@ +// Copyright (c) 2022 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. + +#pragma once + +#include "paddle/phi/core/dense_tensor.h" +#include "paddle/phi/core/device_context.h" + +namespace phi { + +template +void UnfoldKernel(const Context& ctx, + const DenseTensor& x, + const std::vector& kernel_sizes, + const std::vector& strides, + const std::vector& paddings, + const std::vector& dilations, + DenseTensor* out); + +} // namespace phi diff --git a/paddle/phi/ops/compat/unfold_sig.cc b/paddle/phi/ops/compat/unfold_sig.cc new file mode 100644 index 00000000000..ddc3b1813cb --- /dev/null +++ b/paddle/phi/ops/compat/unfold_sig.cc @@ -0,0 +1,28 @@ +/* Copyright (c) 2022 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 "paddle/phi/core/compat/op_utils.h" + +namespace phi { + +KernelSignature UnfoldGradOpArgumentMapping(const ArgumentMappingContext& ctx) { + return KernelSignature("unfold_grad", + {"X", GradVarName("Y")}, + {"kernel_sizes", "strides", "paddings", "dilations"}, + {GradVarName("X")}); +} + +} // namespace phi + +PD_REGISTER_ARG_MAPPING_FN(unfold_grad, phi::UnfoldGradOpArgumentMapping); -- GitLab