sum for sequences?
Steve Howell
showell30 at yahoo.com
Sun Mar 28 11:55:05 EDT 2010
On Mar 28, 8:17 am, Duncan Booth <duncan.bo... at invalid.invalid> wrote:
> Steve Howell <showel... at yahoo.com> wrote:
> > The mildly surprising part of sum() is that is does add vs. add-in-
> > place, which leads to O(N) vs. O(1) for the inner loop calls, for
> > certain data structures, notably lists, even though none of the
> > intermediate results get used by the caller. For lists, you could
> > make a more efficient variant of sum() that clones the start value and
> > does add-in-place.
>
> Doing add-in-place isn't the only way to make sum more efficient: if you
> assume that addition is associative (which of course the builtin sum can't)
> then you can form partial sums. e.g. instead of calculating:
>
> (((((((a + b) + c) + d) + e) + f) + g) + h)
>
> you calculate:
>
> (((a + b) + (c + d)) + ((e + f) + (g + h)))
>
> Obviously this requires more space than the naive sum, but not as much as
> you might at first expect: you only need to hold log(n) intermediates
> values at any time.
>
Yep, I did mention in my post that the outer loop does not *have* to
be O(N), if you can parallelize it. Apart from reducing
intermediates, the divide-and-conquer method does not reduce overall
computation time unless you have multiple processors, correct?
> > I could guess pretty confidently that the reason this optimization was
> > never tried is that sum() has always been intended to be used on
> > numerics, since other alternatives exist for strings (join), lists
> > (chain), and hand-coded data classes that support add-in-place (roll-
> > your-own loop).
>
> Doing it this way helps summing lists or strings (though not as much as
> str.join), but it also helps if you need to sum a long list of similarly
> sized floats as you'll get a more accurate answer.
>
Interesting! That makes sense. The docs for math.fsum() suggest that
partial sums are used to maintain precision.
http://docs.python.org/library/math.html#math.fsum
> Seehttp://groups.google.com/group/comp.lang.python/browse_thread/thread/...
> faf92f532e/027cef7d4429aa3a
> for an earlier discussion of this, or just Google comp.lang.python for
> 'pairwise sum'.
>
> Here's the code I posted in that thread:
>
> def sumpairs(seq):
> tmp = []
> for i,v in enumerate(seq):
> if i&1:
> tmp[-1] = tmp[-1] + v
> i = i + 1
> n = i & -i
> while n > 2:
> t = tmp.pop(-1)
> tmp[-1] = tmp[-1] + t
> n >>= 1
> else:
> tmp.append(v)
> while len(tmp) > 1:
> t = tmp.pop(-1)
> tmp[-1] = tmp[-1] + t
> return tmp[0]
>
> and I claimed that my Python coded sumpairs function was faster than the
> builtin sum on a list of lists once you had more than about 210 items.
> I never did get round to rewriting it in C for a more realistic speed
> comparison: summing integers my Python version is about 60 times slower
> than the builtin.
More information about the Python-list
mailing list