Skip to content

CuPy support #6

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

Merged
merged 24 commits into from
Dec 5, 2022
Merged

CuPy support #6

merged 24 commits into from
Dec 5, 2022

Conversation

asmeurer
Copy link
Member

This refactors the code to be array library independent, so that it can work with either NumPy or CuPy.

Other libraries could be supported as well, although the wrapping for each library would be specific to the differences between that library and the array API.

Fixes #3.

I still need to factor out uses of 'np' in other places in the code.

I'm also not completely sure about the solution for asarray(). asarray() can't
just infer the namespace from the input like every other function can. For
now, I have added a namespace keyword argument to it, which defaults to numpy.
try:
xp = get_namespace(obj, _use_compat=False)
except ValueError:
# TODO: What about lists of arrays?
Copy link
Member

Choose a reason for hiding this comment

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

What you have seems reasonable. Libraries should be passing namespace=numpy if they want this to work, or otherwise handle lists/sequences themselves.

@rgommers
Copy link
Member

I'm looking at get_xp and thinking there's still a piece of the puzzle missing here. Should I wait until that's in place, or am I just missing how it works?

@asmeurer
Copy link
Member Author

I haven't added any cupy functionality yet if that's what you mean. I also need to make sure that NumPy is only an optional dependency of all the code here.

@asmeurer asmeurer marked this pull request as ready for review November 30, 2022 23:49
@asmeurer
Copy link
Member Author

asmeurer commented Dec 1, 2022

This is ready to go. Anyone want to review the overall design here? I've described it in the README.

I still need to set up some CI here, but I've tested the NumPy and CuPy support with the array API test suite and the only issues are things which can't really be fixed by wrapping.

Copy link
Member

@rgommers rgommers left a comment

Choose a reason for hiding this comment

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

I like the approach Aaron, it's pretty easy to understand and it should be extensible.

The one thing that comes to mind as a possible concern is that the get_xp decorator may have some overhead that's larger than desired - if so that could be fairly easily changed to a codegen approach where xp gets replaced by np or cp it looks like.

README.md Outdated

Each will include all the functions from the normal NumPy/CuPy namespace,
except that functions that are part of the array API are wrapped so that they
have the correct array API behavior. In each case, the array object
Copy link
Member

Choose a reason for hiding this comment

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

incomplete sentence here - and it seems to start saying something that's fairly important.


import cupy as cp

# TODO: Should we reject ndarray subclasses?
Copy link
Member

Choose a reason for hiding this comment

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

I am not aware of "bad" cupy.ndarray subclasses that need to be avoided.


import numpy as np

# TODO: Should we reject ndarray subclasses?
Copy link
Member

Choose a reason for hiding this comment

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

Always a question mark. With "reject", do you mean "convert to ndarray", or "raise", or "ignore", or ....?

Copy link
Member Author

Choose a reason for hiding this comment

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

My thinking here was specifically for get_namespace, although this helper is also used in asarray. Right now it does accept them, because it uses isinstance. I've no idea if an ndarray subclass could implement behavior that would break things here. Presumably if they are properly Liskov substitutable, they shouldn't. My guess is that at worst some functions might return ndarray instead of the appropriate subclass, because we don't properly account for subclases when creating new array objects.

But I haven't tested it. It's possible some people one of the units libraries (I forget which ones subclass ndarray) might care about this at some point, though.

Copy link
Member

Choose a reason for hiding this comment

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

Presumably if they are properly Liskov substitutable, they shouldn't.

np.matrix for one isn't, that's a major issue. IIRC also np.ma.MaskedArray isn't.

@asmeurer
Copy link
Member Author

asmeurer commented Dec 5, 2022

Here's an idea of the overhead of get_xp:

In [1]: import numpy as np

In [2]: import array_api_compat.numpy as npc

In [3]: a = np.asarray(1.)

In [4]: %timeit np.arccos(a)
435 ns ± 8.46 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

In [5]: %timeit npc.acos(a)
737 ns ± 4.31 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

It looks like it's about 300 ns per function call. Does this seem acceptable or should we investigate faster approaches?

@rgommers
Copy link
Member

rgommers commented Dec 5, 2022

Thanks @asmeurer. I think that that is fine for now; in case it becomes a problem because this function is used a lot, I think there is a fairly straightforward way to improve it. Let's first get this used, once a user complains about the overhead I guess we'll have made very nice progress with adoption:)

@asmeurer asmeurer merged commit 6dfc00b into main Dec 5, 2022
@asmeurer asmeurer deleted the cupy branch December 5, 2022 23:02
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.

Support cupy.ndarray?
2 participants