From 3d2ab4d428d49d60165faa08b1db2c9fb2b14b31 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 8 Sep 2026 12:47:28 +0200 Subject: [PATCH 1/2] Reuse reduction/dot buffer as sqrt output in linalg.norm Pass out= to dpnp.sqrt in the 2-norm and Frobenius-norm branches so the existing reduction (or dot) result is reused as the sqrt output buffer instead of allocating a new array. --- dpnp/linalg/dpnp_utils_linalg.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dpnp/linalg/dpnp_utils_linalg.py b/dpnp/linalg/dpnp_utils_linalg.py index 527235496b9..ac1c87a61b5 100644 --- a/dpnp/linalg/dpnp_utils_linalg.py +++ b/dpnp/linalg/dpnp_utils_linalg.py @@ -1162,8 +1162,8 @@ def _norm_int_axis(x, ord, axis, keepdims): return dpnp.abs(x).sum(axis=axis, keepdims=keepdims) if ord is None or ord == 2: # special case for speedup - s = (dpnp.conj(x) * x).real - return dpnp.sqrt(dpnp.sum(s, axis=axis, keepdims=keepdims)) + s = dpnp.sum((dpnp.conj(x) * x).real, axis=axis, keepdims=keepdims) + return dpnp.sqrt(s, out=s) if isinstance(ord, (int, float)): absx = dpnp.abs(x) absx **= ord @@ -1215,7 +1215,8 @@ def _norm_tuple_axis(x, ord, row_axis, col_axis, keepdims): row_axis -= 1 ret = dpnp.abs(x).sum(axis=col_axis).min(axis=row_axis) elif ord in [None, "fro", "f"]: - ret = dpnp.sqrt(dpnp.sum((dpnp.conj(x) * x).real, axis=axis)) + ret = dpnp.sum((dpnp.conj(x) * x).real, axis=axis) + ret = dpnp.sqrt(ret, out=ret) elif ord == "nuc": ret = _multi_svd_norm(x, row_axis, col_axis, dpnp.sum) else: @@ -2360,7 +2361,7 @@ def dpnp_norm(x, ord=None, axis=None, keepdims=False): sqnorm = dpnp.dot(x_real, x_real) + dpnp.dot(x_imag, x_imag) else: sqnorm = dpnp.dot(x, x) - ret = dpnp.sqrt(sqnorm) + ret = dpnp.sqrt(sqnorm, out=sqnorm) if keepdims: ret = ret.reshape((1,) * ndim) return ret From ce5d3e4164f2181d7b0221ac85ad931a8776ea2d Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 8 Sep 2026 12:50:28 +0200 Subject: [PATCH 2/2] Add changelog entry for linalg.norm sqrt out= reuse --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09961c7ccd3..24064fcc16a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ This release is compatible with NumPy 2.5. * Linked the `dpnp_backend_c` library against only the MKL SYCL domains it uses (`BLAS`, `RNG`, `VM`) [#3012](https://github.com/IntelPython/dpnp/pull/3012) * `dpnp` uses pybind11 3.1.0 [#3015](https://github.com/IntelPython/dpnp/pull/3015) * Reworked the ASV benchmarks and added end-to-end workload benchmarks derived from dpBench [#2996](https://github.com/IntelPython/dpnp/pull/2996) +* Reduced allocations in `dpnp.linalg.norm` by reusing the reduction result as the `sqrt` output buffer in the 2-norm and Frobenius-norm branches [#3062](https://github.com/IntelPython/dpnp/pull/3062) ### Deprecated