Skip to content

Commit 37db1c5

Browse files
authored
Update third party tests (#2627)
The PR update the scope of third party tests and adds missing check for the strides.
1 parent aae2dc0 commit 37db1c5

File tree

5 files changed

+192
-71
lines changed

5 files changed

+192
-71
lines changed

dpnp/tests/third_party/cupy/core_tests/test_ndarray_indexing.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import unittest
24
import warnings
35

@@ -6,6 +8,10 @@
68

79
import dpnp as cupy
810
from dpnp.tests.third_party.cupy import testing
11+
from dpnp.tests.third_party.cupy.testing._protocol_helpers import (
12+
DummyObjectWithCudaArrayInterface,
13+
DummyObjectWithCuPyGetNDArray,
14+
)
915

1016
if numpy.lib.NumpyVersion(numpy.__version__) >= "2.0.0b1":
1117
from numpy.exceptions import ComplexWarning
@@ -130,9 +136,30 @@
130136
)
131137
class TestArrayIndexingParameterized(unittest.TestCase):
132138

139+
_getitem_hip_skip_condition = [
140+
((1, 0, 2), (2, 3, 4), None),
141+
((-1, 0, -2), (2, 3, 4), None),
142+
((1, 0, 2), (2, 3, 4), (2, 0, 1)),
143+
((-1, 0, -2), (2, 3, 4), (2, 0, 1)),
144+
((slice(None, None, None), None), (2,), None),
145+
((slice(-9, -10, -1),), (10,), None),
146+
((slice(-4, -5, -1),), (10,), None),
147+
((slice(-5, -6, -1),), (10,), None),
148+
]
149+
150+
def _check_getitem_hip_skip_condition(self):
151+
return (
152+
self.indexes,
153+
self.shape,
154+
self.transpose,
155+
) in self._getitem_hip_skip_condition
156+
133157
@testing.for_all_dtypes()
134158
@testing.numpy_cupy_array_equal()
135159
def test_getitem(self, xp, dtype):
160+
# if cupy.cuda.runtime.is_hip:
161+
# if self._check_getitem_hip_skip_condition():
162+
# pytest.xfail("HIP may have a bug")
136163
a = testing.shaped_arange(self.shape, xp, dtype)
137164
if self.transpose:
138165
a = a.transpose(self.transpose)
@@ -261,3 +288,18 @@ def test_remain0d(self, xp):
261288
a = xp.zeros((2, 3, 4), dtype=dtype)
262289
a[0, 1, 2] = testing.shaped_arange((), xp, dtype)
263290
return a
291+
292+
293+
@pytest.mark.skip("CUDA array interface is not supported")
294+
@pytest.mark.parametrize(
295+
"cupy_like",
296+
[
297+
DummyObjectWithCuPyGetNDArray,
298+
DummyObjectWithCudaArrayInterface,
299+
],
300+
)
301+
def test_setitem_with_cupy_like(cupy_like):
302+
# Test that normal assignment supports interfaces
303+
a = cupy.zeros(10)
304+
a[...] = cupy_like(cupy.arange(10))
305+
testing.assert_array_equal(a, cupy.arange(10))

dpnp/tests/third_party/cupy/core_tests/test_reduction.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1+
from __future__ import annotations
2+
13
import unittest
24

35
import numpy
46
import pytest
5-
from dpctl.tensor._numpy_helper import AxisError
67

78
import dpnp as cupy
89

910
# import cupy._core._accelerator as _acc
1011
# from cupy import _core
1112
from dpnp.tests.third_party.cupy import testing
13+
from dpnp.tests.third_party.cupy.testing._protocol_helpers import (
14+
DummyObjectWithCudaArrayInterface,
15+
DummyObjectWithCuPyGetNDArray,
16+
)
17+
18+
# from cupy.exceptions import ComplexWarning, AxisError
1219

13-
if numpy.lib.NumpyVersion(numpy.__version__) >= "2.0.0b1":
14-
from numpy.exceptions import ComplexWarning
15-
else:
16-
from numpy import ComplexWarning
1720

