-
Notifications
You must be signed in to change notification settings - Fork 15
Improve DLPack support for non CPU devices #233
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
Open
betatim
wants to merge
3
commits into
data-apis:main
Choose a base branch
from
betatim:match-from_dlpack_device
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -10,7 +10,9 @@ | |||||||||||
|
|
||||||||||||
| from .. import ones, arange, reshape, asarray, result_type, all, equal, stack | ||||||||||||
| from .._array_object import Array | ||||||||||||
| from .._devices import CPU_DEVICE, Device | ||||||||||||
| from .._devices import ( | ||||||||||||
| ALL_DEVICES, CPU_DEVICE, Device, DLDeviceType, _DLPACK_DEVICE_FOR | ||||||||||||
| ) | ||||||||||||
| from .._dtypes import ( | ||||||||||||
| _all_dtypes, | ||||||||||||
| _boolean_dtypes, | ||||||||||||
|
|
@@ -759,6 +761,61 @@ def test_dlpack_2023_12(api_version): | |||||||||||
| a.__dlpack__(copy=None) | ||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| @pytest.mark.parametrize("device", ALL_DEVICES) | ||||||||||||
| def test_dlpack_device_numbers(device): | ||||||||||||
| a = asarray([1, 2, 3], device=device) | ||||||||||||
| # the data of every logical device lives in host memory, so they all report | ||||||||||||
| # the CPU device, which is device number zero | ||||||||||||
| assert a.__dlpack_device__() == (DLDeviceType.kDLCPU, 0) | ||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| def test_dlpack_device_map_is_complete(): | ||||||||||||
| assert set(_DLPACK_DEVICE_FOR) == set(ALL_DEVICES) | ||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| @pytest.mark.parametrize( | ||||||||||||
| "device", [device for device in ALL_DEVICES if device != CPU_DEVICE] | ||||||||||||
| ) | ||||||||||||
| def test_dlpack_export_from_non_cpu_device(device): | ||||||||||||
| a = asarray([1, 2, 3], device=device) | ||||||||||||
|
|
||||||||||||
| with pytest.raises(BufferError): | ||||||||||||
| a.__dlpack__() | ||||||||||||
| with pytest.raises(BufferError): | ||||||||||||
| np.from_dlpack(a) | ||||||||||||
|
|
||||||||||||
| if np.lib.NumpyVersion(np.__version__) < "2.1.0": | ||||||||||||
| return | ||||||||||||
|
|
||||||||||||
| # asking for a device explicitly does not help: the array has to be moved | ||||||||||||
| # to the CPU device first. Even asking for the CPU device, which is what | ||||||||||||
| # __dlpack_device__ reports, is refused: these devices are meant to | ||||||||||||
| # represent a GPU or other accelerator, so the consumer would end up with | ||||||||||||
| # the data on a device the array is not logically on. | ||||||||||||
| with pytest.raises(BufferError): | ||||||||||||
| a.__dlpack__(dl_device=a.__dlpack_device__()) | ||||||||||||
| with pytest.raises(BufferError): | ||||||||||||
| a.__dlpack__(dl_device=(DLDeviceType.kDLCPU, 0)) | ||||||||||||
| with pytest.raises(BufferError): | ||||||||||||
| np.from_dlpack(a, device="cpu") | ||||||||||||
|
|
||||||||||||
| np.from_dlpack(a.to_device(CPU_DEVICE)) | ||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about
Suggested change
or some such |
||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| def test_dlpack_export_from_cpu_device(): | ||||||||||||
| a = asarray([1, 2, 3]) | ||||||||||||
|
|
||||||||||||
| a.__dlpack__() | ||||||||||||
| np.from_dlpack(a) | ||||||||||||
|
|
||||||||||||
| if np.lib.NumpyVersion(np.__version__) < "2.1.0": | ||||||||||||
| return | ||||||||||||
|
|
||||||||||||
| a.__dlpack__(dl_device=a.__dlpack_device__()) | ||||||||||||
| with pytest.raises(BufferError): | ||||||||||||
| a.__dlpack__(dl_device=(DLDeviceType.kDLCUDA, 0)) | ||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| def test_pickle(): | ||||||||||||
| """Check that arrays are pickleable (despite raising on `__new__`)""" | ||||||||||||
| a = ones(2) | ||||||||||||
|
|
||||||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,7 +24,7 @@ | |
| ) | ||
| from .._dtypes import float32, float64, complex64, int32, int64, bool as xp_bool | ||
| from .._array_object import Array | ||
| from .._devices import CPU_DEVICE, ALL_DEVICES, Device | ||
| from .._devices import CPU_DEVICE, ALL_DEVICES, Device, DLDeviceType | ||
| from .._info import __array_namespace_info__ | ||
| from .._flags import set_array_api_strict_flags | ||
|
|
||
|
|
@@ -413,3 +413,29 @@ def test_from_dlpack_default_device(): | |
| z = from_dlpack(np.asarray([1, 2, 3])) | ||
| assert x.device == y.device == z.device == CPU_DEVICE | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("device", ALL_DEVICES) | ||
| def test_from_dlpack_preserves_device(device): | ||
| x = asarray([1, 2, 3], device=device) | ||
| y = from_dlpack(x) | ||
| assert y.device == device | ||
|
|
||
|
|
||
| def test_from_dlpack_unknown_device(): | ||
| class ForeignArray: | ||
| """An array on a device which array_api_strict knows nothing about.""" | ||
| def __init__(self): | ||
| self._array = np.asarray([1, 2, 3]) | ||
|
|
||
| def __dlpack_device__(self): | ||
| return (DLDeviceType.kDLCUDA, 0) | ||
|
|
||
| def __dlpack__(self, **kwargs): | ||
| return self._array.__dlpack__(**kwargs) | ||
|
|
||
| with pytest.raises(BufferError): | ||
| 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 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to cover |
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| """Check how other libraries see arrays of array_api_strict via DLPack. | ||
|
|
||
| Tests that libraries like NumPy and PyTorch can import arrays from | ||
| array_api_strict via DLPack. | ||
|
|
||
| Only run if torch is available. | ||
| """ | ||
| import numpy as np | ||
| import pytest | ||
|
|
||
| import array_api_strict as xp | ||
| from .._devices import ALL_DEVICES, CPU_DEVICE | ||
|
|
||
| torch = pytest.importorskip("torch") | ||
|
|
||
|
|
||
| def test_export_from_cpu_device(): | ||
| x = xp.asarray([1, 2, 3], device=CPU_DEVICE) | ||
|
|
||
| assert np.from_dlpack(x).tolist() == [1, 2, 3] | ||
| assert torch.from_dlpack(x).tolist() == [1, 2, 3] | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| "device", [device for device in ALL_DEVICES if device != CPU_DEVICE] | ||
| ) | ||
| def test_export_from_other_devices(device): | ||
| x = xp.asarray([1, 2, 3], device=device) | ||
|
|
||
| with pytest.raises(BufferError): | ||
| np.from_dlpack(x) | ||
| with pytest.raises(BufferError): | ||
| torch.from_dlpack(x) | ||
|
|
||
| assert torch.from_dlpack(x.to_device(CPU_DEVICE)).tolist() == [1, 2, 3] | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("device", ALL_DEVICES) | ||
| def test_import_from_torch(device): | ||
| # int32 is the widest integer every device supports | ||
| x = xp.from_dlpack(torch.asarray([1, 2, 3], dtype=torch.int32), device=device) | ||
|
|
||
| assert x.device == device | ||
| assert xp.all(x == xp.asarray([1, 2, 3], dtype=xp.int32, device=device)) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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
kDLsuffix: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.