17
17
import collections
18
18
import ctypes
19
19
20
+ import numpy as np
20
21
import pytest
21
- from helper import skip_if_dtype_not_supported
22
+ from helper import get_queue_or_skip , skip_if_dtype_not_supported
22
23
23
24
import dpctl
24
25
import dpctl .tensor as dpt
25
26
import dpctl .tensor ._dlpack as _dlp
26
27
import dpctl .tensor ._usmarray as dpt_arr
27
28
28
- device_oneAPI = 14 # DLDeviceType.kDLOneAPI
29
+ device_CPU = dpt_arr .DLDeviceType .kDLCPU
30
+ device_oneAPI = dpt_arr .DLDeviceType .kDLOneAPI
29
31
30
32
_usm_types_list = ["shared" , "device" , "host" ]
31
33
@@ -491,7 +493,7 @@ def test_dlpack_dl_device():
491
493
cap2 = x .__dlpack__ (dl_device = (1 , 0 ), max_version = max_supported_ver )
492
494
assert _is_capsule (cap2 )
493
495
cap3 = x .__dlpack__ (
494
- dl_device = (dpt_arr . DLDeviceType . kDLCPU , 0 ),
496
+ dl_device = (device_CPU , 0 ),
495
497
max_version = max_supported_ver ,
496
498
)
497
499
assert _is_capsule (cap3 )
@@ -505,3 +507,192 @@ def test_dlpack_dl_device():
505
507
with pytest .raises (NotImplementedError ):
506
508
# exercise check for length
507
509
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