Skip to content

ENH: Support DLPack for scalars by converting to 0-D array#31893

Open
MaanasArora wants to merge 3 commits into
numpy:mainfrom
MaanasArora:dlpack-scalars
Open

ENH: Support DLPack for scalars by converting to 0-D array#31893
MaanasArora wants to merge 3 commits into
numpy:mainfrom
MaanasArora:dlpack-scalars

Conversation

@MaanasArora

@MaanasArora MaanasArora commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Closes #27137 by adding __dlpack__ and __dlpack_device__ methods to NumPy scalars. scalar.__dlpack__ currently delegates to ndarray.__dlpack__ by converting the scalar to a 0-D array. This is a very minimal solution - a copy is fairly natural in this context, so this workaround seemed natural as well. ping @seberg - thanks!

I have to check if we can add additional handling for the copy= kwarg - that seemed to be the main case where the array and scalar implementations might diverge in practice (we are always copying). Perhaps with certain conditions we can add validation for copy. I also have to check if I missed some other nuances within the arguments, and needs a release note, but otherwise, this is ready for review!

AI Disclosure

I used an agent to search for DLPack's implementation in more detail, to check for errors in my code, and to write a few tests (the independent_copy one, mainly).

@MaanasArora MaanasArora marked this pull request as draft July 7, 2026 08:01
@MaanasArora MaanasArora force-pushed the dlpack-scalars branch 3 times, most recently from a7f6f8d to 0c7fab4 Compare July 8, 2026 04:14
@MaanasArora

Copy link
Copy Markdown
Contributor Author

I Just pushed an update to reject copy=False explicitly and pass NPY_COPY_IF_NEEDED to the array delegate (to avoid a double copy). I also refactored to use the same implementation function for both, not sure if nice, so I can revert and use a more manual check if needed. (I wasn't entirely sure if we needed to call the array's Python function, but it seems more complicated.) I think this should be ready for review now!

@MaanasArora MaanasArora marked this pull request as ready for review July 8, 2026 05:42
@ikrommyd ikrommyd self-requested a review July 10, 2026 03:14
@ikrommyd

Copy link
Copy Markdown
Member

Added myself to the reviewers here as its one of the things I wanted to review when I find the next time slot.

@ikrommyd ikrommyd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is good and clean! Only left two minor comments.

Comment on lines +599 to +604
if (result_device.device_type != kDLCPU ||
result_device.device_id != 0) {
PyErr_SetString(PyExc_BufferError,
"Cannot export a scalar to DLPack on a non-CPU device.");
return NULL;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is dead code. device_converter should already guarantee that device_type will be kDLCPU. Unless you wanted it for a different error message.

Suggested change
if (result_device.device_type != kDLCPU ||
result_device.device_id != 0) {
PyErr_SetString(PyExc_BufferError,
"Cannot export a scalar to DLPack on a non-CPU device.");
return NULL;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd add testing for the dl_device argument and for the copy=True case which if I'm seeing correctly are currently missing.

@ikrommyd

ikrommyd commented Jul 10, 2026

Copy link
Copy Markdown
Member

@seberg based on your comment #27137 (comment)
I'd like to ask, should any of these work? Cause they don't right now. So thanks for reminding me to consider bfloat16 for example too.

In [1]: import ml_dtypes

In [2]: ml_dtypes.bfloat16(4).__dlpack__()
---------------------------------------------------------------------------
BufferError                               Traceback (most recent call last)
Cell In[2], line 1
----> 1 ml_dtypes.bfloat16(4).__dlpack__()

BufferError: DLPack only supports signed/unsigned integers, float and complex dtypes (or dtypes registered by third-party packages).

In [3]: from numpy_quaddtype import QuadPrecDType, QuadPrecision

In [4]: QuadPrecision(4).__dlpack__()
---------------------------------------------------------------------------
BufferError                               Traceback (most recent call last)
Cell In[4], line 1
----> 1 QuadPrecision(4).__dlpack__()

BufferError: DLPack only supports signed/unsigned integers, float and complex dtypes (or dtypes registered by third-party packages).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: scalars don't have dlpack support

2 participants