<br><br><div class="gmail_quote">On Thu, Feb 10, 2011 at 2:26 PM, Mark Wiebe <span dir="ltr"><<a href="mailto:mwwiebe@gmail.com">mwwiebe@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div class="gmail_quote"><div class="im">On Thu, Feb 10, 2011 at 10:31 AM, Pauli Virtanen <span dir="ltr"><<a href="mailto:pav@iki.fi" target="_blank">pav@iki.fi</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

Thu, 10 Feb 2011 12:16:12 -0600, Robert Kern wrote:<br>
[clip]<br>
<div>> One thing that might be worthwhile is to make<br>
> implementations of sum() and cumsum() that avoid the ufunc machinery and<br>
> do their iterations more quickly, at least for some common combinations<br>
> of dtype and contiguity.<br>
<br>
</div>I wonder what is the balance between the iterator overhead and the time<br>
taken in the reduction inner loop. This should be straightforward to<br>
benchmark.<br>
<br>
Apparently, some overhead decreased with the new iterators, since current<br>
Numpy master outperforms 1.5.1 by a factor of 2 for this benchmark:<br>
<br>
In [8]: %timeit M.sum(1)     # Numpy 1.5.1<br>
10 loops, best of 3: 85 ms per loop<br>
<br>
In [8]: %timeit M.sum(1)     # Numpy master<br>
10 loops, best of 3: 49.5 ms per loop<br>
<br>
I don't think this is explainable by the new memory layout optimizations,<br>
since M is C-contiguous.<br>
<br>
Perhaps there would be room for more optimization, even within the ufunc<br>
framework?<br></blockquote><div><br></div></div><div>I played around with this in einsum, where it's a bit easier to specialize this case than in the ufunc machinery. What I found made the biggest difference is to use SSE prefetching instructions to prepare the cache in advance. Here are the kind of numbers I get, all from the current Numpy master:</div>

<div><br></div><div><div><div>In [7]: timeit M.sum(1)</div><div>10 loops, best of 3: 44.6 ms per loop</div><div><br></div><div>In [8]: timeit dot(M, o)</div><div>10 loops, best of 3: 36.8 ms per loop</div><div><br></div>
<div>
In [9]: timeit einsum('ij->i', M)</div><div>10 loops, best of 3: 32.1 ms per loop</div></div></div><div>...</div></div></blockquote><div><br>I get an even bigger speedup:<br><br>In [5]: timeit M.sum(1)<br>10 loops, best of 3: 19.2 ms per loop<br>
<br>In [6]: timeit dot(M, o)<br>100 loops, best of 3: 15.2 ms per loop<br><br>In [7]: timeit einsum('ij->i', M)<br>100 loops, best of 3: 11.4 ms per loop<br><br><snip><br><br>Chuck<br></div></div>