Skip to content

Reuse reduction/dot buffer as sqrt output in linalg.norm - #3062

Merged
antonwolfy merged 2 commits into
masterfrom
norm-sqrt-out
Sep 8, 2026
Merged

Reuse reduction/dot buffer as sqrt output in linalg.norm#3062
antonwolfy merged 2 commits into
masterfrom
norm-sqrt-out

Conversation

@antonwolfy

@antonwolfy antonwolfy commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

In the dpnp.linalg.norm implementation, the 2-norm and Frobenius-norm branches computed sqrt(sum(...)) (or sqrt(dot(...)) on the axis=None fast path) allocating a fresh array for the sqrt output on top of the array already produced by the reduction.

These branches now capture the reduction (or dot) result and pass it back as out= to dpnp.sqrt, so the intermediate buffer is reused as the output instead of allocating a new one. The reused buffer is a private, unaliased array in every case, and its dtype matches the sqrt output, so the in-place write is safe. On the axis=None fast path the reused buffer is a scalar, so the change there is for consistency.

This is an allocation saving only; it does not change results or reduce the number of kernel launches.

  • Have you provided a meaningful PR description?
  • Have you added a test, reproducer or referred to an issue with a reproducer?
  • Have you tested your changes locally for CPU and GPU devices?
  • Have you made sure that new changes do not introduce compiler warnings?
  • Have you checked performance impact of proposed changes?
  • Have you added documentation for your changes, if necessary?
  • Have you added your changes to the changelog?

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.
@antonwolfy antonwolfy self-assigned this Sep 8, 2026
@antonwolfy antonwolfy added this to the 0.21.0 release milestone Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

View rendered docs @ https://intelpython.github.io/dpnp/index.html

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Array API standard conformance tests for dpnp=0.21.0dev8=py314ha0e2e8e_4 ran successfully.
Passed: 1376
Failed: 0
Skipped: 6

@coveralls

Copy link
Copy Markdown
Collaborator

Coverage Status

coverage: 78.495% (+0.001%) from 78.494% — norm-sqrt-out into master

@antonwolfy

Copy link
Copy Markdown
Contributor Author

Performance & memory validation

Benchmarked this branch against master on an Intel Arc iGPU (Lunar Lake) and CPU. Since the change is Python-only, both variants were measured by swapping just dpnp/linalg/dpnp_utils_linalg.py — no rebuild.

Coverage — 5 workloads, one per touched branch (a large-output variant to show the memory effect and a scalar-output variant as a no-regression control), across float32/float64/complex64/complex128 on GPU + CPU:

Workload norm() call Branch exercised
vector 2-norm (4M) norm(x) dpnp_norm axis=None fast path (dot)
row 2-norm (1M×8) norm(x, axis=1) _norm_int_axis — large output
row 2-norm (4k×4k) norm(x, axis=1) _norm_int_axis — small output
batched Frobenius (262k×4×4) norm(x, axis=(1,2)) _norm_tuple_axis — large output
matrix Frobenius (4k×4k) norm(x, ord="fro", axis=(0,1)) _norm_tuple_axis — scalar output

Method — median of 400 pooled reps per config (4 rounds × 100, alternating master/PR order each round to cancel thermal drift; 5 cold warmup calls excluded, device queue synced per call), with a bootstrap 95% CI on each master-vs-PR ratio. Transient USM allocations were counted by instrumenting fresh dpnp array creation and dpnp.sqrt.

Runtime — no regression

  • GPU median ratio 0.99×, CPU median 1.00× (PR ÷ master; <1 = PR faster).
  • The residual per-config deltas split in both directions and don't track the change. The largest apparent slowdown lands on the scalar-output fro_2d case where the two code paths are essentially identical — i.e. a measurement artifact, not the edit. The largest genuine speedups (≈0.88–0.95×) land on the large-reduction cases that actually skip the allocation.

Memory — one buffer removed per call

  • The transient USM allocation count drops by exactly 1 in all 40 configs.
  • The eliminated buffer equals the output shape: a few bytes for whole-array norms (scalar output), up to a full output-sized buffer for row-wise/batched norms:
Workload float32 float64 complex64 complex128
vector 2-norm (4M) 4 B 8 B 4 B 8 B
row 2-norm (1M×8) 4 MB 8 MB 4 MB 8 MB
row 2-norm (4k×4k) 16 KB 32 KB 16 KB 32 KB
batched Frobenius (262k×4×4) 1 MB 2 MB 1 MB 2 MB
matrix Frobenius (4k×4k) 4 B 8 B 4 B 8 B

Conclusion

Results confirm the PR description: an allocation saving only — no change to results or kernel-launch count, no runtime regression, and a deterministic one-buffer-per-call memory reduction that scales with output size.

@antonwolfy
antonwolfy marked this pull request as ready for review September 8, 2026 15:13

@ndgrigorian ndgrigorian left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@antonwolfy
antonwolfy merged commit cbd45df into master Sep 8, 2026
108 of 118 checks passed
@antonwolfy
antonwolfy deleted the norm-sqrt-out branch September 8, 2026 17:31
github-actions Bot added a commit that referenced this pull request Sep 8, 2026
In the `dpnp.linalg.norm` implementation, the 2-norm and Frobenius-norm
branches computed `sqrt(sum(...))` (or `sqrt(dot(...))` on the
`axis=None` fast path) allocating a fresh array for the `sqrt` output on
top of the array already produced by the reduction.

These branches now capture the reduction (or dot) result and pass it
back as `out=` to `dpnp.sqrt`, so the intermediate buffer is reused as
the output instead of allocating a new one. The reused buffer is a
private, unaliased array in every case, and its dtype matches the `sqrt`
output, so the in-place write is safe. On the `axis=None` fast path the
reused buffer is a scalar, so the change there is for consistency.

This is an allocation saving only; it does not change results or reduce
the number of kernel launches. cbd45df
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants