Which is faster in Python: x**.5 or math.sqrt(x)?

I've been wondering this for some time. As the title say, which is faster, the actual function or simply raising to the half power?

UPDATE

This is not a matter of premature optimization. This is simply a question of how the underlying code actually works. What is the theory of how Python code works?

I sent Guido van Rossum an email cause I really wanted to know the differences in these methods.

My email:

There are at least 3 ways to do a square root in Python: math.sqrt, the '**' operator and pow(x,.5). I'm just curious as to the differences in the implementation of each of these. When it comes to efficiency which is better?

His response:

pow and ** are equivalent; math.sqrt doesn't work for complex numbers, and links to the C sqrt() function. As to which one is faster, I have no idea...


As per comments, I've updated the code:

import time
import math

def timeit1():
    s = time.time()
    for i in xrange(750000):
        z=i**.5
    print "Took %f seconds" % (time.time() - s)

def timeit2(arg=math.sqrt):
    s = time.time()
    for i in xrange(750000):
        z=arg(i)
    print "Took %f seconds" % (time.time() - s)

timeit1()
timeit2()

Now the math.sqrt function is directly in a local argument, meaning it has the fastest lookup possible.

UPDATE: The python version seems to matter here. I used to think that timeit1 would be faster, since when python parses "i**.5" it knows, syntactically, which method to call ( __pow__ or some variant), so it doesn't have to go through the overhead of lookup that the math.sqrt variant does. But I might be wrong:

Python 2.5: 0.191000 vs. 0.224000

Python 2.6: 0.195000 vs. 0.139000

Also psyco seems to deal with math.sqrt better:

Python 2.5 + Psyco 2.0: 0.109000 vs. 0.043000

Python 2.6 + Psyco 2.0: 0.128000 vs. 0.067000


| Interpreter    |  x**.5, |   sqrt, | sqrt faster, % |
|                | seconds | seconds |                |
|----------------+---------+---------+----------------|
| Python 3.2rc1+ |    0.32 |    0.27 |             19 |
| Python 3.1.2   |   0.136 |   0.088 |             55 |
| Python 3.0.1   |   0.155 |   0.102 |             52 |
| Python 2.7     |   0.132 |   0.079 |             67 |
| Python 2.6.6   |   0.121 |   0.075 |             61 |
| PyPy 1.4.1     |   0.083 |  0.0159 |            422 |
| Jython 2.5.1   |   0.132 |    0.22 |            -40 |
| Python 2.5.5   |   0.129 |   0.125 |              3 |
| Python 2.4.6   |   0.131 |   0.123 |              7 |
#+TBLFM: $4=100*($2-$3)/$3;%.0f

Table results produced on machine:

$ uname -vms
Linux #42-Ubuntu SMP Thu Dec 2 02:41:37 UTC 2010 x86_64
$ cat /proc/cpuinfo | grep 'model name' | head -1
model name      : Intel(R) Core(TM) i7 CPU         920  @ 2.67GHz

To reproduce results:

  • get source: git clone git://gist.github.com/783011.git gist-783011
  • install tox : pip install tox
  • run tox from the directory with tox.ini file.

  • first rule of optimization: don't do it
  • second rule: don't do it, yet
  • Here's some timings (Python 2.5.2, Windows):

    $ python -mtimeit -s"from math import sqrt; x = 123" "x**.5"
    1000000 loops, best of 3: 0.445 usec per loop
    
    $ python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
    1000000 loops, best of 3: 0.574 usec per loop
    
    $ python -mtimeit -s"import math; x = 123" "math.sqrt(x)"
    1000000 loops, best of 3: 0.727 usec per loop
    

    This test shows that x**.5 is slightly faster than sqrt(x) .

    For the Python 3.0 the result is the opposite:

    $ Python30python -mtimeit -s"from math import sqrt; x = 123" "x**.5"
    1000000 loops, best of 3: 0.803 usec per loop
    
    $ Python30python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
    1000000 loops, best of 3: 0.695 usec per loop
    
    $ Python30python -mtimeit -s"import math; x = 123" "math.sqrt(x)"
    1000000 loops, best of 3: 0.761 usec per loop
    

    math.sqrt(x) is always faster than x**.5 on another machine (Ubuntu, Python 2.6 and 3.1):

    $ python -mtimeit -s"from math import sqrt; x = 123" "x**.5"
    10000000 loops, best of 3: 0.173 usec per loop
    $ python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
    10000000 loops, best of 3: 0.115 usec per loop
    $ python -mtimeit -s"import math; x = 123" "math.sqrt(x)"
    10000000 loops, best of 3: 0.158 usec per loop
    $ python3.1 -mtimeit -s"from math import sqrt; x = 123" "x**.5"
    10000000 loops, best of 3: 0.194 usec per loop
    $ python3.1 -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)"
    10000000 loops, best of 3: 0.123 usec per loop
    $ python3.1 -mtimeit -s"import math; x = 123" "math.sqrt(x)"
    10000000 loops, best of 3: 0.157 usec per loop
    

    How many square roots are you really performing? Are you trying to write some 3D graphics engine in Python? If not, then why go with code which is cryptic over code that is easy to read? The time difference is would be less than anybody could notice in just about any application I could forsee. I really don't mean to put down your question, but it seems that you're going a little too far with premature optimization.

    链接地址: http://www.djcxy.com/p/39624.html

    上一篇: 在Python中优化列表中的列表迭代

    下一篇: Python中更快:x **。5或math.sqrt(x)?