From 541bdcc1245bd27f6074364a6a654754d0e35637 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Wed, 15 Feb 2023 09:22:38 +0000 Subject: [PATCH 01/24] Add unitest from shilong --- paddle/phi/infermeta/unary.cc | 41 +-- .../tests/unittests/test_zero_dim_tensor.py | 237 +++++++++++++++++- .../unittests/xpu/test_zero_dim_tensor_xpu.py | 75 +++++- python/paddle/tensor/manipulation.py | 20 +- 4 files changed, 346 insertions(+), 27 deletions(-) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index e1aebcfbcece0..145874b52f460 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -472,6 +472,7 @@ void CumInferMeta(const MetaTensor& x, out->set_dims(x_dims); out->set_dtype(x.dtype()); } + out->share_lod(x); } @@ -970,7 +971,7 @@ void ExpandInferMeta(const MetaTensor& x, MAX_RANK_SUPPORTED)); PADDLE_ENFORCE_GE( expand_shape.size(), - 1, + 0, phi::errors::InvalidArgument("The number of elements (%d) of 'shape' for " "must be a positive integer.", expand_shape.size())); @@ -1005,7 +1006,7 @@ void ExpandInferMeta(const MetaTensor& x, out->set_dims(make_ddim(out_shape)); out->set_dtype(x.dtype()); - if (out_shape[0] == x_dims[0]) { + if (out_rank > 0 && out_shape[0] == x_dims[0]) { out->share_lod(x); } } @@ -4100,14 +4101,23 @@ void TopKInferMeta(const MetaTensor& x, MetaConfig config) { auto input_dims = x.dims(); const int& dim_size = input_dims.size(); - PADDLE_ENFORCE_EQ( - (axis < dim_size) && (axis >= (-1 * dim_size)), - true, - phi::errors::InvalidArgument( - "the axis of topk must be [-%d, %d), but you set axis is %d", - dim_size, - dim_size, - axis)); + if (dim_size != 0) { + PADDLE_ENFORCE_EQ( + (axis < dim_size) && (axis >= (-1 * dim_size)), + true, + phi::errors::InvalidArgument( + "the axis of topk must be [-%d, %d), but you set axis is %d", + dim_size, + dim_size, + axis)); + } else { + PADDLE_ENFORCE_EQ( + (axis == dim_size) || (axis == -1), + true, + phi::errors::InvalidArgument("the axis of topk must be 0 or -1 when " + "x.dims() = 0, but you set axis is %d", + axis)); + } if (axis < 0) axis += dim_size; @@ -4125,12 +4135,13 @@ void TopKInferMeta(const MetaTensor& x, PADDLE_ENFORCE_GE( input_dims.size(), - 1, - phi::errors::InvalidArgument("input of topk must have >= 1d shape")); + 0, + phi::errors::InvalidArgument("input of topk must have >= 0d shape")); phi::DDim dims = input_dims; - - dims[axis] = k; + if (input_dims.size() > 0) { + dims[axis] = k; + } out->set_dims(dims); out->share_lod(x); out->set_dtype(x.dtype()); @@ -4885,4 +4896,4 @@ void ChannelShuffleInferMeta(const MetaTensor& x, } // namespace phi -PD_REGISTER_INFER_META_FN(flatten, phi::FlattenInferMeta); +PD_REGISTER_INFER_META_FN(flatten, phi::FlattenInferMeta); \ No newline at end of file diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 64881c08fb637..65e037bf7f269 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -571,6 +571,104 @@ def setUp(self): paddle.disable_static() self.x = paddle.rand([]) + def test_expand(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + out = paddle.expand(x, shape=[1]) + out.backward() + self.assertEqual(x.shape, []) + self.assertEqual(x.item(), 1.0) + self.assertEqual(x.grad.shape, [1]) + self.assertEqual(x.grad.item(0), 1.0) + self.assertEqual(out.shape, [1]) + self.assertEqual(out.item(0), 1.0) + self.assertEqual(out.grad, None) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + out1 = paddle.expand(x1, shape=[]) + out1.backward() + self.assertEqual(x1.shape, []) + self.assertEqual(x1.item(), 1.0) + self.assertEqual(x1.grad.shape, []) + self.assertEqual(x1.grad.item(), 1.0) + self.assertEqual(out1.shape, []) + self.assertEqual(out1.item(), 1.0) + self.assertEqual(out1.grad, None) + + def test_expand_as(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + y = paddle.full([], 1, 'float32') + y.stop_gradient = False + out = paddle.expand_as(x, y) + out.backward() + self.assertEqual(x.shape, []) + self.assertEqual(x.item(), 1.0) + self.assertEqual(x.grad.shape, []) + self.assertEqual(x.grad.item(), 1.0) + self.assertEqual(out.shape, []) + self.assertEqual(out.item(), 1.0) + self.assertEqual(out.grad, None) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + y1 = paddle.full([1], 1, 'float32') + out1 = paddle.expand_as(x1, y1) + out1.backward() + self.assertEqual(x1.shape, []) + self.assertEqual(x1.item(), 1.0) + self.assertEqual(x1.grad.shape, [1]) + self.assertEqual(x1.grad.item(0), 1.0) + self.assertEqual(out1.shape, [1]) + self.assertEqual(out1.item(0), 1.0) + self.assertEqual(out1.grad, None) + + def test_top_k(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + out, indices = paddle.topk(x, k=1, axis=0) + self.assertEqual(x.shape, []) + self.assertEqual(x.item(), 1.0) + self.assertEqual(out.shape, []) + self.assertEqual(out.item(), 1.0) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + out1, indices1 = paddle.topk(x1, k=1, axis=-1) + self.assertEqual(x1.shape, []) + self.assertEqual(x1.item(), 1.0) + self.assertEqual(out1.shape, []) + self.assertEqual(out1.item(), 1.0) + + with self.assertRaises(ValueError): + tmp = paddle.topk(x1, k=1, axis=2) + + def test_broadcast_to(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + out = paddle.broadcast_to(x, shape=[1]) + out.backward() + self.assertEqual(x.shape, []) + self.assertEqual(x.item(), 1.0) + self.assertEqual(x.grad.shape, [1]) + self.assertEqual(x.grad.item(0), 1.0) + self.assertEqual(out.shape, [1]) + self.assertEqual(out.item(0), 1.0) + self.assertEqual(out.grad, None) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + out1 = paddle.broadcast_to(x1, shape=[]) + out1.backward() + self.assertEqual(x1.shape, []) + self.assertEqual(x1.item(), 1.0) + self.assertEqual(x1.grad.shape, []) + self.assertEqual(x1.grad.item(), 1.0) + self.assertEqual(out1.shape, []) + self.assertEqual(out1.item(), 1.0) + self.assertEqual(out1.grad, None) + def test_argmin(self): x = paddle.rand([]) out1 = paddle.argmin(x, 0) @@ -1680,6 +1778,143 @@ def setUp(self): self.exe = paddle.static.Executor() @prog_scope() + def test_expand(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + out = paddle.expand(x, shape=[1]) + paddle.static.append_backward(out.sum()) + + prog = paddle.static.default_main_program() + res = self.exe.run( + prog, fetch_list=[x, out, x.grad_name, out.grad_name] + ) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[0], 1.0) + self.assertEqual(res[1].shape, (1,)) + self.assertEqual(res[1], 1.0) + self.assertEqual(res[2].shape, (1,)) + self.assertEqual(res[2], 1.0) + self.assertEqual(res[3].shape, (1,)) + self.assertEqual(res[3], 1.0) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + out1 = paddle.expand(x1, shape=[]) + paddle.static.append_backward(out1.sum()) + prog = paddle.static.default_main_program() + res = self.exe.run( + prog, fetch_list=[x1, out1, x1.grad_name, out1.grad_name] + ) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[0], 1.0) + self.assertEqual(res[1].shape, ()) + self.assertEqual(res[1], 1.0) + self.assertEqual(res[2].shape, ()) + self.assertEqual(res[2], 1.0) + self.assertEqual(res[3].shape, ()) + self.assertEqual(res[3], 1.0) + + @prog_scope() + def test_expand_as(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + y = paddle.full([], 1, 'float32') + y.stop_gradient = False + out = paddle.expand_as(x, y) + paddle.static.append_backward(out.sum()) + + prog = paddle.static.default_main_program() + res = self.exe.run( + prog, fetch_list=[x, out, x.grad_name, out.grad_name] + ) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[0], 1.0) + self.assertEqual(res[1].shape, ()) + self.assertEqual(res[1], 1.0) + self.assertEqual(res[2].shape, ()) + self.assertEqual(res[2], 1.0) + self.assertEqual(res[3].shape, ()) + self.assertEqual(res[3], 1.0) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + y1 = paddle.full([1], 1, 'float32') + y1.stop_gradient = False + out1 = paddle.expand_as(x1, y1) + paddle.static.append_backward(out1.sum()) + + prog = paddle.static.default_main_program() + res = self.exe.run( + prog, fetch_list=[x1, out1, x1.grad_name, out1.grad_name] + ) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[0], 1.0) + self.assertEqual(res[1].shape, (1,)) + self.assertEqual(res[1], 1.0) + self.assertEqual(res[2].shape, (1,)) + self.assertEqual(res[2], 1.0) + self.assertEqual(res[3].shape, (1,)) + self.assertEqual(res[3], 1.0) + + @prog_scope() + def test_top_k(self): + x = paddle.full([], 1, 'float32') + out, indices = paddle.topk(x, k=1, axis=0) + prog = paddle.static.default_main_program() + res = self.exe.run(prog, fetch_list=[x, out]) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[0], 1.0) + self.assertEqual(res[1].shape, ()) + self.assertEqual(res[1], 1.0) + + x1 = paddle.full([], 1, 'float32') + out1, indices1 = paddle.topk(x1, k=1, axis=-1) + prog = paddle.static.default_main_program() + res = self.exe.run(prog, fetch_list=[x1, out1]) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[0], 1.0) + self.assertEqual(res[1].shape, ()) + self.assertEqual(res[1], 1.0) + + with self.assertRaises(ValueError): + tmp = paddle.topk(x1, k=1, axis=2) + + @prog_scope() + def test_broadcast_to(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + out = paddle.broadcast_to(x, shape=[1]) + paddle.static.append_backward(out.sum()) + prog = paddle.static.default_main_program() + res = self.exe.run( + prog, fetch_list=[x, out, x.grad_name, out.grad_name] + ) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[0], 1.0) + self.assertEqual(res[1].shape, (1,)) + self.assertEqual(res[1], 1.0) + self.assertEqual(res[2].shape, (1,)) + self.assertEqual(res[2], 1.0) + self.assertEqual(res[3].shape, (1,)) + self.assertEqual(res[3], 1.0) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + out1 = paddle.broadcast_to(x1, shape=[]) + paddle.static.append_backward(out1.sum()) + prog = paddle.static.default_main_program() + res = self.exe.run( + prog, fetch_list=[x1, out1, x1.grad_name, out1.grad_name] + ) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[0], 1.0) + self.assertEqual(res[1].shape, ()) + self.assertEqual(res[1], 1.0) + self.assertEqual(res[2].shape, ()) + self.assertEqual(res[2], 1.0) + self.assertEqual(res[3].shape, ()) + self.assertEqual(res[3], 1.0) + def test_argmin(self): x = paddle.rand([]) out1 = paddle.argmin(x, 0) @@ -3375,4 +3610,4 @@ def test_static(self): if __name__ == "__main__": - unittest.main() + unittest.main() \ No newline at end of file diff --git a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py index 518b1c1488e17..1e47318bd02d9 100644 --- a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py +++ b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py @@ -328,6 +328,79 @@ def setUp(self): paddle.disable_static() self.x = paddle.rand([]) + def test_expand(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + out = paddle.expand(x, shape=[1]) + out.backward() + self.assertEqual(x.shape, []) + self.assertEqual(x.item(), 1.0) + self.assertEqual(x.grad.shape, [1]) + self.assertEqual(x.grad.item(0), 1.0) + self.assertEqual(out.shape, [1]) + self.assertEqual(out.item(0), 1.0) + # self.assertEqual(out.grad, None) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + out1 = paddle.expand(x1, shape=[]) + out1.backward() + self.assertEqual(x1.shape, []) + self.assertEqual(x1.item(), 1.0) + self.assertEqual(x1.grad.shape, []) + self.assertEqual(x1.grad.item(), 1.0) + self.assertEqual(out1.shape, []) + self.assertEqual(out1.item(), 1.0) + self.assertEqual(out1.grad, None) + + def test_expand_as(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + y = paddle.full([], 1, 'float32') + y.stop_gradient = False + out = paddle.expand_as(x, y) + out.backward() + self.assertEqual(x.shape, []) + self.assertEqual(x.item(), 1.0) + self.assertEqual(x.grad.shape, []) + self.assertEqual(x.grad.item(), 1.0) + self.assertEqual(out.shape, []) + self.assertEqual(out.item(), 1.0) + self.assertEqual(out.grad, None) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + y1 = paddle.full([1], 1, 'float32') + out1 = paddle.expand_as(x1, y1) + out1.backward() + self.assertEqual(x1.shape, []) + self.assertEqual(x1.item(), 1.0) + self.assertEqual(x1.grad.shape, [1]) + self.assertEqual(x1.grad.item(0), 1.0) + self.assertEqual(out1.shape, [1]) + self.assertEqual(out1.item(0), 1.0) + self.assertEqual(out1.grad, None) + + def test_top_k(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + out, indices = paddle.topk(x, k=1, axis=0) + self.assertEqual(x.shape, []) + self.assertEqual(x.item(), 1.0) + self.assertEqual(out.shape, []) + self.assertEqual(out.item(), 1.0) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + out1, indices1 = paddle.topk(x1, k=1, axis=-1) + self.assertEqual(x1.shape, []) + self.assertEqual(x1.item(), 1.0) + self.assertEqual(out1.shape, []) + self.assertEqual(out1.item(), 1.0) + + with self.assertRaises(ValueError): + tmp = paddle.topk(x1, k=1, axis=2) + def test_argmin(self): x = paddle.rand([]) out1 = paddle.argmin(x, 0) @@ -1190,4 +1263,4 @@ def test_where(self): if __name__ == "__main__": - unittest.main() + unittest.main() \ No newline at end of file diff --git a/python/paddle/tensor/manipulation.py b/python/paddle/tensor/manipulation.py index b9feee2fe1dd9..8abffb7a9e9d5 100644 --- a/python/paddle/tensor/manipulation.py +++ b/python/paddle/tensor/manipulation.py @@ -3269,18 +3269,18 @@ def broadcast_to(x, shape, name=None): return _C_ops.expand(x, shape) else: if isinstance(shape, Variable): - assert len(shape.shape) == 1, 'shape must be an 1-D Tensor.' + assert len(shape.shape) <= 1, 'shape must be an 0-D or 1-D Tensor.' else: + type_tuple = (int, np.int32, np.int64) for elem in shape: if isinstance(elem, Variable): assert ( - len(elem.shape) == 1 - ), 'Elements in shape must be 1-D Tensors or integers.' + len(elem.shape) <= 1 + ), 'Elements in shape must be 0-D or 1-D Tensors or integers.' else: - type_tuple = (int, np.int32, np.int64) assert isinstance( elem, type_tuple - ), 'Elements in shape must be 1-D Tensors or integers.' + ), 'Elements in shape must be 0-D or 1-D Tensors or integers.' check_variable_and_dtype( x, @@ -3363,18 +3363,18 @@ def expand(x, shape, name=None): return _C_ops.expand(x, shape) else: if isinstance(shape, Variable): - assert len(shape.shape) == 1, 'shape must be an 1-D Tensor.' + assert len(shape.shape) <= 1, 'shape must be an 0-D or 1-D Tensor.' else: for elem in shape: if isinstance(elem, Variable): assert ( - len(elem.shape) == 1 - ), 'Elements in shape must be 1-D Tensors or integers.' + len(elem.shape) <= 1 + ), 'Elements in shape must be 0-D or 1-D Tensors or integers.' else: type_tuple = (int, np.int32, np.int64) assert isinstance( elem, type_tuple - ), 'Elements in shape must be 1-D Tensors or integers.' + ), 'Elements in shape must be 0-D or 1-D Tensors or integers.' check_variable_and_dtype( x, @@ -4711,4 +4711,4 @@ def index_add_(x, index, axis, value, name=None): } for name, func in __METHODS.items(): setattr(core.VarBase, name, func) - setattr(core.eager.Tensor, name, func) + setattr(core.eager.Tensor, name, func) \ No newline at end of file From 592b3a075e372dacd44cdc1e6d049410c649a3d9 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Wed, 15 Feb 2023 09:28:30 +0000 Subject: [PATCH 02/24] Add kernel code from shilong --- paddle/phi/kernels/cpu/top_k_kernel.cc | 8 ++++++-- paddle/phi/kernels/gpu/top_k_kernel.cu | 7 ++++++- paddle/phi/kernels/impl/expand_as_kernel_impl.h | 11 +++++++++-- paddle/phi/kernels/impl/expand_kernel_impl.h | 12 +++++++++--- paddle/phi/kernels/xpu/expand_as_kernel.cc | 15 +++++++++++++-- paddle/phi/kernels/xpu/expand_kernel.cc | 15 +++++++++++++-- paddle/phi/kernels/xpu/top_k_kernel.cc | 12 ++++++++++-- 7 files changed, 66 insertions(+), 14 deletions(-) diff --git a/paddle/phi/kernels/cpu/top_k_kernel.cc b/paddle/phi/kernels/cpu/top_k_kernel.cc index cebe292d33951..4549b086b5ac4 100644 --- a/paddle/phi/kernels/cpu/top_k_kernel.cc +++ b/paddle/phi/kernels/cpu/top_k_kernel.cc @@ -140,7 +140,11 @@ void TopkKernel(const Context& dev_ctx, const auto* input = &x; // Get the top k elements of each row of input tensor const auto& in_dims = input->dims(); - + // 0d input x + if (in_dims.size() == 0) { + phi::Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); + return; + } // axis < 0, cacluate the real axis if (axis < 0) { axis += in_dims.size(); @@ -235,4 +239,4 @@ void TopkKernel(const Context& dev_ctx, } // namespace phi PD_REGISTER_KERNEL( - topk, CPU, ALL_LAYOUT, phi::TopkKernel, float, double, int32_t, int64_t) {} + topk, CPU, ALL_LAYOUT, phi::TopkKernel, float, double, int32_t, int64_t) {} \ No newline at end of file diff --git a/paddle/phi/kernels/gpu/top_k_kernel.cu b/paddle/phi/kernels/gpu/top_k_kernel.cu index a455d9305d955..71727028bf67c 100644 --- a/paddle/phi/kernels/gpu/top_k_kernel.cu +++ b/paddle/phi/kernels/gpu/top_k_kernel.cu @@ -61,6 +61,11 @@ void TopkKernel(const Context& dev_ctx, const auto* input = &x; // get the input dims const auto& in_dims = input->dims(); + // 0d input tensor + if (in_dims.size() == 0) { + phi::Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); + return; + } // calcluate the real axis if (axis < 0) axis += in_dims.size(); @@ -340,4 +345,4 @@ PD_REGISTER_KERNEL(topk, double, int, int64_t, - phi::dtype::float16) {} + phi::dtype::float16) {} \ No newline at end of file diff --git a/paddle/phi/kernels/impl/expand_as_kernel_impl.h b/paddle/phi/kernels/impl/expand_as_kernel_impl.h index 717fd8ebc8950..c3dbab3d6b754 100755 --- a/paddle/phi/kernels/impl/expand_as_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_as_kernel_impl.h @@ -34,6 +34,10 @@ void ExpandAs(const Context& context, auto diff = target_shape.size() - vec_in_dims.size(); vec_in_dims.insert(vec_in_dims.begin(), diff, 1); std::vector repeat_times(vec_in_dims.size()); + if (Rank == 0) { + phi::Copy(context, x, context.GetPlace(), false, out); + return; + } for (size_t i = 0; i < vec_in_dims.size(); ++i) { PADDLE_ENFORCE_NE( target_shape[i], @@ -108,7 +112,7 @@ void ExpandAsKernel(const Context& ctx, rank)); PADDLE_ENFORCE_GE( rank, - 1, + 0, errors::InvalidArgument("The rank (%d) of the input 'x' for " "expand_as_v2 op must be positive.", rank)); @@ -133,6 +137,9 @@ void ExpandAsKernel(const Context& ctx, } switch (target_rank) { + case 0: + ExpandAs(ctx, x, real_target_shape, out); + break; case 1: ExpandAs(ctx, x, real_target_shape, out); break; @@ -154,4 +161,4 @@ void ExpandAsKernel(const Context& ctx, } } -} // namespace phi +} // namespace phi \ No newline at end of file diff --git a/paddle/phi/kernels/impl/expand_kernel_impl.h b/paddle/phi/kernels/impl/expand_kernel_impl.h index 54fd1100ab332..d9250073ceab7 100644 --- a/paddle/phi/kernels/impl/expand_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_kernel_impl.h @@ -35,6 +35,10 @@ void Expand(const Context& ctx, auto diff = expand_shape.size() - vec_in_dims.size(); vec_in_dims.insert(vec_in_dims.begin(), diff, 1); std::vector repeat_times(vec_in_dims.size()); + if (Rank == 0) { + phi::Copy(ctx, x, ctx.GetPlace(), false, out); + return; + } for (size_t i = 0; i < vec_in_dims.size(); ++i) { PADDLE_ENFORCE_NE( expand_shape[i], @@ -74,7 +78,6 @@ void Expand(const Context& ctx, repeat_times[i] = 1; } } - Eigen::DSizes bcast_dims; for (size_t i = 0; i < repeat_times.size(); ++i) { bcast_dims[i] = repeat_times[i]; @@ -112,7 +115,7 @@ void ExpandKernel(const Context& ctx, auto rank = x.dims().size(); PADDLE_ENFORCE_GE( rank, - 1, + 0, phi::errors::InvalidArgument( "The rank of the input 'X' for expand_v2 op must be positive, " "but the value received is %d.", @@ -145,6 +148,9 @@ void ExpandKernel(const Context& ctx, MAX_RANK_SUPPORTED)); rank = std::max(rank, static_cast(shape_size)); switch (rank) { + case 0: + Expand(ctx, x, shape, out); + break; case 1: Expand(ctx, x, shape, out); break; @@ -166,4 +172,4 @@ void ExpandKernel(const Context& ctx, } } -} // namespace phi +} // namespace phi \ No newline at end of file diff --git a/paddle/phi/kernels/xpu/expand_as_kernel.cc b/paddle/phi/kernels/xpu/expand_as_kernel.cc index 1427c61f4503b..a748ba3346e26 100644 --- a/paddle/phi/kernels/xpu/expand_as_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_as_kernel.cc @@ -49,10 +49,21 @@ void ExpandAs(const Context& context, target_shape[i])); } } + if (target_shape.size() == 0) { + int r = xpu::copy(context.x_context(), + reinterpret_cast(x.data()), + reinterpret_cast(out->data()), + x.numel()); + PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); + return; + } phi::DDim out_dims = phi::make_ddim(target_shape); out->Resize(out_dims); context.template Alloc(out); auto& x_shape = vec_in_dims; + if (x.dims().size() == 0) { + x_shape = std::vector({1}); + } auto out_shape = phi::vectorize(out_dims); int r = XPU_SUCCESS; @@ -95,7 +106,7 @@ void ExpandAsKernel(const Context& ctx, rank)); PADDLE_ENFORCE_GE( rank, - 1, + 0, phi::errors::InvalidArgument("The rank (%d) of the input 'x' for " "expand_as_v2 op must be positive.", rank)); @@ -118,4 +129,4 @@ PD_REGISTER_KERNEL(expand_as, phi::dtype::float16, bool, int, - int64_t) {} + int64_t) {} \ No newline at end of file diff --git a/paddle/phi/kernels/xpu/expand_kernel.cc b/paddle/phi/kernels/xpu/expand_kernel.cc index d356737e3df4b..087876924d918 100644 --- a/paddle/phi/kernels/xpu/expand_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_kernel.cc @@ -78,7 +78,7 @@ void ExpandKernel(const Context& ctx, auto rank = x.dims().size(); PADDLE_ENFORCE_GE( rank, - 1, + 0, phi::errors::InvalidArgument( "The rank of the input 'X' for expand_v2_npu op must be positive, " "but the value received is %d.", @@ -94,10 +94,21 @@ void ExpandKernel(const Context& ctx, shape_size, rank)); + if (shape_size == 0) { + int r = xpu::copy(ctx.x_context(), + reinterpret_cast(x.data()), + reinterpret_cast(out->data()), + x.numel()); + PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); + return; + } DDim out_dims = phi::make_ddim(final_expand_shape); out->Resize(out_dims); ctx.template Alloc(out); auto& x_shape = vec_in_dims; + if (rank == 0) { + x_shape = std::vector({1}); + } auto out_shape = phi::vectorize(out_dims); int r = XPU_SUCCESS; @@ -130,4 +141,4 @@ PD_REGISTER_KERNEL(expand, phi::dtype::float16, bool, int, - int64_t) {} + int64_t) {} \ No newline at end of file diff --git a/paddle/phi/kernels/xpu/top_k_kernel.cc b/paddle/phi/kernels/xpu/top_k_kernel.cc index 0fdb66c41294d..b953627d360da 100644 --- a/paddle/phi/kernels/xpu/top_k_kernel.cc +++ b/paddle/phi/kernels/xpu/top_k_kernel.cc @@ -28,6 +28,7 @@ void TopkKernel(const Context& dev_ctx, bool sorted, DenseTensor* out, DenseTensor* indices) { + using XPUType = typename XPUTypeTrait::Type; const auto& in_dims = x.dims(); const T* in_data = x.data(); int64_t* indices_data = dev_ctx.template Alloc(indices); @@ -47,7 +48,14 @@ void TopkKernel(const Context& dev_ctx, errors::External( "XPU API does not support smallest topk operation currently." " Operator will be supported in future update.")); - + if (in_dims.size() == 0) { + int r = xpu::copy(dev_ctx.x_context(), + reinterpret_cast(x.data()), + reinterpret_cast(out->data()), + x.numel()); + PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); + return; + } if (axis < 0) axis += in_dims.size(); size_t k = k_scalar.to(); @@ -173,4 +181,4 @@ void TopkKernel(const Context& dev_ctx, } // namespace phi -PD_REGISTER_KERNEL(topk, XPU, ALL_LAYOUT, phi::TopkKernel, float) {} +PD_REGISTER_KERNEL(topk, XPU, ALL_LAYOUT, phi::TopkKernel, float) {} \ No newline at end of file From c5f19b92a8b91b6dc728be0f7e033c481066b088 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Wed, 15 Feb 2023 11:04:53 +0000 Subject: [PATCH 03/24] fix codestyle --- paddle/phi/infermeta/unary.cc | 2 +- paddle/phi/kernels/cpu/top_k_kernel.cc | 2 +- paddle/phi/kernels/gpu/top_k_kernel.cu | 2 +- paddle/phi/kernels/impl/expand_as_kernel_impl.h | 2 +- paddle/phi/kernels/impl/expand_kernel_impl.h | 2 +- paddle/phi/kernels/xpu/expand_as_kernel.cc | 2 +- paddle/phi/kernels/xpu/expand_kernel.cc | 2 +- paddle/phi/kernels/xpu/top_k_kernel.cc | 2 +- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 2 +- .../fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py | 2 +- python/paddle/tensor/manipulation.py | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/paddle/phi/infermeta/unary.cc b/paddle/phi/infermeta/unary.cc index 145874b52f460..c18374a362966 100644 --- a/paddle/phi/infermeta/unary.cc +++ b/paddle/phi/infermeta/unary.cc @@ -4896,4 +4896,4 @@ void ChannelShuffleInferMeta(const MetaTensor& x, } // namespace phi -PD_REGISTER_INFER_META_FN(flatten, phi::FlattenInferMeta); \ No newline at end of file +PD_REGISTER_INFER_META_FN(flatten, phi::FlattenInferMeta); diff --git a/paddle/phi/kernels/cpu/top_k_kernel.cc b/paddle/phi/kernels/cpu/top_k_kernel.cc index 4549b086b5ac4..2059e02c08ec6 100644 --- a/paddle/phi/kernels/cpu/top_k_kernel.cc +++ b/paddle/phi/kernels/cpu/top_k_kernel.cc @@ -239,4 +239,4 @@ void TopkKernel(const Context& dev_ctx, } // namespace phi PD_REGISTER_KERNEL( - topk, CPU, ALL_LAYOUT, phi::TopkKernel, float, double, int32_t, int64_t) {} \ No newline at end of file + topk, CPU, ALL_LAYOUT, phi::TopkKernel, float, double, int32_t, int64_t) {} diff --git a/paddle/phi/kernels/gpu/top_k_kernel.cu b/paddle/phi/kernels/gpu/top_k_kernel.cu index 71727028bf67c..b6a3b4e3a6f55 100644 --- a/paddle/phi/kernels/gpu/top_k_kernel.cu +++ b/paddle/phi/kernels/gpu/top_k_kernel.cu @@ -345,4 +345,4 @@ PD_REGISTER_KERNEL(topk, double, int, int64_t, - phi::dtype::float16) {} \ No newline at end of file + phi::dtype::float16) {} diff --git a/paddle/phi/kernels/impl/expand_as_kernel_impl.h b/paddle/phi/kernels/impl/expand_as_kernel_impl.h index c3dbab3d6b754..7e3a1a6656140 100755 --- a/paddle/phi/kernels/impl/expand_as_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_as_kernel_impl.h @@ -161,4 +161,4 @@ void ExpandAsKernel(const Context& ctx, } } -} // namespace phi \ No newline at end of file +} // namespace phi diff --git a/paddle/phi/kernels/impl/expand_kernel_impl.h b/paddle/phi/kernels/impl/expand_kernel_impl.h index d9250073ceab7..4738088781de9 100644 --- a/paddle/phi/kernels/impl/expand_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_kernel_impl.h @@ -172,4 +172,4 @@ void ExpandKernel(const Context& ctx, } } -} // namespace phi \ No newline at end of file +} // namespace phi diff --git a/paddle/phi/kernels/xpu/expand_as_kernel.cc b/paddle/phi/kernels/xpu/expand_as_kernel.cc index a748ba3346e26..f4258cbc4b53e 100644 --- a/paddle/phi/kernels/xpu/expand_as_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_as_kernel.cc @@ -129,4 +129,4 @@ PD_REGISTER_KERNEL(expand_as, phi::dtype::float16, bool, int, - int64_t) {} \ No newline at end of file + int64_t) {} diff --git a/paddle/phi/kernels/xpu/expand_kernel.cc b/paddle/phi/kernels/xpu/expand_kernel.cc index 087876924d918..a94142afc06f8 100644 --- a/paddle/phi/kernels/xpu/expand_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_kernel.cc @@ -141,4 +141,4 @@ PD_REGISTER_KERNEL(expand, phi::dtype::float16, bool, int, - int64_t) {} \ No newline at end of file + int64_t) {} diff --git a/paddle/phi/kernels/xpu/top_k_kernel.cc b/paddle/phi/kernels/xpu/top_k_kernel.cc index b953627d360da..982f122079222 100644 --- a/paddle/phi/kernels/xpu/top_k_kernel.cc +++ b/paddle/phi/kernels/xpu/top_k_kernel.cc @@ -181,4 +181,4 @@ void TopkKernel(const Context& dev_ctx, } // namespace phi -PD_REGISTER_KERNEL(topk, XPU, ALL_LAYOUT, phi::TopkKernel, float) {} \ No newline at end of file +PD_REGISTER_KERNEL(topk, XPU, ALL_LAYOUT, phi::TopkKernel, float) {} diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 65e037bf7f269..fad869616f64a 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -3610,4 +3610,4 @@ def test_static(self): if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() diff --git a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py index 1e47318bd02d9..8fa4d2fb2af05 100644 --- a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py +++ b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py @@ -1263,4 +1263,4 @@ def test_where(self): if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() diff --git a/python/paddle/tensor/manipulation.py b/python/paddle/tensor/manipulation.py index 8abffb7a9e9d5..25ac0564c4dbd 100644 --- a/python/paddle/tensor/manipulation.py +++ b/python/paddle/tensor/manipulation.py @@ -4711,4 +4711,4 @@ def index_add_(x, index, axis, value, name=None): } for name, func in __METHODS.items(): setattr(core.VarBase, name, func) - setattr(core.eager.Tensor, name, func) \ No newline at end of file + setattr(core.eager.Tensor, name, func) From 2e22a3e0608feda16a0ba6cb48675cd06ddfbce0 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Wed, 15 Feb 2023 12:19:55 +0000 Subject: [PATCH 04/24] add broadcast_shape test --- .../tests/unittests/test_zero_dim_tensor.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index fad869616f64a..8ee05295f2832 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -669,6 +669,22 @@ def test_broadcast_to(self): self.assertEqual(out1.item(), 1.0) self.assertEqual(out1.grad, None) + def test_broadcast_shape(self): + x = [] + y = [3, 5] + out = paddle.broadcast_shape(x, y) + self.assertEqual(out, [3, 5]) + + x = [3, 5] + y = [] + out = paddle.broadcast_shape(x, y) + self.assertEqual(out, [3, 5]) + + x = [] + y = [] + out = paddle.broadcast_shape(x, y) + self.assertEqual(out, []) + def test_argmin(self): x = paddle.rand([]) out1 = paddle.argmin(x, 0) From 42108bfe3d05f618cb12bb670cadd998f732a6b2 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Thu, 16 Feb 2023 08:02:49 +0000 Subject: [PATCH 05/24] fix unitest --- .../paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 8ee05295f2832..184871afd6bfa 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -578,7 +578,7 @@ def test_expand(self): out.backward() self.assertEqual(x.shape, []) self.assertEqual(x.item(), 1.0) - self.assertEqual(x.grad.shape, [1]) + self.assertEqual(x.grad.shape, []) self.assertEqual(x.grad.item(0), 1.0) self.assertEqual(out.shape, [1]) self.assertEqual(out.item(0), 1.0) @@ -651,7 +651,7 @@ def test_broadcast_to(self): out.backward() self.assertEqual(x.shape, []) self.assertEqual(x.item(), 1.0) - self.assertEqual(x.grad.shape, [1]) + self.assertEqual(x.grad.shape, []) self.assertEqual(x.grad.item(0), 1.0) self.assertEqual(out.shape, [1]) self.assertEqual(out.item(0), 1.0) @@ -1808,7 +1808,7 @@ def test_expand(self): self.assertEqual(res[0], 1.0) self.assertEqual(res[1].shape, (1,)) self.assertEqual(res[1], 1.0) - self.assertEqual(res[2].shape, (1,)) + self.assertEqual(res[2].shape, ()) self.assertEqual(res[2], 1.0) self.assertEqual(res[3].shape, (1,)) self.assertEqual(res[3], 1.0) @@ -1909,7 +1909,7 @@ def test_broadcast_to(self): self.assertEqual(res[0], 1.0) self.assertEqual(res[1].shape, (1,)) self.assertEqual(res[1], 1.0) - self.assertEqual(res[2].shape, (1,)) + self.assertEqual(res[2].shape, ()) self.assertEqual(res[2], 1.0) self.assertEqual(res[3].shape, (1,)) self.assertEqual(res[3], 1.0) @@ -1922,6 +1922,7 @@ def test_broadcast_to(self): res = self.exe.run( prog, fetch_list=[x1, out1, x1.grad_name, out1.grad_name] ) + self.assertEqual(res[0].shape, ()) self.assertEqual(res[0], 1.0) self.assertEqual(res[1].shape, ()) From 77d523a8511fc5e89c78437ec188c968edc2243e Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Thu, 16 Feb 2023 08:13:15 +0000 Subject: [PATCH 06/24] fix unitests --- .../fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py index 8fa4d2fb2af05..d59f1707c28ff 100644 --- a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py +++ b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py @@ -335,11 +335,11 @@ def test_expand(self): out.backward() self.assertEqual(x.shape, []) self.assertEqual(x.item(), 1.0) - self.assertEqual(x.grad.shape, [1]) + self.assertEqual(x.grad.shape, []) self.assertEqual(x.grad.item(0), 1.0) self.assertEqual(out.shape, [1]) self.assertEqual(out.item(0), 1.0) - # self.assertEqual(out.grad, None) + self.assertEqual(out.grad, None) x1 = paddle.full([], 1, 'float32') x1.stop_gradient = False From 48ac230037bbc6b191d3f2a07f1818b0fd9db98b Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Thu, 16 Feb 2023 11:57:51 +0000 Subject: [PATCH 07/24] fix unitest --- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 2 +- .../fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 184871afd6bfa..952036a2ee5bc 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -1922,7 +1922,7 @@ def test_broadcast_to(self): res = self.exe.run( prog, fetch_list=[x1, out1, x1.grad_name, out1.grad_name] ) - + self.assertEqual(res[0].shape, ()) self.assertEqual(res[0], 1.0) self.assertEqual(res[1].shape, ()) diff --git a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py index d59f1707c28ff..5a6e90bf0c2a5 100644 --- a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py +++ b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py @@ -339,7 +339,7 @@ def test_expand(self): self.assertEqual(x.grad.item(0), 1.0) self.assertEqual(out.shape, [1]) self.assertEqual(out.item(0), 1.0) - self.assertEqual(out.grad, None) + # self.assertEqual(out.grad, None) x1 = paddle.full([], 1, 'float32') x1.stop_gradient = False From 83b9eb3434d6289830831e8ce690a2f07de5976c Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Fri, 17 Feb 2023 07:30:18 +0000 Subject: [PATCH 08/24] add 0D grad support --- paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h | 10 ++++++++++ paddle/phi/kernels/impl/expand_grad_kernel_impl.h | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h b/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h index 998c54e77fe01..9b6a8ae1131c4 100644 --- a/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h @@ -49,6 +49,16 @@ void ExpandAsGradKernel(const Context& context, const std::vector& target_shape, DenseTensor* in_grad) { auto x_dims = x.dims(); + + // For 0-D tensor + std::cout << "XYY Debug in expand_as_grad_kernel_impl.h, the x_dims is :" + << x_dims << std::endl; + if (x_dims == 0) { + context.template Alloc(in_grad); + phi::Copy(context, out_grad, context.GetPlace(), false, in_grad); + return; + } + auto vec_in_dims = phi::vectorize(x_dims); auto diff = target_shape.size() - vec_in_dims.size(); vec_in_dims.insert(vec_in_dims.begin(), diff, 1); diff --git a/paddle/phi/kernels/impl/expand_grad_kernel_impl.h b/paddle/phi/kernels/impl/expand_grad_kernel_impl.h index 31cb87da25f65..3d05373d15204 100644 --- a/paddle/phi/kernels/impl/expand_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_grad_kernel_impl.h @@ -54,6 +54,16 @@ void ExpandGradKernel(const Context& ctx, DenseTensor* in_grad) { auto expand_shape = shape.GetData(); auto x_dims = x.dims(); + + // For 0-D Tensor + std::cout << "XYY Debug in expand_grad_kernel_impl.h, the x_dims is :" + << x_dims << std::endl; + if (x_dims == 0) { + context.template Alloc(in_grad); + phi::Copy(ctx, out_grad, ctx.GetPlace(), false, in_grad); + return; + } + auto vec_in_dims = phi::vectorize(x_dims); auto diff = expand_shape.size() - vec_in_dims.size(); vec_in_dims.insert(vec_in_dims.begin(), diff, 1); From 7b771058638409ceb14769b19bcd8b55557848c2 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Fri, 17 Feb 2023 07:35:19 +0000 Subject: [PATCH 09/24] add 0D grad support --- .../fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py index 5a6e90bf0c2a5..547230fed6564 100644 --- a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py +++ b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py @@ -375,7 +375,7 @@ def test_expand_as(self): out1.backward() self.assertEqual(x1.shape, []) self.assertEqual(x1.item(), 1.0) - self.assertEqual(x1.grad.shape, [1]) + self.assertEqual(x1.grad.shape, []) self.assertEqual(x1.grad.item(0), 1.0) self.assertEqual(out1.shape, [1]) self.assertEqual(out1.item(0), 1.0) From bbfe4f2d737d33c802654b9f93c16d8514f6368a Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Fri, 17 Feb 2023 07:55:10 +0000 Subject: [PATCH 10/24] add 0D grad support --- paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h | 2 +- paddle/phi/kernels/impl/expand_grad_kernel_impl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h b/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h index 9b6a8ae1131c4..e362aaeb4881a 100644 --- a/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h @@ -53,7 +53,7 @@ void ExpandAsGradKernel(const Context& context, // For 0-D tensor std::cout << "XYY Debug in expand_as_grad_kernel_impl.h, the x_dims is :" << x_dims << std::endl; - if (x_dims == 0) { + if (x_dims.size() == 0) { context.template Alloc(in_grad); phi::Copy(context, out_grad, context.GetPlace(), false, in_grad); return; diff --git a/paddle/phi/kernels/impl/expand_grad_kernel_impl.h b/paddle/phi/kernels/impl/expand_grad_kernel_impl.h index 3d05373d15204..374ac1c268e1c 100644 --- a/paddle/phi/kernels/impl/expand_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_grad_kernel_impl.h @@ -58,7 +58,7 @@ void ExpandGradKernel(const Context& ctx, // For 0-D Tensor std::cout << "XYY Debug in expand_grad_kernel_impl.h, the x_dims is :" << x_dims << std::endl; - if (x_dims == 0) { + if (x_dims.size() == 0) { context.template Alloc(in_grad); phi::Copy(ctx, out_grad, ctx.GetPlace(), false, in_grad); return; From adaa85c62a42c14adc737165f0f045a617397da1 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Fri, 17 Feb 2023 08:37:18 +0000 Subject: [PATCH 11/24] fix 0D tensor --- paddle/phi/kernels/impl/expand_grad_kernel_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/phi/kernels/impl/expand_grad_kernel_impl.h b/paddle/phi/kernels/impl/expand_grad_kernel_impl.h index 374ac1c268e1c..3b481d6585be5 100644 --- a/paddle/phi/kernels/impl/expand_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_grad_kernel_impl.h @@ -59,7 +59,7 @@ void ExpandGradKernel(const Context& ctx, std::cout << "XYY Debug in expand_grad_kernel_impl.h, the x_dims is :" << x_dims << std::endl; if (x_dims.size() == 0) { - context.template Alloc(in_grad); + ctx.template Alloc(in_grad); phi::Copy(ctx, out_grad, ctx.GetPlace(), false, in_grad); return; } From 05950695054cece5edcae616d3e722dd33dbbdc8 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Sun, 19 Feb 2023 08:55:39 +0000 Subject: [PATCH 12/24] fix 0D --- paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h | 2 +- paddle/phi/kernels/impl/expand_grad_kernel_impl.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h b/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h index e362aaeb4881a..be85e819c28b8 100644 --- a/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h @@ -52,7 +52,7 @@ void ExpandAsGradKernel(const Context& context, // For 0-D tensor std::cout << "XYY Debug in expand_as_grad_kernel_impl.h, the x_dims is :" - << x_dims << std::endl; + << x_dims << ", it .size() is : " << x_dims.size() << std::endl; if (x_dims.size() == 0) { context.template Alloc(in_grad); phi::Copy(context, out_grad, context.GetPlace(), false, in_grad); diff --git a/paddle/phi/kernels/impl/expand_grad_kernel_impl.h b/paddle/phi/kernels/impl/expand_grad_kernel_impl.h index 3b481d6585be5..2f2ad8322361a 100644 --- a/paddle/phi/kernels/impl/expand_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_grad_kernel_impl.h @@ -57,8 +57,9 @@ void ExpandGradKernel(const Context& ctx, // For 0-D Tensor std::cout << "XYY Debug in expand_grad_kernel_impl.h, the x_dims is :" - << x_dims << std::endl; + << x_dims << ", it .size() is : " << x_dims.size() << std::endl; if (x_dims.size() == 0) { + std::cout << "XYYDebug ==== The x_dims is empty =======" << std::endl; ctx.template Alloc(in_grad); phi::Copy(ctx, out_grad, ctx.GetPlace(), false, in_grad); return; From d2bfc237e585036e992b07f398deed333a65d3ce Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Sun, 19 Feb 2023 09:12:21 +0000 Subject: [PATCH 13/24] fix xpu 0D --- paddle/phi/kernels/xpu/expand_as_kernel.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/paddle/phi/kernels/xpu/expand_as_kernel.cc b/paddle/phi/kernels/xpu/expand_as_kernel.cc index f4258cbc4b53e..8335006bbf1bc 100644 --- a/paddle/phi/kernels/xpu/expand_as_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_as_kernel.cc @@ -50,6 +50,11 @@ void ExpandAs(const Context& context, } } if (target_shape.size() == 0) { + std::cout << "XYY Debug, debug the 「Tensor holds no memory」" << std::endl; + phi::DDim out_dims = phi::make_ddim(target_shape); + out->Resize(out_dims); + context.template Alloc(out); + int r = xpu::copy(context.x_context(), reinterpret_cast(x.data()), reinterpret_cast(out->data()), @@ -57,6 +62,7 @@ void ExpandAs(const Context& context, PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); return; } + phi::DDim out_dims = phi::make_ddim(target_shape); out->Resize(out_dims); context.template Alloc(out); From 26118b4b60db04f4629b8b679df93214f219021f Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Tue, 21 Feb 2023 02:25:53 +0000 Subject: [PATCH 14/24] fix expand kernel --- .../kernels/impl/expand_as_grad_kernel_impl.h | 3 - .../kernels/impl/expand_grad_kernel_impl.h | 112 ++++++++---------- .../tests/unittests/test_zero_dim_tensor.py | 111 +++++++++++++---- 3 files changed, 136 insertions(+), 90 deletions(-) diff --git a/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h b/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h index be85e819c28b8..635a5b2765fcc 100644 --- a/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h @@ -50,9 +50,6 @@ void ExpandAsGradKernel(const Context& context, DenseTensor* in_grad) { auto x_dims = x.dims(); - // For 0-D tensor - std::cout << "XYY Debug in expand_as_grad_kernel_impl.h, the x_dims is :" - << x_dims << ", it .size() is : " << x_dims.size() << std::endl; if (x_dims.size() == 0) { context.template Alloc(in_grad); phi::Copy(context, out_grad, context.GetPlace(), false, in_grad); diff --git a/paddle/phi/kernels/impl/expand_grad_kernel_impl.h b/paddle/phi/kernels/impl/expand_grad_kernel_impl.h index 2f2ad8322361a..700f64863e4fe 100644 --- a/paddle/phi/kernels/impl/expand_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_grad_kernel_impl.h @@ -55,16 +55,10 @@ void ExpandGradKernel(const Context& ctx, auto expand_shape = shape.GetData(); auto x_dims = x.dims(); - // For 0-D Tensor - std::cout << "XYY Debug in expand_grad_kernel_impl.h, the x_dims is :" - << x_dims << ", it .size() is : " << x_dims.size() << std::endl; - if (x_dims.size() == 0) { - std::cout << "XYYDebug ==== The x_dims is empty =======" << std::endl; - ctx.template Alloc(in_grad); + if (in_grad->dims() == out_grad.dims()) { phi::Copy(ctx, out_grad, ctx.GetPlace(), false, in_grad); return; } - auto vec_in_dims = phi::vectorize(x_dims); auto diff = expand_shape.size() - vec_in_dims.size(); vec_in_dims.insert(vec_in_dims.begin(), diff, 1); @@ -90,63 +84,55 @@ void ExpandGradKernel(const Context& ctx, int dims = reduce_dims_vec.size(); - bool just_copy = true; - for (size_t i = 0; i < repeat_times.size(); i++) { - if (repeat_times[i] != 1) { - just_copy = false; + PADDLE_ENFORCE_GE( + dims, + 0, + phi::errors::InvalidArgument("The rank of the input 'Out@GRAD' for " + "expand_v2_grad op must be greater than or " + "equal to 0, but the value received is %d.", + dims)); + PADDLE_ENFORCE_LE(dims, + MAX_RANK_SUPPORTED, + phi::errors::InvalidArgument( + "The rank of the input 'Out@GRAD' for " + "expand_v2_grad op must be less than or equal " + "to %d, but the value received is %d.", + MAX_RANK_SUPPORTED, + dims)); + switch (dims) { + case 0: + ExpandBackward( + ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); break; - } - } - // no need reduce, just copy - if (just_copy) { - phi::Copy(ctx, out_grad, ctx.GetPlace(), false, in_grad); - } else { - PADDLE_ENFORCE_GE(dims, - 1, - phi::errors::InvalidArgument( - "The rank of the input 'Out@GRAD' for " - "expand_v2_grad op must be greater than or " - "equal to 1, but the value received is %d.", - dims)); - PADDLE_ENFORCE_LE(dims, - MAX_RANK_SUPPORTED, - phi::errors::InvalidArgument( - "The rank of the input 'Out@GRAD' for " - "expand_v2_grad op must be less than or equal " - "to %d, but the value received is %d.", - MAX_RANK_SUPPORTED, - dims)); - switch (dims) { - case 1: - ExpandBackward( - ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - case 2: - ExpandBackward( - ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - case 3: - ExpandBackward( - ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - case 4: - ExpandBackward( - ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - case 5: - ExpandBackward( - ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - case 6: - ExpandBackward( - ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - default: - PADDLE_THROW(phi::errors::InvalidArgument( - "Only support tensor with rank being between 1 and 6. But " - "received tensor's rank = %d.", - dims)); - } + case 1: + ExpandBackward( + ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + case 2: + ExpandBackward( + ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + case 3: + ExpandBackward( + ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + case 4: + ExpandBackward( + ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + case 5: + ExpandBackward( + ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + case 6: + ExpandBackward( + ctx, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + default: + PADDLE_THROW(phi::errors::InvalidArgument( + "Only support tensor with rank being between 1 and 6. But " + "received tensor's rank = %d.", + dims)); } } diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 952036a2ee5bc..2a9d5f40c6f36 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -572,29 +572,61 @@ def setUp(self): self.x = paddle.rand([]) def test_expand(self): + # case1 x = paddle.full([], 1, 'float32') x.stop_gradient = False out = paddle.expand(x, shape=[1]) + out.retain_grads() out.backward() - self.assertEqual(x.shape, []) - self.assertEqual(x.item(), 1.0) - self.assertEqual(x.grad.shape, []) - self.assertEqual(x.grad.item(0), 1.0) + self.assertEqual(out.shape, [1]) - self.assertEqual(out.item(0), 1.0) - self.assertEqual(out.grad, None) + np.testing.assert_allclose(out, 1.0) + self.assertEqual(x.grad.shape, []) + np.testing.assert_allclose(x.grad, 1.0) + self.assertEqual(out.grad.shape, [1]) + np.testing.assert_allclose(out.grad, 1.0) + # case2 x1 = paddle.full([], 1, 'float32') x1.stop_gradient = False out1 = paddle.expand(x1, shape=[]) + out1.retain_grads() out1.backward() - self.assertEqual(x1.shape, []) - self.assertEqual(x1.item(), 1.0) - self.assertEqual(x1.grad.shape, []) - self.assertEqual(x1.grad.item(), 1.0) + self.assertEqual(out1.shape, []) - self.assertEqual(out1.item(), 1.0) - self.assertEqual(out1.grad, None) + np.testing.assert_allclose(out1, 1.0) + self.assertEqual(x1.grad.shape, []) + np.testing.assert_allclose(x1.grad, 1.0) + self.assertEqual(out1.grad.shape, []) + np.testing.assert_allclose(out1.grad, 1.0) + + # case3 + x2 = paddle.full([], 1, 'float32') + x2.stop_gradient = False + out2 = paddle.expand(x2, shape=[1, 1]) + out2.retain_grads() + out2.backward() + + self.assertEqual(out2.shape, [1, 1]) + np.testing.assert_allclose(out2, 1.0) + self.assertEqual(x2.grad.shape, []) + np.testing.assert_allclose(x2.grad, 1.0) + self.assertEqual(out2.grad.shape, [1, 1]) + np.testing.assert_allclose(out2.grad, 1.0) + + # case4 + x3 = paddle.full([], 1, 'float32') + x3.stop_gradient = False + out3 = paddle.expand(x3, shape=[3, 3]) + out3.retain_grads() + out3.backward() + + self.assertEqual(out3.shape, [3, 3]) + np.testing.assert_allclose(out3, 1.0) + self.assertEqual(x3.grad.shape, []) + np.testing.assert_allclose(x3.grad, 9.0) + self.assertEqual(out3.grad.shape, [3, 3]) + np.testing.assert_allclose(out3.grad, 1.0) def test_expand_as(self): x = paddle.full([], 1, 'float32') @@ -648,26 +680,57 @@ def test_broadcast_to(self): x = paddle.full([], 1, 'float32') x.stop_gradient = False out = paddle.broadcast_to(x, shape=[1]) + out.retain_grads() out.backward() - self.assertEqual(x.shape, []) - self.assertEqual(x.item(), 1.0) - self.assertEqual(x.grad.shape, []) - self.assertEqual(x.grad.item(0), 1.0) + self.assertEqual(out.shape, [1]) - self.assertEqual(out.item(0), 1.0) - self.assertEqual(out.grad, None) + np.testing.assert_allclose(out, 1.0) + self.assertEqual(x.grad.shape, []) + np.testing.assert_allclose(x.grad, 1.0) + self.assertEqual(out.grad.shape, [1]) + np.testing.assert_allclose(out.grad, 1.0) + # case2 x1 = paddle.full([], 1, 'float32') x1.stop_gradient = False out1 = paddle.broadcast_to(x1, shape=[]) + out1.retain_grads() out1.backward() - self.assertEqual(x1.shape, []) - self.assertEqual(x1.item(), 1.0) - self.assertEqual(x1.grad.shape, []) - self.assertEqual(x1.grad.item(), 1.0) + self.assertEqual(out1.shape, []) - self.assertEqual(out1.item(), 1.0) - self.assertEqual(out1.grad, None) + np.testing.assert_allclose(out1, 1.0) + self.assertEqual(x1.grad.shape, []) + np.testing.assert_allclose(x1.grad, 1.0) + self.assertEqual(out1.grad.shape, []) + np.testing.assert_allclose(out1.grad, 1.0) + + # case3 + x2 = paddle.full([], 1, 'float32') + x2.stop_gradient = False + out2 = paddle.broadcast_to(x2, shape=[1, 1]) + out2.retain_grads() + out2.backward() + + self.assertEqual(out2.shape, [1, 1]) + np.testing.assert_allclose(out2, 1.0) + self.assertEqual(x2.grad.shape, []) + np.testing.assert_allclose(x2.grad, 1.0) + self.assertEqual(out2.grad.shape, [1, 1]) + np.testing.assert_allclose(out2.grad, 1.0) + + # case4 + x3 = paddle.full([], 1, 'float32') + x3.stop_gradient = False + out3 = paddle.broadcast_to(x3, shape=[3, 3]) + out3.retain_grads() + out3.backward() + + self.assertEqual(out3.shape, [3, 3]) + np.testing.assert_allclose(out3, 1.0) + self.assertEqual(x3.grad.shape, []) + np.testing.assert_allclose(x3.grad, 9.0) + self.assertEqual(out3.grad.shape, [3, 3]) + np.testing.assert_allclose(out3.grad, 1.0) def test_broadcast_shape(self): x = [] From 91ab26c8b0f30c9b916bfafa1289603c3b8dd8a8 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Tue, 21 Feb 2023 10:54:26 +0000 Subject: [PATCH 15/24] fix xpu expand --- paddle/phi/kernels/xpu/expand_as_kernel.cc | 1 - paddle/phi/kernels/xpu/expand_kernel.cc | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/paddle/phi/kernels/xpu/expand_as_kernel.cc b/paddle/phi/kernels/xpu/expand_as_kernel.cc index 8335006bbf1bc..0e4a5ca5c270b 100644 --- a/paddle/phi/kernels/xpu/expand_as_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_as_kernel.cc @@ -50,7 +50,6 @@ void ExpandAs(const Context& context, } } if (target_shape.size() == 0) { - std::cout << "XYY Debug, debug the 「Tensor holds no memory」" << std::endl; phi::DDim out_dims = phi::make_ddim(target_shape); out->Resize(out_dims); context.template Alloc(out); diff --git a/paddle/phi/kernels/xpu/expand_kernel.cc b/paddle/phi/kernels/xpu/expand_kernel.cc index a94142afc06f8..b5af94b2b7413 100644 --- a/paddle/phi/kernels/xpu/expand_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_kernel.cc @@ -95,6 +95,10 @@ void ExpandKernel(const Context& ctx, rank)); if (shape_size == 0) { + phi::DDim out_dims = phi::make_ddim(final_expand_shape); + out->Resize(out_dims); + context.template Alloc(out); + int r = xpu::copy(ctx.x_context(), reinterpret_cast(x.data()), reinterpret_cast(out->data()), From 1ab5d3970b81ee1d76e932344ad8ae6e39bbb380 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Wed, 22 Feb 2023 07:17:59 +0000 Subject: [PATCH 16/24] Fix 0D kernel --- paddle/phi/kernels/cpu/top_k_grad_kernel.cc | 5 + paddle/phi/kernels/cpu/top_k_kernel.cc | 2 + paddle/phi/kernels/gpu/top_k_grad_kernel.cu | 5 + paddle/phi/kernels/gpu/top_k_kernel.cu | 3 + .../kernels/impl/expand_as_grad_kernel_impl.h | 109 ++++++++-------- .../tests/unittests/test_zero_dim_tensor.py | 117 +++++++++++------- 6 files changed, 138 insertions(+), 103 deletions(-) diff --git a/paddle/phi/kernels/cpu/top_k_grad_kernel.cc b/paddle/phi/kernels/cpu/top_k_grad_kernel.cc index 2d02b0ab523b2..a65c2324cc768 100644 --- a/paddle/phi/kernels/cpu/top_k_grad_kernel.cc +++ b/paddle/phi/kernels/cpu/top_k_grad_kernel.cc @@ -66,6 +66,11 @@ void TopkGradKernel(const Context& dev_ctx, axis = (axis < 0) ? (in_dims.size() + axis) : axis; T* x_grad_data = dev_ctx.template Alloc(x_grad); + if (in_dims.size() == 0) { + phi::Copy(dev_ctx, out_grad, dev_ctx.GetPlace(), false, x_grad); + return; + } + if (axis + 1 == in_dims.size()) { // allocate the memory for the input_grad diff --git a/paddle/phi/kernels/cpu/top_k_kernel.cc b/paddle/phi/kernels/cpu/top_k_kernel.cc index 2059e02c08ec6..25e5b08bc13c9 100644 --- a/paddle/phi/kernels/cpu/top_k_kernel.cc +++ b/paddle/phi/kernels/cpu/top_k_kernel.cc @@ -143,6 +143,8 @@ void TopkKernel(const Context& dev_ctx, // 0d input x if (in_dims.size() == 0) { phi::Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); + int64_t* indices_data = dev_ctx.template Alloc(indices); + indices_data[0] = 0; return; } // axis < 0, cacluate the real axis diff --git a/paddle/phi/kernels/gpu/top_k_grad_kernel.cu b/paddle/phi/kernels/gpu/top_k_grad_kernel.cu index e20fec806873f..638d53c010ce6 100644 --- a/paddle/phi/kernels/gpu/top_k_grad_kernel.cu +++ b/paddle/phi/kernels/gpu/top_k_grad_kernel.cu @@ -47,6 +47,11 @@ void TopkGradKernel(const Context& dev_ctx, const T* out_grad_data = out_grad.data(); const int64_t* indices_data = indices.data(); + if (in_dims.size() == 0) { + phi::Copy(dev_ctx, out_grad, dev_ctx.GetPlace(), false, x_grad); + return; + } + int pre, n, post; phi::funcs::GetDims(in_dims, axis, &pre, &n, &post); diff --git a/paddle/phi/kernels/gpu/top_k_kernel.cu b/paddle/phi/kernels/gpu/top_k_kernel.cu index b6a3b4e3a6f55..03f675bc47af7 100644 --- a/paddle/phi/kernels/gpu/top_k_kernel.cu +++ b/paddle/phi/kernels/gpu/top_k_kernel.cu @@ -61,9 +61,12 @@ void TopkKernel(const Context& dev_ctx, const auto* input = &x; // get the input dims const auto& in_dims = input->dims(); + // 0d input tensor if (in_dims.size() == 0) { phi::Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); + int64_t* indices_data = dev_ctx.template Alloc(indices); + indices_data = 0; return; } // calcluate the real axis diff --git a/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h b/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h index 635a5b2765fcc..f0c32dd32e42f 100644 --- a/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/expand_as_grad_kernel_impl.h @@ -50,8 +50,7 @@ void ExpandAsGradKernel(const Context& context, DenseTensor* in_grad) { auto x_dims = x.dims(); - if (x_dims.size() == 0) { - context.template Alloc(in_grad); + if (in_grad->dims() == out_grad.dims()) { phi::Copy(context, out_grad, context.GetPlace(), false, in_grad); return; } @@ -72,64 +71,56 @@ void ExpandAsGradKernel(const Context& context, } int dims = reduce_dims_vec.size(); - bool just_copy = true; - for (size_t i = 0; i < repeat_times.size(); i++) { - if (repeat_times[i] != 1) { - just_copy = false; + + PADDLE_ENFORCE_GE( + dims, + 0, + errors::InvalidArgument("The rank of the input 'Out@GRAD' for " + "expand_as_v2_grad op must be greater than or " + "equal to 0, but the value received is %d.", + dims)); + PADDLE_ENFORCE_LE( + dims, + MAX_RANK_SUPPORTED, + errors::InvalidArgument("The rank of the input 'Out@GRAD' for " + "expand_as_v2_grad op must be less than or equal " + "to %d, but the value received is %d.", + MAX_RANK_SUPPORTED, + dims)); + switch (dims) { + case 0: + ExpandAsBackward( + context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); break; - } - } - // no need reduce, just copy - if (just_copy) { - context.template Alloc(in_grad); - phi::Copy(context, out_grad, context.GetPlace(), false, in_grad); - } else { - PADDLE_ENFORCE_GE( - dims, - 1, - errors::InvalidArgument("The rank of the input 'Out@GRAD' for " - "expand_as_v2_grad op must be greater than or " - "equal to 1, but the value received is %d.", - dims)); - PADDLE_ENFORCE_LE(dims, - MAX_RANK_SUPPORTED, - errors::InvalidArgument( - "The rank of the input 'Out@GRAD' for " - "expand_as_v2_grad op must be less than or equal " - "to %d, but the value received is %d.", - MAX_RANK_SUPPORTED, - dims)); - switch (dims) { - case 1: - ExpandAsBackward( - context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - case 2: - ExpandAsBackward( - context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - case 3: - ExpandAsBackward( - context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - case 4: - ExpandAsBackward( - context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - case 5: - ExpandAsBackward( - context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - case 6: - ExpandAsBackward( - context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); - break; - default: - PADDLE_THROW(errors::InvalidArgument( - "Only support tensor with rank being between 1 and 6. But " - "received tensor's rank = %d.", - dims)); - } + case 1: + ExpandAsBackward( + context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + case 2: + ExpandAsBackward( + context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + case 3: + ExpandAsBackward( + context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + case 4: + ExpandAsBackward( + context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + case 5: + ExpandAsBackward( + context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + case 6: + ExpandAsBackward( + context, out_grad, reshape_dims_vec, reduce_dims_vec, in_grad); + break; + default: + PADDLE_THROW(errors::InvalidArgument( + "Only support tensor with rank being between 1 and 6. But " + "received tensor's rank = %d.", + dims)); } } diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 2bc5e13e6b46b..83f760cac6b10 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -12,11 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Note: -# 0D Tensor indicates that the tensor's dimension is 0 -# 0D Tensor's shape is always [], numel is 1 -# which can be created by paddle.rand([]) - import unittest import numpy as np @@ -293,7 +288,6 @@ def test_static_reduce(self): paddle.fmax, paddle.fmin, paddle.complex, - paddle.kron, ] binary_int_api_list = [ @@ -656,28 +650,55 @@ def test_expand_as(self): out1.backward() self.assertEqual(x1.shape, []) self.assertEqual(x1.item(), 1.0) - self.assertEqual(x1.grad.shape, [1]) + self.assertEqual(x1.grad.shape, []) self.assertEqual(x1.grad.item(0), 1.0) self.assertEqual(out1.shape, [1]) self.assertEqual(out1.item(0), 1.0) self.assertEqual(out1.grad, None) + x2 = paddle.full([], 1, 'float32') + x2.stop_gradient = False + y2 = paddle.full([3, 3], 1, 'float32') + out2 = paddle.expand_as(x2, y2) + out2.backward() + self.assertEqual(x2.shape, []) + self.assertEqual(x2.item(), 1.0) + self.assertEqual(x2.grad.shape, []) + self.assertEqual(x2.grad.item(0), 9.0) + self.assertEqual(out2.shape, [3, 3]) + self.assertEqual(out2.item(0), 1.0) + self.assertEqual(out2.grad, None) + def test_top_k(self): x = paddle.full([], 1, 'float32') x.stop_gradient = False out, indices = paddle.topk(x, k=1, axis=0) + out.retain_grads() + out.backward() + self.assertEqual(indices.shape, []) + self.assertEqual(indices.item(), 0) self.assertEqual(x.shape, []) self.assertEqual(x.item(), 1.0) + self.assertEqual(x.grad.shape, []) + self.assertEqual(x.grad.item(0), 1.0) self.assertEqual(out.shape, []) self.assertEqual(out.item(), 1.0) + self.assertEqual(out.grad, 1.0) x1 = paddle.full([], 1, 'float32') x1.stop_gradient = False out1, indices1 = paddle.topk(x1, k=1, axis=-1) + out1.retain_grads() + out1.backward() + self.assertEqual(indices1.shape, []) + self.assertEqual(indices1.item(), 0) self.assertEqual(x1.shape, []) self.assertEqual(x1.item(), 1.0) + self.assertEqual(x.grad.shape, []) + self.assertEqual(x.grad.item(0), 1.0) self.assertEqual(out1.shape, []) self.assertEqual(out1.item(), 1.0) + self.assertEqual(out1.grad, 1.0) with self.assertRaises(ValueError): tmp = paddle.topk(x1, k=1, axis=2) @@ -1811,29 +1832,24 @@ def test_t(self): self.assertEqual(x.grad.shape, []) def test_prelu(self): - x1 = paddle.full([], 1.0, 'float32') - x1.stop_gradient = False - w1 = paddle.full([], 0.25, dtype='float32') - out1 = paddle.nn.functional.prelu(x1, w1) + x = paddle.full([], 1.0, 'float32') + x.stop_gradient = False + + w1 = paddle.to_tensor([0.25], dtype='float32') + out1 = paddle.nn.functional.prelu(x, w1) out1.retain_grads() out1.backward() self.assertEqual(out1.shape, []) - self.assertEqual(out1.numpy(), 1.0) self.assertEqual(out1.grad.shape, []) - self.assertEqual(x1.grad.shape, []) - self.assertEqual(x1.grad.numpy(), 1.0) + self.assertEqual(x.grad.shape, []) - x2 = paddle.full([], -1.0, 'float32') - x2.stop_gradient = False w2 = paddle.full([], 0.25, dtype='float32') - out2 = paddle.nn.functional.prelu(x2, w2) + out2 = paddle.nn.functional.prelu(x, w2) out2.retain_grads() out2.backward() self.assertEqual(out2.shape, []) - self.assertEqual(out2.numpy(), -0.25) self.assertEqual(out2.grad.shape, []) - self.assertEqual(x2.grad.shape, []) - self.assertEqual(x2.grad.numpy(), 0.25) + self.assertEqual(x.grad.shape, []) def test_while_loop(self): def cond(i, x): @@ -1904,6 +1920,23 @@ def test_expand(self): self.assertEqual(res[3].shape, ()) self.assertEqual(res[3], 1.0) + x2 = paddle.full([], 1, 'float32') + x2.stop_gradient = False + out2 = paddle.expand(x2, shape=[3, 3]) + paddle.static.append_backward(out2.sum()) + prog = paddle.static.default_main_program() + res = self.exe.run( + prog, fetch_list=[x2, out2, x2.grad_name, out2.grad_name] + ) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[0], 1.0) + self.assertEqual(res[1].shape, (3, 3)) + self.assertEqual(res[1].any(), 1.0) + self.assertEqual(res[2].shape, ()) + self.assertEqual(res[2], 9) + self.assertEqual(res[3].shape, (3, 3)) + self.assertEqual(res[3].any(), 1.0) + @prog_scope() def test_expand_as(self): x = paddle.full([], 1, 'float32') @@ -1941,11 +1974,30 @@ def test_expand_as(self): self.assertEqual(res[0], 1.0) self.assertEqual(res[1].shape, (1,)) self.assertEqual(res[1], 1.0) - self.assertEqual(res[2].shape, (1,)) + self.assertEqual(res[2].shape, ()) self.assertEqual(res[2], 1.0) self.assertEqual(res[3].shape, (1,)) self.assertEqual(res[3], 1.0) + x2 = paddle.full([], 1, 'float32') + x2.stop_gradient = False + y2 = paddle.full([3, 3], 1, 'float32') + y2.stop_gradient = False + out2 = paddle.expand_as(x2, y2) + paddle.static.append_backward(out2.sum()) + prog = paddle.static.default_main_program() + res = self.exe.run( + prog, fetch_list=[x2, out2, x2.grad_name, out2.grad_name] + ) + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[0], 1.0) + self.assertEqual(res[1].shape, (3, 3)) + self.assertEqual(res[1].any(), 1.0) + self.assertEqual(res[2].shape, ()) + self.assertEqual(res[2], 9) + self.assertEqual(res[3].shape, (3, 3)) + self.assertEqual(res[3].any(), 1.0) + @prog_scope() def test_top_k(self): x = paddle.full([], 1, 'float32') @@ -3065,29 +3117,6 @@ def test_prelu(self): self.assertEqual(res[4].shape, ()) self.assertEqual(res[5].shape, ()) - def test_static_nn_prelu(self): - x1 = paddle.full([], 1.0, 'float32') - x1.stop_gradient = False - out1 = paddle.static.nn.prelu(x1, 'all') - paddle.static.append_backward(out1.sum()) - - prog = paddle.static.default_main_program() - self.exe.run(paddle.static.default_startup_program()) - res = self.exe.run( - prog, - fetch_list=[ - out1, - x1.grad_name, - out1.grad_name, - ], - ) - - self.assertEqual(res[0].shape, ()) - self.assertEqual(res[1].shape, ()) - self.assertEqual(res[2].shape, ()) - np.testing.assert_allclose(res[0], np.array(1)) - np.testing.assert_allclose(res[1], np.array(1)) - @prog_scope() def test_while_loop(self): def cond(i, x): From 27ea99f9073bba5ebe4688135b650c73f46a3fb3 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Thu, 23 Feb 2023 02:53:48 +0000 Subject: [PATCH 17/24] fix 0D --- paddle/phi/kernels/cpu/top_k_kernel.cc | 3 +- paddle/phi/kernels/gpu/top_k_kernel.cu | 3 +- paddle/phi/kernels/xpu/expand_kernel.cc | 2 +- paddle/phi/kernels/xpu/top_k_kernel.cc | 3 + .../tests/unittests/test_zero_dim_tensor.py | 49 +++++++++-- .../unittests/xpu/test_zero_dim_tensor_xpu.py | 83 ++++++++++++++++--- 6 files changed, 118 insertions(+), 25 deletions(-) diff --git a/paddle/phi/kernels/cpu/top_k_kernel.cc b/paddle/phi/kernels/cpu/top_k_kernel.cc index 25e5b08bc13c9..2f26b1016cef1 100644 --- a/paddle/phi/kernels/cpu/top_k_kernel.cc +++ b/paddle/phi/kernels/cpu/top_k_kernel.cc @@ -143,8 +143,7 @@ void TopkKernel(const Context& dev_ctx, // 0d input x if (in_dims.size() == 0) { phi::Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); - int64_t* indices_data = dev_ctx.template Alloc(indices); - indices_data[0] = 0; + phi::funcs::set_constant(dev_ctx, indices, 0); return; } // axis < 0, cacluate the real axis diff --git a/paddle/phi/kernels/gpu/top_k_kernel.cu b/paddle/phi/kernels/gpu/top_k_kernel.cu index 03f675bc47af7..d6681317be216 100644 --- a/paddle/phi/kernels/gpu/top_k_kernel.cu +++ b/paddle/phi/kernels/gpu/top_k_kernel.cu @@ -65,8 +65,7 @@ void TopkKernel(const Context& dev_ctx, // 0d input tensor if (in_dims.size() == 0) { phi::Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); - int64_t* indices_data = dev_ctx.template Alloc(indices); - indices_data = 0; + phi::funcs::set_constant(dev_ctx, indices, 0); return; } // calcluate the real axis diff --git a/paddle/phi/kernels/xpu/expand_kernel.cc b/paddle/phi/kernels/xpu/expand_kernel.cc index b5af94b2b7413..51dfbc25fb88c 100644 --- a/paddle/phi/kernels/xpu/expand_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_kernel.cc @@ -97,7 +97,7 @@ void ExpandKernel(const Context& ctx, if (shape_size == 0) { phi::DDim out_dims = phi::make_ddim(final_expand_shape); out->Resize(out_dims); - context.template Alloc(out); + ctx.template Alloc(out); int r = xpu::copy(ctx.x_context(), reinterpret_cast(x.data()), diff --git a/paddle/phi/kernels/xpu/top_k_kernel.cc b/paddle/phi/kernels/xpu/top_k_kernel.cc index e3effff0f422b..318eb716e637e 100644 --- a/paddle/phi/kernels/xpu/top_k_kernel.cc +++ b/paddle/phi/kernels/xpu/top_k_kernel.cc @@ -55,6 +55,9 @@ void TopkKernel(const Context& dev_ctx, reinterpret_cast(out->data()), x.numel()); PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); + + phi::funcs::set_constant(dev_ctx, indices, 0); + return; } if (axis < 0) axis += in_dims.size(); diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 11999c9ee4949..926306d2d47b4 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -12,6 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Note: +# 0D Tensor indicates that the tensor's dimension is 0 +# 0D Tensor's shape is always [], numel is 1 +# which can be created by paddle.rand([]) + import unittest import numpy as np @@ -1814,24 +1819,29 @@ def test_t(self): self.assertEqual(x.grad.shape, []) def test_prelu(self): - x = paddle.full([], 1.0, 'float32') - x.stop_gradient = False - - w1 = paddle.to_tensor([0.25], dtype='float32') - out1 = paddle.nn.functional.prelu(x, w1) + x1 = paddle.full([], 1.0, 'float32') + x1.stop_gradient = False + w1 = paddle.full([], 0.25, dtype='float32') + out1 = paddle.nn.functional.prelu(x1, w1) out1.retain_grads() out1.backward() self.assertEqual(out1.shape, []) + self.assertEqual(out1.numpy(), 1.0) self.assertEqual(out1.grad.shape, []) - self.assertEqual(x.grad.shape, []) + self.assertEqual(x1.grad.shape, []) + self.assertEqual(x1.grad.numpy(), 1.0) + x2 = paddle.full([], -1.0, 'float32') + x2.stop_gradient = False w2 = paddle.full([], 0.25, dtype='float32') - out2 = paddle.nn.functional.prelu(x, w2) + out2 = paddle.nn.functional.prelu(x2, w2) out2.retain_grads() out2.backward() self.assertEqual(out2.shape, []) + self.assertEqual(out2.numpy(), -0.25) self.assertEqual(out2.grad.shape, []) - self.assertEqual(x.grad.shape, []) + self.assertEqual(x2.grad.shape, []) + self.assertEqual(x2.grad.numpy(), 0.25) def test_while_loop(self): def cond(i, x): @@ -3099,6 +3109,29 @@ def test_prelu(self): self.assertEqual(res[4].shape, ()) self.assertEqual(res[5].shape, ()) + def test_static_nn_prelu(self): + x1 = paddle.full([], 1.0, 'float32') + x1.stop_gradient = False + out1 = paddle.static.nn.prelu(x1, 'all') + paddle.static.append_backward(out1.sum()) + + prog = paddle.static.default_main_program() + self.exe.run(paddle.static.default_startup_program()) + res = self.exe.run( + prog, + fetch_list=[ + out1, + x1.grad_name, + out1.grad_name, + ], + ) + + self.assertEqual(res[0].shape, ()) + self.assertEqual(res[1].shape, ()) + self.assertEqual(res[2].shape, ()) + np.testing.assert_allclose(res[0], np.array(1)) + np.testing.assert_allclose(res[1], np.array(1)) + @prog_scope() def test_while_loop(self): def cond(i, x): diff --git a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py index ffd2ef8d0e2da..f25b7716ab274 100644 --- a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py +++ b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py @@ -331,29 +331,61 @@ def setUp(self): self.x = paddle.rand([]) def test_expand(self): + # case1 x = paddle.full([], 1, 'float32') x.stop_gradient = False out = paddle.expand(x, shape=[1]) + out.retain_grads() out.backward() - self.assertEqual(x.shape, []) - self.assertEqual(x.item(), 1.0) - self.assertEqual(x.grad.shape, []) - self.assertEqual(x.grad.item(0), 1.0) + self.assertEqual(out.shape, [1]) - self.assertEqual(out.item(0), 1.0) - # self.assertEqual(out.grad, None) + np.testing.assert_allclose(out, 1.0) + self.assertEqual(x.grad.shape, []) + np.testing.assert_allclose(x.grad, 1.0) + self.assertEqual(out.grad.shape, [1]) + np.testing.assert_allclose(out.grad, 1.0) + # case2 x1 = paddle.full([], 1, 'float32') x1.stop_gradient = False out1 = paddle.expand(x1, shape=[]) + out1.retain_grads() out1.backward() - self.assertEqual(x1.shape, []) - self.assertEqual(x1.item(), 1.0) - self.assertEqual(x1.grad.shape, []) - self.assertEqual(x1.grad.item(), 1.0) + self.assertEqual(out1.shape, []) - self.assertEqual(out1.item(), 1.0) - self.assertEqual(out1.grad, None) + np.testing.assert_allclose(out1, 1.0) + self.assertEqual(x1.grad.shape, []) + np.testing.assert_allclose(x1.grad, 1.0) + self.assertEqual(out1.grad.shape, []) + np.testing.assert_allclose(out1.grad, 1.0) + + # case3 + x2 = paddle.full([], 1, 'float32') + x2.stop_gradient = False + out2 = paddle.expand(x2, shape=[1, 1]) + out2.retain_grads() + out2.backward() + + self.assertEqual(out2.shape, [1, 1]) + np.testing.assert_allclose(out2, 1.0) + self.assertEqual(x2.grad.shape, []) + np.testing.assert_allclose(x2.grad, 1.0) + self.assertEqual(out2.grad.shape, [1, 1]) + np.testing.assert_allclose(out2.grad, 1.0) + + # case4 + x3 = paddle.full([], 1, 'float32') + x3.stop_gradient = False + out3 = paddle.expand(x3, shape=[3, 3]) + out3.retain_grads() + out3.backward() + + self.assertEqual(out3.shape, [3, 3]) + np.testing.assert_allclose(out3, 1.0) + self.assertEqual(x3.grad.shape, []) + np.testing.assert_allclose(x3.grad, 9.0) + self.assertEqual(out3.grad.shape, [3, 3]) + np.testing.assert_allclose(out3.grad, 1.0) def test_expand_as(self): x = paddle.full([], 1, 'float32') @@ -383,22 +415,49 @@ def test_expand_as(self): self.assertEqual(out1.item(0), 1.0) self.assertEqual(out1.grad, None) + x2 = paddle.full([], 1, 'float32') + x2.stop_gradient = False + y2 = paddle.full([3, 3], 1, 'float32') + out2 = paddle.expand_as(x2, y2) + out2.backward() + self.assertEqual(x2.shape, []) + self.assertEqual(x2.item(), 1.0) + self.assertEqual(x2.grad.shape, []) + self.assertEqual(x2.grad.item(0), 9.0) + self.assertEqual(out2.shape, [3, 3]) + self.assertEqual(out2.item(0), 1.0) + self.assertEqual(out2.grad, None) + def test_top_k(self): x = paddle.full([], 1, 'float32') x.stop_gradient = False out, indices = paddle.topk(x, k=1, axis=0) + out.retain_grads() + out.backward() + self.assertEqual(indices.shape, []) + self.assertEqual(indices.item(), 0) self.assertEqual(x.shape, []) self.assertEqual(x.item(), 1.0) + self.assertEqual(x.grad.shape, []) + self.assertEqual(x.grad.item(0), 1.0) self.assertEqual(out.shape, []) self.assertEqual(out.item(), 1.0) + self.assertEqual(out.grad, 1.0) x1 = paddle.full([], 1, 'float32') x1.stop_gradient = False out1, indices1 = paddle.topk(x1, k=1, axis=-1) + out1.retain_grads() + out1.backward() + self.assertEqual(indices1.shape, []) + self.assertEqual(indices1.item(), 0) self.assertEqual(x1.shape, []) self.assertEqual(x1.item(), 1.0) + self.assertEqual(x.grad.shape, []) + self.assertEqual(x.grad.item(0), 1.0) self.assertEqual(out1.shape, []) self.assertEqual(out1.item(), 1.0) + self.assertEqual(out1.grad, 1.0) with self.assertRaises(ValueError): tmp = paddle.topk(x1, k=1, axis=2) From 29f368f75aa497e19a32f4371a30701ceb1b4039 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Thu, 23 Feb 2023 09:20:52 +0000 Subject: [PATCH 18/24] fix 0D --- paddle/phi/kernels/cpu/top_k_kernel.cc | 3 ++- paddle/phi/kernels/gpu/top_k_kernel.cu | 3 ++- .../tests/unittests/test_zero_dim_tensor.py | 21 +++++++++++++-- python/paddle/tensor/manipulation.py | 26 +++++++++---------- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/paddle/phi/kernels/cpu/top_k_kernel.cc b/paddle/phi/kernels/cpu/top_k_kernel.cc index 2f26b1016cef1..3e2a2ac2a75be 100644 --- a/paddle/phi/kernels/cpu/top_k_kernel.cc +++ b/paddle/phi/kernels/cpu/top_k_kernel.cc @@ -143,7 +143,8 @@ void TopkKernel(const Context& dev_ctx, // 0d input x if (in_dims.size() == 0) { phi::Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); - phi::funcs::set_constant(dev_ctx, indices, 0); + dev_ctx.template Alloc(indices); + phi::funcs::set_constant(dev_ctx, indices, 0.0); return; } // axis < 0, cacluate the real axis diff --git a/paddle/phi/kernels/gpu/top_k_kernel.cu b/paddle/phi/kernels/gpu/top_k_kernel.cu index d6681317be216..7a8aede44e9da 100644 --- a/paddle/phi/kernels/gpu/top_k_kernel.cu +++ b/paddle/phi/kernels/gpu/top_k_kernel.cu @@ -65,7 +65,8 @@ void TopkKernel(const Context& dev_ctx, // 0d input tensor if (in_dims.size() == 0) { phi::Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); - phi::funcs::set_constant(dev_ctx, indices, 0); + dev_ctx.template Alloc(indices); + phi::funcs::set_constant(dev_ctx, indices, 0.0); return; } // calcluate the real axis diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 926306d2d47b4..596423a0fd49f 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -275,6 +275,7 @@ def test_static_reduce(self): paddle.fmax, paddle.fmin, paddle.complex, + paddle.kron, ] binary_int_api_list = [ @@ -1995,20 +1996,36 @@ def test_top_k(self): x = paddle.full([], 1, 'float32') out, indices = paddle.topk(x, k=1, axis=0) prog = paddle.static.default_main_program() - res = self.exe.run(prog, fetch_list=[x, out]) + res = self.exe.run( + prog, fetch_list=[x, out, indices, x.grad_name, out.grad_name] + ) self.assertEqual(res[0].shape, ()) self.assertEqual(res[0], 1.0) self.assertEqual(res[1].shape, ()) self.assertEqual(res[1], 1.0) + self.assertEqual(res[2].shape, ()) + self.assertEqual(res[2], 0.0) + self.assertEqual(res[3].shape, ()) + self.assertEqual(res[3], 1.0) + self.assertEqual(res[4].shape, ()) + self.assertEqual(res[4], 1.0) x1 = paddle.full([], 1, 'float32') out1, indices1 = paddle.topk(x1, k=1, axis=-1) prog = paddle.static.default_main_program() - res = self.exe.run(prog, fetch_list=[x1, out1]) + res = self.exe.run( + prog, fetch_list=[x1, out1, indices1, x1.grad, out1.grad] + ) self.assertEqual(res[0].shape, ()) self.assertEqual(res[0], 1.0) self.assertEqual(res[1].shape, ()) self.assertEqual(res[1], 1.0) + self.assertEqual(res[2].shape, ()) + self.assertEqual(res[2], 0.0) + self.assertEqual(res[3].shape, ()) + self.assertEqual(res[3], 1.0) + self.assertEqual(res[4].shape, ()) + self.assertEqual(res[4], 1.0) with self.assertRaises(ValueError): tmp = paddle.topk(x1, k=1, axis=2) diff --git a/python/paddle/tensor/manipulation.py b/python/paddle/tensor/manipulation.py index 8f5999bc19782..e2325fda753a1 100644 --- a/python/paddle/tensor/manipulation.py +++ b/python/paddle/tensor/manipulation.py @@ -3192,7 +3192,7 @@ def expand_as(x, y, name=None): Expand the input tensor ``x`` to the same shape as the input tensor ``y``. - Both the number of dimensions of ``x`` and ``y`` must be less than or equal to 6, and the number of dimensions of ``y`` must be greather than or equal to that of ``x``. The dimension to expand must have a value of 1. + Both the number of dimensions of ``x`` and ``y`` must be less than or equal to 6, and the number of dimensions of ``y`` must be greather than or equal to that of ``x``. The dimension to expand must have a value of 0. Args: x (Tensor): The input tensor, its data type is bool, float32, float64, int32 or int64. @@ -3252,13 +3252,13 @@ def broadcast_to(x, shape, name=None): Broadcast the input tensor to a given shape. - Both the number of dimensions of ``x`` and the number of elements in ``shape`` should be less than or equal to 6. The dimension to broadcast to must have a value 1. + Both the number of dimensions of ``x`` and the number of elements in ``shape`` should be less than or equal to 6. The dimension to broadcast to must have a value 0. Args: x (Tensor): The input tensor, its data type is bool, float32, float64, int32 or int64. shape (list|tuple|Tensor): The result shape after broadcasting. The data type is int32. If shape is a list or tuple, all its elements - should be integers or 1-D Tensors with the data type int32. If shape is a Tensor, it should be an 1-D Tensor with the data type int32. + should be integers or 0-D or 1-D Tensors with the data type int32. If shape is a Tensor, it should be an 1-D Tensor with the data type int32. The value -1 in shape means keeping the corresponding dimension unchanged. name (str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. Returns: @@ -3278,18 +3278,18 @@ def broadcast_to(x, shape, name=None): return _C_ops.expand(x, shape) else: if isinstance(shape, Variable): - assert len(shape.shape) <= 1, 'shape must be an 0-D or 1-D Tensor.' + assert len(shape.shape) == 1, 'shape must be an 1-D Tensor.' else: type_tuple = (int, np.int32, np.int64) for elem in shape: if isinstance(elem, Variable): assert ( - len(elem.shape) <= 1 - ), 'Elements in shape must be 0-D or 1-D Tensors or integers.' + len(elem.shape) == 1 + ), 'Elements in shape must be 1-D Tensors or integers.' else: assert isinstance( elem, type_tuple - ), 'Elements in shape must be 0-D or 1-D Tensors or integers.' + ), 'Elements in shape must be 1-D Tensors or integers.' check_variable_and_dtype( x, @@ -3346,12 +3346,12 @@ def expand(x, shape, name=None): Expand the input tensor to a given shape. - Both the number of dimensions of ``x`` and the number of elements in ``shape`` should be less than or equal to 6. And the number of dimensions of ``x`` should be less than the number of elements in ``shape``. The dimension to expand must have a value 1. + Both the number of dimensions of ``x`` and the number of elements in ``shape`` should be less than or equal to 6. And the number of dimensions of ``x`` should be less than the number of elements in ``shape``. The dimension to expand must have a value 0. Args: x (Tensor): The input Tensor, its data type is bool, float32, float64, int32 or int64. shape (list|tuple|Tensor): The result shape after expanding. The data type is int32. If shape is a list or tuple, all its elements - should be integers or 1-D Tensors with the data type int32. If shape is a Tensor, it should be an 1-D Tensor with the data type int32. + should be integers or 0-D or 1-D Tensors with the data type int32. If shape is a Tensor, it should be an 1-D Tensor with the data type int32. The value -1 in shape means keeping the corresponding dimension unchanged. name (str, optional): The default value is None. Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name` . @@ -3372,18 +3372,18 @@ def expand(x, shape, name=None): return _C_ops.expand(x, shape) else: if isinstance(shape, Variable): - assert len(shape.shape) <= 1, 'shape must be an 0-D or 1-D Tensor.' + assert len(shape.shape) == 1, 'shape must be an 1-D Tensor.' else: for elem in shape: if isinstance(elem, Variable): assert ( - len(elem.shape) <= 1 - ), 'Elements in shape must be 0-D or 1-D Tensors or integers.' + len(elem.shape) == 1 + ), 'Elements in shape must be 1-D Tensors or integers.' else: type_tuple = (int, np.int32, np.int64) assert isinstance( elem, type_tuple - ), 'Elements in shape must be 0-D or 1-D Tensors or integers.' + ), 'Elements in shape must be 1-D Tensors or integers.' check_variable_and_dtype( x, From 46fe2c0045f12270cb3a62601785de438134a290 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Thu, 23 Feb 2023 09:33:33 +0000 Subject: [PATCH 19/24] fix 0D --- paddle/phi/kernels/cpu/top_k_kernel.cc | 2 +- paddle/phi/kernels/gpu/top_k_kernel.cu | 2 +- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/paddle/phi/kernels/cpu/top_k_kernel.cc b/paddle/phi/kernels/cpu/top_k_kernel.cc index 3e2a2ac2a75be..5a5789effadf9 100644 --- a/paddle/phi/kernels/cpu/top_k_kernel.cc +++ b/paddle/phi/kernels/cpu/top_k_kernel.cc @@ -143,7 +143,7 @@ void TopkKernel(const Context& dev_ctx, // 0d input x if (in_dims.size() == 0) { phi::Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); - dev_ctx.template Alloc(indices); + dev_ctx.template Alloc(indices); phi::funcs::set_constant(dev_ctx, indices, 0.0); return; } diff --git a/paddle/phi/kernels/gpu/top_k_kernel.cu b/paddle/phi/kernels/gpu/top_k_kernel.cu index 7a8aede44e9da..01bae0dd96cc5 100644 --- a/paddle/phi/kernels/gpu/top_k_kernel.cu +++ b/paddle/phi/kernels/gpu/top_k_kernel.cu @@ -65,7 +65,7 @@ void TopkKernel(const Context& dev_ctx, // 0d input tensor if (in_dims.size() == 0) { phi::Copy(dev_ctx, x, dev_ctx.GetPlace(), false, out); - dev_ctx.template Alloc(indices); + dev_ctx.template Alloc(indices); phi::funcs::set_constant(dev_ctx, indices, 0.0); return; } diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 596423a0fd49f..2a3213f54624b 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -1994,7 +1994,9 @@ def test_expand_as(self): @prog_scope() def test_top_k(self): x = paddle.full([], 1, 'float32') + x.stop_gradient = False out, indices = paddle.topk(x, k=1, axis=0) + paddle.static.append_backward(out.sum()) prog = paddle.static.default_main_program() res = self.exe.run( prog, fetch_list=[x, out, indices, x.grad_name, out.grad_name] @@ -2011,7 +2013,9 @@ def test_top_k(self): self.assertEqual(res[4], 1.0) x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False out1, indices1 = paddle.topk(x1, k=1, axis=-1) + paddle.static.append_backward(out1.sum()) prog = paddle.static.default_main_program() res = self.exe.run( prog, fetch_list=[x1, out1, indices1, x1.grad, out1.grad] From 8a1a6f47db5f55f50f31718d2696c59e8827d638 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Thu, 23 Feb 2023 10:33:42 +0000 Subject: [PATCH 20/24] fix 0D --- python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py index 2a3213f54624b..fd48cd3722624 100644 --- a/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py +++ b/python/paddle/fluid/tests/unittests/test_zero_dim_tensor.py @@ -2018,7 +2018,7 @@ def test_top_k(self): paddle.static.append_backward(out1.sum()) prog = paddle.static.default_main_program() res = self.exe.run( - prog, fetch_list=[x1, out1, indices1, x1.grad, out1.grad] + prog, fetch_list=[x1, out1, indices1, x1.grad_name, out1.grad_name] ) self.assertEqual(res[0].shape, ()) self.assertEqual(res[0], 1.0) From 7d8a63008243fcfb862912c08f107cbad55a1165 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Fri, 24 Feb 2023 02:26:52 +0000 Subject: [PATCH 21/24] fix XPU top_k --- paddle/phi/kernels/xpu/top_k_kernel.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/phi/kernels/xpu/top_k_kernel.cc b/paddle/phi/kernels/xpu/top_k_kernel.cc index 318eb716e637e..1ed20b0ddf22d 100644 --- a/paddle/phi/kernels/xpu/top_k_kernel.cc +++ b/paddle/phi/kernels/xpu/top_k_kernel.cc @@ -16,7 +16,7 @@ #include "paddle/phi/backends/xpu/enforce_xpu.h" #include "paddle/phi/core/kernel_registry.h" - +#include "paddle/phi/kernels/funcs/math_function.h" namespace phi { template From 3d376f866638ea9b5c265b9745ffedca26470f45 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Fri, 24 Feb 2023 07:34:54 +0000 Subject: [PATCH 22/24] cancel the modify of xpu --- paddle/phi/kernels/xpu/expand_as_kernel.cc | 18 +-- paddle/phi/kernels/xpu/expand_kernel.cc | 17 +-- paddle/phi/kernels/xpu/top_k_kernel.cc | 12 +- .../unittests/xpu/test_zero_dim_tensor_xpu.py | 132 ------------------ 4 files changed, 3 insertions(+), 176 deletions(-) diff --git a/paddle/phi/kernels/xpu/expand_as_kernel.cc b/paddle/phi/kernels/xpu/expand_as_kernel.cc index 0e4a5ca5c270b..1427c61f4503b 100644 --- a/paddle/phi/kernels/xpu/expand_as_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_as_kernel.cc @@ -49,26 +49,10 @@ void ExpandAs(const Context& context, target_shape[i])); } } - if (target_shape.size() == 0) { - phi::DDim out_dims = phi::make_ddim(target_shape); - out->Resize(out_dims); - context.template Alloc(out); - - int r = xpu::copy(context.x_context(), - reinterpret_cast(x.data()), - reinterpret_cast(out->data()), - x.numel()); - PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); - return; - } - phi::DDim out_dims = phi::make_ddim(target_shape); out->Resize(out_dims); context.template Alloc(out); auto& x_shape = vec_in_dims; - if (x.dims().size() == 0) { - x_shape = std::vector({1}); - } auto out_shape = phi::vectorize(out_dims); int r = XPU_SUCCESS; @@ -111,7 +95,7 @@ void ExpandAsKernel(const Context& ctx, rank)); PADDLE_ENFORCE_GE( rank, - 0, + 1, phi::errors::InvalidArgument("The rank (%d) of the input 'x' for " "expand_as_v2 op must be positive.", rank)); diff --git a/paddle/phi/kernels/xpu/expand_kernel.cc b/paddle/phi/kernels/xpu/expand_kernel.cc index 51dfbc25fb88c..d356737e3df4b 100644 --- a/paddle/phi/kernels/xpu/expand_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_kernel.cc @@ -78,7 +78,7 @@ void ExpandKernel(const Context& ctx, auto rank = x.dims().size(); PADDLE_ENFORCE_GE( rank, - 0, + 1, phi::errors::InvalidArgument( "The rank of the input 'X' for expand_v2_npu op must be positive, " "but the value received is %d.", @@ -94,25 +94,10 @@ void ExpandKernel(const Context& ctx, shape_size, rank)); - if (shape_size == 0) { - phi::DDim out_dims = phi::make_ddim(final_expand_shape); - out->Resize(out_dims); - ctx.template Alloc(out); - - int r = xpu::copy(ctx.x_context(), - reinterpret_cast(x.data()), - reinterpret_cast(out->data()), - x.numel()); - PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); - return; - } DDim out_dims = phi::make_ddim(final_expand_shape); out->Resize(out_dims); ctx.template Alloc(out); auto& x_shape = vec_in_dims; - if (rank == 0) { - x_shape = std::vector({1}); - } auto out_shape = phi::vectorize(out_dims); int r = XPU_SUCCESS; diff --git a/paddle/phi/kernels/xpu/top_k_kernel.cc b/paddle/phi/kernels/xpu/top_k_kernel.cc index 1ed20b0ddf22d..74cda9e0102df 100644 --- a/paddle/phi/kernels/xpu/top_k_kernel.cc +++ b/paddle/phi/kernels/xpu/top_k_kernel.cc @@ -16,7 +16,7 @@ #include "paddle/phi/backends/xpu/enforce_xpu.h" #include "paddle/phi/core/kernel_registry.h" -#include "paddle/phi/kernels/funcs/math_function.h" + namespace phi { template @@ -49,17 +49,7 @@ void TopkKernel(const Context& dev_ctx, errors::External( "XPU API does not support smallest topk operation currently." " Operator will be supported in future update.")); - if (in_dims.size() == 0) { - int r = xpu::copy(dev_ctx.x_context(), - reinterpret_cast(x.data()), - reinterpret_cast(out->data()), - x.numel()); - PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); - - phi::funcs::set_constant(dev_ctx, indices, 0); - return; - } if (axis < 0) axis += in_dims.size(); size_t k = k_scalar.to(); diff --git a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py index f25b7716ab274..ea54f5b26388e 100644 --- a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py +++ b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py @@ -330,138 +330,6 @@ def setUp(self): paddle.disable_static() self.x = paddle.rand([]) - def test_expand(self): - # case1 - x = paddle.full([], 1, 'float32') - x.stop_gradient = False - out = paddle.expand(x, shape=[1]) - out.retain_grads() - out.backward() - - self.assertEqual(out.shape, [1]) - np.testing.assert_allclose(out, 1.0) - self.assertEqual(x.grad.shape, []) - np.testing.assert_allclose(x.grad, 1.0) - self.assertEqual(out.grad.shape, [1]) - np.testing.assert_allclose(out.grad, 1.0) - - # case2 - x1 = paddle.full([], 1, 'float32') - x1.stop_gradient = False - out1 = paddle.expand(x1, shape=[]) - out1.retain_grads() - out1.backward() - - self.assertEqual(out1.shape, []) - np.testing.assert_allclose(out1, 1.0) - self.assertEqual(x1.grad.shape, []) - np.testing.assert_allclose(x1.grad, 1.0) - self.assertEqual(out1.grad.shape, []) - np.testing.assert_allclose(out1.grad, 1.0) - - # case3 - x2 = paddle.full([], 1, 'float32') - x2.stop_gradient = False - out2 = paddle.expand(x2, shape=[1, 1]) - out2.retain_grads() - out2.backward() - - self.assertEqual(out2.shape, [1, 1]) - np.testing.assert_allclose(out2, 1.0) - self.assertEqual(x2.grad.shape, []) - np.testing.assert_allclose(x2.grad, 1.0) - self.assertEqual(out2.grad.shape, [1, 1]) - np.testing.assert_allclose(out2.grad, 1.0) - - # case4 - x3 = paddle.full([], 1, 'float32') - x3.stop_gradient = False - out3 = paddle.expand(x3, shape=[3, 3]) - out3.retain_grads() - out3.backward() - - self.assertEqual(out3.shape, [3, 3]) - np.testing.assert_allclose(out3, 1.0) - self.assertEqual(x3.grad.shape, []) - np.testing.assert_allclose(x3.grad, 9.0) - self.assertEqual(out3.grad.shape, [3, 3]) - np.testing.assert_allclose(out3.grad, 1.0) - - def test_expand_as(self): - x = paddle.full([], 1, 'float32') - x.stop_gradient = False - y = paddle.full([], 1, 'float32') - y.stop_gradient = False - out = paddle.expand_as(x, y) - out.backward() - self.assertEqual(x.shape, []) - self.assertEqual(x.item(), 1.0) - self.assertEqual(x.grad.shape, []) - self.assertEqual(x.grad.item(), 1.0) - self.assertEqual(out.shape, []) - self.assertEqual(out.item(), 1.0) - self.assertEqual(out.grad, None) - - x1 = paddle.full([], 1, 'float32') - x1.stop_gradient = False - y1 = paddle.full([1], 1, 'float32') - out1 = paddle.expand_as(x1, y1) - out1.backward() - self.assertEqual(x1.shape, []) - self.assertEqual(x1.item(), 1.0) - self.assertEqual(x1.grad.shape, []) - self.assertEqual(x1.grad.item(0), 1.0) - self.assertEqual(out1.shape, [1]) - self.assertEqual(out1.item(0), 1.0) - self.assertEqual(out1.grad, None) - - x2 = paddle.full([], 1, 'float32') - x2.stop_gradient = False - y2 = paddle.full([3, 3], 1, 'float32') - out2 = paddle.expand_as(x2, y2) - out2.backward() - self.assertEqual(x2.shape, []) - self.assertEqual(x2.item(), 1.0) - self.assertEqual(x2.grad.shape, []) - self.assertEqual(x2.grad.item(0), 9.0) - self.assertEqual(out2.shape, [3, 3]) - self.assertEqual(out2.item(0), 1.0) - self.assertEqual(out2.grad, None) - - def test_top_k(self): - x = paddle.full([], 1, 'float32') - x.stop_gradient = False - out, indices = paddle.topk(x, k=1, axis=0) - out.retain_grads() - out.backward() - self.assertEqual(indices.shape, []) - self.assertEqual(indices.item(), 0) - self.assertEqual(x.shape, []) - self.assertEqual(x.item(), 1.0) - self.assertEqual(x.grad.shape, []) - self.assertEqual(x.grad.item(0), 1.0) - self.assertEqual(out.shape, []) - self.assertEqual(out.item(), 1.0) - self.assertEqual(out.grad, 1.0) - - x1 = paddle.full([], 1, 'float32') - x1.stop_gradient = False - out1, indices1 = paddle.topk(x1, k=1, axis=-1) - out1.retain_grads() - out1.backward() - self.assertEqual(indices1.shape, []) - self.assertEqual(indices1.item(), 0) - self.assertEqual(x1.shape, []) - self.assertEqual(x1.item(), 1.0) - self.assertEqual(x.grad.shape, []) - self.assertEqual(x.grad.item(0), 1.0) - self.assertEqual(out1.shape, []) - self.assertEqual(out1.item(), 1.0) - self.assertEqual(out1.grad, 1.0) - - with self.assertRaises(ValueError): - tmp = paddle.topk(x1, k=1, axis=2) - def test_argmin(self): x = paddle.rand([]) out1 = paddle.argmin(x, 0) From da37b677ec93f5e5cb30608658dd7b29b37aa69b Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Mon, 27 Feb 2023 02:11:26 +0000 Subject: [PATCH 23/24] add XPU 0D tensor --- paddle/phi/kernels/xpu/expand_as_kernel.cc | 18 ++- paddle/phi/kernels/xpu/expand_kernel.cc | 17 ++- paddle/phi/kernels/xpu/top_k_kernel.cc | 12 +- .../unittests/xpu/test_zero_dim_tensor_xpu.py | 132 ++++++++++++++++++ 4 files changed, 176 insertions(+), 3 deletions(-) diff --git a/paddle/phi/kernels/xpu/expand_as_kernel.cc b/paddle/phi/kernels/xpu/expand_as_kernel.cc index 1427c61f4503b..0e4a5ca5c270b 100644 --- a/paddle/phi/kernels/xpu/expand_as_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_as_kernel.cc @@ -49,10 +49,26 @@ void ExpandAs(const Context& context, target_shape[i])); } } + if (target_shape.size() == 0) { + phi::DDim out_dims = phi::make_ddim(target_shape); + out->Resize(out_dims); + context.template Alloc(out); + + int r = xpu::copy(context.x_context(), + reinterpret_cast(x.data()), + reinterpret_cast(out->data()), + x.numel()); + PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); + return; + } + phi::DDim out_dims = phi::make_ddim(target_shape); out->Resize(out_dims); context.template Alloc(out); auto& x_shape = vec_in_dims; + if (x.dims().size() == 0) { + x_shape = std::vector({1}); + } auto out_shape = phi::vectorize(out_dims); int r = XPU_SUCCESS; @@ -95,7 +111,7 @@ void ExpandAsKernel(const Context& ctx, rank)); PADDLE_ENFORCE_GE( rank, - 1, + 0, phi::errors::InvalidArgument("The rank (%d) of the input 'x' for " "expand_as_v2 op must be positive.", rank)); diff --git a/paddle/phi/kernels/xpu/expand_kernel.cc b/paddle/phi/kernels/xpu/expand_kernel.cc index d356737e3df4b..51dfbc25fb88c 100644 --- a/paddle/phi/kernels/xpu/expand_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_kernel.cc @@ -78,7 +78,7 @@ void ExpandKernel(const Context& ctx, auto rank = x.dims().size(); PADDLE_ENFORCE_GE( rank, - 1, + 0, phi::errors::InvalidArgument( "The rank of the input 'X' for expand_v2_npu op must be positive, " "but the value received is %d.", @@ -94,10 +94,25 @@ void ExpandKernel(const Context& ctx, shape_size, rank)); + if (shape_size == 0) { + phi::DDim out_dims = phi::make_ddim(final_expand_shape); + out->Resize(out_dims); + ctx.template Alloc(out); + + int r = xpu::copy(ctx.x_context(), + reinterpret_cast(x.data()), + reinterpret_cast(out->data()), + x.numel()); + PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); + return; + } DDim out_dims = phi::make_ddim(final_expand_shape); out->Resize(out_dims); ctx.template Alloc(out); auto& x_shape = vec_in_dims; + if (rank == 0) { + x_shape = std::vector({1}); + } auto out_shape = phi::vectorize(out_dims); int r = XPU_SUCCESS; diff --git a/paddle/phi/kernels/xpu/top_k_kernel.cc b/paddle/phi/kernels/xpu/top_k_kernel.cc index 74cda9e0102df..1ed20b0ddf22d 100644 --- a/paddle/phi/kernels/xpu/top_k_kernel.cc +++ b/paddle/phi/kernels/xpu/top_k_kernel.cc @@ -16,7 +16,7 @@ #include "paddle/phi/backends/xpu/enforce_xpu.h" #include "paddle/phi/core/kernel_registry.h" - +#include "paddle/phi/kernels/funcs/math_function.h" namespace phi { template @@ -49,7 +49,17 @@ void TopkKernel(const Context& dev_ctx, errors::External( "XPU API does not support smallest topk operation currently." " Operator will be supported in future update.")); + if (in_dims.size() == 0) { + int r = xpu::copy(dev_ctx.x_context(), + reinterpret_cast(x.data()), + reinterpret_cast(out->data()), + x.numel()); + PADDLE_ENFORCE_XDNN_SUCCESS(r, "copy"); + + phi::funcs::set_constant(dev_ctx, indices, 0); + return; + } if (axis < 0) axis += in_dims.size(); size_t k = k_scalar.to(); diff --git a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py index ea54f5b26388e..f25b7716ab274 100644 --- a/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py +++ b/python/paddle/fluid/tests/unittests/xpu/test_zero_dim_tensor_xpu.py @@ -330,6 +330,138 @@ def setUp(self): paddle.disable_static() self.x = paddle.rand([]) + def test_expand(self): + # case1 + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + out = paddle.expand(x, shape=[1]) + out.retain_grads() + out.backward() + + self.assertEqual(out.shape, [1]) + np.testing.assert_allclose(out, 1.0) + self.assertEqual(x.grad.shape, []) + np.testing.assert_allclose(x.grad, 1.0) + self.assertEqual(out.grad.shape, [1]) + np.testing.assert_allclose(out.grad, 1.0) + + # case2 + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + out1 = paddle.expand(x1, shape=[]) + out1.retain_grads() + out1.backward() + + self.assertEqual(out1.shape, []) + np.testing.assert_allclose(out1, 1.0) + self.assertEqual(x1.grad.shape, []) + np.testing.assert_allclose(x1.grad, 1.0) + self.assertEqual(out1.grad.shape, []) + np.testing.assert_allclose(out1.grad, 1.0) + + # case3 + x2 = paddle.full([], 1, 'float32') + x2.stop_gradient = False + out2 = paddle.expand(x2, shape=[1, 1]) + out2.retain_grads() + out2.backward() + + self.assertEqual(out2.shape, [1, 1]) + np.testing.assert_allclose(out2, 1.0) + self.assertEqual(x2.grad.shape, []) + np.testing.assert_allclose(x2.grad, 1.0) + self.assertEqual(out2.grad.shape, [1, 1]) + np.testing.assert_allclose(out2.grad, 1.0) + + # case4 + x3 = paddle.full([], 1, 'float32') + x3.stop_gradient = False + out3 = paddle.expand(x3, shape=[3, 3]) + out3.retain_grads() + out3.backward() + + self.assertEqual(out3.shape, [3, 3]) + np.testing.assert_allclose(out3, 1.0) + self.assertEqual(x3.grad.shape, []) + np.testing.assert_allclose(x3.grad, 9.0) + self.assertEqual(out3.grad.shape, [3, 3]) + np.testing.assert_allclose(out3.grad, 1.0) + + def test_expand_as(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + y = paddle.full([], 1, 'float32') + y.stop_gradient = False + out = paddle.expand_as(x, y) + out.backward() + self.assertEqual(x.shape, []) + self.assertEqual(x.item(), 1.0) + self.assertEqual(x.grad.shape, []) + self.assertEqual(x.grad.item(), 1.0) + self.assertEqual(out.shape, []) + self.assertEqual(out.item(), 1.0) + self.assertEqual(out.grad, None) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + y1 = paddle.full([1], 1, 'float32') + out1 = paddle.expand_as(x1, y1) + out1.backward() + self.assertEqual(x1.shape, []) + self.assertEqual(x1.item(), 1.0) + self.assertEqual(x1.grad.shape, []) + self.assertEqual(x1.grad.item(0), 1.0) + self.assertEqual(out1.shape, [1]) + self.assertEqual(out1.item(0), 1.0) + self.assertEqual(out1.grad, None) + + x2 = paddle.full([], 1, 'float32') + x2.stop_gradient = False + y2 = paddle.full([3, 3], 1, 'float32') + out2 = paddle.expand_as(x2, y2) + out2.backward() + self.assertEqual(x2.shape, []) + self.assertEqual(x2.item(), 1.0) + self.assertEqual(x2.grad.shape, []) + self.assertEqual(x2.grad.item(0), 9.0) + self.assertEqual(out2.shape, [3, 3]) + self.assertEqual(out2.item(0), 1.0) + self.assertEqual(out2.grad, None) + + def test_top_k(self): + x = paddle.full([], 1, 'float32') + x.stop_gradient = False + out, indices = paddle.topk(x, k=1, axis=0) + out.retain_grads() + out.backward() + self.assertEqual(indices.shape, []) + self.assertEqual(indices.item(), 0) + self.assertEqual(x.shape, []) + self.assertEqual(x.item(), 1.0) + self.assertEqual(x.grad.shape, []) + self.assertEqual(x.grad.item(0), 1.0) + self.assertEqual(out.shape, []) + self.assertEqual(out.item(), 1.0) + self.assertEqual(out.grad, 1.0) + + x1 = paddle.full([], 1, 'float32') + x1.stop_gradient = False + out1, indices1 = paddle.topk(x1, k=1, axis=-1) + out1.retain_grads() + out1.backward() + self.assertEqual(indices1.shape, []) + self.assertEqual(indices1.item(), 0) + self.assertEqual(x1.shape, []) + self.assertEqual(x1.item(), 1.0) + self.assertEqual(x.grad.shape, []) + self.assertEqual(x.grad.item(0), 1.0) + self.assertEqual(out1.shape, []) + self.assertEqual(out1.item(), 1.0) + self.assertEqual(out1.grad, 1.0) + + with self.assertRaises(ValueError): + tmp = paddle.topk(x1, k=1, axis=2) + def test_argmin(self): x = paddle.rand([]) out1 = paddle.argmin(x, 0) From 32508f3f09f32e264799e75144833e6306c823d8 Mon Sep 17 00:00:00 2001 From: yunyaoXYY Date: Tue, 28 Feb 2023 11:31:17 +0000 Subject: [PATCH 24/24] fix 0D --- paddle/phi/kernels/xpu/expand_as_kernel.cc | 4 ---- paddle/phi/kernels/xpu/expand_grad_kernel.cc | 5 +++++ paddle/phi/kernels/xpu/expand_kernel.cc | 3 --- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/paddle/phi/kernels/xpu/expand_as_kernel.cc b/paddle/phi/kernels/xpu/expand_as_kernel.cc index 0e4a5ca5c270b..ae72b85bf06b1 100644 --- a/paddle/phi/kernels/xpu/expand_as_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_as_kernel.cc @@ -31,7 +31,6 @@ void ExpandAs(const Context& context, auto vec_in_dims = phi::vectorize(in_dims); auto diff = target_shape.size() - vec_in_dims.size(); vec_in_dims.insert(vec_in_dims.begin(), diff, 1); - for (size_t i = 0; i < vec_in_dims.size(); ++i) { PADDLE_ENFORCE_NE(target_shape[i], 0, @@ -66,9 +65,6 @@ void ExpandAs(const Context& context, out->Resize(out_dims); context.template Alloc(out); auto& x_shape = vec_in_dims; - if (x.dims().size() == 0) { - x_shape = std::vector({1}); - } auto out_shape = phi::vectorize(out_dims); int r = XPU_SUCCESS; diff --git a/paddle/phi/kernels/xpu/expand_grad_kernel.cc b/paddle/phi/kernels/xpu/expand_grad_kernel.cc index 565afd95366cb..52fc0fd38f1f8 100644 --- a/paddle/phi/kernels/xpu/expand_grad_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_grad_kernel.cc @@ -35,6 +35,11 @@ void ExpandGradKernel(const Context& ctx, in_grad_dims.insert( in_grad_dims.begin(), out_grad.dims().size() - in_grad->dims().size(), 1); + // Two zero + if (out_grad_dims.size() == 0 && in_grad_dims.size() == 0) { + return; + } + int r = xpu::expand_grad( ctx.x_context(), reinterpret_cast(out_grad.data()), diff --git a/paddle/phi/kernels/xpu/expand_kernel.cc b/paddle/phi/kernels/xpu/expand_kernel.cc index 51dfbc25fb88c..10b8c18e9d33a 100644 --- a/paddle/phi/kernels/xpu/expand_kernel.cc +++ b/paddle/phi/kernels/xpu/expand_kernel.cc @@ -110,9 +110,6 @@ void ExpandKernel(const Context& ctx, out->Resize(out_dims); ctx.template Alloc(out); auto& x_shape = vec_in_dims; - if (rank == 0) { - x_shape = std::vector({1}); - } auto out_shape = phi::vectorize(out_dims); int r = XPU_SUCCESS;