Skip to content

Commit 6c3da9b

Browse files
Merge branch 'master' into histogramdd
2 parents f00e8b2 + 4607833 commit 6c3da9b

File tree

122 files changed

+16967
-2137
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+16967
-2137
lines changed

.github/workflows/openssf-scorecard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,6 @@ jobs:
6868

6969
# Upload the results to GitHub's code scanning dashboard.
7070
- name: "Upload to code-scanning"
71-
uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
71+
uses: github/codeql-action/upload-sarif@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6
7272
with:
7373
sarif_file: results.sarif

.pre-commit-config.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ repos:
3434
(?x)^(
3535
dpnp/tests/test_arraycreation.py|
3636
dpnp/tests/test_sycl_queue.py|
37-
dpnp/tests/test_usm_type.py
37+
dpnp/tests/test_usm_type.py|
38+
dpnp/tests/third_party/cupy/core_tests/test_nep50_examples.py
3839
)$
3940
- id: python-no-log-warn
4041
- id: python-use-type-annotations

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
### Fixed
1414

1515

16+
## [0.16.1] - 12/06/2024
17+
18+
This is a bug-fix release.
19+
20+
### Changed
21+
22+
* Changed to use `Miniforge` installer in GitHub actions [#2057](https://github.com/IntelPython/dpnp/pull/2057)
23+
* Updated `README.md` to reflect current installation requirements and available options [#2166](https://github.com/IntelPython/dpnp/pull/2166)
24+
* Corrected the list of owners and code maintainers [#2185](https://github.com/IntelPython/dpnp/pull/2185)
25+
* Bumped the version of `oneMKL` interface used in dpnp build by default to align it with `2025.0` oneAPI release [#2193](https://github.com/IntelPython/dpnp/pull/2193)
26+
27+
### Fixed
28+
29+
* Resolved an issue with Compute Follows Data inconsistency in `dpnp.extract` function [#2172](https://github.com/IntelPython/dpnp/pull/2172)
30+
* Resolved an import error when using `dpnp` in virtual environment on Linux [#2199](https://github.com/IntelPython/dpnp/pull/2199)
31+
* Fixed incorrect result produced by `dpnp.fft.fft` function when input array has negative strides [#2202](https://github.com/IntelPython/dpnp/pull/2202)
32+
* Fixed an issue with `numpy.ndarray` input processing in the `dpnp.from_dlpack` function and updated the documentation [#2209](https://github.com/IntelPython/dpnp/pull/2209)
33+
* Resolved a compilation error when building with DPC++ 2025.1 compiler [#2211](https://github.com/IntelPython/dpnp/pull/2211)
34+
35+
1636
## [0.16.0] - 10/14/2024
1737

1838
This release reaches an important milestone by making offloading fully asynchronous. Calls to `dpnp` submit tasks for execution to DPC++ runtime and return without waiting for execution of these tasks to finish. The sequential semantics a user comes to expect from execution of Python script is preserved though.

dpnp/dpnp_array.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def mT(self):
150150
if self.ndim < 2:
151151
raise ValueError("matrix transpose with ndim < 2 is undefined")
152152

153-
return self._array_obj.mT
153+
return dpnp_array._create_from_usm_ndarray(self._array_obj.mT)
154154

155155
def to_device(self, target_device):
156156
"""Transfer array to target device."""

dpnp/linalg/dpnp_utils_linalg.py

Lines changed: 78 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ def _batched_qr(a, mode="reduced"):
475475
)
476476

477477

478+
# pylint: disable=too-many-locals
478479
def _batched_svd(
479480
a,
480481
uv_type,
@@ -532,29 +533,30 @@ def _batched_svd(
532533
batch_shape_orig,
533534
)
534535

535-
k = min(m, n)
536-
if compute_uv:
537-
if full_matrices:
538-
u_shape = (m, m) + (batch_size,)
539-
vt_shape = (n, n) + (batch_size,)
540-
jobu = ord("A")
541-
jobvt = ord("A")
542-
else:
543-
u_shape = (m, k) + (batch_size,)
544-
vt_shape = (k, n) + (batch_size,)
545-
jobu = ord("S")
546-
jobvt = ord("S")
536+
# Transpose if m < n:
537+
# 1. cuSolver gesvd supports only m >= n
538+
# 2. Reducing a matrix with m >= n to bidiagonal form is more efficient
539+
if m < n:
540+
n, m = a.shape[-2:]
541+
trans_flag = True
547542
else:
548-
u_shape = vt_shape = ()
549-
jobu = ord("N")
550-
jobvt = ord("N")
543+
trans_flag = False
544+
545+
u_shape, vt_shape, s_shape, jobu, jobvt = _get_svd_shapes_and_flags(
546+
m, n, compute_uv, full_matrices, batch_size=batch_size
547+
)
551548

552549
_manager = dpu.SequentialOrderManager[exec_q]
553550
dep_evs = _manager.submitted_events
554551

555552
# Reorder the elements by moving the last two axes of `a` to the front
556553
# to match fortran-like array order which is assumed by gesvd.
557-
a = dpnp.moveaxis(a, (-2, -1), (0, 1))
554+
if trans_flag:
555+
# Transpose axes for cuSolver and to optimize reduction
556+
# to bidiagonal form
557+
a = dpnp.moveaxis(a, (-1, -2), (0, 1))
558+
else:
559+
a = dpnp.moveaxis(a, (-2, -1), (0, 1))
558560

559561
# oneMKL LAPACK gesvd destroys `a` and assumes fortran-like array
560562
# as input.
@@ -583,7 +585,7 @@ def _batched_svd(
583585
sycl_queue=exec_q,
584586
)
585587
s_h = dpnp.empty(
586-
(batch_size,) + (k,),
588+
s_shape,
587589
dtype=s_type,
588590
order="C",
589591
usm_type=usm_type,
@@ -607,16 +609,23 @@ def _batched_svd(
607609
# gesvd call writes `u_h` and `vt_h` in Fortran order;
608610
# reorder the axes to match C order by moving the last axis
609611
# to the front
610-
u = dpnp.moveaxis(u_h, -1, 0)
611-
vt = dpnp.moveaxis(vt_h, -1, 0)
612+
if trans_flag:
613+
# Transpose axes to restore U and V^T for the original matrix
614+
u = dpnp.moveaxis(u_h, (0, -1), (-1, 0))
615+
vt = dpnp.moveaxis(vt_h, (0, -1), (-1, 0))
616+
else:
617+
u = dpnp.moveaxis(u_h, -1, 0)
618+
vt = dpnp.moveaxis(vt_h, -1, 0)
619+
612620
if a_ndim > 3:
613621
u = u.reshape(batch_shape_orig + u.shape[-2:])
614622
vt = vt.reshape(batch_shape_orig + vt.shape[-2:])
615623
# dpnp.moveaxis can make the array non-contiguous if it is not 2D
616624
# Convert to contiguous to align with NumPy
617625
u = dpnp.ascontiguousarray(u)
618626
vt = dpnp.ascontiguousarray(vt)
619-
return u, s, vt
627+
# Swap `u` and `vt` for transposed input to restore correct order
628+
return (vt, s, u) if trans_flag else (u, s, vt)
620629
return s
621630

622631

@@ -759,6 +768,36 @@ def _common_inexact_type(default_dtype, *dtypes):
759768
return dpnp.result_type(*inexact_dtypes)
760769

761770

771+
def _get_svd_shapes_and_flags(m, n, compute_uv, full_matrices, batch_size=None):
772+
"""Return the shapes and flags for SVD computations."""
773+
774+
k = min(m, n)
775+
if compute_uv:
776+
if full_matrices:
777+
u_shape = (m, m)
778+
vt_shape = (n, n)
779+
jobu = ord("A")
780+
jobvt = ord("A")
781+
else:
782+
u_shape = (m, k)
783+
vt_shape = (k, n)
784+
jobu = ord("S")
785+
jobvt = ord("S")
786+
else:
787+
u_shape = vt_shape = ()
788+
jobu = ord("N")
789+
jobvt = ord("N")
790+
791+
s_shape = (k,)
792+
if batch_size is not None:
793+
if compute_uv:
794+
u_shape += (batch_size,)
795+
vt_shape += (batch_size,)
796+
s_shape = (batch_size,) + s_shape
797+
798+
return u_shape, vt_shape, s_shape, jobu, jobvt
799+
800+
762801
def _hermitian_svd(a, compute_uv):
763802
"""
764803
_hermitian_svd(a, compute_uv)
@@ -2695,6 +2734,16 @@ def dpnp_svd(
26952734
a, uv_type, s_type, full_matrices, compute_uv, exec_q, usm_type
26962735
)
26972736

2737+
# Transpose if m < n:
2738+
# 1. cuSolver gesvd supports only m >= n
2739+
# 2. Reducing a matrix with m >= n to bidiagonal form is more efficient
2740+
if m < n:
2741+
n, m = a.shape
2742+
a = a.transpose()
2743+
trans_flag = True
2744+
else:
2745+
trans_flag = False
2746+
26982747
# oneMKL LAPACK gesvd destroys `a` and assumes fortran-like array as input.
26992748
# Allocate 'F' order memory for dpnp arrays to comply with
27002749
# these requirements.
@@ -2716,22 +2765,9 @@ def dpnp_svd(
27162765
)
27172766
_manager.add_event_pair(ht_ev, copy_ev)
27182767

2719-
k = min(m, n)
2720-
if compute_uv:
2721-
if full_matrices:
2722-
u_shape = (m, m)
2723-
vt_shape = (n, n)
2724-
jobu = ord("A")
2725-
jobvt = ord("A")
2726-
else:
2727-
u_shape = (m, k)
2728-
vt_shape = (k, n)
2729-
jobu = ord("S")
2730-
jobvt = ord("S")
2731-
else:
2732-
u_shape = vt_shape = ()
2733-
jobu = ord("N")
2734-
jobvt = ord("N")
2768+
u_shape, vt_shape, s_shape, jobu, jobvt = _get_svd_shapes_and_flags(
2769+
m, n, compute_uv, full_matrices
2770+
)
27352771

27362772
# oneMKL LAPACK assumes fortran-like array as input.
27372773
# Allocate 'F' order memory for dpnp output arrays to comply with
@@ -2746,7 +2782,7 @@ def dpnp_svd(
27462782
shape=vt_shape,
27472783
order="F",
27482784
)
2749-
s_h = dpnp.empty_like(a_h, shape=(k,), dtype=s_type)
2785+
s_h = dpnp.empty_like(a_h, shape=s_shape, dtype=s_type)
27502786

27512787
ht_ev, gesvd_ev = li._gesvd(
27522788
exec_q,
@@ -2761,6 +2797,11 @@ def dpnp_svd(
27612797
_manager.add_event_pair(ht_ev, gesvd_ev)
27622798

27632799
if compute_uv:
2800+
# Transposing the input matrix swaps the roles of U and Vt:
2801+
# For A^T = V S^T U^T, `u_h` becomes V and `vt_h` becomes U^T.
2802+
# Transpose and swap them back to restore correct order for A.
2803+
if trans_flag:
2804+
return vt_h.T, s_h, u_h.T
27642805
# gesvd call writes `u_h` and `vt_h` in Fortran order;
27652806
# Convert to contiguous to align with NumPy
27662807
u_h = dpnp.ascontiguousarray(u_h)

dpnp/random/dpnp_iface_random.py

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,25 +1022,31 @@ def power(a, size=None):
10221022
return call_origin(numpy.random.power, a, size)
10231023

10241024

1025-
def rand(d0, *dn, device=None, usm_type="device", sycl_queue=None):
1025+
def rand(*args, device=None, usm_type="device", sycl_queue=None):
10261026
"""
10271027
Random values in a given shape.
10281028
1029-
Create an array of the given shape and populate it with random samples
1030-
from a uniform distribution over [0, 1).
1029+
Create an array of the given shape and populate it with random samples from
1030+
a uniform distribution over ``[0, 1)``.
10311031
10321032
For full documentation refer to :obj:`numpy.random.rand`.
10331033
10341034
Parameters
10351035
----------
1036+
*args : sequence of ints, optional
1037+
The dimensions of the returned array, must be non-negative.
1038+
If no argument is given a single Python float is returned.
10361039
device : {None, string, SyclDevice, SyclQueue}, optional
10371040
An array API concept of device where the output array is created.
1038-
The `device` can be ``None`` (the default), an OneAPI filter selector string,
1039-
an instance of :class:`dpctl.SyclDevice` corresponding to a non-partitioned SYCL device,
1040-
an instance of :class:`dpctl.SyclQueue`, or a `Device` object returned by
1041+
The `device` can be ``None`` (the default), an OneAPI filter selector
1042+
string, an instance of :class:`dpctl.SyclDevice` corresponding to
1043+
a non-partitioned SYCL device, an instance of :class:`dpctl.SyclQueue`,
1044+
or a `Device` object returned by
10411045
:obj:`dpnp.dpnp_array.dpnp_array.device` property.
1046+
Default: ``None``.
10421047
usm_type : {"device", "shared", "host"}, optional
10431048
The type of SYCL USM allocation for the output array.
1049+
Default: ``"device"``.
10441050
sycl_queue : {None, SyclQueue}, optional
10451051
A SYCL queue to use for output array allocation and copying. The
10461052
`sycl_queue` can be passed as ``None`` (the default), which means
@@ -1051,23 +1057,27 @@ def rand(d0, *dn, device=None, usm_type="device", sycl_queue=None):
10511057
Returns
10521058
-------
10531059
out : dpnp.ndarray
1054-
Random values in a given shape.
1055-
Output array data type is :obj:`dpnp.float64` if device supports it, or :obj:`dpnp.float32` otherwise.
1060+
Random values in a given shape ``(d0, d1, ..., dn)``.
1061+
Output array data type is :obj:`dpnp.float64` if a device supports it,
1062+
or :obj:`dpnp.float32` type otherwise.
10561063
1057-
Examples
1064+
See Also
10581065
--------
1059-
>>> s = dpnp.random.rand(3, 2)
1066+
:obj:`dpnp.random.random` : Return random floats in the half-open interval
1067+
``[0.0, 1.0)``.
1068+
:obj:`dpnp.random.random_sample` : Return random floats in the half-open
1069+
interval ``[0.0, 1.0)``.
1070+
:obj:`dpnp.random.uniform` : Draw samples from a uniform distribution.
10601071
1061-
See Also
1072+
Examples
10621073
--------
1063-
:obj:`dpnp.random.random`
1064-
:obj:`dpnp.random.random_sample`
1065-
:obj:`dpnp.random.uniform`
1074+
>>> import dpnp as np
1075+
>>> s = np.random.rand(3, 2)
10661076
10671077
"""
10681078

10691079
rs = _get_random_state(device=device, sycl_queue=sycl_queue)
1070-
return rs.rand(d0, *dn, usm_type=usm_type)
1080+
return rs.rand(*args, usm_type=usm_type)
10711081

10721082

10731083
def randint(

0 commit comments

Comments
 (0)