Skip to content

Make scalar operands of binary elementwise functions asynchronous - #3182

Open
ndgrigorian wants to merge 2 commits into
masterfrom
make-scalar-operands-in-binary-ops-asynchronous
Open

ndgrigorian wants to merge 2 commits into
masterfrom
make-scalar-operands-in-binary-ops-asynchronous

Conversation

@ndgrigorian

@ndgrigorian ndgrigorian commented Nov 8, 2026 •

Copy link
Copy Markdown
Collaborator

This PR makes binary elementwise functions with a Python or NumPy scalar operand asynchronous, closes #3148

A scalar operand (2 * x, x == 0, x * np.float32(2)), the scalar of clip and where, and a scalar assigned through basic indexing (x[0] = 1) were turned into a 0-d array by _copy_numpy_ndarray_into_usm_ndarray. That copy waits for all work already submitted to the queue, so each of these calls blocked the host until the device was idle. _copy_from_numpy_into and dpnp.tensor.asarray now fill 0-d input with _full_usm_ndarray, ordered after the queue's submitted events, instead. Arrays with ndim > 0 still go through the copy

The value is cast on the host the way the copy kernel would cast it, so results don't change

  • Through float32/complex64 on devices without fp64
  • Complex to real keeps the real part
  • Float to integer goes through int64, so it wraps like the copy kernel where a direct NumPy cast saturates (e.g. 1e10 into int16 gives -7168)
  • No NumPy cast warnings

The new tests patch _copy_numpy_ndarray_into_usm_ndarray to raise, and cover asarray of Python scalars, NumPy scalars and 0-d arrays of every dtype, casts to another dtype, fp64 scalars on devices without fp64, indexed assignment, and binary operators, out= and in-place operators with a scalar operand. They fail without the fix (131 cases). The affected dpnp.tensor tests and dpnp/tests/test_arraycreation.py pass on a Level Zero iGPU and the OpenCL CPU device. The fp64-less test only skipped here, since both devices support fp64

With the reproducer from #3148 on the iGPU, the host time of one call issued right after a ~75 ms matmul:

call master this PR
x * x 0.45 ms 0.51 ms
2 * x 69.37 ms 1.23 ms
x == 0 80.70 ms 0.92 ms
x * np.float32(2) 75.50 ms 1.32 ms
x[0] = 1 76.07 ms 0.43 ms
  • 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?

A Python or NumPy scalar was turned into a 0-d array, or assigned through
basic indexing, with _copy_numpy_ndarray_into_usm_ndarray. That copy
waits for all work submitted to the queue, so every binary operation with
a scalar operand (2 * x, x == 0), clip, where and x[0] = 1 blocked the
host until the device was idle (gh-3148).

_copy_from_numpy_into and asarray now fill 0-d input with
_full_usm_ndarray. The value is cast on the host the way the copy kernel
casts it: through float32/complex64 on devices without fp64, the real
part of complex values, float-to-integer through int64 so that it wraps,
and without NumPy's cast warnings.
@github-actions

github-actions Bot commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actions Bot commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Array API standard conformance tests for dpnp=0.22.0dev1=np2py314h8d9cdd5_7 ran successfully.
Passed: 1491
Failed: 0
Skipped: 6

@coveralls

Copy link
Copy Markdown
Collaborator

Coverage Status

coverage: 84.397%. remained the same — make-scalar-operands-in-binary-ops-asynchronous into master

This branch has not been deployed

No deployments
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.

Python scalar operands in binary elementwise functions synchronize the queue

2 participants