Skip to content

Commit 16e2bee

Browse files
Merge branch 'master' into histogram2d
2 parents dbc2579 + 13816bd commit 16e2bee

35 files changed

+1461
-101
lines changed

.github/workflows/array-api-skips.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ array_api_tests/test_sorting_functions.py::test_sort
5757
array_api_tests/test_signatures.py::test_func_signature[std]
5858
array_api_tests/test_signatures.py::test_func_signature[var]
5959

60-
# missing 'stream' keyword argument
61-
array_api_tests/test_signatures.py::test_array_method_signature[to_device]
62-
6360
# wrong shape is returned
6461
array_api_tests/test_linalg.py::test_vecdot
6562
array_api_tests/test_linalg.py::test_linalg_vecdot

.github/workflows/check-mkl-interfaces.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ jobs:
108108
id: run_tests
109109
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0
110110
with:
111-
timeout_minutes: 10
111+
timeout_minutes: 12
112112
max_attempts: ${{ env.RUN_TESTS_MAX_ATTEMPTS }}
113113
retry_on: any
114114
command: |
@@ -216,7 +216,7 @@ jobs:
216216
id: run_tests
217217
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0
218218
with:
219-
timeout_minutes: 10
219+
timeout_minutes: 12
220220
max_attempts: ${{ env.RUN_TESTS_MAX_ATTEMPTS }}
221221
retry_on: any
222222
command: |

.github/workflows/cron-run-tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ jobs:
126126
id: run_tests_linux
127127
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0
128128
with:
129-
timeout_minutes: 10
129+
timeout_minutes: 12
130130
max_attempts: ${{ env.RUN_TESTS_MAX_ATTEMPTS }}
131131
retry_on: any
132132
command: |

dpnp/dpnp_array.py

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,6 @@ def mT(self):
153153

154154
return dpnp_array._create_from_usm_ndarray(self._array_obj.mT)
155155

156-
def to_device(self, target_device):
157-
"""Transfer array to target device."""
158-
159-
return dpnp_array(
160-
shape=self.shape, buffer=self.get_array().to_device(target_device)
161-
)
162-
163156
@property
164157
def sycl_queue(self):
165158
return self._array_obj.sycl_queue
@@ -199,7 +192,9 @@ def __and__(self, other):
199192
# '__array_prepare__',
200193
# '__array_priority__',
201194
# '__array_struct__',
202-
# '__array_ufunc__',
195+
196+
__array_ufunc__ = None
197+
203198
# '__array_wrap__',
204199

205200
def __array_namespace__(self, /, *, api_version=None):
@@ -612,6 +607,25 @@ def __truediv__(self, other):
612607
"""Return ``self/value``."""
613608
return dpnp.true_divide(self, other)
614609

610+
@property
611+
def __usm_ndarray__(self):
612+
"""
613+
Property to support `__usm_ndarray__` protocol.
614+
615+
It assumes to return :class:`dpctl.tensor.usm_ndarray` instance
616+
corresponding to the content of the object.
617+
618+
This property is intended to speed-up conversion from
619+
:class:`dpnp.ndarray` to :class:`dpctl.tensor.usm_ndarray` passed
620+
into `dpctl.tensor.asarray` function. The input object that implements
621+
`__usm_ndarray__` protocol is recognized as owner of USM allocation
622+
that is managed by a smart pointer, and asynchronous deallocation
623+
will not involve GIL.
624+
625+
"""
626+
627+
return self._array_obj
628+
615629
def __xor__(self, other):
616630
"""Return ``self^value``."""
617631
return dpnp.bitwise_xor(self, other)
@@ -1693,6 +1707,48 @@ def take(self, indices, axis=None, out=None, mode="wrap"):
16931707

16941708
return dpnp.take(self, indices, axis=axis, out=out, mode=mode)
16951709

1710+
def to_device(self, device, /, *, stream=None):
1711+
"""
1712+
Transfers this array to specified target device.
1713+
1714+
Parameters
1715+
----------
1716+
device : {string, SyclDevice, SyclQueue}
1717+
Array API concept of target device. It can be an OneAPI filter
1718+
selector string, an instance of :class:`dpctl.SyclDevice`
1719+
corresponding to a non-partitioned SYCL device, an instance of
1720+
:class:`dpctl.SyclQueue`, or a :class:`dpctl.tensor.Device` object
1721+
returned by :obj:`dpnp.dpnp_array.dpnp_array.device` property.
1722+
stream : {SyclQueue, None}, optional
1723+
Execution queue to synchronize with. If ``None``, synchronization
1724+
is not performed.
1725+
Default: ``None``.
1726+
1727+
Returns
1728+
-------
1729+
out : dpnp.ndarray
1730+
A view if data copy is not required, and a copy otherwise.
1731+
If copying is required, it is done by copying from the original
1732+
allocation device to the host, followed by copying from host
1733+
to the target device.
1734+
1735+
Examples
1736+
--------
1737+
>>> import dpnp as np, dpctl
1738+
>>> x = np.full(100, 2, dtype=np.int64)
1739+
>>> q_prof = dpctl.SyclQueue(x.sycl_device, property="enable_profiling")
1740+
>>> # return a view with profile-enabled queue
1741+
>>> y = x.to_device(q_prof)
1742+
>>> timer = dpctl.SyclTimer()
1743+
>>> with timer(q_prof):
1744+
... z = y * y
1745+
>>> print(timer.dt)
1746+
1747+
"""
1748+
1749+
usm_res = self._array_obj.to_device(device, stream=stream)
1750+
return dpnp_array._create_from_usm_ndarray(usm_res)
1751+
16961752
# 'tobytes',
16971753
# 'tofile',
16981754
# 'tolist',

