From 1b11952ce3c0732f991a25580f8d6ee4b1525ed9 Mon Sep 17 00:00:00 2001 From: veyron95 Date: Mon, 27 Dec 2021 10:07:07 +0000 Subject: [PATCH 01/13] Support EagerTensor init with kwargs --- paddle/fluid/pybind/eager.cc | 934 ++++++++++++++---- .../tests/unittests/test_egr_python_api.py | 252 +++++ 2 files changed, 985 insertions(+), 201 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index 94ff2eb4c1e23..ba25d8ffab474 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -142,19 +142,16 @@ void InitEagerTensorWithEagerTensor(EagerTensorObject* self, } } -// TODO(jiabin): We have to do some ugly work, refactor this method using -// PyArg_ParseTuple(),PyArg_ParseTupleAndKeywords() and PyArg_Parse() later to -// support kwargs. -int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwds) { +int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { /** We should have init function with signature: * 1. * def __init__ () * 2. - * def __init__ ( + * def __init__ () * ** dtype: paddle::framework::proto::VarType::Type, * ** dims: vector, * ** name: std::string, - * ** type: paddle::framework::proto::VarType::Type, + * ** type: paddle::framework::proto::VarType::LodTensor, * ** persistable: bool) * 3. (multi-place) (must have first 2 parameter) * def __init__ ( @@ -176,6 +173,47 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwds) { * ** place: paddle::platform::Place, * ** name: std::string) * **/ + + // set a flag to record use kwargs or not + bool flag_kwargs = false; + if (kwargs) flag_kwargs = true; + + // all kwargs + PyObject* kw_zero_copy = NULL; + PyObject* kw_persistable = NULL; + PyObject* kw_stop_gradient = NULL; + + PyObject* kw_value = NULL; // receive PyArray or EagerTensor + PyObject* kw_place = NULL; + PyObject* kw_name = NULL; + PyObject* kw_dims = NULL; + PyObject* kw_dtype = NULL; + PyObject* kw_type = NULL; + + // the keywords argument + static char* kwlist[] = { + const_cast("value"), const_cast("place"), + const_cast("persistable"), const_cast("zero_copy"), + const_cast("name"), const_cast("stop_gradient"), + const_cast("dims"), const_cast("dtype"), + const_cast("vtype"), NULL}; + + // 'O' Store a Python object (without any conversion) in a C object pointer, + // '|' Indicates that the remaining arguments in the Python argument list are + // optional. + // PyArg_ParseTupleAndKeywords can Parse the parameters of a function that + // takes both positional + // and keyword parameters into local variables, which enhance case3, case4, + // case5, case6. + bool flag_ = PyArg_ParseTupleAndKeywords( + args, kwargs, "|OOOOOOOOO", kwlist, &kw_value, &kw_place, &kw_persistable, + &kw_zero_copy, &kw_name, &kw_stop_gradient, &kw_dims, &kw_dtype, + &kw_type); + + PADDLE_ENFORCE_EQ(flag_, true, paddle::platform::errors::PreconditionNotMet( + "Please check your input first and make " + "sure you are on the right way.")); + PADDLE_ENFORCE_NOT_NULL( self, paddle::platform::errors::Fatal( "Calling __init__ of Eager Tensor without __new__ is " @@ -184,198 +222,722 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwds) { auto py_tensor_ptr = reinterpret_cast(self); - // TODO(jiabin): Only support case 2 for now Py_ssize_t args_num = PyTuple_Size(args); + VLOG(6) << " args_num: " << args_num; switch (args_num) { case (Py_ssize_t)0: { - // case 1 - VLOG(6) << "Calling case1's initializer."; - EmptyEagerTensorInitializer( - py_tensor_ptr, - egr::Controller::Instance().GenerateUniqueName("generated_tensor"), - egr::Controller::Instance().GetExpectedPlace()); - return 0; - } - case (Py_ssize_t)1: { - // case 4, 5 - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case4's initializer."; - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: ndarray. " - "But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = py::object(py::handle(arg0_ptr), true); + if (!flag_kwargs) { + // case 1 + VLOG(6) << "Calling case1's initializer."; EmptyEagerTensorInitializer( py_tensor_ptr, egr::Controller::Instance().GenerateUniqueName("generated_tensor"), egr::Controller::Instance().GetExpectedPlace()); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, - /** zero copy **/ false); return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case5's initializer."; - auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); - InitEagerTensorWithEagerTensor( - py_tensor_ptr, src_tensor, - egr::Controller::Instance().GetExpectedPlace(), - egr::Controller::Instance().GenerateUniqueName("generated_tensor")); - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We only support construct tensor from numpy value or tensor with " - "python args by this initializer, " - "please check your input first and make sure you are on the right " - "way.")); + } else { // no position args, all arguments are kwargs + if (kw_value != NULL && + pybind11::detail::npy_api::get().PyArray_Check_(kw_value)) { + VLOG(6) << "Calling case3's or case4's initializer"; + PADDLE_ENFORCE_EQ( + pybind11::detail::npy_api::get().PyArray_Check_(kw_value), true, + paddle::platform::errors::Fatal( + "We expected initial parametes list like: \n **value: " + "ndarray. " + "But got value with wrong type: %s", + reinterpret_cast(kw_value->ob_type)->tp_name)); + + // init by PyArray + py::object numpy_value = py::object(py::handle(kw_value), true); + + std::string act_name = ""; + if (kw_name == NULL) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kw_name, 0); + } + + paddle::platform::Place place = + egr::Controller::Instance().GetExpectedPlace(); + if (kw_place != NULL) { + place = CastPyArg2Place(kw_place, 0); + } + + bool persistable = false; + if (kw_persistable != NULL) { + persistable = CastPyArg2AttrBoolean(kw_persistable, 0); + } + + bool stop_gradient = true; + if (kw_stop_gradient != NULL) { + stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); + } + + bool zero_copy = false; + if (kw_zero_copy != NULL) { + zero_copy = CastPyArg2AttrBoolean(kw_zero_copy, 0); + } + + EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, + persistable, stop_gradient); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); + + return 0; + } else if (kw_value != NULL && + PyObject_IsInstance(kw_value, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case5's or case6's initializer"; + + // init by eager tensor + auto src_tensor = CastPyArg2EagerTensor(kw_value, 0); + + paddle::platform::Place place = + egr::Controller::Instance().GetExpectedPlace(); + if (kw_place != NULL) { + place = CastPyArg2Place(kw_place, 0); + } + + std::string act_name = ""; + if (kw_name == NULL) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kw_name, 0); + } + + InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, + act_name); + + return 0; + } else if (kw_dtype != NULL && + PyObject_IsInstance(kw_dtype, reinterpret_cast( + g_vartype_pytype))) { + VLOG(6) << "Calling case2's initializer"; + + PADDLE_ENFORCE_NOT_NULL( + kw_dims, + paddle::platform::errors::Fatal( + "Calling __init__ of Eager Tensor with NULL dims is " + "forbidden. Please check your code and make sure you new a " + "dims before calling this constructor.")); + + PADDLE_ENFORCE_NOT_NULL( + kw_name, + paddle::platform::errors::Fatal( + "Calling __init__ of Eager Tensor with NULL name is " + "forbidden. Please check your code and make sure you new a " + "name before calling this constructor.")); + + PADDLE_ENFORCE_NOT_NULL( + kw_dtype, + paddle::platform::errors::Fatal( + "Calling __init__ of Eager Tensor with NULL dtype is " + "forbidden. Please check your code and make sure you new a " + "dtype before calling this constructor.")); + + PADDLE_ENFORCE_NOT_NULL( + kw_persistable, + paddle::platform::errors::Fatal( + "Calling __init__ of Eager Tensor with NULL persistable is " + "forbidden. Please check your code and make sure you new a " + "persistable before calling this constructor.")); + + paddle::framework::proto::VarType::Type dtype = + CastPyArg2ProtoType(kw_dtype, 0); + std::vector dims = CastPyArg2VectorOfInt(kw_dims, 0); + + std::string act_name = ""; + if (kw_name == Py_None) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kw_name, 0); + } + + paddle::framework::proto::VarType::Type var_type = + CastPyArg2ProtoType(kw_type, 0); + bool persistable = CastPyArg2AttrBoolean(kw_persistable, 0); + + EmptyEagerTensorInitializer( + py_tensor_ptr, act_name, + egr::Controller::Instance().GetExpectedPlace(), persistable, + /* stop_gradient */ true, dtype, dims, var_type); + + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We support construct tensor from numpy value or tensor with " + "python args and kwargs by this initializer. " + "please check your input first and make sure you are on the " + "right " + "way.")); + } + } + } + case (Py_ssize_t)1: { + if (!flag_kwargs) { + // case 4, 5 + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case4's initializer."; + PADDLE_ENFORCE_EQ( + pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, + paddle::platform::errors::Fatal( + "We expected initial parametes list like: \n **value: " + "ndarray. " + "But got value with wrong type: %s", + reinterpret_cast(arg0_ptr->ob_type)->tp_name)); + py::object numpy_value = py::object(py::handle(arg0_ptr), true); + EmptyEagerTensorInitializer( + py_tensor_ptr, egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"), + egr::Controller::Instance().GetExpectedPlace()); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, + /** zero copy **/ false); + return 0; + } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case5's initializer."; + auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); + InitEagerTensorWithEagerTensor( + py_tensor_ptr, src_tensor, + egr::Controller::Instance().GetExpectedPlace(), + egr::Controller::Instance().GenerateUniqueName( + "generated_tensor")); + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We only support construct tensor from numpy value or tensor " + "with " + "python args by this initializer, " + "please check your input first and make sure you are on the " + "right " + "way.")); + } + } else { // one position arg, remainting arguments are kwargs + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's or case4's initializer"; + // init by PyArray + PADDLE_ENFORCE_EQ( + pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, + paddle::platform::errors::Fatal( + "We expected initial parametes list like: \n **value: " + "ndarray. " + "But got value with wrong type: %s", + reinterpret_cast(arg0_ptr->ob_type)->tp_name)); + py::object numpy_value = py::object(py::handle(arg0_ptr), true); + + std::string act_name = ""; + if (kw_name == NULL) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kw_name, 0); + } + + paddle::platform::Place place = + egr::Controller::Instance().GetExpectedPlace(); + if (kw_place != NULL) { + place = CastPyArg2Place(kw_place, 0); + } + + bool persistable = false; + if (kw_persistable != NULL) { + persistable = CastPyArg2AttrBoolean(kw_persistable, 0); + } + + bool stop_gradient = true; + if (kw_stop_gradient != NULL) { + stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); + } + + bool zero_copy = false; + if (kw_zero_copy != NULL) { + zero_copy = CastPyArg2AttrBoolean(kw_zero_copy, 0); + } + + EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, + persistable, stop_gradient); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); + + return 0; + } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case5's or case6's initializer"; + // init by eager tensor + auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); + + paddle::platform::Place place = + egr::Controller::Instance().GetExpectedPlace(); + if (kw_place != NULL) { + place = CastPyArg2Place(kw_place, 0); + } + + std::string act_name = ""; + if (kw_name == NULL) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kw_name, 0); + } + + InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, + act_name); + + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We support construct tensor from numpy value or tensor with " + "python args and kwargs by this initializer. " + "please check your input first and make sure you are on the " + "right " + "way.")); + } } - return 0; } case (Py_ssize_t)2: { - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's initializer."; - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: ndarray. " - "But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = py::object(py::handle(arg0_ptr), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - EmptyEagerTensorInitializer( - py_tensor_ptr, - egr::Controller::Instance().GenerateUniqueName("generated_tensor"), - place); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, - /** zero copy **/ false); - return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case6's initializer."; - auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - InitEagerTensorWithEagerTensor( - py_tensor_ptr, src_tensor, place, - egr::Controller::Instance().GenerateUniqueName("generated_tensor")); - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We only support construct tensor from numpy value or tensor with " - "python args by this initializer, " - "please check your input first and make sure you are on the right " - "way.")); + if (!flag_kwargs) { // using args + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's initializer."; + PADDLE_ENFORCE_EQ( + pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, + paddle::platform::errors::Fatal( + "We expected initial parametes list like: \n **value: " + "ndarray. " + "But got value with wrong type: %s", + reinterpret_cast(arg0_ptr->ob_type)->tp_name)); + py::object numpy_value = py::object(py::handle(arg0_ptr), true); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + EmptyEagerTensorInitializer( + py_tensor_ptr, egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"), + place); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, + /** zero copy **/ false); + return 0; + } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case6's initializer."; + auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + InitEagerTensorWithEagerTensor( + py_tensor_ptr, src_tensor, place, + egr::Controller::Instance().GenerateUniqueName( + "generated_tensor")); + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We only support construct tensor from numpy value or tensor " + "with " + "python args by this initializer, " + "please check your input first and make sure you are on the " + "right " + "way.")); + } + } else { // two position args, remainting arguments are kwargs + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's or case4's initializer"; + // init by PyArray + PADDLE_ENFORCE_EQ( + pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, + paddle::platform::errors::Fatal( + "We expected initial parametes list like: \n **value: " + "ndarray. " + "But got value with wrong type: %s", + reinterpret_cast(arg0_ptr->ob_type)->tp_name)); + py::object numpy_value = py::object(py::handle(arg0_ptr), true); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + + std::string act_name = ""; + if (kw_name == NULL) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kw_name, 0); + } + + bool persistable = false; + if (kw_persistable != NULL) { + persistable = CastPyArg2AttrBoolean(kw_persistable, 0); + } + + bool stop_gradient = true; + if (kw_stop_gradient != NULL) { + stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); + } + + bool zero_copy = false; + if (kw_zero_copy != NULL) { + zero_copy = CastPyArg2AttrBoolean(kw_zero_copy, 0); + } + + EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, + persistable, stop_gradient); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); + + return 0; + } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case5's or case6's initializer"; + // init by eager tensor + auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + + std::string act_name = ""; + if (kw_name == NULL) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kw_name, 0); + } + + InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, + act_name); + + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We support construct tensor from numpy value or tensor with " + "python args and kwargs by this initializer. " + "please check your input first and make sure you are on the " + "right " + "way.")); + } } } case (Py_ssize_t)3: { - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + if (!flag_kwargs) { + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's initializer."; + PADDLE_ENFORCE_EQ( + pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, + paddle::platform::errors::Fatal( + "We expected initial parametes list like: \n **value: " + "ndarray. " + "But got value with wrong type: %s", + reinterpret_cast(arg0_ptr->ob_type)->tp_name)); + py::object numpy_value = py::object(py::handle(arg0_ptr), true); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + bool persistable = + CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); + EmptyEagerTensorInitializer( + py_tensor_ptr, egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"), + place, persistable); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, + /** zero copy **/ false); + return 0; + } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case6's initializer."; + auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + std::string act_name = ""; + PyObject* name_obj = PyTuple_GET_ITEM(args, 2); + if (name_obj == Py_None) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(name_obj, 2); + } + InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, + act_name); + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We only support construct tensor from numpy value or tensor " + "with " + "python args by this initializer, " + "please check your input first and make sure you are on the " + "right " + "way.")); + } + } else { // three position args, remainting arguments are kwargs + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's or case4's initializer"; + + PADDLE_ENFORCE_EQ( + pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, + paddle::platform::errors::Fatal( + "We expected initial parametes list like: \n **value: " + "ndarray. " + "But got value with wrong type: %s", + reinterpret_cast(arg0_ptr->ob_type)->tp_name)); + py::object numpy_value = py::object(py::handle(arg0_ptr), true); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + bool persistable = + CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); + + std::string act_name = ""; + if (kw_name == Py_None) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kw_name, 0); + } + + bool stop_gradient = true; + if (kw_stop_gradient != NULL) { + stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); + } + + bool zero_copy = false; + if (kw_zero_copy != NULL) { + zero_copy = CastPyArg2AttrBoolean(kw_zero_copy, 0); + } + + EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, + persistable, stop_gradient); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); + + return 0; + } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case5's or case6's initializer"; + auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + std::string act_name = ""; + PyObject* name_obj = PyTuple_GET_ITEM(args, 2); + if (name_obj == Py_None) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(name_obj, 2); + } + InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, + act_name); + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We support construct tensor from numpy value or tensor with " + "python args and kwargs by this initializer. " + "please check your input first and make sure you are on the " + "right " + "way.")); + } + } + } + case (Py_ssize_t)4: { + if (!flag_kwargs) { VLOG(6) << "Calling case3's initializer."; + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); PADDLE_ENFORCE_EQ( pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: ndarray. " - "But got value with wrong type: %s", + "We expected initial parametes list like: \n **value: ndarray, " + "\n ** place: paddle::platform::Place, \n ** persistable: " + "bool, " + "\n ** zero_copy: bool, \n ** name: std::string, \n ** " + "stop_gradient: bool. But got value with wrong type: %s", reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = py::object(py::handle(arg0_ptr), true); + py::object numpy_value = + py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); paddle::platform::Place place = CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); bool persistable = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); + bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); EmptyEagerTensorInitializer( py_tensor_ptr, egr::Controller::Instance().GenerateUniqueName("generated_tensor"), place, persistable); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, - /** zero copy **/ false); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case6's initializer."; - auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - std::string act_name = ""; - PyObject* name_obj = PyTuple_GET_ITEM(args, 2); - if (name_obj == Py_None) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(name_obj, 2); + } else { // four position args, remainting arguments are kwargs + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's or case4's initializer"; + PADDLE_ENFORCE_EQ( + pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, + paddle::platform::errors::Fatal( + "We expected initial parametes list like: \n **value: " + "ndarray, " + "\n ** place: paddle::platform::Place, \n ** persistable: " + "bool, " + "\n ** zero_copy: bool, \n ** name: std::string, \n ** " + "stop_gradient: bool. But got value with wrong type: %s", + reinterpret_cast(arg0_ptr->ob_type)->tp_name)); + + py::object numpy_value = + py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + bool persistable = + CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); + bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); + + std::string act_name = ""; + if (kw_name == NULL) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kw_name, 0); + } + + bool stop_gradient = true; + if (kw_stop_gradient != NULL) { + stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); + VLOG(3) << " updated kwargs stop_gradient:" << stop_gradient; + } + + EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, + persistable, stop_gradient); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); + + return 0; + } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( + p_eager_tensor_type))) { + PADDLE_THROW(platform::errors::InvalidArgument( + "We support construct tensor from numpy value or tensor with " + "python args and kwargs by this initializer. " + "please check your input first and make sure you are on the " + "right " + "way.")); } - InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, - act_name); - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We only support construct tensor from numpy value or tensor with " - "python args by this initializer, " - "please check your input first and make sure you are on the right " - "way.")); } } - case (Py_ssize_t)4: { - VLOG(6) << "Calling case3's initializer."; - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: ndarray, " - "\n ** place: paddle::platform::Place, \n ** persistable: bool, " - "\n ** zero_copy: bool, \n ** name: std::string, \n ** " - "stop_gradient: bool. But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = - py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - bool persistable = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); - bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); - EmptyEagerTensorInitializer( - py_tensor_ptr, - egr::Controller::Instance().GenerateUniqueName("generated_tensor"), - place, persistable); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); - return 0; - } case (Py_ssize_t)5: { - // case 2 - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (PyObject_IsInstance(arg0_ptr, - reinterpret_cast(g_vartype_pytype))) { - VLOG(6) << "Calling case2's initializer."; - paddle::framework::proto::VarType::Type dtype = - CastPyArg2ProtoType(PyTuple_GET_ITEM(args, 0), 0); - std::vector dims = - - CastPyArg2VectorOfInt(PyTuple_GET_ITEM(args, 1), 1); - std::string act_name = ""; - PyObject* name_obj = PyTuple_GET_ITEM(args, 2); - if (name_obj == Py_None) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); + if (!flag_kwargs) { + // case 2 + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (PyObject_IsInstance( + arg0_ptr, reinterpret_cast(g_vartype_pytype))) { + VLOG(6) << "Calling case2's initializer."; + paddle::framework::proto::VarType::Type dtype = + CastPyArg2ProtoType(PyTuple_GET_ITEM(args, 0), 0); + std::vector dims = + + CastPyArg2VectorOfInt(PyTuple_GET_ITEM(args, 1), 1); + std::string act_name = ""; + PyObject* name_obj = PyTuple_GET_ITEM(args, 2); + if (name_obj == Py_None) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 2), 2); + } + paddle::framework::proto::VarType::Type var_type = + CastPyArg2ProtoType(PyTuple_GET_ITEM(args, 3), 3); + bool persistable = + CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 4), 4); + EmptyEagerTensorInitializer( + py_tensor_ptr, act_name, + egr::Controller::Instance().GetExpectedPlace(), persistable, true, + dtype, dims, var_type); + return 0; + } else if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + PADDLE_ENFORCE_EQ( + pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, + paddle::platform::errors::Fatal( + "We expected initial parametes list like: \n **value: " + "ndarray, " + "\n ** place: paddle::platform::Place, \n ** persistable: " + "bool, \n ** zero_copy: bool, \n ** name: std::string, \n ** " + "stop_gradient: bool. But got value with wrong type: %s", + reinterpret_cast(arg0_ptr->ob_type)->tp_name)); + py::object numpy_value = + py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + bool persistable = + CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); + bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); + std::string act_name = ""; + PyObject* name_obj = PyTuple_GET_ITEM(args, 4); + if (name_obj == Py_None) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 4), 4); + } + + EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, + persistable); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); + + return 0; } else { - act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 2), 2); + PADDLE_THROW(platform::errors::InvalidArgument( + "We only support construct tensor from numpy value or dtype with " + "python args by this initializer, " + "please check your input first and make sure you are on the " + "right " + "way.")); } - paddle::framework::proto::VarType::Type var_type = - CastPyArg2ProtoType(PyTuple_GET_ITEM(args, 3), 3); - bool persistable = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 4), 4); - EmptyEagerTensorInitializer( - py_tensor_ptr, act_name, - egr::Controller::Instance().GetExpectedPlace(), persistable, true, - dtype, dims, var_type); - return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { + } else { // five position args, remainting arguments are kwargs + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's or case4's initializer"; + PADDLE_ENFORCE_EQ( + pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, + paddle::platform::errors::Fatal( + "We expected initial parametes list like: \n **value: " + "ndarray, " + "\n ** place: paddle::platform::Place, \n ** persistable: " + "bool, \n ** zero_copy: bool, \n ** name: std::string, \n ** " + "stop_gradient: bool. But got value with wrong type: %s", + reinterpret_cast(arg0_ptr->ob_type)->tp_name)); + // init by PyArray + py::object numpy_value = + py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); + paddle::platform::Place place = + CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + bool persistable = + CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); + bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); + std::string act_name = ""; + PyObject* name_obj = PyTuple_GET_ITEM(args, 4); + if (name_obj == Py_None) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 4), 4); + } + + bool stop_gradient = true; + if (kw_stop_gradient != NULL) { + stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); + } + + EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, + persistable, stop_gradient); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); + + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We support construct tensor from numpy value or tensor with " + "python args and kwargs by this initializer. " + "please check your input first and make sure you are on the " + "right " + "way.")); + } + } + } + case (Py_ssize_t)6: { + if (!flag_kwargs) { + // case 3 + VLOG(6) << "Calling case3's initializer."; + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); PADDLE_ENFORCE_EQ( pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, paddle::platform::errors::Fatal( "We expected initial parametes list like: \n **value: ndarray, " "\n ** place: paddle::platform::Place, \n ** persistable: " - "bool, \n ** zero_copy: bool, \n ** name: std::string, \n ** " + "bool, " + "\n ** zero_copy: bool, \n ** name: std::string, \n ** " "stop_gradient: bool. But got value with wrong type: %s", reinterpret_cast(arg0_ptr->ob_type)->tp_name)); py::object numpy_value = @@ -390,52 +952,22 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwds) { act_name = egr::Controller::Instance().GenerateUniqueName( "generated_tensor"); } else { - act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 4), 4); + act_name = CastPyArg2AttrString(name_obj, 4); } - EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, - persistable); + bool stop_gradient = + CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 5), 5); + EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, persistable, + stop_gradient); InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); return 0; - } else { + } else { // six position args, remainting arguments are kwargs, but this + // is not a right way PADDLE_THROW(platform::errors::InvalidArgument( - "We only support construct tensor from numpy value or dtype with " - "python args by this initializer, " + "There are six position args and the remainting arguments are " + "kwargs," "please check your input first and make sure you are on the right " "way.")); } - return 0; - } - case (Py_ssize_t)6: { - // case 3 - VLOG(6) << "Calling case3's initializer."; - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: ndarray, " - "\n ** place: paddle::platform::Place, \n ** persistable: bool, " - "\n ** zero_copy: bool, \n ** name: std::string, \n ** " - "stop_gradient: bool. But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = - py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - bool persistable = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); - bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); - std::string act_name = ""; - PyObject* name_obj = PyTuple_GET_ITEM(args, 4); - if (name_obj == Py_None) { - act_name = - egr::Controller::Instance().GenerateUniqueName("generated_tensor"); - } else { - act_name = CastPyArg2AttrString(name_obj, 4); - } - bool stop_gradient = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 5), 5); - EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, persistable, - stop_gradient); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); - return 0; } default: { PADDLE_THROW(platform::errors::Fatal( @@ -512,7 +1044,7 @@ void BindEager(pybind11::module* module) { p_eager_tensor_type = &eager_tensor_type; if (PyType_Ready(&eager_tensor_type) < 0) { PADDLE_THROW(platform::errors::Fatal( - "Init Paddle erroe in BindEager(PyType_Ready).")); + "Init Paddle error in BindEager(PyType_Ready).")); return; } @@ -522,7 +1054,7 @@ void BindEager(pybind11::module* module) { Py_DECREF(&eager_tensor_type); Py_DECREF(m.ptr()); PADDLE_THROW(platform::errors::Fatal( - "Init Paddle erroe in BindEager(PyModule_AddObject).")); + "Init Paddle error in BindEager(PyModule_AddObject).")); return; } 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 08a68ca246f40..ef14c6e0b8cf0 100644 --- a/python/paddle/fluid/tests/unittests/test_egr_python_api.py +++ b/python/paddle/fluid/tests/unittests/test_egr_python_api.py @@ -202,6 +202,258 @@ def test_constructor(self): for p in place_list: self.constructor(p) + def constructor_with_kwargs(self, place): + # init EagerTensor by Python array + arr = np.random.rand(4, 16, 16, 32).astype('float32') + + egr_tensor0 = core.eager.EagerTensor(value=arr) + self.assertEqual(egr_tensor0.persistable, False) + self.assertTrue("generated" in egr_tensor0.name) + self.assertEqual(egr_tensor0.shape, [4, 16, 16, 32]) + self.assertTrue( + egr_tensor0.place._equals( + paddle.fluid.framework._current_expected_place())) + self.assertEqual(egr_tensor0.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor0.stop_gradient, True) + + egr_tensor1 = core.eager.EagerTensor(value=arr, place=place) + self.assertEqual(egr_tensor1.persistable, False) + self.assertTrue("generated" in egr_tensor1.name) + self.assertEqual(egr_tensor1.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor1.place._equals(place)) + self.assertEqual(egr_tensor1.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor1.stop_gradient, True) + + egr_tensor2 = core.eager.EagerTensor(arr, place=place) + self.assertEqual(egr_tensor2.persistable, False) + self.assertTrue("generated" in egr_tensor2.name) + self.assertEqual(egr_tensor2.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor2.place._equals(place)) + self.assertEqual(egr_tensor2.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor2.stop_gradient, True) + + egr_tensor3 = core.eager.EagerTensor( + arr, place=place, name="new_eager_tensor") + self.assertEqual(egr_tensor3.persistable, False) + self.assertTrue("new_eager_tensor" in egr_tensor3.name) + self.assertEqual(egr_tensor3.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor3.place._equals(place)) + self.assertEqual(egr_tensor3.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor3.stop_gradient, True) + + egr_tensor4 = core.eager.EagerTensor( + arr, place=place, persistable=True, name="new_eager_tensor") + self.assertEqual(egr_tensor4.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor4.name) + self.assertEqual(egr_tensor4.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor4.place._equals(place)) + self.assertEqual(egr_tensor4.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor4.stop_gradient, True) + + egr_tensor5 = core.eager.EagerTensor( + arr, + core.CPUPlace(), + persistable=True, + name="new_eager_tensor", + zero_copy=True) + self.assertEqual(egr_tensor5.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor5.name) + self.assertEqual(egr_tensor5.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor5.place.is_cpu_place()) + self.assertEqual(egr_tensor5.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor5.stop_gradient, True) + + egr_tensor6 = core.eager.EagerTensor( + arr, + place=core.CPUPlace(), + persistable=True, + name="new_eager_tensor", + zero_copy=True) + self.assertEqual(egr_tensor6.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor6.name) + self.assertEqual(egr_tensor6.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor6.place.is_cpu_place()) + self.assertEqual(egr_tensor6.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor6.stop_gradient, True) + + egr_tensor7 = core.eager.EagerTensor( + arr, + place=place, + persistable=True, + name="new_eager_tensor", + zero_copy=True) + self.assertEqual(egr_tensor7.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor7.name) + self.assertEqual(egr_tensor7.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor7.place._equals(place)) + self.assertEqual(egr_tensor7.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor7.stop_gradient, True) + + egr_tensor8 = core.eager.EagerTensor( + arr, + place=place, + persistable=True, + name="new_eager_tensor", + zero_copy=True, + stop_gradient=False) + self.assertEqual(egr_tensor8.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor8.name) + self.assertEqual(egr_tensor8.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor8.place._equals(place)) + self.assertEqual(egr_tensor8.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor8.stop_gradient, False) + + egr_tensor9 = core.eager.EagerTensor( + arr, place, True, True, "new_eager_tensor", stop_gradient=False) + self.assertEqual(egr_tensor9.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor9.name) + self.assertEqual(egr_tensor9.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor9.place._equals(place)) + self.assertEqual(egr_tensor9.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor9.stop_gradient, False) + + egr_tensor10 = core.eager.EagerTensor( + arr, + place, + True, + True, + name="new_eager_tensor", + stop_gradient=False) + self.assertEqual(egr_tensor10.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor10.name) + self.assertEqual(egr_tensor10.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor10.place._equals(place)) + self.assertEqual(egr_tensor10.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor10.stop_gradient, False) + + egr_tensor11 = core.eager.EagerTensor( + arr, + place, + True, + zero_copy=True, + name="new_eager_tensor", + stop_gradient=False) + self.assertEqual(egr_tensor11.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor11.name) + self.assertEqual(egr_tensor11.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor11.place._equals(place)) + self.assertEqual(egr_tensor11.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor11.stop_gradient, False) + + egr_tensor12 = core.eager.EagerTensor( + arr, + place, + persistable=True, + zero_copy=True, + name="new_eager_tensor", + stop_gradient=False) + self.assertEqual(egr_tensor12.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor12.name) + self.assertEqual(egr_tensor12.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor12.place._equals(place)) + self.assertEqual(egr_tensor12.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor12.stop_gradient, False) + + egr_tensor13 = core.eager.EagerTensor( + value=arr, + place=place, + persistable=True, + zero_copy=True, + name="new_eager_tensor", + stop_gradient=False) + self.assertEqual(egr_tensor13.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor13.name) + self.assertEqual(egr_tensor13.shape, [4, 16, 16, 32]) + self.assertTrue(egr_tensor13.place._equals(place)) + self.assertEqual(egr_tensor13.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor13.stop_gradient, False) + + # special case + egr_tensor14 = core.eager.EagerTensor( + dtype=core.VarDesc.VarType.FP32, + dims=[4, 16, 16, 32], + name="special_eager_tensor", + vtype=core.VarDesc.VarType.LOD_TENSOR, + persistable=True) + self.assertEqual(egr_tensor14.persistable, True) + self.assertEqual(egr_tensor14.name, "special_eager_tensor") + self.assertEqual(egr_tensor14.shape, [4, 16, 16, 32]) + self.assertEqual(egr_tensor14.dtype, core.VarDesc.VarType.FP32) + + # init EagerTensor by EagerTensor + egr_tensor15 = core.eager.EagerTensor(value=egr_tensor14) + self.assertEqual(egr_tensor15.persistable, True) + self.assertTrue("generated" in egr_tensor15.name) + self.assertEqual(egr_tensor15.shape, egr_tensor14.shape) + self.assertEqual(egr_tensor15.dtype, egr_tensor14.dtype) + self.assertEqual(egr_tensor15.stop_gradient, True) + self.assertTrue( + egr_tensor15.place._equals( + paddle.fluid.framework._current_expected_place())) + self.assertTrue( + np.array_equal(egr_tensor15.numpy(), egr_tensor14.numpy())) + + egr_tensor16 = core.eager.EagerTensor( + value=egr_tensor4, name="new_eager_tensor") + self.assertEqual(egr_tensor16.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor16.name) + self.assertEqual(egr_tensor16.shape, egr_tensor4.shape) + self.assertEqual(egr_tensor16.dtype, egr_tensor4.dtype) + self.assertEqual(egr_tensor16.stop_gradient, True) + self.assertTrue( + egr_tensor16.place._equals( + paddle.fluid.framework._current_expected_place())) + self.assertTrue( + np.array_equal(egr_tensor16.numpy(), egr_tensor4.numpy())) + + egr_tensor17 = core.eager.EagerTensor( + value=egr_tensor4, + place=place, + name="new_eager_tensor", ) + self.assertEqual(egr_tensor17.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor17.name) + self.assertEqual(egr_tensor17.shape, egr_tensor4.shape) + self.assertEqual(egr_tensor17.dtype, egr_tensor4.dtype) + self.assertEqual(egr_tensor17.stop_gradient, True) + self.assertTrue(egr_tensor17.place._equals(place)) + self.assertTrue( + np.array_equal(egr_tensor17.numpy(), egr_tensor4.numpy())) + + egr_tensor18 = core.eager.EagerTensor( + egr_tensor4, + place=place, + name="new_eager_tensor", ) + self.assertEqual(egr_tensor18.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor18.name) + self.assertEqual(egr_tensor18.shape, egr_tensor4.shape) + self.assertEqual(egr_tensor18.dtype, egr_tensor4.dtype) + self.assertEqual(egr_tensor18.stop_gradient, True) + self.assertTrue(egr_tensor18.place._equals(place)) + self.assertTrue( + np.array_equal(egr_tensor18.numpy(), egr_tensor4.numpy())) + + egr_tensor19 = core.eager.EagerTensor( + egr_tensor4, + place, + name="new_eager_tensor", ) + self.assertEqual(egr_tensor19.persistable, True) + self.assertTrue("new_eager_tensor" in egr_tensor19.name) + self.assertEqual(egr_tensor19.shape, egr_tensor4.shape) + self.assertEqual(egr_tensor19.dtype, egr_tensor4.dtype) + self.assertEqual(egr_tensor19.stop_gradient, True) + self.assertTrue(egr_tensor19.place._equals(place)) + self.assertTrue( + np.array_equal(egr_tensor19.numpy(), egr_tensor4.numpy())) + + def test_constructor_with_kwargs(self): + print("Test_constructor_with_kwargs") + place_list = [core.CPUPlace()] + if core.is_compiled_with_cuda(): + place_list.append(core.CUDAPlace(0)) + with _test_eager_guard(): + for p in place_list: + self.constructor_with_kwargs(p) + def test_copy_and_copy_to(self): print("Test_copy_and_copy_to") with _test_eager_guard(): From 65623a027f7f65609ce9842a26bd712044ffa3c1 Mon Sep 17 00:00:00 2001 From: veyron95 Date: Mon, 27 Dec 2021 11:02:41 +0000 Subject: [PATCH 02/13] Updated comments --- paddle/fluid/pybind/eager.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index ba25d8ffab474..8632c1aa96f4e 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -147,7 +147,7 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { * 1. * def __init__ () * 2. - * def __init__ () + * def __init__ ( * ** dtype: paddle::framework::proto::VarType::Type, * ** dims: vector, * ** name: std::string, @@ -202,9 +202,8 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { // '|' Indicates that the remaining arguments in the Python argument list are // optional. // PyArg_ParseTupleAndKeywords can Parse the parameters of a function that - // takes both positional - // and keyword parameters into local variables, which enhance case3, case4, - // case5, case6. + // takes both positional and keyword parameters into local variables, + // which enhance case2, case3, case4, case5, case6. bool flag_ = PyArg_ParseTupleAndKeywords( args, kwargs, "|OOOOOOOOO", kwlist, &kw_value, &kw_place, &kw_persistable, &kw_zero_copy, &kw_name, &kw_stop_gradient, &kw_dims, &kw_dtype, From 84c9e13b4b71e0c9b446f76000eb1b7dedde75d9 Mon Sep 17 00:00:00 2001 From: veyron95 Date: Mon, 27 Dec 2021 11:36:27 +0000 Subject: [PATCH 03/13] Updated unit tests case --- .../paddle/fluid/tests/unittests/test_egr_python_api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 ef14c6e0b8cf0..ca477c9437dda 100644 --- a/python/paddle/fluid/tests/unittests/test_egr_python_api.py +++ b/python/paddle/fluid/tests/unittests/test_egr_python_api.py @@ -381,17 +381,17 @@ def constructor_with_kwargs(self, place): self.assertEqual(egr_tensor14.dtype, core.VarDesc.VarType.FP32) # init EagerTensor by EagerTensor - egr_tensor15 = core.eager.EagerTensor(value=egr_tensor14) + egr_tensor15 = core.eager.EagerTensor(value=egr_tensor4) self.assertEqual(egr_tensor15.persistable, True) self.assertTrue("generated" in egr_tensor15.name) - self.assertEqual(egr_tensor15.shape, egr_tensor14.shape) - self.assertEqual(egr_tensor15.dtype, egr_tensor14.dtype) + self.assertEqual(egr_tensor15.shape, egr_tensor4.shape) + self.assertEqual(egr_tensor15.dtype, egr_tensor4.dtype) self.assertEqual(egr_tensor15.stop_gradient, True) self.assertTrue( egr_tensor15.place._equals( paddle.fluid.framework._current_expected_place())) self.assertTrue( - np.array_equal(egr_tensor15.numpy(), egr_tensor14.numpy())) + np.array_equal(egr_tensor15.numpy(), egr_tensor4.numpy())) egr_tensor16 = core.eager.EagerTensor( value=egr_tensor4, name="new_eager_tensor") From 78d9d10cd713cf6694f4086e1ce0a45816e54883 Mon Sep 17 00:00:00 2001 From: veyron95 Date: Tue, 28 Dec 2021 08:05:55 +0000 Subject: [PATCH 04/13] Refactor InitTensor related code to reduce duplicate code --- paddle/fluid/pybind/eager.cc | 772 +++++------------- .../tests/unittests/test_egr_python_api.py | 5 +- 2 files changed, 199 insertions(+), 578 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index 8632c1aa96f4e..046b83dbe5592 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -142,8 +142,137 @@ void InitEagerTensorWithEagerTensor(EagerTensorObject* self, } } -int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { - /** We should have init function with signature: +// initialize EagerTensor by EagerTensor (mix args and kwargs) automatically +void AutoInitEagerTensorByTensor( + EagerTensorObject* py_tensor_ptr, + std::unordered_map kws_map, PyObject* args, + bool flag_kwargs, Py_ssize_t args_num) { + // key_word lists: [value, place, name] + std::unordered_map kw_order_map{ + {"value", 1}, {"place", 2}, {"name", 3}}; + + egr::EagerTensor src_tensor; + paddle::platform::Place place = + egr::Controller::Instance().GetExpectedPlace(); + std::string act_name = ""; + + if (kw_order_map["value"] <= args_num) { + src_tensor = CastPyArg2EagerTensor(PyTuple_GET_ITEM(args, 0), 0); + } else { + if (flag_kwargs && kws_map["value"] != NULL) { + src_tensor = CastPyArg2EagerTensor(kws_map["value"], 0); + } + } + + if (kw_order_map["place"] <= args_num) { + place = CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + } else { + if (flag_kwargs && kws_map["place"] != NULL) { + place = CastPyArg2Place(kws_map["place"], 0); + } + } + + if (kw_order_map["name"] <= args_num) { + act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 2), 2); + } else { + if (flag_kwargs) { + if (kws_map["name"] == NULL) { + act_name = + egr::Controller::Instance().GenerateUniqueName("generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kws_map["name"], 0); + } + } else { + act_name = + egr::Controller::Instance().GenerateUniqueName("generated_tensor"); + } + } + + InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, act_name); +} + +// initialize EagerTensor by PyArray (mix args and kwargs) automatically +void AutoInitEagerTensorByPyArray( + EagerTensorObject* py_tensor_ptr, + std::unordered_map kws_map, PyObject* args, + bool flag_kwargs, Py_ssize_t args_num) { + // key_word lists: [value, place, persistable, zero_copy, name, stop_gradient] + std::unordered_map kw_order_map{ + {"value", 1}, {"place", 2}, {"persistable", 3}, + {"zero_copy", 4}, {"name", 5}, {"stop_gradient", 6}}; + + py::object numpy_value = py::object(); + paddle::platform::Place place = + egr::Controller::Instance().GetExpectedPlace(); + bool persistable = false; + bool zero_copy = false; + std::string act_name = ""; + bool stop_gradient = true; + + if (kw_order_map["value"] <= args_num) { + numpy_value = py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); + } else { + if (flag_kwargs && kws_map["value"] != NULL) { + numpy_value = py::object(py::handle(kws_map["value"]), true); + } + } + + if (kw_order_map["place"] <= args_num) { + place = CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + } else { + if (flag_kwargs && kws_map["place"] != NULL) { + place = CastPyArg2Place(kws_map["place"], 0); + } + } + + if (kw_order_map["persistable"] <= args_num) { + persistable = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); + } else { + if (flag_kwargs && kws_map["persistable"] != NULL) { + persistable = CastPyArg2AttrBoolean(kws_map["persistable"], 0); + } + } + + if (kw_order_map["zero_copy"] <= args_num) { + zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); + } else { + if (flag_kwargs && kws_map["zero_copy"] != NULL) { + zero_copy = CastPyArg2AttrBoolean(kws_map["zero_copy"], 0); + } + } + + if (kw_order_map["name"] <= args_num) { + act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 4), 4); + } else { + if (flag_kwargs) { + if (kws_map["name"] == NULL) { + act_name = + egr::Controller::Instance().GenerateUniqueName("generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kws_map["name"], 0); + } + } else { + act_name = + egr::Controller::Instance().GenerateUniqueName("generated_tensor"); + } + } + + if (kw_order_map["stop_gradient"] <= args_num) { + stop_gradient = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 5), 5); + + } else { + if (flag_kwargs) { + if (kws_map["stop_gradient"] != NULL) { + stop_gradient = CastPyArg2AttrBoolean(kws_map["stop_gradient"], 0); + } + } + } + EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, persistable, + stop_gradient); + InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); +} + +/** We should have init function with signature: * 1. * def __init__ () * 2. @@ -153,7 +282,9 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { * ** name: std::string, * ** type: paddle::framework::proto::VarType::LodTensor, * ** persistable: bool) - * 3. (multi-place) (must have first 2 parameter) + * 3. (multi-place) + * (should have at least one parameter, one parameter equals to case 4, zero + * parameter equals to case 1) * def __init__ ( * ** value: ndarray, * ** place: paddle::platform::Place, @@ -167,13 +298,15 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { * 5. * def __init__ ( * ** tensor: EagerTensor) - * 6. (multi-place) (must have first 2 parameter) + * 6. (multi-place) + * (should have at least one parameter, one parameter equals to case 5, zero + * parameter equals to case 1.) * def __init__ ( * ** tensor: EagerTensor, * ** place: paddle::platform::Place, * ** name: std::string) * **/ - +int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { // set a flag to record use kwargs or not bool flag_kwargs = false; if (kwargs) flag_kwargs = true; @@ -209,6 +342,18 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { &kw_zero_copy, &kw_name, &kw_stop_gradient, &kw_dims, &kw_dtype, &kw_type); + // helper map + std::unordered_map kws_map{ + {"value", kw_value}, + {"place", kw_place}, + {"persistable", kw_persistable}, + {"zero_copy", kw_zero_copy}, + {"name", kw_name}, + {"stop_gradient", kw_stop_gradient}, + {"dims", kw_dims}, + {"dtype", kw_dtype}, + {"type", kw_type}}; + PADDLE_ENFORCE_EQ(flag_, true, paddle::platform::errors::PreconditionNotMet( "Please check your input first and make " "sure you are on the right way.")); @@ -234,80 +379,19 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { egr::Controller::Instance().GetExpectedPlace()); return 0; } else { // no position args, all arguments are kwargs - if (kw_value != NULL && - pybind11::detail::npy_api::get().PyArray_Check_(kw_value)) { - VLOG(6) << "Calling case3's or case4's initializer"; - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(kw_value), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: " - "ndarray. " - "But got value with wrong type: %s", - reinterpret_cast(kw_value->ob_type)->tp_name)); - - // init by PyArray - py::object numpy_value = py::object(py::handle(kw_value), true); - - std::string act_name = ""; - if (kw_name == NULL) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kw_name, 0); - } - - paddle::platform::Place place = - egr::Controller::Instance().GetExpectedPlace(); - if (kw_place != NULL) { - place = CastPyArg2Place(kw_place, 0); - } - - bool persistable = false; - if (kw_persistable != NULL) { - persistable = CastPyArg2AttrBoolean(kw_persistable, 0); - } - - bool stop_gradient = true; - if (kw_stop_gradient != NULL) { - stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); - } - - bool zero_copy = false; - if (kw_zero_copy != NULL) { - zero_copy = CastPyArg2AttrBoolean(kw_zero_copy, 0); - } - - EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, - persistable, stop_gradient); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); - - return 0; - } else if (kw_value != NULL && - PyObject_IsInstance(kw_value, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case5's or case6's initializer"; - - // init by eager tensor - auto src_tensor = CastPyArg2EagerTensor(kw_value, 0); - - paddle::platform::Place place = - egr::Controller::Instance().GetExpectedPlace(); - if (kw_place != NULL) { - place = CastPyArg2Place(kw_place, 0); - } - - std::string act_name = ""; - if (kw_name == NULL) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kw_name, 0); + if (kw_value != NULL) { + if (pybind11::detail::npy_api::get().PyArray_Check_(kw_value)) { + VLOG(6) << "Calling case3's or case4's initializer"; + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, + flag_kwargs, args_num); + return 0; + } else if (PyObject_IsInstance(kw_value, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case5's or case6's initializer"; + AutoInitEagerTensorByTensor(py_tensor_ptr, kws_map, args, + flag_kwargs, args_num); + return 0; } - - InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, - act_name); - - return 0; } else if (kw_dtype != NULL && PyObject_IsInstance(kw_dtype, reinterpret_cast( g_vartype_pytype))) { @@ -373,351 +457,38 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { } } } - case (Py_ssize_t)1: { - if (!flag_kwargs) { - // case 4, 5 - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case4's initializer."; - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: " - "ndarray. " - "But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = py::object(py::handle(arg0_ptr), true); - EmptyEagerTensorInitializer( - py_tensor_ptr, egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"), - egr::Controller::Instance().GetExpectedPlace()); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, - /** zero copy **/ false); - return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case5's initializer."; - auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); - InitEagerTensorWithEagerTensor( - py_tensor_ptr, src_tensor, - egr::Controller::Instance().GetExpectedPlace(), - egr::Controller::Instance().GenerateUniqueName( - "generated_tensor")); - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We only support construct tensor from numpy value or tensor " - "with " - "python args by this initializer, " - "please check your input first and make sure you are on the " - "right " - "way.")); - } - } else { // one position arg, remainting arguments are kwargs - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's or case4's initializer"; - // init by PyArray - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: " - "ndarray. " - "But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = py::object(py::handle(arg0_ptr), true); - - std::string act_name = ""; - if (kw_name == NULL) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kw_name, 0); - } - - paddle::platform::Place place = - egr::Controller::Instance().GetExpectedPlace(); - if (kw_place != NULL) { - place = CastPyArg2Place(kw_place, 0); - } - - bool persistable = false; - if (kw_persistable != NULL) { - persistable = CastPyArg2AttrBoolean(kw_persistable, 0); - } - - bool stop_gradient = true; - if (kw_stop_gradient != NULL) { - stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); - } - - bool zero_copy = false; - if (kw_zero_copy != NULL) { - zero_copy = CastPyArg2AttrBoolean(kw_zero_copy, 0); - } - - EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, - persistable, stop_gradient); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); - - return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case5's or case6's initializer"; - // init by eager tensor - auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); - - paddle::platform::Place place = - egr::Controller::Instance().GetExpectedPlace(); - if (kw_place != NULL) { - place = CastPyArg2Place(kw_place, 0); - } - - std::string act_name = ""; - if (kw_name == NULL) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kw_name, 0); - } - - InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, - act_name); - - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We support construct tensor from numpy value or tensor with " - "python args and kwargs by this initializer. " - "please check your input first and make sure you are on the " - "right " - "way.")); - } - } - } - case (Py_ssize_t)2: { - if (!flag_kwargs) { // using args - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's initializer."; - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: " - "ndarray. " - "But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = py::object(py::handle(arg0_ptr), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - EmptyEagerTensorInitializer( - py_tensor_ptr, egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"), - place); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, - /** zero copy **/ false); - return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case6's initializer."; - auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - InitEagerTensorWithEagerTensor( - py_tensor_ptr, src_tensor, place, - egr::Controller::Instance().GenerateUniqueName( - "generated_tensor")); - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We only support construct tensor from numpy value or tensor " - "with " - "python args by this initializer, " - "please check your input first and make sure you are on the " - "right " - "way.")); - } - } else { // two position args, remainting arguments are kwargs - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's or case4's initializer"; - // init by PyArray - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: " - "ndarray. " - "But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = py::object(py::handle(arg0_ptr), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - - std::string act_name = ""; - if (kw_name == NULL) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kw_name, 0); - } - - bool persistable = false; - if (kw_persistable != NULL) { - persistable = CastPyArg2AttrBoolean(kw_persistable, 0); - } - - bool stop_gradient = true; - if (kw_stop_gradient != NULL) { - stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); - } - - bool zero_copy = false; - if (kw_zero_copy != NULL) { - zero_copy = CastPyArg2AttrBoolean(kw_zero_copy, 0); - } - - EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, - persistable, stop_gradient); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); - - return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case5's or case6's initializer"; - // init by eager tensor - auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - - std::string act_name = ""; - if (kw_name == NULL) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kw_name, 0); - } - - InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, - act_name); - - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We support construct tensor from numpy value or tensor with " - "python args and kwargs by this initializer. " - "please check your input first and make sure you are on the " - "right " - "way.")); - } + case (Py_ssize_t)1: + case (Py_ssize_t)2: + case (Py_ssize_t)3: { + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's initializer."; + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, + args_num); + return 0; + } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case6's initializer."; + AutoInitEagerTensorByTensor(py_tensor_ptr, kws_map, args, flag_kwargs, + args_num); + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We only support construct tensor from numpy value or tensor " + "with " + "python args by this initializer, " + "please check your input first and make sure you are on the " + "right " + "way.")); } } - case (Py_ssize_t)3: { + case (Py_ssize_t)4: { if (!flag_kwargs) { PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { VLOG(6) << "Calling case3's initializer."; - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: " - "ndarray. " - "But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = py::object(py::handle(arg0_ptr), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - bool persistable = - CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); - EmptyEagerTensorInitializer( - py_tensor_ptr, egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"), - place, persistable); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, - /** zero copy **/ false); - return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case6's initializer."; - auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - std::string act_name = ""; - PyObject* name_obj = PyTuple_GET_ITEM(args, 2); - if (name_obj == Py_None) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(name_obj, 2); - } - InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, - act_name); - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We only support construct tensor from numpy value or tensor " - "with " - "python args by this initializer, " - "please check your input first and make sure you are on the " - "right " - "way.")); - } - } else { // three position args, remainting arguments are kwargs - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's or case4's initializer"; - - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: " - "ndarray. " - "But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = py::object(py::handle(arg0_ptr), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - bool persistable = - CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); - - std::string act_name = ""; - if (kw_name == Py_None) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kw_name, 0); - } - - bool stop_gradient = true; - if (kw_stop_gradient != NULL) { - stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); - } - - bool zero_copy = false; - if (kw_zero_copy != NULL) { - zero_copy = CastPyArg2AttrBoolean(kw_zero_copy, 0); - } - - EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, - persistable, stop_gradient); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); - - return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case5's or case6's initializer"; - auto src_tensor = CastPyArg2EagerTensor(arg0_ptr, 0); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - std::string act_name = ""; - PyObject* name_obj = PyTuple_GET_ITEM(args, 2); - if (name_obj == Py_None) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(name_obj, 2); - } - InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, - act_name); + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, + flag_kwargs, args_num); return 0; } else { PADDLE_THROW(platform::errors::InvalidArgument( @@ -727,74 +498,12 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { "right " "way.")); } - } - } - case (Py_ssize_t)4: { - if (!flag_kwargs) { - VLOG(6) << "Calling case3's initializer."; - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: ndarray, " - "\n ** place: paddle::platform::Place, \n ** persistable: " - "bool, " - "\n ** zero_copy: bool, \n ** name: std::string, \n ** " - "stop_gradient: bool. But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = - py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - bool persistable = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); - bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); - EmptyEagerTensorInitializer( - py_tensor_ptr, - egr::Controller::Instance().GenerateUniqueName("generated_tensor"), - place, persistable); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); - return 0; } else { // four position args, remainting arguments are kwargs PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { VLOG(6) << "Calling case3's or case4's initializer"; - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: " - "ndarray, " - "\n ** place: paddle::platform::Place, \n ** persistable: " - "bool, " - "\n ** zero_copy: bool, \n ** name: std::string, \n ** " - "stop_gradient: bool. But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - - py::object numpy_value = - py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - bool persistable = - CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); - bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); - - std::string act_name = ""; - if (kw_name == NULL) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kw_name, 0); - } - - bool stop_gradient = true; - if (kw_stop_gradient != NULL) { - stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); - VLOG(3) << " updated kwargs stop_gradient:" << stop_gradient; - } - - EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, - persistable, stop_gradient); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); - + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, + flag_kwargs, args_num); return 0; } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( p_eager_tensor_type))) { @@ -809,7 +518,6 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { } case (Py_ssize_t)5: { if (!flag_kwargs) { - // case 2 PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); if (PyObject_IsInstance( arg0_ptr, reinterpret_cast(g_vartype_pytype))) { @@ -817,7 +525,6 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { paddle::framework::proto::VarType::Type dtype = CastPyArg2ProtoType(PyTuple_GET_ITEM(args, 0), 0); std::vector dims = - CastPyArg2VectorOfInt(PyTuple_GET_ITEM(args, 1), 1); std::string act_name = ""; PyObject* name_obj = PyTuple_GET_ITEM(args, 2); @@ -837,35 +544,8 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { dtype, dims, var_type); return 0; } else if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: " - "ndarray, " - "\n ** place: paddle::platform::Place, \n ** persistable: " - "bool, \n ** zero_copy: bool, \n ** name: std::string, \n ** " - "stop_gradient: bool. But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = - py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - bool persistable = - CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); - bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); - std::string act_name = ""; - PyObject* name_obj = PyTuple_GET_ITEM(args, 4); - if (name_obj == Py_None) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 4), 4); - } - - EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, - persistable); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); - + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, + flag_kwargs, args_num); return 0; } else { PADDLE_THROW(platform::errors::InvalidArgument( @@ -879,41 +559,8 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { VLOG(6) << "Calling case3's or case4's initializer"; - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: " - "ndarray, " - "\n ** place: paddle::platform::Place, \n ** persistable: " - "bool, \n ** zero_copy: bool, \n ** name: std::string, \n ** " - "stop_gradient: bool. But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - // init by PyArray - py::object numpy_value = - py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - bool persistable = - CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); - bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); - std::string act_name = ""; - PyObject* name_obj = PyTuple_GET_ITEM(args, 4); - if (name_obj == Py_None) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 4), 4); - } - - bool stop_gradient = true; - if (kw_stop_gradient != NULL) { - stop_gradient = CastPyArg2AttrBoolean(kw_stop_gradient, 0); - } - - EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, - persistable, stop_gradient); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); - + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, + flag_kwargs, args_num); return 0; } else { PADDLE_THROW(platform::errors::InvalidArgument( @@ -929,35 +576,8 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { if (!flag_kwargs) { // case 3 VLOG(6) << "Calling case3's initializer."; - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - PADDLE_ENFORCE_EQ( - pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr), true, - paddle::platform::errors::Fatal( - "We expected initial parametes list like: \n **value: ndarray, " - "\n ** place: paddle::platform::Place, \n ** persistable: " - "bool, " - "\n ** zero_copy: bool, \n ** name: std::string, \n ** " - "stop_gradient: bool. But got value with wrong type: %s", - reinterpret_cast(arg0_ptr->ob_type)->tp_name)); - py::object numpy_value = - py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); - paddle::platform::Place place = - CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - bool persistable = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); - bool zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); - std::string act_name = ""; - PyObject* name_obj = PyTuple_GET_ITEM(args, 4); - if (name_obj == Py_None) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(name_obj, 4); - } - bool stop_gradient = - CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 5), 5); - EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, persistable, - stop_gradient); - InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, + args_num); return 0; } else { // six position args, remainting arguments are kwargs, but this // is not a right way 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 ca477c9437dda..9c8d8dec641a7 100644 --- a/python/paddle/fluid/tests/unittests/test_egr_python_api.py +++ b/python/paddle/fluid/tests/unittests/test_egr_python_api.py @@ -447,9 +447,10 @@ def constructor_with_kwargs(self, place): def test_constructor_with_kwargs(self): print("Test_constructor_with_kwargs") + paddle.set_device("cpu") place_list = [core.CPUPlace()] - if core.is_compiled_with_cuda(): - place_list.append(core.CUDAPlace(0)) + # if core.is_compiled_with_cuda(): + # place_list.append(core.CUDAPlace(0)) with _test_eager_guard(): for p in place_list: self.constructor_with_kwargs(p) From 1b59a3dc5af7c00b780223987ea72e1f1ddfd19e Mon Sep 17 00:00:00 2001 From: veyron95 Date: Tue, 28 Dec 2021 08:11:19 +0000 Subject: [PATCH 05/13] Updated the error reporting msg --- paddle/fluid/pybind/eager.cc | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index 046b83dbe5592..7a2be9492430c 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -449,11 +449,10 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { return 0; } else { PADDLE_THROW(platform::errors::InvalidArgument( - "We support construct tensor from numpy value or tensor with " - "python args and kwargs by this initializer. " + "We support construct tensor from numpy value or tensor " + "with python args and kwargs by this initializer, " "please check your input first and make sure you are on the " - "right " - "way.")); + "right way.")); } } } @@ -474,12 +473,10 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { return 0; } else { PADDLE_THROW(platform::errors::InvalidArgument( - "We only support construct tensor from numpy value or tensor " - "with " - "python args by this initializer, " + "We support construct tensor from numpy value or tensor " + "with python args and kwargs by this initializer, " "please check your input first and make sure you are on the " - "right " - "way.")); + "right way.")); } } case (Py_ssize_t)4: { @@ -495,8 +492,7 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { "We support construct tensor from numpy value or tensor with " "python args and kwargs by this initializer. " "please check your input first and make sure you are on the " - "right " - "way.")); + "right way.")); } } else { // four position args, remainting arguments are kwargs PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); @@ -511,8 +507,7 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { "We support construct tensor from numpy value or tensor with " "python args and kwargs by this initializer. " "please check your input first and make sure you are on the " - "right " - "way.")); + "right way.")); } } } @@ -549,11 +544,10 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { return 0; } else { PADDLE_THROW(platform::errors::InvalidArgument( - "We only support construct tensor from numpy value or dtype with " - "python args by this initializer, " + "We support construct tensor from numpy value or tensor " + "with python args and kwargs by this initializer, " "please check your input first and make sure you are on the " - "right " - "way.")); + "right way.")); } } else { // five position args, remainting arguments are kwargs PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); @@ -567,8 +561,7 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { "We support construct tensor from numpy value or tensor with " "python args and kwargs by this initializer. " "please check your input first and make sure you are on the " - "right " - "way.")); + "right way.")); } } } From 4d4d02ad5cc43360dede1a941b8d4ed9a51dc569 Mon Sep 17 00:00:00 2001 From: veyron95 Date: Tue, 28 Dec 2021 08:14:25 +0000 Subject: [PATCH 06/13] Updated VLOG msg --- paddle/fluid/pybind/eager.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index 7a2be9492430c..337a61404cc89 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -461,13 +461,13 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { case (Py_ssize_t)3: { PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's initializer."; + VLOG(6) << "Calling case3's or case4's initializer."; AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, args_num); return 0; } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( p_eager_tensor_type))) { - VLOG(6) << "Calling case6's initializer."; + VLOG(6) << "Calling case5's or case6's initializer."; AutoInitEagerTensorByTensor(py_tensor_ptr, kws_map, args, flag_kwargs, args_num); return 0; From 3f4d175f516abf5d75027e7642797f679622f7f1 Mon Sep 17 00:00:00 2001 From: veyron95 Date: Wed, 29 Dec 2021 09:50:28 +0000 Subject: [PATCH 07/13] Merge develop and Update EagerTensor init func --- paddle/fluid/pybind/eager.cc | 196 ++++++++++-------- .../tests/unittests/test_egr_python_api.py | 57 ++++- 2 files changed, 159 insertions(+), 94 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index 7b40825a26e22..2e9b7f9978842 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -88,6 +88,38 @@ void EmptyEagerTensorInitializer( } } +void InitEagerTensorWithFrameworkTensor(EagerTensorObject* self, + const framework::Tensor& src, + const paddle::platform::Place& place, + const std::string& name) { + self->eager_tensor.set_name(name); + if (place == src.place()) { + std::shared_ptr dense_tensor = + std::make_shared( + pten::make_intrusive(place), + pten::DenseTensorMeta(pten::TransToPtenDataType(src.type()), + src.dims())); + paddle::experimental::ReMakePtenDenseTensor(src, dense_tensor.get()); + self->eager_tensor.set_impl(dense_tensor); + VLOG(4) << "Same place, do ShareDataWith"; + } else { + std::shared_ptr dense_tensor = + std::make_shared( + pten::make_intrusive( + src.place()), + pten::DenseTensorMeta(pten::TransToPtenDataType(src.type()), + src.dims())); + paddle::experimental::ReMakePtenDenseTensor(src, dense_tensor.get()); + auto temp = egr::EagerTensor(dense_tensor); + self->eager_tensor.set_impl( + temp.copy_to(pten::TransToPtenBackend(place), true).impl()); + VLOG(4) << "Different place, do TensorCopy"; + } + egr::EagerUtils::autograd_meta(&(self->eager_tensor))->SetStopGradient(true); + egr::EagerUtils::unsafe_autograd_meta(self->eager_tensor) + ->SetPersistable(false); +} + void InitEagerTensorWithNumpyValue(EagerTensorObject* self, const py::object& array, bool zero_copy = false) { @@ -155,69 +187,6 @@ void InitEagerTensorWithEagerTensor(EagerTensorObject* self, } } -// initialize EagerTensor by EagerTensor or framework::Tensor (mix args and -// kwargs) automatically -void AutoInitEagerTensorByTensor( - EagerTensorObject* py_tensor_ptr, - std::unordered_map kws_map, PyObject* args, - bool flag_kwargs, Py_ssize_t args_num, bool init_by_egr_tensor = true) { - // key_word lists: [value, place, name] - std::unordered_map kw_order_map{ - {"value", 1}, {"place", 2}, {"name", 3}}; - - paddle::platform::Place place = - egr::Controller::Instance().GetExpectedPlace(); - std::string act_name = ""; - - if (kw_order_map["place"] <= args_num) { - place = CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - } else { - if (flag_kwargs && kws_map["place"] != NULL) { - place = CastPyArg2Place(kws_map["place"], 0); - } - } - - if (kw_order_map["name"] <= args_num) { - act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 2), 2); - } else { - if (flag_kwargs) { - if (kws_map["name"] == NULL) { - act_name = - egr::Controller::Instance().GenerateUniqueName("generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kws_map["name"], 0); - } - } else { - act_name = - egr::Controller::Instance().GenerateUniqueName("generated_tensor"); - } - } - - if (init_by_egr_tensor) { - egr::EagerTensor src_tensor; - if (kw_order_map["value"] <= args_num) { - src_tensor = CastPyArg2EagerTensor(PyTuple_GET_ITEM(args, 0), 0); - } else { - if (flag_kwargs && kws_map["value"] != NULL) { - src_tensor = CastPyArg2EagerTensor(kws_map["value"], 0); - } - } - InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, act_name); - } else { - // init by framework tensor - framework::Tensor src_tensor; - if (kw_order_map["value"] <= args_num) { - src_tensor = CastPyArg2FrameworkTensor(PyTuple_GET_ITEM(args, 0), 0); - } else { - if (flag_kwargs && kws_map["value"] != NULL) { - src_tensor = CastPyArg2FrameworkTensor(kws_map["value"], 0); - } - } - InitEagerTensorWithFrameworkTensor(py_tensor_ptr, src_tensor, place, - act_name); - } -} - // initialize EagerTensor by PyArray (mix args and kwargs) automatically void AutoInitEagerTensorByPyArray( EagerTensorObject* py_tensor_ptr, @@ -269,7 +238,13 @@ void AutoInitEagerTensorByPyArray( } if (kw_order_map["name"] <= args_num) { - act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 4), 4); + PyObject* name_obj = PyTuple_GET_ITEM(args, 4); + if (name_obj == Py_None) { + act_name = + egr::Controller::Instance().GenerateUniqueName("generated_tensor"); + } else { + act_name = CastPyArg2AttrString(name_obj, 4); + } } else { if (flag_kwargs) { if (kws_map["name"] == NULL) { @@ -299,36 +274,73 @@ void AutoInitEagerTensorByPyArray( InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); } -void InitEagerTensorWithFrameworkTensor(EagerTensorObject* self, - const framework::Tensor& src, - const paddle::platform::Place& place, - const std::string& name) { - self->eager_tensor.set_name(name); - if (place == src.place()) { - std::shared_ptr dense_tensor = - std::make_shared( - pten::make_intrusive(place), - pten::DenseTensorMeta(pten::TransToPtenDataType(src.type()), - src.dims())); - paddle::experimental::ReMakePtenDenseTensor(src, dense_tensor.get()); - self->eager_tensor.set_impl(dense_tensor); - VLOG(4) << "Same place, do ShareDataWith"; +// initialize EagerTensor by EagerTensor or framework::Tensor (mix args and +// kwargs) automatically +void AutoInitEagerTensorByTensor( + EagerTensorObject* py_tensor_ptr, + std::unordered_map kws_map, PyObject* args, + bool flag_kwargs, Py_ssize_t args_num, bool init_by_egr_tensor = true) { + // key_word lists: [value, place, name] + std::unordered_map kw_order_map{ + {"value", 1}, {"place", 2}, {"name", 3}}; + + paddle::platform::Place place = + egr::Controller::Instance().GetExpectedPlace(); + std::string act_name = ""; + + if (kw_order_map["place"] <= args_num) { + place = CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); } else { - std::shared_ptr dense_tensor = - std::make_shared( - pten::make_intrusive( - src.place()), - pten::DenseTensorMeta(pten::TransToPtenDataType(src.type()), - src.dims())); - paddle::experimental::ReMakePtenDenseTensor(src, dense_tensor.get()); - auto temp = egr::EagerTensor(dense_tensor); - self->eager_tensor.set_impl( - temp.copy_to(pten::TransToPtenBackend(place), true).impl()); - VLOG(4) << "Different place, do TensorCopy"; + if (flag_kwargs && kws_map["place"] != NULL) { + place = CastPyArg2Place(kws_map["place"], 0); + } + } + + if (kw_order_map["name"] <= args_num) { + PyObject* name_obj = PyTuple_GET_ITEM(args, 2); + if (name_obj == Py_None) { + act_name = + egr::Controller::Instance().GenerateUniqueName("generated_tensor"); + } else { + act_name = CastPyArg2AttrString(name_obj, 2); + } + } else { + if (flag_kwargs) { + if (kws_map["name"] == NULL) { + act_name = + egr::Controller::Instance().GenerateUniqueName("generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kws_map["name"], 0); + } + } else { + act_name = + egr::Controller::Instance().GenerateUniqueName("generated_tensor"); + } + } + + if (init_by_egr_tensor) { + egr::EagerTensor src_tensor; + if (kw_order_map["value"] <= args_num) { + src_tensor = CastPyArg2EagerTensor(PyTuple_GET_ITEM(args, 0), 0); + } else { + if (flag_kwargs && kws_map["value"] != NULL) { + src_tensor = CastPyArg2EagerTensor(kws_map["value"], 0); + } + } + InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, act_name); + } else { + // init by framework tensor + framework::Tensor src_tensor; + if (kw_order_map["value"] <= args_num) { + src_tensor = CastPyArg2FrameworkTensor(PyTuple_GET_ITEM(args, 0), 0); + } else { + if (flag_kwargs && kws_map["value"] != NULL) { + src_tensor = CastPyArg2FrameworkTensor(kws_map["value"], 0); + } + } + InitEagerTensorWithFrameworkTensor(py_tensor_ptr, src_tensor, place, + act_name); } - egr::EagerUtils::autograd_meta(&(self->eager_tensor))->SetStopGradient(true); - egr::EagerUtils::unsafe_autograd_meta(self->eager_tensor) - ->SetPersistable(false); } /** We should have init function with signature: 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 649a37df1f356..83951eed3918e 100644 --- a/python/paddle/fluid/tests/unittests/test_egr_python_api.py +++ b/python/paddle/fluid/tests/unittests/test_egr_python_api.py @@ -532,12 +532,65 @@ def constructor_with_kwargs(self, place): self.assertTrue( np.array_equal(egr_tensor19.numpy(), egr_tensor4.numpy())) + # init eager tensor by framework tensor + x = np.random.rand(3, 3).astype('float32') + t = paddle.fluid.Tensor() + t.set(x, paddle.fluid.CPUPlace()) + egr_tensor20 = core.eager.EagerTensor(value=t) + self.assertEqual(egr_tensor20.persistable, False) + self.assertTrue("generated_tensor" in egr_tensor20.name) + self.assertEqual(egr_tensor20.shape, [3, 3]) + self.assertEqual(egr_tensor20.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor20.stop_gradient, True) + self.assertTrue( + egr_tensor20.place._equals( + paddle.fluid.framework._current_expected_place())) + self.assertTrue(np.array_equal(egr_tensor20.numpy(), x)) + + egr_tensor21 = core.eager.EagerTensor(value=t, place=place) + self.assertEqual(egr_tensor21.persistable, False) + self.assertTrue("generated_tensor" in egr_tensor21.name) + self.assertEqual(egr_tensor21.shape, [3, 3]) + self.assertEqual(egr_tensor21.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor21.stop_gradient, True) + self.assertTrue(egr_tensor21.place._equals(place)) + self.assertTrue(np.array_equal(egr_tensor21.numpy(), x)) + + egr_tensor22 = core.eager.EagerTensor(t, place=place) + self.assertEqual(egr_tensor22.persistable, False) + self.assertTrue("generated_tensor" in egr_tensor22.name) + self.assertEqual(egr_tensor22.shape, [3, 3]) + self.assertEqual(egr_tensor22.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor22.stop_gradient, True) + self.assertTrue(egr_tensor22.place._equals(place)) + self.assertTrue(np.array_equal(egr_tensor22.numpy(), x)) + + egr_tensor23 = core.eager.EagerTensor( + t, place, name="from_framework_tensor") + self.assertEqual(egr_tensor23.persistable, False) + self.assertTrue("from_framework_tensor" in egr_tensor23.name) + self.assertEqual(egr_tensor23.shape, [3, 3]) + self.assertEqual(egr_tensor23.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor23.stop_gradient, True) + self.assertTrue(egr_tensor23.place._equals(place)) + self.assertTrue(np.array_equal(egr_tensor23.numpy(), x)) + + egr_tensor24 = core.eager.EagerTensor( + value=t, place=place, name="from_framework_tensor") + self.assertEqual(egr_tensor24.persistable, False) + self.assertTrue("from_framework_tensor" in egr_tensor24.name) + self.assertEqual(egr_tensor24.shape, [3, 3]) + self.assertEqual(egr_tensor24.dtype, core.VarDesc.VarType.FP32) + self.assertEqual(egr_tensor24.stop_gradient, True) + self.assertTrue(egr_tensor24.place._equals(place)) + self.assertTrue(np.array_equal(egr_tensor24.numpy(), x)) + def test_constructor_with_kwargs(self): print("Test_constructor_with_kwargs") paddle.set_device("cpu") place_list = [core.CPUPlace()] - # if core.is_compiled_with_cuda(): - # place_list.append(core.CUDAPlace(0)) + if core.is_compiled_with_cuda(): + place_list.append(core.CUDAPlace(0)) with _test_eager_guard(): for p in place_list: self.constructor_with_kwargs(p) From 20fce8edac90608eabcbb361f716154a947bf93e Mon Sep 17 00:00:00 2001 From: veyron95 Date: Wed, 29 Dec 2021 11:17:56 +0000 Subject: [PATCH 08/13] Polish switch case, reduce some code --- paddle/fluid/pybind/eager.cc | 45 ++++++++++++------------------------ 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index 2e9b7f9978842..89bed9c96c6e1 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -544,6 +544,7 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { case (Py_ssize_t)1: case (Py_ssize_t)2: case (Py_ssize_t)3: { + // 1 to 3 position args, remainting arguments are kwargs PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { VLOG(6) << "Calling case3's or case4's initializer."; @@ -574,37 +575,20 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { return 0; } case (Py_ssize_t)4: { - if (!flag_kwargs) { - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's initializer."; - AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, - flag_kwargs, args_num); - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We support construct tensor from numpy value or tensor with " - "python args and kwargs by this initializer. " - "please check your input first and make sure you are on the " - "right way.")); - } - } else { // four position args, remainting arguments are kwargs - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's or case4's initializer"; - AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, - flag_kwargs, args_num); - return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - PADDLE_THROW(platform::errors::InvalidArgument( - "We support construct tensor from numpy value or tensor with " - "python args and kwargs by this initializer. " - "please check your input first and make sure you are on the " - "right way.")); - } + // 4 position args, remainting arguments are kwargs + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's or case4's initializer."; + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, + args_num); + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We support construct tensor from numpy value or tensor with " + "python args and kwargs by this initializer. " + "please check your input first and make sure you are on the " + "right way.")); } - return 0; } case (Py_ssize_t)5: { if (!flag_kwargs) { @@ -634,6 +618,7 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { dtype, dims, var_type); return 0; } else if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's initializer."; AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, args_num); return 0; From 61177595d5d65589326a8a6d88ba95b4417cc029 Mon Sep 17 00:00:00 2001 From: veyron95 Date: Fri, 31 Dec 2021 04:25:07 +0000 Subject: [PATCH 09/13] Add SyntaxError unit test case --- python/paddle/fluid/tests/unittests/test_egr_python_api.py | 5 +++++ 1 file changed, 5 insertions(+) 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 83951eed3918e..67fe17d1a9a26 100644 --- a/python/paddle/fluid/tests/unittests/test_egr_python_api.py +++ b/python/paddle/fluid/tests/unittests/test_egr_python_api.py @@ -20,6 +20,7 @@ from paddle.fluid.data_feeder import convert_dtype import unittest import copy +import paddle.compat as cpt class EagerScaleTestCase(unittest.TestCase): @@ -585,6 +586,10 @@ def constructor_with_kwargs(self, place): self.assertTrue(egr_tensor24.place._equals(place)) self.assertTrue(np.array_equal(egr_tensor24.numpy(), x)) + # Bad usage + # SyntaxError: positional argument follows keyword argument + # egr_tensor25 = core.eager.EagerTensor(value=t, place) + def test_constructor_with_kwargs(self): print("Test_constructor_with_kwargs") paddle.set_device("cpu") From ca39b05019d8db0259c9f517051ec8b98fd14545 Mon Sep 17 00:00:00 2001 From: veyron95 Date: Sat, 1 Jan 2022 05:32:58 +0000 Subject: [PATCH 10/13] Refactor the related initialization func of EagerTensor --- paddle/fluid/pybind/eager.cc | 676 ++++++++++-------- .../tests/unittests/test_egr_python_api.py | 2 +- 2 files changed, 385 insertions(+), 293 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index 89bed9c96c6e1..ffa002ed3ba9a 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -88,38 +88,6 @@ void EmptyEagerTensorInitializer( } } -void InitEagerTensorWithFrameworkTensor(EagerTensorObject* self, - const framework::Tensor& src, - const paddle::platform::Place& place, - const std::string& name) { - self->eager_tensor.set_name(name); - if (place == src.place()) { - std::shared_ptr dense_tensor = - std::make_shared( - pten::make_intrusive(place), - pten::DenseTensorMeta(pten::TransToPtenDataType(src.type()), - src.dims())); - paddle::experimental::ReMakePtenDenseTensor(src, dense_tensor.get()); - self->eager_tensor.set_impl(dense_tensor); - VLOG(4) << "Same place, do ShareDataWith"; - } else { - std::shared_ptr dense_tensor = - std::make_shared( - pten::make_intrusive( - src.place()), - pten::DenseTensorMeta(pten::TransToPtenDataType(src.type()), - src.dims())); - paddle::experimental::ReMakePtenDenseTensor(src, dense_tensor.get()); - auto temp = egr::EagerTensor(dense_tensor); - self->eager_tensor.set_impl( - temp.copy_to(pten::TransToPtenBackend(place), true).impl()); - VLOG(4) << "Different place, do TensorCopy"; - } - egr::EagerUtils::autograd_meta(&(self->eager_tensor))->SetStopGradient(true); - egr::EagerUtils::unsafe_autograd_meta(self->eager_tensor) - ->SetPersistable(false); -} - void InitEagerTensorWithNumpyValue(EagerTensorObject* self, const py::object& array, bool zero_copy = false) { @@ -187,63 +155,132 @@ void InitEagerTensorWithEagerTensor(EagerTensorObject* self, } } -// initialize EagerTensor by PyArray (mix args and kwargs) automatically -void AutoInitEagerTensorByPyArray( - EagerTensorObject* py_tensor_ptr, - std::unordered_map kws_map, PyObject* args, - bool flag_kwargs, Py_ssize_t args_num) { - // key_word lists: [value, place, persistable, zero_copy, name, stop_gradient] - std::unordered_map kw_order_map{ - {"value", 1}, {"place", 2}, {"persistable", 3}, - {"zero_copy", 4}, {"name", 5}, {"stop_gradient", 6}}; +void InitEagerTensorWithFrameworkTensor(EagerTensorObject* self, + const framework::Tensor& src, + const paddle::platform::Place& place, + const std::string& name) { + self->eager_tensor.set_name(name); + if (place == src.place()) { + std::shared_ptr dense_tensor = + std::make_shared( + pten::make_intrusive(place), + pten::DenseTensorMeta(pten::TransToPtenDataType(src.type()), + src.dims())); + paddle::experimental::ReMakePtenDenseTensor(src, dense_tensor.get()); + self->eager_tensor.set_impl(dense_tensor); + VLOG(4) << "Same place, do ShareDataWith"; + } else { + std::shared_ptr dense_tensor = + std::make_shared( + pten::make_intrusive( + src.place()), + pten::DenseTensorMeta(pten::TransToPtenDataType(src.type()), + src.dims())); + paddle::experimental::ReMakePtenDenseTensor(src, dense_tensor.get()); + auto temp = egr::EagerTensor(dense_tensor); + self->eager_tensor.set_impl( + temp.copy_to(pten::TransToPtenBackend(place), true).impl()); + VLOG(4) << "Different place, do TensorCopy"; + } + egr::EagerUtils::autograd_meta(&(self->eager_tensor))->SetStopGradient(true); + egr::EagerUtils::unsafe_autograd_meta(self->eager_tensor) + ->SetPersistable(false); +} +py::object ParsePyArray( + std::unordered_map kws_map, + std::unordered_map kw_order_map, PyObject* args, + bool flag_kwargs, Py_ssize_t args_num) { py::object numpy_value = py::object(); - paddle::platform::Place place = - egr::Controller::Instance().GetExpectedPlace(); - bool persistable = false; - bool zero_copy = false; - std::string act_name = ""; - bool stop_gradient = true; if (kw_order_map["value"] <= args_num) { - numpy_value = py::object(py::handle(PyTuple_GET_ITEM(args, 0)), true); + numpy_value = py::object( + py::handle(PyTuple_GET_ITEM(args, kw_order_map["value"] - 1)), true); } else { if (flag_kwargs && kws_map["value"] != NULL) { numpy_value = py::object(py::handle(kws_map["value"]), true); + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "The first expected arguments is {value: PyArray}, " + "but could not parse the first argument {value: PyArray} " + "successfully. " + "Please check your input first and make sure you are on the right " + "way.")); } } + return numpy_value; +} + +paddle::platform::Place ParsePlace( + std::unordered_map kws_map, + std::unordered_map kw_order_map, PyObject* args, + bool flag_kwargs, Py_ssize_t args_num) { + paddle::platform::Place place = + egr::Controller::Instance().GetExpectedPlace(); if (kw_order_map["place"] <= args_num) { - place = CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); + place = CastPyArg2Place(PyTuple_GET_ITEM(args, kw_order_map["place"] - 1), + kw_order_map["place"] - 1); } else { if (flag_kwargs && kws_map["place"] != NULL) { place = CastPyArg2Place(kws_map["place"], 0); + } else { + // default + return place; } } + return place; +} + +bool ParsePersistable(std::unordered_map kws_map, + std::unordered_map kw_order_map, + PyObject* args, bool flag_kwargs, Py_ssize_t args_num) { + bool persistable = false; if (kw_order_map["persistable"] <= args_num) { - persistable = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 2), 2); + persistable = CastPyArg2AttrBoolean( + PyTuple_GET_ITEM(args, kw_order_map["persistable"] - 1), + kw_order_map["persistable"] - 1); } else { if (flag_kwargs && kws_map["persistable"] != NULL) { persistable = CastPyArg2AttrBoolean(kws_map["persistable"], 0); + } else { + return persistable; } } + return persistable; +} + +bool ParseZeroCopy(std::unordered_map kws_map, + std::unordered_map kw_order_map, + PyObject* args, bool flag_kwargs, Py_ssize_t args_num) { + bool zero_copy = false; if (kw_order_map["zero_copy"] <= args_num) { - zero_copy = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 3), 3); + zero_copy = CastPyArg2AttrBoolean( + PyTuple_GET_ITEM(args, kw_order_map["zero_copy"] - 1), + kw_order_map["zero_copy"] - 1); } else { if (flag_kwargs && kws_map["zero_copy"] != NULL) { zero_copy = CastPyArg2AttrBoolean(kws_map["zero_copy"], 0); + } else { + return zero_copy; } } + return zero_copy; +} +std::string ParseName(std::unordered_map kws_map, + std::unordered_map kw_order_map, + PyObject* args, bool flag_kwargs, Py_ssize_t args_num) { + std::string act_name = ""; if (kw_order_map["name"] <= args_num) { - PyObject* name_obj = PyTuple_GET_ITEM(args, 4); + PyObject* name_obj = PyTuple_GET_ITEM(args, kw_order_map["name"] - 1); if (name_obj == Py_None) { act_name = egr::Controller::Instance().GenerateUniqueName("generated_tensor"); } else { - act_name = CastPyArg2AttrString(name_obj, 4); + act_name = CastPyArg2AttrString(name_obj, kw_order_map["name"] - 1); } } else { if (flag_kwargs) { @@ -258,29 +295,81 @@ void AutoInitEagerTensorByPyArray( egr::Controller::Instance().GenerateUniqueName("generated_tensor"); } } + return act_name; +} + +bool ParseStopGradient(std::unordered_map kws_map, + std::unordered_map kw_order_map, + PyObject* args, bool flag_kwargs, Py_ssize_t args_num) { + bool stop_gradient = true; if (kw_order_map["stop_gradient"] <= args_num) { - stop_gradient = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 5), 5); + stop_gradient = CastPyArg2AttrBoolean( + PyTuple_GET_ITEM(args, kw_order_map["stop_gradient"] - 1), + kw_order_map["stop_gradient"] - 1); } else { - if (flag_kwargs) { - if (kws_map["stop_gradient"] != NULL) { - stop_gradient = CastPyArg2AttrBoolean(kws_map["stop_gradient"], 0); - } + if (flag_kwargs && kws_map["stop_gradient"] != NULL) { + stop_gradient = CastPyArg2AttrBoolean(kws_map["stop_gradient"], 0); + } else { + return stop_gradient; } } + return stop_gradient; +} + +// initialize EagerTensor by PyArray(first argument is PyArray, +// mix args and kwargs) automatically. +void AutoInitEagerTensorByPyArray( + EagerTensorObject* py_tensor_ptr, + std::unordered_map kws_map, PyObject* args, + bool flag_kwargs, Py_ssize_t args_num) { + // The first argument of the EagerTensor constructor is PyArray, + // there are 6 arguments to construct the new EagerTensor, + // kw_order_map's key is every arguments of the constructor, + // kw_order_map's value is the position of the arguments respectively. + // If u want to update this constructor with new arguments, + // need to update this map and to add or change related code. + std::unordered_map kw_order_map{ + {"value", 1}, {"place", 2}, {"persistable", 3}, + {"zero_copy", 4}, {"name", 5}, {"stop_gradient", 6}}; + + py::object numpy_value = py::object(); + paddle::platform::Place place = + egr::Controller::Instance().GetExpectedPlace(); + bool persistable = false; + bool zero_copy = false; + std::string act_name = ""; + bool stop_gradient = true; + + numpy_value = + ParsePyArray(kws_map, kw_order_map, args, flag_kwargs, args_num); + place = ParsePlace(kws_map, kw_order_map, args, flag_kwargs, args_num); + persistable = + ParsePersistable(kws_map, kw_order_map, args, flag_kwargs, args_num); + zero_copy = ParseZeroCopy(kws_map, kw_order_map, args, flag_kwargs, args_num); + act_name = ParseName(kws_map, kw_order_map, args, flag_kwargs, args_num); + stop_gradient = + ParseStopGradient(kws_map, kw_order_map, args, flag_kwargs, args_num); + EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, persistable, stop_gradient); InitEagerTensorWithNumpyValue(py_tensor_ptr, numpy_value, zero_copy); } // initialize EagerTensor by EagerTensor or framework::Tensor (mix args and -// kwargs) automatically +// kwargs) automatically. void AutoInitEagerTensorByTensor( EagerTensorObject* py_tensor_ptr, std::unordered_map kws_map, PyObject* args, bool flag_kwargs, Py_ssize_t args_num, bool init_by_egr_tensor = true) { - // key_word lists: [value, place, name] + // The first argument of the EagerTensor constructor is EagerTensor or + // framework Tensor, + // there are 3 arguments to construct the new EagerTensor, + // kw_order_map's key is every arguments of the constructor, + // kw_order_map's value is the position of the arguments respectively. + // If u want to update this constructor with new arguments, + // need to update this map and to add or change related code. std::unordered_map kw_order_map{ {"value", 1}, {"place", 2}, {"name", 3}}; @@ -288,43 +377,25 @@ void AutoInitEagerTensorByTensor( egr::Controller::Instance().GetExpectedPlace(); std::string act_name = ""; - if (kw_order_map["place"] <= args_num) { - place = CastPyArg2Place(PyTuple_GET_ITEM(args, 1), 1); - } else { - if (flag_kwargs && kws_map["place"] != NULL) { - place = CastPyArg2Place(kws_map["place"], 0); - } - } - - if (kw_order_map["name"] <= args_num) { - PyObject* name_obj = PyTuple_GET_ITEM(args, 2); - if (name_obj == Py_None) { - act_name = - egr::Controller::Instance().GenerateUniqueName("generated_tensor"); - } else { - act_name = CastPyArg2AttrString(name_obj, 2); - } - } else { - if (flag_kwargs) { - if (kws_map["name"] == NULL) { - act_name = - egr::Controller::Instance().GenerateUniqueName("generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kws_map["name"], 0); - } - } else { - act_name = - egr::Controller::Instance().GenerateUniqueName("generated_tensor"); - } - } + place = ParsePlace(kws_map, kw_order_map, args, flag_kwargs, args_num); + act_name = ParseName(kws_map, kw_order_map, args, flag_kwargs, args_num); if (init_by_egr_tensor) { egr::EagerTensor src_tensor; if (kw_order_map["value"] <= args_num) { - src_tensor = CastPyArg2EagerTensor(PyTuple_GET_ITEM(args, 0), 0); + src_tensor = CastPyArg2EagerTensor( + PyTuple_GET_ITEM(args, kw_order_map["value"] - 1), + kw_order_map["value"] - 1); } else { if (flag_kwargs && kws_map["value"] != NULL) { src_tensor = CastPyArg2EagerTensor(kws_map["value"], 0); + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "The first expected kwargs is {value: EagerTensor}, " + "but could not parse the first argument {value: EagerTensor} " + "successfully. " + "Please check your input first and make sure you are on the right " + "way.")); } } InitEagerTensorWithEagerTensor(py_tensor_ptr, src_tensor, place, act_name); @@ -332,10 +403,19 @@ void AutoInitEagerTensorByTensor( // init by framework tensor framework::Tensor src_tensor; if (kw_order_map["value"] <= args_num) { - src_tensor = CastPyArg2FrameworkTensor(PyTuple_GET_ITEM(args, 0), 0); + src_tensor = CastPyArg2FrameworkTensor( + PyTuple_GET_ITEM(args, kw_order_map["value"] - 1), + kw_order_map["value"] - 1); } else { if (flag_kwargs && kws_map["value"] != NULL) { src_tensor = CastPyArg2FrameworkTensor(kws_map["value"], 0); + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "The first expected arguments is {value: framework::Tensor}, " + "but could not parse the first argument {value: framework::Tensor} " + "successfully. " + "Please check your input first and make sure you are on the right " + "way.")); } } InitEagerTensorWithFrameworkTensor(py_tensor_ptr, src_tensor, place, @@ -406,14 +486,14 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { const_cast("persistable"), const_cast("zero_copy"), const_cast("name"), const_cast("stop_gradient"), const_cast("dims"), const_cast("dtype"), - const_cast("vtype"), NULL}; + const_cast("type"), NULL}; // 'O' Store a Python object (without any conversion) in a C object pointer, // '|' Indicates that the remaining arguments in the Python argument list are // optional. // PyArg_ParseTupleAndKeywords can Parse the parameters of a function that // takes both positional and keyword parameters into local variables, - // which enhance case2, case3, case4, case5, case6. + // which enhance case2, case3, case4, case5, case6, case7. bool flag_ = PyArg_ParseTupleAndKeywords( args, kwargs, "|OOOOOOOOO", kwlist, &kw_value, &kw_place, &kw_persistable, &kw_zero_copy, &kw_name, &kw_stop_gradient, &kw_dims, &kw_dtype, @@ -431,9 +511,14 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { {"dtype", kw_dtype}, {"type", kw_type}}; - PADDLE_ENFORCE_EQ(flag_, true, paddle::platform::errors::PreconditionNotMet( - "Please check your input first and make " - "sure you are on the right way.")); + PADDLE_ENFORCE_EQ(flag_, true, + paddle::platform::errors::PreconditionNotMet( + "Could not parse args and kwargs successfully," + "please check your input first and make" + "sure you are on the right way. " + "The expected arguments as follow: (" + "value, place, persistable, zero_copy, " + "name, stop_gradient, dims, dtype, type)")); PADDLE_ENFORCE_NOT_NULL( self, paddle::platform::errors::Fatal( @@ -445,229 +530,236 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { Py_ssize_t args_num = PyTuple_Size(args); VLOG(6) << " args_num: " << args_num; - switch (args_num) { - case (Py_ssize_t)0: { - if (!flag_kwargs) { - // case 1 - VLOG(6) << "Calling case1's initializer."; - EmptyEagerTensorInitializer( - py_tensor_ptr, - egr::Controller::Instance().GenerateUniqueName("generated_tensor"), - egr::Controller::Instance().GetExpectedPlace()); - return 0; - } else { // no position args, all arguments are kwargs - if (kw_value != NULL) { - if (pybind11::detail::npy_api::get().PyArray_Check_(kw_value)) { - VLOG(6) << "Calling case3's or case4's initializer"; - AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, - flag_kwargs, args_num); - return 0; - } else if (PyObject_IsInstance(kw_value, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case5's or case6's initializer"; - AutoInitEagerTensorByTensor(py_tensor_ptr, kws_map, args, - flag_kwargs, args_num); - return 0; - } else if (PyObject_IsInstance(kw_value, - reinterpret_cast( - g_framework_tensor_pytype))) { - VLOG(6) << "Calling case7's initializer."; - AutoInitEagerTensorByTensor( - py_tensor_ptr, kws_map, args, flag_kwargs, args_num, - /* false means not init by egr tensor*/ false); - return 0; - } - } else if (kw_dtype != NULL && - PyObject_IsInstance(kw_dtype, reinterpret_cast( - g_vartype_pytype))) { - VLOG(6) << "Calling case2's initializer"; - - PADDLE_ENFORCE_NOT_NULL( - kw_dims, - paddle::platform::errors::Fatal( - "Calling __init__ of Eager Tensor with NULL dims is " - "forbidden. Please check your code and make sure you new a " - "dims before calling this constructor.")); - - PADDLE_ENFORCE_NOT_NULL( - kw_name, - paddle::platform::errors::Fatal( - "Calling __init__ of Eager Tensor with NULL name is " - "forbidden. Please check your code and make sure you new a " - "name before calling this constructor.")); - - PADDLE_ENFORCE_NOT_NULL( - kw_dtype, - paddle::platform::errors::Fatal( - "Calling __init__ of Eager Tensor with NULL dtype is " - "forbidden. Please check your code and make sure you new a " - "dtype before calling this constructor.")); - - PADDLE_ENFORCE_NOT_NULL( - kw_persistable, - paddle::platform::errors::Fatal( - "Calling __init__ of Eager Tensor with NULL persistable is " - "forbidden. Please check your code and make sure you new a " - "persistable before calling this constructor.")); - - paddle::framework::proto::VarType::Type dtype = - CastPyArg2ProtoType(kw_dtype, 0); - std::vector dims = CastPyArg2VectorOfInt(kw_dims, 0); - - std::string act_name = ""; - if (kw_name == Py_None) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(kw_name, 0); - } - - paddle::framework::proto::VarType::Type var_type = - CastPyArg2ProtoType(kw_type, 0); - bool persistable = CastPyArg2AttrBoolean(kw_persistable, 0); - - EmptyEagerTensorInitializer( - py_tensor_ptr, act_name, - egr::Controller::Instance().GetExpectedPlace(), persistable, - /* stop_gradient */ true, dtype, dims, var_type); + // args_num = 0, means that there is no position arguments. + if (args_num == (Py_ssize_t)0) { + if (!flag_kwargs) { + // case 1 + VLOG(6) << "Calling case1's initializer."; + EmptyEagerTensorInitializer( + py_tensor_ptr, + egr::Controller::Instance().GenerateUniqueName("generated_tensor"), + egr::Controller::Instance().GetExpectedPlace()); + return 0; + } else { // no position args, all arguments are kwargs + if (kw_value != NULL) { + if (pybind11::detail::npy_api::get().PyArray_Check_(kw_value)) { + VLOG(6) << "Calling case3's or case4's initializer"; + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, + flag_kwargs, args_num); + return 0; + } else if (PyObject_IsInstance(kw_value, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case5's or case6's initializer"; + AutoInitEagerTensorByTensor(py_tensor_ptr, kws_map, args, flag_kwargs, + args_num); + return 0; + } else if (PyObject_IsInstance(kw_value, + reinterpret_cast( + g_framework_tensor_pytype))) { + VLOG(6) << "Calling case7's initializer."; + AutoInitEagerTensorByTensor( + py_tensor_ptr, kws_map, args, flag_kwargs, args_num, + /* false means not init by egr tensor*/ false); return 0; } else { PADDLE_THROW(platform::errors::InvalidArgument( - "We support construct tensor from numpy value or tensor " - "with python args and kwargs by this initializer, " - "please check your input first and make sure you are on the " + "Could not parse the first keyword argument successfully," + "the first keyword argument is value, but it should be PyArray " + "or EagerTensor or framework::Tensor. " + "Please check your input first and make sure you are on the " "right way.")); } - } - } - case (Py_ssize_t)1: - case (Py_ssize_t)2: - case (Py_ssize_t)3: { - // 1 to 3 position args, remainting arguments are kwargs - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's or case4's initializer."; - AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, - args_num); - return 0; - } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( - p_eager_tensor_type))) { - VLOG(6) << "Calling case5's or case6's initializer."; - AutoInitEagerTensorByTensor(py_tensor_ptr, kws_map, args, flag_kwargs, - args_num); - return 0; - } else if (PyObject_IsInstance( - arg0_ptr, - reinterpret_cast(g_framework_tensor_pytype))) { - VLOG(6) << "Calling case7's initializer."; - AutoInitEagerTensorByTensor( - py_tensor_ptr, kws_map, args, flag_kwargs, args_num, - /* false means not init by egr tensor*/ false); + } else if (kw_dtype != NULL && + PyObject_IsInstance( + kw_dtype, reinterpret_cast(g_vartype_pytype))) { + VLOG(6) << "Calling case2's initializer"; + + PADDLE_ENFORCE_NOT_NULL( + kw_dims, + paddle::platform::errors::Fatal( + "Calling __init__ of Eager Tensor with NULL dims is " + "forbidden. Please check your code and make sure you new a " + "dims before calling this constructor.")); + + PADDLE_ENFORCE_NOT_NULL( + kw_name, + paddle::platform::errors::Fatal( + "Calling __init__ of Eager Tensor with NULL name is " + "forbidden. Please check your code and make sure you new a " + "name before calling this constructor.")); + + PADDLE_ENFORCE_NOT_NULL( + kw_dtype, + paddle::platform::errors::Fatal( + "Calling __init__ of Eager Tensor with NULL dtype is " + "forbidden. Please check your code and make sure you new a " + "dtype before calling this constructor.")); + + PADDLE_ENFORCE_NOT_NULL( + kw_persistable, + paddle::platform::errors::Fatal( + "Calling __init__ of Eager Tensor with NULL persistable is " + "forbidden. Please check your code and make sure you new a " + "persistable before calling this constructor.")); + + paddle::framework::proto::VarType::Type dtype = + CastPyArg2ProtoType(kw_dtype, 0); + std::vector dims = CastPyArg2VectorOfInt(kw_dims, 0); + + std::string act_name = ""; + if (kw_name == Py_None) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(kw_name, 0); + } + + paddle::framework::proto::VarType::Type var_type = + CastPyArg2ProtoType(kw_type, 0); + bool persistable = CastPyArg2AttrBoolean(kw_persistable, 0); + + EmptyEagerTensorInitializer( + py_tensor_ptr, act_name, + egr::Controller::Instance().GetExpectedPlace(), persistable, + /* stop_gradient */ true, dtype, dims, var_type); + return 0; } else { PADDLE_THROW(platform::errors::InvalidArgument( - "We support construct tensor from numpy value or tensor " - "with python args and kwargs by this initializer, " - "please check your input first and make sure you are on the " - "right way.")); + "We not only support construct EagerTensor from numpy value " + "or tensor(EagerTensor or framework::Tensor) " + "with python kwargs by this initializer, " + "but also even support dtype to init a empty EagerTensor. " + "Please check your input first and make sure you call the existed " + "constructor.")); } + } + } else if (args_num == (Py_ssize_t)1 || args_num == (Py_ssize_t)2 || + args_num == (Py_ssize_t)3) { + // 1 to 3 position args, remainting arguments are kwargs + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's or case4's initializer."; + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, + args_num); + return 0; + } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( + p_eager_tensor_type))) { + VLOG(6) << "Calling case5's or case6's initializer."; + AutoInitEagerTensorByTensor(py_tensor_ptr, kws_map, args, flag_kwargs, + args_num); return 0; + } else if (PyObject_IsInstance(arg0_ptr, reinterpret_cast( + g_framework_tensor_pytype))) { + VLOG(6) << "Calling case7's initializer."; + AutoInitEagerTensorByTensor( + py_tensor_ptr, kws_map, args, flag_kwargs, args_num, + /* false means not init by egr tensor*/ false); + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "We support construct EagerTensor from numpy value " + "or tensor(EagerTensor or framework::Tensor) " + "with python args and kwargs by this initializer, " + "but the first argument should be PyArray or EagerTensor or " + "framework::Tensor. " + "Please check your input first and make sure you call the existed " + "constructor.")); + } + } else if (args_num == (Py_ssize_t)4) { + // 4 position args, remainting arguments are kwargs + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's or case4's initializer."; + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, + args_num); + return 0; + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "Incompatible constructor arguments, " + "there are 4 position args and remainting arguments arg kwargs," + "but the first position args should be PyArray. " + "Please check your code and make sure the first position args is " + "PyArray.")); } - case (Py_ssize_t)4: { - // 4 position args, remainting arguments are kwargs + } else if (args_num == (Py_ssize_t)5) { + if (!flag_kwargs) { PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's or case4's initializer."; + if (PyObject_IsInstance(arg0_ptr, + reinterpret_cast(g_vartype_pytype))) { + VLOG(6) << "Calling case2's initializer."; + paddle::framework::proto::VarType::Type dtype = + CastPyArg2ProtoType(PyTuple_GET_ITEM(args, 0), 0); + std::vector dims = + CastPyArg2VectorOfInt(PyTuple_GET_ITEM(args, 1), 1); + std::string act_name = ""; + PyObject* name_obj = PyTuple_GET_ITEM(args, 2); + if (name_obj == Py_None) { + act_name = egr::Controller::Instance().GenerateUniqueName( + "generated_tensor"); + } else { + act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 2), 2); + } + paddle::framework::proto::VarType::Type var_type = + CastPyArg2ProtoType(PyTuple_GET_ITEM(args, 3), 3); + bool persistable = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 4), 4); + EmptyEagerTensorInitializer( + py_tensor_ptr, act_name, + egr::Controller::Instance().GetExpectedPlace(), persistable, true, + dtype, dims, var_type); + return 0; + } else if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's initializer."; AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, args_num); return 0; } else { PADDLE_THROW(platform::errors::InvalidArgument( - "We support construct tensor from numpy value or tensor with " - "python args and kwargs by this initializer. " - "please check your input first and make sure you are on the " - "right way.")); + "Incompatible constructor arguments, " + "there are only 5 position args," + "but the first position args should be PyArray or dtype. " + "Please check your code and make sure you call the existed " + "constructor.")); } - } - case (Py_ssize_t)5: { - if (!flag_kwargs) { - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (PyObject_IsInstance( - arg0_ptr, reinterpret_cast(g_vartype_pytype))) { - VLOG(6) << "Calling case2's initializer."; - paddle::framework::proto::VarType::Type dtype = - CastPyArg2ProtoType(PyTuple_GET_ITEM(args, 0), 0); - std::vector dims = - CastPyArg2VectorOfInt(PyTuple_GET_ITEM(args, 1), 1); - std::string act_name = ""; - PyObject* name_obj = PyTuple_GET_ITEM(args, 2); - if (name_obj == Py_None) { - act_name = egr::Controller::Instance().GenerateUniqueName( - "generated_tensor"); - } else { - act_name = CastPyArg2AttrString(PyTuple_GET_ITEM(args, 2), 2); - } - paddle::framework::proto::VarType::Type var_type = - CastPyArg2ProtoType(PyTuple_GET_ITEM(args, 3), 3); - bool persistable = - CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, 4), 4); - EmptyEagerTensorInitializer( - py_tensor_ptr, act_name, - egr::Controller::Instance().GetExpectedPlace(), persistable, true, - dtype, dims, var_type); - return 0; - } else if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's initializer."; - AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, - flag_kwargs, args_num); - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We support construct tensor from numpy value or tensor " - "with python args and kwargs by this initializer, " - "please check your input first and make sure you are on the " - "right way.")); - } - } else { // five position args, remainting arguments are kwargs - PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); - if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { - VLOG(6) << "Calling case3's or case4's initializer"; - AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, - flag_kwargs, args_num); - return 0; - } else { - PADDLE_THROW(platform::errors::InvalidArgument( - "We support construct tensor from numpy value or tensor with " - "python args and kwargs by this initializer. " - "please check your input first and make sure you are on the " - "right way.")); - } - } - } - case (Py_ssize_t)6: { - if (!flag_kwargs) { - // case 3 - VLOG(6) << "Calling case3's initializer."; + } else { // five position args, remainting arguments are kwargs + PyObject* arg0_ptr = PyTuple_GET_ITEM(args, 0); + if (pybind11::detail::npy_api::get().PyArray_Check_(arg0_ptr)) { + VLOG(6) << "Calling case3's or case4's initializer"; AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, args_num); return 0; - } else { // six position args, remainting arguments are kwargs, but this - // is not a right way + } else { PADDLE_THROW(platform::errors::InvalidArgument( - "There are six position args and the remainting arguments are " - "kwargs," - "please check your input first and make sure you are on the right " - "way.")); + "Incompatible constructor arguments, " + "there are 5 position args and remainting arguments are kwargs," + "but the first position args should be PyArray. " + "Please check your code and make sure the first position args is " + "PyArray.")); } } - default: { - PADDLE_THROW(platform::errors::Fatal( - "Can't not find expected num of args, please check your call, and " - "make sure u call the existed constructor.")); - return 1; + } else if (args_num == (Py_ssize_t)6) { + if (!flag_kwargs) { + // case 3 + VLOG(6) << "Calling case3's initializer."; + AutoInitEagerTensorByPyArray(py_tensor_ptr, kws_map, args, flag_kwargs, + args_num); + return 0; + } else { // six position args, remainting arguments are kwargs, but this + // is not a right way + PADDLE_THROW(platform::errors::InvalidArgument( + "Incompatible constructor arguments, " + "there are 6 position args and the remainting arguments are kwargs. " + "Please check your code and make sure the first position args is " + "PyArray.")); } + } else { + PADDLE_THROW(platform::errors::Fatal( + "Can't not find expected num of args, please check your call, and " + "make sure u call the existed constructor.")); } + + return 1; } static void eagertensor_dealloc(EagerTensorObject* self) { 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 67fe17d1a9a26..9c2315afcad7f 100644 --- a/python/paddle/fluid/tests/unittests/test_egr_python_api.py +++ b/python/paddle/fluid/tests/unittests/test_egr_python_api.py @@ -461,7 +461,7 @@ def constructor_with_kwargs(self, place): dtype=core.VarDesc.VarType.FP32, dims=[4, 16, 16, 32], name="special_eager_tensor", - vtype=core.VarDesc.VarType.LOD_TENSOR, + type=core.VarDesc.VarType.LOD_TENSOR, persistable=True) self.assertEqual(egr_tensor14.persistable, True) self.assertEqual(egr_tensor14.name, "special_eager_tensor") From d9a5f22a4869a82cc3b83f8353a85f0115db2793 Mon Sep 17 00:00:00 2001 From: veyron95 Date: Sat, 1 Jan 2022 06:29:16 +0000 Subject: [PATCH 11/13] Remove ParseStopGradient and ParseZeroCopy and ParsePersistable, construct ParseBooleanArgs instead. --- paddle/fluid/pybind/eager.cc | 72 +++++++++--------------------------- 1 file changed, 18 insertions(+), 54 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index ffa002ed3ba9a..1b3f28c40c6ff 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -232,42 +232,25 @@ paddle::platform::Place ParsePlace( return place; } -bool ParsePersistable(std::unordered_map kws_map, +// boolean arguments: zero_copy, stop_gradient, persistable +bool ParseBooleanArgs(std::string key, + std::unordered_map kws_map, std::unordered_map kw_order_map, PyObject* args, bool flag_kwargs, Py_ssize_t args_num) { - bool persistable = false; - - if (kw_order_map["persistable"] <= args_num) { - persistable = CastPyArg2AttrBoolean( - PyTuple_GET_ITEM(args, kw_order_map["persistable"] - 1), - kw_order_map["persistable"] - 1); - } else { - if (flag_kwargs && kws_map["persistable"] != NULL) { - persistable = CastPyArg2AttrBoolean(kws_map["persistable"], 0); - } else { - return persistable; - } - } - return persistable; -} - -bool ParseZeroCopy(std::unordered_map kws_map, - std::unordered_map kw_order_map, - PyObject* args, bool flag_kwargs, Py_ssize_t args_num) { - bool zero_copy = false; + bool res = false; + if (key == "stop_gradient") res = true; - if (kw_order_map["zero_copy"] <= args_num) { - zero_copy = CastPyArg2AttrBoolean( - PyTuple_GET_ITEM(args, kw_order_map["zero_copy"] - 1), - kw_order_map["zero_copy"] - 1); + if (kw_order_map[key] <= args_num) { + res = CastPyArg2AttrBoolean(PyTuple_GET_ITEM(args, kw_order_map[key] - 1), + kw_order_map[key] - 1); } else { - if (flag_kwargs && kws_map["zero_copy"] != NULL) { - zero_copy = CastPyArg2AttrBoolean(kws_map["zero_copy"], 0); + if (flag_kwargs && kws_map[key] != NULL) { + res = CastPyArg2AttrBoolean(kws_map[key], 0); } else { - return zero_copy; + return res; } } - return zero_copy; + return res; } std::string ParseName(std::unordered_map kws_map, @@ -298,26 +281,6 @@ std::string ParseName(std::unordered_map kws_map, return act_name; } -bool ParseStopGradient(std::unordered_map kws_map, - std::unordered_map kw_order_map, - PyObject* args, bool flag_kwargs, Py_ssize_t args_num) { - bool stop_gradient = true; - - if (kw_order_map["stop_gradient"] <= args_num) { - stop_gradient = CastPyArg2AttrBoolean( - PyTuple_GET_ITEM(args, kw_order_map["stop_gradient"] - 1), - kw_order_map["stop_gradient"] - 1); - - } else { - if (flag_kwargs && kws_map["stop_gradient"] != NULL) { - stop_gradient = CastPyArg2AttrBoolean(kws_map["stop_gradient"], 0); - } else { - return stop_gradient; - } - } - return stop_gradient; -} - // initialize EagerTensor by PyArray(first argument is PyArray, // mix args and kwargs) automatically. void AutoInitEagerTensorByPyArray( @@ -345,12 +308,13 @@ void AutoInitEagerTensorByPyArray( numpy_value = ParsePyArray(kws_map, kw_order_map, args, flag_kwargs, args_num); place = ParsePlace(kws_map, kw_order_map, args, flag_kwargs, args_num); - persistable = - ParsePersistable(kws_map, kw_order_map, args, flag_kwargs, args_num); - zero_copy = ParseZeroCopy(kws_map, kw_order_map, args, flag_kwargs, args_num); + persistable = ParseBooleanArgs("persistable", kws_map, kw_order_map, args, + flag_kwargs, args_num); + zero_copy = ParseBooleanArgs("zero_copy", kws_map, kw_order_map, args, + flag_kwargs, args_num); act_name = ParseName(kws_map, kw_order_map, args, flag_kwargs, args_num); - stop_gradient = - ParseStopGradient(kws_map, kw_order_map, args, flag_kwargs, args_num); + stop_gradient = ParseBooleanArgs("stop_gradient", kws_map, kw_order_map, args, + flag_kwargs, args_num); EmptyEagerTensorInitializer(py_tensor_ptr, act_name, place, persistable, stop_gradient); From bcc419b1456076dd61c03075072a9f5d4dfae4be Mon Sep 17 00:00:00 2001 From: veyron95 Date: Tue, 4 Jan 2022 10:55:19 +0000 Subject: [PATCH 12/13] Updated error msg to pass CI --- paddle/fluid/pybind/eager.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index 1b3f28c40c6ff..bb8fb2e26c5c6 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -477,7 +477,7 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { PADDLE_ENFORCE_EQ(flag_, true, paddle::platform::errors::PreconditionNotMet( - "Could not parse args and kwargs successfully," + "Could not parse args and kwargs successfully, " "please check your input first and make" "sure you are on the right way. " "The expected arguments as follow: (" @@ -528,7 +528,7 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { return 0; } else { PADDLE_THROW(platform::errors::InvalidArgument( - "Could not parse the first keyword argument successfully," + "Could not parse the first keyword argument successfully, " "the first keyword argument is value, but it should be PyArray " "or EagerTensor or framework::Tensor. " "Please check your input first and make sure you are on the " From 4e19a2a92d8c1ba32912ae90586d2149ce3cbe9e Mon Sep 17 00:00:00 2001 From: veyron95 Date: Tue, 4 Jan 2022 11:01:02 +0000 Subject: [PATCH 13/13] Updated PADDLE_ENFORCE error type --- paddle/fluid/pybind/eager.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/paddle/fluid/pybind/eager.cc b/paddle/fluid/pybind/eager.cc index bb8fb2e26c5c6..0aa2e2cdf3537 100644 --- a/paddle/fluid/pybind/eager.cc +++ b/paddle/fluid/pybind/eager.cc @@ -541,28 +541,28 @@ int EagerTensorInit(PyObject* self, PyObject* args, PyObject* kwargs) { PADDLE_ENFORCE_NOT_NULL( kw_dims, - paddle::platform::errors::Fatal( + paddle::platform::errors::InvalidArgument( "Calling __init__ of Eager Tensor with NULL dims is " "forbidden. Please check your code and make sure you new a " "dims before calling this constructor.")); PADDLE_ENFORCE_NOT_NULL( kw_name, - paddle::platform::errors::Fatal( + paddle::platform::errors::InvalidArgument( "Calling __init__ of Eager Tensor with NULL name is " "forbidden. Please check your code and make sure you new a " "name before calling this constructor.")); PADDLE_ENFORCE_NOT_NULL( kw_dtype, - paddle::platform::errors::Fatal( + paddle::platform::errors::InvalidArgument( "Calling __init__ of Eager Tensor with NULL dtype is " "forbidden. Please check your code and make sure you new a " "dtype before calling this constructor.")); PADDLE_ENFORCE_NOT_NULL( kw_persistable, - paddle::platform::errors::Fatal( + paddle::platform::errors::InvalidArgument( "Calling __init__ of Eager Tensor with NULL persistable is " "forbidden. Please check your code and make sure you new a " "persistable before calling this constructor."));