<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Apr 27, 2020 at 12:10 AM Sebastian Berg <<a href="mailto:sebastian@sipsolutions.net">sebastian@sipsolutions.net</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Sat, 2020-04-25 at 10:52 -0700, Stephan Hoyer wrote:<br>
> On Sat, Apr 25, 2020 at 10:40 AM Ralf Gommers <<a href="mailto:ralf.gommers@gmail.com" target="_blank">ralf.gommers@gmail.com</a><br>
> ><br>
> wrote:<br>
> <br>
> > <br>
> > On Fri, Apr 24, 2020 at 12:35 PM Eric Wieser <<br>
> > <a href="mailto:wieser.eric%2Bnumpy@gmail.com" target="_blank">wieser.eric+numpy@gmail.com</a>><br>
> > wrote:<br>
> > <br>
> > > Perhaps worth mentioning that we've discussed this sort of API<br>
> > > before, in<br>
> > > <a href="https://github.com/numpy/numpy/pull/11897" rel="noreferrer" target="_blank">https://github.com/numpy/numpy/pull/11897</a>.<br>
> > > <br>
> > > Under that proposal, the api would be something like:<br>
> > > <br>
> > > * `copy=True` - always copy, like it is today<br>
> > > * `copy=False` - copy if needed, like it is today<br>
> > > * `copy=np.never_copy` - never copy, throw an exception if not<br>
> > > possible<br>
> > > <br>
> > <br>
> > There's a couple of issues I see with using `copy` for __array__:<br>
> > - copy is already weird (False doesn't mean no), and a [bool,<br>
> > some_obj_or_str] keyword isn't making that better<br>
> > - the behavior we're talking about can do more than copying, e.g.<br>
> > for<br>
> > PyTorch it would modify the autograd graph by adding detach(), and<br>
> > for<br>
> > sparse it's not just "make a copy" (which implies doubling memory<br>
> > use) but<br>
> > it densifies which can massively blow up the memory.<br>
> > - I'm -1 on adding things to the main namespace (never_copy) for<br>
> > something<br>
> > that can be handled differently (like a string, or a new keyword)<br>
> > <br>
> > tl;dr a new `force` keyword would be better<br>
> > <br>
> <br>
> I agree, “copy” is not a good description of this desired coercion<br>
> behavior.<br>
> <br>
> A new keyword argument like “force” would be much clearer.<br>
> <br>
<br>
That seems fine and practical. But, in the end it seems to me that the<br>
`force=` keyword, just means that some projects want to teach their<br>
users that:<br>
<br>
1. `np.asarray()` can be expensive (and may always copy)<br>
2. `np.asarray()` always loses type properties<br>
<br>
while others do not choose to teach about it.  There seems very little<br>
or even no "promise" attached to either `force=True` or `force=False`.<br>
<br>
<br>
In the end, the question is whether sparse will actually want to<br>
implement `force=True` if the main reason we add is for library use.<br></blockquote><div><br></div><div>That's for PyData Sparse and scipy.sparse devs to answer. Maybe Hameer can answer for the former here. For SciPy that should be decided on the scipy-dev list, but my opinion would be: yes to adding __array__ that raises TypeError by default, and converts with `force=True`.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
There is no difference between a visualization library or numpy. In<br>
both cases the users memory will blow up just the same.<br>
<br>
As for PyTorch, is `.detach()` even a good reason?  Maybe I am missing<br>
things, but:<br>
<br>
>>> torch.ones(10, requires_grad=True) + np.arange(10)<br>
# RuntimeError: Can't call numpy() on Variable that requires grad. Use<br>
var.detach().numpy() instead.<br>
<br>
So arguably, there is no type-safety concern due to `.detach()`. </blockquote><div><br></div><div>I'm not sure what the question is here; no one mentioned type-safety. The PyTorch maintainers have already said they're fine with adding a force keyword.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">There<br>
is an (obvious) general loss of type information that always occurs<br>
with an `np.asarray` call.<br>
But I do not see that creating any openings for bugs here, due to the<br>
wisdom of not allowing the above operation.<br>
In fact, it actually seems much worse for for xarray, or pandas. They<br>
do support the above operation and will potentially mess up if the<br>
arange was previously an xarray with a matching index, but different<br>
order.<br>
<br>
<br>
I am very much in favor of adding such things, but I still lack a bit<br>
of clarity as to whom we would be helping?<br></blockquote><div><br></div><div>See Juan's first email. I personally am ambivalent on this proposal, but if Juan and the Napari devs really want it, that's good enough for me.</div><div><br></div><div>Cheers,<br></div><div>Ralf</div><div><br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
If end-users will actually use `np.asarray(..., force=True)` over<br>
special methods, then great! But I am currently not sure the type-<br>
safety argument is all that big of a point.  And the performance or<br>
memory-blowup argument remains true even for visualization libraries<br>
(where the array is purely input and never output as such).<br>
<br>
<br>
But yes, "never copy" is a somewhat different extension to `__array__`<br>
and `np.asarray`. It guarantees high speed and in-place behaviour which<br>
is useful for different settings.<br>
<br>
- Sebastian<br>
<br>
<br>
> <br>
> > Cheers,<br>
> > Ralf<br>
> > <br>
> > <br>
> > > I think the discussion stalled on the precise spelling of the<br>
> > > third<br>
> > > option.<br>
> > > <br>
> > > `__array__` was not discussed there, but it seems like adding the<br>
> > > `copy`<br>
> > > argument to `__array__` would be a perfectly reasonable<br>
> > > extension.<br>
> > > <br>
> > > Eric<br>
> > > <br>
> > > On Fri, 24 Apr 2020 at 03:00, Juan Nunez-Iglesias <<br>
> > > <a href="mailto:jni@fastmail.com" target="_blank">jni@fastmail.com</a>><br>
> > > wrote:<br>
> > > <br>
> > > > Hi everyone,<br>
> > > > <br>
> > > > One bit of expressivity we would miss is “copy if necessary,<br>
> > > > but<br>
> > > > > otherwise don’t bother”, but there are workarounds to this.<br>
> > > > > <br>
> > > > <br>
> > > > After a side discussion with Stéfan van der Walt, we came up<br>
> > > > with<br>
> > > > `allow_copy=True`, which would express to the downstream<br>
> > > > library that we<br>
> > > > don’t mind waiting, but that zero-copy would also be ok.<br>
> > > > <br>
> > > > This sounds like the sort of thing that is use case driven. If<br>
> > > > enough<br>
> > > > projects want to use it, then I have no objections to adding<br>
> > > > the keyword.<br>
> > > > OTOH, we need to be careful about adding too many<br>
> > > > interoperability tricks<br>
> > > > as they complicate the code and makes it hard for folks to<br>
> > > > determine the<br>
> > > > best solution. Interoperability is a hot topic and we need to<br>
> > > > be careful<br>
> > > > not put too leave behind too many experiments in the NumPy<br>
> > > > code.  Do you<br>
> > > > have any other ideas of how to achieve the same effect?<br>
> > > > <br>
> > > > <br>
> > > > Personally, I don’t have any other ideas, but would be happy to<br>
> > > > hear<br>
> > > > some!<br>
> > > > <br>
> > > > My view regarding API/experiment creep is that `__array__` is<br>
> > > > the oldest<br>
> > > > and most basic of all the interop tricks and that this can be<br>
> > > > safely<br>
> > > > maintained for future generations. Currently it only takes<br>
> > > > `dtype=` as a<br>
> > > > keyword argument, so it is a very lean API. I think this<br>
> > > > particular use<br>
> > > > case is very natural and I’ve encountered the reluctance to<br>
> > > > implicitly copy<br>
> > > > twice, so I expect it is reasonably common.<br>
> > > > <br>
> > > > Regarding difficulty in determining the best solution, I would<br>
> > > > be happy<br>
> > > > to contribute to the dispatch basics guide together with the<br>
> > > > new kwarg. I<br>
> > > > agree that the protocols are getting quite numerous and I<br>
> > > > couldn’t find a<br>
> > > > single place that gathers all the best practices together. But,<br>
> > > > to<br>
> > > > reiterate my point: `__array__` is the simplest of these and I<br>
> > > > think this<br>
> > > > keyword is pretty safe to add.<br>
> > > > <br>
> > > > For ease of discussion, here are the API options discussed so<br>
> > > > far, as<br>
> > > > well as a few extra that I don’t like but might trigger other<br>
> > > > ideas:<br>
> > > > <br>
> > > > np.asarray(my_duck_array, allow_copy=True)  # default is False,<br>
> > > > or None<br>
> > > > -> leave it to the duck array to decide<br>
> > > > np.asarray(my_duck_array, copy=True)  # always copies, but, if<br>
> > > > supported<br>
> > > > by the duck array, defers to it for the copy<br>
> > > > np.asarray(my_duck_array, copy=‘allow’)  # could take values<br>
> > > > ‘allow’,<br>
> > > > ‘force’, ’no’, True(=‘force’), False(=’no’)<br>
> > > > np.asarray(my_duck_array, force_copy=False, allow_copy=True)  #<br>
> > > > separate<br>
> > > > concepts, but unclear what force_copy=True, allow_copy=False<br>
> > > > means!<br>
> > > > np.asarray(my_duck_array, force=True)<br>
> > > > <br>
> > > > Juan.<br>
> > > > _______________________________________________<br>
> > > > NumPy-Discussion mailing list<br>
> > > > <a href="mailto:NumPy-Discussion@python.org" target="_blank">NumPy-Discussion@python.org</a><br>
> > > > <a href="https://mail.python.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/numpy-discussion</a><br>
> > > > <br>
> > > _______________________________________________<br>
> > > NumPy-Discussion mailing list<br>
> > > <a href="mailto:NumPy-Discussion@python.org" target="_blank">NumPy-Discussion@python.org</a><br>
> > > <a href="https://mail.python.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/numpy-discussion</a><br>
> > > <br>
> > _______________________________________________<br>
> > NumPy-Discussion mailing list<br>
> > <a href="mailto:NumPy-Discussion@python.org" target="_blank">NumPy-Discussion@python.org</a><br>
> > <a href="https://mail.python.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/numpy-discussion</a><br>
> > <br>
> <br>
> _______________________________________________<br>
> NumPy-Discussion mailing list<br>
> <a href="mailto:NumPy-Discussion@python.org" target="_blank">NumPy-Discussion@python.org</a><br>
> <a href="https://mail.python.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/numpy-discussion</a><br>
<br>
<br>
_______________________________________________<br>
NumPy-Discussion mailing list<br>
<a href="mailto:NumPy-Discussion@python.org" target="_blank">NumPy-Discussion@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/numpy-discussion</a><br>
</blockquote></div></div>