You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As of NumPy 2.0, __array__ implementations will never receive copy=True when NumPy calls the function. As a followup for adding the copy keyword, we need to first prevent numpy from making a copy before calling __array__ and pass copy=True to __array__ implementations. We also need to update the documentation to emphasize that the library is responsible for making a copy, or if making a copy is impossible, raising an error.
I followed np.array implementation and, if I understood it correctly, we need to prevent numpy from making a copy after__array__ is called rather than before.
def __array__() (with copy argument) is only called deep inside PyArray_DiscoverDTypeAndShape which is meant to discover ndims. I think the result of __array__ is stored in a cache passed to that function (first copy, 1. in the photo), but then this cache is passed in ctors.c::1622:
arr= (PyArrayObject*)(cache->arr_or_sequence);
/* we may need to cast or assert flags (e.g. copy) */PyObject*res=PyArray_FromArray(arr, dtype, flags);
where flags still has "copy always" (second copy?, 2. in the photo).
My question: Would it be sufficient to avoid the second copy by changing "copy always" flag to "copy if needed" in flags, as the cache that was provisioned in Py_Array_Discover... already holds a copy?
When the discovery finds an array immediately, we may or may not already get a copy if we pass it on with copy=True. But that of course only works for __array__ and none of the others, so would need to add the copy logic also for others or indicate that a copy was made.
When the discovery finds a sequence (of arrays), a copy has to be made in any case and it doesn't make sense to keep passing on copy=True to __array__. (also we must fail for copy=False, but I think we do)
Activity
mtsokol commentedon Apr 4, 2024
Hi @ngoldbaum @seberg,
I followed
np.arrayimplementation and, if I understood it correctly, we need to prevent numpy from making a copy after__array__is called rather than before.def __array__()(withcopyargument) is only called deep insidePyArray_DiscoverDTypeAndShapewhich is meant to discover ndims. I think the result of__array__is stored in a cache passed to that function (first copy,1.in the photo), but then this cache is passed inctors.c::1622:where
flagsstill has "copy always" (second copy?,2.in the photo).My question: Would it be sufficient to avoid the second copy by changing "copy always" flag to "copy if needed" in
flags, as the cache that was provisioned inPy_Array_Discover...already holds a copy?seberg commentedon Apr 4, 2024
Well, there are two things to note I guess:
copy=True. But that of course only works for__array__and none of the others, so would need to add the copy logic also for others or indicate that a copy was made.copy=Trueto__array__. (also we must fail forcopy=False, but I think we do)mtsokol commentedon Apr 4, 2024
Then I can try with
copy was madeindicator that is set byPy_Array_Discover..., that would remove that flag for further processing.[-]ENH: pass copy=True to __array__[/-][+]ENH: pass `copy=True` to `__array__`[/+]GH-41098: [Python] Add copy keyword in Array.__array__ for numpy 2.0+…
GH-41098: [Python] Add copy keyword in Array.__array__ for numpy 2.0+…
apacheGH-41098: [Python] Add copy keyword in Array.__array__ for nump…