Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

API: Adddevice andto_device tonumpy.ndarray [Array API]#25233

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ngoldbaum merged 3 commits intonumpy:mainfrommtsokol:numpy-device
Jan 18, 2024

Conversation

@mtsokol
Copy link
Member

@mtsokolmtsokol commentedNov 23, 2023
edited
Loading

Hi@rgommers@seberg,

This PR introducesdevice andto_device members tonumpy.ndarray.

Additionally,device keyword-only arguments were added to:
numpy.asarray,numpy.arange,numpy.empty,numpy.empty_like,
numpy.eye,numpy.full,numpy.full_like,numpy.linspace,
numpy.ones,numpy.ones_like,numpy.zeros, andnumpy.zeros_like.

@mtsokolmtsokol self-assigned thisNov 23, 2023
@mtsokolmtsokol changed the titleAPI: Adddevice andto_device tonumpy.ndarrayAPI: Adddevice andto_device tonumpy.ndarray [Array API]Nov 23, 2023
@mtsokolmtsokolforce-pushed thenumpy-device branch 2 times, most recently from4a36606 to5037b48CompareNovember 23, 2023 13:35
@mtsokolmtsokol added this to the2.0.0 release milestoneNov 29, 2023
@mtsokolmtsokolforce-pushed thenumpy-device branch 2 times, most recently from4e99405 to89184dfCompareNovember 29, 2023 15:58
@mtsokol
Copy link
MemberAuthor

mtsokol commentedNov 29, 2023
edited
Loading

Hi@seberg,
I completed C-level changes: The new enum and keyword-only arguments are in place. I added the string interning optimization for"cpu", I did an experiment andobject == npy_ma_str_cpu comparison works fordevice="cpu".
In the implementation I kept it asPyUnicode_Compare(object, npy_ma_str_cpu) becausePyUnicode_Compare starts withan identity comparison. (Or should I keep it as==?)

@ngoldbaum
Copy link
Member

I think there's enough code out there relying on the identity comparison fast path inPyUnicde_Compare that you can assume CPython won't remove it.

There's a real test failure though:

self = <numpy._core.tests.test_multiarray.TestDevice object at 0x000001c0cb8314b0>    def test_device(self):        arr = np.arange(5)            assert arr.device == "cpu"        with assert_raises_regex(            AttributeError,            "attribute 'device' of 'numpy.ndarray' objects is "            "not writable"        ):>           arr.device = "other"E           AttributeError: attribute 'device' of 'ndarray' objects is not writable

@mtsokol
Copy link
MemberAuthor

There's a real test failure though:

Right, I need to adjust the regex to conform to pypy's ndarray name.

@mtsokol
Copy link
MemberAuthor

Now it's ready.

@ngoldbaum
Copy link
Member

Just for the record - it would be nice to see a little justification here or in the eventual NEP for why we need this, despite the only allowed options being"cpu" orNone. It's self-evident it adds benefits if you want to write code that will work correctly in numpy or pytorch generically (for example) - are there any other plusses for users who don't need array API compat? On the whole it's probably worth adding stuff to the API that isn't actually useful but does make it easier to write array API-compatible code, but that argument should be spelled out somewhere.

I would also add to all the docstrings fordevice as a keyword argument something like:

.. note:    Only the ``"cpu"`` device is supported by NumPy.
mtsokol, lucascolley, and steven-channel reacted with thumbs up emoji

@charrischarris changed the titleAPI: Adddevice andto_device tonumpy.ndarray [Array API]API: Adddevice andto_device tonumpy.ndarray [Array API]Dec 11, 2023
@ngoldbaum
Copy link
Member

@mtsokol
Copy link
MemberAuthor

Hmm, looks like those note admonitions don't show up in the docstrings:https://output.circle-artifacts.com/output/job/ce6f8552-de08-47c3-80bb-91eb2ad750a5/artifacts/0/doc/build/html/reference/generated/numpy.empty.html#numpy.empty

Ah, I missed one: in thenote:: definition - now they're all visible.

@mtsokolmtsokolforce-pushed thenumpy-device branch 4 times, most recently frombe8b328 to5498f7fCompareDecember 21, 2023 16:50
asmeurer added a commit to asmeurer/numpy that referenced this pull requestJan 10, 2024
Copy link
Contributor

@mhvkmhvk left a comment

Choose a reason for hiding this comment

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

Comments mostly from the point of view that we should try to minimize any impact from an argument that for numpy is not useful. So I'd putdevice afterlike, and would try to minimize extra lines added and impact on code by passing it on as much as possible, so that there is only one place where the error gets raised (in the C code parsingdevice).

