From 5c5536cb9a977e50d54aeb811306f5351008d7b8 Mon Sep 17 00:00:00 2001 From: RedContritio Date: Mon, 13 Feb 2023 11:36:18 +0800 Subject: [PATCH] Fix div 0 error of case25: paddle.dot (#50014) * support size 0 dot input * prevent div 0 in grad * add unittest * remove unnecessary vlog * add unittests --- paddle/phi/kernels/cpu/dot_kernel.cc | 8 +- .../phi/kernels/impl/dot_grad_kernel_impl.h | 88 +++++++++++++------ .../fluid/tests/unittests/test_dot_op.py | 26 ++++++ 3 files changed, 92 insertions(+), 30 deletions(-) diff --git a/paddle/phi/kernels/cpu/dot_kernel.cc b/paddle/phi/kernels/cpu/dot_kernel.cc index 3518501a6b6..5fc3d299a6b 100644 --- a/paddle/phi/kernels/cpu/dot_kernel.cc +++ b/paddle/phi/kernels/cpu/dot_kernel.cc @@ -35,7 +35,13 @@ void DotKernel(const Context& dev_ctx, // B pairs along the way where B is the dimension of the least ordered axis auto&& d = x.dims(); auto const N = x.numel(); - auto const B = d[d.size() - 1]; + + // prevent div 0 + auto const _B = d.size() == 0 ? 1 : d[d.size() - 1]; + auto const B = _B != 0 ? _B : 1; + + // initialize for N / B <= 0 + z[0] = 0; for (int j = 0; j < N / B; j++) { T ss = 0; diff --git a/paddle/phi/kernels/impl/dot_grad_kernel_impl.h b/paddle/phi/kernels/impl/dot_grad_kernel_impl.h index a9b6b27d0ec..7e49465ec61 100644 --- a/paddle/phi/kernels/impl/dot_grad_kernel_impl.h +++ b/paddle/phi/kernels/impl/dot_grad_kernel_impl.h @@ -42,6 +42,7 @@ struct DotGradFunction> { const DenseTensor* tensor_dout, DenseTensor* tensor_dx, DenseTensor* tensor_dy) { + VLOG(1) << "enable route"; #if defined(__NVCC__) || defined(__HIPCC__) if (1 == tensor_dout->dims().size()) { auto dout = EigenVector::Flatten(*tensor_dout); @@ -103,7 +104,8 @@ struct DotGradFunction> { const DDim& dim = tensor_x->dims(); size_t N = static_cast(phi::product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { @@ -118,7 +120,8 @@ struct DotGradFunction> { const DDim& dim = tensor_y->dims(); size_t N = static_cast(phi::product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { @@ -182,7 +185,8 @@ struct DotGradFunction> { *dz = tensor_dout->data(); auto&& d = tensor_x->dims(); auto const N = tensor_x->numel(); - auto const B = d[d.size() - 1]; + auto const _B = d.size() == 0 ? 1 : d[d.size() - 1]; + auto const B = _B != 0 ? _B : 1; if (tensor_dx) { auto* dx = ctx.template Alloc(tensor_dx); @@ -298,7 +302,8 @@ struct DotDoubleGradFunction> { const DDim& dim = tensor_dx->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { @@ -316,7 +321,8 @@ struct DotDoubleGradFunction> { const DDim& dim = tensor_dy->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { @@ -337,7 +343,8 @@ struct DotDoubleGradFunction> { const DDim& dim = tensor_dy->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; bool new_s = false; @@ -362,7 +369,8 @@ struct DotDoubleGradFunction> { const DDim& dim = tensor_dy->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; bool new_s = false; @@ -385,7 +393,8 @@ struct DotDoubleGradFunction> { const DDim& dim = tensor_dx->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; bool new_s = false; @@ -475,7 +484,8 @@ struct DotDoubleGradFunction> { auto* data_dx = ctx.template Alloc(tensor_dx); const DDim& dim = tensor_dx->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { if (0 == i % step) ++s; @@ -490,7 +500,8 @@ struct DotDoubleGradFunction> { auto* data_dy = ctx.template Alloc(tensor_dy); const DDim& dim = tensor_dy->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { if (0 == i % step) ++s; @@ -505,7 +516,8 @@ struct DotDoubleGradFunction> { auto* data_ddout = ctx.template Alloc(tensor_ddout); const DDim& dim = tensor_dy->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; bool new_s = false; for (size_t i = 0; i < N; ++i) { @@ -524,7 +536,8 @@ struct DotDoubleGradFunction> { auto* data_ddout = ctx.template Alloc(tensor_ddout); const DDim& dim = tensor_dy->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; bool new_s = false; for (size_t i = 0; i < N; ++i) { @@ -543,7 +556,8 @@ struct DotDoubleGradFunction> { auto* data_ddout = ctx.template Alloc(tensor_ddout); const DDim& dim = tensor_dx->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; bool new_s = false; for (size_t i = 0; i < N; ++i) { @@ -771,7 +785,8 @@ struct DotTripleGradFunction> { auto* data_d_y = ctx.template Alloc(out_tensor_d_y); const DDim& dim = out_tensor_d_y->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { @@ -785,7 +800,8 @@ struct DotTripleGradFunction> { auto* data_d_dout = ctx.template Alloc(out_tensor_d_dout); const DDim& dim = in_tensor_x->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; bool new_s = false; for (size_t i = 0; i < N; ++i) { @@ -811,7 +827,8 @@ struct DotTripleGradFunction> { auto* data_d_x = ctx.template Alloc(out_tensor_d_x); const DDim& dim = out_tensor_d_x->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { @@ -824,7 +841,8 @@ struct DotTripleGradFunction> { auto* data_d_dout = ctx.template Alloc(out_tensor_d_dout); const DDim& dim = in_tensor_x->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; bool new_s = false; if (d_dout_flag) { @@ -859,7 +877,8 @@ struct DotTripleGradFunction> { auto* data_d_ddy = ctx.template Alloc(out_tensor_d_ddy); const DDim& dim = out_tensor_d_ddy->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { if (0 == i % step) ++s; @@ -875,7 +894,8 @@ struct DotTripleGradFunction> { auto* data_d_ddx = ctx.template Alloc(out_tensor_d_ddx); const DDim& dim = out_tensor_d_ddx->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { if (0 == i % step) ++s; @@ -891,7 +911,8 @@ struct DotTripleGradFunction> { auto* data_d_ddx = ctx.template Alloc(out_tensor_d_ddx); const DDim& dim = out_tensor_d_ddx->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; if (d_ddx_flag) { for (size_t i = 0; i < N; ++i) { @@ -911,7 +932,8 @@ struct DotTripleGradFunction> { auto* data_d_ddy = ctx.template Alloc(out_tensor_d_ddy); const DDim& dim = out_tensor_d_ddy->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; if (d_ddy_flag) { for (size_t i = 0; i < N; ++i) { @@ -1144,7 +1166,8 @@ struct DotTripleGradFunction> { auto* data_d_y = ctx.template Alloc(out_tensor_d_y); const DDim& dim = out_tensor_d_y->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { if (0 == i % step) ++s; @@ -1155,7 +1178,8 @@ struct DotTripleGradFunction> { auto* data_d_dout = ctx.template Alloc(out_tensor_d_dout); const DDim& dim = in_tensor_x->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; bool new_s = false; for (size_t i = 0; i < N; ++i) { @@ -1179,7 +1203,8 @@ struct DotTripleGradFunction> { auto* data_d_x = ctx.template Alloc(out_tensor_d_x); const DDim& dim = out_tensor_d_x->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { if (0 == i % step) ++s; @@ -1190,7 +1215,8 @@ struct DotTripleGradFunction> { auto* data_d_dout = ctx.template Alloc(out_tensor_d_dout); const DDim& dim = in_tensor_x->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; bool new_s = false; if (d_dout_flag) { @@ -1222,7 +1248,8 @@ struct DotTripleGradFunction> { auto* data_d_ddy = ctx.template Alloc(out_tensor_d_ddy); const DDim& dim = out_tensor_d_ddy->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { if (0 == i % step) ++s; @@ -1237,7 +1264,8 @@ struct DotTripleGradFunction> { auto* data_d_ddx = ctx.template Alloc(out_tensor_d_ddx); const DDim& dim = out_tensor_d_ddx->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; for (size_t i = 0; i < N; ++i) { if (0 == i % step) ++s; @@ -1252,7 +1280,8 @@ struct DotTripleGradFunction> { auto* data_d_ddx = ctx.template Alloc(out_tensor_d_ddx); const DDim& dim = out_tensor_d_ddx->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; if (d_ddx_flag) { for (size_t i = 0; i < N; ++i) { @@ -1270,7 +1299,8 @@ struct DotTripleGradFunction> { auto* data_d_ddy = ctx.template Alloc(out_tensor_d_ddy); const DDim& dim = out_tensor_d_ddy->dims(); size_t N = static_cast(product(dim)); - auto step = dim[dim.size() - 1]; + auto _step = dim.size() > 0 ? dim[dim.size() - 1] : 1; + auto step = _step != 0 ? _step : 1; int s = -1; if (d_ddy_flag) { for (size_t i = 0; i < N; ++i) { diff --git a/python/paddle/fluid/tests/unittests/test_dot_op.py b/python/paddle/fluid/tests/unittests/test_dot_op.py index aa61c1e1778..6c0d0c73855 100644 --- a/python/paddle/fluid/tests/unittests/test_dot_op.py +++ b/python/paddle/fluid/tests/unittests/test_dot_op.py @@ -92,6 +92,32 @@ class DotOp(OpTest): self.dtype = np.float64 +class DotOpEmptyInput(unittest.TestCase): + def test_1d_input(self): + data = np.array([], dtype=np.float32) + x = paddle.to_tensor(np.reshape(data, [0]), dtype='float32') + y = paddle.to_tensor(np.reshape(data, [0]), dtype='float32') + np_out = np.dot(data, data) + pd_out = paddle.dot(x, y) + + self.assertEquals(np_out, pd_out) + + def test_2d_input(self): + data = np.array([], dtype=np.float32) + x = paddle.to_tensor(np.reshape(data, [0, 0]), dtype='float32') + y = paddle.to_tensor(np.reshape(data, [0, 0]), dtype='float32') + pd_out = paddle.dot(x, y) + + self.assertEqual(pd_out.shape, (0, 1)) + + def test_3d_input_error(self): + data = np.array([], dtype=np.float32) + x = paddle.to_tensor(np.reshape(data, [0, 0, 0]), dtype='float32') + y = paddle.to_tensor(np.reshape(data, [0, 0, 0]), dtype='float32') + + self.assertRaises(Exception, paddle.dot, x, y) + + class DotOpBatch(DotOp): def init_input_output(self): self.x = ( -- GitLab