Cupy is a library for vectorized operations on GPU. It's very similar to NumPy;
cupy.ndarray implements array, but it doesn't work since np.asarray(cupy_array) raises an exception. This was done intentionally by the creators to avoid hidden performance issues.
However to convert a cupy array in a numpy array there is the function cupy.asnumpy(...).
As a result, matplotlib cannot natively plot data in cupy arrays: they must converted to numpy before.
Maybe, given that cupy is fairly spread, should be written a workaround so that matplotlib can optionally make the conversion itself.
If the cupy devs want you to explicitly call cupy.asnumpy, then I don't think matplotlib should be doing this under the hood for you, i.e. you should call cupy.asnumpy yourself. (I make no judgment as to whether cupy's approach of throwing an exception in __array__ is sound, but we certainly shouldn't be pulling the rug under them by undoing their choice.)
I mean something like adding a keyword argument in plot/scatter/etc. (e.g. cupy_convert=True/False with False default) just to make code less redundant, so that matplotlib makes the conversion only if explicitly asked.
How is adding cupy_convert=True to each of your calls less redundant than adding cupy.asnumpy (which you can do just once on each of your arrays before starting to plot them, which will likely be more efficient anyways than Matplotlib converting them again and again)?
Also from the API/interface separation point-of-view I'm 👎 on accepting cupy arrays. We are accepting array-like objects (which includes being able to call np.asarray on them). Arbitrary array containers can conform with that by defining __array__ (https://numpy.org/devdocs/user/basics.dispatch.html). Using duck-typing, we therefore support all such classes without the need to know them, to create a dependency on these libraries or even to have to write additional specialized handling for them.
If cupy does not support this, it's not on us to jump through extra hoops. Concerning usability, I play the ball back to cupy. If they have concerns with unconditionally supporting conversion to numpy via the __array__ interface, they could add a global config or a context manager that controls the behavior. That would allow for code like
with cupy.autoconvert_numpy():
plt.plot(cupy_array)
which is far better than explicit conversion or a cupy_convert flat in Matplotlib.
Additional note: There's also the quite recent https://numpy.org/neps/nep-0018-array-function-protocol.html. That might be something to look into, even though I'm not clear if there's a conversion method "leave as is, if this implements the array-function-protocol; otherwise convert using np.asarray".
they could add a global config or a context manager that controls the behavior.
They could also write a convertor like pandas already does for datetimes and make it a hook that only gets loaded when matplotlib is installed. Then as far as the user is concerned, cupy arrays would automagically plot for at least the plotting methods. A PR to make units work for AxesImage would be welcome but is more annoying because of the colorbars.
I'm going to close because I think the strong consensus is that we are not going to special-case array-like objects that do not have an __array__ representation, but feel free to continue discussion, or re-open if there is something we should do.
Hi all, @tacaswell mentioned this issue to me. CuPy does support __array_function__ from NEP-18, but not (yet) __array__. It was brought up a while ago, so it'd be nice to bring this need to their attention (again): cupy/cupy#589.
Hi everyone :-) Because this wastes keystrokes for many people around the world, my talented colleague AleixBP has fixed it for everyone:
pip install plt-wrapper
and then
import matplotlib.pyplot -> from plt import plt
will solve all your problems.
Here is how I converted gpu array to numpy array -
new_cupy_array = cupy_array.get().astype(float)
Now you can apply any matplotlib function on new_cupy_array
Activity
anntzer commented on May 27, 2020
If the cupy devs want you to explicitly call cupy.asnumpy, then I don't think matplotlib should be doing this under the hood for you, i.e. you should call cupy.asnumpy yourself. (I make no judgment as to whether cupy's approach of throwing an exception in __array__ is sound, but we certainly shouldn't be pulling the rug under them by undoing their choice.)
raeubaen commented on May 27, 2020
I mean something like adding a keyword argument in plot/scatter/etc. (e.g. cupy_convert=True/False with False default) just to make code less redundant, so that matplotlib makes the conversion only if explicitly asked.
anntzer commented on May 27, 2020
How is adding cupy_convert=True to each of your calls less redundant than adding cupy.asnumpy (which you can do just once on each of your arrays before starting to plot them, which will likely be more efficient anyways than Matplotlib converting them again and again)?
timhoffm commented on May 27, 2020
Also from the API/interface separation point-of-view I'm 👎 on accepting cupy arrays. We are accepting array-like objects (which includes being able to call np.asarray on them). Arbitrary array containers can conform with that by defining __array__ (https://numpy.org/devdocs/user/basics.dispatch.html). Using duck-typing, we therefore support all such classes without the need to know them, to create a dependency on these libraries or even to have to write additional specialized handling for them.
If cupy does not support this, it's not on us to jump through extra hoops. Concerning usability, I play the ball back to cupy. If they have concerns with unconditionally supporting conversion to numpy via the __array__ interface, they could add a global config or a context manager that controls the behavior. That would allow for code like
with cupy.autoconvert_numpy(): plt.plot(cupy_array)which is far better than explicit conversion or a cupy_convert flat in Matplotlib.
Additional note: There's also the quite recent https://numpy.org/neps/nep-0018-array-function-protocol.html. That might be something to look into, even though I'm not clear if there's a conversion method "leave as is, if this implements the array-function-protocol; otherwise convert using np.asarray".
story645 commented on May 27, 2020
They could also write a convertor like pandas already does for datetimes and make it a hook that only gets loaded when matplotlib is installed. Then as far as the user is concerned, cupy arrays would automagically plot for at least the plotting methods. A PR to make units work for AxesImage would be welcome but is more annoying because of the colorbars.
jklymak commented on May 28, 2020
I'm going to close because I think the strong consensus is that we are not going to special-case array-like objects that do not have an __array__ representation, but feel free to continue discussion, or re-open if there is something we should do.
tacaswell commented on May 28, 2020
I agree with the consensus here.
leofang commented on May 28, 2020
Hi all, @tacaswell mentioned this issue to me. CuPy does support __array_function__ from NEP-18, but not (yet) __array__. It was brought up a while ago, so it'd be nice to bring this need to their attention (again): cupy/cupy#589.
poldap commented on May 16, 2022
Hi everyone :-) Because this wastes keystrokes for many people around the world, my talented colleague AleixBP has fixed it for everyone:
pip install plt-wrapper
and then
import matplotlib.pyplot -> from plt import plt
will solve all your problems.
lalitbhagat7 commented on Aug 12, 2022
Here is how I converted gpu array to numpy array -
new_cupy_array = cupy_array.get().astype(float)
Now you can apply any matplotlib function on new_cupy_array