Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
7 changes: 5 additions & 2 deletions python/pylibcudf/pylibcudf/column.pxd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2023-2024, NVIDIA CORPORATION.
# Copyright (c) 2023-2025, NVIDIA CORPORATION.

from libcpp.memory cimport unique_ptr
from libcpp.vector cimport vector
Expand Down Expand Up @@ -35,7 +35,10 @@ cdef class Column:
cdef Column from_libcudf(unique_ptr[column] libcudf_col)

@staticmethod
cdef Column from_column_view(const column_view& libcudf_col, Column owner)
cdef Column from_column_view(const column_view& cv, Column owner)

@staticmethod
cdef Column from_column_view_of_arbitrary(const column_view& cv, object owner)

cpdef DataType type(self)
cpdef Column child(self, size_type index)
Expand Down
59 changes: 49 additions & 10 deletions python/pylibcudf/pylibcudf/column.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ cdef class Column:

@staticmethod
cdef Column from_column_view(const column_view& cv, Column owner):
"""Create a Column from a libcudf column_view.
"""Create a Column from a libcudf column_view into a Column owner.

This method accepts shared ownership of the underlying data from the
owner and relies on the offset from the view.
Expand All @@ -210,23 +210,62 @@ cdef class Column:
calling libcudf algorithms, and should generally not be needed by users
(even direct pylibcudf Cython users).
"""
cdef DataType dtype = DataType.from_libcudf(cv.type())
cdef size_type size = cv.size()
cdef size_type null_count = cv.null_count()
children = []
cdef size_type i
if cv.num_children() != 0:
for i in range(cv.num_children()):
children.append(Column.from_column_view(cv.child(i), owner.child(i)))

return Column(
DataType.from_libcudf(cv.type()),
cv.size(),
owner._data,
owner._mask,
cv.null_count(),
cv.offset(),
children,
)

# Ideally this function would simply be handled via a fused type in
# from_column_view, but this does not work due to
# https://github.com/cython/cython/issues/6740
@staticmethod
cdef Column from_column_view_of_arbitrary(const column_view& cv, object owner):
"""Create a Column from a libcudf column_view into an arbitrary owner.

This method accepts shared ownership of the underlying data from the owner.
Since the owner may be any arbitrary object, every child Column also shares
ownership of the same buffer since they do not have the information available to
choose to only own subsets of it.

This method is for pylibcudf's functions to use to ingest outputs of
calling libcudf algorithms, and should generally not be needed by users
(even direct pylibcudf Cython users).
"""
# For efficiency, prohibit calling this overload with a Column owner.
assert not isinstance(owner, Column)

children = []
cdef size_type i
if cv.num_children() != 0:
for i in range(cv.num_children()):
children.append(
Column.from_column_view(cv.child(i), owner.child(i))
Column.from_column_view_of_arbitrary(cv.child(i), owner)
)

cdef gpumemoryview owning_data = gpumemoryview.from_pointer(
<Py_ssize_t> cv.head[char](), owner
)
cdef gpumemoryview owning_mask = gpumemoryview.from_pointer(
<Py_ssize_t> cv.null_mask(), owner
)

return Column(
dtype,
size,
owner._data,
owner._mask,
null_count,
DataType.from_libcudf(cv.type()),
cv.size(),
owning_data,
owning_mask,
cv.null_count(),
cv.offset(),
children,
)
Expand Down
12 changes: 3 additions & 9 deletions python/pylibcudf/pylibcudf/contiguous_split.pyx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2024, NVIDIA CORPORATION.
# Copyright (c) 2024-2025, NVIDIA CORPORATION.

from cython.operator cimport dereference
from libc.stdint cimport uint8_t
Expand Down Expand Up @@ -163,10 +163,7 @@ cpdef Table unpack(PackedColumns input):
Copy of the packed columns.
"""
cdef table_view v = cpp_unpack(dereference(input.c_obj))
# Since `Table.from_table_view` doesn't support an arbitrary owning object,
# we copy the table, see <https://github.com/rapidsai/cudf/issues/17040>.
cdef unique_ptr[table] t = make_unique[table](v)
return Table.from_libcudf(move(t))
return Table.from_table_view_of_arbitrary(v, input)


cpdef Table unpack_from_memoryviews(memoryview metadata, gpumemoryview gpu_data):
Expand Down Expand Up @@ -201,7 +198,4 @@ cpdef Table unpack_from_memoryviews(memoryview metadata, gpumemoryview gpu_data)
cdef const uint8_t* gpu_data_ptr = <uint8_t*>int_to_void_ptr(gpu_data.ptr)

