Skip to content

Commit 5847b70

Browse files
committed
Adds tests for DLPack using kDLCPU dl_device
1 parent 3c35c3b commit 5847b70

File tree

1 file changed

+194
-3
lines changed

1 file changed

+194
-3
lines changed

dpctl/tests/test_usm_ndarray_dlpack.py

Lines changed: 194 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,17 @@
1717
import collections
1818
import ctypes
1919

20+
import numpy as np
2021
import pytest
21-
from helper import skip_if_dtype_not_supported
22+
from helper import get_queue_or_skip, skip_if_dtype_not_supported
2223

2324
import dpctl
2425
import dpctl.tensor as dpt
2526
import dpctl.tensor._dlpack as _dlp
2627
import dpctl.tensor._usmarray as dpt_arr
2728

28-
device_oneAPI = 14 # DLDeviceType.kDLOneAPI
29+
device_CPU = dpt_arr.DLDeviceType.kDLCPU
30+
device_oneAPI = dpt_arr.DLDeviceType.kDLOneAPI
2931

3032
_usm_types_list = ["shared", "device", "host"]
3133

@@ -491,7 +493,7 @@ def test_dlpack_dl_device():
491493
cap2 = x.__dlpack__(dl_device=(1, 0), max_version=max_supported_ver)
492494
assert _is_capsule(cap2)
493495
cap3 = x.__dlpack__(
494-
dl_device=(dpt_arr.DLDeviceType.kDLCPU, 0),
496+
dl_device=(device_CPU, 0),
495497
max_version=max_supported_ver,
496498
)
497499
assert _is_capsule(cap3)
@@ -505,3 +507,192 @@ def test_dlpack_dl_device():
505507
with pytest.raises(NotImplementedError):
506508
# exercise check for length
507509
x.__dlpack__(dl_device=(3,), max_version=max_supported_ver)
510+
511+
512+
def test_from_dlpack_kdlcpu_interop_numpy():
513+
"""
514+
Basic test that usm_ndarray can interoperate with NumPy ndarray
515+
`__dlpack_device__`.
516+
"""
517+
get_queue_or_skip()
518+
519+
sh = 5
520+
dt = dpt.int32
521+
522+
X = dpt.empty(sh, dtype=dt)
523+
dl_device_np = np.empty(()).__dlpack_device__()
524+
525+
Y = dpt.from_dlpack(X, device=dl_device_np)
526+
assert isinstance(Y, np.ndarray)
527+
assert X.shape == Y.shape
528+
assert X.dtype == Y.dtype
529+
530+
V = dpt.from_dlpack(Y)
531+
assert isinstance(V, np.ndarray)
532+
assert Y.shape == V.shape
533+
assert Y.dtype == V.dtype
534+
535+
536+
@pytest.mark.parametrize("shape", [tuple(), (2,), (3, 0, 1), (2, 2, 2)])
537+
def test_from_dlpack_to_kdlcpu(shape, typestr):
538+
q = get_queue_or_skip()
539+
skip_if_dtype_not_supported(typestr, q.sycl_device)
540+
541+
X = dpt.empty(shape, dtype=typestr, sycl_queue=q)
542+
Y = dpt.from_dlpack(X, device=(device_CPU, 0))
543+
assert isinstance(Y, np.ndarray)
544+
assert X.shape == Y.shape
545+
assert X.dtype == Y.dtype
546+
# NumPy does not treat size 0 arrays consistently
547+
# w.r.t. strides, so skip these cases
548+
if X.ndim and X.size != 0:
549+
V = Y[::-1]
550+
W = dpt.from_dlpack(V)
551+
assert V.strides == W.strides
552+
553+
554+
@pytest.mark.parametrize("mod", [2, 5])
555+
def test_from_dlpack_to_kdlcpu_strides(mod, typestr):
556+
q = get_queue_or_skip()
557+
skip_if_dtype_not_supported(typestr, q.sycl_device)
558+
559+
X0 = dpt.empty(3 * mod, dtype=typestr, sycl_queue=q)
560+
for start in range(mod):
561+
X = X0[slice(-start - 1, None, -mod)]
562+
Y = dpt.from_dlpack(X, device=(device_CPU, 0))
563+
assert X.shape == Y.shape
564+
assert X.dtype == Y.dtype
565+
if Y.ndim:
566+
V = Y[::-1]
567+
W = dpt.from_dlpack(V)
568+
assert V.strides == W.strides
569+
570+
571+
def test_dlpack_from_subdevice_to_kdlcpu():
572+
"""
573+
Check that array allocated on a sub-device can be
574+
imported via DLPack to kDLCPU device (as a NumPy array).
575+
"""
576+
n = 64
577+
try:
578+
dev = dpctl.SyclDevice()
579+
except dpctl.SyclDeviceCreationError:
580+
pytest.skip("No default device available")
581+
try:
582+
sdevs = dev.create_sub_devices(partition="next_partitionable")
583+
except dpctl.SyclSubDeviceCreationError:
584+
sdevs = None
585+
try:
586+
if sdevs is None:
587+
sdevs = dev.create_sub_devices(partition=[1, 1])
588+
except dpctl.SyclSubDeviceCreationError:
589+
pytest.skip("Default device can not be partitioned")
590+
assert isinstance(sdevs, list) and len(sdevs) > 0
591+
try:
592+
ctx = sdevs[0].sycl_platform.default_context
593+
except dpctl.SyclContextCreationError:
594+
pytest.skip("Platform's default_context is not available")
595+
try:
596+
q = dpctl.SyclQueue(ctx, sdevs[0])
597+
except dpctl.SyclQueueCreationError:
598+
pytest.skip("Queue could not be created")
599+
600+
ar = dpt.arange(n, dtype=dpt.int32, sycl_queue=q)
601+
ar2 = dpt.from_dlpack(ar, dl_device=(device_CPU, 0))
602+
assert isinstance(ar2, np.ndarray)
603+
604+
605+
def test_legacy_dlpack_capsule_from_numpy():
606+
"""
607+
Check that NumPy's exported legacy DLPack capsule
608+
will interoperate with from_dlpack_capsule,
609+
especially with zero-copy.
610+
"""
611+
x = np.arange(100, dtype="i4")
612+
cap = x.__dlpack__()
613+
y = _dlp.from_dlpack_capsule(cap)
614+
del cap
615+
assert x.ctypes.data == y.ctypes.data
616+
617+
x = np.arange(100, dtype="u4").reshape((10, 10)).mT
618+
cap = x.__dlpack__()
619+
y = _dlp.from_dlpack_capsule(cap)
620+
del cap
621+
assert x.ctypes.data == y.ctypes.data
622+
del x
623+
624+
x = np.arange(100, dtype="f4").reshape((10, 10), order="F")
625+
cap = x.__dlpack__()
626+
y = _dlp.from_dlpack_capsule(cap)
627+
del cap
628+
assert x.ctypes.data == y.ctypes.data
629+
630+
x = np.arange(100, dtype="c8")
631+
x1 = x[::-2]
632+
cap = x1.__dlpack__()
633+
y = _dlp.from_dlpack_capsule(cap)
634+
assert x1.ctypes.data == y.ctypes.data
635+
del x1, y, x
636+
del cap
637+
638+
x = np.ones(100, dtype="?")
639+
x1 = x[::-2]
640+
cap = x1.__dlpack__()
641+
y = _dlp.from_dlpack_capsule(cap)
642+
assert x1.ctypes.data == y.ctypes.data
643+
del x1, y, x
644+
del cap
645+
646+
647+
def test_dlpack_capsule_readonly_array_to_kdlcpu():
648+
try:
649+
x = dpt.arange(100, dtype="i4")
650+
except dpctl.SyclDeviceCreationError:
651+
pytest.skip("No default device available")
652+
653+
max_supported_ver = _dlp.get_build_dlpack_version()
654+
# read-only array
655+
x.flags["W"] = False
656+
cap = x.__dlpack__(max_version=max_supported_ver, dl_device=(device_CPU, 0))
657+
y = _dlp.from_dlpack_capsule(cap)
658+
assert dpt.all(x == dpt.asarray(y))
659+
assert not y.flags["W"]
660+
661+
cap1 = _dlp.numpy_to_dlpack_versioned_capsule(y, not y.flags["W"])
662+
y1 = _dlp.from_dlpack_capsule(cap1)
663+
assert not y1.flags["W"]
664+
665+
666+
def test_used_dlpack_capsule_from_numpy():
667+
get_queue_or_skip()
668+
669+
x_np = np.arange(100, dtype="i4")
670+
671+
cap = x_np.__dlpack__()
672+
_dlp.from_dlpack_capsule(cap)
673+
with pytest.raises(
674+
ValueError,
675+
match="A DLPack tensor object can not be consumed multiple times",
676+
):
677+
_dlp.from_dlpack_capsule(cap)
678+
del cap
679+
680+
x = dpt.asarray(x_np)
681+
max_supported_ver = _dlp.get_build_dlpack_version()
682+
cap = x.__dlpack__(max_version=max_supported_ver, dl_device=(device_CPU, 0))
683+
_dlp.from_dlpack_capsule(cap)
684+
with pytest.raises(
685+
ValueError,
686+
match="A DLPack tensor object can not be consumed multiple times",
687+
):
688+
_dlp.from_dlpack_capsule(cap)
689+
del cap
690+
691+
692+
def test_dlpack_size_0_on_kdlcpu():
693+
get_queue_or_skip()
694+
x_np = np.ones(0, dtype="i4")
695+
696+
cap = x_np.__dlpack__()
697+
y = _dlp.from_dlpack_capsule(cap)
698+
assert y.ctypes.data == x_np.ctypes.data

0 commit comments

Comments
 (0)