seberg reacted with thumbs up emoji
add_newdoc('numpy._core.multiarray','asarray',
"""
asarray(a, dtype=None, order=None, *, like=None)
asarray(a, dtype=None, order=None, *,device=None,like=None)
Copy link
Contributor

Choose a reason for hiding this comment

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

Here and below, why isdevice ahead oflike? Since one cannot use it for anything useful, my tendency would be to put it at the end.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, why not just set the default to"cpu"? That seems clearer. (Still fine to acceptNone).

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Right now the function dispatch requireslike to be the last argument - here's a check that raisesRuntimeError if a function doesn't comply with it:

last_arg=co.co_argcount+co.co_kwonlyargcount-1
last_arg=co.co_varnames[last_arg]
iflast_arg!="like"orco.co_kwonlyargcount==0:
raiseRuntimeError(
"__array_function__ expects `like=` to be the last "
"argument and a keyword-only argument. "
f"{implementation} does not seem to comply.")

Can I keepdevice beforelike or should we update the__array_function__ protocol?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Also, why not just set the default to"cpu"? That seems clearer. (Still fine to acceptNone).

That's true that"cpu" is the only supported value, but I would prefer to stick to the Array API standard here. It defines the default value fordevice asNone:https://data-apis.org/array-api/latest/API_specification/generated/array_api.asarray.html

We're adding these keyword arguments for Array API compatibility only, so I would prefer to fully conform with it.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think it matters from the Array API perspective, it doesn't make NumPy non-compliant, it just makes it explicit about what that default is.

But, I'll give a very slight vote to just keep itNone anyway. Just becuase I don't think the more explicitdevice="cpu" makes it clearer, since users should ignore it anyway (you only use it viaxp = arr.__array_namespace__() as an Array API user, never directly as a NumPy user).

Copy link
Member

Choose a reason for hiding this comment

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

The order doesn't matter much in principle, since it's keyword-only andlike is only for other non-numpy libraries as well. However, there's a bigger problem here:

>>>importnumpyasnp>>>importdask.arrayasda>>>d=da.ones((1,2))>>>np.asarray([1,2],device='cpu')array([1,2])>>>np.asarray([1,2],device='cpu',like=d)Traceback (mostrecentcalllast):CellIn[24],line1np.asarray([1,2],device='cpu',like=d)File~/code/tmp/dask/dask/array/core.py:1760in__array_function__returnda_func(*args,**kwargs)File~/code/tmp/dask/dask/array/core.py:4581inasarrayreturnfrom_array(a,getitem=getter_inline,**kwargs)TypeError:from_array()gotanunexpectedkeywordargument'device'

Thedevice keyword probably should not be added to the dispatchers for any of these creation functions. It looks like the__array_function__ protocol wasn't implemented in a forward-looking way - I haven't looked much deeper yet, but at first sight it may be the case that we can never add a new keyword to dispatched functions anymore.

In this case,device is here to support writing cross-library-compatible code via the array API standard. The dispatching protocols kinda were earlier attempts to do something similar. So probably they should not interact anyway?

seberg reacted with thumbs up emoji
Copy link
Member

@rgommersrgommersJan 17, 2024
edited
Loading

Choose a reason for hiding this comment

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

Ah wait, it's maybe not that extreme -np.asarray([1, 2], like=d) still works, so new keywords are fine,as long as they are not used (then they don't get forwarded). Of course that's a bit funky, but there's no way to avoid it really.

>>>np.asarray([1,2],device='cpu')array([1,2])>>>np.asarray([1,2],like=d)dask.array<array,shape=(2,),dtype=int64,chunksize=(2,),chunktype=numpy.ndarray>>>>np.asarray([1,2],like=d,device='cpu')...TypeError:from_array()gotanunexpectedkeywordargument'device'

This would have been much more problematic if libraries like SciPy and scikit-learn supported non-numpy array inputs via__array_ufunc/function__. But since they squash such inputs anyway withnp.asarray, there shouldn't be too much of an issue in practice.

And it's fairly easy to add support for new keywords in Dask & co. They just need a new 2.0-compatible release that adds such support, and thendevice/like can be used together.

Copy link
Contributor

Choose a reason for hiding this comment

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

@rgommers - I've gotten quite used to updating astropy's__array_function__ wrappers to remain compatible with numpy functions -- and we've got tests to check that our signatures remain consistent. Of course it doesn't happen that often. So, I don't think that's a worry, and overall I'd tend to not special-case any arguments (i.e., pass it on if present).

On the order: iflike has to be last, then just keep it like that, sorry for not noticing myself.

Copy link
Member

Choose a reason for hiding this comment

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

Just to clarify: the check is only there to test habits, and probably mainly to make sure it is kwarg only.
It may have to be last in C (not sure), but it doesn't really matter anywhere here. But... it also doesn't matter a lot (especially since if someone cares, they can change it).

Copy link
Member

Choose a reason for hiding this comment

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

Thanks@mhvk, that is useful context. A test that flag mismatches sounds like a great idea. 🤞🏼 most implementers have that.

@ngoldbaum
Copy link
Member

Merging this one as well since all comments have been addressed. Thanks@mtsokol!

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@sebergsebergseberg left review comments

@rgommersrgommersrgommers left review comments

@mhvkmhvkmhvk left review comments

@ngoldbaumngoldbaumngoldbaum left review comments

Assignees

@mtsokolmtsokol

Projects

None yet

Milestone

2.0.0 release

Development

Successfully merging this pull request may close these issues.

5 participants

@mtsokol@ngoldbaum@seberg@rgommers@mhvk

[8]ページ先頭

©2009-2025 Movatter.jp