-
Notifications
You must be signed in to change notification settings - Fork 5.9k
use PYTHON_C_API in dygraph #32524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use PYTHON_C_API in dygraph #32524
Conversation
|
Thanks for your contribution! |
|
Sorry to inform you that 090a540's CIs have passed for more than 7 days. To prevent PR conflicts, you need to re-run all CIs manually. |
| const char* IN_VAR_LIST_TYPE = R"(py::handle)"; | ||
|
|
||
| const char* OUT_VAR_TYPE = R"(std::shared_ptr<imperative::VarBase>)"; | ||
| const char* OUT_VAR_LIST_TYPE = R"(std::vector<std::shared_ptr<imperative::VarBase>>)"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
在这个文件上面,output创建这个地方,貌似用make_shared更快一些,可以试一试
const char* OUT_INITIALIZER_TEMPLATE =
R"({"%s", {std::shared_ptr<imperative::VarBase>(new imperative::VarBase(tracer->GenerateUniqueName()))}})";
https://stackoverflow.com/questions/20895648/difference-in-make-shared-and-normal-shared-ptr-in-c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
我改完,使用core.ops.elementwise_add测了一下,没有发现明显收益。但既然理论上make_shared更优,应当在一些地方还是有收益的。只是在core.ops.elementwise_add这种极简单的测试场景下体现不出来。
现在已经改成了使用make_shared。
paddle/fluid/pybind/op_function.h
Outdated
| namespace paddle { | ||
| namespace pybind { | ||
|
|
||
| std::unordered_map< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
编程规范里有这样一条,禁止定义静态生存周期的对象,这个地方建议用单例模式管理,以明确对象的初始化顺序

https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/scoping/#static-and-global-variables
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,thx!
paddle/fluid/pybind/op_function.h
Outdated
| if (PyObject_CheckLong(obj)) { | ||
| attrs[key] = (int)PyLong_AsLong(obj); // NOLINT | ||
| } else { | ||
| PADDLE_THROW(platform::errors::InvalidArgument( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个THROW语句都是重复的,要不要写到一个地方统一调用,之后如果要完善报错信息会好维护一些
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
是有些THROW是重复的,但有些地方有细微的差异。另外,抛出异常的行数是比较重要的调试信息。如果放到统一的地方THROW,行数信息就丢掉了。我保持了原样。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
也可以写成宏,可以保留行号。
paddle/fluid/pybind/op_function.h
Outdated
| return result; | ||
| } | ||
|
|
||
| void init_ops_attrtype_map() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
建议函数命名风格统一,这里也使用驼峰式命名
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,thx!
paddle/fluid/pybind/op_function.h
Outdated
| PyObject* EnforceNotMetException = | ||
| PyErr_NewException("paddle.EnforceNotMet", PyExc_Exception, NULL); | ||
|
|
||
| void throw_exception_to_python(std::exception_ptr p) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
同上
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,thx!
paddle/fluid/pybind/imperative.cc
Outdated
| namespace paddle { | ||
| namespace pybind { | ||
|
|
||
| PyTypeObject *g_VarBase_PyType = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better use either camelcase(variableName) or underscores(variable_name), not combined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,thx!
paddle/fluid/pybind/op_function.h
Outdated
| #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION | ||
| #define PY_ARRAY_UNIQUE_SYMBOL MY_PyArray_API |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it seem no usage of these marcos?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个是为了解决include numpy的头文件导致的编译错误。
paddle/fluid/pybind/op_function.h
Outdated
| #define INIT_NUMPY_ARRAY_CPP | ||
| #ifndef INIT_NUMPY_ARRAY_CPP | ||
| #define NO_IMPORT_ARRAY // for usual translation units | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why need this macro?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
不必要的已经删除
paddle/fluid/pybind/op_function.h
Outdated
| #include "paddle/fluid/imperative/type_defs.h" | ||
| #include "paddle/fluid/pybind/imperative.h" | ||
| #pragma GCC diagnostic ignored "-Wconversion-null" | ||
| #pragma GCC diagnostic ignored "-Wunused-variable" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why ignore warning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
最早有些实现方式需要用到,现在已经不需要了,已经删除。
paddle/fluid/pybind/op_function.h
Outdated
| int init_numpy() { | ||
| import_array(); | ||
| return 0; | ||
| } | ||
| const static int numpy_initialized = init_numpy(); // NOLINT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest add some comments on this, it is not easy to follow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
最早有些实现方式需要用到,现在已经不需要了,已经删除。
paddle/fluid/pybind/op_function.h
Outdated
| } | ||
|
|
||
| inline bool PyObject_CheckFloat(PyObject* obj) { | ||
| return PyFloat_Check(obj) || PyLong_Check(obj) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better comment on why PyLong_Check is added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,thx!
paddle/fluid/pybind/op_function.h
Outdated
| PADDLE_ENFORCE_EQ( | ||
| (attr_end - attr_start + 1) % 2, 0, | ||
| platform::errors::InvalidArgument( | ||
| "The number of arguments for arributes should be even.")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: arributes -> attributes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,thx!
paddle/fluid/pybind/op_function.h
Outdated
| const std::string& op_type, PyObject* args, ssize_t attr_start, | ||
| ssize_t attr_end, paddle::framework::AttributeMap& attrs) { // NOLINT | ||
| PADDLE_ENFORCE_EQ( | ||
| (attr_end - attr_start + 1) % 2, 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not important. I suggest passing attr_end+1 directly to avoid some problems, [start, end) is commonly used (which means start is reachable and end is not).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,thx!
paddle/fluid/pybind/op_function.h
Outdated
| auto attr_type_map = &(OpAttrTypeMap::Instance().Map()[op_type]); | ||
|
|
||
| PyObject* obj = nullptr; | ||
| for (ssize_t arg_pos = attr_start; arg_pos < attr_end + 1; arg_pos += 2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for attr_end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,thx!
| py::gil_scoped_release release; | ||
| %s | ||
| framework::AttributeMap attrs; | ||
| ConstructAttrMapFromPyArgs("%s", args, %d, PyTuple_GET_SIZE(args)-1 , attrs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better pass PyTuple_GET_SIZE(args).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,thx!
paddle/fluid/pybind/op_function.h
Outdated
| const char* key_prt; | ||
| obj = PyTuple_GET_ITEM(args, arg_pos); | ||
| if (PyObject_CheckString(obj)) { | ||
| key_prt = PyUnicode_AsUTF8AndSize(obj, &key_len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, key_prt -> key_ptr ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done,thx!
paddle/fluid/pybind/op_function.h
Outdated
| if (PyObject_CheckLong(obj)) { | ||
| attrs[key] = (int)PyLong_AsLong(obj); // NOLINT | ||
| } else { | ||
| PADDLE_THROW(platform::errors::InvalidArgument( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
也可以写成宏,可以保留行号。
| break; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest adding a function for each case to make this function short.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
已经为每个case创建了函数,PADDLE_THROW不仅是行号的问题,认真看报错内容的话,不同的PADDLE_THROW抛出的异常内容、格式略有差别,不适合封装公共异常抛出代码。
| op_type, arg_name, arg_idx, | ||
| ((PyTypeObject*)((PyObject*)item)->ob_type)->tp_name)); // NOLINT | ||
| } | ||
| void** vh = item->simple_layout ? item->simple_value_holder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better add comments on simple_layout?
| void** vh = item->simple_layout ? item->simple_value_holder | ||
| : &item->nonsimple.values_and_holders[0]; | ||
| result.emplace_back( | ||
| reinterpret_cast<std::shared_ptr<paddle::imperative::VarBase>&>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed offline, what will be happended to the lifetime fo VarBase?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of using NULL macro, using nullptr would be better.
done.thx! |



PR types
Performance optimization
PR changes
Others
Describe
动态图对外暴露core.ops不再使用pybind11,改用Python_c_API。原因是Python_c_API的性能要更好一些,以降低动态图的调度成本。
本PR的修改的一些关键点:
其中自动生成的
op_function_impl.h代码请见:https://gist.github.com/wanghuancoder/65be9f6d527e7da036f9ff5bc347c9bc
经测试,动态图性能略有提升:
core.ops.elementwise_add耗时点对比: