diff --git a/paddle/phi/kernels/funcs/activation_functor.h b/paddle/phi/kernels/funcs/activation_functor.h index 2309f5fa30de28..d310e989fec8d9 100644 --- a/paddle/phi/kernels/funcs/activation_functor.h +++ b/paddle/phi/kernels/funcs/activation_functor.h @@ -398,7 +398,7 @@ struct CosDoubleGradFunctor : public BaseActivationFunctor { const DenseTensor* ddX, DenseTensor* dX, DenseTensor* ddOut) const { - auto* d = dev.eigen_device(); + auto* device = dev.eigen_device(); auto d2d1x = EigenVector::Flatten( GET_DATA_SAFELY(ddX, "Input", "d2d1x", "CosDoubleGrad")); auto x = EigenVector::Flatten( @@ -407,21 +407,17 @@ struct CosDoubleGradFunctor : public BaseActivationFunctor { // calculate d2x first, so d2d1y can inplace d2d1x auto d2x = EigenVector::Flatten( GET_DATA_SAFELY(dX, "Output", "d2x", "CosDoubleGrad")); - if (ddOut) { - if (dOut) { - auto d1y = EigenVector::Flatten( - GET_DATA_SAFELY(dOut, "Output", "d1y", "CosDoubleGrad")); - d2x.device(*d) = -d2d1x * x.unaryExpr(Cosine()) * d1y; - } else { - d2x.device(*d) = x * static_cast(0); - } + if (dX) { + auto d1y = EigenVector::Flatten( + GET_DATA_SAFELY(dOut, "Output", "d1y", "CosDoubleGrad")); + d2x.device(*device) = -d2d1x * x.unaryExpr(Cosine()) * d1y; } - if (dX) { + if (ddOut) { // calculate d2d1y auto d2d1y = EigenVector::Flatten( GET_DATA_SAFELY(ddOut, "Output", "d2d1y", "CosDoubleGrad")); - d2d1y.device(*d) = -d2d1x * x.unaryExpr(Sine()); + d2d1y.device(*device) = -d2d1x * x.unaryExpr(Sine()); } } static constexpr ActBwdOpFwdDeps FwdDeps() { return kDepX; } diff --git a/test/legacy_test/test_activation_nn_grad.py b/test/legacy_test/test_activation_nn_grad.py index 3f86c97e589a23..d88d52f46be1c9 100644 --- a/test/legacy_test/test_activation_nn_grad.py +++ b/test/legacy_test/test_activation_nn_grad.py @@ -17,6 +17,7 @@ import gradient_checker import numpy as np from decorator_helper import prog_scope +from utils import dygraph_guard, static_guard import paddle import paddle.nn.functional as F @@ -544,6 +545,52 @@ def test_grad(self): self.func(p) +class TestCosDoubleGradCheck2(unittest.TestCase): + @test_with_pir_api + def _check_cos_double_dynamic(self, place): + with dygraph_guard(): + x = paddle.randn([64, 64]) + x = paddle.to_tensor(x, place=place, stop_gradient=False) + y = paddle.cos(x) + dx = paddle.grad(y, x, create_graph=True) + dxx_result = paddle.grad(dx, x)[0] + dxx_expected = -paddle.cos(x) + np.testing.assert_allclose( + dxx_result.numpy(), + dxx_expected.numpy(), + 1e-6, + 1e-6, + ) + + @test_with_pir_api + def _check_cos_double_static(self, place): + x_data = np.random.randn(64, 64).astype("float32") + with static_guard(): + main_prog = paddle.static.Program() + starup_prog = paddle.static.Program() + with paddle.static.program_guard(main_prog, starup_prog): + x = paddle.assign(x_data) + x.stop_gradient = False + y = paddle.cos(x) + dx = paddle.static.gradients(y, x) + dxx = paddle.static.gradients(dx, x)[0] + + exe = paddle.static.Executor(place) + exe.run(starup_prog) + (dxx_result,) = exe.run(main_prog, fetch_list=[dxx]) + dxx_expected = -np.cos(x_data) + np.testing.assert_allclose(dxx_result, dxx_expected, 1e-6, 1e-6) + + def test_cos_double_grad(self): + places = [base.CPUPlace()] + if core.is_compiled_with_cuda(): + places.append(base.CUDAPlace(0)) + + for place in places: + self._check_cos_double_dynamic(place) + self._check_cos_double_static(place) + + class TestPowDoubleGradCheck1(unittest.TestCase): def pow_wrapper(self, x): return paddle.pow(x[0], 2)