<div dir="ltr">My possibly poorly thought out API would be something like np.add_sq_diff.set_c(42.0).reduce(x), basically add a setter method which returned self.  Thanks for explaining what data was intended to do.  All of this is really just a dance around the requirement that reduce only works on binary functions.  Would there be any interest in extending reduce to allow for arbitrary numbers of input and output arguments?<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Nov 11, 2016 at 1:38 PM, Julian Taylor <span dir="ltr"><<a href="mailto:jtaylor.debian@googlemail.com" target="_blank">jtaylor.debian@googlemail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">here is an old unfinished PR adding max_abs which has a similar purpose<br>
as yours:<br>
<a href="https://github.com/numpy/numpy/pull/5509" rel="noreferrer" target="_blank">https://github.com/numpy/<wbr>numpy/pull/5509</a><br>
<br>
So far I know data is set during runtime construction and is part of the<br>
ufunc object, so it is not really very suitable to pass in constants on<br>
call.<br>
Its intended purpose is pass in functions to be called in generic loops<br>
like PyUFunc_d_d.<br>
<br>
Having an option to mark arguments of a ufunc as special in reductions<br>
could be useful, e.g. it would allow a potential<br>
(fused-)multiply-and-add ufunc to be used to implement a weighted sum.<br>
<span class=""><br>
On 11.11.2016 17:25, Matthew Harrigan wrote:<br>
> I started a ufunc to compute the sum of square differences here<br>
</span>> <<a href="https://gist.github.com/mattharrigan/6f678b3d6df5efd236fc23bfb59fd3bd" rel="noreferrer" target="_blank">https://gist.github.com/<wbr>mattharrigan/<wbr>6f678b3d6df5efd236fc23bfb59fd3<wbr>bd</a>>.  It<br>
<span class="">> is about 4x faster and uses half the memory compared to<br>
> np.sum(np.square(x-c)).  This could significantly speed up common<br>
> operations like std and var (where c=np.mean(x).  It faster because its<br>
> a single pass instead of 3, and also because the inner loop is<br>
> specialized for the common reduce case, which might be an optimization<br>
> considering more generally.<br>
><br>
> I think I have answered my question #2&3 above.<br>
><br>
> Can someone please point me to an example where "data" was used in a<br>
> ufunc inner loop?  How can that value be set at runtime?  Thanks<br>
><br>
> On Fri, Nov 4, 2016 at 5:33 PM, Sebastian Berg<br>
</span><span class="">> <<a href="mailto:sebastian@sipsolutions.net">sebastian@sipsolutions.net</a> <mailto:<a href="mailto:sebastian@sipsolutions.net">sebastian@<wbr>sipsolutions.net</a>>> wrote:<br>
><br>
>     On Fr, 2016-11-04 at 15:42 -0400, Matthew Harrigan wrote:<br>
>     > I didn't notice identity before.  Seems like frompyfunc always sets<br>
>     > it to None.  If it were zero maybe it would work as desired here.<br>
>     ><br>
>     > In the writing your own ufunc doc, I was wondering if the pointer to<br>
>     > data could be used to get a constant at runtime.  If not, what could<br>
>     > that be used for?<br>
>     > static void double_logit(char **args, npy_intp *dimensions,<br>
>     >                             npy_intp* steps, void* data)<br>
>     > Why would the numerical accuracy be any different?  The subtraction<br>
>     > and square operations look identical and I thought np.sum just calls<br>
>     > np.add.reduce, so the reduction step uses the same code and would<br>
>     > therefore have the same accuracy.<br>
>     ><br>
><br>
>     Sorry, did not read it carefully, I guess `c` is the mean, so you are<br>
>     doing the two pass method.<br>
><br>
>     - Sebastian<br>
><br>
><br>
>     > Thanks<br>
>     ><br>
>     > On Fri, Nov 4, 2016 at 1:56 PM, Sebastian Berg <sebastian@sipsolution<br>
</span><div><div class="h5">>     > <a href="http://s.net" rel="noreferrer" target="_blank">s.net</a> <<a href="http://s.net" rel="noreferrer" target="_blank">http://s.net</a>>> wrote:<br>
>     > > On Fr, 2016-11-04 at 13:11 -0400, Matthew Harrigan wrote:<br>
>     > > > I was reading this and got thinking about if a ufunc could<br>
>     > > compute<br>
>     > > > the sum of squared differences in a single pass without a<br>
>     > > temporary<br>
>     > > > array.  The python code below demonstrates a possible approach.<br>
>     > > ><br>
>     > > > import numpy as np<br>
>     > > > x = np.arange(10)<br>
>     > > > c = 1.0<br>
>     > > > def add_square_diff(x1, x2):<br>
>     > > >     return x1 + (x2-c)**2<br>
>     > > > ufunc = np.frompyfunc(add_square_diff, 2, 1)<br>
>     > > > print(ufunc.reduce(x) - x[0] + (x[0]-c)**2)<br>
>     > > > print(np.sum(np.square(x-c)))<br>
>     > > ><br>
>     > > > I have (at least) 4 questions:<br>
>     > > > 1. Is it possible to pass run time constants to a ufunc written<br>
>     > > in C<br>
>     > > > for use in its inner loop, and if so how?<br>
>     > ><br>
>     > > I don't think its anticipated, since a ufunc could in most cases<br>
>     > > use a<br>
>     > > third argument, but a 3 arg ufunc can't be reduced. Not sure if<br>
>     > > there<br>
>     > > might be some trickery possible.<br>
>     > ><br>
>     > > > 2. Is it possible to pass an initial value to reduce to avoid the<br>
>     > > > clean up required for the first element?<br>
>     > ><br>
>     > > This is the identity normally. But the identity can only be 0, 1 or<br>
>     > > -1<br>
>     > > right now I think. The identity is what the output array gets<br>
>     > > initialized with (which effectively makes it the first value passed<br>
>     > > into the inner loop).<br>
>     > ><br>
>     > > > 3. Does that ufunc work, or are there special cases which cause<br>
>     > > it to<br>
>     > > > fall apart?<br>
>     > > > 4. Would a very specialized ufunc such as this be considered for<br>
>     > > > incorporating in numpy since it would help reduce time and memory<br>
>     > > of<br>
>     > > > functions already in numpy?<br>
>     > > ><br>
>     > ><br>
>     > > Might be mixing up things, however, IIRC the single pass approach<br>
>     > > has a<br>
>     > > bad numerical accuracy, so that I doubt that it is a good default<br>
>     > > algorithm.<br>
>     > ><br>
>     > > - Sebastian<br>
>     > ><br>
>     > ><br>
>     > > > Thank you,<br>
>     > > > Matt<br>
>     > > > ______________________________<wbr>_________________<br>
>     > > > NumPy-Discussion mailing list<br>
</div></div>>     > > > <a href="mailto:NumPy-Discussion@scipy.org">NumPy-Discussion@scipy.org</a> <mailto:<a href="mailto:NumPy-Discussion@scipy.org">NumPy-Discussion@<wbr>scipy.org</a>><br>
>     > > > <a href="https://mail.scipy.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/numpy-<wbr>discussion</a><br>
<span class="">>     <<a href="https://mail.scipy.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/numpy-<wbr>discussion</a>><br>
>     > > ______________________________<wbr>_________________<br>
>     > > NumPy-Discussion mailing list<br>
</span>>     > > <a href="mailto:NumPy-Discussion@scipy.org">NumPy-Discussion@scipy.org</a> <mailto:<a href="mailto:NumPy-Discussion@scipy.org">NumPy-Discussion@<wbr>scipy.org</a>><br>
>     > > <a href="https://mail.scipy.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/numpy-<wbr>discussion</a><br>
<span class="">>     <<a href="https://mail.scipy.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/numpy-<wbr>discussion</a>><br>
>     > ><br>
>     > ______________________________<wbr>_________________<br>
>     > NumPy-Discussion mailing list<br>
</span>>     > <a href="mailto:NumPy-Discussion@scipy.org">NumPy-Discussion@scipy.org</a> <mailto:<a href="mailto:NumPy-Discussion@scipy.org">NumPy-Discussion@<wbr>scipy.org</a>><br>
>     > <a href="https://mail.scipy.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/numpy-<wbr>discussion</a><br>
<span class="">>     <<a href="https://mail.scipy.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/numpy-<wbr>discussion</a>><br>
><br>
>     ______________________________<wbr>_________________<br>
>     NumPy-Discussion mailing list<br>
</span>>     <a href="mailto:NumPy-Discussion@scipy.org">NumPy-Discussion@scipy.org</a> <mailto:<a href="mailto:NumPy-Discussion@scipy.org">NumPy-Discussion@<wbr>scipy.org</a>><br>
>     <a href="https://mail.scipy.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/numpy-<wbr>discussion</a><br>
<div class="HOEnZb"><div class="h5">>     <<a href="https://mail.scipy.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/numpy-<wbr>discussion</a>><br>
><br>
><br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> NumPy-Discussion mailing list<br>
> <a href="mailto:NumPy-Discussion@scipy.org">NumPy-Discussion@scipy.org</a><br>
> <a href="https://mail.scipy.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/numpy-<wbr>discussion</a><br>
><br>
<br>
______________________________<wbr>_________________<br>
NumPy-Discussion mailing list<br>
<a href="mailto:NumPy-Discussion@scipy.org">NumPy-Discussion@scipy.org</a><br>
<a href="https://mail.scipy.org/mailman/listinfo/numpy-discussion" rel="noreferrer" target="_blank">https://mail.scipy.org/<wbr>mailman/listinfo/numpy-<wbr>discussion</a><br>
</div></div></blockquote></div><br></div>