dpnp/dpnp_iface.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"get_result_array",
6969
"get_usm_ndarray",
7070
"get_usm_ndarray_or_scalar",
71+
"is_cuda_backend",
7172
"is_supported_array_or_scalar",
7273
"is_supported_array_type",
7374
"synchronize_array_data",
@@ -681,6 +682,41 @@ def get_usm_ndarray_or_scalar(a):
681682
return a if dpnp.isscalar(a) else get_usm_ndarray(a)
682683

683684

685+
def is_cuda_backend(obj=None):
686+
"""
687+
Checks that object has a CUDA backend.
688+
689+
Parameters
690+
----------
691+
obj : {Device, SyclDevice, SyclQueue, dpnp.ndarray, usm_ndarray, None},
692+
optional
693+
An input object with sycl_device property to check device backend.
694+
If `obj` is ``None``, device backend will be checked for the default
695+
queue.
696+
Default: ``None``.
697+
698+
Returns
699+
-------
700+
out : bool
701+
Return ``True`` if data of the input object resides on a CUDA backend,
702+
otherwise ``False``.
703+
704+
"""
705+
706+
if obj is None:
707+
sycl_device = dpctl.select_default_device()
708+
elif isinstance(obj, dpctl.SyclDevice):
709+
sycl_device = obj
710+
else:
711+
sycl_device = getattr(obj, "sycl_device", None)
712+
if (
713+
sycl_device is not None
714+
and sycl_device.backend == dpctl.backend_type.cuda
715+
):
716+
return True
717+
return False
718+
719+
684720
def is_supported_array_or_scalar(a):
685721
"""
686722
Return ``True`` if `a` is a scalar or an array of either

dpnp/dpnp_iface_indexing.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ def choose(x1, choices, out=None, mode="raise"):
128128
:obj:`dpnp.take_along_axis` : Preferable if choices is an array.
129129
130130
"""
131+
131132
x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False)
132133

133134
choices_list = []
@@ -137,6 +138,11 @@ def choose(x1, choices, out=None, mode="raise"):
137138
)
138139

139140
if x1_desc:
141+
if dpnp.is_cuda_backend(x1_desc.get_array()):
142+
raise NotImplementedError(
143+
"Running on CUDA is currently not supported"
144+
)
145+
140146
if any(not desc for desc in choices_list):
141147
pass
142148
elif out is not None:

dpnp/dpnp_iface_libmath.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ def erf(in_array1):
8282
in_array1, copy_when_strides=False, copy_when_nondefault_queue=False
8383
)
8484
if x1_desc:
85+
if dpnp.is_cuda_backend(x1_desc.get_array()):
86+
raise NotImplementedError(
87+
"Running on CUDA is currently not supported"
88+
)
8589
return dpnp_erf(x1_desc).get_pyobj()
8690

8791
result = create_output_descriptor_py(

dpnp/dpnp_iface_mathematical.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2945,8 +2945,16 @@ def modf(x1, **kwargs):
29452945
"""
29462946

29472947
x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False)
2948-
if x1_desc and not kwargs:
2949-
return dpnp_modf(x1_desc)
2948+
if x1_desc:
2949+
if dpnp.is_cuda_backend(x1_desc.get_array()):
2950+
raise NotImplementedError(
2951+
"Running on CUDA is currently not supported"
2952+
)
2953+
2954+
if kwargs:
2955+
pass
2956+
else:
2957+
return dpnp_modf(x1_desc)
29502958

29512959
return call_origin(numpy.modf, x1, **kwargs)
29522960

dpnp/dpnp_iface_sorting.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ def partition(x1, kth, axis=-1, kind="introselect", order=None):
192192

193193
x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False)
194194
if x1_desc:
195+
if dpnp.is_cuda_backend(x1_desc.get_array()):
196+
raise NotImplementedError(
197+
"Running on CUDA is currently not supported"
198+
)
199+
195200
if not isinstance(kth, int):
196201
pass
197202
elif x1_desc.ndim == 0:

dpnp/linalg/dpnp_utils_linalg.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,14 @@ def _batched_qr(a, mode="reduced"):
397397
batch_size,
398398
depends=[copy_ev],
399399
)
400-
_manager.add_event_pair(ht_ev, geqrf_ev)
400+
401+
# w/a to avoid raice conditional on CUDA during multiple runs
402+
# TODO: Remove it ones the OneMath issue is resolved
403+
# https://github.com/uxlfoundation/oneMath/issues/626
404+
if dpnp.is_cuda_backend(a_sycl_queue):
405+
ht_ev.wait()
406+
else:
407+
_manager.add_event_pair(ht_ev, geqrf_ev)
401408

402409
if mode in ["r", "raw"]:
403410
if mode == "r":
@@ -2468,7 +2475,14 @@ def dpnp_qr(a, mode="reduced"):
24682475
ht_ev, geqrf_ev = li._geqrf(
24692476
a_sycl_queue, a_t.get_array(), tau_h.get_array(), depends=[copy_ev]
24702477
)
2471-
_manager.add_event_pair(ht_ev, geqrf_ev)
2478+
2479+
# w/a to avoid raice conditional on CUDA during multiple runs
2480+
# TODO: Remove it ones the OneMath issue is resolved
2481+
# https://github.com/uxlfoundation/oneMath/issues/626
2482+
if dpnp.is_cuda_backend(a_sycl_queue):
2483+
ht_ev.wait()
2484+
else:
2485+
_manager.add_event_pair(ht_ev, geqrf_ev)
24722486

24732487
if mode in ["r", "raw"]:
24742488
if mode == "r":

0 commit comments

Comments
 (0)