Skip to content

Improve DLPack support for non CPU devices - #233

Open
betatim wants to merge 7 commits into
data-apis:mainfrom
betatim:match-from_dlpack_device
Open

Improve DLPack support for non CPU devices#233
betatim wants to merge 7 commits into
data-apis:mainfrom
betatim:match-from_dlpack_device

Conversation

@betatim

@betatim betatim commented Jul 29, 2026

Copy link
Copy Markdown
Member

This improves the from_dlpack behaviour for round-tripping array-api-strict arrays and raises an error for arrays that are not on the CPU device.

This is a follow up to #219 and #221

We use the device ID to tell the difference between the different "devices" present in array-api-strict. This seems to work/not bother libraries like torch or numpy. The device type is always CPU. In #212 we tried using different device type IDs, but that turns out not to work. I think the standard says (or suggests?) that for the CPU device the only device ID that makes sense is zero. In practice it seems every library ignores this field for CPU devices. Originally I thought we needed to use different device IDs to be able to make the following code work:

x = asarray([1, 2, 3], device=device)
y = from_dlpack(x)
assert y.device == device

Before this PR the assert will fail.

But, now we have a isinstance(x, Array) branch in from_dlpack (line 257 of array_api_strict/_creation_functions.py). So we could do some special casing in this if statement. That way we don't have to report IDs that are not part of the standard. The downside is that __dlpack_device__ would report the same for all the devices in array-api-strict. I can't make up my mind which option I prefer.

On main it is possible to "transfer" a device from "device1" to the CPU by using np.from_dlpack(x_on_device1). This is explicitly not allowed when using np.asarray(). This PR adjusts the DLPack behaviour to match the __buffer__ based behaviour.

This also installs torch for one of the CI jobs to test DLpack'ing arrays to and from a different library.

betatim added 2 commits July 29, 2026 13:58
This improves the `from_dlpack` behaviour for round-tripping
array-api-strict arrays and raises an error for arrays that are not on
the CPU device.
The CPU device can not really have multiple devices, and we don't need
to be able to tell devices apart. So this removes the "not spec
compliant" code.
@betatim

betatim commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

To illustrate my indecision, the second commit removes the special "use different device IDs for different logical devices". I think it is cleaner this way

@ev-br ev-br 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.

This looks pretty comprehensive!
I agree with the decision to not fiddle with device IDs. I don't know if the standards mandates that CPU device ID is always 0, but even if it does not, what would <CPU, 3> mean anyway---a third node on a multinode HPC cluster? If anything, previous experience emulating these dlpack details showed that it can backfire in unexpected ways. So since fake device IDs are not strictly necessary, I agree with keeping it all minimal.

The comments below are all minor, really. One thing that stands out is the difference in naming of DLPack enum values between the DLPack spec and the Array API spec; maybe this is something to fix in the latter?

Adding a test run against torch is great actually.

Testing: my brain hurts when I try to trace through how this interacts with copy={True, False, None}. Maybe testing can be extended to cover various values of copy=?

And there are merge conflicts because of the ruff refactor (no comment).

Comment thread array_api_strict/_devices.py Outdated
kDLOneAPI = 14
kDLWebGPU = 15
kDLHexagon = 16
kDLMAIA = 17

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.

Nit: The spec mandates valid device type enum members without a leading kDL suffix:
https://data-apis.org/array-api/draft/API_specification/generated/array_api.array.__dlpack_device__.html#dlpack-device

I wonder why and whether we'd rather change it in the Array API spec to match the DLPack spec.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I have no opinion on the names here, but I think this being Python we should probably match the names in https://data-apis.org/array-api/draft/API_specification/generated/array_api.array.__dlpack_device__.html#dlpack-device instead of what I did (take them from the DLPack header file). The kDLCPU feels very "C".

I also removed a few entries from the enum, those that are not mentioned on the array API spec website. We are "the strict library" after all

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Mark as resolved?

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 it's worth a brief mention in the community meeting , if only to double-check the overwhelming support for dropping the C-style prefixes (and they do feel very C indeed).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I made an entry in the hackmd

Comment thread array_api_strict/tests/test_array_object.py Outdated
from_dlpack(ForeignArray())

# an explicit device is a request to transfer, so nothing has to be inferred
assert from_dlpack(ForeignArray(), device=CPU_DEVICE).device == CPU_DEVICE

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.

Do we want to cover copy={True, False} here, too?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Can we leave it for a new PR? I'm not yet sure I fully grok how it should work (copy=)

@betatim

betatim commented Aug 4, 2026

Copy link
Copy Markdown
Member Author

Conflicts resolved. I'd prefer to leave the copy= questions to a new PR, mostly because I'd have to spend some time thinking about it first

@ev-br

ev-br commented Aug 4, 2026

Copy link
Copy Markdown
Member

I ran array-api-tests on this branch with a large number of examples, and it passed. Also checked that the SciPy tests suite passes with array-api-strict from this branch. That in itself is not very surprising, since SciPy testing of devices is rather thin, but we have a confirmation that changes here don't break it.
Do you prefer to test scikit-learn before landing this or after @betatim ?

@ev-br ev-br added this to the 2.7 milestone Aug 4, 2026
@betatim

betatim commented Aug 4, 2026

Copy link
Copy Markdown
Member Author

I checked scikit-learn's tests. Of course something fails, but I suspect it might be legit bug in scikit-learn? I'll keep you posted.

@ev-br

ev-br commented Aug 4, 2026

Copy link
Copy Markdown
Member

From my side, the PR status is ready as soon as Tim says it is.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants