From 23fb0b8a3b363d85dc92d0b6ad8c7fdfbfa81880 Mon Sep 17 00:00:00 2001 From: 0x45f Date: Thu, 11 Aug 2022 11:45:36 +0000 Subject: [PATCH 01/22] Adapt tensor axis for reduce_min --- .../operators/reduce_ops/reduce_min_op.cc | 2 +- paddle/phi/api/yaml/legacy_api.yaml | 4 +- paddle/phi/api/yaml/legacy_backward.yaml | 4 +- paddle/phi/infermeta/unary.cc | 44 +++++++++ paddle/phi/infermeta/unary.h | 13 +++ paddle/phi/kernels/cpu/reduce_min_kernel.cc | 4 +- .../impl/reduce_min_grad_kernel_impl.h | 4 +- paddle/phi/kernels/kps/reduce_min_kernel.cu | 6 +- paddle/phi/kernels/reduce_min_grad_kernel.h | 3 +- paddle/phi/kernels/reduce_min_kernel.cc | 2 +- paddle/phi/kernels/reduce_min_kernel.h | 6 +- .../fluid/tests/unittests/test_min_op.py | 94 +++++++++++++++++-- python/paddle/tensor/math.py | 2 + 13 files changed, 163 insertions(+), 25 deletions(-) diff --git a/paddle/fluid/operators/reduce_ops/reduce_min_op.cc b/paddle/fluid/operators/reduce_ops/reduce_min_op.cc index 2dced4fecee12..654ff4ad375d8 100644 --- a/paddle/fluid/operators/reduce_ops/reduce_min_op.cc +++ b/paddle/fluid/operators/reduce_ops/reduce_min_op.cc @@ -27,7 +27,7 @@ class ReduceMinOpMaker : public ops::ReduceOpMaker { DECLARE_INFER_SHAPE_FUNCTOR(reduce_min, ReduceMinInferShapeFunctor, - PD_INFER_META(phi::ReduceInferMetaBase)); + PD_INFER_META(phi::ReduceMinInferMetaBase)); REGISTER_OPERATOR( reduce_min, diff --git a/paddle/phi/api/yaml/legacy_api.yaml b/paddle/phi/api/yaml/legacy_api.yaml index b67498bcc1a20..ee3b59cb443eb 100755 --- a/paddle/phi/api/yaml/legacy_api.yaml +++ b/paddle/phi/api/yaml/legacy_api.yaml @@ -1707,10 +1707,10 @@ backward : meshgrid_grad - api : min - args : (Tensor x, int64_t[] dims={}, bool keep_dim=false) + args : (Tensor x, IntArray dims, bool keep_dim=false) output : Tensor(out) infer_meta : - func : ReduceInferMeta + func : ReduceMinInferMeta kernel : func : min backward : min_grad diff --git a/paddle/phi/api/yaml/legacy_backward.yaml b/paddle/phi/api/yaml/legacy_backward.yaml index fdf2321ea38e1..db19c3e11e7e5 100755 --- a/paddle/phi/api/yaml/legacy_backward.yaml +++ b/paddle/phi/api/yaml/legacy_backward.yaml @@ -1479,8 +1479,8 @@ func : meshgrid_grad - backward_api : min_grad - forward: min (Tensor x, int64_t[] dims={}, bool keep_dim=false) -> Tensor(out) - args : (Tensor x, Tensor out, Tensor out_grad, int64_t[] dims={}, bool keep_dim=false, bool reduce_all=false) + forward: min (Tensor x, IntArray dims, bool keep_dim=false) -> Tensor(out) + args : (Tensor x, Tensor out, Tensor out_grad, IntArray dims, bool keep_dim=false, bool reduce_all=false) output : Tensor(x_grad) infer_meta : func : UnchangedInferMeta diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index d6395c8a2e424..cf82b1225e9c7 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2603,6 +2603,50 @@ void ReduceInferMetaBase(const MetaTensor& x, out->set_layout(x.layout()); } +void ReduceMinInferMetaBase(const MetaTensor& x, + const IntArray& axis, + bool keep_dim, + bool reduce_all, + MetaTensor* out, + MetaConfig config) { + std::vector vec_axis = axis.GetData(); + if (config.is_runtime) { + ReduceInferMetaBase(x, vec_axis, keep_dim, reduce_all, out); + } else { + auto x_rank = static_cast(x.dims().size()); + + // PADDLE_ENFORCE_LE( + // vec_axis.size(), + // x_rank, + // errors::InvalidArgument( + // "The length of axis should be less than or equal to " + // "x_rank. But received the length of axis = %d, " + // "x_rank = %d", + // vec_axis.size(), + // x_rank)); + + std::vector vec_dim; + if (vec_axis.size() >= x_rank) { + vec_dim = {-1}; + } else { + vec_dim = std::vector(x.dims().size() - vec_axis.size(), -1); + } + DDim out_dim = phi::make_ddim(vec_dim); + out->set_dims(out_dim); + out->set_dtype(x.dtype()); + out->set_layout(x.layout()); + } +} + +void ReduceMinInferMeta(const MetaTensor& x, + const IntArray& axis, + bool keep_dim, + MetaTensor* out, + MetaConfig config) { + bool reduce_all = false; + ReduceMinInferMetaBase(x, axis, keep_dim, reduce_all, out, config); +} + void RepeatInterleaveInferMeta(const MetaTensor& x, int repeats, int dim, diff --git a/paddle/phi/infermeta/unary.h b/paddle/phi/infermeta/unary.h index f2bb43e952d5f..47fd9827945b1 100644 --- a/paddle/phi/infermeta/unary.h +++ b/paddle/phi/infermeta/unary.h @@ -353,6 +353,19 @@ void ReduceInferMetaBase(const MetaTensor& x, bool reduce_all, MetaTensor* out); +void ReduceMinInferMetaBase(const MetaTensor& x, + const IntArray& axis, + bool keep_dim, + bool reduce_all, + MetaTensor* out, + MetaConfig config = MetaConfig()); + +void ReduceMinInferMeta(const MetaTensor& x, + const IntArray& axis, + bool keep_dim, + MetaTensor* out, + MetaConfig config = MetaConfig()); + void RepeatInterleaveInferMeta(const MetaTensor& x, int repeats, int dim, diff --git a/paddle/phi/kernels/cpu/reduce_min_kernel.cc b/paddle/phi/kernels/cpu/reduce_min_kernel.cc index 0a241c81dbe69..a11de5ea81ab6 100644 --- a/paddle/phi/kernels/cpu/reduce_min_kernel.cc +++ b/paddle/phi/kernels/cpu/reduce_min_kernel.cc @@ -24,13 +24,13 @@ namespace phi { template void MinRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out) { auto out_dtype = x.dtype(); phi::Reduce( - dev_ctx, x, reduce_all, dims, keep_dim, out_dtype, out); + dev_ctx, x, reduce_all, dims.GetData(), keep_dim, out_dtype, out); } } // namespace phi diff --git a/paddle/phi/kernels/impl/reduce_min_grad_kernel_impl.h b/paddle/phi/kernels/impl/reduce_min_grad_kernel_impl.h index 592b5309cd970..93afa07ff01af 100644 --- a/paddle/phi/kernels/impl/reduce_min_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/reduce_min_grad_kernel_impl.h @@ -25,12 +25,12 @@ void ReduceMinGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad) { ReduceGradKernel( - dev_ctx, x, out, out_grad, dims, keep_dim, reduce_all, x_grad); + dev_ctx, x, out, out_grad, dims.GetData(), keep_dim, reduce_all, x_grad); } } // namespace phi diff --git a/paddle/phi/kernels/kps/reduce_min_kernel.cu b/paddle/phi/kernels/kps/reduce_min_kernel.cu index 6fea48b588abb..9c3e61d3c0bc5 100644 --- a/paddle/phi/kernels/kps/reduce_min_kernel.cu +++ b/paddle/phi/kernels/kps/reduce_min_kernel.cu @@ -12,22 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "paddle/phi/kernels/reduce_min_kernel.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/gpu/reduce.h" -#include "paddle/phi/kernels/reduce_min_kernel.h" namespace phi { template void MinRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out) { auto out_dtype = x.dtype(); phi::Reduce( - dev_ctx, x, reduce_all, dims, keep_dim, out_dtype, out); + dev_ctx, x, reduce_all, dims.GetData(), keep_dim, out_dtype, out); } } // namespace phi diff --git a/paddle/phi/kernels/reduce_min_grad_kernel.h b/paddle/phi/kernels/reduce_min_grad_kernel.h index 3c6ea3a3564cf..c737761439089 100644 --- a/paddle/phi/kernels/reduce_min_grad_kernel.h +++ b/paddle/phi/kernels/reduce_min_grad_kernel.h @@ -15,6 +15,7 @@ #pragma once #include "paddle/phi/common/data_type.h" +#include "paddle/phi/common/int_array.h" #include "paddle/phi/core/dense_tensor.h" namespace phi { @@ -23,7 +24,7 @@ void ReduceMinGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad); diff --git a/paddle/phi/kernels/reduce_min_kernel.cc b/paddle/phi/kernels/reduce_min_kernel.cc index 69725759e4e82..11f11b772ef6f 100644 --- a/paddle/phi/kernels/reduce_min_kernel.cc +++ b/paddle/phi/kernels/reduce_min_kernel.cc @@ -22,7 +22,7 @@ namespace phi { template void MinKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, DenseTensor* out) { bool reduce_all = false; diff --git a/paddle/phi/kernels/reduce_min_kernel.h b/paddle/phi/kernels/reduce_min_kernel.h index bbf3f2ab81826..4619a0ed4136c 100644 --- a/paddle/phi/kernels/reduce_min_kernel.h +++ b/paddle/phi/kernels/reduce_min_kernel.h @@ -16,12 +16,14 @@ #include "paddle/phi/core/dense_tensor.h" +#include "paddle/phi/common/int_array.h" + namespace phi { template void MinRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out); @@ -29,7 +31,7 @@ void MinRawKernel(const Context& dev_ctx, template void MinKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, DenseTensor* out); diff --git a/python/paddle/fluid/tests/unittests/test_min_op.py b/python/paddle/fluid/tests/unittests/test_min_op.py index 6e5f9d1321593..63b43d01390d1 100644 --- a/python/paddle/fluid/tests/unittests/test_min_op.py +++ b/python/paddle/fluid/tests/unittests/test_min_op.py @@ -14,12 +14,15 @@ from __future__ import print_function +import os import unittest +import tempfile import numpy as np from op_test import OpTest, skip_check_grad_ci, check_out_dtype import paddle import paddle.fluid.core as core from paddle.fluid.framework import _test_eager_guard +import paddle.inference as paddle_infer class ApiMinTest(unittest.TestCase): @@ -70,15 +73,6 @@ def test_input_type(): self.assertRaises(TypeError, test_input_type) - def test_axis_type(): - with paddle.static.program_guard(paddle.static.Program(), - paddle.static.Program()): - data = paddle.static.data("data", shape=[10, 10], dtype="int64") - axis = paddle.static.data("axis", shape=[10, 10], dtype="int64") - result_min = paddle.min(data, axis) - - self.assertRaises(TypeError, test_axis_type) - def test_imperative_api(self): paddle.disable_static() np_x = np.array([10, 10]).astype('float64') @@ -103,5 +97,87 @@ def test_min(self): expect_dtypes=['float32', 'float64', 'int32', 'int64']) +class TestMinWithTensorAxis1(unittest.TestCase): + + def setUp(self): + self.temp_dir = tempfile.TemporaryDirectory() + self.save_path = os.path.join(self.temp_dir.name, + 'min_with_tensor_axis') + self.place = paddle.CUDAPlace( + 0) if paddle.is_compiled_with_cuda() else paddle.CPUPlace() + self.init_data() + + def tearDwon(self): + self.temp_dir.cleanup() + + def init_data(self): + self.x = paddle.randn([2, 3, 4, 5, 5], dtype='float32') + self.axis = paddle.to_tensor([1, 2], dtype='int64') + + def test_dygraph(self): + self.x.stop_gradient = False + pd_out = paddle.min(self.x, self.axis) + np_out = np.min(self.x.numpy(), tuple(self.axis.numpy())) + + self.assertTrue( + np.array_equal(pd_out.numpy() if pd_out.size > 1 else pd_out.item(), + np_out)) + pd_out.backward() + self.assertEqual(self.x.gradient().shape, tuple(self.x.shape)) + + def test_static_and_infer(self): + paddle.enable_static() + main_prog = paddle.static.Program() + starup_prog = paddle.static.Program() + with paddle.static.program_guard(main_prog, starup_prog): + # run static + x = paddle.static.data(shape=self.x.shape, + name='x', + dtype=self.x.dtype) + axis = paddle.static.data(shape=self.axis.shape, + name='axis', + dtype=self.axis.dtype) + fc = paddle.nn.Linear(self.x.shape[-1], 6) + fc_out = fc(x) + out = paddle.min(fc_out, axis) + exe = paddle.static.Executor(self.place) + exe.run(starup_prog) + static_out = exe.run(feed={ + 'x': self.x.numpy(), + 'axis': self.axis.numpy() + }, + fetch_list=[out]) + + # run infer + paddle.static.save_inference_model(self.save_path, [x, axis], [out], + exe) + config = paddle_infer.Config(self.save_path + '.pdmodel', + self.save_path + '.pdiparams') + predictor = paddle_infer.create_predictor(config) + input_names = predictor.get_input_names() + input_handle = predictor.get_input_handle(input_names[0]) + fake_input = self.x.numpy() + input_handle.reshape(self.x.shape) + input_handle.copy_from_cpu(fake_input) + input_handle = predictor.get_input_handle(input_names[1]) + fake_input = self.axis.numpy() + input_handle.reshape(self.axis.shape) + input_handle.copy_from_cpu(fake_input) + predictor.run() + output_names = predictor.get_output_names() + output_handle = predictor.get_output_handle(output_names[0]) + infer_out = output_handle.copy_to_cpu() + + self.assertTrue(np.array_equal(static_out[0], infer_out)) + paddle.disable_static() + + +class TestMinWithTensorAxis2(TestMinWithTensorAxis1): + + def init_data(self): + self.x = paddle.randn([3, 4, 7], dtype='float32') + self.axis = paddle.to_tensor([0, 1, 2], dtype='int64') + + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/tensor/math.py b/python/paddle/tensor/math.py index b94329eb9213c..9f66b92beba09 100644 --- a/python/paddle/tensor/math.py +++ b/python/paddle/tensor/math.py @@ -2059,6 +2059,8 @@ def _get_reduce_axis(axis): Internal function for max, min, amax and amin. It computes the attribute reduce_all value based on axis. """ + if isinstance(axis, Variable): + return False, axis if axis is not None and not isinstance(axis, list): if isinstance(axis, tuple): axis = list(axis) From 49755104ceac0f7cd25fb51e72614cd78c72f89a Mon Sep 17 00:00:00 2001 From: 0x45f Date: Thu, 11 Aug 2022 11:51:34 +0000 Subject: [PATCH 02/22] Remove some comments --- paddle/phi/infermeta/unary.cc | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index cf82b1225e9c7..7289abc89e7f2 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2614,17 +2614,6 @@ void ReduceMinInferMetaBase(const MetaTensor& x, ReduceInferMetaBase(x, vec_axis, keep_dim, reduce_all, out); } else { auto x_rank = static_cast(x.dims().size()); - - // PADDLE_ENFORCE_LE( - // vec_axis.size(), - // x_rank, - // errors::InvalidArgument( - // "The length of axis should be less than or equal to " - // "x_rank. But received the length of axis = %d, " - // "x_rank = %d", - // vec_axis.size(), - // x_rank)); - std::vector vec_dim; if (vec_axis.size() >= x_rank) { vec_dim = {-1}; From 98ef6b7d1edb459aa3e9cf41b5eb78741df28462 Mon Sep 17 00:00:00 2001 From: 0x45f Date: Thu, 11 Aug 2022 13:11:43 +0000 Subject: [PATCH 03/22] Add dims default value in yaml --- paddle/phi/api/yaml/legacy_api.yaml | 2 +- paddle/phi/api/yaml/legacy_backward.yaml | 4 ++-- paddle/phi/infermeta/unary.cc | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/paddle/phi/api/yaml/legacy_api.yaml b/paddle/phi/api/yaml/legacy_api.yaml index ee3b59cb443eb..7e81b1fee6d07 100755 --- a/paddle/phi/api/yaml/legacy_api.yaml +++ b/paddle/phi/api/yaml/legacy_api.yaml @@ -1707,7 +1707,7 @@ backward : meshgrid_grad - api : min - args : (Tensor x, IntArray dims, bool keep_dim=false) + args : (Tensor x, IntArray dims={}, bool keep_dim=false) output : Tensor(out) infer_meta : func : ReduceMinInferMeta diff --git a/paddle/phi/api/yaml/legacy_backward.yaml b/paddle/phi/api/yaml/legacy_backward.yaml index db19c3e11e7e5..3942abcda2387 100755 --- a/paddle/phi/api/yaml/legacy_backward.yaml +++ b/paddle/phi/api/yaml/legacy_backward.yaml @@ -1479,8 +1479,8 @@ func : meshgrid_grad - backward_api : min_grad - forward: min (Tensor x, IntArray dims, bool keep_dim=false) -> Tensor(out) - args : (Tensor x, Tensor out, Tensor out_grad, IntArray dims, bool keep_dim=false, bool reduce_all=false) + forward: min (Tensor x, IntArray dims={}, bool keep_dim=false) -> Tensor(out) + args : (Tensor x, Tensor out, Tensor out_grad, IntArray dims={}, bool keep_dim=false, bool reduce_all=false) output : Tensor(x_grad) infer_meta : func : UnchangedInferMeta diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index 7289abc89e7f2..960ddda7f0376 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2633,6 +2633,9 @@ void ReduceMinInferMeta(const MetaTensor& x, MetaTensor* out, MetaConfig config) { bool reduce_all = false; + if (axis.size() == 0) { + reduce_all = true; + } ReduceMinInferMetaBase(x, axis, keep_dim, reduce_all, out, config); } From 65f20ba436eb22885075c20dea1aa9d429005b98 Mon Sep 17 00:00:00 2001 From: 0x45f Date: Fri, 12 Aug 2022 02:53:09 +0000 Subject: [PATCH 04/22] Fix get_reduce_axis --- python/paddle/tensor/math.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/python/paddle/tensor/math.py b/python/paddle/tensor/math.py index 9f66b92beba09..ff4a61d48a889 100644 --- a/python/paddle/tensor/math.py +++ b/python/paddle/tensor/math.py @@ -2059,8 +2059,6 @@ def _get_reduce_axis(axis): Internal function for max, min, amax and amin. It computes the attribute reduce_all value based on axis. """ - if isinstance(axis, Variable): - return False, axis if axis is not None and not isinstance(axis, list): if isinstance(axis, tuple): axis = list(axis) @@ -2074,6 +2072,11 @@ def _get_reduce_axis(axis): axis = [] return reduce_all, axis +def _get_reduce_axis_with_tensor(axis): + if isinstance(axis, Variable): + return False, axis + return _get_reduce_axis(axis) + def _get_reduce_all_value(axis): """ Internal function for max, min, amax and amin. @@ -2271,7 +2274,7 @@ def min(x, axis=None, keepdim=False, name=None): #[1., 2.], [[[1., 1.], [0., 0.]], [[0., 0.], [0., 0.]]] """ - reduce_all, axis = _get_reduce_axis(axis) + reduce_all, axis = _get_reduce_axis_with_tensor(axis) if in_dygraph_mode(): return _C_ops.final_state_min(x, axis, keepdim) From 426fc6298fb4d0366cfc527160561893f583ae78 Mon Sep 17 00:00:00 2001 From: 0x45f Date: Fri, 12 Aug 2022 02:58:54 +0000 Subject: [PATCH 05/22] Fxi test_max_op --- python/paddle/fluid/tests/unittests/test_max_op.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/fluid/tests/unittests/test_max_op.py b/python/paddle/fluid/tests/unittests/test_max_op.py index dc11d78699e73..5ae5c344ae7fb 100644 --- a/python/paddle/fluid/tests/unittests/test_max_op.py +++ b/python/paddle/fluid/tests/unittests/test_max_op.py @@ -75,7 +75,7 @@ def test_axis_type(): paddle.static.Program()): data = paddle.static.data("data", shape=[10, 10], dtype="int64") axis = paddle.static.data("axis", shape=[10, 10], dtype="int64") - result_min = paddle.min(data, axis) + result_max = paddle.max(data, axis) self.assertRaises(TypeError, test_axis_type) From 61ca6a27795b0133996ee6a1e9079d4801cad151 Mon Sep 17 00:00:00 2001 From: 0x45f Date: Mon, 15 Aug 2022 03:59:49 +0000 Subject: [PATCH 06/22] Rename infermeta function --- .../operators/reduce_ops/reduce_min_op.cc | 7 +++--- paddle/phi/api/yaml/legacy_api.yaml | 2 +- paddle/phi/infermeta/unary.cc | 24 +++++++++---------- paddle/phi/infermeta/unary.h | 24 +++++++++---------- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/paddle/fluid/operators/reduce_ops/reduce_min_op.cc b/paddle/fluid/operators/reduce_ops/reduce_min_op.cc index 654ff4ad375d8..e9fafce1332d2 100644 --- a/paddle/fluid/operators/reduce_ops/reduce_min_op.cc +++ b/paddle/fluid/operators/reduce_ops/reduce_min_op.cc @@ -25,9 +25,10 @@ class ReduceMinOpMaker : public ops::ReduceOpMaker { virtual std::string GetOpType() const { return "Reduce reduce_min"; } }; -DECLARE_INFER_SHAPE_FUNCTOR(reduce_min, - ReduceMinInferShapeFunctor, - PD_INFER_META(phi::ReduceMinInferMetaBase)); +DECLARE_INFER_SHAPE_FUNCTOR( + reduce_min, + ReduceMinInferShapeFunctor, + PD_INFER_META(phi::ReduceIntArrayAxisInferMetaBase)); REGISTER_OPERATOR( reduce_min, diff --git a/paddle/phi/api/yaml/legacy_api.yaml b/paddle/phi/api/yaml/legacy_api.yaml index 7e81b1fee6d07..79ae456a80edd 100755 --- a/paddle/phi/api/yaml/legacy_api.yaml +++ b/paddle/phi/api/yaml/legacy_api.yaml @@ -1710,7 +1710,7 @@ args : (Tensor x, IntArray dims={}, bool keep_dim=false) output : Tensor(out) infer_meta : - func : ReduceMinInferMeta + func : ReduceIntArrayAxisInferMeta kernel : func : min backward : min_grad diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index 960ddda7f0376..c7c46de98e1dc 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2603,12 +2603,12 @@ void ReduceInferMetaBase(const MetaTensor& x, out->set_layout(x.layout()); } -void ReduceMinInferMetaBase(const MetaTensor& x, - const IntArray& axis, - bool keep_dim, - bool reduce_all, - MetaTensor* out, - MetaConfig config) { +void ReduceIntArrayAxisInferMetaBase(const MetaTensor& x, + const IntArray& axis, + bool keep_dim, + bool reduce_all, + MetaTensor* out, + MetaConfig config) { std::vector vec_axis = axis.GetData(); if (config.is_runtime) { ReduceInferMetaBase(x, vec_axis, keep_dim, reduce_all, out); @@ -2627,16 +2627,16 @@ void ReduceMinInferMetaBase(const MetaTensor& x, } } -void ReduceMinInferMeta(const MetaTensor& x, - const IntArray& axis, - bool keep_dim, - MetaTensor* out, - MetaConfig config) { +void ReduceIntArrayAxisInferMeta(const MetaTensor& x, + const IntArray& axis, + bool keep_dim, + MetaTensor* out, + MetaConfig config) { bool reduce_all = false; if (axis.size() == 0) { reduce_all = true; } - ReduceMinInferMetaBase(x, axis, keep_dim, reduce_all, out, config); + ReduceIntArrayAxisInferMetaBase(x, axis, keep_dim, reduce_all, out, config); } void RepeatInterleaveInferMeta(const MetaTensor& x, diff --git a/paddle/phi/infermeta/unary.h b/paddle/phi/infermeta/unary.h index 47fd9827945b1..cafe9f40b0a89 100644 --- a/paddle/phi/infermeta/unary.h +++ b/paddle/phi/infermeta/unary.h @@ -353,18 +353,18 @@ void ReduceInferMetaBase(const MetaTensor& x, bool reduce_all, MetaTensor* out); -void ReduceMinInferMetaBase(const MetaTensor& x, - const IntArray& axis, - bool keep_dim, - bool reduce_all, - MetaTensor* out, - MetaConfig config = MetaConfig()); - -void ReduceMinInferMeta(const MetaTensor& x, - const IntArray& axis, - bool keep_dim, - MetaTensor* out, - MetaConfig config = MetaConfig()); +void ReduceIntArrayAxisInferMetaBase(const MetaTensor& x, + const IntArray& axis, + bool keep_dim, + bool reduce_all, + MetaTensor* out, + MetaConfig config = MetaConfig()); + +void ReduceIntArrayAxisInferMeta(const MetaTensor& x, + const IntArray& axis, + bool keep_dim, + MetaTensor* out, + MetaConfig config = MetaConfig()); void RepeatInterleaveInferMeta(const MetaTensor& x, int repeats, From 2223e1286901a38cf07858018481e0adaf9c940c Mon Sep 17 00:00:00 2001 From: 0x45f Date: Mon, 15 Aug 2022 08:13:19 +0000 Subject: [PATCH 07/22] adapt reduce_max --- paddle/fluid/operators/reduce_ops/reduce_max_op.cc | 7 ++++--- paddle/phi/api/yaml/legacy_api.yaml | 4 ++-- paddle/phi/api/yaml/legacy_backward.yaml | 4 ++-- paddle/phi/kernels/cpu/matrix_rank_tol_kernel.cc | 2 +- paddle/phi/kernels/cpu/reduce_max_kernel.cc | 4 ++-- paddle/phi/kernels/gpu/matrix_rank_tol_kernel.cu | 2 +- paddle/phi/kernels/impl/reduce_max_grad_kernel_impl.h | 4 ++-- paddle/phi/kernels/kps/reduce_max_kernel.cu | 6 +++--- paddle/phi/kernels/reduce_max_grad_kernel.h | 3 ++- paddle/phi/kernels/reduce_max_kernel.cc | 2 +- paddle/phi/kernels/reduce_max_kernel.h | 5 +++-- paddle/phi/kernels/reduce_min_kernel.h | 3 +-- python/paddle/fluid/tests/unittests/test_max_op.py | 9 --------- python/paddle/tensor/math.py | 2 +- 14 files changed, 25 insertions(+), 32 deletions(-) diff --git a/paddle/fluid/operators/reduce_ops/reduce_max_op.cc b/paddle/fluid/operators/reduce_ops/reduce_max_op.cc index bfc89403d8dd7..21e16a5cd14c6 100644 --- a/paddle/fluid/operators/reduce_ops/reduce_max_op.cc +++ b/paddle/fluid/operators/reduce_ops/reduce_max_op.cc @@ -25,9 +25,10 @@ class ReduceMaxOpMaker : public ops::ReduceOpMaker { virtual std::string GetOpType() const { return "Reduce reduce_max"; } }; -DECLARE_INFER_SHAPE_FUNCTOR(reduce_max, - ReduceMaxInferShapeFunctor, - PD_INFER_META(phi::ReduceInferMetaBase)); +DECLARE_INFER_SHAPE_FUNCTOR( + reduce_max, + ReduceMaxInferShapeFunctor, + PD_INFER_META(phi::ReduceIntArrayAxisInferMetaBase)); REGISTER_OPERATOR( reduce_max, diff --git a/paddle/phi/api/yaml/legacy_api.yaml b/paddle/phi/api/yaml/legacy_api.yaml index 79ae456a80edd..03a935cd18295 100755 --- a/paddle/phi/api/yaml/legacy_api.yaml +++ b/paddle/phi/api/yaml/legacy_api.yaml @@ -1635,10 +1635,10 @@ func : matrix_rank_tol - api : max - args : (Tensor x, int64_t[] dims={}, bool keep_dim=false) + args : (Tensor x, IntArray dims={}, bool keep_dim=false) output : Tensor(out) infer_meta : - func : ReduceInferMeta + func : ReduceIntArrayAxisInferMeta kernel : func : max backward : max_grad diff --git a/paddle/phi/api/yaml/legacy_backward.yaml b/paddle/phi/api/yaml/legacy_backward.yaml index 3942abcda2387..bebc795bf8543 100755 --- a/paddle/phi/api/yaml/legacy_backward.yaml +++ b/paddle/phi/api/yaml/legacy_backward.yaml @@ -1394,8 +1394,8 @@ func : matrix_power_grad - backward_api : max_grad - forward: max (Tensor x, int64_t[] dims={}, bool keep_dim=false) -> Tensor(out) - args : (Tensor x, Tensor out, Tensor out_grad, int64_t[] dims={}, bool keep_dim=false, bool reduce_all=false) + forward: max (Tensor x, IntArray dims={}, bool keep_dim=false) -> Tensor(out) + args : (Tensor x, Tensor out, Tensor out_grad, IntArray dims={}, bool keep_dim=false, bool reduce_all=false) output : Tensor(x_grad) infer_meta : func : UnchangedInferMeta diff --git a/paddle/phi/kernels/cpu/matrix_rank_tol_kernel.cc b/paddle/phi/kernels/cpu/matrix_rank_tol_kernel.cc index 4f941099c9d05..491e9c5d210cb 100644 --- a/paddle/phi/kernels/cpu/matrix_rank_tol_kernel.cc +++ b/paddle/phi/kernels/cpu/matrix_rank_tol_kernel.cc @@ -118,7 +118,7 @@ void MatrixRankTolKernel(const Context& dev_ctx, dev_ctx.template Alloc(&max_eigenvalue_tensor); phi::MaxKernel(dev_ctx, eigenvalue_tensor, - std::vector{-1}, + phi::IntArray({-1}), false, &max_eigenvalue_tensor); diff --git a/paddle/phi/kernels/cpu/reduce_max_kernel.cc b/paddle/phi/kernels/cpu/reduce_max_kernel.cc index f9ea0aa0faf06..b15a555a2cf4d 100644 --- a/paddle/phi/kernels/cpu/reduce_max_kernel.cc +++ b/paddle/phi/kernels/cpu/reduce_max_kernel.cc @@ -24,13 +24,13 @@ namespace phi { template void MaxRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out) { auto out_dtype = x.dtype(); phi::Reduce( - dev_ctx, x, reduce_all, dims, keep_dim, out_dtype, out); + dev_ctx, x, reduce_all, dims.GetData(), keep_dim, out_dtype, out); } } // namespace phi diff --git a/paddle/phi/kernels/gpu/matrix_rank_tol_kernel.cu b/paddle/phi/kernels/gpu/matrix_rank_tol_kernel.cu index 5661d61c4e8c5..050c6d2faf535 100644 --- a/paddle/phi/kernels/gpu/matrix_rank_tol_kernel.cu +++ b/paddle/phi/kernels/gpu/matrix_rank_tol_kernel.cu @@ -378,7 +378,7 @@ void MatrixRankTolKernel(const Context& dev_ctx, phi::MaxKernel(dev_ctx, eigenvalue_tensor, - std::vector{-1}, + phi::IntArray({-1}), false, &max_eigenvalue_tensor); diff --git a/paddle/phi/kernels/impl/reduce_max_grad_kernel_impl.h b/paddle/phi/kernels/impl/reduce_max_grad_kernel_impl.h index 83dd4a2b576bb..33730a3717781 100644 --- a/paddle/phi/kernels/impl/reduce_max_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/reduce_max_grad_kernel_impl.h @@ -25,12 +25,12 @@ void ReduceMaxGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad) { ReduceGradKernel( - dev_ctx, x, out, out_grad, dims, keep_dim, reduce_all, x_grad); + dev_ctx, x, out, out_grad, dims.GetData(), keep_dim, reduce_all, x_grad); } } // namespace phi diff --git a/paddle/phi/kernels/kps/reduce_max_kernel.cu b/paddle/phi/kernels/kps/reduce_max_kernel.cu index 52644849ad8bf..fb47b64f6ecec 100644 --- a/paddle/phi/kernels/kps/reduce_max_kernel.cu +++ b/paddle/phi/kernels/kps/reduce_max_kernel.cu @@ -12,22 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "paddle/phi/kernels/reduce_max_kernel.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/gpu/reduce.h" -#include "paddle/phi/kernels/reduce_max_kernel.h" namespace phi { template void MaxRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out) { auto out_dtype = x.dtype(); phi::Reduce( - dev_ctx, x, reduce_all, dims, keep_dim, out_dtype, out); + dev_ctx, x, reduce_all, dims.GetData(), keep_dim, out_dtype, out); } } // namespace phi diff --git a/paddle/phi/kernels/reduce_max_grad_kernel.h b/paddle/phi/kernels/reduce_max_grad_kernel.h index ef3d9f36d28de..d1522667935f6 100644 --- a/paddle/phi/kernels/reduce_max_grad_kernel.h +++ b/paddle/phi/kernels/reduce_max_grad_kernel.h @@ -15,6 +15,7 @@ #pragma once #include "paddle/phi/common/data_type.h" +#include "paddle/phi/common/int_array.h" #include "paddle/phi/core/dense_tensor.h" namespace phi { @@ -23,7 +24,7 @@ void ReduceMaxGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad); diff --git a/paddle/phi/kernels/reduce_max_kernel.cc b/paddle/phi/kernels/reduce_max_kernel.cc index 7bdf9ba2bbcc6..72dd515fc4321 100644 --- a/paddle/phi/kernels/reduce_max_kernel.cc +++ b/paddle/phi/kernels/reduce_max_kernel.cc @@ -22,7 +22,7 @@ namespace phi { template void MaxKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, DenseTensor* out) { bool reduce_all = false; diff --git a/paddle/phi/kernels/reduce_max_kernel.h b/paddle/phi/kernels/reduce_max_kernel.h index f224f494a7229..2af22a2ddde3d 100644 --- a/paddle/phi/kernels/reduce_max_kernel.h +++ b/paddle/phi/kernels/reduce_max_kernel.h @@ -14,13 +14,14 @@ #pragma once +#include "paddle/phi/common/int_array.h" #include "paddle/phi/core/dense_tensor.h" namespace phi { template void MaxRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out); @@ -28,7 +29,7 @@ void MaxRawKernel(const Context& dev_ctx, template void MaxKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, DenseTensor* out); diff --git a/paddle/phi/kernels/reduce_min_kernel.h b/paddle/phi/kernels/reduce_min_kernel.h index 4619a0ed4136c..e6f133cc9ca00 100644 --- a/paddle/phi/kernels/reduce_min_kernel.h +++ b/paddle/phi/kernels/reduce_min_kernel.h @@ -14,9 +14,8 @@ #pragma once -#include "paddle/phi/core/dense_tensor.h" - #include "paddle/phi/common/int_array.h" +#include "paddle/phi/core/dense_tensor.h" namespace phi { diff --git a/python/paddle/fluid/tests/unittests/test_max_op.py b/python/paddle/fluid/tests/unittests/test_max_op.py index 5ae5c344ae7fb..2e8d3d1d986d1 100644 --- a/python/paddle/fluid/tests/unittests/test_max_op.py +++ b/python/paddle/fluid/tests/unittests/test_max_op.py @@ -70,15 +70,6 @@ def test_input_type(): self.assertRaises(TypeError, test_input_type) - def test_axis_type(): - with paddle.static.program_guard(paddle.static.Program(), - paddle.static.Program()): - data = paddle.static.data("data", shape=[10, 10], dtype="int64") - axis = paddle.static.data("axis", shape=[10, 10], dtype="int64") - result_max = paddle.max(data, axis) - - self.assertRaises(TypeError, test_axis_type) - def test_imperative_api(self): paddle.disable_static() np_x = np.array([10, 10]).astype('float64') diff --git a/python/paddle/tensor/math.py b/python/paddle/tensor/math.py index ff4a61d48a889..c3bd2776a28e7 100644 --- a/python/paddle/tensor/math.py +++ b/python/paddle/tensor/math.py @@ -2173,7 +2173,7 @@ def max(x, axis=None, keepdim=False, name=None): #[7., 8.], [[[0., 0.], [0., 0.]], [[0., 0.], [1., 1.]]] """ - reduce_all, axis = _get_reduce_axis(axis) + reduce_all, axis = _get_reduce_axis_with_tensor(axis) if in_dygraph_mode(): return _C_ops.final_state_max(x, axis, keepdim) if _in_legacy_dygraph(): From 1f405d149cb23f20c170d0e636e8f08a0028548c Mon Sep 17 00:00:00 2001 From: 0x45f Date: Mon, 15 Aug 2022 11:50:37 +0000 Subject: [PATCH 08/22] Add UT --- .../fluid/tests/unittests/test_max_op.py | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/python/paddle/fluid/tests/unittests/test_max_op.py b/python/paddle/fluid/tests/unittests/test_max_op.py index 2e8d3d1d986d1..446d06906a403 100644 --- a/python/paddle/fluid/tests/unittests/test_max_op.py +++ b/python/paddle/fluid/tests/unittests/test_max_op.py @@ -14,12 +14,15 @@ from __future__ import print_function +import os import unittest +import tempfile import numpy as np from op_test import OpTest, skip_check_grad_ci, check_out_dtype import paddle from paddle.fluid.framework import _test_eager_guard import paddle.fluid.core as core +import paddle.inference as paddle_infer class ApiMaxTest(unittest.TestCase): @@ -115,5 +118,87 @@ def test_max(self): expect_dtypes=['float32', 'float64', 'int32', 'int64']) +class TestMaxWithTensorAxis1(unittest.TestCase): + + def setUp(self): + self.temp_dir = tempfile.TemporaryDirectory() + self.save_path = os.path.join(self.temp_dir.name, + 'max_with_tensor_axis') + self.place = paddle.CUDAPlace( + 0) if paddle.is_compiled_with_cuda() else paddle.CPUPlace() + self.init_data() + + def tearDwon(self): + self.temp_dir.cleanup() + + def init_data(self): + self.x = paddle.randn([2, 3, 4, 5, 5], dtype='float32') + self.axis = paddle.to_tensor([1, 2], dtype='int64') + + def test_dygraph(self): + self.x.stop_gradient = False + pd_out = paddle.max(self.x, self.axis) + np_out = np.max(self.x.numpy(), tuple(self.axis.numpy())) + + self.assertTrue( + np.array_equal(pd_out.numpy() if pd_out.size > 1 else pd_out.item(), + np_out)) + pd_out.backward() + self.assertEqual(self.x.gradient().shape, tuple(self.x.shape)) + + def test_static_and_infer(self): + paddle.enable_static() + main_prog = paddle.static.Program() + starup_prog = paddle.static.Program() + with paddle.static.program_guard(main_prog, starup_prog): + # run static + x = paddle.static.data(shape=self.x.shape, + name='x', + dtype=self.x.dtype) + axis = paddle.static.data(shape=self.axis.shape, + name='axis', + dtype=self.axis.dtype) + fc = paddle.nn.Linear(self.x.shape[-1], 6) + fc_out = fc(x) + out = paddle.max(fc_out, axis) + exe = paddle.static.Executor(self.place) + exe.run(starup_prog) + static_out = exe.run(feed={ + 'x': self.x.numpy(), + 'axis': self.axis.numpy() + }, + fetch_list=[out]) + + # run infer + paddle.static.save_inference_model(self.save_path, [x, axis], [out], + exe) + config = paddle_infer.Config(self.save_path + '.pdmodel', + self.save_path + '.pdiparams') + predictor = paddle_infer.create_predictor(config) + input_names = predictor.get_input_names() + input_handle = predictor.get_input_handle(input_names[0]) + fake_input = self.x.numpy() + input_handle.reshape(self.x.shape) + input_handle.copy_from_cpu(fake_input) + input_handle = predictor.get_input_handle(input_names[1]) + fake_input = self.axis.numpy() + input_handle.reshape(self.axis.shape) + input_handle.copy_from_cpu(fake_input) + predictor.run() + output_names = predictor.get_output_names() + output_handle = predictor.get_output_handle(output_names[0]) + infer_out = output_handle.copy_to_cpu() + + self.assertTrue(np.array_equal(static_out[0], infer_out)) + paddle.disable_static() + + +class TestMaxWithTensorAxis2(TestMaxWithTensorAxis1): + + def init_data(self): + self.x = paddle.randn([3, 4, 7], dtype='float32') + self.axis = paddle.to_tensor([0, 1, 2], dtype='int64') + + if __name__ == '__main__': unittest.main() From bc5699a291470de0eba54c3ce4f1e86025b8cf88 Mon Sep 17 00:00:00 2001 From: 0x45f Date: Mon, 15 Aug 2022 13:34:16 +0000 Subject: [PATCH 09/22] Adapt reduce_mean --- .../operators/reduce_ops/reduce_mean_op.cc | 7 +++--- paddle/phi/api/yaml/legacy_api.yaml | 4 +-- paddle/phi/api/yaml/legacy_backward.yaml | 8 +++--- .../kernels/cpu/reduce_mean_grad_kernel.cc | 12 ++++++--- paddle/phi/kernels/cpu/reduce_mean_kernel.cc | 4 +-- .../kernels/gpu/reduce_mean_grad_kernel.cu | 6 ++--- paddle/phi/kernels/kps/reduce_mean_kernel.cu | 6 ++--- paddle/phi/kernels/reduce_mean_grad_kernel.h | 3 ++- paddle/phi/kernels/reduce_mean_kernel.cc | 2 +- paddle/phi/kernels/reduce_mean_kernel.h | 8 +++--- python/paddle/tensor/stat.py | 25 +++++++++++-------- 11 files changed, 49 insertions(+), 36 deletions(-) diff --git a/paddle/fluid/operators/reduce_ops/reduce_mean_op.cc b/paddle/fluid/operators/reduce_ops/reduce_mean_op.cc index 9afa493e4ad9e..a5827b1e0a9d1 100644 --- a/paddle/fluid/operators/reduce_ops/reduce_mean_op.cc +++ b/paddle/fluid/operators/reduce_ops/reduce_mean_op.cc @@ -97,9 +97,10 @@ class __reduce_meanMaker__ : public ops::ReduceOpMaker { virtual std::string GetOpType() const { return "Reduce reduce_mean"; } }; -DECLARE_INFER_SHAPE_FUNCTOR(reduce_mean, - ReduceMeanInferShapeFunctor, - PD_INFER_META(phi::ReduceInferMetaBase)); +DECLARE_INFER_SHAPE_FUNCTOR( + reduce_mean, + ReduceMeanInferShapeFunctor, + PD_INFER_META(phi::ReduceIntArrayAxisInferMetaBase)); REGISTER_OPERATOR(reduce_mean, ops::ReduceOp, diff --git a/paddle/phi/api/yaml/legacy_api.yaml b/paddle/phi/api/yaml/legacy_api.yaml index 03a935cd18295..87fabccd025de 100755 --- a/paddle/phi/api/yaml/legacy_api.yaml +++ b/paddle/phi/api/yaml/legacy_api.yaml @@ -1680,10 +1680,10 @@ backward : maxout_grad - api : mean - args : (Tensor x, int64_t[] dims={}, bool keep_dim=false) + args : (Tensor x, IntArray dims={}, bool keep_dim=false) output : Tensor(out) infer_meta : - func : ReduceInferMeta + func : ReduceIntArrayAxisInferMeta kernel : func : mean backward : mean_grad diff --git a/paddle/phi/api/yaml/legacy_backward.yaml b/paddle/phi/api/yaml/legacy_backward.yaml index bebc795bf8543..b9ce54ae844ba 100755 --- a/paddle/phi/api/yaml/legacy_backward.yaml +++ b/paddle/phi/api/yaml/legacy_backward.yaml @@ -1452,14 +1452,14 @@ func : mean_all_grad - backward_api : mean_double_grad - forward: mean_grad (Tensor x, Tensor grad_out, int64_t[] dims={}, bool keep_dim=false, bool reduce_all = false) -> Tensor(grad_x) - args : (Tensor grad_x_grad, int64_t[] dims={}, bool keep_dim=false, bool reduce_all=false) + forward: mean_grad (Tensor x, Tensor grad_out, IntArray dims={}, bool keep_dim=false, bool reduce_all = false) -> Tensor(grad_x) + args : (Tensor grad_x_grad, IntArray dims={}, bool keep_dim=false, bool reduce_all=false) output : Tensor(grad_out_grad) invoke : mean(grad_x_grad, dims, keep_dim) - backward_api : mean_grad - forward: mean (Tensor x, int64_t[] dims={}, bool keep_dim=false) -> Tensor(out) - args : (Tensor x, Tensor out_grad, int64_t[] dims={}, bool keep_dim=false, bool reduce_all=false) + forward: mean (Tensor x, IntArray dims={}, bool keep_dim=false) -> Tensor(out) + args : (Tensor x, Tensor out_grad, IntArray dims={}, bool keep_dim=false, bool reduce_all=false) output : Tensor(x_grad) infer_meta : func : UnchangedInferMeta diff --git a/paddle/phi/kernels/cpu/reduce_mean_grad_kernel.cc b/paddle/phi/kernels/cpu/reduce_mean_grad_kernel.cc index 77176d5d7469e..3ab8a40a85e55 100644 --- a/paddle/phi/kernels/cpu/reduce_mean_grad_kernel.cc +++ b/paddle/phi/kernels/cpu/reduce_mean_grad_kernel.cc @@ -24,12 +24,18 @@ template void ReduceMeanGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad) { - ReduceGradKernel( - dev_ctx, x, paddle::none, out_grad, dims, keep_dim, reduce_all, x_grad); + ReduceGradKernel(dev_ctx, + x, + paddle::none, + out_grad, + dims.GetData(), + keep_dim, + reduce_all, + x_grad); } } // namespace phi diff --git a/paddle/phi/kernels/cpu/reduce_mean_kernel.cc b/paddle/phi/kernels/cpu/reduce_mean_kernel.cc index 8fa687632f653..7164ec8b2bf99 100644 --- a/paddle/phi/kernels/cpu/reduce_mean_kernel.cc +++ b/paddle/phi/kernels/cpu/reduce_mean_kernel.cc @@ -24,13 +24,13 @@ namespace phi { template void MeanRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out) { auto out_dtype = x.dtype(); phi::Reduce( - dev_ctx, x, reduce_all, dims, keep_dim, out_dtype, out); + dev_ctx, x, reduce_all, dims.GetData(), keep_dim, out_dtype, out); } } // namespace phi diff --git a/paddle/phi/kernels/gpu/reduce_mean_grad_kernel.cu b/paddle/phi/kernels/gpu/reduce_mean_grad_kernel.cu index 50564a339ddc0..7da2502a5eea7 100644 --- a/paddle/phi/kernels/gpu/reduce_mean_grad_kernel.cu +++ b/paddle/phi/kernels/gpu/reduce_mean_grad_kernel.cu @@ -25,13 +25,13 @@ template void ReduceMeanGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad) { int dim_size = x.dims().size(); std::vector reduce_dims = - funcs::details::GetReduceDim(dims, dim_size, reduce_all); + funcs::details::GetReduceDim(dims.GetData(), dim_size, reduce_all); int reduce_num = 1; for (auto i : reduce_dims) { reduce_num *= (x.dims())[i]; @@ -41,7 +41,7 @@ void ReduceMeanGradKernel(const Context& dev_ctx, dev_ctx, x, out_grad, - dims, + dims.GetData(), keep_dim, reduce_all, x_grad, diff --git a/paddle/phi/kernels/kps/reduce_mean_kernel.cu b/paddle/phi/kernels/kps/reduce_mean_kernel.cu index c4ecd4380c306..7f7946e030063 100644 --- a/paddle/phi/kernels/kps/reduce_mean_kernel.cu +++ b/paddle/phi/kernels/kps/reduce_mean_kernel.cu @@ -12,22 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "paddle/phi/kernels/reduce_mean_kernel.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/gpu/reduce.h" -#include "paddle/phi/kernels/reduce_mean_kernel.h" namespace phi { template void MeanRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out) { auto out_dtype = x.dtype(); phi::Reduce( - dev_ctx, x, reduce_all, dims, keep_dim, out_dtype, out, true); + dev_ctx, x, reduce_all, dims.GetData(), keep_dim, out_dtype, out, true); } } // namespace phi diff --git a/paddle/phi/kernels/reduce_mean_grad_kernel.h b/paddle/phi/kernels/reduce_mean_grad_kernel.h index ccda3160aa9e5..572e5a0f6fb0c 100644 --- a/paddle/phi/kernels/reduce_mean_grad_kernel.h +++ b/paddle/phi/kernels/reduce_mean_grad_kernel.h @@ -15,6 +15,7 @@ #pragma once #include "paddle/phi/common/data_type.h" +#include "paddle/phi/common/int_array.h" #include "paddle/phi/core/dense_tensor.h" namespace phi { @@ -22,7 +23,7 @@ template void ReduceMeanGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad); diff --git a/paddle/phi/kernels/reduce_mean_kernel.cc b/paddle/phi/kernels/reduce_mean_kernel.cc index 599b7eca32110..4bb77ac974792 100644 --- a/paddle/phi/kernels/reduce_mean_kernel.cc +++ b/paddle/phi/kernels/reduce_mean_kernel.cc @@ -22,7 +22,7 @@ namespace phi { template void MeanKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, DenseTensor* out) { bool reduce_all = false; diff --git a/paddle/phi/kernels/reduce_mean_kernel.h b/paddle/phi/kernels/reduce_mean_kernel.h index 2ac4bd8a46e64..f868746fafd54 100644 --- a/paddle/phi/kernels/reduce_mean_kernel.h +++ b/paddle/phi/kernels/reduce_mean_kernel.h @@ -22,7 +22,7 @@ namespace phi { template void MeanRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out); @@ -30,18 +30,18 @@ void MeanRawKernel(const Context& dev_ctx, template void MeanKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, DenseTensor* out); template DenseTensor Mean(const Context& dev_ctx, const DenseTensor& x, - const std::vector& axis, + const IntArray& axis, bool keep_dim) { DenseTensor dense_out; MetaTensor meta_out(&dense_out); - SumRawInferMeta(x, axis, keep_dim, false, x.dtype(), &meta_out); + SumRawInferMeta(x, axis.GetData(), keep_dim, false, x.dtype(), &meta_out); MeanKernel(dev_ctx, x, axis, keep_dim, &dense_out); return dense_out; } diff --git a/python/paddle/tensor/stat.py b/python/paddle/tensor/stat.py index f0bc955734d61..2093f56011539 100644 --- a/python/paddle/tensor/stat.py +++ b/python/paddle/tensor/stat.py @@ -80,17 +80,20 @@ def mean(x, axis=None, keepdim=False, name=None): # [ 8.5 12.5 16.5] """ - if isinstance(axis, int): - axis = [axis] - reduce_all = True if axis is None \ - or len(axis)==0 \ - or len(axis) == len(x.shape) else False - if axis is None or len(axis) == 0: - axis = [0] + if isinstance(axis, Variable): + reduce_all = False + else: + if isinstance(axis, int): + axis = [axis] + reduce_all = True if axis is None \ + or len(axis)==0 \ + or len(axis) == len(x.shape) else False + if axis is None or len(axis) == 0: + axis = [0] if in_dygraph_mode(): if reduce_all: - axis = range(len(x.shape)) + axis = list(range(len(x.shape))) return _C_ops.final_state_mean(x, axis, keepdim) if _in_legacy_dygraph(): return _C_ops.reduce_mean(x, 'dim', axis, 'keep_dim', keepdim, @@ -99,10 +102,12 @@ def mean(x, axis=None, keepdim=False, name=None): check_variable_and_dtype(x, 'x/input', ['uint16', 'float16', 'float32', 'float64'], 'mean/reduce_mean') - check_type(axis, 'axis/dim', (int, list, tuple), 'mean/reduce_mean') + check_type(axis, 'axis/dim', (int, list, tuple, Variable), + 'mean/reduce_mean') if isinstance(axis, (list, tuple)): for item in axis: - check_type(item, 'elements of axis/dim', (int), 'mean/reduce_mean') + check_type(item, 'elements of axis/dim', (int, Variable), + 'mean/reduce_mean') helper = LayerHelper('mean', **locals()) attrs = {'dim': axis, 'keep_dim': keepdim, 'reduce_all': reduce_all} From e824874ed14c3d1ab5e19603f49f5aea47542ca7 Mon Sep 17 00:00:00 2001 From: 0x45f Date: Tue, 16 Aug 2022 11:36:48 +0000 Subject: [PATCH 10/22] Polish Infershape --- paddle/phi/infermeta/unary.cc | 20 ++++++++++++++++---- python/paddle/tensor/math.py | 5 +++++ python/paddle/tensor/stat.py | 4 ++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index c7c46de98e1dc..fc3102b02cd30 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2613,12 +2613,24 @@ void ReduceIntArrayAxisInferMetaBase(const MetaTensor& x, if (config.is_runtime) { ReduceInferMetaBase(x, vec_axis, keep_dim, reduce_all, out); } else { - auto x_rank = static_cast(x.dims().size()); std::vector vec_dim; - if (vec_axis.size() >= x_rank) { - vec_dim = {-1}; + if (reduce_all) { + if (keep_dim) { + vec_dim = std::vector(x.dims().size(), 1); + } else { + vec_dim = {1}; + } } else { - vec_dim = std::vector(x.dims().size() - vec_axis.size(), -1); + if (keep_dim) { + vec_dim = std::vector(x.dims().size(), 1); + } else { + auto x_rank = static_cast(x.dims().size()); + if (vec_axis.size() >= x_rank) { + vec_dim = {-1}; + } else { + vec_dim = std::vector(x.dims().size() - vec_axis.size(), -1); + } + } } DDim out_dim = phi::make_ddim(vec_dim); out->set_dims(out_dim); diff --git a/python/paddle/tensor/math.py b/python/paddle/tensor/math.py index c3bd2776a28e7..525ebecbf10c2 100644 --- a/python/paddle/tensor/math.py +++ b/python/paddle/tensor/math.py @@ -34,6 +34,7 @@ from ..framework import _varbase_creator, convert_np_dtype_to_dtype_ from ..fluid.data_feeder import check_variable_and_dtype, check_type, check_dtype, convert_dtype from ..fluid.dygraph.inplace_utils import inplace_apis_in_dygraph_only +from ..fluid.layers import utils # TODO: define math functions # yapf: disable @@ -2183,6 +2184,8 @@ def max(x, axis=None, keepdim=False, name=None): helper = LayerHelper('max', **locals()) check_variable_and_dtype( x, 'x', ['float32', 'float64', 'int32', 'int64'], 'max') + if utils._contain_var(axis): + axis = utils._convert_to_tensor_list(axis) out = helper.create_variable_for_type_inference( dtype=x.dtype) @@ -2285,6 +2288,8 @@ def min(x, axis=None, keepdim=False, name=None): helper = LayerHelper('min', **locals()) check_variable_and_dtype( x, 'x', ['float32', 'float64', 'int32', 'int64'], 'min') + if utils._contain_var(axis): + axis = utils._convert_to_tensor_list(axis) out = helper.create_variable_for_type_inference( dtype=x.dtype) diff --git a/python/paddle/tensor/stat.py b/python/paddle/tensor/stat.py index 2093f56011539..a211494b09961 100644 --- a/python/paddle/tensor/stat.py +++ b/python/paddle/tensor/stat.py @@ -21,6 +21,7 @@ from paddle.fluid.framework import _in_legacy_dygraph, in_dygraph_mode from .search import where from ..fluid.data_feeder import convert_dtype, check_variable_and_dtype, check_type, check_dtype +from ..fluid.layers import utils import paddle from paddle import _C_ops @@ -110,6 +111,9 @@ def mean(x, axis=None, keepdim=False, name=None): 'mean/reduce_mean') helper = LayerHelper('mean', **locals()) + + if utils._contain_var(axis): + axis = utils._convert_to_tensor_list(axis) attrs = {'dim': axis, 'keep_dim': keepdim, 'reduce_all': reduce_all} out = helper.create_variable_for_type_inference(x.dtype) helper.append_op(type='reduce_mean', From 2ba21023298fb28ad6c9bfaaaddb871cb4b263da Mon Sep 17 00:00:00 2001 From: 0x45f Date: Wed, 17 Aug 2022 03:07:37 +0000 Subject: [PATCH 11/22] Refine InferMeta in compile time --- paddle/phi/infermeta/unary.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index fc3102b02cd30..a55533a22c385 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2613,6 +2613,14 @@ void ReduceIntArrayAxisInferMetaBase(const MetaTensor& x, if (config.is_runtime) { ReduceInferMetaBase(x, vec_axis, keep_dim, reduce_all, out); } else { + bool is_all_minus_one = + std::all_of(vec_axis.begin(), vec_axis.end(), [](int64_t axis) { + return axis == -1; + }); + if (!is_all_minus_one) { + ReduceInferMetaBase(x, vec_axis, keep_dim, reduce_all, out); + return; + } std::vector vec_dim; if (reduce_all) { if (keep_dim) { @@ -2622,7 +2630,7 @@ void ReduceIntArrayAxisInferMetaBase(const MetaTensor& x, } } else { if (keep_dim) { - vec_dim = std::vector(x.dims().size(), 1); + vec_dim = std::vector(x.dims().size(), -1); } else { auto x_rank = static_cast(x.dims().size()); if (vec_axis.size() >= x_rank) { From e98da10a41072759018ebe0c318f300bb6730a60 Mon Sep 17 00:00:00 2001 From: 0x45f Date: Wed, 17 Aug 2022 07:06:55 +0000 Subject: [PATCH 12/22] Use IntArray.FromTensor --- paddle/phi/infermeta/unary.cc | 10 +--------- python/paddle/fluid/tests/unittests/test_max_op.py | 1 + python/paddle/fluid/tests/unittests/test_min_op.py | 1 + 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index a55533a22c385..24e18079b1c82 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2610,17 +2610,9 @@ void ReduceIntArrayAxisInferMetaBase(const MetaTensor& x, MetaTensor* out, MetaConfig config) { std::vector vec_axis = axis.GetData(); - if (config.is_runtime) { + if (config.is_runtime || !axis.FromTensor()) { ReduceInferMetaBase(x, vec_axis, keep_dim, reduce_all, out); } else { - bool is_all_minus_one = - std::all_of(vec_axis.begin(), vec_axis.end(), [](int64_t axis) { - return axis == -1; - }); - if (!is_all_minus_one) { - ReduceInferMetaBase(x, vec_axis, keep_dim, reduce_all, out); - return; - } std::vector vec_dim; if (reduce_all) { if (keep_dim) { diff --git a/python/paddle/fluid/tests/unittests/test_max_op.py b/python/paddle/fluid/tests/unittests/test_max_op.py index 446d06906a403..92daaf44c6adf 100644 --- a/python/paddle/fluid/tests/unittests/test_max_op.py +++ b/python/paddle/fluid/tests/unittests/test_max_op.py @@ -121,6 +121,7 @@ def test_max(self): class TestMaxWithTensorAxis1(unittest.TestCase): def setUp(self): + paddle.seed(2022) self.temp_dir = tempfile.TemporaryDirectory() self.save_path = os.path.join(self.temp_dir.name, 'max_with_tensor_axis') diff --git a/python/paddle/fluid/tests/unittests/test_min_op.py b/python/paddle/fluid/tests/unittests/test_min_op.py index 63b43d01390d1..40aed0cf9e76f 100644 --- a/python/paddle/fluid/tests/unittests/test_min_op.py +++ b/python/paddle/fluid/tests/unittests/test_min_op.py @@ -100,6 +100,7 @@ def test_min(self): class TestMinWithTensorAxis1(unittest.TestCase): def setUp(self): + paddle.seed(2022) self.temp_dir = tempfile.TemporaryDirectory() self.save_path = os.path.join(self.temp_dir.name, 'min_with_tensor_axis') From 2f37607165e07e15a76803f67c6e0ed15946cabc Mon Sep 17 00:00:00 2001 From: 0x45f Date: Wed, 17 Aug 2022 11:07:06 +0000 Subject: [PATCH 13/22] Add SupportTensor for dim --- paddle/fluid/operators/reduce_ops/reduce_op.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/paddle/fluid/operators/reduce_ops/reduce_op.h b/paddle/fluid/operators/reduce_ops/reduce_op.h index 9e53a6b56de5c..df7804dc7a68d 100644 --- a/paddle/fluid/operators/reduce_ops/reduce_op.h +++ b/paddle/fluid/operators/reduce_ops/reduce_op.h @@ -698,7 +698,8 @@ class ReduceOpMaker : public framework::OpProtoAndCheckerMaker { "Must be in the range [-rank(input), rank(input)). " "If `dim[i] < 0`, the dims[i] to reduce is `rank + dims[i]`. " "Note that reducing on the first dim will make the LoD info lost.") - .SetDefault({0}); + .SetDefault({0}) + .SupportTensor(); AddAttr("keep_dim", "(bool, default false) " "If true, retain the reduced dimension with length 1.") From 0ae23c6633403f05bdec6d0b91b16b9c2c9a0b8f Mon Sep 17 00:00:00 2001 From: 0x45f Date: Wed, 17 Aug 2022 12:27:37 +0000 Subject: [PATCH 14/22] Using allclose --- python/paddle/fluid/tests/unittests/test_max_op.py | 2 +- python/paddle/fluid/tests/unittests/test_min_op.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_max_op.py b/python/paddle/fluid/tests/unittests/test_max_op.py index 92daaf44c6adf..1215621938c7a 100644 --- a/python/paddle/fluid/tests/unittests/test_max_op.py +++ b/python/paddle/fluid/tests/unittests/test_max_op.py @@ -190,7 +190,7 @@ def test_static_and_infer(self): output_handle = predictor.get_output_handle(output_names[0]) infer_out = output_handle.copy_to_cpu() - self.assertTrue(np.array_equal(static_out[0], infer_out)) + np.assert_allclose(static_out[0], infer_out) paddle.disable_static() diff --git a/python/paddle/fluid/tests/unittests/test_min_op.py b/python/paddle/fluid/tests/unittests/test_min_op.py index 40aed0cf9e76f..777669bd32853 100644 --- a/python/paddle/fluid/tests/unittests/test_min_op.py +++ b/python/paddle/fluid/tests/unittests/test_min_op.py @@ -169,7 +169,7 @@ def test_static_and_infer(self): output_handle = predictor.get_output_handle(output_names[0]) infer_out = output_handle.copy_to_cpu() - self.assertTrue(np.array_equal(static_out[0], infer_out)) + np.assert_allclose(static_out[0], infer_out) paddle.disable_static() From 323f71e1f20cb2701700b11cd9076a43a2adf214 Mon Sep 17 00:00:00 2001 From: 0x45f Date: Thu, 18 Aug 2022 03:11:06 +0000 Subject: [PATCH 15/22] Fix assert_allclose --- python/paddle/fluid/tests/unittests/test_max_op.py | 2 +- python/paddle/fluid/tests/unittests/test_min_op.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_max_op.py b/python/paddle/fluid/tests/unittests/test_max_op.py index 1215621938c7a..e3c800f85ff86 100644 --- a/python/paddle/fluid/tests/unittests/test_max_op.py +++ b/python/paddle/fluid/tests/unittests/test_max_op.py @@ -190,7 +190,7 @@ def test_static_and_infer(self): output_handle = predictor.get_output_handle(output_names[0]) infer_out = output_handle.copy_to_cpu() - np.assert_allclose(static_out[0], infer_out) + np.testing.assert_allclose(static_out[0], infer_out) paddle.disable_static() diff --git a/python/paddle/fluid/tests/unittests/test_min_op.py b/python/paddle/fluid/tests/unittests/test_min_op.py index 777669bd32853..2a80e20ce95c1 100644 --- a/python/paddle/fluid/tests/unittests/test_min_op.py +++ b/python/paddle/fluid/tests/unittests/test_min_op.py @@ -169,7 +169,7 @@ def test_static_and_infer(self): output_handle = predictor.get_output_handle(output_names[0]) infer_out = output_handle.copy_to_cpu() - np.assert_allclose(static_out[0], infer_out) + np.testing.assert_allclose(static_out[0], infer_out) paddle.disable_static() From c7538782cdc14395fb3e8e3e3ac74848180c683f Mon Sep 17 00:00:00 2001 From: 0x45f Date: Sun, 21 Aug 2022 07:34:52 +0000 Subject: [PATCH 16/22] Replcae linear whit conv to fix win-infer ci --- python/paddle/fluid/tests/unittests/test_max_op.py | 13 ++++++++----- python/paddle/fluid/tests/unittests/test_min_op.py | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_max_op.py b/python/paddle/fluid/tests/unittests/test_max_op.py index e3c800f85ff86..16e834ee0eb97 100644 --- a/python/paddle/fluid/tests/unittests/test_max_op.py +++ b/python/paddle/fluid/tests/unittests/test_max_op.py @@ -24,6 +24,9 @@ import paddle.fluid.core as core import paddle.inference as paddle_infer +if paddle.fluid.is_compiled_with_cuda(): + paddle.fluid.set_flags({'FLAGS_cudnn_deterministic': True}) + class ApiMaxTest(unittest.TestCase): @@ -133,7 +136,7 @@ def tearDwon(self): self.temp_dir.cleanup() def init_data(self): - self.x = paddle.randn([2, 3, 4, 5, 5], dtype='float32') + self.x = paddle.randn([10, 5, 9, 9], dtype='float32') self.axis = paddle.to_tensor([1, 2], dtype='int64') def test_dygraph(self): @@ -159,9 +162,9 @@ def test_static_and_infer(self): axis = paddle.static.data(shape=self.axis.shape, name='axis', dtype=self.axis.dtype) - fc = paddle.nn.Linear(self.x.shape[-1], 6) - fc_out = fc(x) - out = paddle.max(fc_out, axis) + conv = paddle.nn.Conv2D(self.x.shape[1], 5, 3) + conv_out = conv(x) + out = paddle.max(conv_out, axis) exe = paddle.static.Executor(self.place) exe.run(starup_prog) static_out = exe.run(feed={ @@ -197,7 +200,7 @@ def test_static_and_infer(self): class TestMaxWithTensorAxis2(TestMaxWithTensorAxis1): def init_data(self): - self.x = paddle.randn([3, 4, 7], dtype='float32') + self.x = paddle.randn([10, 5, 9, 9], dtype='float32') self.axis = paddle.to_tensor([0, 1, 2], dtype='int64') diff --git a/python/paddle/fluid/tests/unittests/test_min_op.py b/python/paddle/fluid/tests/unittests/test_min_op.py index 2a80e20ce95c1..f9fd614d1e471 100644 --- a/python/paddle/fluid/tests/unittests/test_min_op.py +++ b/python/paddle/fluid/tests/unittests/test_min_op.py @@ -24,6 +24,9 @@ from paddle.fluid.framework import _test_eager_guard import paddle.inference as paddle_infer +if paddle.fluid.is_compiled_with_cuda(): + paddle.fluid.set_flags({'FLAGS_cudnn_deterministic': True}) + class ApiMinTest(unittest.TestCase): @@ -112,7 +115,7 @@ def tearDwon(self): self.temp_dir.cleanup() def init_data(self): - self.x = paddle.randn([2, 3, 4, 5, 5], dtype='float32') + self.x = paddle.randn([10, 5, 9, 9], dtype='float32') self.axis = paddle.to_tensor([1, 2], dtype='int64') def test_dygraph(self): @@ -138,9 +141,9 @@ def test_static_and_infer(self): axis = paddle.static.data(shape=self.axis.shape, name='axis', dtype=self.axis.dtype) - fc = paddle.nn.Linear(self.x.shape[-1], 6) - fc_out = fc(x) - out = paddle.min(fc_out, axis) + conv = paddle.nn.Conv2D(self.x.shape[1], 5, 3) + conv_out = conv(x) + out = paddle.max(conv_out, axis) exe = paddle.static.Executor(self.place) exe.run(starup_prog) static_out = exe.run(feed={ @@ -176,7 +179,7 @@ def test_static_and_infer(self): class TestMinWithTensorAxis2(TestMinWithTensorAxis1): def init_data(self): - self.x = paddle.randn([3, 4, 7], dtype='float32') + self.x = paddle.randn([10, 5, 9, 9], dtype='float32') self.axis = paddle.to_tensor([0, 1, 2], dtype='int64') From a6244376794263217db8cb3d0face4ee9f959aae Mon Sep 17 00:00:00 2001 From: 0x45f Date: Mon, 22 Aug 2022 09:33:36 +0000 Subject: [PATCH 17/22] Adapt reduce_sum and add UTs --- paddle/phi/api/yaml/legacy_api.yaml | 2 +- paddle/phi/api/yaml/legacy_backward.yaml | 12 +-- paddle/phi/infermeta/unary.cc | 39 +++++-- paddle/phi/infermeta/unary.h | 10 +- .../cpu/graph_send_ue_recv_grad_kernel.cc | 8 +- .../kernels/cpu/graph_send_uv_grad_kernel.cc | 4 +- .../phi/kernels/cpu/reduce_sum_grad_kernel.cc | 18 +++- paddle/phi/kernels/cpu/reduce_sum_kernel.cc | 4 +- .../gpu/graph_send_ue_recv_grad_kernel.cu | 8 +- .../kernels/gpu/graph_send_uv_grad_kernel.cu | 4 +- .../phi/kernels/gpu/reduce_sum_grad_kernel.cu | 4 +- paddle/phi/kernels/impl/einsum_grad_impl.h | 2 +- paddle/phi/kernels/impl/einsum_impl.h | 3 +- paddle/phi/kernels/impl/lstsq_kernel_impl.h | 4 +- paddle/phi/kernels/kps/reduce_sum_kernel.cu | 4 +- paddle/phi/kernels/reduce_mean_kernel.h | 2 +- paddle/phi/kernels/reduce_sum_grad_kernel.h | 3 +- paddle/phi/kernels/reduce_sum_kernel.cc | 2 +- paddle/phi/kernels/reduce_sum_kernel.h | 7 +- paddle/phi/tests/kernels/test_sum_dev_api.cc | 4 +- .../fluid/tests/unittests/test_max_op.py | 95 +++------------- .../fluid/tests/unittests/test_mean_op.py | 25 +++++ .../fluid/tests/unittests/test_min_op.py | 95 +++------------- .../fluid/tests/unittests/test_sum_op.py | 101 ++++++++++++++++++ python/paddle/tensor/math.py | 35 +++--- python/paddle/tensor/stat.py | 2 +- 26 files changed, 274 insertions(+), 223 deletions(-) diff --git a/paddle/phi/api/yaml/legacy_api.yaml b/paddle/phi/api/yaml/legacy_api.yaml index e1eb727dca911..d0c4e7a2e46ac 100755 --- a/paddle/phi/api/yaml/legacy_api.yaml +++ b/paddle/phi/api/yaml/legacy_api.yaml @@ -2562,7 +2562,7 @@ backward : subtract_grad - api : sum - args : (Tensor x, int64_t[] dims={}, DataType out_dtype=DataType::UNDEFINED, bool keep_dim=false) + args : (Tensor x, IntArray dims={}, DataType out_dtype=DataType::UNDEFINED, bool keep_dim=false) output : Tensor(out) infer_meta : func : SumInferMeta diff --git a/paddle/phi/api/yaml/legacy_backward.yaml b/paddle/phi/api/yaml/legacy_backward.yaml index dfea0ca96ae76..3c63e98f40596 100755 --- a/paddle/phi/api/yaml/legacy_backward.yaml +++ b/paddle/phi/api/yaml/legacy_backward.yaml @@ -2402,15 +2402,15 @@ inplace : (out_grad -> x_grad) - backward_api : sum_double_grad - forward : sum_grad (Tensor x, Tensor grad_out, int64_t[] dims, bool keep_dim, bool reduce_all=false) -> Tensor(grad_x) - args : (Tensor grad_x_grad, int64_t[] dims={}, bool keep_dim=false) + forward : sum_grad (Tensor x, Tensor grad_out, IntArray dims, bool keep_dim, bool reduce_all=false) -> Tensor(grad_x) + args : (Tensor grad_x_grad, IntArray dims={}, bool keep_dim=false) output : Tensor(grad_out_grad) invoke : sum(grad_x_grad, dims, grad_x_grad.dtype(), keep_dim) backward : sum_triple_grad - backward_api : sum_grad - forward : sum (Tensor x, int64_t[] dims={}, DataType out_dtype=DataType::UNDEFINED, bool keep_dim=false) -> Tensor(out) - args : (Tensor x, Tensor out_grad, int64_t[] dims, bool keep_dim, bool reduce_all=false) + forward : sum (Tensor x, IntArray dims={}, DataType out_dtype=DataType::UNDEFINED, bool keep_dim=false) -> Tensor(out) + args : (Tensor x, Tensor out_grad, IntArray dims, bool keep_dim, bool reduce_all=false) output : Tensor(x_grad) infer_meta : func : UnchangedInferMeta @@ -2421,8 +2421,8 @@ backward : sum_double_grad - backward_api : sum_triple_grad - forward : sum_double_grad (Tensor grad_grad_x, int64_t[] dims={}, bool keep_dim=false) -> Tensor(grad_grad_out) - args : (Tensor grad_grad_x, Tensor grad_grad_out_grad, int64_t[] dims={}, bool keep_dim=false, bool reduce_all=false) + forward : sum_double_grad (Tensor grad_grad_x, IntArray dims={}, bool keep_dim=false) -> Tensor(grad_grad_out) + args : (Tensor grad_grad_x, Tensor grad_grad_out_grad, IntArray dims={}, bool keep_dim=false, bool reduce_all=false) output : Tensor(grad_grad_x_grad) invoke : sum_grad(grad_grad_x, grad_grad_out_grad, dims, keep_dim, reduce_all, grad_grad_x_grad) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index afb255df73e81..5fa9939ebd11f 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -3360,24 +3360,51 @@ void StridedSliceInferMeta(const MetaTensor& x, api.yaml */ void SumInferMeta(const MetaTensor& x, - const std::vector& axis, + const IntArray& axis, DataType dtype, bool keep_dim, - MetaTensor* out) { + MetaTensor* out, + MetaConfig config) { bool reduce_all = false; if (axis.size() == 0) { reduce_all = true; } - SumRawInferMeta(x, axis, keep_dim, reduce_all, dtype, out); + SumRawInferMeta(x, axis, keep_dim, reduce_all, dtype, out, config); } void SumRawInferMeta(const MetaTensor& x, - const std::vector& axis, + const IntArray& axis, bool keep_dim, bool reduce_all, DataType dtype, - MetaTensor* out) { - DDim out_dim = ReduceInferDim(x, axis, keep_dim, reduce_all); + MetaTensor* out, + MetaConfig config) { + DDim out_dim; + std::vector vec_axis = axis.GetData(); + if (config.is_runtime || !axis.FromTensor()) { + out_dim = ReduceInferDim(x, vec_axis, keep_dim, reduce_all); + } else { + std::vector vec_dim; + if (reduce_all) { + if (keep_dim) { + vec_dim = std::vector(x.dims().size(), 1); + } else { + vec_dim = {1}; + } + } else { + if (keep_dim) { + vec_dim = std::vector(x.dims().size(), -1); + } else { + auto x_rank = static_cast(x.dims().size()); + if (vec_axis.size() >= x_rank) { + vec_dim = {-1}; + } else { + vec_dim = std::vector(x.dims().size() - vec_axis.size(), -1); + } + } + } + out_dim = phi::make_ddim(vec_dim); + } DataType out_dtype; if (dtype != DataType::UNDEFINED) { diff --git a/paddle/phi/infermeta/unary.h b/paddle/phi/infermeta/unary.h index 08c110c184cf7..bcb93608998b3 100644 --- a/paddle/phi/infermeta/unary.h +++ b/paddle/phi/infermeta/unary.h @@ -478,17 +478,19 @@ void StridedSliceInferMeta(const MetaTensor& x, MetaConfig config = MetaConfig()); void SumInferMeta(const MetaTensor& x, - const std::vector& axis, + const IntArray& axis, DataType dtype, bool keep_dim, - MetaTensor* out); + MetaTensor* out, + MetaConfig config = MetaConfig()); void SumRawInferMeta(const MetaTensor& x, - const std::vector& axis, + const IntArray& axis, bool keep_dim, bool reduce_all, DataType dtype, - MetaTensor* out); + MetaTensor* out, + MetaConfig config = MetaConfig()); void SvdInferMeta(const MetaTensor& x, bool full_matrices, diff --git a/paddle/phi/kernels/cpu/graph_send_ue_recv_grad_kernel.cc b/paddle/phi/kernels/cpu/graph_send_ue_recv_grad_kernel.cc index c7b1e3e51853b..912426a778d0c 100644 --- a/paddle/phi/kernels/cpu/graph_send_ue_recv_grad_kernel.cc +++ b/paddle/phi/kernels/cpu/graph_send_ue_recv_grad_kernel.cc @@ -73,7 +73,7 @@ void CalculateXGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); memcpy(x_grad, x_grad_out.data(), x_grad_out.numel() * sizeof(T)); @@ -131,7 +131,7 @@ void CalculateXGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); memcpy(x_grad, x_grad_out.data(), x_grad_out.numel() * sizeof(T)); @@ -166,7 +166,7 @@ void CalculateXGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); memcpy(x_grad, x_grad_out.data(), x_grad_out.numel() * sizeof(T)); @@ -220,7 +220,7 @@ void CalculateXGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); memcpy(x_grad, x_grad_out.data(), x_grad_out.numel() * sizeof(T)); diff --git a/paddle/phi/kernels/cpu/graph_send_uv_grad_kernel.cc b/paddle/phi/kernels/cpu/graph_send_uv_grad_kernel.cc index 4e28acdad3db4..23e5172c3afa7 100644 --- a/paddle/phi/kernels/cpu/graph_send_uv_grad_kernel.cc +++ b/paddle/phi/kernels/cpu/graph_send_uv_grad_kernel.cc @@ -86,7 +86,7 @@ void CalculateGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); memcpy(x_grad, x_grad_out.data(), x_grad_out.numel() * sizeof(T)); @@ -148,7 +148,7 @@ void CalculateGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); memcpy(x_grad, x_grad_out.data(), x_grad_out.numel() * sizeof(T)); diff --git a/paddle/phi/kernels/cpu/reduce_sum_grad_kernel.cc b/paddle/phi/kernels/cpu/reduce_sum_grad_kernel.cc index abc18b1c578a8..87e3df717b244 100644 --- a/paddle/phi/kernels/cpu/reduce_sum_grad_kernel.cc +++ b/paddle/phi/kernels/cpu/reduce_sum_grad_kernel.cc @@ -73,7 +73,7 @@ template void ReduceSumGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad) { @@ -84,17 +84,25 @@ void ReduceSumGradKernel(const Context& dev_ctx, DenseTensor x_grad_tmp = phi::Empty(dev_ctx, std::move(x_grad_meta)); - ComputeFromInput(dev_ctx, x, out_grad, dims, &x_grad_tmp); + ComputeFromInput( + dev_ctx, x, out_grad, dims.GetData(), &x_grad_tmp); phi::CastKernel(dev_ctx, x_grad_tmp, x.dtype(), x_grad); } else { - ComputeFromInput(dev_ctx, x, out_grad, dims, x_grad); + ComputeFromInput( + dev_ctx, x, out_grad, dims.GetData(), x_grad); } } - ReduceGradKernel( - dev_ctx, x, paddle::none, out_grad, dims, keep_dim, reduce_all, x_grad); + ReduceGradKernel(dev_ctx, + x, + paddle::none, + out_grad, + dims.GetData(), + keep_dim, + reduce_all, + x_grad); } } // namespace phi diff --git a/paddle/phi/kernels/cpu/reduce_sum_kernel.cc b/paddle/phi/kernels/cpu/reduce_sum_kernel.cc index 0b4c4b9f4705a..95e5a1a214bb9 100644 --- a/paddle/phi/kernels/cpu/reduce_sum_kernel.cc +++ b/paddle/phi/kernels/cpu/reduce_sum_kernel.cc @@ -24,7 +24,7 @@ namespace phi { template void SumRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DataType out_dtype, @@ -33,7 +33,7 @@ void SumRawKernel(const Context& dev_ctx, out_dtype = out->dtype(); } phi::Reduce( - dev_ctx, x, reduce_all, dims, keep_dim, out_dtype, out); + dev_ctx, x, reduce_all, dims.GetData(), keep_dim, out_dtype, out); } } // namespace phi diff --git a/paddle/phi/kernels/gpu/graph_send_ue_recv_grad_kernel.cu b/paddle/phi/kernels/gpu/graph_send_ue_recv_grad_kernel.cu index c5d5fb7196fb2..1544cf3205d5e 100644 --- a/paddle/phi/kernels/gpu/graph_send_ue_recv_grad_kernel.cu +++ b/paddle/phi/kernels/gpu/graph_send_ue_recv_grad_kernel.cu @@ -158,7 +158,7 @@ void CalculateXGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); #ifdef PADDLE_WITH_HIP @@ -235,7 +235,7 @@ void CalculateXGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); #ifdef PADDLE_WITH_HIP @@ -281,7 +281,7 @@ void CalculateXGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); #ifdef PADDLE_WITH_HIP @@ -349,7 +349,7 @@ void CalculateXGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); // TODO(daisiming): Whether use x_grad instead. diff --git a/paddle/phi/kernels/gpu/graph_send_uv_grad_kernel.cu b/paddle/phi/kernels/gpu/graph_send_uv_grad_kernel.cu index 5b8d7b28dcc29..3240381b513d3 100644 --- a/paddle/phi/kernels/gpu/graph_send_uv_grad_kernel.cu +++ b/paddle/phi/kernels/gpu/graph_send_uv_grad_kernel.cu @@ -108,7 +108,7 @@ void CalculateGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); #ifdef PADDLE_WITH_HIP @@ -190,7 +190,7 @@ void CalculateGrad(const Context& ctx, DenseTensor x_grad_out = phi::Sum( ctx, x_grad_v2, - reduce_idx, + phi::IntArray(reduce_idx), paddle::experimental::CppTypeToDataType::Type(), true); #ifdef PADDLE_WITH_HIP diff --git a/paddle/phi/kernels/gpu/reduce_sum_grad_kernel.cu b/paddle/phi/kernels/gpu/reduce_sum_grad_kernel.cu index c0955cd7424ae..2230b4b8525b3 100644 --- a/paddle/phi/kernels/gpu/reduce_sum_grad_kernel.cu +++ b/paddle/phi/kernels/gpu/reduce_sum_grad_kernel.cu @@ -25,7 +25,7 @@ template void ReduceSumGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad) { @@ -41,7 +41,7 @@ void ReduceSumGradKernel(const Context& dev_ctx, reduce_all = true; } std::vector reduce_dims = - funcs::details::GetReduceDim(dims, dim_size, reduce_all); + funcs::details::GetReduceDim(dims.GetData(), dim_size, reduce_all); auto update_dims = vectorize(d_x->dims()); int reduce_num = 1; diff --git a/paddle/phi/kernels/impl/einsum_grad_impl.h b/paddle/phi/kernels/impl/einsum_grad_impl.h index a04185a0c53ed..992b7572c1be5 100644 --- a/paddle/phi/kernels/impl/einsum_grad_impl.h +++ b/paddle/phi/kernels/impl/einsum_grad_impl.h @@ -80,7 +80,7 @@ DenseTensor PerformTileAndReduction(const Context& dev_ctx, if (to_reduce.size() != 0) { ret = Sum(dev_ctx, after_tile, - to_reduce, + phi::IntArray(to_reduce), after_tile.dtype(), false); // not keep dim. } else { diff --git a/paddle/phi/kernels/impl/einsum_impl.h b/paddle/phi/kernels/impl/einsum_impl.h index b5bc826881af8..80529c8b669aa 100644 --- a/paddle/phi/kernels/impl/einsum_impl.h +++ b/paddle/phi/kernels/impl/einsum_impl.h @@ -383,7 +383,8 @@ DenseTensor PerformReduction(const Context& dev_ctx, VLOG(5) << "call PerformReduction: with axis: " << paddle::string::join_strings(indices, ","); if (indices.size() == 0) return tensor; - return Sum(dev_ctx, tensor, indices, tensor.dtype(), true); + return Sum( + dev_ctx, tensor, phi::IntArray(indices), tensor.dtype(), true); } inline bool is_no_need_transpose(const std::vector& axis) { diff --git a/paddle/phi/kernels/impl/lstsq_kernel_impl.h b/paddle/phi/kernels/impl/lstsq_kernel_impl.h index 73ba954614a22..1644d0852a87d 100644 --- a/paddle/phi/kernels/impl/lstsq_kernel_impl.h +++ b/paddle/phi/kernels/impl/lstsq_kernel_impl.h @@ -69,8 +69,8 @@ inline void GetResidualsTensor(const DeviceContext& dev_ctx, dev_ctx.template Alloc(pow_tensor); phi::PowKernel(dev_ctx, sub_tensor, Scalar(2), pow_tensor); - auto sum_tensor = - phi::Sum(dev_ctx, *pow_tensor, {-2}, pow_tensor->dtype(), false); + auto sum_tensor = phi::Sum( + dev_ctx, *pow_tensor, phi::IntArray({-2}), pow_tensor->dtype(), false); phi::Copy( dev_ctx, sum_tensor, dev_ctx.GetPlace(), true, residuals); } else { diff --git a/paddle/phi/kernels/kps/reduce_sum_kernel.cu b/paddle/phi/kernels/kps/reduce_sum_kernel.cu index f219abd3348a6..fde63963ef3aa 100644 --- a/paddle/phi/kernels/kps/reduce_sum_kernel.cu +++ b/paddle/phi/kernels/kps/reduce_sum_kernel.cu @@ -12,16 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "paddle/phi/kernels/reduce_sum_kernel.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/gpu/reduce.h" -#include "paddle/phi/kernels/reduce_sum_kernel.h" namespace phi { template void SumRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DataType out_dtype, diff --git a/paddle/phi/kernels/reduce_mean_kernel.h b/paddle/phi/kernels/reduce_mean_kernel.h index f868746fafd54..13c387a86e228 100644 --- a/paddle/phi/kernels/reduce_mean_kernel.h +++ b/paddle/phi/kernels/reduce_mean_kernel.h @@ -41,7 +41,7 @@ DenseTensor Mean(const Context& dev_ctx, bool keep_dim) { DenseTensor dense_out; MetaTensor meta_out(&dense_out); - SumRawInferMeta(x, axis.GetData(), keep_dim, false, x.dtype(), &meta_out); + SumRawInferMeta(x, axis, keep_dim, false, x.dtype(), &meta_out); MeanKernel(dev_ctx, x, axis, keep_dim, &dense_out); return dense_out; } diff --git a/paddle/phi/kernels/reduce_sum_grad_kernel.h b/paddle/phi/kernels/reduce_sum_grad_kernel.h index b8b6618d43ec9..8cea1f4b34594 100644 --- a/paddle/phi/kernels/reduce_sum_grad_kernel.h +++ b/paddle/phi/kernels/reduce_sum_grad_kernel.h @@ -15,6 +15,7 @@ #pragma once #include "paddle/phi/common/data_type.h" +#include "paddle/phi/common/int_array.h" #include "paddle/phi/core/dense_tensor.h" namespace phi { @@ -22,7 +23,7 @@ template void ReduceSumGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad); diff --git a/paddle/phi/kernels/reduce_sum_kernel.cc b/paddle/phi/kernels/reduce_sum_kernel.cc index c9622768c45d9..5fed4dbc44d99 100644 --- a/paddle/phi/kernels/reduce_sum_kernel.cc +++ b/paddle/phi/kernels/reduce_sum_kernel.cc @@ -22,7 +22,7 @@ namespace phi { template void SumKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, DataType out_dtype, bool keep_dim, DenseTensor* out) { diff --git a/paddle/phi/kernels/reduce_sum_kernel.h b/paddle/phi/kernels/reduce_sum_kernel.h index c969cea296db1..3bcf025d96bc4 100644 --- a/paddle/phi/kernels/reduce_sum_kernel.h +++ b/paddle/phi/kernels/reduce_sum_kernel.h @@ -14,6 +14,7 @@ #pragma once +#include "paddle/phi/common/int_array.h" #include "paddle/phi/core/dense_tensor.h" #include "paddle/phi/infermeta/unary.h" @@ -21,7 +22,7 @@ namespace phi { template void SumRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DataType out_dtype, @@ -30,7 +31,7 @@ void SumRawKernel(const Context& dev_ctx, template void SumKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, DataType out_dtype, bool keep_dim, DenseTensor* out); @@ -38,7 +39,7 @@ void SumKernel(const Context& dev_ctx, template DenseTensor Sum(const Context& dev_ctx, const DenseTensor& x, - const std::vector& axis, + const IntArray& axis, DataType dtype, bool keep_dim) { DenseTensor dense_out; diff --git a/paddle/phi/tests/kernels/test_sum_dev_api.cc b/paddle/phi/tests/kernels/test_sum_dev_api.cc index 20e934eb69297..b870861eaad2d 100644 --- a/paddle/phi/tests/kernels/test_sum_dev_api.cc +++ b/paddle/phi/tests/kernels/test_sum_dev_api.cc @@ -51,8 +51,8 @@ TEST(DEV_API, sum) { .get()); // 2. test API - auto out = - phi::Sum(dev_ctx, dense_x, axis, phi::DataType::FLOAT32, false); + auto out = phi::Sum( + dev_ctx, dense_x, phi::IntArray(axis), phi::DataType::FLOAT32, false); // 3. check result ASSERT_EQ(out.dims().size(), 1); diff --git a/python/paddle/fluid/tests/unittests/test_max_op.py b/python/paddle/fluid/tests/unittests/test_max_op.py index 16e834ee0eb97..235eef5d90983 100644 --- a/python/paddle/fluid/tests/unittests/test_max_op.py +++ b/python/paddle/fluid/tests/unittests/test_max_op.py @@ -23,9 +23,7 @@ from paddle.fluid.framework import _test_eager_guard import paddle.fluid.core as core import paddle.inference as paddle_infer - -if paddle.fluid.is_compiled_with_cuda(): - paddle.fluid.set_flags({'FLAGS_cudnn_deterministic': True}) +from test_sum_op import TestReduceOPTensorAxisBase class ApiMaxTest(unittest.TestCase): @@ -121,87 +119,28 @@ def test_max(self): expect_dtypes=['float32', 'float64', 'int32', 'int64']) -class TestMaxWithTensorAxis1(unittest.TestCase): - - def setUp(self): - paddle.seed(2022) - self.temp_dir = tempfile.TemporaryDirectory() - self.save_path = os.path.join(self.temp_dir.name, - 'max_with_tensor_axis') - self.place = paddle.CUDAPlace( - 0) if paddle.is_compiled_with_cuda() else paddle.CPUPlace() - self.init_data() - - def tearDwon(self): - self.temp_dir.cleanup() +class TestMaxWithTensorAxis1(TestReduceOPTensorAxisBase): def init_data(self): - self.x = paddle.randn([10, 5, 9, 9], dtype='float32') - self.axis = paddle.to_tensor([1, 2], dtype='int64') + self.pd_api = paddle.max + self.np_api = np.max + self.x = paddle.randn([10, 5, 9, 9], dtype='float64') + self.np_axis = np.array([1, 2], dtype='int64') + self.tensor_axis = paddle.to_tensor([1, 2], dtype='int64') - def test_dygraph(self): - self.x.stop_gradient = False - pd_out = paddle.max(self.x, self.axis) - np_out = np.max(self.x.numpy(), tuple(self.axis.numpy())) - self.assertTrue( - np.array_equal(pd_out.numpy() if pd_out.size > 1 else pd_out.item(), - np_out)) - pd_out.backward() - self.assertEqual(self.x.gradient().shape, tuple(self.x.shape)) - - def test_static_and_infer(self): - paddle.enable_static() - main_prog = paddle.static.Program() - starup_prog = paddle.static.Program() - with paddle.static.program_guard(main_prog, starup_prog): - # run static - x = paddle.static.data(shape=self.x.shape, - name='x', - dtype=self.x.dtype) - axis = paddle.static.data(shape=self.axis.shape, - name='axis', - dtype=self.axis.dtype) - conv = paddle.nn.Conv2D(self.x.shape[1], 5, 3) - conv_out = conv(x) - out = paddle.max(conv_out, axis) - exe = paddle.static.Executor(self.place) - exe.run(starup_prog) - static_out = exe.run(feed={ - 'x': self.x.numpy(), - 'axis': self.axis.numpy() - }, - fetch_list=[out]) - - # run infer - paddle.static.save_inference_model(self.save_path, [x, axis], [out], - exe) - config = paddle_infer.Config(self.save_path + '.pdmodel', - self.save_path + '.pdiparams') - predictor = paddle_infer.create_predictor(config) - input_names = predictor.get_input_names() - input_handle = predictor.get_input_handle(input_names[0]) - fake_input = self.x.numpy() - input_handle.reshape(self.x.shape) - input_handle.copy_from_cpu(fake_input) - input_handle = predictor.get_input_handle(input_names[1]) - fake_input = self.axis.numpy() - input_handle.reshape(self.axis.shape) - input_handle.copy_from_cpu(fake_input) - predictor.run() - output_names = predictor.get_output_names() - output_handle = predictor.get_output_handle(output_names[0]) - infer_out = output_handle.copy_to_cpu() - - np.testing.assert_allclose(static_out[0], infer_out) - paddle.disable_static() - - -class TestMaxWithTensorAxis2(TestMaxWithTensorAxis1): +class TestMaxWithTensorAxis2(TestReduceOPTensorAxisBase): def init_data(self): - self.x = paddle.randn([10, 5, 9, 9], dtype='float32') - self.axis = paddle.to_tensor([0, 1, 2], dtype='int64') + self.pd_api = paddle.max + self.np_api = np.max + self.x = paddle.randn([10, 10, 9, 9], dtype='float64') + self.np_axis = np.array([0, 1, 2], dtype='int64') + self.tensor_axis = [ + 0, + paddle.to_tensor([1], 'int64'), + paddle.to_tensor([2], 'int64') + ] if __name__ == '__main__': diff --git a/python/paddle/fluid/tests/unittests/test_mean_op.py b/python/paddle/fluid/tests/unittests/test_mean_op.py index 965d70a59503f..a4ed6dc3b575c 100644 --- a/python/paddle/fluid/tests/unittests/test_mean_op.py +++ b/python/paddle/fluid/tests/unittests/test_mean_op.py @@ -22,6 +22,7 @@ import paddle.fluid as fluid from paddle.fluid import Program, program_guard from paddle.fluid.framework import _test_eager_guard +from test_sum_op import TestReduceOPTensorAxisBase np.random.seed(10) @@ -408,6 +409,30 @@ def test_errors(self): self.assertRaises(TypeError, paddle.mean, x) +class TestMeanWithTensorAxis1(TestReduceOPTensorAxisBase): + + def init_data(self): + self.pd_api = paddle.mean + self.np_api = np.mean + self.x = paddle.randn([10, 5, 9, 9], dtype='float64') + self.np_axis = np.array([1, 2], dtype='int64') + self.tensor_axis = paddle.to_tensor([1, 2], dtype='int64') + + +class TestMeanWithTensorAxis2(TestReduceOPTensorAxisBase): + + def init_data(self): + self.pd_api = paddle.mean + self.np_api = np.mean + self.x = paddle.randn([10, 10, 9, 9], dtype='float64') + self.np_axis = np.array([0, 1, 2], dtype='int64') + self.tensor_axis = [ + 0, + paddle.to_tensor([1], 'int64'), + paddle.to_tensor([2], 'int64') + ] + + if __name__ == "__main__": paddle.enable_static() unittest.main() diff --git a/python/paddle/fluid/tests/unittests/test_min_op.py b/python/paddle/fluid/tests/unittests/test_min_op.py index f9fd614d1e471..1e01f45f72456 100644 --- a/python/paddle/fluid/tests/unittests/test_min_op.py +++ b/python/paddle/fluid/tests/unittests/test_min_op.py @@ -23,9 +23,7 @@ import paddle.fluid.core as core from paddle.fluid.framework import _test_eager_guard import paddle.inference as paddle_infer - -if paddle.fluid.is_compiled_with_cuda(): - paddle.fluid.set_flags({'FLAGS_cudnn_deterministic': True}) +from test_sum_op import TestReduceOPTensorAxisBase class ApiMinTest(unittest.TestCase): @@ -100,87 +98,28 @@ def test_min(self): expect_dtypes=['float32', 'float64', 'int32', 'int64']) -class TestMinWithTensorAxis1(unittest.TestCase): - - def setUp(self): - paddle.seed(2022) - self.temp_dir = tempfile.TemporaryDirectory() - self.save_path = os.path.join(self.temp_dir.name, - 'min_with_tensor_axis') - self.place = paddle.CUDAPlace( - 0) if paddle.is_compiled_with_cuda() else paddle.CPUPlace() - self.init_data() - - def tearDwon(self): - self.temp_dir.cleanup() +class TestMinWithTensorAxis1(TestReduceOPTensorAxisBase): def init_data(self): - self.x = paddle.randn([10, 5, 9, 9], dtype='float32') - self.axis = paddle.to_tensor([1, 2], dtype='int64') + self.pd_api = paddle.min + self.np_api = np.min + self.x = paddle.randn([10, 5, 9, 9], dtype='float64') + self.np_axis = np.array([1, 2], dtype='int64') + self.tensor_axis = paddle.to_tensor([1, 2], dtype='int64') - def test_dygraph(self): - self.x.stop_gradient = False - pd_out = paddle.min(self.x, self.axis) - np_out = np.min(self.x.numpy(), tuple(self.axis.numpy())) - self.assertTrue( - np.array_equal(pd_out.numpy() if pd_out.size > 1 else pd_out.item(), - np_out)) - pd_out.backward() - self.assertEqual(self.x.gradient().shape, tuple(self.x.shape)) - - def test_static_and_infer(self): - paddle.enable_static() - main_prog = paddle.static.Program() - starup_prog = paddle.static.Program() - with paddle.static.program_guard(main_prog, starup_prog): - # run static - x = paddle.static.data(shape=self.x.shape, - name='x', - dtype=self.x.dtype) - axis = paddle.static.data(shape=self.axis.shape, - name='axis', - dtype=self.axis.dtype) - conv = paddle.nn.Conv2D(self.x.shape[1], 5, 3) - conv_out = conv(x) - out = paddle.max(conv_out, axis) - exe = paddle.static.Executor(self.place) - exe.run(starup_prog) - static_out = exe.run(feed={ - 'x': self.x.numpy(), - 'axis': self.axis.numpy() - }, - fetch_list=[out]) - - # run infer - paddle.static.save_inference_model(self.save_path, [x, axis], [out], - exe) - config = paddle_infer.Config(self.save_path + '.pdmodel', - self.save_path + '.pdiparams') - predictor = paddle_infer.create_predictor(config) - input_names = predictor.get_input_names() - input_handle = predictor.get_input_handle(input_names[0]) - fake_input = self.x.numpy() - input_handle.reshape(self.x.shape) - input_handle.copy_from_cpu(fake_input) - input_handle = predictor.get_input_handle(input_names[1]) - fake_input = self.axis.numpy() - input_handle.reshape(self.axis.shape) - input_handle.copy_from_cpu(fake_input) - predictor.run() - output_names = predictor.get_output_names() - output_handle = predictor.get_output_handle(output_names[0]) - infer_out = output_handle.copy_to_cpu() - - np.testing.assert_allclose(static_out[0], infer_out) - paddle.disable_static() - - -class TestMinWithTensorAxis2(TestMinWithTensorAxis1): +class TestMinWithTensorAxis2(TestReduceOPTensorAxisBase): def init_data(self): - self.x = paddle.randn([10, 5, 9, 9], dtype='float32') - self.axis = paddle.to_tensor([0, 1, 2], dtype='int64') + self.pd_api = paddle.min + self.np_api = np.min + self.x = paddle.randn([10, 10, 9, 9], dtype='float64') + self.np_axis = np.array([0, 1, 2], dtype='int64') + self.tensor_axis = [ + 0, + paddle.to_tensor([1], 'int64'), + paddle.to_tensor([2], 'int64') + ] if __name__ == '__main__': diff --git a/python/paddle/fluid/tests/unittests/test_sum_op.py b/python/paddle/fluid/tests/unittests/test_sum_op.py index a431f79af61ca..ef6fc3df05217 100644 --- a/python/paddle/fluid/tests/unittests/test_sum_op.py +++ b/python/paddle/fluid/tests/unittests/test_sum_op.py @@ -14,7 +14,9 @@ from __future__ import print_function +import os import unittest +import tempfile import numpy as np from op_test import OpTest import paddle @@ -27,6 +29,7 @@ convert_uint16_to_float) from paddle import _C_ops from paddle.fluid.framework import _test_eager_guard +import paddle.inference as paddle_infer class TestSumOp(OpTest): @@ -483,6 +486,104 @@ def test_list_of_none_input(): create_test_sum_fp16_class(TestSelectedRowsSumOp) create_test_sum_fp16_class(TestLoDTensorAndSelectedRowsOp) + +class TestReduceOPTensorAxisBase(unittest.TestCase): + + def setUp(self): + paddle.disable_static() + paddle.seed(2022) + self.temp_dir = tempfile.TemporaryDirectory() + self.save_path = os.path.join(self.temp_dir.name, + 'sum_with_tensor_axis') + self.place = paddle.CUDAPlace( + 0) if paddle.is_compiled_with_cuda() else paddle.CPUPlace() + self.init_data() + + def tearDwon(self): + self.temp_dir.cleanup() + + def init_data(self): + self.pd_api = paddle.sum + self.np_api = np.sum + self.x = paddle.randn([10, 5, 9, 9], dtype='float64') + self.np_axis = np.array((1, 2), dtype='int64') + self.tensor_axis = paddle.to_tensor(self.np_axis, dtype='int64') + + def test_dygraph(self): + self.x.stop_gradient = False + pd_out = self.pd_api(self.x, self.tensor_axis) + np_out = self.np_api(self.x.numpy(), tuple(self.np_axis)) + np.testing.assert_allclose( + pd_out.numpy() if pd_out.size > 1 else pd_out.item(), np_out) + pd_out.backward() + self.assertEqual(self.x.gradient().shape, tuple(self.x.shape)) + + def test_dygraph_keepdim(self): + pd_out = self.pd_api(self.x, self.tensor_axis, keepdim=True) + np_out = self.np_api(self.x.numpy(), tuple(self.np_axis), keepdims=True) + np.testing.assert_allclose( + pd_out.numpy() if pd_out.size > 1 else pd_out.item(), np_out) + + def test_static_and_infer(self): + paddle.enable_static() + main_prog = paddle.static.Program() + starup_prog = paddle.static.Program() + with paddle.static.program_guard(main_prog, starup_prog): + # run static + x = paddle.static.data(shape=self.x.shape, + name='x', + dtype='float32') + if isinstance(self.tensor_axis, paddle.Tensor): + axis = paddle.assign(self.np_axis) + else: + axis = [] + for i, item in enumerate(self.tensor_axis): + if isinstance(item, int): + axis.append(item) + else: + axis.append(paddle.full([1], self.np_axis[i], 'int64')) + + conv = paddle.nn.Conv2D(x.shape[1], 5, 3) + conv_out = conv(x) + out = self.pd_api(conv_out, axis) + exe = paddle.static.Executor(self.place) + exe.run(starup_prog) + static_out = exe.run(feed={'x': self.x.numpy().astype('float32')}, + fetch_list=[out]) + + # run infer + paddle.static.save_inference_model(self.save_path, [x], [out], exe) + config = paddle_infer.Config(self.save_path + '.pdmodel', + self.save_path + '.pdiparams') + predictor = paddle_infer.create_predictor(config) + input_names = predictor.get_input_names() + input_handle = predictor.get_input_handle(input_names[0]) + fake_input = self.x.numpy().astype('float32') + input_handle.reshape(self.x.shape) + input_handle.copy_from_cpu(fake_input) + predictor.run() + output_names = predictor.get_output_names() + output_handle = predictor.get_output_handle(output_names[0]) + infer_out = output_handle.copy_to_cpu() + + np.testing.assert_allclose(static_out[0], infer_out) + # paddle.disable_static() + + +class TestSumWithTensorAxis1(TestReduceOPTensorAxisBase): + + def init_data(self): + self.pd_api = paddle.sum + self.np_api = np.sum + self.x = paddle.randn([10, 5, 9, 9], dtype='float64') + self.np_axis = np.array([0, 1, 2], dtype='int64') + self.tensor_axis = [ + 0, + paddle.to_tensor([1], 'int64'), + paddle.to_tensor([2], 'int64') + ] + + if __name__ == "__main__": enable_static() unittest.main() diff --git a/python/paddle/tensor/math.py b/python/paddle/tensor/math.py index 5c870ac7071d7..e404555504e7c 100644 --- a/python/paddle/tensor/math.py +++ b/python/paddle/tensor/math.py @@ -1160,11 +1160,22 @@ def sum(x, axis=None, dtype=None, keepdim=False, name=None): out8 = paddle.sum(x, axis=0) # [1, 1, 1, 1] out9 = paddle.sum(x, axis=1) # [4, 0] """ - if axis is not None and not isinstance(axis, (list, tuple)): - axis = [axis] + if isinstance(axis, Variable): + reduce_all_flag = True if axis.shape[0] == len(x.shape) else False + else: + if axis is not None and not isinstance(axis, (list, tuple)): + axis = [axis] - if not axis: - axis = [] + if not axis: + axis = [] + + if len(axis) == 0: + reduce_all_flag = True + else: + if len(axis) == len(x.shape): + reduce_all_flag = True + else: + reduce_all_flag = False dtype_flag = False if dtype is not None: @@ -1174,16 +1185,12 @@ def sum(x, axis=None, dtype=None, keepdim=False, name=None): if in_dygraph_mode(): return _C_ops.final_state_sum(x, axis, dtype, keepdim) - if len(axis) == 0: - reduce_all_flag = True - else: - if len(axis) == len(x.shape): - reduce_all_flag = True - else: - reduce_all_flag = False + if not isinstance(axis, Variable): + axis = axis if axis != None and axis != [] and axis != () else [0] + if utils._contain_var(axis): + axis = utils._convert_to_tensor_list(axis) if _in_legacy_dygraph(): - axis = axis if axis != None and axis != [] else [0] if dtype_flag: return _C_ops.reduce_sum(x, 'dim', axis, 'keep_dim', keepdim, 'reduce_all', reduce_all_flag, 'in_dtype', @@ -1193,7 +1200,7 @@ def sum(x, axis=None, dtype=None, keepdim=False, name=None): 'reduce_all', reduce_all_flag) attrs = { - 'dim': axis if axis != None and axis != [] and axis != () else [0], + 'dim': axis, 'keep_dim': keepdim, 'reduce_all': reduce_all_flag } @@ -1210,7 +1217,7 @@ def sum(x, axis=None, dtype=None, keepdim=False, name=None): u'bool', u'float16', u'float32', u'float64', u'int32', u'int64', u'complex64', u'complex128'], 'sum') - check_type(axis, 'axis', (int, list, tuple, type(None)), 'sum') + check_type(axis, 'axis', (int, list, tuple, type(None), Variable), 'sum') helper = LayerHelper('sum', **locals()) if dtype_flag: diff --git a/python/paddle/tensor/stat.py b/python/paddle/tensor/stat.py index a211494b09961..9e69b4bc4b8a8 100644 --- a/python/paddle/tensor/stat.py +++ b/python/paddle/tensor/stat.py @@ -82,7 +82,7 @@ def mean(x, axis=None, keepdim=False, name=None): """ if isinstance(axis, Variable): - reduce_all = False + reduce_all = True if axis.shape[0] == len(x.shape) else False else: if isinstance(axis, int): axis = [axis] From 1010dccc8ab49f0fa6d872b121dfce7d8bd4989f Mon Sep 17 00:00:00 2001 From: 0x45f Date: Mon, 22 Aug 2022 11:24:04 +0000 Subject: [PATCH 18/22] Fix SumRawKernel --- paddle/phi/kernels/cpu/identity_loss_kernel.cc | 2 +- paddle/phi/kernels/kps/reduce_sum_kernel.cu | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/phi/kernels/cpu/identity_loss_kernel.cc b/paddle/phi/kernels/cpu/identity_loss_kernel.cc index 941174eb5b0bd..5edf6d9e16024 100644 --- a/paddle/phi/kernels/cpu/identity_loss_kernel.cc +++ b/paddle/phi/kernels/cpu/identity_loss_kernel.cc @@ -31,7 +31,7 @@ void IdentityLossKernel(const Context& dev_ctx, case 0: // sum phi::SumRawKernel( - dev_ctx, x, std::vector{0}, false, true, out->dtype(), out); + dev_ctx, x, phi::IntArray({0}), false, true, out->dtype(), out); break; case 1: // mean diff --git a/paddle/phi/kernels/kps/reduce_sum_kernel.cu b/paddle/phi/kernels/kps/reduce_sum_kernel.cu index fde63963ef3aa..f3d3246854f33 100644 --- a/paddle/phi/kernels/kps/reduce_sum_kernel.cu +++ b/paddle/phi/kernels/kps/reduce_sum_kernel.cu @@ -30,7 +30,7 @@ void SumRawKernel(const Context& dev_ctx, out_dtype = out->dtype(); } phi::Reduce( - dev_ctx, x, reduce_all, dims, keep_dim, out_dtype, out); + dev_ctx, x, reduce_all, dims.GetData(), keep_dim, out_dtype, out); } } // namespace phi From 8c843e65626ba3b13f725b89df5f5190229995db Mon Sep 17 00:00:00 2001 From: 0x45f Date: Mon, 22 Aug 2022 12:21:14 +0000 Subject: [PATCH 19/22] Adapt reduce_prod and add UT --- .../operators/reduce_ops/reduce_prod_op.cc | 7 ++-- paddle/phi/api/yaml/legacy_api.yaml | 4 +-- paddle/phi/api/yaml/legacy_backward.yaml | 4 +-- paddle/phi/kernels/cpu/reduce_prod_kernel.cc | 4 +-- .../impl/reduce_prod_grad_kernel_impl.h | 5 +-- paddle/phi/kernels/kps/reduce_prod_kernel.cu | 6 ++-- paddle/phi/kernels/reduce_prod_grad_kernel.h | 3 +- paddle/phi/kernels/reduce_prod_kernel.cc | 2 +- paddle/phi/kernels/reduce_prod_kernel.h | 5 +-- .../fluid/tests/unittests/test_prod_op.py | 25 ++++++++++++++ python/paddle/tensor/math.py | 33 +++++++++++-------- python/paddle/tensor/stat.py | 2 +- 12 files changed, 67 insertions(+), 33 deletions(-) diff --git a/paddle/fluid/operators/reduce_ops/reduce_prod_op.cc b/paddle/fluid/operators/reduce_ops/reduce_prod_op.cc index 578954663c7f5..0b78e80746412 100644 --- a/paddle/fluid/operators/reduce_ops/reduce_prod_op.cc +++ b/paddle/fluid/operators/reduce_ops/reduce_prod_op.cc @@ -35,9 +35,10 @@ class ReduceProdOpMaker : public ops::ReduceOpMaker { virtual std::string GetOpType() const { return "Reduce reduce_prod"; } }; -DECLARE_INFER_SHAPE_FUNCTOR(reduce_prod, - ReduceProdInferShapeFunctor, - PD_INFER_META(phi::ReduceInferMetaBase)); +DECLARE_INFER_SHAPE_FUNCTOR( + reduce_prod, + ReduceProdInferShapeFunctor, + PD_INFER_META(phi::ReduceIntArrayAxisInferMetaBase)); REGISTER_OPERATOR( reduce_prod, diff --git a/paddle/phi/api/yaml/legacy_api.yaml b/paddle/phi/api/yaml/legacy_api.yaml index d0c4e7a2e46ac..07841bacc52c0 100755 --- a/paddle/phi/api/yaml/legacy_api.yaml +++ b/paddle/phi/api/yaml/legacy_api.yaml @@ -2102,10 +2102,10 @@ # reduce_prod - api : reduce_prod - args : (Tensor x, int64_t[] dims, bool keep_dim, bool reduce_all) + args : (Tensor x, IntArray dims, bool keep_dim, bool reduce_all) output : Tensor infer_meta : - func : ReduceInferMetaBase + func : ReduceIntArrayAxisInferMetaBase kernel : func : prod_raw backward : reduce_prod_grad diff --git a/paddle/phi/api/yaml/legacy_backward.yaml b/paddle/phi/api/yaml/legacy_backward.yaml index 3c63e98f40596..ac9e979b32878 100755 --- a/paddle/phi/api/yaml/legacy_backward.yaml +++ b/paddle/phi/api/yaml/legacy_backward.yaml @@ -1849,8 +1849,8 @@ inplace : (out_grad -> x_grad) - backward_api : reduce_prod_grad - forward : reduce_prod (Tensor x, int64_t[] dims, bool keep_dim, bool reduce_all) -> Tensor(out) - args : (Tensor x, Tensor out, Tensor out_grad, int64_t[] dims, bool keep_dim, bool reduce_all) + forward : reduce_prod (Tensor x, IntArray dims, bool keep_dim, bool reduce_all) -> Tensor(out) + args : (Tensor x, Tensor out, Tensor out_grad, IntArray dims, bool keep_dim, bool reduce_all) output : Tensor(x_grad) infer_meta : func : UnchangedInferMeta diff --git a/paddle/phi/kernels/cpu/reduce_prod_kernel.cc b/paddle/phi/kernels/cpu/reduce_prod_kernel.cc index d31a6e5626289..36766d27ed434 100644 --- a/paddle/phi/kernels/cpu/reduce_prod_kernel.cc +++ b/paddle/phi/kernels/cpu/reduce_prod_kernel.cc @@ -24,13 +24,13 @@ namespace phi { template void ProdRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out) { auto out_dtype = x.dtype(); phi::Reduce( - dev_ctx, x, reduce_all, dims, keep_dim, out_dtype, out); + dev_ctx, x, reduce_all, dims.GetData(), keep_dim, out_dtype, out); } } // namespace phi diff --git a/paddle/phi/kernels/impl/reduce_prod_grad_kernel_impl.h b/paddle/phi/kernels/impl/reduce_prod_grad_kernel_impl.h index 69775281a259c..a6f92543cc9c6 100644 --- a/paddle/phi/kernels/impl/reduce_prod_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/reduce_prod_grad_kernel_impl.h @@ -14,6 +14,7 @@ #pragma once +#include "paddle/phi/common/int_array.h" #include "paddle/phi/kernels/funcs/reduce_functor.h" #include "paddle/phi/kernels/impl/reduce_grad.h" #include "paddle/phi/kernels/reduce_prod_grad_kernel.h" @@ -25,12 +26,12 @@ void ReduceProdGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad) { ReduceGradKernel( - dev_ctx, x, out, out_grad, dims, keep_dim, reduce_all, x_grad); + dev_ctx, x, out, out_grad, dims.GetData(), keep_dim, reduce_all, x_grad); } } // namespace phi diff --git a/paddle/phi/kernels/kps/reduce_prod_kernel.cu b/paddle/phi/kernels/kps/reduce_prod_kernel.cu index 13d8e29b60b12..f5b52937e36fe 100644 --- a/paddle/phi/kernels/kps/reduce_prod_kernel.cu +++ b/paddle/phi/kernels/kps/reduce_prod_kernel.cu @@ -12,22 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "paddle/phi/kernels/reduce_prod_kernel.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/kernels/gpu/reduce.h" -#include "paddle/phi/kernels/reduce_prod_kernel.h" namespace phi { template void ProdRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out) { auto out_dtype = x.dtype(); phi::Reduce( - dev_ctx, x, reduce_all, dims, keep_dim, out_dtype, out); + dev_ctx, x, reduce_all, dims.GetData(), keep_dim, out_dtype, out); } } // namespace phi diff --git a/paddle/phi/kernels/reduce_prod_grad_kernel.h b/paddle/phi/kernels/reduce_prod_grad_kernel.h index fbf9f19a1bb82..fb773f167f90b 100644 --- a/paddle/phi/kernels/reduce_prod_grad_kernel.h +++ b/paddle/phi/kernels/reduce_prod_grad_kernel.h @@ -15,6 +15,7 @@ #pragma once #include "paddle/phi/common/data_type.h" +#include "paddle/phi/common/int_array.h" #include "paddle/phi/core/dense_tensor.h" namespace phi { @@ -23,7 +24,7 @@ void ReduceProdGradKernel(const Context& dev_ctx, const DenseTensor& x, const DenseTensor& out, const DenseTensor& out_grad, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* x_grad); diff --git a/paddle/phi/kernels/reduce_prod_kernel.cc b/paddle/phi/kernels/reduce_prod_kernel.cc index 3bb1c7552b11f..37f1f7bb8172e 100644 --- a/paddle/phi/kernels/reduce_prod_kernel.cc +++ b/paddle/phi/kernels/reduce_prod_kernel.cc @@ -22,7 +22,7 @@ namespace phi { template void ProdKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, DenseTensor* out) { bool reduce_all = false; diff --git a/paddle/phi/kernels/reduce_prod_kernel.h b/paddle/phi/kernels/reduce_prod_kernel.h index be46a554b57e1..91de087ccbc73 100644 --- a/paddle/phi/kernels/reduce_prod_kernel.h +++ b/paddle/phi/kernels/reduce_prod_kernel.h @@ -14,13 +14,14 @@ #pragma once +#include "paddle/phi/common/int_array.h" #include "paddle/phi/core/dense_tensor.h" namespace phi { template void ProdRawKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, bool reduce_all, DenseTensor* out); @@ -28,7 +29,7 @@ void ProdRawKernel(const Context& dev_ctx, template void ProdKernel(const Context& dev_ctx, const DenseTensor& x, - const std::vector& dims, + const IntArray& dims, bool keep_dim, DenseTensor* out); diff --git a/python/paddle/fluid/tests/unittests/test_prod_op.py b/python/paddle/fluid/tests/unittests/test_prod_op.py index 19611a933cc29..dde612ea746c5 100644 --- a/python/paddle/fluid/tests/unittests/test_prod_op.py +++ b/python/paddle/fluid/tests/unittests/test_prod_op.py @@ -17,6 +17,7 @@ import paddle import unittest import numpy as np +from test_sum_op import TestReduceOPTensorAxisBase class TestProdOp(unittest.TestCase): @@ -168,5 +169,29 @@ def test_error(self): self.assertRaises(TypeError, paddle.prod, x, 'bool') +class TestProdWithTensorAxis1(TestReduceOPTensorAxisBase): + + def init_data(self): + self.pd_api = paddle.prod + self.np_api = np.prod + self.x = paddle.randn([10, 5, 9, 9], dtype='float64') + self.np_axis = np.array([1, 2], dtype='int64') + self.tensor_axis = paddle.to_tensor([1, 2], dtype='int64') + + +class TestProdWithTensorAxis2(TestReduceOPTensorAxisBase): + + def init_data(self): + self.pd_api = paddle.prod + self.np_api = np.prod + self.x = paddle.randn([10, 10, 9, 9], dtype='float64') + self.np_axis = np.array([0, 1, 2], dtype='int64') + self.tensor_axis = [ + 0, + paddle.to_tensor([1], 'int64'), + paddle.to_tensor([2], 'int64') + ] + + if __name__ == "__main__": unittest.main() diff --git a/python/paddle/tensor/math.py b/python/paddle/tensor/math.py index e404555504e7c..cc05155894077 100644 --- a/python/paddle/tensor/math.py +++ b/python/paddle/tensor/math.py @@ -2192,7 +2192,7 @@ def max(x, axis=None, keepdim=False, name=None): helper = LayerHelper('max', **locals()) check_variable_and_dtype( x, 'x', ['float32', 'float64', 'int32', 'int64'], 'max') - if utils._contain_var(axis): + if not isinstance(axis, Variable) and utils._contain_var(axis): axis = utils._convert_to_tensor_list(axis) out = helper.create_variable_for_type_inference( @@ -2296,7 +2296,7 @@ def min(x, axis=None, keepdim=False, name=None): helper = LayerHelper('min', **locals()) check_variable_and_dtype( x, 'x', ['float32', 'float64', 'int32', 'int64'], 'min') - if utils._contain_var(axis): + if not isinstance(axis, Variable) and utils._contain_var(axis): axis = utils._convert_to_tensor_list(axis) out = helper.create_variable_for_type_inference( @@ -3403,19 +3403,22 @@ def prod(x, axis=None, keepdim=False, dtype=None, name=None): x = cast(x, dtype) dim = axis - if dim is not None and not isinstance(dim, list): - if isinstance(dim, tuple): - dim = list(dim) - elif isinstance(dim, int): - dim = [dim] - else: - raise TypeError( - "The type of axis must be int, list or tuple, but received {}". - format(type(dim))) + if isinstance(dim, Variable): + reduce_all = True if axis.shape[0] == len(x.shape) else False + else: + if dim is not None and not isinstance(dim, list): + if isinstance(dim, tuple): + dim = list(dim) + elif isinstance(dim, int): + dim = [dim] + else: + raise TypeError( + "The type of axis must be int, list or tuple, but received {}". + format(type(dim))) - reduce_all = True if dim is None or len(dim) == 0 or len(dim) == len(x.shape) else False - if dim is None or len(dim) == 0: - dim = [0] + reduce_all = True if dim is None or len(dim) == 0 or len(dim) == len(x.shape) else False + if dim is None or len(dim) == 0: + dim = [0] if in_dygraph_mode(): return _C_ops.final_state_reduce_prod(x, dim, keepdim, reduce_all) @@ -3427,6 +3430,8 @@ def prod(x, axis=None, keepdim=False, dtype=None, name=None): check_variable_and_dtype( x, 'x/input', ['float32', 'float64', 'int32', 'int64'], 'reduce_prod') out = helper.create_variable_for_type_inference(dtype=helper.input_dtype()) + if not isinstance(dim, Variable) and utils._contain_var(dim): + dim = utils._convert_to_tensor_list(dim) helper.append_op( type='reduce_prod', inputs={'X': x}, diff --git a/python/paddle/tensor/stat.py b/python/paddle/tensor/stat.py index 9e69b4bc4b8a8..1f2a2627423d3 100644 --- a/python/paddle/tensor/stat.py +++ b/python/paddle/tensor/stat.py @@ -112,7 +112,7 @@ def mean(x, axis=None, keepdim=False, name=None): helper = LayerHelper('mean', **locals()) - if utils._contain_var(axis): + if not isinstance(axis, Variable) and utils._contain_var(axis): axis = utils._convert_to_tensor_list(axis) attrs = {'dim': axis, 'keep_dim': keepdim, 'reduce_all': reduce_all} out = helper.create_variable_for_type_inference(x.dtype) From c9fc9e89c8d3e49a67199c97ff1c6bec1a923c4a Mon Sep 17 00:00:00 2001 From: 0x45f Date: Tue, 23 Aug 2022 05:59:11 +0000 Subject: [PATCH 20/22] Set infer place --- python/paddle/fluid/tests/unittests/test_sum_op.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_sum_op.py b/python/paddle/fluid/tests/unittests/test_sum_op.py index ef6fc3df05217..6d50e6aaa0622 100644 --- a/python/paddle/fluid/tests/unittests/test_sum_op.py +++ b/python/paddle/fluid/tests/unittests/test_sum_op.py @@ -493,8 +493,7 @@ def setUp(self): paddle.disable_static() paddle.seed(2022) self.temp_dir = tempfile.TemporaryDirectory() - self.save_path = os.path.join(self.temp_dir.name, - 'sum_with_tensor_axis') + self.save_path = os.path.join(self.temp_dir.name, 'reduce_tensor_axis') self.place = paddle.CUDAPlace( 0) if paddle.is_compiled_with_cuda() else paddle.CPUPlace() self.init_data() @@ -543,7 +542,7 @@ def test_static_and_infer(self): else: axis.append(paddle.full([1], self.np_axis[i], 'int64')) - conv = paddle.nn.Conv2D(x.shape[1], 5, 3) + conv = paddle.nn.Linear(x.shape[-1], 5) conv_out = conv(x) out = self.pd_api(conv_out, axis) exe = paddle.static.Executor(self.place) @@ -555,6 +554,10 @@ def test_static_and_infer(self): paddle.static.save_inference_model(self.save_path, [x], [out], exe) config = paddle_infer.Config(self.save_path + '.pdmodel', self.save_path + '.pdiparams') + if paddle.is_compiled_with_cuda(): + config.enable_use_gpu(100, 0) + else: + config.disable_gpu() predictor = paddle_infer.create_predictor(config) input_names = predictor.get_input_names() input_handle = predictor.get_input_handle(input_names[0]) @@ -565,9 +568,7 @@ def test_static_and_infer(self): output_names = predictor.get_output_names() output_handle = predictor.get_output_handle(output_names[0]) infer_out = output_handle.copy_to_cpu() - np.testing.assert_allclose(static_out[0], infer_out) - # paddle.disable_static() class TestSumWithTensorAxis1(TestReduceOPTensorAxisBase): From 4f8448b8b3a9f299497a2336db1256a487cbac6d Mon Sep 17 00:00:00 2001 From: 0x45f Date: Tue, 23 Aug 2022 08:17:01 +0000 Subject: [PATCH 21/22] Polish UT --- python/paddle/fluid/tests/unittests/test_sum_op.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_sum_op.py b/python/paddle/fluid/tests/unittests/test_sum_op.py index 6d50e6aaa0622..4107181556781 100644 --- a/python/paddle/fluid/tests/unittests/test_sum_op.py +++ b/python/paddle/fluid/tests/unittests/test_sum_op.py @@ -542,9 +542,9 @@ def test_static_and_infer(self): else: axis.append(paddle.full([1], self.np_axis[i], 'int64')) - conv = paddle.nn.Linear(x.shape[-1], 5) - conv_out = conv(x) - out = self.pd_api(conv_out, axis) + linear = paddle.nn.Linear(x.shape[-1], 5) + linear_out = linear(x) + out = self.pd_api(linear_out, axis) exe = paddle.static.Executor(self.place) exe.run(starup_prog) static_out = exe.run(feed={'x': self.x.numpy().astype('float32')}, From 7d8aee6018c0f8afe9f93b03cd0cfba53f1f684b Mon Sep 17 00:00:00 2001 From: 0x45f Date: Fri, 26 Aug 2022 03:03:56 +0000 Subject: [PATCH 22/22] Refine infershape and add UT --- paddle/phi/infermeta/unary.cc | 75 ++++++++----------- .../fluid/tests/unittests/test_min_op.py | 1 + .../fluid/tests/unittests/test_sum_op.py | 9 +-- 3 files changed, 34 insertions(+), 51 deletions(-) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index 5fa9939ebd11f..532166e29c1d5 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -2641,6 +2641,33 @@ DDim ReduceInferDim(const MetaTensor& x, return out_dim; } +DDim ReduceInferDimForIntArrayAxis(const MetaTensor& x, + const IntArray& axis, + bool keep_dim, + bool reduce_all) { + std::vector vec_axis = axis.GetData(); + std::vector vec_dim; + if (reduce_all) { + if (keep_dim) { + vec_dim = std::vector(x.dims().size(), 1); + } else { + vec_dim = {1}; + } + } else { + if (keep_dim) { + vec_dim = std::vector(x.dims().size(), -1); + } else { + auto x_rank = static_cast(x.dims().size()); + if (vec_axis.size() >= x_rank) { + vec_dim = {-1}; + } else { + vec_dim = std::vector(x.dims().size() - vec_axis.size(), -1); + } + } + } + return phi::make_ddim(vec_dim); +} + void ReduceInferMeta(const MetaTensor& x, const std::vector& axis, bool keep_dim, @@ -2669,30 +2696,10 @@ void ReduceIntArrayAxisInferMetaBase(const MetaTensor& x, bool reduce_all, MetaTensor* out, MetaConfig config) { - std::vector vec_axis = axis.GetData(); if (config.is_runtime || !axis.FromTensor()) { - ReduceInferMetaBase(x, vec_axis, keep_dim, reduce_all, out); + ReduceInferMetaBase(x, axis.GetData(), keep_dim, reduce_all, out); } else { - std::vector vec_dim; - if (reduce_all) { - if (keep_dim) { - vec_dim = std::vector(x.dims().size(), 1); - } else { - vec_dim = {1}; - } - } else { - if (keep_dim) { - vec_dim = std::vector(x.dims().size(), -1); - } else { - auto x_rank = static_cast(x.dims().size()); - if (vec_axis.size() >= x_rank) { - vec_dim = {-1}; - } else { - vec_dim = std::vector(x.dims().size() - vec_axis.size(), -1); - } - } - } - DDim out_dim = phi::make_ddim(vec_dim); + DDim out_dim = ReduceInferDimForIntArrayAxis(x, axis, keep_dim, reduce_all); out->set_dims(out_dim); out->set_dtype(x.dtype()); out->set_layout(x.layout()); @@ -3380,30 +3387,10 @@ void SumRawInferMeta(const MetaTensor& x, MetaTensor* out, MetaConfig config) { DDim out_dim; - std::vector vec_axis = axis.GetData(); if (config.is_runtime || !axis.FromTensor()) { - out_dim = ReduceInferDim(x, vec_axis, keep_dim, reduce_all); + out_dim = ReduceInferDim(x, axis.GetData(), keep_dim, reduce_all); } else { - std::vector vec_dim; - if (reduce_all) { - if (keep_dim) { - vec_dim = std::vector(x.dims().size(), 1); - } else { - vec_dim = {1}; - } - } else { - if (keep_dim) { - vec_dim = std::vector(x.dims().size(), -1); - } else { - auto x_rank = static_cast(x.dims().size()); - if (vec_axis.size() >= x_rank) { - vec_dim = {-1}; - } else { - vec_dim = std::vector(x.dims().size() - vec_axis.size(), -1); - } - } - } - out_dim = phi::make_ddim(vec_dim); + out_dim = ReduceInferDimForIntArrayAxis(x, axis, keep_dim, reduce_all); } DataType out_dtype; diff --git a/python/paddle/fluid/tests/unittests/test_min_op.py b/python/paddle/fluid/tests/unittests/test_min_op.py index 1e01f45f72456..2daa813997154 100644 --- a/python/paddle/fluid/tests/unittests/test_min_op.py +++ b/python/paddle/fluid/tests/unittests/test_min_op.py @@ -120,6 +120,7 @@ def init_data(self): paddle.to_tensor([1], 'int64'), paddle.to_tensor([2], 'int64') ] + self.keepdim = True if __name__ == '__main__': diff --git a/python/paddle/fluid/tests/unittests/test_sum_op.py b/python/paddle/fluid/tests/unittests/test_sum_op.py index 4107181556781..a2b17c0dc73bf 100644 --- a/python/paddle/fluid/tests/unittests/test_sum_op.py +++ b/python/paddle/fluid/tests/unittests/test_sum_op.py @@ -496,6 +496,7 @@ def setUp(self): self.save_path = os.path.join(self.temp_dir.name, 'reduce_tensor_axis') self.place = paddle.CUDAPlace( 0) if paddle.is_compiled_with_cuda() else paddle.CPUPlace() + self.keepdim = False self.init_data() def tearDwon(self): @@ -517,12 +518,6 @@ def test_dygraph(self): pd_out.backward() self.assertEqual(self.x.gradient().shape, tuple(self.x.shape)) - def test_dygraph_keepdim(self): - pd_out = self.pd_api(self.x, self.tensor_axis, keepdim=True) - np_out = self.np_api(self.x.numpy(), tuple(self.np_axis), keepdims=True) - np.testing.assert_allclose( - pd_out.numpy() if pd_out.size > 1 else pd_out.item(), np_out) - def test_static_and_infer(self): paddle.enable_static() main_prog = paddle.static.Program() @@ -544,7 +539,7 @@ def test_static_and_infer(self): linear = paddle.nn.Linear(x.shape[-1], 5) linear_out = linear(x) - out = self.pd_api(linear_out, axis) + out = self.pd_api(linear_out, axis, keepdim=self.keepdim) exe = paddle.static.Executor(self.place) exe.run(starup_prog) static_out = exe.run(feed={'x': self.x.numpy().astype('float32')},