diff --git a/paddle/phi/kernels/xpu/expand_as_kernel.cc b/paddle/phi/kernels/xpu/expand_as_kernel.cc index 1427c61f4503b..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, @@ -49,6 +48,19 @@ 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); @@ -95,7 +107,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_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 d356737e3df4b..10b8c18e9d33a 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,6 +94,18 @@ 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); 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)