0

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!

0

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, I guess if my function isn't doing anything, no wonder it's going so fast! Thanks for answering me with such excellent examples!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.