1821
pytest.skip(
1922
"create/get_reduction_func() and ReductionKernel are not supported",
@@ -258,3 +261,26 @@ def test_large_dims_keep_kernels(self):
258261
shape = (4, 3, 2, 4, 3, 2, 2)
259262
axis = (1, 4, 3, 6)
260263
self.check_int8_sum(shape, axis=axis, keepdims=True)
264+
265+
266+
class TestArgumentTypes:
267+
kernel = _core.create_reduction_func(
268+
"my_sum", ("f->f",), ("in0", "a + b", "out0 = a", None), 0
269+
)
270+
271+
@pytest.mark.parametrize(
272+
"cupy_like",
273+
[
274+
DummyObjectWithCuPyGetNDArray,
275+
DummyObjectWithCudaArrayInterface,
276+
],
277+
)
278+
def test_cupy_like_protocols(self, cupy_like):
279+
# Check that reduction kernels work on the cupy like protocols
280+
x = cupy_like(cupy.arange(10, dtype=cupy.float32))
281+
res = self.kernel(x)
282+
assert res == 45
283+
284+
def test_bad_argument(self):
285+
with pytest.raises(TypeError, match="Argument 'a' has incorrect type"):
286+
self.kernel(numpy.array([1, 2, 3]))

dpnp/tests/third_party/cupy/creation_tests/test_from_data.py

Lines changed: 35 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from __future__ import annotations
2+
3+
import os
14
import tempfile
25
import unittest
36

@@ -8,6 +11,10 @@
811
import dpnp as cupy
912
from dpnp.tests.helper import has_support_aspect64, is_cuda_device
1013
from dpnp.tests.third_party.cupy import testing
14+
from dpnp.tests.third_party.cupy.testing._protocol_helpers import (
15+
DummyObjectWithCudaArrayInterface,
16+
DummyObjectWithCuPyGetNDArray,
17+
)
1118

1219

1320
class TestFromData(unittest.TestCase):
@@ -37,6 +44,11 @@ def test_array_from_numpy(self, xp, dtype, order):
3744
a = testing.shaped_arange((2, 3, 4), numpy, dtype)
3845
return xp.array(a, order=order)
3946

47+
@pytest.mark.skip("no blocking keyword")
48+
def test_array_from_numpy_blocking(self):
49+
a = testing.shaped_arange((2, 3, 4), numpy, numpy.float32)
50+
testing.assert_array_equal(cupy.array(a, blocking=True), a)
51+
4052
@testing.for_orders("CFAK")
4153
@testing.for_all_dtypes()
4254
@testing.numpy_cupy_array_equal()
@@ -242,7 +254,7 @@ def test_array_copy_with_dtype_being_none(self, xp, order):
242254
@testing.for_orders("CFAK", name="dst_order")
243255
@testing.for_all_dtypes(name="dtype1", no_complex=True)
244256
@testing.for_all_dtypes(name="dtype2")
245-
@testing.numpy_cupy_array_equal()
257+
@testing.numpy_cupy_array_equal(strides_check=True)
246258
def test_array_copy_list_of_numpy_with_dtype(
247259
self, xp, dtype1, dtype2, src_order, dst_order
248260
):
@@ -258,7 +270,7 @@ def test_array_copy_list_of_numpy_with_dtype(
258270
@testing.for_orders("CFAK", name="dst_order")
259271
@testing.for_all_dtypes(name="dtype1", no_complex=True)
260272
@testing.for_all_dtypes(name="dtype2")
261-
@testing.numpy_cupy_array_equal()
273+
@testing.numpy_cupy_array_equal(strides_check=True)
262274
def test_array_copy_list_of_numpy_with_dtype_char(
263275
self, xp, dtype1, dtype2, src_order, dst_order
264276
):
@@ -274,7 +286,7 @@ def test_array_copy_list_of_numpy_with_dtype_char(
274286
@testing.for_orders("CFAK", name="dst_order")
275287
@testing.for_all_dtypes(name="dtype1", no_complex=True)
276288
@testing.for_all_dtypes(name="dtype2")
277-
@testing.numpy_cupy_array_equal()
289+
@testing.numpy_cupy_array_equal(strides_check=True)
278290
def test_array_copy_list_of_cupy_with_dtype(
279291
self, xp, dtype1, dtype2, src_order, dst_order
280292
):
@@ -290,7 +302,7 @@ def test_array_copy_list_of_cupy_with_dtype(
290302
@testing.for_orders("CFAK", name="dst_order")
291303
@testing.for_all_dtypes(name="dtype1", no_complex=True)
292304
@testing.for_all_dtypes(name="dtype2")
293-
@testing.numpy_cupy_array_equal()
305+
@testing.numpy_cupy_array_equal(strides_check=True)
294306
def test_array_copy_list_of_cupy_with_dtype_char(
295307
self, xp, dtype1, dtype2, src_order, dst_order
296308
):
@@ -401,6 +413,11 @@ def test_asarray(self, xp, dtype):
401413
a = testing.shaped_arange((2, 3, 4), xp, dtype)
402414
return xp.asarray(a)
403415

416+
@pytest.mark.skip("no blocking keyword")
417+
def test_asarray_blocking(self):
418+
a = testing.shaped_arange((2, 3, 4), numpy, numpy.float32)
419+
testing.assert_array_equal(cupy.asarray(a, blocking=True), a)
420+
404421
@testing.for_all_dtypes()
405422
@testing.numpy_cupy_array_equal()
406423
def test_asarray_is_not_copied(self, xp, dtype):
@@ -454,6 +471,11 @@ def test_asanyarray_from_big_endian(self, xp, dtype):
454471
# happens to work before the change in #5828
455472
return b + b
456473

474+
@pytest.mark.skip("no blocking keyword")
475+
def test_asanyarray_blocking(self):
476+
a = testing.shaped_arange((2, 3, 4), numpy, numpy.float32)
477+
testing.assert_array_equal(cupy.asanyarray(a, blocking=True), a)
478+
457479
@testing.for_CF_orders()
458480
@testing.for_all_dtypes()
459481
@testing.numpy_cupy_array_equal()
@@ -727,67 +749,6 @@ def test_with_over_size_array(self):
727749
testing.assert_array_equal(a, b)
728750

729751

730-
class DummyObjectWithCudaArrayInterface:
731-
def __init__(self, a, ver, include_strides=False, mask=None, stream=None):
732-
assert ver in tuple(range(max_cuda_array_interface_version + 1))
733-
self.a = None
734-
if isinstance(a, cupy.ndarray):
735-
self.a = a
736-
else:
737-
self.shape, self.strides, self.typestr, self.descr, self.data = a
738-
self.ver = ver
739-
self.include_strides = include_strides
740-
self.mask = mask
741-
self.stream = stream
742-
743-
@property
744-
def __cuda_array_interface__(self):
745-
if self.a is not None:
746-
desc = {
747-
"shape": self.a.shape,
748-
"typestr": self.a.dtype.str,
749-
"descr": self.a.dtype.descr,
750-
"data": (self.a.data.ptr, False),
751-
"version": self.ver,
752-
}
753-
if self.a.flags.c_contiguous:
754-
if self.include_strides is True:
755-
desc["strides"] = self.a.strides
756-
elif self.include_strides is None:
757-
desc["strides"] = None
758-
else: # self.include_strides is False
759-
pass
760-
else: # F contiguous or neither
761-
desc["strides"] = self.a.strides
762-
else:
763-
desc = {
764-
"shape": self.shape,
765-
"typestr": self.typestr,
766-
"descr": self.descr,
767-
"data": (self.data, False),
768-
"version": self.ver,
769-
}
770-
if self.include_strides is True:
771-
desc["strides"] = self.strides
772-
elif self.include_strides is None:
773-
desc["strides"] = None
774-
else: # self.include_strides is False
775-
pass
776-
if self.mask is not None:
777-
desc["mask"] = self.mask
778-
# The stream field is kept here for compliance. However, since the
779-
# synchronization is done via calling a cpdef function, which cannot
780-
# be mock-tested.
781-
if self.stream is not None:
782-
if self.stream is cuda.Stream.null:
783-
desc["stream"] = cuda.runtime.streamLegacy
784-
elif (not cuda.runtime.is_hip) and self.stream is cuda.Stream.ptds:
785-
desc["stream"] = cuda.runtime.streamPerThread
786-
else:
787-
desc["stream"] = self.stream.ptr
788-
return desc
789-
790-
791752
@testing.parameterize(
792753
*testing.product(
793754
{
@@ -848,3 +809,12 @@ def test_invalid_type(self):
848809
a = numpy.array([1, 2, 3], dtype=object)
849810
with self.assertRaises(TypeError):
850811
cupy.array(a)
812+
813+
814+
@pytest.mark.skip("CUDA array interface is not supported")
815+
class TestArrayCuPyGetNDArray(unittest.TestCase):
816+
def test_cupy_get_ndarray(self):
817+
a = cupy.array([1, 2, 3])
818+
dummy = DummyObjectWithCuPyGetNDArray(a)
819+
res = cupy.asarray(dummy)
820+
assert a is res # OK if it was a view

dpnp/tests/third_party/cupy/testing/_array.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,11 @@ def assert_array_equal(
171171
)
172172

173173
if strides_check:
174-
strides = tuple(el // desired.itemsize for el in desired.strides)
174+
strides = desired.strides
175+
if isinstance(actual, cupy.ndarray):
176+
# need to agreed the strides with numpy.ndarray
177+
strides = tuple(el // desired.itemsize for el in desired.strides)
178+
175179
if actual.strides != strides:
176180
msg = ["Strides are not equal:"]
177181
if err_msg:
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from __future__ import annotations
2+
3+
import dpnp as cupy
4+
5+
# from cupy import cuda
6+
7+
8+
max_cuda_array_interface_version = 3
9+
10+
11+
class DummyObjectWithCudaArrayInterface:
12+
# Private helper used for testing cuda array interface support.
13+
def __init__(self, a, ver=3, include_strides=False, mask=None, stream=None):
14+
assert ver in tuple(range(max_cuda_array_interface_version + 1))
15+
self.a = None
16+
if isinstance(a, cupy.ndarray):
17+
self.a = a
18+
else:
19+
self.shape, self.strides, self.typestr, self.descr, self.data = a
20+
self.ver = ver
21+
self.include_strides = include_strides
22+
self.mask = mask
23+
self.stream = stream
24+
25+
@property
26+
def __cuda_array_interface__(self):
27+
if self.a is not None:
28+
desc = {
29+
"shape": self.a.shape,
30+
"typestr": self.a.dtype.str,
31+
"descr": self.a.dtype.descr,
32+
"data": (self.a.data.ptr, False),
33+
"version": self.ver,
34+
}
35+
if self.a.flags.c_contiguous:
36+
if self.include_strides is True:
37+
desc["strides"] = self.a.strides
38+
elif self.include_strides is None:
39+
desc["strides"] = None
40+
else: # self.include_strides is False
41+
pass
42+
else: # F contiguous or neither
43+
desc["strides"] = self.a.strides
44+
else:
45+
desc = {
46+
"shape": self.shape,
47+
"typestr": self.typestr,
48+
"descr": self.descr,
49+
"data": (self.data, False),
50+
"version": self.ver,
51+
}
52+
if self.include_strides is True:
53+
desc["strides"] = self.strides
54+
elif self.include_strides is None:
55+
desc["strides"] = None
56+
else: # self.include_strides is False
57+
pass
58+
if self.mask is not None:
59+
desc["mask"] = self.mask
60+
# The stream field is kept here for compliance. However, since the
61+
# synchronization is done via calling a cpdef function, which cannot
62+
# be mock-tested.
63+
if self.stream is not None:
64+
if self.stream is cuda.Stream.null:
65+
desc["stream"] = cuda.runtime.streamLegacy
66+
elif (not cuda.runtime.is_hip) and self.stream is cuda.Stream.ptds:
67+
desc["stream"] = cuda.runtime.streamPerThread
68+
else:
69+
desc["stream"] = self.stream.ptr
70+
return desc
71+
72+
73+
class DummyObjectWithCuPyGetNDArray:
74+
# Private helper used for testing `__cupy_get_ndarray__` support.
75+
def __init__(self, a):
76+
self.a = a
77+
78+
def __cupy_get_ndarray__(self):
79+
return self.a

0 commit comments

Comments
 (0)