未验证 提交 e3b033f9 编写于 作者: Z Zhanlue Yang 提交者: GitHub

Generated CoreOpsInfos for potential use in append_op API (#38085)

* Rearranged Eager AutoCodeGen directory structure

* Removed USE_OP in Eager AutoCodeGen

* Enabled generation for Operators without Grad/Inputs/Outputs

* Resolved operators without input

* Fixed merge conflicts

* Enabled Eager AutoCodeGen for 10+ more operators

* Refactored Eager AutoCodeGen with more organized helper objects

* Enabled Eager AutoCodeGen for operators with multiple OpBases

* Adjusted Eager AutoCodeGen to Enable Passing Output Tensor as Input Argument

* Handled Dispensable Inputs/Outputs in Eager AutoCodeGen

* Adjusted function generation/call between Python-C API & Dygraph API

* Synchronized auto-generated Python-C API with Dygraph Forward Functions

* Generated CoreOpsInfos for potential use in append_op API

* Fixed CI problem
上级 a7de0e66
......@@ -29,6 +29,12 @@
namespace paddle {
namespace framework {
// To handle append_op at python-level
std::unordered_map<std::string, std::vector<std::string>>
core_ops_returns_info = {};
std::unordered_map<std::string, std::vector<std::string>> core_ops_args_info =
{};
/* --- Static maps to handle corner cases --- */
static std::unordered_map<std::string, paddle::framework::AttributeMap>
operators_with_attrs = {};
......@@ -1109,6 +1115,8 @@ static std::pair<std::string, std::string> GenerateForwardFunctionContents(
std::string generated_function_body = "";
std::string dygraph_function_args_str = "";
core_ops_args_info[op_type] = {};
core_ops_args_info[op_type].resize(in_vars.size());
/* ------ Dygraph forward function generation ------ */
generated_function_body += " // Dygraph Forward Pass\n";
......@@ -1131,6 +1139,7 @@ static std::pair<std::string, std::string> GenerateForwardFunctionContents(
input_args_str_list[input_position] =
paddle::string::Sprintf(FWD_INS_ARG_TEMPLATE, input_name);
}
core_ops_args_info[op_type][input_position] = input_name;
if (input.dispensable()) continue;
......@@ -1208,6 +1217,8 @@ static std::pair<std::string, std::string> GenerateForwardFunctionContents(
outs_contents_str += paddle::string::Sprintf(
FWD_OUTS_CONTENT_TEMPLATE, output_name, output_var_name);
core_ops_args_info[op_type].push_back(output_var_name);
} else {
if (output.duplicable()) {
outnum = output_name + "Num";
......@@ -1220,6 +1231,7 @@ static std::pair<std::string, std::string> GenerateForwardFunctionContents(
"{ \"%s\", egr::EagerUtils::ConstructDuplicableOutput(%s) },";
outs_contents_str += paddle::string::Sprintf(FWD_OUTS_CONTENT_TEMPLATE,
output_name, outnum);
core_ops_args_info[op_type].push_back(outnum);
} else {
const char* FWD_OUTS_CONTENT_TEMPLATE =
"{ \"%s\", "
......@@ -1294,6 +1306,9 @@ static std::pair<std::string, std::string> GenerateForwardFunctionContents(
generated_function_body += "\n";
VLOG(6) << "Converted Output VarBase to EagerTensor(s)";
// [Generation] Handle core_ops_returns_info
core_ops_returns_info[op_type] = return_contents;
// [Generation] ComputeRequireGrad -> GradNodeCreation
if (!bwd_info.GenerateForwardOnly()) {
std::string grad_node_creation_body_str =
......@@ -1808,6 +1823,25 @@ static std::string GenerateGradNodeHeaderContents(
/* --------------------------------- */
/* --------- FileGeneration --------- */
/* ---------------------------------- */
static std::string GenerateDygraphHFileIncludes() {
std::string dygraph_forward_api_includes_str =
"#pragma once\n"
"#include \"glog/logging.h\"\n"
"#include \"paddle/fluid/eager/autograd_meta.h\"\n"
"#include \"paddle/pten/api/all.h\"\n"
"#include \"paddle/fluid/eager/utils.h\"\n"
"#include \"paddle/fluid/framework/op_registry.h\"\n\n";
dygraph_forward_api_includes_str +=
"extern std::unordered_map<std::string, std::vector<std::string>> "
"core_ops_args_info;\n";
dygraph_forward_api_includes_str +=
"extern std::unordered_map<std::string, std::vector<std::string>> "
"core_ops_returns_info;\n\n";
return dygraph_forward_api_includes_str;
}
static void GenerateForwardHFile(const std::string& output_dir,
const std::string& dygraph_forward_api_str) {
std::string dygraph_forward_api_path = output_dir + "/dygraph_forward_api.h";
......@@ -1875,16 +1909,50 @@ static void GenerateNodeCCFile(const std::string& output_dir,
node_cc_stream.close();
}
static std::string GenerateDygraphHFileIncludes() {
std::string dygraph_forward_api_includes_str =
"#pragma once\n"
"#include \"glog/logging.h\"\n"
"#include \"paddle/fluid/eager/autograd_meta.h\"\n"
"#include \"paddle/pten/api/all.h\"\n"
"#include \"paddle/fluid/eager/utils.h\"\n"
"#include \"paddle/fluid/framework/op_registry.h\"\n\n";
static std::string ConvertCoreOpsInfosToString(
const std::unordered_map<std::string, std::vector<std::string>>&
core_ops_info) {
std::string core_ops_returns_info_init_str = "";
for (const auto& iter : core_ops_info) {
const char* Core_Ops_Returns_TEMPLATE = "{ \"%s\", { %s } },\n";
const std::string& op_type = iter.first;
return dygraph_forward_api_includes_str;
std::string returns_str = "";
for (const auto& vector_iter : iter.second) {
returns_str += "\"" + vector_iter + "\" ,";
}
// Remove trailing ','
if (returns_str.size() > 0) returns_str.pop_back();
std::string op_type_init_str = paddle::string::Sprintf(
Core_Ops_Returns_TEMPLATE, op_type, returns_str);
core_ops_returns_info_init_str += op_type_init_str;
}
// Remove trailing ','
if (core_ops_returns_info_init_str.size() > 0)
core_ops_returns_info_init_str.pop_back();
return core_ops_returns_info_init_str;
}
static std::string GenerateCoreOpsReturnsInfo() {
const char* Core_Ops_Returns_MAP_TEMPLATE =
"std::unordered_map<std::string, std::vector<std::string>> "
"core_ops_args_info = { %s };\n"
"std::unordered_map<std::string, std::vector<std::string>> "
"core_ops_returns_info = { %s };\n";
std::string core_ops_args_info_init_str =
ConvertCoreOpsInfosToString(core_ops_args_info);
std::string core_ops_returns_info_init_str =
ConvertCoreOpsInfosToString(core_ops_returns_info);
std::string core_ops_info_str = paddle::string::Sprintf(
Core_Ops_Returns_MAP_TEMPLATE, core_ops_args_info_init_str,
core_ops_returns_info_init_str);
return core_ops_info_str;
}
static void DygraphCodeGeneration(const std::string& output_dir) {
......@@ -1953,6 +2021,8 @@ static void DygraphCodeGeneration(const std::string& output_dir) {
}
VLOG(6) << "-------- GenerateDygraphForwardCCFile -------";
fwd_function_str += "\n";
fwd_function_str += GenerateCoreOpsReturnsInfo();
GenerateForwardDygraphFile(output_dir, fwd_function_str);
VLOG(6) << "-------- GenerateForwardHFile -------";
......
......@@ -15,7 +15,6 @@ limitations under the License. */
#include <vector>
#include "paddle/fluid/eager/api/all.h"
#include "paddle/fluid/eager/api/generated/fluid_generated/dygraph_forward_api.h"
#include "paddle/fluid/eager/autograd_meta.h"
#include "paddle/fluid/eager/utils.h"
#include "paddle/fluid/memory/allocation/allocator.h"
......
......@@ -290,6 +290,41 @@ std::string GenerateOpFunctionsBody(
return op_function_str;
}
static std::string GenerateCoreOpsInfoMap() {
std::string result =
"static PyObject * eager_get_core_ops_args_info(PyObject *self) {\n"
" PyThreadState *tstate = nullptr;\n"
" try\n"
" {\n"
" return ToPyObject(core_ops_args_info);\n"
" }\n"
" catch(...) {\n"
" if (tstate) {\n"
" PyEval_RestoreThread(tstate);\n"
" }\n"
" ThrowExceptionToPython(std::current_exception());\n"
" return nullptr;\n"
" }\n"
"}\n"
"\n"
"static PyObject * eager_get_core_ops_returns_info(PyObject *self) {\n"
" PyThreadState *tstate = nullptr;\n"
" try\n"
" {\n"
" return ToPyObject(core_ops_returns_info);\n"
" }\n"
" catch(...) {\n"
" if (tstate) {\n"
" PyEval_RestoreThread(tstate);\n"
" }\n"
" ThrowExceptionToPython(std::current_exception());\n"
" return nullptr;\n"
" }\n"
"}\n";
return result;
}
static std::tuple<std::vector<std::string>, std::vector<std::string>>
GenerateOpFunctions() {
auto& op_info_map = paddle::framework::OpInfoMap::Instance().map();
......@@ -338,6 +373,8 @@ int main(int argc, char* argv[]) {
std::vector<std::string> headers{
"\"pybind11/detail/common.h\"",
"\"paddle/fluid/pybind/op_function_common.h\"",
"\"paddle/fluid/eager/api/generated/fluid_generated/"
"dygraph_forward_api.h\"",
"\"paddle/fluid/pybind/exception.h\"", "<Python.h>"};
std::ofstream out(argv[1], std::ios::out);
......@@ -351,15 +388,25 @@ int main(int argc, char* argv[]) {
out << "\n\n";
auto op_funcs = GenerateOpFunctions();
auto core_ops_infos = GenerateCoreOpsInfoMap();
std::string core_ops_infos_registry =
"{\"get_core_ops_args_info\", "
"(PyCFunction)(void(*)(void))eager_get_core_ops_args_info, METH_NOARGS, "
"\"C++ interface function for eager_get_core_ops_args_info.\"},\n"
" {\"get_core_ops_returns_info\", "
"(PyCFunction)(void(*)(void))eager_get_core_ops_returns_info, "
"METH_NOARGS, \"C++ interface function for "
"eager_get_core_ops_returns_info.\"},\n";
out << "namespace paddle {\n"
<< "namespace pybind {\n\n";
out << core_ops_infos;
out << paddle::string::join_strings(std::get<0>(op_funcs), '\n');
out << "\n\n";
out << "static PyMethodDef ExtestMethods[] = {\n"
<< paddle::string::join_strings(std::get<1>(op_funcs), '\n')
<< "\n {nullptr,nullptr,0,nullptr}"
<< paddle::string::join_strings(std::get<1>(op_funcs), '\n') << "\n"
<< core_ops_infos_registry << "\n {nullptr,nullptr,0,nullptr}"
<< "};\n\n";
out << "inline void BindEagerOpFunctions(pybind11::module *module) {\n"
......
......@@ -402,6 +402,41 @@ PyObject* ToPyObject(const void* value) {
platform::errors::Fatal("ToPyObject do not support void* with value."));
}
PyObject* ToPyObject(
const std::unordered_map<std::string, std::vector<std::string>>& value) {
PyObject* dict = PyDict_New();
for (const auto map_iter : value) {
// Convert Key
PyObject* key_string = PyUnicode_FromString(map_iter.first.c_str());
if (!key_string) {
PADDLE_THROW(
platform::errors::Fatal("Unable to convert std::string to PyObject"));
}
// Convert Val
PyObject* py_list = PyList_New(0);
for (const auto vector_iter : map_iter.second) {
PyObject* val_string = PyUnicode_FromString(vector_iter.c_str());
if (!val_string) {
PADDLE_THROW(platform::errors::Fatal(
"Unable to convert std::string to PyObject"));
}
if (PyList_Append(py_list, val_string) != 0) {
PADDLE_THROW(
platform::errors::Fatal("Unable to append string to py_list"));
}
}
if (PyDict_SetItem(dict, key_string, py_list) != 0) {
PADDLE_THROW(
platform::errors::Fatal("Unable to set key:value for py_dict"));
}
}
return dict;
}
egr::EagerTensor GetEagerTensorFromArgs(const std::string& op_type,
const std::string& arg_name,
PyObject* args, ssize_t arg_idx,
......
......@@ -54,6 +54,8 @@ PyObject* ToPyObject(const std::vector<egr::EagerTensor>& value);
PyObject* ToPyObject(const platform::Place& value);
PyObject* ToPyObject(const paddle::framework::proto::VarType::Type& dtype);
PyObject* ToPyObject(const void* value);
PyObject* ToPyObject(
const std::unordered_map<std::string, std::vector<std::string>>& value);
template <typename Tuple, size_t N>
struct TupleEagerTensorResult {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册