Reputation: 36
I'm trying to optimize this piece of code for speed only (and correctness, of course) in python3:
from math import log
from timeit import Timer
def groffle_slow(mass, density):
total = 0.0
for i in range(10000):
masslog = log(mass * density)
total += masslog/(i+1)
return total
I've been amazed at how much map
speeds things up, so...
def groffle_faster(mass, density):
total = 0.0
masslog = log(mass * density)
return map(sum, (masslog/(i+1) for i in range(10000)))
Looking at the difference in time of execution, there's no comparison. groffle_faster() is waaay faster, but it's returning a map object. The map object should contain the sum as a float.
Anyway I can get the float out of the map object?
Thanks!
Upvotes: 0
Views: 544
Reputation: 353604
It's waaay faster because it's not doing anything; and if it were, it wouldn't work.
>>> mass = 1.2
>>> density = 2.3
>>> masslog = math.log(mass * density)
>>> map(sum, (masslog/(i+1) for i in range(10000)))
<map object at 0x7feccaf1fc18>
This map
object is a lazy object which will yield the results of the function sum
applied to each element of the iterable, which in this case is the generator expression (masslog/(i+1) for i in range(10000))
. No calculations have been done.
But this doesn't make much sense here anyway, because you're trying to apply the sum
function to each element individually, and so:
>>> list(map(sum, (masslog/(i+1) for i in range(10000))))
Traceback (most recent call last):
File "<ipython-input-13-c0f9c805843a>", line 1, in <module>
list(map(sum, (masslog/(i+1) for i in range(10000))))
TypeError: 'float' object is not iterable
What you really want is simply
>>> sum(masslog/(i+1) for i in range(10000))
9.936677928893602
which would give
>>> %timeit groffle_slow(1.5, 2.5)
100 loops, best of 3: 5.08 ms per loop
>>> %timeit groffle_fast(1.5, 2.5)
100 loops, best of 3: 3.02 ms per loop
But since sum(1/(i+1) for i in range(10000))
is a fixed number, I'm not sure why you don't simply use something like
>>> def groffle_O1(mass, density):
... MSUM = 9.787606036044345
... return log(mass*density) * MSUM
...
>>> %timeit groffle_O1(1.5, 2.5)
1000000 loops, best of 3: 424 ns per loop
But you haven't specified what constraints you're really operating under, so it's hard to know what your real problem is.
Upvotes: 3