From 97ccaa796e3b401d87d6da8f27c6d22934640891 Mon Sep 17 00:00:00 2001 From: Zhanlue Yang Date: Thu, 3 Mar 2022 14:28:27 +0800 Subject: [PATCH] [Eager][Yaml]Supported Scalar and ScalarArray for AutoCodeGen (#40080) --- .../final_state_generator/eager_gen.py | 4 +- .../final_state_generator/python_c_gen.py | 24 ++--- paddle/fluid/pybind/eager_utils.cc | 100 ++++++++++++++++-- paddle/fluid/pybind/eager_utils.h | 10 ++ 4 files changed, 111 insertions(+), 27 deletions(-) diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py index af9540b6fb3..65dbb0368c6 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/eager_gen.py @@ -31,7 +31,9 @@ yaml_types_mapping = { 'int64_t[]' : 'std::vector', 'int[]' : 'std::vector', 'Tensor' : 'Tensor', 'Tensor[]' : 'std::vector', - 'Tensor[Tensor[]]' : 'std::vector>' + 'Tensor[Tensor[]]' : 'std::vector>', + 'Scalar' : 'Scalar', + 'ScalarArray' : 'ScalarArray' } diff --git a/paddle/fluid/eager/auto_code_generator/final_state_generator/python_c_gen.py b/paddle/fluid/eager/auto_code_generator/final_state_generator/python_c_gen.py index 9329dc5ffc9..9c4e102ca45 100644 --- a/paddle/fluid/eager/auto_code_generator/final_state_generator/python_c_gen.py +++ b/paddle/fluid/eager/auto_code_generator/final_state_generator/python_c_gen.py @@ -14,7 +14,7 @@ import os import argparse -from eager_gen import ReadFwdFile, ParseDispensable, IsVectorTensorType, GetForwardFunctionName, ParseYamlForward, DetermineForwardPositionMap +from eager_gen import yaml_types_mapping, ReadFwdFile, ParseDispensable, IsVectorTensorType, GetForwardFunctionName, ParseYamlForward, DetermineForwardPositionMap atype_to_parsing_function = { "bool": "CastPyArg2Boolean", @@ -27,21 +27,9 @@ atype_to_parsing_function = { "long[]": "CastPyArg2Longs", "float[]": "CastPyArg2Floats", "double[]": "CastPyArg2Float64s", - "string[]": "CastPyArg2Strings" -} - -atype_to_cxx_type = { - "bool": "bool", - "int": "int", - "long": "long", - "float": "float", - "string": "std::string", - "bool[]": "std::vector", - "int[]": "std::vector", - "long[]": "std::vector", - "float[]": "std::vector", - "double[]": "std::vector", - "string[]": "std::vector" + "string[]": "CastPyArg2Strings", + "Scalar": "CastPyArg2Scalar", + "ScalarArray": "CastPyArg2ScalarArray" } @@ -56,10 +44,10 @@ def ParseArguments(): def GetCxxType(atype): - if atype not in atype_to_cxx_type.keys(): + if atype not in yaml_types_mapping.keys(): assert False - return atype_to_cxx_type[atype] + return yaml_types_mapping[atype] def FindParsingFunctionFromAttributeType(atype): diff --git a/paddle/fluid/pybind/eager_utils.cc b/paddle/fluid/pybind/eager_utils.cc index 57f37621d3b..7647930ef07 100644 --- a/paddle/fluid/pybind/eager_utils.cc +++ b/paddle/fluid/pybind/eager_utils.cc @@ -587,14 +587,9 @@ paddle::optional GetOptionalTensorFromArgs( reinterpret_cast(obj)->tensor); } -// For Intermediate State Dygraph, -// we use an uninitialized Tensor to represent dispensable Tensor -paddle::experimental::Tensor& GetTensorFromArgs(const std::string& op_type, - const std::string& arg_name, - PyObject* args, ssize_t arg_idx, - bool dispensable) { - PyObject* obj = PyTuple_GET_ITEM(args, arg_idx); - +static paddle::experimental::Tensor& GetTensorFromPyObject( + const std::string& op_type, const std::string& arg_name, PyObject* obj, + ssize_t arg_idx, bool dispensable) { if (PyTuple_Check(obj)) { obj = PyTuple_GET_ITEM(obj, 0); } @@ -612,6 +607,16 @@ paddle::experimental::Tensor& GetTensorFromArgs(const std::string& op_type, return reinterpret_cast(obj)->tensor; } +// For Intermediate State Dygraph, +// we use an uninitialized Tensor to represent dispensable Tensor +paddle::experimental::Tensor& GetTensorFromArgs(const std::string& op_type, + const std::string& arg_name, + PyObject* args, ssize_t arg_idx, + bool dispensable) { + PyObject* obj = PyTuple_GET_ITEM(args, arg_idx); + return GetTensorFromPyObject(op_type, arg_name, obj, arg_idx, dispensable); +} + std::vector GetTensorListFromArgs( const std::string& op_type, const std::string& arg_name, PyObject* args, ssize_t arg_idx, bool dispensable) { @@ -746,5 +751,84 @@ std::vector GetTensorPtrListFromArgs( return result; } +paddle::experimental::Scalar CastPyArg2Scalar(PyObject* obj, + const std::string& op_type, + ssize_t arg_pos) { + if (obj == Py_None) { + PADDLE_THROW(platform::errors::InvalidArgument( + "%s(): argument (position %d) must be " + "bool, but got %s", + op_type, arg_pos + 1, + ((PyTypeObject*)obj->ob_type)->tp_name)); // NOLINT + } + + // obj could be: int, float, bool, paddle.Tensor + PyTypeObject* type = obj->ob_type; + auto type_name = std::string(type->tp_name); + if (type_name == "int") { + int value = CastPyArg2Int(obj, op_type, arg_pos); + return paddle::experimental::Scalar(value); + } else if (type_name == "float") { + float value = CastPyArg2Float(obj, op_type, arg_pos); + return paddle::experimental::Scalar(value); + + } else if (type_name == "bool") { + bool value = CastPyArg2Boolean(obj, op_type, arg_pos); + return paddle::experimental::Scalar(value); + + } else if (type_name == "paddle.Tensor") { + paddle::experimental::Tensor& value = GetTensorFromPyObject( + op_type, "" /*arg_name*/, obj, arg_pos, false /*dispensable*/); + return paddle::experimental::Scalar(value); + + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "%s(): argument (position %d) must be " + "bool, but got %s", + op_type, arg_pos + 1, + ((PyTypeObject*)obj->ob_type)->tp_name)); // NOLINT + } + + // Fake a Scalar + return paddle::experimental::Scalar(1.0); +} + +paddle::experimental::ScalarArray CastPyArg2ScalarArray( + PyObject* obj, const std::string& op_type, ssize_t arg_pos) { + // In case of ScalarArray, only two possible PyObjects: + // 1. list of int + // 2. Tensor + if (obj == Py_None) { + PADDLE_THROW(platform::errors::InvalidArgument( + "%s(): argument (position %d) must be " + "bool, but got %s", + op_type, arg_pos + 1, + ((PyTypeObject*)obj->ob_type)->tp_name)); // NOLINT + } + + // obj could be: int, float, bool, paddle.Tensor + PyTypeObject* type = obj->ob_type; + auto type_name = std::string(type->tp_name); + if (type_name == "list") { + std::vector value = CastPyArg2Ints(obj, op_type, arg_pos); + return paddle::experimental::ScalarArray(value); + + } else if (type_name == "paddle.Tensor") { + paddle::experimental::Tensor& value = GetTensorFromPyObject( + op_type, "" /*arg_name*/, obj, arg_pos, false /*dispensable*/); + return paddle::experimental::ScalarArray(value); + + } else { + PADDLE_THROW(platform::errors::InvalidArgument( + "%s(): argument (position %d) must be " + "bool, but got %s", + op_type, arg_pos + 1, + ((PyTypeObject*)obj->ob_type)->tp_name)); // NOLINT + } + + // Fake a ScalarArray + return paddle::experimental::ScalarArray({1}); +} + } // namespace pybind } // namespace paddle diff --git a/paddle/fluid/pybind/eager_utils.h b/paddle/fluid/pybind/eager_utils.h index 92afc3ae487..6e990691776 100644 --- a/paddle/fluid/pybind/eager_utils.h +++ b/paddle/fluid/pybind/eager_utils.h @@ -11,7 +11,10 @@ limitations under the License. */ #pragma once #include +#include "paddle/phi/common/scalar.h" +#include "paddle/phi/common/scalar_array.h" #include "paddle/phi/core/dense_tensor.h" + #include "pybind11/pybind11.h" #include "pybind11/stl.h" namespace paddle { @@ -90,6 +93,13 @@ PyObject* ToPyObject(const std::tuple& out) { return result; } +paddle::experimental::Scalar CastPyArg2Scalar(PyObject* obj, + const std::string& op_type, + ssize_t arg_pos); + +paddle::experimental::ScalarArray CastPyArg2ScalarArray( + PyObject* obj, const std::string& op_type, ssize_t arg_pos); + paddle::optional GetOptionalTensorFromArgs( const std::string& op_type, const std::string& arg_name, PyObject* args, ssize_t arg_idx, bool dispensable = false); -- GitLab