Skip to content

[Cpp Extension] Support Cpp Extension #49893

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

Merged
merged 47 commits into from
Feb 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
df60146
update include directory
jiahy0825 Jan 6, 2023
1a8266e
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
jiahy0825 Jan 16, 2023
a088e18
fully support C++ extension, pass unittest
jiahy0825 Jan 17, 2023
cfd2b50
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
jiahy0825 Jan 17, 2023
716a7be
fix include directory
jiahy0825 Jan 17, 2023
3c0c182
support both extension and operator in one file
jiahy0825 Jan 17, 2023
4c24472
polish testcase
jiahy0825 Jan 17, 2023
2352468
add jit unittest
jiahy0825 Jan 17, 2023
98c9ef0
update third_party.cmake, pass CI test
jiahy0825 Jan 18, 2023
36d39ef
fix cmake
jiahy0825 Jan 18, 2023
c6ff3d7
fix setup
jiahy0825 Jan 18, 2023
8330201
fix inference, fix unittest precision
jiahy0825 Jan 18, 2023
1e42f72
fix unittest precision
jiahy0825 Jan 18, 2023
2b77782
fix inference_lib cmake
jiahy0825 Jan 18, 2023
3ea9292
try fix setup, try fix inference_lib
jiahy0825 Jan 18, 2023
81c3982
try fix inference_lib pybind
jiahy0825 Jan 18, 2023
e2cbfaa
fix mix_op_extension, fix inference_lib
jiahy0825 Jan 19, 2023
be02319
fix mix_op_extension, fix inference_lib
jiahy0825 Jan 19, 2023
7cb1dbf
change cmake
jiahy0825 Jan 19, 2023
2013aaa
change cmake
jiahy0825 Jan 19, 2023
21e71ef
add compile flags
jiahy0825 Jan 20, 2023
dfa0cb4
add Python.h headerfile
jiahy0825 Jan 26, 2023
adc6129
add test_custom_plugin_creater cmake
jiahy0825 Jan 26, 2023
a32ef46
comment compile flag
jiahy0825 Jan 26, 2023
1a55aef
pass all CI
jiahy0825 Jan 27, 2023
4ef6175
pass all CI
jiahy0825 Jan 27, 2023
af05e34
comment compile flag
jiahy0825 Jan 27, 2023
4c34a8b
try solve test_custom_plugin_creater link error
jiahy0825 Jan 28, 2023
7c822c3
try solve test_custom_plugin_creater link error
jiahy0825 Jan 28, 2023
65f184d
polish codes
jiahy0825 Jan 28, 2023
79a15d3
remove windows compile flag
jiahy0825 Jan 28, 2023
a71887f
remove python_include_path
jiahy0825 Jan 28, 2023
e05ed87
update pybind11, 2.4.3->2.6.0
jiahy0825 Jan 28, 2023
9738fb9
update pybind11, 2.6.0->2.10.0
jiahy0825 Jan 28, 2023
23e63e6
update pybind11, 2.10.0->2.6.0b1
jiahy0825 Jan 28, 2023
63cf859
update pybind11, 2.6.0b1->2.6.0, start fix unittest
jiahy0825 Jan 28, 2023
95c5be8
fix pybind11 2.6.0 VarBase print error
jiahy0825 Jan 29, 2023
08f99dc
fix pybind11 2.6.0 VarBase print error
jiahy0825 Jan 29, 2023
45bc3b8
handle PADDLE_ON_INFERENCE
jiahy0825 Jan 30, 2023
85c4abd
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
jiahy0825 Jan 31, 2023
c193063
modify according to reviewer
jiahy0825 Feb 1, 2023
6a20c8f
fix cmake
jiahy0825 Feb 1, 2023
3063de9
cmake decouple pybind_util when not ON_INFER
jiahy0825 Feb 2, 2023
8609d90
cmake decouple pybind_util when not ON_INFER
jiahy0825 Feb 2, 2023
4b9126e
remove copy of inference_lib.cmake
jiahy0825 Feb 3, 2023
68e2e9f
change pybind.cc headerfile fluid->phi
jiahy0825 Feb 10, 2023
941d674
Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into…
jiahy0825 Feb 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmake/third_party.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ if(TARGET extern_protobuf)
list(APPEND third_party_deps extern_protobuf)
endif()