cdef table_view v = cpp_unpack(metadata_ptr, gpu_data_ptr)
# Since `Table.from_table_view` doesn't support an arbitrary owning object,
# we copy the table, see <https://github.com/rapidsai/cudf/issues/17040>.
cdef unique_ptr[table] t = make_unique[table](v)
return Table.from_libcudf(move(t))
return Table.from_table_view_of_arbitrary(v, gpu_data)
10 changes: 6 additions & 4 deletions python/pylibcudf/pylibcudf/gpumemoryview.pxd
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Copyright (c) 2023, NVIDIA CORPORATION.
# Copyright (c) 2023-2025, NVIDIA CORPORATION.


cdef class gpumemoryview:
# TODO: Eventually probably want to make this opaque, but for now it's fine
# to treat this object as something like a POD struct
cdef readonly:
Py_ssize_t ptr
object obj
cdef readonly Py_ssize_t ptr
cdef readonly object obj

@staticmethod
cdef gpumemoryview from_pointer(Py_ssize_t ptr, object owner)
20 changes: 20 additions & 0 deletions python/pylibcudf/pylibcudf/gpumemoryview.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@ cdef class gpumemoryview:
# TODO: Need to respect readonly
self.ptr = cai["data"][0]

@staticmethod
cdef gpumemoryview from_pointer(Py_ssize_t ptr, object owner):
Comment thread
vyasr marked this conversation as resolved.
Resolved
"""Create a gpumemoryview from a pointer and an owning object.

Parameters
----------
ptr : Py_ssize_t
The pointer to the memory.
owner : object
The object that owns the data the pointer points to.

Returns
-------
gpumemoryview
"""
cdef gpumemoryview out = gpumemoryview.__new__(gpumemoryview)
out.obj = owner
out.ptr = ptr
return out

@property
def __cuda_array_interface__(self):
return self.obj.__cuda_array_interface__
Expand Down
5 changes: 4 additions & 1 deletion python/pylibcudf/pylibcudf/table.pxd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2023-2024, NVIDIA CORPORATION.
# Copyright (c) 2023-2025, NVIDIA CORPORATION.

from libcpp.memory cimport unique_ptr
from pylibcudf.libcudf.table.table cimport table
Expand All @@ -20,4 +20,7 @@ cdef class Table:
@staticmethod
cdef Table from_table_view(const table_view& tv, Table owner)

@staticmethod
cdef Table from_table_view_of_arbitrary(const table_view& tv, object owner)

cpdef list columns(self)
32 changes: 28 additions & 4 deletions python/pylibcudf/pylibcudf/table.pyx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2023-2024, NVIDIA CORPORATION.
# Copyright (c) 2023-2025, NVIDIA CORPORATION.

from cython.operator cimport dereference
from libcpp.memory cimport unique_ptr
Expand Down Expand Up @@ -62,10 +62,9 @@ cdef class Table:

@staticmethod
cdef Table from_table_view(const table_view& tv, Table owner):
"""Create a Table from a libcudf table.
"""Create a Table from a libcudf table_view into a Table owner.

This method accepts shared ownership of the underlying data from the
owner and relies on the offset from the view.
This method accepts shared ownership of the underlying data from the owner.

This method is for pylibcudf's functions to use to ingest outputs of
calling libcudf algorithms, and should generally not be needed by users
Expand All @@ -77,6 +76,31 @@ cdef class Table:
for i in range(tv.num_columns())
])

# Ideally this function would simply be handled via a fused type in
# from_table_view, but this does not work due to
# https://github.com/cython/cython/issues/6740
@staticmethod
cdef Table from_table_view_of_arbitrary(const table_view& tv, object owner):
Comment thread
mroeschke marked this conversation as resolved.
Resolved
"""Create a Table from a libcudf table_view into an arbitrary owner.

This method accepts shared ownership of the underlying data from the owner.
Since the owner may be any arbitrary object, every buffer view that is part of
the table (each column and all of their children) share ownership of the same
buffer since they do not have the information available to choose to only own
subsets of it.

This method is for pylibcudf's functions to use to ingest outputs of
calling libcudf algorithms, and should generally not be needed by users
(even direct pylibcudf Cython users).
"""
# For efficiency, prohibit calling this overload with a Table owner.
assert not isinstance(owner, Table)
cdef int i
return Table([
Column.from_column_view_of_arbitrary(tv.column(i), owner)
for i in range(tv.num_columns())
])

cpdef int num_columns(self):
"""The number of columns in this table."""
return len(self._columns)
Expand Down