<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Apr 28, 2020 at 5:03 PM 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 Tue, 2020-04-28 at 11:51 +0200, Ralf Gommers wrote:<br>
<snip><br>
> > So arguably, there is no type-safety concern due to `.detach()`.<br>
> <br>
> I'm not sure what the question is here; no one mentioned type-safety. <br>
> The<br>
> PyTorch maintainers have already said they're fine with adding a<br>
> force<br>
> keyword.<br>
<br>
But type-safety is the reason to distinguish between:<br>
<br>
* np.asarrau(tensor)<br>
* np.asarray(tensor, force=True)<br></blockquote><div><br></div><div>No it's not, the rationale given by library authors is expensive conversion / memory copies / side effects. `np.asarray(x)` is used all over the place, and can/will continue to be used by library authors. `force=True` is for cases where things like expensive conversion don't matter, like visualization - if you need a picture of an array then it helps, while the downside of writing inefficient/unreliable numerical code isn't present.<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>
Similar to:<br>
<br>
* operator.index(obj)<br>
* int(obj)   # convert less type-safe (strings, floats)!<br>
<br>
I actually mentioned 3 reasons in my email:<br>
<br>
1. Teach and Inform users (about the next two mainly)<br>
2. Type-safety<br>
3. Expensive conversion <br>
<br>
And only type-safety is related to `.detach()` mentioning that there<br>
may not be clear story about the usage in that case.<br>
<br>
(continued below)<br>
<br>
> <br>
<snip><br>
> > <br>
> > <br>
> > I am very much in favor of adding such things, but I still lack a<br>
> > bit<br>
> > of clarity as to whom we would be helping?<br>
> > <br>
> <br>
> See Juan's first email. I personally am ambivalent on this proposal,<br>
> but if<br>
> Juan and the Napari devs really want it, that's good enough for me.<br>
<br>
Of course I read it, twice, but it is only good enough for me if we<br>
actually *solve the issue*, and for that I want to know which issue we<br>
are solving :), it seems obvious, but I am not so sure...<br>
<br>
That brings us to the other two reasons:<br>
<br>
Teaching and Informing users:<br>
<br>
If Napari uses `force=True` indiscriminately, it is not very clear to<br>
the user about whether or not the operation is expensive.  I.e. the<br>
user can learn it is when using `np.asarray(sparse_arr)` with other<br>
libraries. But they are not notified that `napari.vis_func(sparse_arr)`<br>
might kill their computer.<br>
<br>
So the "Teaching" part can still partially work, but it does not inform<br>
the user well anymore on whether or not a function will blow-up memory.<br>
<br>
Expensive Conversion:<br>
<br>
If the main reason is expensive conversions, however, than, as a<br>
library I would probably just use it for half my API, since copying<br>
from GPU to CPU will still be much faster than my own function.<br>
<br>
<br>
Generally:<br>
<br>
I want to help Napari, but it seems like there may be more to this, and<br>
it may be good to finish these thoughts before making a call.<br>
<br>
E.g. Napari wants to use it, but do the array-providers want Napari to<br>
use it?<br>
<br>
For sparse Hameer just mentioned that he still would want big warnings<br>
both during the operation and in the `np.asarray` documentation.<br>
If we put such big warnings there, we should have an idea of who we<br>
want to ignore that warning? (Napari yes, sklearn sometimes, ...?)<br></blockquote><div><br></div><div>There clearly should not be warnings. And sklearn is irrelevant, it cannot use `force=True`.</div><div><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>
   -> Is "whatever the library feels right" good enough?<br>
<br>
And if the conversion still gives warnings for some array-objects, have<br>
we actually gained much?<br>
<br>
  -> Maybe we do, end-users may be happy to ignore those warnings...<br>
<br>
<br>
The one clear use-case for `force=True` is the end-user. Just like no<br>
library uses `int(obj)`, but end-users can use it very nicely.<br>
I am happy to help the end-user in this case, but if that is the target<br>
audience we may want to _discourage_ Napari from using `force=True` and<br>
encourage sparse not to put any RuntimeWarnings on it!<br>
<br>
- Sebastian<br>
<br>
<br>
> Cheers,<br>
> Ralf<br>
> <br>
> <br>
> <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<br>
> > 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<br>
> > `__array__`<br>
> > and `np.asarray`. It guarantees high speed and in-place behaviour<br>
> > which<br>
> > is useful for different settings.<br>
> > <br>
> > - Sebastian<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<br>
> > > > > 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<br>
> > > > > > necessary,<br>
> > > > > > but<br>
> > > > > > > otherwise don’t bother”, but there are workarounds to<br>
> > > > > > > this.<br>
> > > > > > > <br>
> > > > > > <br>
> > > > > > After a side discussion with Stéfan van der Walt, we came<br>
> > > > > > 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.<br>
> > > > > > If<br>
> > > > > > enough<br>
> > > > > > projects want to use it, then I have no objections to<br>
> > > > > > 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<br>
> > > > > > 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<br>
> > > > > > happy to<br>
> > > > > > hear<br>
> > > > > > some!<br>
> > > > > > <br>
> > > > > > My view regarding API/experiment creep is that `__array__`<br>
> > > > > > is<br>
> > > > > > the oldest<br>
> > > > > > and most basic of all the interop tricks and that this can<br>
> > > > > > 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<br>
> > > > > > would<br>
> > > > > > be happy<br>
> > > > > > to contribute to the dispatch basics guide together with<br>
> > > > > > 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.<br>
> > > > > > But,<br>
> > > > > > to<br>
> > > > > > reiterate my point: `__array__` is the simplest of these<br>
> > > > > > and I<br>
> > > > > > think this<br>
> > > > > > keyword is pretty safe to add.<br>
> > > > > > <br>
> > > > > > For ease of discussion, here are the API options discussed<br>
> > > > > > so<br>
> > > > > > far, as<br>
> > > > > > well as a few extra that I don’t like but might trigger<br>
> > > > > > other<br>
> > > > > > ideas:<br>
> > > > > > <br>
> > > > > > np.asarray(my_duck_array, allow_copy=True)  # default is<br>
> > > > > > False,<br>
> > > > > > or None<br>
> > > > > > -> leave it to the duck array to decide<br>
> > > > > > np.asarray(my_duck_array, copy=True)  # always copies, but,<br>
> > > > > > if<br>
> > > > > > supported<br>
> > > > > > by the duck array, defers to it for the copy<br>
> > > > > > np.asarray(my_duck_array, copy=‘allow’)  # could take<br>
> > > > > > values<br>
> > > > > > ‘allow’,<br>
> > > > > > ‘force’, ’no’, True(=‘force’), False(=’no’)<br>
> > > > > > np.asarray(my_duck_array, force_copy=False,<br>
> > > > > > allow_copy=True)  #<br>
> > > > > > separate<br>
> > > > > > concepts, but unclear what force_copy=True,<br>
> > > > > > 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>
> > 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>