3

Profiling this code shows the bulk of the time is spent on the log operation. Is there another way to write this in Python 3 for more efficiency? Replacing the loop with a list comprehension was actually less efficient and so was map because of lambdas.

def log_total(data): 
    total = 0.0   
    log = log(data) 
    for i in range(10000): 
        total += log/(i+1)  
    return total

Thanks!

7
  • 5
    Did you really have to choose the same variable name as the log function? Commented Dec 23, 2012 at 3:41
  • 2
    You could save an addition: for i in range(1,10001): total += log/i Commented Dec 23, 2012 at 4:14
  • @mgilson: Huh, that speeds it up from 1.42 msec per loop to 1.09 msec per loop. That's a pretty big improvement. Commented Dec 23, 2012 at 4:18
  • @mgilson, that is indeed faster! Commented Dec 23, 2012 at 4:21
  • 1
    Is your log function the one from the math module? If so, I doubt you'll be able to improve on its performance directly (since it's a built-in function implemented in C). If log is something you've coded for yourself, then there's might be room for improvement, but you'll have to show its code before we can suggest anything! Commented Dec 23, 2012 at 4:33

2 Answers 2

9

I'd factor the log out of your summation and cache your sum:

harmonic_series = sum(1. / i for i in range(1, 10001))  # Thanks, @mgilson

def log_total(data): 
    return log(data) * harmonic_series

You could also use PyPy to speed it up even more.

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

6 Comments

@user_noname_00: See my edit. There's really no way it could be slower.
Caching like this IS super fast but is like cheating :) There must be a way to optimize the function internally. When I said it was slower the sum was computed inside the function.
But, the solutions are equivalent. Even if you optimized the log it would still be called 10,000 times thus incurring a huge cost each time, especially when you are essentially using a static variable, but computing it each call to the method. The next step would be to use memmoization as stated in the other question to get an even more speed from the function.
@user_noname_00: So you want to optimize it, but it needs to stay slow?
You can do better with numpy as well: '(1./np.arange(1,10001)).sum()' cuts it down by a factor of ~6 for me, (but isn't as lazy)
|
0

Can write with lambda in on line, like this:

total = lambda data: log(data) * sum(1.0 / i for i in xrange(1, 10001))

I used Python 2.7.3.

5 Comments

I changed it . I forgot that a * b1 + a * b2 + a * bn = a * (b1 + b2 + bn).
Haha , i'm forgot write that.
Change your list comprehension to a generator. By adding the brackets, an actual list with 10000 elements is created (try changing 10001 to 1000000001 and see what happens), which takes up a ton of RAM.
Your snippet is doing integer division. Change to 1.0/i or use from __future__ import division, else your sum will equate to 1+0+0+0+....
@Paul McGuire Thanks! I learn from__future__ import division.

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.