if(WITH_PYTHON)
if(NOT ((NOT WITH_PYTHON) AND ON_INFER))
include(external/python) # find python and python_module
include(external/pybind11) # download pybind11
list(APPEND third_party_deps extern_pybind)
Expand Down
4 changes: 4 additions & 0 deletions paddle/extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ limitations under the License. */

// All paddle apis in C++ frontend
#include "paddle/phi/api/all.h"
// Python bindings for the C++ frontend
#ifndef PADDLE_ON_INFERENCE
#include "paddle/utils/pybind.h"
#endif
1 change: 1 addition & 0 deletions paddle/fluid/pybind/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ if(WITH_PYTHON)
list(APPEND PYBIND_DEPS eager_tensor_operants)
list(APPEND PYBIND_DEPS static_tensor_operants)
list(APPEND PYBIND_DEPS phi_tensor_operants)
list(APPEND PYBIND_DEPS pybind_util)
endif()

# On Linux, cc_library(paddle SHARED ..) will generate the libpaddle.so,
Expand Down
4 changes: 2 additions & 2 deletions paddle/fluid/pybind/eager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ namespace pybind {

namespace py = ::pybind11;

PyTypeObject* p_tensor_type;
PyTypeObject* p_string_tensor_type; // For StringTensor
extern PyTypeObject* p_tensor_type;
extern PyTypeObject* p_string_tensor_type; // For StringTensor
extern PyTypeObject* g_vartype_pytype;
extern PyTypeObject* g_framework_tensor_pytype;

Expand Down
7 changes: 1 addition & 6 deletions paddle/fluid/pybind/eager.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,13 @@ limitations under the License. */
#include "paddle/fluid/eager/hooks.h"
#include "paddle/fluid/eager/pylayer/py_layer_node.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/utils/pybind.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"

namespace paddle {
namespace pybind {

typedef struct {
PyObject_HEAD paddle::experimental::Tensor tensor;
// Weak references
PyObject* weakrefs;
} TensorObject;

typedef struct {
PyObject_HEAD PyObject* container;
bool container_be_packed;
Expand Down
42 changes: 0 additions & 42 deletions paddle/fluid/pybind/eager_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -211,24 +211,6 @@ std::string CastPyArg2AttrString(PyObject* obj, ssize_t arg_pos) {
}
}

bool PyCheckTensor(PyObject* obj) {
return PyObject_IsInstance(obj, reinterpret_cast<PyObject*>(p_tensor_type));
}

paddle::experimental::Tensor CastPyArg2Tensor(PyObject* obj, ssize_t arg_pos) {
if (PyObject_IsInstance(obj, reinterpret_cast<PyObject*>(p_tensor_type)) ||
PyObject_IsInstance(obj,
reinterpret_cast<PyObject*>(p_string_tensor_type))) {
return reinterpret_cast<TensorObject*>(obj)->tensor;
} else {
PADDLE_THROW(platform::errors::InvalidArgument(
"argument (position %d) must be "
"Tensor, but got %s",
arg_pos + 1,
reinterpret_cast<PyTypeObject*>(obj->ob_type)->tp_name));
}
}

std::shared_ptr<imperative::VarBase> CastPyArg2VarBase(PyObject* obj,
ssize_t arg_pos) {
return py::cast<std::shared_ptr<imperative::VarBase>>(obj);
Expand Down Expand Up @@ -662,30 +644,6 @@ PyObject* ToPyObject(const std::string& value) {
return PyUnicode_FromString(value.c_str());
}

PyObject* ToPyObject(const paddle::experimental::Tensor& value,
bool return_py_none_if_not_initialize) {
if (return_py_none_if_not_initialize && !value.initialized()) {
RETURN_PY_NONE
}
PyObject* obj = nullptr;
if (value.initialized() && value.is_string_tensor()) {
// In order to return the core.eager.StringTensor, there is need
// to use p_string_tensor_type to create a python obj.
obj = p_string_tensor_type->tp_alloc(p_string_tensor_type, 0);
} else {
obj = p_tensor_type->tp_alloc(p_tensor_type, 0);
}
if (obj) {
auto v = reinterpret_cast<TensorObject*>(obj);
new (&(v->tensor)) paddle::experimental::Tensor();
v->tensor = value;
} else {
PADDLE_THROW(platform::errors::Fatal(
"tp_alloc return null, can not new a PyObject."));
}
return obj;
}

PyObject* ToPyObject(const paddle::experimental::Tensor& value,
PyObject* args,
const std::map<ssize_t, ssize_t>& inplace_var_idx_map) {
Expand Down
9 changes: 1 addition & 8 deletions paddle/fluid/pybind/eager_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ typedef SSIZE_T ssize_t;
#include "paddle/phi/common/scalar.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/selected_rows.h"
#include "paddle/utils/pybind.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"
namespace paddle {
Expand All @@ -44,14 +45,9 @@ class Scope;
namespace pybind {

namespace py = ::pybind11;
#define RETURN_PY_NONE \
Py_INCREF(Py_None); \
return Py_None;

int TensorDtype2NumpyDtype(phi::DataType dtype);

bool PyCheckTensor(PyObject* obj);

bool PyObject_CheckLongOrConvertToLong(PyObject** obj);
bool PyObject_CheckFloatOrConvertToFloat(PyObject** obj);
bool PyObject_CheckStr(PyObject* obj);
Expand All @@ -63,7 +59,6 @@ float CastPyArg2AttrFloat(PyObject* obj, ssize_t arg_pos);
std::string CastPyArg2AttrString(PyObject* obj, ssize_t arg_pos);
paddle::CustomOpKernelContext CastPyArg2CustomOpKernelContext(PyObject* obj,
ssize_t arg_pos);
paddle::experimental::Tensor CastPyArg2Tensor(PyObject* obj, ssize_t arg_pos);
std::shared_ptr<imperative::VarBase> CastPyArg2VarBase(PyObject* obj,
ssize_t arg_pos);
std::vector<paddle::experimental::Tensor> CastPyArg2VectorOfTensor(
Expand Down Expand Up @@ -94,8 +89,6 @@ PyObject* ToPyObject(float value);
PyObject* ToPyObject(double value);
PyObject* ToPyObject(const char* value);
PyObject* ToPyObject(const std::string& value);
PyObject* ToPyObject(const paddle::experimental::Tensor& value,
bool return_py_none_if_not_initialize = false);
PyObject* ToPyObject(const paddle::experimental::Tensor& value,
PyObject* args,
const std::map<ssize_t, ssize_t>& inplace_var_idx_map);
Expand Down
7 changes: 7 additions & 0 deletions paddle/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@ cc_test(
variant_test
SRCS variant_test.cc
DEPS gtest)

if(NOT ((NOT WITH_PYTHON) AND ON_INFER))
cc_library(
pybind_util
SRCS pybind.cc
DEPS phi_tensor_raw)
endif()
70 changes: 70 additions & 0 deletions paddle/utils/pybind.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle/utils/pybind.h"
#include "paddle/phi/core/enforce.h"

namespace paddle {
namespace pybind {

PyTypeObject* p_tensor_type;
PyTypeObject* p_string_tensor_type;

bool PyCheckTensor(PyObject* obj) {
if (!p_tensor_type) {
return false;
}
return PyObject_IsInstance(obj, reinterpret_cast<PyObject*>(p_tensor_type));
}

paddle::experimental::Tensor CastPyArg2Tensor(PyObject* obj, ssize_t arg_pos) {
if (PyObject_IsInstance(obj, reinterpret_cast<PyObject*>(p_tensor_type)) ||
PyObject_IsInstance(obj,
reinterpret_cast<PyObject*>(p_string_tensor_type))) {
return reinterpret_cast<TensorObject*>(obj)->tensor;
} else {
PADDLE_THROW(phi::errors::InvalidArgument(
"argument (position %d) must be "
"Tensor, but got %s",
arg_pos + 1,
reinterpret_cast<PyTypeObject*>(obj->ob_type)->tp_name));
}
}

PyObject* ToPyObject(const paddle::experimental::Tensor& value,
bool return_py_none_if_not_initialize) {
if (return_py_none_if_not_initialize && !value.initialized()) {
RETURN_PY_NONE
}
PyObject* obj = nullptr;
if (value.initialized() && value.is_string_tensor()) {
// In order to return the core.eager.StringTensor, there is need
// to use p_string_tensor_type to create a python obj.
obj = p_string_tensor_type->tp_alloc(p_string_tensor_type, 0);
} else {
obj = p_tensor_type->tp_alloc(p_tensor_type, 0);
}
if (obj) {
auto v = reinterpret_cast<TensorObject*>(obj);
new (&(v->tensor)) paddle::experimental::Tensor();
v->tensor = value;
} else {
PADDLE_THROW(
phi::errors::Fatal("tp_alloc return null, can not new a PyObject."));
}
return obj;
}

} // namespace pybind
} // namespace paddle
76 changes: 76 additions & 0 deletions paddle/utils/pybind.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include "paddle/phi/api/include/tensor.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"

namespace py = pybind11;

namespace paddle {
namespace pybind {

extern PyTypeObject* p_tensor_type;

typedef struct {
PyObject_HEAD paddle::experimental::Tensor tensor;
// Weak references
PyObject* weakrefs;
} TensorObject;

#define RETURN_PY_NONE \
Py_INCREF(Py_None); \
return Py_None;

// Internal use only, to expose the Tensor type to Python.
bool PyCheckTensor(PyObject* obj);

// Internal use only, to expose the Tensor type to Python.
paddle::experimental::Tensor CastPyArg2Tensor(PyObject* obj, ssize_t arg_pos);

// Internal use only, to expose the Tensor type to Python.
PyObject* ToPyObject(const paddle::experimental::Tensor& value,
bool return_py_none_if_not_initialize = false);

} // namespace pybind
} // namespace paddle

namespace pybind11 {
namespace detail {

template <>
struct type_caster<paddle::experimental::Tensor> {
public:
PYBIND11_TYPE_CASTER(paddle::experimental::Tensor,
_("paddle::experimental::Tensor"));

bool load(handle src, bool) {
PyObject* obj = src.ptr();
if (paddle::pybind::PyCheckTensor(obj)) {
value = paddle::pybind::CastPyArg2Tensor(obj, 0);
return true;
}
return false;
}

static handle cast(const paddle::experimental::Tensor& src,
return_value_policy /* policy */,
handle /* parent */) {
return handle(paddle::pybind::ToPyObject(src));
}
};
} // namespace detail
} // namespace pybind11
3 changes: 2 additions & 1 deletion python/env_dict.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,6 @@ env_dict={
'ORIGIN':'@ORIGIN@',
'WIN32':'@WIN32@',
'JIT_RELEASE_WHL':'@JIT_RELEASE_WHL@',
'WITH_PSLIB':'@WITH_PSLIB@'
'WITH_PSLIB':'@WITH_PSLIB@',
'PYBIND_INCLUDE_DIR':'@PYBIND_INCLUDE_DIR@'
}
1 change: 1 addition & 0 deletions python/paddle/fluid/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ endforeach()

add_subdirectory(unittests)
add_subdirectory(book)
add_subdirectory(cpp_extension)
add_subdirectory(custom_op)
add_subdirectory(custom_kernel)
add_subdirectory(custom_runtime)
5 changes: 5 additions & 0 deletions python/paddle/fluid/tests/cpp_extension/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
py_test(test_cpp_extension_setup SRCS test_cpp_extension_setup.py)
py_test(test_cpp_extension_jit SRCS test_cpp_extension_jit.py)

set_tests_properties(test_cpp_extension_setup PROPERTIES TIMEOUT 120)
set_tests_properties(test_cpp_extension_jit PROPERTIES TIMEOUT 120)
38 changes: 38 additions & 0 deletions python/paddle/fluid/tests/cpp_extension/cpp_extension_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
from site import getsitepackages

from paddle.utils.cpp_extension import CppExtension, setup

paddle_includes = []
for site_packages_path in getsitepackages():
paddle_includes.append(
os.path.join(site_packages_path, 'paddle', 'include')
)
paddle_includes.append(
os.path.join(site_packages_path, 'paddle', 'include', 'third_party')
)

setup(
name='custom_cpp_extension',
ext_modules=CppExtension(
sources=["custom_add.cc", "custom_sub.cc"],
include_dirs=paddle_includes
+ [os.path.dirname(os.path.abspath(__file__))],
extra_compile_args={'cc': ['-w', '-g']},
verbose=True,
),
)
Loading