Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Follow recommendation on the interaction with numpy.ndarray in binary ops #2266

Merged
merged 8 commits into from
Jan 20, 2025

Conversation

antonwolfy
Copy link
Contributor

@antonwolfy antonwolfy commented Jan 20, 2025

The PR proposes to follow NEP-13 recommendations on how to interact with numpy.ndarray in binary the operations.

It will set __array_ufunc__ = None which means that dpnp implements Python binary operations freely and so numpy.ufuncs called on this argument will raise TypeError:

a = numpy.ones(10)
b = dpnp.ones(10)
a += b
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[9], line 1
----> 1 a += b

TypeError: operand 'dpnp_array' does not support ufuncs (__array_ufunc__=None)

And an elementwise operation with numpy.ndarray will cause an explicit exception in dpnp:

a + b
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[4], line 1
----> 1 a + b

File ~/code/dpnp/dpnp/dpnp_array.py:518, in dpnp_array.__radd__(self, other)
    516 def __radd__(self, other):
    517     """Return ``value+self``."""
--> 518     return dpnp.add(other, self)

File ~/code/dpnp/dpnp/dpnp_algo/dpnp_elementwise_common.py:314, in DPNPBinaryFunc.__call__(self, x1, x2, out, where, order, dtype, subok, **kwargs)
    303 def __call__(
    304     self,
    305     x1,
   (...)
    312     **kwargs,
    313 ):
--> 314     dpnp.check_supported_arrays_type(
    315         x1, x2, scalar_type=True, all_scalars=False
    316     )
    317     if kwargs:
    318         raise NotImplementedError(
    319             f"Requested function={self.name_} with kwargs={kwargs} "
    320             "isn't currently supported."
    321         )

File ~/code/dpnp/dpnp/dpnp_iface.py:400, in check_supported_arrays_type(scalar_type, all_scalars, *arrays)
    397     if scalar_type and dpnp.isscalar(a):
    398         continue
--> 400     raise TypeError(
    401         f"An array must be any of supported type, but got {type(a)}"
    402     )
    404 if len(arrays) > 0 and not (all_scalars or any_is_array):
    405     raise TypeError(
    406         "At least one input must be of supported array type, "
    407         "but got all scalars."
    408     )

TypeError: An array must be any of supported type, but got <class 'numpy.ndarray'>

Previously it works as in a way:

a = numpy.ones(10)
b = dpnp.ones(10)

a + b
# Out:
# array([array(2.), array(2.), array(2.), array(2.), array(2.), array(2.),
#        array(2.), array(2.), array(2.), array(2.)], dtype=object)

Note, some updates in tests from #2260 have been mapped to that PR.

  • Have you provided a meaningful PR description?
  • Have you added a test, reproducer or referred to 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?
  • If this PR is a work in progress, are you filing the PR as a draft?

@coveralls
Copy link
Collaborator

coveralls commented Jan 20, 2025

Coverage Status

coverage: 70.845% (+0.001%) from 70.844%
when pulling ede832e on follow-nep-13
into 7ce5219 on master.

dpnp/tests/helper.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@vlad-perevezentsev vlad-perevezentsev left a comment

Choose a reason for hiding this comment

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

LGTM!
Thank you @antonwolfy

Copy link
Contributor

Array API standard conformance tests for dpnp=0.17.0dev4=py312he4f9c94_17 ran successfully.
Passed: 950
Failed: 0
Skipped: 50

@antonwolfy antonwolfy merged commit 13816bd into master Jan 20, 2025
46 of 53 checks passed
@antonwolfy antonwolfy deleted the follow-nep-13 branch January 20, 2025 18:07
github-actions bot added a commit that referenced this pull request Jan 20, 2025
…ry ops (#2266)

The PR proposes to follow NEP-13
[recommendations](https://numpy.org/neps/nep-0013-ufunc-overrides.html#behavior-in-combination-with-python-s-binary-operations)
on how to interact with `numpy.ndarray` in binary the operations.

It will set `__array_ufunc__ = None` which means that dpnp implements
Python binary operations freely and so `numpy.ufuncs` called on this
argument will raise `TypeError`:
```python
a = numpy.ones(10)
b = dpnp.ones(10)
a += b
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[9], line 1
----> 1 a += b

TypeError: operand 'dpnp_array' does not support ufuncs (__array_ufunc__=None)
```
And an elementwise operation with `numpy.ndarray` will cause an explicit
exception in dpnp:
```python
a + b
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[4], line 1
----> 1 a + b

File ~/code/dpnp/dpnp/dpnp_array.py:518, in dpnp_array.__radd__(self, other)
    516 def __radd__(self, other):
    517     """Return ``value+self``."""
--> 518     return dpnp.add(other, self)

File ~/code/dpnp/dpnp/dpnp_algo/dpnp_elementwise_common.py:314, in DPNPBinaryFunc.__call__(self, x1, x2, out, where, order, dtype, subok, **kwargs)
    303 def __call__(
    304     self,
    305     x1,
   (...)
    312     **kwargs,
    313 ):
--> 314     dpnp.check_supported_arrays_type(
    315         x1, x2, scalar_type=True, all_scalars=False
    316     )
    317     if kwargs:
    318         raise NotImplementedError(
    319             f"Requested function={self.name_} with kwargs={kwargs} "
    320             "isn't currently supported."
    321         )

File ~/code/dpnp/dpnp/dpnp_iface.py:400, in check_supported_arrays_type(scalar_type, all_scalars, *arrays)
    397     if scalar_type and dpnp.isscalar(a):
    398         continue
--> 400     raise TypeError(
    401         f"An array must be any of supported type, but got {type(a)}"
    402     )
    404 if len(arrays) > 0 and not (all_scalars or any_is_array):
    405     raise TypeError(
    406         "At least one input must be of supported array type, "
    407         "but got all scalars."
    408     )

TypeError: An array must be any of supported type, but got <class 'numpy.ndarray'>
```

Previously it works as in a way:
```python
a = numpy.ones(10)
b = dpnp.ones(10)

a + b
# Out:
# array([array(2.), array(2.), array(2.), array(2.), array(2.), array(2.),
#        array(2.), array(2.), array(2.), array(2.)], dtype=object)
```

Note, some updates in tests from #2260 have been mapped to that PR. 13816bd
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