From d7d490e413a89e8595cf50d7547c7098f6334d59 Mon Sep 17 00:00:00 2001 From: DesmonDay <908660116@qq.com> Date: Wed, 1 Feb 2023 07:01:31 +0000 Subject: [PATCH 1/4] fix to_dlpack for loop --- paddle/fluid/pybind/tensor.cc | 18 ++++++------------ python/paddle/tests/test_dlpack.py | 6 ++++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/paddle/fluid/pybind/tensor.cc b/paddle/fluid/pybind/tensor.cc index 4bdde24f431bc..29a17d25d9dc2 100644 --- a/paddle/fluid/pybind/tensor.cc +++ b/paddle/fluid/pybind/tensor.cc @@ -475,20 +475,14 @@ void BindTensor(pybind11::module &m) { // NOLINT [](phi::DenseTensor &self) { DLPackTensor dlpack_tensor(self, 1); DLManagedTensor *dmt = dlpack_tensor.ToDLManagedTensor(); - auto capsule = py::capsule( + auto capsule = pybind11::capsule( static_cast(dmt), "dltensor", [](PyObject *ptr) { - if (ptr) { - auto dltensor = new DLManagedTensor; - try { - dltensor = reinterpret_cast( - PyCapsule_GetPointer(ptr, "used_dltensor")); - return; - } catch (...) { - dltensor = reinterpret_cast( - PyCapsule_GetPointer(ptr, "dltensor")); - } - dltensor->deleter(dltensor); + if (!PyCapsule_IsValid(ptr, "dltensor")) { + return; } + DLManagedTensor *dmt = static_cast( + PyCapsule_GetPointer(ptr, "dltensor")); + dmt->deleter(dmt); }); return capsule; }) diff --git a/python/paddle/tests/test_dlpack.py b/python/paddle/tests/test_dlpack.py index 77ffdbecedbf6..504ff4c48c66e 100644 --- a/python/paddle/tests/test_dlpack.py +++ b/python/paddle/tests/test_dlpack.py @@ -116,6 +116,12 @@ def test_dlpack_deletion(self): dlpack = paddle.utils.dlpack.to_dlpack(a) b = paddle.utils.dlpack.from_dlpack(dlpack) + def test_to_dlpack_for_loop(self): + # See Paddle issue 50120 + for i in range(10): + x = paddle.rand([3, 5]) + dlpack = paddle.utils.dlpack.to_dlpack(x) + class TestRaiseError(unittest.TestCase): def test_from_dlpack_raise_type_error(self): From 94cf213dc15f5c7f08f8d01f16f7ce0a0a9be536 Mon Sep 17 00:00:00 2001 From: DesmonDay <908660116@qq.com> Date: Wed, 1 Feb 2023 10:41:57 +0000 Subject: [PATCH 2/4] fix reference count --- paddle/fluid/framework/dlpack_tensor.cc | 11 +++++++++-- paddle/fluid/framework/dlpack_tensor.h | 4 +++- paddle/fluid/pybind/tensor.cc | 2 ++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/paddle/fluid/framework/dlpack_tensor.cc b/paddle/fluid/framework/dlpack_tensor.cc index 32c6e17143fa2..419eb0e7fe849 100644 --- a/paddle/fluid/framework/dlpack_tensor.cc +++ b/paddle/fluid/framework/dlpack_tensor.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "paddle/fluid/framework/dlpack_tensor.h" +#include "pybind11/pybind11.h" #include "paddle/fluid/framework/convert_utils.h" #include "paddle/fluid/framework/data_type.h" @@ -134,8 +135,9 @@ struct DLDeviceVisitor }; } // namespace internal -DLPackTensor::DLPackTensor(const phi::DenseTensor &tensor, LaneType lanes) { +DLPackTensor::DLPackTensor(phi::DenseTensor &tensor, LaneType lanes) { // init data, data buffer + dt_ = &tensor; t_.data = const_cast(tensor.data()); // init device, DLDevice type with device_type and device_id @@ -188,12 +190,17 @@ ::DLManagedTensor *DLPackTensor::ToDLManagedTensor() { tensor->dl_tensor = t_; tensor->deleter = [](DLManagedTensor *arg) { + phi::DenseTensor *tensor_ptr = + reinterpret_cast(arg->manager_ctx); + pybind11::handle tensor_handle = pybind11::cast(tensor_ptr); + tensor_handle.dec_ref(); + delete[] arg->dl_tensor.shape; delete[] arg->dl_tensor.strides; delete arg; }; - tensor->manager_ctx = nullptr; + tensor->manager_ctx = dt_; return tensor; } diff --git a/paddle/fluid/framework/dlpack_tensor.h b/paddle/fluid/framework/dlpack_tensor.h index c6fca6707fad2..2fcd2511afb8b 100644 --- a/paddle/fluid/framework/dlpack_tensor.h +++ b/paddle/fluid/framework/dlpack_tensor.h @@ -28,7 +28,7 @@ class DLPackTensor { std::remove_reference::type; // int64_t // lanes is only used in CPU to enable vectorization - explicit DLPackTensor(const phi::DenseTensor& tensor, LaneType lanes = 1); + explicit DLPackTensor(phi::DenseTensor& tensor, LaneType lanes = 1); inline operator const ::DLTensor&() const { return t_; } @@ -42,6 +42,8 @@ class DLPackTensor { // The shape in DLTensor is defined as int64_t* // Add this member to make TVMTensor init without heap allocation ShapeType shape_[DDim::kMaxRank]; + + phi::DenseTensor* dt_; }; } // namespace framework diff --git a/paddle/fluid/pybind/tensor.cc b/paddle/fluid/pybind/tensor.cc index 29a17d25d9dc2..b58e697e69532 100644 --- a/paddle/fluid/pybind/tensor.cc +++ b/paddle/fluid/pybind/tensor.cc @@ -474,6 +474,8 @@ void BindTensor(pybind11::module &m) { // NOLINT .def("_to_dlpack", [](phi::DenseTensor &self) { DLPackTensor dlpack_tensor(self, 1); + pybind11::handle tensor_handle = pybind11::cast(&self); + tensor_handle.inc_ref(); DLManagedTensor *dmt = dlpack_tensor.ToDLManagedTensor(); auto capsule = pybind11::capsule( static_cast(dmt), "dltensor", [](PyObject *ptr) { From 1b8689ac7acef71f621dde88d8b3d1da83e2d17a Mon Sep 17 00:00:00 2001 From: DesmonDay <908660116@qq.com> Date: Wed, 1 Feb 2023 12:51:59 +0000 Subject: [PATCH 3/4] add code --- paddle/fluid/framework/dlpack_tensor.cc | 3 +-- paddle/fluid/framework/dlpack_tensor.h | 1 - paddle/fluid/pybind/tensor.cc | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/paddle/fluid/framework/dlpack_tensor.cc b/paddle/fluid/framework/dlpack_tensor.cc index 419eb0e7fe849..e1131e4c6d994 100644 --- a/paddle/fluid/framework/dlpack_tensor.cc +++ b/paddle/fluid/framework/dlpack_tensor.cc @@ -188,6 +188,7 @@ ::DLManagedTensor *DLPackTensor::ToDLManagedTensor() { auto tensor = new DLManagedTensor; tensor->dl_tensor = t_; + tensor->manager_ctx = dt_; tensor->deleter = [](DLManagedTensor *arg) { phi::DenseTensor *tensor_ptr = @@ -200,8 +201,6 @@ ::DLManagedTensor *DLPackTensor::ToDLManagedTensor() { delete arg; }; - tensor->manager_ctx = dt_; - return tensor; } diff --git a/paddle/fluid/framework/dlpack_tensor.h b/paddle/fluid/framework/dlpack_tensor.h index 2fcd2511afb8b..10c38a956cfda 100644 --- a/paddle/fluid/framework/dlpack_tensor.h +++ b/paddle/fluid/framework/dlpack_tensor.h @@ -42,7 +42,6 @@ class DLPackTensor { // The shape in DLTensor is defined as int64_t* // Add this member to make TVMTensor init without heap allocation ShapeType shape_[DDim::kMaxRank]; - phi::DenseTensor* dt_; }; diff --git a/paddle/fluid/pybind/tensor.cc b/paddle/fluid/pybind/tensor.cc index b58e697e69532..8b020792b6eb2 100644 --- a/paddle/fluid/pybind/tensor.cc +++ b/paddle/fluid/pybind/tensor.cc @@ -473,9 +473,9 @@ void BindTensor(pybind11::module &m) { // NOLINT )DOC") .def("_to_dlpack", [](phi::DenseTensor &self) { - DLPackTensor dlpack_tensor(self, 1); pybind11::handle tensor_handle = pybind11::cast(&self); tensor_handle.inc_ref(); + DLPackTensor dlpack_tensor(self, 1); DLManagedTensor *dmt = dlpack_tensor.ToDLManagedTensor(); auto capsule = pybind11::capsule( static_cast(dmt), "dltensor", [](PyObject *ptr) { From 6bd41ecc2af40e18583946cd970a4bca8e6b3168 Mon Sep 17 00:00:00 2001 From: DesmonDay <908660116@qq.com> Date: Sun, 5 Feb 2023 10:34:55 +0000 Subject: [PATCH 4/4] fix dlpack --- paddle/fluid/framework/dlpack_tensor.cc | 64 +++++++++++++++++++++---- paddle/fluid/framework/dlpack_tensor.h | 5 +- paddle/fluid/pybind/tensor.cc | 5 +- 3 files changed, 59 insertions(+), 15 deletions(-) diff --git a/paddle/fluid/framework/dlpack_tensor.cc b/paddle/fluid/framework/dlpack_tensor.cc index e1131e4c6d994..9bf348506655b 100644 --- a/paddle/fluid/framework/dlpack_tensor.cc +++ b/paddle/fluid/framework/dlpack_tensor.cc @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. #include "paddle/fluid/framework/dlpack_tensor.h" -#include "pybind11/pybind11.h" #include "paddle/fluid/framework/convert_utils.h" #include "paddle/fluid/framework/data_type.h" @@ -135,9 +134,60 @@ struct DLDeviceVisitor }; } // namespace internal -DLPackTensor::DLPackTensor(phi::DenseTensor &tensor, LaneType lanes) { +struct PaddleDLMTensor { + phi::DenseTensor handle; + DLManagedTensor tensor; +}; + +void deleter(DLManagedTensor *arg) { + delete[] arg->dl_tensor.shape; + delete[] arg->dl_tensor.strides; + delete static_cast(arg->manager_ctx); +} + +DLManagedTensor *toDLPack(const phi::DenseTensor &src) { + PaddleDLMTensor *pdDLMTensor(new PaddleDLMTensor); + pdDLMTensor->handle = const_cast(src); + pdDLMTensor->tensor.manager_ctx = pdDLMTensor; + pdDLMTensor->tensor.deleter = &deleter; + pdDLMTensor->tensor.dl_tensor.data = const_cast(src.data()); + + // init ndim + using DimType = decltype(pdDLMTensor->tensor.dl_tensor.ndim); // int + pdDLMTensor->tensor.dl_tensor.ndim = static_cast(src.dims().size()); + DimType ndim = pdDLMTensor->tensor.dl_tensor.ndim; + + // init shape + auto shape = new int64_t[ndim]; + for (DimType i = 0; i < ndim; ++i) { + shape[i] = src.dims()[i]; + } + pdDLMTensor->tensor.dl_tensor.shape = shape; + + // init stride + auto strides = new int64_t[ndim]; + for (DimType i = 0; i < ndim; ++i) { + strides[i] = 1; + } + for (DimType i = ndim - 2; i >= 0; --i) { + strides[i] = shape[i + 1] * strides[i + 1]; + } + pdDLMTensor->tensor.dl_tensor.strides = strides; + + // init device, DLDevice type with device_type and device_id + auto place = src.place(); + pdDLMTensor->tensor.dl_tensor.device = + paddle::platform::VisitPlace(place, internal::DLDeviceVisitor()); + + pdDLMTensor->tensor.dl_tensor.dtype = internal::GetDLDataTypeFromTypeIndex( + framework::TransToProtoVarType(src.dtype())); + + pdDLMTensor->tensor.dl_tensor.byte_offset = 0; + return &(pdDLMTensor->tensor); +} + +DLPackTensor::DLPackTensor(const phi::DenseTensor &tensor, LaneType lanes) { // init data, data buffer - dt_ = &tensor; t_.data = const_cast(tensor.data()); // init device, DLDevice type with device_type and device_id @@ -188,19 +238,15 @@ ::DLManagedTensor *DLPackTensor::ToDLManagedTensor() { auto tensor = new DLManagedTensor; tensor->dl_tensor = t_; - tensor->manager_ctx = dt_; tensor->deleter = [](DLManagedTensor *arg) { - phi::DenseTensor *tensor_ptr = - reinterpret_cast(arg->manager_ctx); - pybind11::handle tensor_handle = pybind11::cast(tensor_ptr); - tensor_handle.dec_ref(); - delete[] arg->dl_tensor.shape; delete[] arg->dl_tensor.strides; delete arg; }; + tensor->manager_ctx = nullptr; + return tensor; } diff --git a/paddle/fluid/framework/dlpack_tensor.h b/paddle/fluid/framework/dlpack_tensor.h index 10c38a956cfda..4cd6d97a0c5cc 100644 --- a/paddle/fluid/framework/dlpack_tensor.h +++ b/paddle/fluid/framework/dlpack_tensor.h @@ -28,7 +28,7 @@ class DLPackTensor { std::remove_reference::type; // int64_t // lanes is only used in CPU to enable vectorization - explicit DLPackTensor(phi::DenseTensor& tensor, LaneType lanes = 1); + explicit DLPackTensor(const phi::DenseTensor& tensor, LaneType lanes = 1); inline operator const ::DLTensor&() const { return t_; } @@ -42,8 +42,9 @@ class DLPackTensor { // The shape in DLTensor is defined as int64_t* // Add this member to make TVMTensor init without heap allocation ShapeType shape_[DDim::kMaxRank]; - phi::DenseTensor* dt_; }; +DLManagedTensor* toDLPack(const phi::DenseTensor& src); + } // namespace framework } // namespace paddle diff --git a/paddle/fluid/pybind/tensor.cc b/paddle/fluid/pybind/tensor.cc index 8b020792b6eb2..570920022e8a9 100644 --- a/paddle/fluid/pybind/tensor.cc +++ b/paddle/fluid/pybind/tensor.cc @@ -473,10 +473,7 @@ void BindTensor(pybind11::module &m) { // NOLINT )DOC") .def("_to_dlpack", [](phi::DenseTensor &self) { - pybind11::handle tensor_handle = pybind11::cast(&self); - tensor_handle.inc_ref(); - DLPackTensor dlpack_tensor(self, 1); - DLManagedTensor *dmt = dlpack_tensor.ToDLManagedTensor(); + DLManagedTensor *dmt = framework::toDLPack(self); auto capsule = pybind11::capsule( static_cast(dmt), "dltensor", [](PyObject *ptr) { if (!PyCapsule_IsValid(ptr, "dltensor")) {