From d7ffa2cc572f28b085127e1810be22ca2f2d237a Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 08:55:27 +0800 Subject: [PATCH 01/32] Add infermeta for ChannelShuffle --- paddle/phi/infermeta/unary.cc | 36 +++++++++++++++++++++++++++++++++++ paddle/phi/infermeta/unary.h | 5 +++++ 2 files changed, 41 insertions(+) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index e0ea637074c20..0a978c537b45a 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2863,6 +2863,42 @@ void WhereIndexInferMeta(const MetaTensor& condition, MetaTensor* out) { out->set_dtype(DataType::INT64); } +void ChannelShuffleInferMeta(const MetaTensor& x, + int groups, + const std::string& data_format, + MetaTensor* out) { + auto input_dims = x.dims(); + PADDLE_ENFORCE_EQ(input_dims.size(), + 4, + phi::errors::InvalidArgument( + "Input should be a 4-D tensor of format [N, C, H, W] " + "or [N, H, W, C], but got %u.", + input_dims.size())); + + const bool channel_last = (data_format == "NHWC"); + + if (!channel_last) { + PADDLE_ENFORCE_EQ(input_dims[1] % groups, + 0, + phi::errors::InvalidArgument( + "The number of groups to divide channels in[%u] " + "should divide the number of channel[%u]", + groups, + input_dims[1])); + } else { + PADDLE_ENFORCE_EQ(input_dims[3] % groups, + 0, + phi::errors::InvalidArgument( + "The number of groups to divide channels in[%u] " + "should divide the number of channel[%u]", + groups, + input_dims[3])); + } + auto output_dims = input_dims; + out->set_dtype(x.dtype()); + out->set_dims(output_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 5106c6f448733..c6a409ddbd22b 100644 --- a/paddle/phi/infermeta/unary.h +++ b/paddle/phi/infermeta/unary.h @@ -426,4 +426,9 @@ void OneHotInferMeta(const MetaTensor& x, const Scalar& depth, MetaTensor* out); void WhereIndexInferMeta(const MetaTensor& condition, MetaTensor* out); +void ChannelShuffleInferMeta(const MetaTensor& x, + int groups, + const std::string& data_format, + MetaTensor* out); + } // namespace phi From b1f69154e1b0fb3933c8a272ba6eed95340d314d Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 09:07:51 +0800 Subject: [PATCH 02/32] Create channel_shuffle_grad_kernel.h --- .../phi/kernels/channel_shuffle_grad_kernel.h | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 paddle/phi/kernels/channel_shuffle_grad_kernel.h diff --git a/paddle/phi/kernels/channel_shuffle_grad_kernel.h b/paddle/phi/kernels/channel_shuffle_grad_kernel.h new file mode 100644 index 0000000000000..1b02f22b25f6d --- /dev/null +++ b/paddle/phi/kernels/channel_shuffle_grad_kernel.h @@ -0,0 +1,29 @@ +// 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/phi/core/dense_tensor.h" + +namespace phi { + +template +void ChannelShuffleGradKernel(const Context& ctx, + const DenseTensor& out_grad, + int groups, + const std::string& data_format, + DenseTensor* x_grad); + +} // namespace phi From 6ca6e5c3428e415da30b7c5655e2d09000b0db22 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 09:07:54 +0800 Subject: [PATCH 03/32] Create channel_shuffle_kernel.h --- paddle/phi/kernels/channel_shuffle_kernel.h | 29 +++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 paddle/phi/kernels/channel_shuffle_kernel.h diff --git a/paddle/phi/kernels/channel_shuffle_kernel.h b/paddle/phi/kernels/channel_shuffle_kernel.h new file mode 100644 index 0000000000000..a3bacef963c3c --- /dev/null +++ b/paddle/phi/kernels/channel_shuffle_kernel.h @@ -0,0 +1,29 @@ +// 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/phi/core/dense_tensor.h" + +namespace phi { + +template +void ChannelShuffleKernel(const Context& ctx, + const DenseTensor& x, + int groups, + const std::string& data_format, + DenseTensor* out); + +} // namespace phi From 9b5fa4070eb2283b7758e5b37e8adf76ed588690 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 10:55:21 +0800 Subject: [PATCH 04/32] Create channel_shuffle_sig.cc --- paddle/phi/ops/compat/channel_shuffle_sig.cc | 37 ++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 paddle/phi/ops/compat/channel_shuffle_sig.cc diff --git a/paddle/phi/ops/compat/channel_shuffle_sig.cc b/paddle/phi/ops/compat/channel_shuffle_sig.cc new file mode 100644 index 0000000000000..da424081d765e --- /dev/null +++ b/paddle/phi/ops/compat/channel_shuffle_sig.cc @@ -0,0 +1,37 @@ +// 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 ChannelShuffleOpArgumentMapping( + const ArgumentMappingContext& ctx) { + return KernelSignature( + "channel_shuffle", {"X"}, {"groups", "data_format"}, {"Out"}); +} + +KernelSignature ChannelShuffleGradOpArgumentMapping( + const ArgumentMappingContext& ctx) { + return KernelSignature("channel_shuffle_grad", + {GradVarName("Out")}, + {"groups", "data_format"}, + {GradVarName("X")}); +} + +} // namespace phi + +PD_REGISTER_ARG_MAPPING_FN(channel_shuffle, phi::ChannelShuffleOpArgumentMapping); +PD_REGISTER_ARG_MAPPING_FN(channel_shuffle_grad, + phi::ChannelShuffleGradOpArgumentMapping); From 7d77d463f90dafc5ef247902f8e2d03a3798f9ef Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 10:57:55 +0800 Subject: [PATCH 05/32] Create channel_shuffle_op.cc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ChannelShuffle算子的描述 --- paddle/fluid/operators/channel_shuffle_op.cc | 121 +++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 paddle/fluid/operators/channel_shuffle_op.cc diff --git a/paddle/fluid/operators/channel_shuffle_op.cc b/paddle/fluid/operators/channel_shuffle_op.cc new file mode 100644 index 0000000000000..419c63a61a507 --- /dev/null +++ b/paddle/fluid/operators/channel_shuffle_op.cc @@ -0,0 +1,121 @@ +/* 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 +#include "paddle/fluid/framework/infershape_utils.h" +#include "paddle/fluid/framework/op_registry.h" +#include "paddle/fluid/framework/op_version_registry.h" +#include "paddle/phi/core/infermeta_utils.h" +#include "paddle/phi/infermeta/unary.h" + +namespace paddle { +namespace operators { + +class ChannelShuffleOp : public framework::OperatorWithKernel { + public: + using framework::OperatorWithKernel::OperatorWithKernel; +}; + +class ChannelShuffleOpMaker : public framework::OpProtoAndCheckerMaker { + public: + void Make() override { + AddInput("X", + "(Tensor, default Tensor), " + "the input feature data of ChannelShuffleOp, the layout is " + "[N, C, H, W] or [N, H, W, C]."); + AddOutput("Out", + "(Tensor, default Tensor), the output of " + "ChannelShuffleOp. The layout is also [N, C, " + "H, W] or [N, H, W, C]."); + AddAttr("groups", + "number of groups to divide channels in.") + .AddCustomChecker([](const int& groups) { + PADDLE_ENFORCE_GE(groups, 1, + platform::errors::InvalidArgument( + "groups should be larger than 0.")); + }); + AddAttr( + "data_format", + "An optional string from: \"NHWC\", \"NCHW\". " + "Defaults to \"NHWC\", Specify the data format of the input data.") + .SetDefault("NCHW"); + + AddComment(R"DOC( + Channel Shuffle operator + This operator divides channels in a tensor of shape :math:`(*, C, H, W)` + into :math:`g` groups and rearranges them as :math:`(*, C/g, g, H, W)` + while keeping the original tensor shape. + + Please refer to the paper: + `ShuffleNet: An Extremely Efficient Convolutional Neural Network for + Mobile Devices `_ + by Zhang et. al (2017) for more details. + + )DOC"); + } +}; + +class ChannelShuffleGradOp : public framework::OperatorWithKernel { + public: + using framework::OperatorWithKernel::OperatorWithKernel; + + void InferShape(framework::InferShapeContext* ctx) const override { + PADDLE_ENFORCE_EQ( + ctx->HasInput(framework::GradVarName("Out")), true, + platform::errors::NotFound("Input(Out@Grad) should not be null")); + PADDLE_ENFORCE_EQ( + ctx->HasOutput(framework::GradVarName("X")), true, + platform::errors::NotFound("Output(X@Grad) should not be null")); + + auto do_dims = ctx->GetInputDim(framework::GradVarName("Out")); + PADDLE_ENFORCE_EQ(do_dims.size(), 4, + platform::errors::InvalidArgument( + "Input should be a 4-D tensor of format [N, C, " + "H, W] or [N, H, W, C], but got %u.", + do_dims.size())); + + auto dx_dims = do_dims; + ctx->SetOutputDim(framework::GradVarName("X"), dx_dims); + } +}; + +template +class ChannelShuffleGradOpMaker : public framework::SingleGradOpMaker { + public: + using framework::SingleGradOpMaker::SingleGradOpMaker; + + protected: + void Apply(GradOpPtr op) const override { + op->SetType("channel_shuffle_grad"); + op->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out")); + op->SetAttrMap(this->Attrs()); + op->SetOutput(framework::GradVarName("X"), this->InputGrad("X")); + } +}; + +} // namespace operators +} // namespace paddle + +namespace ops = paddle::operators; +DECLARE_INFER_SHAPE_FUNCTOR(channel_shuffle, ChannelShuffleInferShapeFunctor, + PD_INFER_META(phi::ChannelShuffleInferMeta)); + +REGISTER_OPERATOR(channel_shuffle, + ops::ChannelShuffleOp, + ops::ChannelShuffleOpMaker, + ops::ChannelShuffleGradOpMaker, + ops::ChannelShuffleGradOpMaker, + ChannelShuffleInferShapeFunctor); + +REGISTER_OPERATOR(channel_shuffle_grad, ops::ChannelShuffleGradOp); From 4c34c106227e6f81cf6ecb2e3533146290d6343b Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 10:59:34 +0800 Subject: [PATCH 06/32] Create channel_shuffle_kernel_impl.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ChannelShuffle核函数的实现 --- .../impl/channel_shuffle_kernel_impl.h | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h diff --git a/paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h b/paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h new file mode 100644 index 0000000000000..27202ce5a23a5 --- /dev/null +++ b/paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h @@ -0,0 +1,55 @@ +// 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 +#include "paddle/phi/core/dense_tensor.h" +#include "paddle/phi/kernels/funcs/math_function.h" + +namespace phi { + +template +void ChannelShuffleKernel(const Context& ctx, + const DenseTensor& x, + int groups, + const std::string& data_format, + DenseTensor* out) { + auto* in = &x; + ctx.template Alloc(out); + bool channel_last = (data_format == "NHWC"); + auto in_dims = in->dims(); + auto o_dims = out->dims(); + + DenseTensor t(*in); + if (!channel_last) { + t.Resize({in_dims[0], groups, in_dims[1]/groups, in_dims[2], in_dims[3]}); + } else { + t.Resize({in_dims[0], in_dims[1], in_dims[2], groups, in_dims[3]/groups}); + } + auto axis = !channel_last ? std::vector {0, 2, 1, 3, 4} + : std::vector {0, 1, 2, 4, 3}; + + DenseTensor o(*out); + if (!channel_last) { + o.Resize({in_dims[0], in_dims[1]/groups, groups, in_dims[2], in_dims[3]}); + } else { + o.Resize({in_dims[0], in_dims[1], in_dims[2], in_dims[3]/groups, groups}); + } + phi::funcs::Transpose trans; + trans(ctx, t, &o, axis); + out->Resize(o_dims); +} + +} // namespace phi From be4df84365883f8b4908055f0070d52c27d17c8d Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:00:22 +0800 Subject: [PATCH 07/32] Create channel_shuffle_grad_kernel_impl.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ChannelShuffle反向核函数的实现 --- .../impl/channel_shuffle_grad_kernel_impl.h | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h diff --git a/paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h b/paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h new file mode 100644 index 0000000000000..4f6b265503a87 --- /dev/null +++ b/paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h @@ -0,0 +1,56 @@ +// 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 +#include "paddle/phi/core/dense_tensor.h" +#include "paddle/phi/kernels/funcs/math_function.h" + +namespace phi { + +template +void ChannelShuffleGradKernel(const Context& ctx, + const DenseTensor& out_grad, + int groups, + const std::string& data_format, + DenseTensor* x_grad) { + auto* dout = &out_grad; + auto* dx = x_grad; + ctx.template Alloc(dx); + bool channel_last = (data_format == "NHWC"); + auto do_dims = dout->dims(); + auto dx_dims = dx->dims(); + + DenseTensor t(*dout); + if (!channel_last) { + t.Resize({do_dims[0], do_dims[1]/groups, groups, do_dims[2], do_dims[3]}); + } else { + t.Resize({do_dims[0], do_dims[1], do_dims[2], do_dims[3]/groups, groups}); + } + auto axis = !channel_last ? std::vector {0, 2, 1, 3, 4} + : std::vector {0, 1, 2, 4, 3}; + + DenseTensor o(*dx); + if (!channel_last) { + o.Resize({dx_dims[0], groups, dx_dims[1]/groups, dx_dims[2], dx_dims[3]}); + } else { + o.Resize({dx_dims[0], dx_dims[1], dx_dims[2], groups, dx_dims[3]/groups}); + } + phi::funcs::Transpose trans; + trans(ctx, t, &o, axis); + dx->Resize(dx_dims); +} + +} // namespace phi From 51829fc62aa51136a17e74981177541a6b691533 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:03:38 +0800 Subject: [PATCH 08/32] Add kernel register of channel shuffle and grad MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 注册ChannelShuffle及其反向的核函数 --- .../cpu/channel_shuffle_grad_kernel.cc | 26 +++++++++++++++++++ .../phi/kernels/cpu/channel_shuffle_kernel.cc | 26 +++++++++++++++++++ .../gpu/channel_shuffle_grad_kernel.cu | 26 +++++++++++++++++++ .../phi/kernels/gpu/channel_shuffle_kernel.cu | 26 +++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc create mode 100644 paddle/phi/kernels/cpu/channel_shuffle_kernel.cc create mode 100644 paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu create mode 100644 paddle/phi/kernels/gpu/channel_shuffle_kernel.cu diff --git a/paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc b/paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc new file mode 100644 index 0000000000000..1f3466faa6bf9 --- /dev/null +++ b/paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc @@ -0,0 +1,26 @@ +// 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/channel_shuffle_grad_kernel.h" +#include "paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h" + +#include "paddle/phi/backends/cpu/cpu_context.h" +#include "paddle/phi/core/kernel_registry.h" + +PD_REGISTER_KERNEL(channel_shuffle_grad, + CPU, + ALL_LAYOUT, + phi::ChannelShuffleGradKernel, + float, + double) {} diff --git a/paddle/phi/kernels/cpu/channel_shuffle_kernel.cc b/paddle/phi/kernels/cpu/channel_shuffle_kernel.cc new file mode 100644 index 0000000000000..3377fb4dcd750 --- /dev/null +++ b/paddle/phi/kernels/cpu/channel_shuffle_kernel.cc @@ -0,0 +1,26 @@ +// 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/channel_shuffle_kernel.h" +#include "paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h" + +#include "paddle/phi/backends/cpu/cpu_context.h" +#include "paddle/phi/core/kernel_registry.h" + +PD_REGISTER_KERNEL(channel_shuffle, + CPU, + ALL_LAYOUT, + phi::ChannelShuffleKernel, + float, + double) {} diff --git a/paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu b/paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu new file mode 100644 index 0000000000000..e33deef259578 --- /dev/null +++ b/paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu @@ -0,0 +1,26 @@ +// 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/impl/channel_shuffle_grad_kernel_impl.h" +#include "paddle/phi/kernels/channel_shuffle_grad_kernel.h" + +#include "paddle/phi/backends/gpu/gpu_context.h" +#include "paddle/phi/core/kernel_registry.h" + +PD_REGISTER_KERNEL(channel_shuffle_grad, + GPU, + ALL_LAYOUT, + phi::ChannelShuffleGradKernel, + float, + double) {} diff --git a/paddle/phi/kernels/gpu/channel_shuffle_kernel.cu b/paddle/phi/kernels/gpu/channel_shuffle_kernel.cu new file mode 100644 index 0000000000000..28a1c6c64b749 --- /dev/null +++ b/paddle/phi/kernels/gpu/channel_shuffle_kernel.cu @@ -0,0 +1,26 @@ +// 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/impl/channel_shuffle_kernel_impl.h" +#include "paddle/phi/kernels/channel_shuffle_kernel.h" + +#include "paddle/phi/backends/gpu/gpu_context.h" +#include "paddle/phi/core/kernel_registry.h" + +PD_REGISTER_KERNEL(channel_shuffle, + GPU, + ALL_LAYOUT, + phi::ChannelShuffleKernel, + float, + double) {} From 25feafbd1455053a790d5f8707e2121a122fb6c2 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:12:18 +0800 Subject: [PATCH 09/32] add nn.functional.channel_shuffle --- python/paddle/nn/functional/__init__.py | 2 + python/paddle/nn/functional/vision.py | 57 +++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/python/paddle/nn/functional/__init__.py b/python/paddle/nn/functional/__init__.py index a24afc45a5995..58251c2890430 100644 --- a/python/paddle/nn/functional/__init__.py +++ b/python/paddle/nn/functional/__init__.py @@ -114,6 +114,7 @@ from .vision import affine_grid # noqa: F401 from .vision import grid_sample # noqa: F401 from .vision import pixel_shuffle # noqa: F401 +from .vision import channel_shuffle # noqa: F401 from .input import one_hot # noqa: F401 from .input import embedding # noqa: F401 from ...fluid.layers import gather_tree # noqa: F401 @@ -213,6 +214,7 @@ 'grid_sample', 'local_response_norm', 'pixel_shuffle', + 'channel_shuffle', 'embedding', 'gather_tree', 'one_hot', diff --git a/python/paddle/nn/functional/vision.py b/python/paddle/nn/functional/vision.py index 43c7757a8777b..89c9834cd0afa 100644 --- a/python/paddle/nn/functional/vision.py +++ b/python/paddle/nn/functional/vision.py @@ -344,3 +344,60 @@ def pixel_shuffle(x, upscale_factor, data_format="NCHW", name=None): attrs={"upscale_factor": upscale_factor, "data_format": data_format}) return out + +def channel_shuffle(x, groups, data_format="NCHW", name=None): + """ + This API implements channel shuffle operation. + See more details in :ref:`api_nn_vision_ChannelShuffle` . + Parameters: + x(Tensor): 4-D tensor, the data type should be float32 or float64. + groups(int): Number of groups to divide channels in. + data_format (str): The data format of the input and output data. An optional string from: "NCHW", "NHWC". The default is "NCHW". When it is "NCHW", the data is stored in the order of: [batch_size, input_channels, input_height, input_width]. + name (str, optional): The default value is None. Normally there is no need for user to set this property. + Returns: + Out(tensor): Rearranged tensor keeping the original tensor shape. + Raises: + ValueError: If the number of groups cannot divide the channels of input. + Examples: + .. code-block:: python + + import paddle + import paddle.nn.functional as F + x = paddle.arange(0, 0.6, 0.1, 'float32') + x = paddle.reshape(x, [1, 6, 1, 1]) + # [[[[0. ]], + # [[0.10000000]], + # [[0.20000000]], + # [[0.30000001]], + # [[0.40000001]], + # [[0.50000000]]]] + y = F.channel_shuffle(x, 3) + # [[[[0. ]], + # [[0.20000000]], + # [[0.40000001]], + # [[0.10000000]], + # [[0.30000001]], + # [[0.50000000]]]] + """ + if not isinstance(groups, int): + raise TypeError("groups must be int type") + + if data_format not in ["NCHW", "NHWC"]: + raise ValueError("Attr(data_format) should be 'NCHW' or 'NHWC'." + "But recevie Attr(data_format): {} ".format( + data_format)) + + if in_dynamic_mode(): + return _C_ops.channel_shuffle(x, "groups", groups, + "data_format", data_format) + + helper = LayerHelper("channel_shuffle", **locals()) + check_variable_and_dtype(x, 'x', ['float32', 'float64'], 'channel_shuffle') + out = helper.create_variable_for_type_inference(dtype=x.dtype) + helper.append_op( + type="channel_shuffle", + inputs={"X": x}, + outputs={"Out": out}, + attrs={"groups": groups, + "data_format": data_format}) + return out From 2f1a95875b124dd1de81a9405600ce15a8b846ec Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:12:55 +0800 Subject: [PATCH 10/32] add nn.ChannelShuffle --- python/paddle/nn/__init__.py | 2 + python/paddle/nn/layer/__init__.py | 1 + python/paddle/nn/layer/vision.py | 68 ++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/python/paddle/nn/__init__.py b/python/paddle/nn/__init__.py index b83a900059bf4..95f1b08607b6b 100644 --- a/python/paddle/nn/__init__.py +++ b/python/paddle/nn/__init__.py @@ -137,6 +137,7 @@ from .layer.distance import PairwiseDistance # noqa: F401 from .layer.vision import PixelShuffle # noqa: F401 +from .layer.vision import ChannelShuffle # noqa: F401 from .layer.container import LayerDict # noqa: F401 from .utils.spectral_norm_hook import spectral_norm @@ -298,6 +299,7 @@ def weight_norm(*args): 'Swish', 'Mish', 'PixelShuffle', + 'ChannelShuffle', 'ELU', 'ReLU6', 'LayerDict', diff --git a/python/paddle/nn/layer/__init__.py b/python/paddle/nn/layer/__init__.py index 2b50508065605..44a6ce5b13c97 100644 --- a/python/paddle/nn/layer/__init__.py +++ b/python/paddle/nn/layer/__init__.py @@ -87,6 +87,7 @@ from .norm import LocalResponseNorm # noqa: F401 from .vision import PixelShuffle # noqa: F401 +from .vision import ChannelShuffle # noqa: F401 from .distance import PairwiseDistance # noqa: F401 from .container import LayerDict # noqa: F401 diff --git a/python/paddle/nn/layer/vision.py b/python/paddle/nn/layer/vision.py index 0531afb4eeeeb..345ebed791803 100644 --- a/python/paddle/nn/layer/vision.py +++ b/python/paddle/nn/layer/vision.py @@ -87,3 +87,71 @@ def extra_repr(self): if self._name is not None: main_str += ', name={}'.format(self._name) return main_str + +class ChannelShuffle(Layer): + """ + + ChannelShuffle Layer + + This operator divides channels in a tensor of shape [N, C, H, W] into g groups + and rearranges them as [N, C/g, g, H, W] while keeping the original tensor shape. + Please refer to the paper: `ShuffleNet: An Extremely Efficient + Convolutional Neural Network for Mobile Devices `_ . + by Zhang et. al (2017) for more details. + + Parameters: + groups(int): Number of groups to divide channels in. + data_format (str): The data format of the input and output data. An optional string from: "NCHW", "NHWC". The default is "NCHW". When it is "NCHW", the data is stored in the order of: [batch_size, input_channels, input_height, input_width]. + name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. + + Shape: + - x: 4-D tensor with shape: (N, C, H, W) or (N, H, W, C). + - out: 4-D tensor with shape same as x. + + Examples: + .. code-block:: python + + import paddle + import paddle.nn as nn + x = paddle.arange(0, 0.6, 0.1, 'float32') + x = paddle.reshape(x, [1, 6, 1, 1]) + # [[[[0. ]], + # [[0.10000000]], + # [[0.20000000]], + # [[0.30000001]], + # [[0.40000001]], + # [[0.50000000]]]] + channel_shuffle = nn.ChannelShuffle(3) + y = channel_shuffle(x, 3) + # [[[[0. ]], + # [[0.20000000]], + # [[0.40000001]], + # [[0.10000000]], + # [[0.30000001]], + # [[0.50000000]]]] + """ + def __init__(self, groups, data_format="NCHW", name=None): + super(ChannelShuffle, self).__init__() + + if not isinstance(groups, int): + raise TypeError("groups must be int type") + + if data_format not in ["NCHW", "NHWC"]: + raise ValueError("Data format should be 'NCHW' or 'NHWC'." + "But recevie data format: {}".format(data_format)) + + self._groups = groups + self._data_format = data_format + self._name = name + + def forward(self, x): + return functional.channel_shuffle(x, self._groups, + self._data_format, self._name) + + def extra_repr(self): + main_str = 'groups={}'.format(self._groups) + if self._data_format != 'NCHW': + main_str += ', data_format={}'.format(self._data_format) + if self._name is not None: + main_str += ', name={}'.format(self._name) + return main_str From d515b55a3e7ae88ea8e5640bea413a3fa0aef529 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:35:25 +0800 Subject: [PATCH 11/32] Create test_channel_shuffle.py --- .../tests/unittests/test_channel_shuffle.py | 217 ++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 python/paddle/fluid/tests/unittests/test_channel_shuffle.py diff --git a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py new file mode 100644 index 0000000000000..a867272b3ea7b --- /dev/null +++ b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py @@ -0,0 +1,217 @@ +# 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. + +from __future__ import print_function + +import unittest +import numpy as np + +from op_test import OpTest +import paddle +import paddle.nn.functional as F +import paddle.fluid.core as core +import paddle.fluid as fluid + + +def channel_shuffle_np(x, groups, data_format="NCHW"): + if data_format == "NCHW": + n, c, h, w = x.shape + new_shape = (n, groups, c // groups, h, w) + npresult = np.reshape(x, new_shape) + npresult = npresult.transpose(0, 2, 1, 3, 4) + oshape = [n, c, h, w] + npresult = np.reshape(npresult, oshape) + return npresult + else: + n, h, w, c = x.shape + new_shape = (n, h, w, groups, c // groups) + npresult = np.reshape(x, new_shape) + npresult = npresult.transpose(0, 1, 2, 4, 3) + oshape = [n, h, w, c] + npresult = np.reshape(npresult, oshape) + return npresult + + +class TestChannelShuffleOp(OpTest): + def setUp(self): + self.op_type = "channel_shuffle" + self.init_data_format() + n, c, h, w = 2, 9, 4, 4 + + if self.format == "NCHW": + shape = [n, c, h, w] + if self.format == "NHWC": + shape = [n, h, w, c] + + groups = 3 + + x = np.random.random(shape).astype("float64") + npresult = channel_shuffle_np(x, groups, self.format) + + self.inputs = {'X': x} + self.outputs = {'Out': npresult} + self.attrs = {'groups': groups, "data_format": self.format} + + def init_data_format(self): + self.format = "NCHW" + + def test_check_output(self): + self.check_output() + + def test_check_grad(self): + self.check_grad(['X'], 'Out') + + +class TestChannelLast(TestChannelShuffleOp): + def init_data_format(self): + self.format = "NHWC" + + +class TestChannelShuffleAPI(unittest.TestCase): + def setUp(self): + self.x_1_np = np.random.random([2, 9, 4, 4]).astype("float64") + self.x_2_np = np.random.random([2, 4, 4, 9]).astype("float64") + self.out_1_np = channel_shuffle_np(self.x_1_np, 3) + self.out_2_np = channel_shuffle_np(self.x_2_np, 3, "NHWC") + + def test_static_graph_functional(self): + for use_cuda in ([False, True] + if core.is_compiled_with_cuda() else [False]): + place = paddle.CUDAPlace(0) if use_cuda else paddle.CPUPlace() + + paddle.enable_static() + x_1 = paddle.fluid.data( + name="x", shape=[2, 9, 4, 4], dtype="float64") + x_2 = paddle.fluid.data( + name="x2", shape=[2, 4, 4, 9], dtype="float64") + out_1 = F.channel_shuffle_np(x_1, 3) + out_2 = F.channel_shuffle_np(x_2, 3, "NHWC") + + exe = paddle.static.Executor(place=place) + res_1 = exe.run(fluid.default_main_program(), + feed={"x": self.x_1_np}, + fetch_list=out_1, + use_prune=True) + + res_2 = exe.run(fluid.default_main_program(), + feed={"x2": self.x_2_np}, + fetch_list=out_2, + use_prune=True) + + assert np.allclose(res_1, self.out_1_np) + assert np.allclose(res_2, self.out_2_np) + + # same test between layer and functional in this op. + def test_static_graph_layer(self): + for use_cuda in ([False, True] + if core.is_compiled_with_cuda() else [False]): + place = paddle.CUDAPlace(0) if use_cuda else paddle.CPUPlace() + + paddle.enable_static() + x_1 = paddle.fluid.data( + name="x", shape=[2, 9, 4, 4], dtype="float64") + x_2 = paddle.fluid.data( + name="x2", shape=[2, 4, 4, 9], dtype="float64") + # init instance + ps_1 = paddle.nn.ChannelShuffle(3) + ps_2 = paddle.nn.ChannelShuffle(3, "NHWC") + out_1 = ps_1(x_1) + out_2 = ps_2(x_2) + out_1_np = channel_shuffle_np(self.x_1_np, 3) + out_2_np = channel_shuffle_np(self.x_2_np, 3, "NHWC") + + exe = paddle.static.Executor(place=place) + res_1 = exe.run(fluid.default_main_program(), + feed={"x": self.x_1_np}, + fetch_list=out_1, + use_prune=True) + + res_2 = exe.run(fluid.default_main_program(), + feed={"x2": self.x_2_np}, + fetch_list=out_2, + use_prune=True) + + assert np.allclose(res_1, out_1_np) + assert np.allclose(res_2, out_2_np) + + def run_dygraph(self, groups, data_format): + + n, c, h, w = 2, 9, 4, 4 + + if data_format == "NCHW": + shape = [n, c, h, w] + if data_format == "NHWC": + shape = [n, h, w, c] + + x = np.random.random(shape).astype("float64") + + npresult = channel_shuffle_np(x, groups, data_format) + + for use_cuda in ([False, True] + if core.is_compiled_with_cuda() else [False]): + place = paddle.CUDAPlace(0) if use_cuda else paddle.CPUPlace() + + paddle.disable_static(place=place) + + channel_shuffle = paddle.nn.ChannelShuffle( + groups, data_format=data_format) + result = channel_shuffle(paddle.to_tensor(x)) + + self.assertTrue(np.allclose(result.numpy(), npresult)) + + result_functional = F.channel_shuffle( + paddle.to_tensor(x), 3, data_format) + self.assertTrue(np.allclose(result_functional.numpy(), npresult)) + + def test_dygraph1(self): + self.run_dygraph(3, "NCHW") + + def test_dygraph2(self): + self.run_dygraph(3, "NHWC") + + +class TestChannelShuffleError(unittest.TestCase): + def test_error_functional(self): + def error_upscale_factor(): + with paddle.fluid.dygraph.guard(): + x = np.random.random([2, 9, 4, 4]).astype("float64") + channel_shuffle = F.channel_shuffle(paddle.to_tensor(x), 3.33) + + self.assertRaises(TypeError, error_upscale_factor) + + def error_data_format(): + with paddle.fluid.dygraph.guard(): + x = np.random.random([2, 9, 4, 4]).astype("float64") + channel_shuffle = F.channel_shuffle( + paddle.to_tensor(x), 3, "WOW") + + self.assertRaises(ValueError, error_data_format) + + def test_error_layer(self): + def error_upscale_factor_layer(): + with paddle.fluid.dygraph.guard(): + x = np.random.random([2, 9, 4, 4]).astype("float64") + cs = paddle.nn.ChannelShuffle(3.33) + + self.assertRaises(TypeError, error_upscale_factor_layer) + + def error_data_format_layer(): + with paddle.fluid.dygraph.guard(): + x = np.random.random([2, 9, 4, 4]).astype("float64") + cs = paddle.nn.ChannelShuffle(3, "MEOW") + + self.assertRaises(ValueError, error_data_format_layer) + +if __name__ == '__main__': + unittest.main() From fa164beec5d19b565c6ddc1b04235c8de0a55ca7 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:49:43 +0800 Subject: [PATCH 12/32] Update example of ChannelShuffle in vision.py --- python/paddle/nn/layer/vision.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/nn/layer/vision.py b/python/paddle/nn/layer/vision.py index 345ebed791803..323baa04d9dae 100644 --- a/python/paddle/nn/layer/vision.py +++ b/python/paddle/nn/layer/vision.py @@ -122,7 +122,7 @@ class ChannelShuffle(Layer): # [[0.40000001]], # [[0.50000000]]]] channel_shuffle = nn.ChannelShuffle(3) - y = channel_shuffle(x, 3) + y = channel_shuffle(x) # [[[[0. ]], # [[0.20000000]], # [[0.40000001]], From 1a29a720dfd0799e3e23d0c2be3b773189123c44 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Sun, 20 Mar 2022 22:31:43 +0800 Subject: [PATCH 13/32] Update test_channel_shuffle.py --- .../fluid/tests/unittests/test_channel_shuffle.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py index a867272b3ea7b..3be6770e2329c 100644 --- a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py +++ b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py @@ -23,6 +23,8 @@ import paddle.fluid.core as core import paddle.fluid as fluid +paddle.enable_static() + def channel_shuffle_np(x, groups, data_format="NCHW"): if data_format == "NCHW": @@ -95,8 +97,8 @@ def test_static_graph_functional(self): name="x", shape=[2, 9, 4, 4], dtype="float64") x_2 = paddle.fluid.data( name="x2", shape=[2, 4, 4, 9], dtype="float64") - out_1 = F.channel_shuffle_np(x_1, 3) - out_2 = F.channel_shuffle_np(x_2, 3, "NHWC") + out_1 = F.channel_shuffle(x_1, 3) + out_2 = F.channel_shuffle(x_2, 3, "NHWC") exe = paddle.static.Executor(place=place) res_1 = exe.run(fluid.default_main_program(), @@ -174,6 +176,11 @@ def run_dygraph(self, groups, data_format): paddle.to_tensor(x), 3, data_format) self.assertTrue(np.allclose(result_functional.numpy(), npresult)) + channel_shuffle_str = 'groups={}'.format(groups) + if data_format != 'NCHW': + channel_shuffle_str += ', data_format={}'.format(data_format) + self.assertEqual(channel_shuffle.extra_repr(), channel_shuffle_str) + def test_dygraph1(self): self.run_dygraph(3, "NCHW") From cc322159cf4ec169be498d61ba73a69834fa8e28 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Tue, 22 Mar 2022 21:25:47 +0800 Subject: [PATCH 14/32] =?UTF-8?q?=E4=BF=AE=E6=94=B9channel=5Fshuffle?= =?UTF-8?q?=E6=A0=B8=E5=87=BD=E6=95=B0=E7=9A=84=E5=AE=9E=E7=8E=B0=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._impl.h => channel_shuffle_grad_kernel.cc} | 22 ++++++++++++++-- ...ernel_impl.h => channel_shuffle_kernel.cc} | 22 ++++++++++++++-- .../cpu/channel_shuffle_grad_kernel.cc | 26 ------------------- .../phi/kernels/cpu/channel_shuffle_kernel.cc | 26 ------------------- .../gpu/channel_shuffle_grad_kernel.cu | 26 ------------------- .../phi/kernels/gpu/channel_shuffle_kernel.cu | 26 ------------------- 6 files changed, 40 insertions(+), 108 deletions(-) rename paddle/phi/kernels/{impl/channel_shuffle_grad_kernel_impl.h => channel_shuffle_grad_kernel.cc} (73%) rename paddle/phi/kernels/{impl/channel_shuffle_kernel_impl.h => channel_shuffle_kernel.cc} (73%) delete mode 100644 paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc delete mode 100644 paddle/phi/kernels/cpu/channel_shuffle_kernel.cc delete mode 100644 paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu delete mode 100644 paddle/phi/kernels/gpu/channel_shuffle_kernel.cu diff --git a/paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h b/paddle/phi/kernels/channel_shuffle_grad_kernel.cc similarity index 73% rename from paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h rename to paddle/phi/kernels/channel_shuffle_grad_kernel.cc index 4f6b265503a87..26f71366b6a0e 100644 --- a/paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h +++ b/paddle/phi/kernels/channel_shuffle_grad_kernel.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// 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. @@ -12,11 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#pragma once #include #include #include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/kernels/funcs/math_function.h" +#include "paddle/phi/kernels/channel_shuffle_grad_kernel.h" +#include "paddle/phi/backends/all_context.h" +#include "paddle/phi/core/kernel_registry.h" namespace phi { @@ -54,3 +56,19 @@ void ChannelShuffleGradKernel(const Context& ctx, } } // namespace phi + +PD_REGISTER_KERNEL(channel_shuffle_grad, + CPU, + ALL_LAYOUT, + phi::ChannelShuffleGradKernel, + float, + double) {} + +#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) +PD_REGISTER_KERNEL(channel_shuffle_grad, + GPU, + ALL_LAYOUT, + phi::ChannelShuffleGradKernel, + float, + double) {} +#endif diff --git a/paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h b/paddle/phi/kernels/channel_shuffle_kernel.cc similarity index 73% rename from paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h rename to paddle/phi/kernels/channel_shuffle_kernel.cc index 27202ce5a23a5..5529fcea88818 100644 --- a/paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h +++ b/paddle/phi/kernels/channel_shuffle_kernel.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// 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. @@ -12,11 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#pragma once #include #include #include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/kernels/funcs/math_function.h" +#include "paddle/phi/kernels/channel_shuffle_kernel.h" +#include "paddle/phi/backends/all_context.h" +#include "paddle/phi/core/kernel_registry.h" namespace phi { @@ -53,3 +55,19 @@ void ChannelShuffleKernel(const Context& ctx, } } // namespace phi + +PD_REGISTER_KERNEL(channel_shuffle, + CPU, + ALL_LAYOUT, + phi::ChannelShuffleKernel, + float, + double) {} + +#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) +PD_REGISTER_KERNEL(channel_shuffle, + GPU, + ALL_LAYOUT, + phi::ChannelShuffleKernel, + float, + double) {} +#endif diff --git a/paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc b/paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc deleted file mode 100644 index 1f3466faa6bf9..0000000000000 --- a/paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc +++ /dev/null @@ -1,26 +0,0 @@ -// 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/channel_shuffle_grad_kernel.h" -#include "paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h" - -#include "paddle/phi/backends/cpu/cpu_context.h" -#include "paddle/phi/core/kernel_registry.h" - -PD_REGISTER_KERNEL(channel_shuffle_grad, - CPU, - ALL_LAYOUT, - phi::ChannelShuffleGradKernel, - float, - double) {} diff --git a/paddle/phi/kernels/cpu/channel_shuffle_kernel.cc b/paddle/phi/kernels/cpu/channel_shuffle_kernel.cc deleted file mode 100644 index 3377fb4dcd750..0000000000000 --- a/paddle/phi/kernels/cpu/channel_shuffle_kernel.cc +++ /dev/null @@ -1,26 +0,0 @@ -// 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/channel_shuffle_kernel.h" -#include "paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h" - -#include "paddle/phi/backends/cpu/cpu_context.h" -#include "paddle/phi/core/kernel_registry.h" - -PD_REGISTER_KERNEL(channel_shuffle, - CPU, - ALL_LAYOUT, - phi::ChannelShuffleKernel, - float, - double) {} diff --git a/paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu b/paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu deleted file mode 100644 index e33deef259578..0000000000000 --- a/paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu +++ /dev/null @@ -1,26 +0,0 @@ -// 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/impl/channel_shuffle_grad_kernel_impl.h" -#include "paddle/phi/kernels/channel_shuffle_grad_kernel.h" - -#include "paddle/phi/backends/gpu/gpu_context.h" -#include "paddle/phi/core/kernel_registry.h" - -PD_REGISTER_KERNEL(channel_shuffle_grad, - GPU, - ALL_LAYOUT, - phi::ChannelShuffleGradKernel, - float, - double) {} diff --git a/paddle/phi/kernels/gpu/channel_shuffle_kernel.cu b/paddle/phi/kernels/gpu/channel_shuffle_kernel.cu deleted file mode 100644 index 28a1c6c64b749..0000000000000 --- a/paddle/phi/kernels/gpu/channel_shuffle_kernel.cu +++ /dev/null @@ -1,26 +0,0 @@ -// 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/impl/channel_shuffle_kernel_impl.h" -#include "paddle/phi/kernels/channel_shuffle_kernel.h" - -#include "paddle/phi/backends/gpu/gpu_context.h" -#include "paddle/phi/core/kernel_registry.h" - -PD_REGISTER_KERNEL(channel_shuffle, - GPU, - ALL_LAYOUT, - phi::ChannelShuffleKernel, - float, - double) {} From 0c9dd647107b9c4a1cfdedeba942a086a289304c Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Wed, 23 Mar 2022 11:34:02 +0800 Subject: [PATCH 15/32] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- paddle/fluid/operators/channel_shuffle_op.cc | 13 +++++-------- .../phi/kernels/channel_shuffle_grad_kernel.cc | 18 +++++++++--------- paddle/phi/kernels/channel_shuffle_kernel.cc | 18 +++++++++--------- paddle/phi/ops/compat/channel_shuffle_sig.cc | 3 ++- .../tests/unittests/test_channel_shuffle.py | 1 + python/paddle/nn/functional/vision.py | 5 +++-- python/paddle/nn/layer/vision.py | 6 ++++-- 7 files changed, 33 insertions(+), 31 deletions(-) diff --git a/paddle/fluid/operators/channel_shuffle_op.cc b/paddle/fluid/operators/channel_shuffle_op.cc index 419c63a61a507..ba379d47b9707 100644 --- a/paddle/fluid/operators/channel_shuffle_op.cc +++ b/paddle/fluid/operators/channel_shuffle_op.cc @@ -38,12 +38,10 @@ class ChannelShuffleOpMaker : public framework::OpProtoAndCheckerMaker { "(Tensor, default Tensor), the output of " "ChannelShuffleOp. The layout is also [N, C, " "H, W] or [N, H, W, C]."); - AddAttr("groups", - "number of groups to divide channels in.") + AddAttr("groups", "number of groups to divide channels in.") .AddCustomChecker([](const int& groups) { - PADDLE_ENFORCE_GE(groups, 1, - platform::errors::InvalidArgument( - "groups should be larger than 0.")); + PADDLE_ENFORCE_GE(groups, 1, platform::errors::InvalidArgument( + "groups should be larger than 0.")); }); AddAttr( "data_format", @@ -84,7 +82,7 @@ class ChannelShuffleGradOp : public framework::OperatorWithKernel { "Input should be a 4-D tensor of format [N, C, " "H, W] or [N, H, W, C], but got %u.", do_dims.size())); - + auto dx_dims = do_dims; ctx->SetOutputDim(framework::GradVarName("X"), dx_dims); } @@ -111,8 +109,7 @@ namespace ops = paddle::operators; DECLARE_INFER_SHAPE_FUNCTOR(channel_shuffle, ChannelShuffleInferShapeFunctor, PD_INFER_META(phi::ChannelShuffleInferMeta)); -REGISTER_OPERATOR(channel_shuffle, - ops::ChannelShuffleOp, +REGISTER_OPERATOR(channel_shuffle, ops::ChannelShuffleOp, ops::ChannelShuffleOpMaker, ops::ChannelShuffleGradOpMaker, ops::ChannelShuffleGradOpMaker, diff --git a/paddle/phi/kernels/channel_shuffle_grad_kernel.cc b/paddle/phi/kernels/channel_shuffle_grad_kernel.cc index 26f71366b6a0e..b66e27f9ba3df 100644 --- a/paddle/phi/kernels/channel_shuffle_grad_kernel.cc +++ b/paddle/phi/kernels/channel_shuffle_grad_kernel.cc @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "paddle/phi/kernels/channel_shuffle_grad_kernel.h" #include #include -#include "paddle/phi/core/dense_tensor.h" -#include "paddle/phi/kernels/funcs/math_function.h" -#include "paddle/phi/kernels/channel_shuffle_grad_kernel.h" #include "paddle/phi/backends/all_context.h" +#include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/core/kernel_registry.h" +#include "paddle/phi/kernels/funcs/math_function.h" namespace phi { @@ -37,18 +37,18 @@ void ChannelShuffleGradKernel(const Context& ctx, DenseTensor t(*dout); if (!channel_last) { - t.Resize({do_dims[0], do_dims[1]/groups, groups, do_dims[2], do_dims[3]}); + t.Resize({do_dims[0], do_dims[1] / groups, groups, do_dims[2], do_dims[3]}); } else { - t.Resize({do_dims[0], do_dims[1], do_dims[2], do_dims[3]/groups, groups}); + t.Resize({do_dims[0], do_dims[1], do_dims[2], do_dims[3] / groups, groups}); } - auto axis = !channel_last ? std::vector {0, 2, 1, 3, 4} - : std::vector {0, 1, 2, 4, 3}; + auto axis = !channel_last ? std::vector{0, 2, 1, 3, 4} + : std::vector{0, 1, 2, 4, 3}; DenseTensor o(*dx); if (!channel_last) { - o.Resize({dx_dims[0], groups, dx_dims[1]/groups, dx_dims[2], dx_dims[3]}); + o.Resize({dx_dims[0], groups, dx_dims[1] / groups, dx_dims[2], dx_dims[3]}); } else { - o.Resize({dx_dims[0], dx_dims[1], dx_dims[2], groups, dx_dims[3]/groups}); + o.Resize({dx_dims[0], dx_dims[1], dx_dims[2], groups, dx_dims[3] / groups}); } phi::funcs::Transpose trans; trans(ctx, t, &o, axis); diff --git a/paddle/phi/kernels/channel_shuffle_kernel.cc b/paddle/phi/kernels/channel_shuffle_kernel.cc index 5529fcea88818..c3c5c1cb87101 100644 --- a/paddle/phi/kernels/channel_shuffle_kernel.cc +++ b/paddle/phi/kernels/channel_shuffle_kernel.cc @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "paddle/phi/kernels/channel_shuffle_kernel.h" #include #include -#include "paddle/phi/core/dense_tensor.h" -#include "paddle/phi/kernels/funcs/math_function.h" -#include "paddle/phi/kernels/channel_shuffle_kernel.h" #include "paddle/phi/backends/all_context.h" +#include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/core/kernel_registry.h" +#include "paddle/phi/kernels/funcs/math_function.h" namespace phi { @@ -36,18 +36,18 @@ void ChannelShuffleKernel(const Context& ctx, DenseTensor t(*in); if (!channel_last) { - t.Resize({in_dims[0], groups, in_dims[1]/groups, in_dims[2], in_dims[3]}); + t.Resize({in_dims[0], groups, in_dims[1] / groups, in_dims[2], in_dims[3]}); } else { - t.Resize({in_dims[0], in_dims[1], in_dims[2], groups, in_dims[3]/groups}); + t.Resize({in_dims[0], in_dims[1], in_dims[2], groups, in_dims[3] / groups}); } - auto axis = !channel_last ? std::vector {0, 2, 1, 3, 4} - : std::vector {0, 1, 2, 4, 3}; + auto axis = !channel_last ? std::vector{0, 2, 1, 3, 4} + : std::vector{0, 1, 2, 4, 3}; DenseTensor o(*out); if (!channel_last) { - o.Resize({in_dims[0], in_dims[1]/groups, groups, in_dims[2], in_dims[3]}); + o.Resize({in_dims[0], in_dims[1] / groups, groups, in_dims[2], in_dims[3]}); } else { - o.Resize({in_dims[0], in_dims[1], in_dims[2], in_dims[3]/groups, groups}); + o.Resize({in_dims[0], in_dims[1], in_dims[2], in_dims[3] / groups, groups}); } phi::funcs::Transpose trans; trans(ctx, t, &o, axis); diff --git a/paddle/phi/ops/compat/channel_shuffle_sig.cc b/paddle/phi/ops/compat/channel_shuffle_sig.cc index da424081d765e..179098ab06d17 100644 --- a/paddle/phi/ops/compat/channel_shuffle_sig.cc +++ b/paddle/phi/ops/compat/channel_shuffle_sig.cc @@ -32,6 +32,7 @@ KernelSignature ChannelShuffleGradOpArgumentMapping( } // namespace phi -PD_REGISTER_ARG_MAPPING_FN(channel_shuffle, phi::ChannelShuffleOpArgumentMapping); +PD_REGISTER_ARG_MAPPING_FN(channel_shuffle, + phi::ChannelShuffleOpArgumentMapping); PD_REGISTER_ARG_MAPPING_FN(channel_shuffle_grad, phi::ChannelShuffleGradOpArgumentMapping); diff --git a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py index 3be6770e2329c..cbd8ba8e71274 100644 --- a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py +++ b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py @@ -220,5 +220,6 @@ def error_data_format_layer(): self.assertRaises(ValueError, error_data_format_layer) + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/nn/functional/vision.py b/python/paddle/nn/functional/vision.py index 89c9834cd0afa..9ca58edc85ad1 100644 --- a/python/paddle/nn/functional/vision.py +++ b/python/paddle/nn/functional/vision.py @@ -345,6 +345,7 @@ def pixel_shuffle(x, upscale_factor, data_format="NCHW", name=None): "data_format": data_format}) return out + def channel_shuffle(x, groups, data_format="NCHW", name=None): """ This API implements channel shuffle operation. @@ -388,8 +389,8 @@ def channel_shuffle(x, groups, data_format="NCHW", name=None): data_format)) if in_dynamic_mode(): - return _C_ops.channel_shuffle(x, "groups", groups, - "data_format", data_format) + return _C_ops.channel_shuffle(x, "groups", groups, "data_format", + data_format) helper = LayerHelper("channel_shuffle", **locals()) check_variable_and_dtype(x, 'x', ['float32', 'float64'], 'channel_shuffle') diff --git a/python/paddle/nn/layer/vision.py b/python/paddle/nn/layer/vision.py index 323baa04d9dae..16012876a0b0e 100644 --- a/python/paddle/nn/layer/vision.py +++ b/python/paddle/nn/layer/vision.py @@ -88,6 +88,7 @@ def extra_repr(self): main_str += ', name={}'.format(self._name) return main_str + class ChannelShuffle(Layer): """ @@ -130,6 +131,7 @@ class ChannelShuffle(Layer): # [[0.30000001]], # [[0.50000000]]]] """ + def __init__(self, groups, data_format="NCHW", name=None): super(ChannelShuffle, self).__init__() @@ -145,8 +147,8 @@ def __init__(self, groups, data_format="NCHW", name=None): self._name = name def forward(self, x): - return functional.channel_shuffle(x, self._groups, - self._data_format, self._name) + return functional.channel_shuffle(x, self._groups, self._data_format, + self._name) def extra_repr(self): main_str = 'groups={}'.format(self._groups) From cd6fe4192c4dc09f6872e04f9238dae9a3b3b093 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Wed, 23 Mar 2022 19:10:07 +0800 Subject: [PATCH 16/32] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=A9=BA=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/paddle/nn/functional/vision.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/nn/functional/vision.py b/python/paddle/nn/functional/vision.py index 9ca58edc85ad1..be86220f65f9d 100644 --- a/python/paddle/nn/functional/vision.py +++ b/python/paddle/nn/functional/vision.py @@ -391,7 +391,7 @@ def channel_shuffle(x, groups, data_format="NCHW", name=None): if in_dynamic_mode(): return _C_ops.channel_shuffle(x, "groups", groups, "data_format", data_format) - + helper = LayerHelper("channel_shuffle", **locals()) check_variable_and_dtype(x, 'x', ['float32', 'float64'], 'channel_shuffle') out = helper.create_variable_for_type_inference(dtype=x.dtype) From 1cfdfd35cb321e1e4dc45aa5b4ecdf3fd1c46bea Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Wed, 30 Mar 2022 13:31:39 +0800 Subject: [PATCH 17/32] =?UTF-8?q?=E5=AE=8C=E5=96=84channel=5Fshuffle?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/paddle/nn/functional/vision.py | 8 ++++++++ python/paddle/nn/layer/vision.py | 3 +++ 2 files changed, 11 insertions(+) diff --git a/python/paddle/nn/functional/vision.py b/python/paddle/nn/functional/vision.py index be86220f65f9d..007ab255231db 100644 --- a/python/paddle/nn/functional/vision.py +++ b/python/paddle/nn/functional/vision.py @@ -380,9 +380,17 @@ def channel_shuffle(x, groups, data_format="NCHW", name=None): # [[0.30000001]], # [[0.50000000]]]] """ + if len(x.shape) != 4: + raise ValueError( + "Input x should be 4D tensor, but received x with the shape of {}". + format(x.shape)) + if not isinstance(groups, int): raise TypeError("groups must be int type") + if groups <= 0: + raise ValueError("groups must be positive") + if data_format not in ["NCHW", "NHWC"]: raise ValueError("Attr(data_format) should be 'NCHW' or 'NHWC'." "But recevie Attr(data_format): {} ".format( diff --git a/python/paddle/nn/layer/vision.py b/python/paddle/nn/layer/vision.py index 16012876a0b0e..39041bcca3fd8 100644 --- a/python/paddle/nn/layer/vision.py +++ b/python/paddle/nn/layer/vision.py @@ -138,6 +138,9 @@ def __init__(self, groups, data_format="NCHW", name=None): if not isinstance(groups, int): raise TypeError("groups must be int type") + if groups <= 0: + raise ValueError("groups must be positive") + if data_format not in ["NCHW", "NHWC"]: raise ValueError("Data format should be 'NCHW' or 'NHWC'." "But recevie data format: {}".format(data_format)) From 5cc340dd1d943e43832ac9455d63c05e3f46f98e Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Wed, 30 Mar 2022 13:32:09 +0800 Subject: [PATCH 18/32] Update unary.cc --- paddle/phi/infermeta/unary.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index 0a978c537b45a..068560967ce3b 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2874,6 +2874,16 @@ void ChannelShuffleInferMeta(const MetaTensor& x, "Input should be a 4-D tensor of format [N, C, H, W] " "or [N, H, W, C], but got %u.", input_dims.size())); + PADDLE_ENFORCE_GE(groups, + 1, + phi::errors::InvalidArgument( + "groups should be larger than 0.")); + PADDLE_ENFORCE_EQ(data_format == "NCHW" || data_format == "NHWC", + true, + phi::errors::InvalidArgument( + "data_format must be one of " + "NCHW and NHWC. But recevied data_format: %s", + data_format)); const bool channel_last = (data_format == "NHWC"); From 88f6e2bf9978e5f2ce3d6f662d4bd69c71ee3883 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Wed, 30 Mar 2022 13:32:45 +0800 Subject: [PATCH 19/32] Update channel_shuffle_op.cc --- paddle/fluid/operators/channel_shuffle_op.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/paddle/fluid/operators/channel_shuffle_op.cc b/paddle/fluid/operators/channel_shuffle_op.cc index ba379d47b9707..b14e30c1209fb 100644 --- a/paddle/fluid/operators/channel_shuffle_op.cc +++ b/paddle/fluid/operators/channel_shuffle_op.cc @@ -12,7 +12,6 @@ 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 "paddle/fluid/framework/infershape_utils.h" #include "paddle/fluid/framework/op_registry.h" #include "paddle/fluid/framework/op_version_registry.h" @@ -38,11 +37,7 @@ class ChannelShuffleOpMaker : public framework::OpProtoAndCheckerMaker { "(Tensor, default Tensor), the output of " "ChannelShuffleOp. The layout is also [N, C, " "H, W] or [N, H, W, C]."); - AddAttr("groups", "number of groups to divide channels in.") - .AddCustomChecker([](const int& groups) { - PADDLE_ENFORCE_GE(groups, 1, platform::errors::InvalidArgument( - "groups should be larger than 0.")); - }); + AddAttr("groups", "number of groups to divide channels in."); AddAttr( "data_format", "An optional string from: \"NHWC\", \"NCHW\". " From b848e45399f201ee2a199f46af127f7918198ffa Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Wed, 30 Mar 2022 13:33:16 +0800 Subject: [PATCH 20/32] Update test_channel_shuffle.py --- .../tests/unittests/test_channel_shuffle.py | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py index cbd8ba8e71274..9aea14baefac9 100644 --- a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py +++ b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import print_function - import unittest import numpy as np @@ -23,8 +21,6 @@ import paddle.fluid.core as core import paddle.fluid as fluid -paddle.enable_static() - def channel_shuffle_np(x, groups, data_format="NCHW"): if data_format == "NCHW": @@ -69,10 +65,14 @@ def init_data_format(self): self.format = "NCHW" def test_check_output(self): + paddle.enable_static() self.check_output() + paddle.disable_static() def test_check_grad(self): + paddle.enable_static() self.check_grad(['X'], 'Out') + paddle.disable_static() class TestChannelLast(TestChannelShuffleOp): @@ -190,12 +190,27 @@ def test_dygraph2(self): class TestChannelShuffleError(unittest.TestCase): def test_error_functional(self): - def error_upscale_factor(): + + def error_input(): + with paddle.fluid.dygraph.guard(): + x = np.random.random([9, 4, 4]).astype("float64") + channel_shuffle = F.channel_shuffle(paddle.to_tensor(x), 3) + + self.assertRaises(ValueError, error_input) + + def error_groups_1(): with paddle.fluid.dygraph.guard(): x = np.random.random([2, 9, 4, 4]).astype("float64") channel_shuffle = F.channel_shuffle(paddle.to_tensor(x), 3.33) - self.assertRaises(TypeError, error_upscale_factor) + self.assertRaises(TypeError, error_groups_1) + + def error_groups_2(): + with paddle.fluid.dygraph.guard(): + x = np.random.random([2, 9, 4, 4]).astype("float64") + channel_shuffle = F.channel_shuffle(paddle.to_tensor(x), -1) + + self.assertRaises(ValueError, error_groups_2) def error_data_format(): with paddle.fluid.dygraph.guard(): @@ -206,12 +221,27 @@ def error_data_format(): self.assertRaises(ValueError, error_data_format) def test_error_layer(self): - def error_upscale_factor_layer(): + def error_input_layer(): + with paddle.fluid.dygraph.guard(): + x = np.random.random([9, 4, 4]).astype("float64") + cs = paddle.nn.ChannelShuffle(3) + cs(paddle.to_tensor(x)) + + self.assertRaises(ValueError, error_input_layer) + + def error_groups_layer_1(): with paddle.fluid.dygraph.guard(): x = np.random.random([2, 9, 4, 4]).astype("float64") cs = paddle.nn.ChannelShuffle(3.33) - self.assertRaises(TypeError, error_upscale_factor_layer) + self.assertRaises(TypeError, error_groups_layer_1) + + def error_groups_layer_2(): + with paddle.fluid.dygraph.guard(): + x = np.random.random([2, 9, 4, 4]).astype("float64") + cs = paddle.nn.ChannelShuffle(-1) + + self.assertRaises(ValueError, error_groups_layer_2) def error_data_format_layer(): with paddle.fluid.dygraph.guard(): From e927fc4af3d24585d0b8f5cb92bf88b656ef4461 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:33:35 +0800 Subject: [PATCH 21/32] Update unary.cc --- paddle/phi/infermeta/unary.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index 068560967ce3b..419657d1674bf 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2891,16 +2891,16 @@ void ChannelShuffleInferMeta(const MetaTensor& x, PADDLE_ENFORCE_EQ(input_dims[1] % groups, 0, phi::errors::InvalidArgument( - "The number of groups to divide channels in[%u] " - "should divide the number of channel[%u]", + "The number of groups to divide channels in [%u] " + "should divide the number of channel [%u]", groups, input_dims[1])); } else { PADDLE_ENFORCE_EQ(input_dims[3] % groups, 0, phi::errors::InvalidArgument( - "The number of groups to divide channels in[%u] " - "should divide the number of channel[%u]", + "The number of groups to divide channels in [%u] " + "should divide the number of channel [%u]", groups, input_dims[3])); } From c0d5651182d34669b363e0194639ee37e6be2783 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:34:00 +0800 Subject: [PATCH 22/32] add channel_shuffle --- tools/static_mode_white_list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/static_mode_white_list.py b/tools/static_mode_white_list.py index f907d51e4d038..734387dae03f2 100755 --- a/tools/static_mode_white_list.py +++ b/tools/static_mode_white_list.py @@ -92,6 +92,7 @@ 'test_case', 'test_cast_op', 'test_center_loss', + 'test_channel_shuffle', 'test_cholesky_op', 'test_chunk_eval_op', 'test_chunk_op', From 3a7d3225451d5373fb44908c77ecf24227a69aec Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:34:30 +0800 Subject: [PATCH 23/32] Update test_channel_shuffle.py --- python/paddle/fluid/tests/unittests/test_channel_shuffle.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py index 9aea14baefac9..d04513f7da567 100644 --- a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py +++ b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py @@ -65,14 +65,10 @@ def init_data_format(self): self.format = "NCHW" def test_check_output(self): - paddle.enable_static() self.check_output() - paddle.disable_static() def test_check_grad(self): - paddle.enable_static() self.check_grad(['X'], 'Out') - paddle.disable_static() class TestChannelLast(TestChannelShuffleOp): From 56f795117aaaa7d2370f059c65b26a63a9cb4243 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:34:50 +0800 Subject: [PATCH 24/32] Update vision.py --- python/paddle/nn/functional/vision.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/paddle/nn/functional/vision.py b/python/paddle/nn/functional/vision.py index 007ab255231db..a8ba2b4a3e01f 100644 --- a/python/paddle/nn/functional/vision.py +++ b/python/paddle/nn/functional/vision.py @@ -21,6 +21,7 @@ from paddle import _C_ops from ...device import is_compiled_with_rocm from paddle import in_dynamic_mode +from paddle.framework import _non_static_mode __all__ = [] @@ -396,7 +397,7 @@ def channel_shuffle(x, groups, data_format="NCHW", name=None): "But recevie Attr(data_format): {} ".format( data_format)) - if in_dynamic_mode(): + if _non_static_mode(): return _C_ops.channel_shuffle(x, "groups", groups, "data_format", data_format) From 048ef2b8adea462214c32960546dd6480b87e081 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Fri, 8 Apr 2022 13:07:46 +0800 Subject: [PATCH 25/32] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- paddle/phi/infermeta/unary.cc | 8 ++++---- paddle/phi/kernels/channel_shuffle_grad_kernel.cc | 2 +- paddle/phi/kernels/channel_shuffle_grad_kernel.h | 2 +- paddle/phi/kernels/channel_shuffle_kernel.cc | 2 +- paddle/phi/kernels/channel_shuffle_kernel.h | 2 +- .../paddle/fluid/tests/unittests/test_channel_shuffle.py | 1 - 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index 419657d1674bf..ff2a7f7570c02 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2874,10 +2874,10 @@ void ChannelShuffleInferMeta(const MetaTensor& x, "Input should be a 4-D tensor of format [N, C, H, W] " "or [N, H, W, C], but got %u.", input_dims.size())); - PADDLE_ENFORCE_GE(groups, - 1, - phi::errors::InvalidArgument( - "groups should be larger than 0.")); + PADDLE_ENFORCE_GE( + groups, + 1, + phi::errors::InvalidArgument("groups should be larger than 0.")); PADDLE_ENFORCE_EQ(data_format == "NCHW" || data_format == "NHWC", true, phi::errors::InvalidArgument( diff --git a/paddle/phi/kernels/channel_shuffle_grad_kernel.cc b/paddle/phi/kernels/channel_shuffle_grad_kernel.cc index b66e27f9ba3df..9ffc3302cbc7c 100644 --- a/paddle/phi/kernels/channel_shuffle_grad_kernel.cc +++ b/paddle/phi/kernels/channel_shuffle_grad_kernel.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// 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. diff --git a/paddle/phi/kernels/channel_shuffle_grad_kernel.h b/paddle/phi/kernels/channel_shuffle_grad_kernel.h index 1b02f22b25f6d..4dbfd627d9da1 100644 --- a/paddle/phi/kernels/channel_shuffle_grad_kernel.h +++ b/paddle/phi/kernels/channel_shuffle_grad_kernel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// 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. diff --git a/paddle/phi/kernels/channel_shuffle_kernel.cc b/paddle/phi/kernels/channel_shuffle_kernel.cc index c3c5c1cb87101..84781f4be2c1b 100644 --- a/paddle/phi/kernels/channel_shuffle_kernel.cc +++ b/paddle/phi/kernels/channel_shuffle_kernel.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// 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. diff --git a/paddle/phi/kernels/channel_shuffle_kernel.h b/paddle/phi/kernels/channel_shuffle_kernel.h index a3bacef963c3c..4f86f30c00b61 100644 --- a/paddle/phi/kernels/channel_shuffle_kernel.h +++ b/paddle/phi/kernels/channel_shuffle_kernel.h @@ -1,4 +1,4 @@ -// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. +// 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. diff --git a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py index d04513f7da567..b4a3fc387068c 100644 --- a/python/paddle/fluid/tests/unittests/test_channel_shuffle.py +++ b/python/paddle/fluid/tests/unittests/test_channel_shuffle.py @@ -186,7 +186,6 @@ def test_dygraph2(self): class TestChannelShuffleError(unittest.TestCase): def test_error_functional(self): - def error_input(): with paddle.fluid.dygraph.guard(): x = np.random.random([9, 4, 4]).astype("float64") From 11b3b0319f2c9ef80890e242ed02f769679bee30 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Mon, 18 Apr 2022 14:27:36 +0800 Subject: [PATCH 26/32] Update channel_shuffle_sig.cc --- paddle/phi/ops/compat/channel_shuffle_sig.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/phi/ops/compat/channel_shuffle_sig.cc b/paddle/phi/ops/compat/channel_shuffle_sig.cc index 179098ab06d17..28544f5d1e812 100644 --- a/paddle/phi/ops/compat/channel_shuffle_sig.cc +++ b/paddle/phi/ops/compat/channel_shuffle_sig.cc @@ -25,9 +25,9 @@ KernelSignature ChannelShuffleOpArgumentMapping( KernelSignature ChannelShuffleGradOpArgumentMapping( const ArgumentMappingContext& ctx) { return KernelSignature("channel_shuffle_grad", - {GradVarName("Out")}, + {"Out@GRAD"}, {"groups", "data_format"}, - {GradVarName("X")}); + {"X@GRAD"}); } } // namespace phi From 236223303976b9514a7fe3ec7cd84d89ec379861 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Tue, 19 Apr 2022 13:08:32 +0800 Subject: [PATCH 27/32] =?UTF-8?q?=E6=9B=B4=E6=96=B0ChannelShuffle=E7=9A=84?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/paddle/nn/layer/vision.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/python/paddle/nn/layer/vision.py b/python/paddle/nn/layer/vision.py index 39041bcca3fd8..e775d4fcf6dfb 100644 --- a/python/paddle/nn/layer/vision.py +++ b/python/paddle/nn/layer/vision.py @@ -91,26 +91,26 @@ def extra_repr(self): class ChannelShuffle(Layer): """ - - ChannelShuffle Layer - - This operator divides channels in a tensor of shape [N, C, H, W] into g groups - and rearranges them as [N, C/g, g, H, W] while keeping the original tensor shape. - Please refer to the paper: `ShuffleNet: An Extremely Efficient + This operator divides channels in a tensor of shape [N, C, H, W] or [N, H, W, C] into g groups, + getting a tensor with the shape of [N, g, C/g, H, W] or [N, H, W, g, C/g], and transposes them + as [N, C/g, g, H, W] or [N, H, W, g, C/g], then rearranges them to original tensor shape. This + operation can improve the interaction between channels, using features efficiently. Please + refer to the paper: `ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices `_ . by Zhang et. al (2017) for more details. Parameters: - groups(int): Number of groups to divide channels in. - data_format (str): The data format of the input and output data. An optional string from: "NCHW", "NHWC". The default is "NCHW". When it is "NCHW", the data is stored in the order of: [batch_size, input_channels, input_height, input_width]. - name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. + groups (int): Number of groups to divide channels in. + data_format (str): The data format of the input and output data. An optional string of NCHW or NHWC. The default is NCHW. When it is NCHW, the data is stored in the order of [batch_size, input_channels, input_height, input_width]. + name (str, optional): Name for the operation (optional, default is None). Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name`. Shape: - - x: 4-D tensor with shape: (N, C, H, W) or (N, H, W, C). - - out: 4-D tensor with shape same as x. + - **x**: 4-D tensor with shape of [N, C, H, W] or [N, H, W, C]. + - **out**: 4-D tensor with shape and dtype same as x. Examples: .. code-block:: python + :name: ChannelShuffle-example import paddle import paddle.nn as nn From dd9be7f156c24aef430e72e35e6c5e5952621311 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Tue, 19 Apr 2022 13:08:42 +0800 Subject: [PATCH 28/32] =?UTF-8?q?=E6=9B=B4=E6=96=B0channel=5Fshuffle?= =?UTF-8?q?=E7=9A=84=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/paddle/nn/functional/vision.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/python/paddle/nn/functional/vision.py b/python/paddle/nn/functional/vision.py index a8ba2b4a3e01f..07e68d71dc1f1 100644 --- a/python/paddle/nn/functional/vision.py +++ b/python/paddle/nn/functional/vision.py @@ -351,17 +351,19 @@ def channel_shuffle(x, groups, data_format="NCHW", name=None): """ This API implements channel shuffle operation. See more details in :ref:`api_nn_vision_ChannelShuffle` . + Parameters: - x(Tensor): 4-D tensor, the data type should be float32 or float64. - groups(int): Number of groups to divide channels in. - data_format (str): The data format of the input and output data. An optional string from: "NCHW", "NHWC". The default is "NCHW". When it is "NCHW", the data is stored in the order of: [batch_size, input_channels, input_height, input_width]. - name (str, optional): The default value is None. Normally there is no need for user to set this property. + x (Tensor): 4-D tensor, the data type should be float32 or float64. + groups (int): Number of groups to divide channels in. + data_format (str): The data format of the input and output data. An optional string of NCHW or NHWC. The default is NCHW. When it is NCHW, the data is stored in the order of [batch_size, input_channels, input_height, input_width]. + name (str, optional): Name for the operation (optional, default is None). Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name`. + Returns: - Out(tensor): Rearranged tensor keeping the original tensor shape. - Raises: - ValueError: If the number of groups cannot divide the channels of input. + Out (Tensor): Rearranged tensor keeping the original tensor shape. + Examples: .. code-block:: python + :name: channel_shuffle-example import paddle import paddle.nn.functional as F From d7ae774593e2ce8e42aa37e3ceec17b1d4541519 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:00:57 +0800 Subject: [PATCH 29/32] remove ChannelShuffleOpArgumentMapping --- paddle/phi/ops/compat/channel_shuffle_sig.cc | 8 -------- 1 file changed, 8 deletions(-) diff --git a/paddle/phi/ops/compat/channel_shuffle_sig.cc b/paddle/phi/ops/compat/channel_shuffle_sig.cc index 28544f5d1e812..ae0aa0a80b6f0 100644 --- a/paddle/phi/ops/compat/channel_shuffle_sig.cc +++ b/paddle/phi/ops/compat/channel_shuffle_sig.cc @@ -16,12 +16,6 @@ namespace phi { -KernelSignature ChannelShuffleOpArgumentMapping( - const ArgumentMappingContext& ctx) { - return KernelSignature( - "channel_shuffle", {"X"}, {"groups", "data_format"}, {"Out"}); -} - KernelSignature ChannelShuffleGradOpArgumentMapping( const ArgumentMappingContext& ctx) { return KernelSignature("channel_shuffle_grad", @@ -32,7 +26,5 @@ KernelSignature ChannelShuffleGradOpArgumentMapping( } // namespace phi -PD_REGISTER_ARG_MAPPING_FN(channel_shuffle, - phi::ChannelShuffleOpArgumentMapping); PD_REGISTER_ARG_MAPPING_FN(channel_shuffle_grad, phi::ChannelShuffleGradOpArgumentMapping); From dbb8fd91fc24c272d6a2812692976f69deb23a5b Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:01:20 +0800 Subject: [PATCH 30/32] add ChannelShuffleGradInferMeta --- paddle/phi/infermeta/backward.cc | 16 ++++++++++++++++ paddle/phi/infermeta/backward.h | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/paddle/phi/infermeta/backward.cc b/paddle/phi/infermeta/backward.cc index 567f39a915c02..4a4585e00eed6 100644 --- a/paddle/phi/infermeta/backward.cc +++ b/paddle/phi/infermeta/backward.cc @@ -67,6 +67,22 @@ void BilinearTensorProductGradInferMeta(const MetaTensor& x, } } +void ChannelShuffleGradInferMeta(const MetaTensor& out_grad, + int groups, + const std::string& data_format, + MetaTensor* x_grad) { + auto do_dims = out_grad.dims(); + PADDLE_ENFORCE_EQ(do_dims.size(), + 4, + phi::errors::InvalidArgument( + "Input should be a 4-D tensor of format [N, C, H, W] " + "or [N, H, W, C], but got %u.", + do_dims.size())); + auto dx_dims = do_dims; + x_grad->set_dims(dx_dims); + x_grad->set_dtype(out_grad.dtype()); +} + void ConvTransposeGradInferMeta(const MetaTensor& x, const MetaTensor& filter, const MetaTensor& dout, diff --git a/paddle/phi/infermeta/backward.h b/paddle/phi/infermeta/backward.h index 6807438ebbb75..9db958778d597 100644 --- a/paddle/phi/infermeta/backward.h +++ b/paddle/phi/infermeta/backward.h @@ -37,6 +37,11 @@ void BilinearTensorProductGradInferMeta(const MetaTensor& x, MetaTensor* dweight, MetaTensor* dbias); +void ChannelShuffleGradInferMeta(const MetaTensor& out_grad, + int groups, + const std::string& data_format, + MetaTensor* x_grad); + void ConvTransposeGradInferMeta(const MetaTensor& x, const MetaTensor& filter, const MetaTensor& dout, From 37d4a5e66bd6a1d12beca8e074498e9e85baf288 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:01:34 +0800 Subject: [PATCH 31/32] Update channel_shuffle_op.cc --- paddle/fluid/operators/channel_shuffle_op.cc | 53 ++++++++------------ 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/paddle/fluid/operators/channel_shuffle_op.cc b/paddle/fluid/operators/channel_shuffle_op.cc index b14e30c1209fb..74b2e04e63f70 100644 --- a/paddle/fluid/operators/channel_shuffle_op.cc +++ b/paddle/fluid/operators/channel_shuffle_op.cc @@ -1,21 +1,22 @@ -/* 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. */ +// Copyright (c) 2021 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/fluid/framework/infershape_utils.h" #include "paddle/fluid/framework/op_registry.h" #include "paddle/fluid/framework/op_version_registry.h" #include "paddle/phi/core/infermeta_utils.h" +#include "paddle/phi/infermeta/backward.h" #include "paddle/phi/infermeta/unary.h" namespace paddle { @@ -62,25 +63,6 @@ class ChannelShuffleOpMaker : public framework::OpProtoAndCheckerMaker { class ChannelShuffleGradOp : public framework::OperatorWithKernel { public: using framework::OperatorWithKernel::OperatorWithKernel; - - void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE_EQ( - ctx->HasInput(framework::GradVarName("Out")), true, - platform::errors::NotFound("Input(Out@Grad) should not be null")); - PADDLE_ENFORCE_EQ( - ctx->HasOutput(framework::GradVarName("X")), true, - platform::errors::NotFound("Output(X@Grad) should not be null")); - - auto do_dims = ctx->GetInputDim(framework::GradVarName("Out")); - PADDLE_ENFORCE_EQ(do_dims.size(), 4, - platform::errors::InvalidArgument( - "Input should be a 4-D tensor of format [N, C, " - "H, W] or [N, H, W, C], but got %u.", - do_dims.size())); - - auto dx_dims = do_dims; - ctx->SetOutputDim(framework::GradVarName("X"), dx_dims); - } }; template @@ -110,4 +92,9 @@ REGISTER_OPERATOR(channel_shuffle, ops::ChannelShuffleOp, ops::ChannelShuffleGradOpMaker, ChannelShuffleInferShapeFunctor); -REGISTER_OPERATOR(channel_shuffle_grad, ops::ChannelShuffleGradOp); +DECLARE_INFER_SHAPE_FUNCTOR(channel_shuffle_grad, + ChannelShuffleGradInferShapeFunctor, + PD_INFER_META(phi::ChannelShuffleGradInferMeta)); + +REGISTER_OPERATOR(channel_shuffle_grad, ops::ChannelShuffleGradOp, + ChannelShuffleGradInferShapeFunctor); From e29fb304a047d548ac77c229bee2f64709858370 Mon Sep 17 00:00:00 2001 From: BrilliantYuKaimin <91609464+BrilliantYuKaimin@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:02:03 +0800 Subject: [PATCH 32/32] =?UTF-8?q?=E8=B0=83=E6=95=B4channel=5Fshuffle?= =?UTF-8?q?=E5=8F=8A=E5=85=B6=E6=A2=AF=E5=BA=A6=E7=9A=84=E6=A0=B8=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E7=9A=84=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../phi/kernels/channel_shuffle_grad_kernel.h | 2 +- paddle/phi/kernels/channel_shuffle_kernel.h | 2 +- .../cpu/channel_shuffle_grad_kernel.cc | 26 +++++++++++++++++ .../phi/kernels/cpu/channel_shuffle_kernel.cc | 26 +++++++++++++++++ .../gpu/channel_shuffle_grad_kernel.cu | 26 +++++++++++++++++ .../phi/kernels/gpu/channel_shuffle_kernel.cu | 26 +++++++++++++++++ .../channel_shuffle_grad_kernel_impl.h} | 28 ++++--------------- .../channel_shuffle_kernel_impl.h} | 28 ++++--------------- 8 files changed, 118 insertions(+), 46 deletions(-) create mode 100644 paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc create mode 100644 paddle/phi/kernels/cpu/channel_shuffle_kernel.cc create mode 100644 paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu create mode 100644 paddle/phi/kernels/gpu/channel_shuffle_kernel.cu rename paddle/phi/kernels/{channel_shuffle_grad_kernel.cc => impl/channel_shuffle_grad_kernel_impl.h} (71%) rename paddle/phi/kernels/{channel_shuffle_kernel.cc => impl/channel_shuffle_kernel_impl.h} (71%) diff --git a/paddle/phi/kernels/channel_shuffle_grad_kernel.h b/paddle/phi/kernels/channel_shuffle_grad_kernel.h index 4dbfd627d9da1..ac89f3336bc76 100644 --- a/paddle/phi/kernels/channel_shuffle_grad_kernel.h +++ b/paddle/phi/kernels/channel_shuffle_grad_kernel.h @@ -20,7 +20,7 @@ namespace phi { template -void ChannelShuffleGradKernel(const Context& ctx, +void ChannelShuffleGradKernel(const Context& dev_ctx, const DenseTensor& out_grad, int groups, const std::string& data_format, diff --git a/paddle/phi/kernels/channel_shuffle_kernel.h b/paddle/phi/kernels/channel_shuffle_kernel.h index 4f86f30c00b61..12de25606dd96 100644 --- a/paddle/phi/kernels/channel_shuffle_kernel.h +++ b/paddle/phi/kernels/channel_shuffle_kernel.h @@ -20,7 +20,7 @@ namespace phi { template -void ChannelShuffleKernel(const Context& ctx, +void ChannelShuffleKernel(const Context& dev_ctx, const DenseTensor& x, int groups, const std::string& data_format, diff --git a/paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc b/paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc new file mode 100644 index 0000000000000..fcc91b2191673 --- /dev/null +++ b/paddle/phi/kernels/cpu/channel_shuffle_grad_kernel.cc @@ -0,0 +1,26 @@ +// 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/channel_shuffle_grad_kernel.h" +#include "paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h" + +#include "paddle/phi/backends/cpu/cpu_context.h" +#include "paddle/phi/core/kernel_registry.h" + +PD_REGISTER_KERNEL(channel_shuffle_grad, + CPU, + ALL_LAYOUT, + phi::ChannelShuffleGradKernel, + float, + double) {} diff --git a/paddle/phi/kernels/cpu/channel_shuffle_kernel.cc b/paddle/phi/kernels/cpu/channel_shuffle_kernel.cc new file mode 100644 index 0000000000000..95d19ec6a7746 --- /dev/null +++ b/paddle/phi/kernels/cpu/channel_shuffle_kernel.cc @@ -0,0 +1,26 @@ +// 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/channel_shuffle_kernel.h" +#include "paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h" + +#include "paddle/phi/backends/cpu/cpu_context.h" +#include "paddle/phi/core/kernel_registry.h" + +PD_REGISTER_KERNEL(channel_shuffle, + CPU, + ALL_LAYOUT, + phi::ChannelShuffleKernel, + float, + double) {} diff --git a/paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu b/paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu new file mode 100644 index 0000000000000..63d3d4a554f81 --- /dev/null +++ b/paddle/phi/kernels/gpu/channel_shuffle_grad_kernel.cu @@ -0,0 +1,26 @@ +// 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/channel_shuffle_grad_kernel.h" +#include "paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h" + +#include "paddle/phi/backends/gpu/gpu_context.h" +#include "paddle/phi/core/kernel_registry.h" + +PD_REGISTER_KERNEL(channel_shuffle_grad, + GPU, + ALL_LAYOUT, + phi::ChannelShuffleGradKernel, + float, + double) {} diff --git a/paddle/phi/kernels/gpu/channel_shuffle_kernel.cu b/paddle/phi/kernels/gpu/channel_shuffle_kernel.cu new file mode 100644 index 0000000000000..f85cb4aafd1dc --- /dev/null +++ b/paddle/phi/kernels/gpu/channel_shuffle_kernel.cu @@ -0,0 +1,26 @@ +// 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/channel_shuffle_kernel.h" +#include "paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h" + +#include "paddle/phi/backends/gpu/gpu_context.h" +#include "paddle/phi/core/kernel_registry.h" + +PD_REGISTER_KERNEL(channel_shuffle, + GPU, + ALL_LAYOUT, + phi::ChannelShuffleKernel, + float, + double) {} diff --git a/paddle/phi/kernels/channel_shuffle_grad_kernel.cc b/paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h similarity index 71% rename from paddle/phi/kernels/channel_shuffle_grad_kernel.cc rename to paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h index 9ffc3302cbc7c..26bee763eca52 100644 --- a/paddle/phi/kernels/channel_shuffle_grad_kernel.cc +++ b/paddle/phi/kernels/impl/channel_shuffle_grad_kernel_impl.h @@ -12,25 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "paddle/phi/kernels/channel_shuffle_grad_kernel.h" +#pragma once + #include #include -#include "paddle/phi/backends/all_context.h" + #include "paddle/phi/core/dense_tensor.h" -#include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/funcs/math_function.h" namespace phi { template -void ChannelShuffleGradKernel(const Context& ctx, +void ChannelShuffleGradKernel(const Context& dev_ctx, const DenseTensor& out_grad, int groups, const std::string& data_format, DenseTensor* x_grad) { auto* dout = &out_grad; auto* dx = x_grad; - ctx.template Alloc(dx); + dev_ctx.template Alloc(dx); bool channel_last = (data_format == "NHWC"); auto do_dims = dout->dims(); auto dx_dims = dx->dims(); @@ -51,24 +51,8 @@ void ChannelShuffleGradKernel(const Context& ctx, o.Resize({dx_dims[0], dx_dims[1], dx_dims[2], groups, dx_dims[3] / groups}); } phi::funcs::Transpose trans; - trans(ctx, t, &o, axis); + trans(dev_ctx, t, &o, axis); dx->Resize(dx_dims); } } // namespace phi - -PD_REGISTER_KERNEL(channel_shuffle_grad, - CPU, - ALL_LAYOUT, - phi::ChannelShuffleGradKernel, - float, - double) {} - -#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) -PD_REGISTER_KERNEL(channel_shuffle_grad, - GPU, - ALL_LAYOUT, - phi::ChannelShuffleGradKernel, - float, - double) {} -#endif diff --git a/paddle/phi/kernels/channel_shuffle_kernel.cc b/paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h similarity index 71% rename from paddle/phi/kernels/channel_shuffle_kernel.cc rename to paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h index 84781f4be2c1b..c723cd3622af9 100644 --- a/paddle/phi/kernels/channel_shuffle_kernel.cc +++ b/paddle/phi/kernels/impl/channel_shuffle_kernel_impl.h @@ -12,24 +12,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "paddle/phi/kernels/channel_shuffle_kernel.h" +#pragma once + #include #include -#include "paddle/phi/backends/all_context.h" + #include "paddle/phi/core/dense_tensor.h" -#include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/funcs/math_function.h" namespace phi { template -void ChannelShuffleKernel(const Context& ctx, +void ChannelShuffleKernel(const Context& dev_ctx, const DenseTensor& x, int groups, const std::string& data_format, DenseTensor* out) { auto* in = &x; - ctx.template Alloc(out); + dev_ctx.template Alloc(out); bool channel_last = (data_format == "NHWC"); auto in_dims = in->dims(); auto o_dims = out->dims(); @@ -50,24 +50,8 @@ void ChannelShuffleKernel(const Context& ctx, o.Resize({in_dims[0], in_dims[1], in_dims[2], in_dims[3] / groups, groups}); } phi::funcs::Transpose trans; - trans(ctx, t, &o, axis); + trans(dev_ctx, t, &o, axis); out->Resize(o_dims); } } // namespace phi - -PD_REGISTER_KERNEL(channel_shuffle, - CPU, - ALL_LAYOUT, - phi::ChannelShuffleKernel, - float, - double) {} - -#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP) -PD_REGISTER_KERNEL(channel_shuffle, - GPU, - ALL_LAYOUT, - phi::ChannelShuffleKernel, - float, - double) {} -#endif