diff --git a/paddle/fluid/eager/to_static/run_program_op_node.h b/paddle/fluid/eager/to_static/run_program_op_node.h index c83e16e9a1ec21b3e7303834ac35b55fed60b2a6..a60d7b5c65ec39484ff11c6bbe869cbf8fcd1975 100644 --- a/paddle/fluid/eager/to_static/run_program_op_node.h +++ b/paddle/fluid/eager/to_static/run_program_op_node.h @@ -51,13 +51,12 @@ static std::vector GetTensorsName( } static void CheckInputVarStatus(const Tensor &tensor) { - PADDLE_ENFORCE_EQ( - tensor.defined() && phi::DenseTensor::classof(tensor.impl().get()), true, - paddle::platform::errors::InvalidArgument( - "The input tensor %s of " - "RunProgram(Grad)Op holds " - "wrong type. Expect type is DenseTensor.", - tensor.name())); + PADDLE_ENFORCE_EQ(tensor.defined() && tensor.is_dense_tensor(), true, + paddle::platform::errors::InvalidArgument( + "The input tensor %s of " + "RunProgram(Grad)Op holds " + "wrong type. Expect type is DenseTensor.", + tensor.name())); PADDLE_ENFORCE_EQ(tensor.initialized(), true, paddle::platform::errors::InvalidArgument( @@ -74,7 +73,7 @@ static void CheckOutputVarStatus(const paddle::framework::Variable &src_var, paddle::platform::errors::InvalidArgument( "dst_tensor shall be defined.")); - if (phi::DenseTensor::classof(dst_tensor.impl().get())) { + if (dst_tensor.is_dense_tensor()) { auto &src_tensor = src_var.Get(); PADDLE_ENFORCE_EQ(phi::DenseTensor::classof(&src_tensor), true, paddle::platform::errors::InvalidArgument( @@ -88,7 +87,7 @@ static void CheckOutputVarStatus(const paddle::framework::Variable &src_var, "RunProgram(Grad)Op's internal " "scope is not initialized.", name)); - } else if (phi::SelectedRows::classof(dst_tensor.impl().get())) { + } else if (dst_tensor.is_selected_rows()) { auto &src_tensor = src_var.Get(); PADDLE_ENFORCE_EQ(phi::SelectedRows::classof(&src_tensor), true, paddle::platform::errors::InvalidArgument( @@ -159,9 +158,6 @@ static void ShareTensorsFromScope( name)); CheckOutputVarStatus(*var, *tensors[i]); // share tensor - // TODO(dev): Determine Tensor type by scope.var - // auto tensor_base = tensors[i]->impl(); - // if (phi::DenseTensor::classof(tensor_base.get())) { if (var->IsType()) { auto &src_tensor = var->Get(); auto *dst_tensor = const_cast( @@ -169,7 +165,6 @@ static void ShareTensorsFromScope( VLOG(2) << "share " << name << " from scope"; *dst_tensor = src_tensor; } else if (var->IsType()) { - // } else if (phi::SelectedRows::classof(tensor_base.get())) { auto &src_tensor = var->Get(); auto *dst_tensor = const_cast( dynamic_cast(tensors[i]->impl().get())); @@ -202,7 +197,6 @@ inline void RunProgramAPI( "The OutScope of RunProgramGradOp should only hold one scope.")); // Step 2. prepare executor and init persistable variables - // NOTE(Aurelius84): While training some models, forward can be called many // times and then apply backpropagation all at once, such as Reinforcement // Learning. Tensor data in multi-step training should be saved into single @@ -277,11 +271,6 @@ inline void RunProgramGradAPI( // if all output vars are set to stop_gradient, grad op no need to executed if (x_grad.empty() && params_grad.empty()) return; - // TODO(dev): Remove this line hard code. And need to deal with the out_grad - // name problem. - // const_cast(out_grad[0]) - // .set_name("matmul_v2_0.tmp_0@GRAD"); - auto *global_block = BOOST_GET_CONST(paddle::framework::BlockDesc *, attrs.at("global_block")); auto orig_end_op_index = BOOST_GET_CONST(int64_t, attrs.at("end_op_index")); @@ -381,8 +370,8 @@ class GradNodeRunProgram : public egr::GradNodeBase { VLOG(3) << "out_grads[0].size() : " << grads[0].size(); std::vector x_grad; std::vector params_grad; - ConstructGradTensors(x_, &x_grad); - ConstructGradTensors(params_, ¶ms_grad); + ConstructXGradTensors(x_, &x_grad); + ConstructParamGradTensors(params_, ¶ms_grad); std::vector x_grad_ptr; std::vector params_grad_ptr; for (auto &i : x_grad) { @@ -392,9 +381,6 @@ class GradNodeRunProgram : public egr::GradNodeBase { params_grad_ptr.emplace_back(&i); } - // auto x_grad_ptr = ConstructGradTensors(x_); - // auto params_grad_ptr = ConstructGradTensors(params_); - PADDLE_ENFORCE_EQ( grads[0].size(), fwd_out_names_.size(), paddle::platform::errors::InvalidArgument( @@ -412,7 +398,6 @@ class GradNodeRunProgram : public egr::GradNodeBase { params_grad_ptr); VLOG(3) << "End Eager Backward Node: GradNodeRunProgram"; return {x_grad, params_grad}; - // return {x_grad, details::DereferenceTensors(params_grad_ptr)}; } void ClearTensorWrappers() override { VLOG(6) << "Do nothing here now"; } @@ -447,29 +432,35 @@ class GradNodeRunProgram : public egr::GradNodeBase { } protected: - void ConstructGradTensors( - const std::vector &fwd_tensors, - std::vector *grad_tensors) { + void ConstructXGradTensors( + const std::vector &x, + std::vector *x_grad) { // TODO(dev): Need an elegant way to determine inforamtion of grad_tensor, // such as: name, tensor type(DenseTensor or SelectedRows). - VLOG(3) << "fwd_tensors.size(): " << fwd_tensors.size(); - for (auto &fwd_t : fwd_tensors) { - if (phi::DenseTensor::classof(fwd_t.impl().get())) { - grad_tensors->emplace_back(std::make_shared()); - } else if (phi::SelectedRows::classof(fwd_t.impl().get())) { - grad_tensors->emplace_back(std::make_shared()); + for (auto &t : x) { + if (t.is_dense_tensor()) { + x_grad->emplace_back(std::make_shared()); + } else if (t.is_selected_rows()) { + x_grad->emplace_back(std::make_shared()); } - auto &grad_t = grad_tensors->back(); - grad_t.set_name(fwd_t.name() + "@GRAD"); + x_grad->back().set_name(t.name() + "@GRAD"); } } - void ConstructGradTensors( - const std::vector &fwd_tensors) { - VLOG(3) << "fwd_tensors.size(): " << fwd_tensors.size(); - for (auto &fwd_t : fwd_tensors) { - auto grad_tesnor = egr::EagerUtils::unsafe_autograd_meta(fwd_t)->Grad(); - grad_tesnor.set_name(fwd_t.name() + "@GRAD"); + void ConstructParamGradTensors( + const std::vector ¶m, + std::vector *param_grad) { + for (auto &t : param) { + auto t_meta = egr::EagerUtils::unsafe_autograd_meta(t); + auto t_grad = egr::EagerUtils::unsafe_autograd_meta(t)->Grad(); + if (t_meta->StopGradient()) { + param_grad->emplace_back(); + } else if (t_grad.is_dense_tensor()) { + param_grad->emplace_back(std::make_shared()); + } else if (t_grad.is_selected_rows()) { + param_grad->emplace_back(std::make_shared()); + } + param_grad->back().set_name(t.name() + "@GRAD"); } } diff --git a/paddle/fluid/eager/utils.cc b/paddle/fluid/eager/utils.cc index 20faae95281db87ad4896b19e63857cf4b7e5e02..f25c4dfcd5932c835e580d70272f56e351617a57 100644 --- a/paddle/fluid/eager/utils.cc +++ b/paddle/fluid/eager/utils.cc @@ -271,6 +271,7 @@ void EagerUtils::GetOutput(const std::shared_ptr& out, "shared_ptr, this error may indicate some outputs " "are nullptr")); out_var->set_impl(out->GetTensorBase()); + out_var->set_name(out->name()); } void EagerUtils::GetOutputs( diff --git a/paddle/fluid/pybind/custom_handwrite_op_funcs.h b/paddle/fluid/pybind/custom_handwrite_op_funcs.h index 3b898ce77ce6fb43ca9aaba38e5db9e01a1d19d3..044c3d5d176e1a021952469db0623197b6302936 100644 --- a/paddle/fluid/pybind/custom_handwrite_op_funcs.h +++ b/paddle/fluid/pybind/custom_handwrite_op_funcs.h @@ -14,6 +14,7 @@ #pragma once #include +#include "paddle/phi/core/enforce.h" static PyObject *eager_api_run_program(PyObject *self, PyObject *args, PyObject *kwargs) { @@ -33,13 +34,24 @@ static PyObject *eager_api_run_program(PyObject *self, PyObject *args, run_program_dygraph_function(X, Params, Out, OutScope, DOut, attrs); PyEval_RestoreThread(tstate); tstate = nullptr; + Py_RETURN_NONE; + } catch (paddle::platform::EnforceNotMet &exception) { + if (tstate) { + PyEval_RestoreThread(tstate); + } + std::ostringstream sout; + sout << exception.what(); + sout << " [operator < run_program > error]"; + exception.set_error_str(sout.str()); + ThrowExceptionToPython(std::current_exception()); + return nullptr; } catch (...) { if (tstate) { PyEval_RestoreThread(tstate); } ThrowExceptionToPython(std::current_exception()); + return nullptr; } - Py_RETURN_NONE; } static PyMethodDef CustomEagerFinalStateMethods[] = { diff --git a/paddle/fluid/pybind/eager_method.cc b/paddle/fluid/pybind/eager_method.cc index bb638ffd3a1e4177934d225e4025484c7a3efd67..9f74bcff77d4a6323c18e05f7cf3f06deed08c73 100644 --- a/paddle/fluid/pybind/eager_method.cc +++ b/paddle/fluid/pybind/eager_method.cc @@ -959,11 +959,11 @@ static PyObject* tensor__set_grad_type(TensorObject* self, PyObject* args, EAGER_TRY auto var_type = pybind::CastPyArg2ProtoType(PyTuple_GET_ITEM(args, 0), 0); auto grad_tensor = - egr::EagerUtils::unsafe_autograd_meta(self->tensor)->Grad(); + egr::EagerUtils::unsafe_autograd_meta(self->tensor)->MutableGrad(); if (var_type == framework::proto::VarType::LOD_TENSOR) { - grad_tensor.set_impl(std::make_shared()); + grad_tensor->set_impl(std::make_shared()); } else if (var_type == framework::proto::VarType::SELECTED_ROWS) { - grad_tensor.set_impl(std::make_shared()); + grad_tensor->set_impl(std::make_shared()); } return Py_None; EAGER_CATCH_AND_THROW_RETURN_NULL diff --git a/python/paddle/fluid/data_feeder.py b/python/paddle/fluid/data_feeder.py index c11ebf7f8eae6021829d8b541eaa6917f0e657cb..f8ffdb8fefc4e2ea03373e5036d56cfb85a9778d 100644 --- a/python/paddle/fluid/data_feeder.py +++ b/python/paddle/fluid/data_feeder.py @@ -105,9 +105,8 @@ def check_type(input, input_name, expected_type, op_name, extra_message=''): if not isinstance(expected_type, tuple): expected_type = (expected_type, ) expected_type += (core.VarBase, ) - # TODO(jiabin): uncomment it when we support declarative mode in eager - # if _in_eager_mode(): - # expected_type += (core.eager.Tensor, ) + if core._in_eager_mode(): + expected_type += (core.eager.Tensor, ) elif isinstance(input, core.VarBase): raise TypeError( "Please use `with fluid.dygraph.guard()` as context or `fluid.enable_dygraph()` to switch to imperative mode firstly. " diff --git a/python/paddle/fluid/tests/unittests/dygraph_to_static/test_ifelse.py b/python/paddle/fluid/tests/unittests/dygraph_to_static/test_ifelse.py index 171685e4a40f70190d43101d2fe219298a7190b9..4062a460298345404ce1f8dfbaab5f041fa2a3e3 100644 --- a/python/paddle/fluid/tests/unittests/dygraph_to_static/test_ifelse.py +++ b/python/paddle/fluid/tests/unittests/dygraph_to_static/test_ifelse.py @@ -20,6 +20,7 @@ import unittest import paddle from paddle.fluid.dygraph.jit import declarative from paddle.fluid.dygraph.dygraph_to_static.program_translator import ProgramTranslator +import paddle.fluid.core as core from ifelse_simple_func import * @@ -379,7 +380,7 @@ class TestDy2StIfElseRetInt1(unittest.TestCase): return out def test_ast_to_func(self): - self.assertIsInstance(self.out[0], paddle.Tensor) + self.assertIsInstance(self.out[0], (paddle.Tensor, core.eager.Tensor)) self.assertIsInstance(self.out[1], int) @@ -390,8 +391,8 @@ class TestDy2StIfElseRetInt2(TestDy2StIfElseRetInt1): self.out = self.get_dy2stat_out() def test_ast_to_func(self): - self.assertIsInstance(self.out[0], paddle.Tensor) - self.assertIsInstance(self.out[1], paddle.Tensor) + self.assertIsInstance(self.out[0], (paddle.Tensor, core.eager.Tensor)) + self.assertIsInstance(self.out[1], (paddle.Tensor, core.eager.Tensor)) class TestDy2StIfElseRetInt3(TestDy2StIfElseRetInt1): @@ -401,7 +402,7 @@ class TestDy2StIfElseRetInt3(TestDy2StIfElseRetInt1): self.out = self.get_dy2stat_out() def test_ast_to_func(self): - self.assertIsInstance(self.out, paddle.Tensor) + self.assertIsInstance(self.out, (paddle.Tensor, core.eager.Tensor)) class TestDy2StIfElseRetInt4(TestDy2StIfElseRetInt1): diff --git a/python/paddle/fluid/tests/unittests/dygraph_to_static/test_partial_program.py b/python/paddle/fluid/tests/unittests/dygraph_to_static/test_partial_program.py index 220347909f978c11a02e1faa28deb185a399f9f9..427e4c22524519e06ba106a59e0173b021dde176 100644 --- a/python/paddle/fluid/tests/unittests/dygraph_to_static/test_partial_program.py +++ b/python/paddle/fluid/tests/unittests/dygraph_to_static/test_partial_program.py @@ -118,7 +118,8 @@ class TestWithNestedOutput(unittest.TestCase): self.assertTrue(len(dygraph_res) == len(static_res)) for dy_var, st_var in zip(dygraph_res, static_res): - if isinstance(dy_var, fluid.core.VarBase): + if isinstance(dy_var, + (fluid.core.VarBase, fluid.core.eager.Tensor)): self.assertTrue(np.allclose(dy_var.numpy(), st_var.numpy())) else: self.assertTrue(dy_var, st_var) diff --git a/python/paddle/fluid/tests/unittests/dygraph_to_static/test_return.py b/python/paddle/fluid/tests/unittests/dygraph_to_static/test_return.py index 7ab60082c37d0a4b632def30bfe0e79163371259..507133aba98e2ffc14c157be774ca1d4e2527a9e 100644 --- a/python/paddle/fluid/tests/unittests/dygraph_to_static/test_return.py +++ b/python/paddle/fluid/tests/unittests/dygraph_to_static/test_return.py @@ -218,7 +218,7 @@ class TestReturnBase(unittest.TestCase): res = self.dygraph_func(self.input) if isinstance(res, (tuple, list)): return tuple(r.numpy() for r in res) - elif isinstance(res, core.VarBase): + elif isinstance(res, (core.VarBase, core.eager.Tensor)): return res.numpy() return res diff --git a/python/paddle/fluid/tests/unittests/test_egr_python_api.py b/python/paddle/fluid/tests/unittests/test_egr_python_api.py index ce771a572e2c19a0089325e95e28507ba49683a1..b985834773d49381fece56158d8e10834b998a08 100644 --- a/python/paddle/fluid/tests/unittests/test_egr_python_api.py +++ b/python/paddle/fluid/tests/unittests/test_egr_python_api.py @@ -251,6 +251,9 @@ class EagerVariablePropertiesAndMethodsTestCase(unittest.TestCase): self.assertTrue(egr_tensor12.place._equals(paddle.fluid.CPUPlace())) self.assertTrue(np.array_equal(egr_tensor12.numpy(), x)) + egr_tensor13 = paddle.randn([2, 2]) + self.assertTrue("eager_tmp" in egr_tensor13.name) + with self.assertRaisesRegexp( ValueError, "The shape of Parameter should not be None"): eager_param = EagerParamBase(shape=None, dtype="float32")