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

我一直在想这个。 正如标题所说,哪个更快,实际功能还是简单地提高到一半的功率?

UPDATE

这不是过早优化的问题。 这只是底层代码实际工作的问题。 Python代码的工作原理是什么?

我给Guido van Rossum发了一封电子邮件,因为我真的很想知道这些方法的不同之处。

我的电子邮件:

至少有三种方法可以在Python中做平方根:math.sqrt,'**'运算符和pow(x,.5)。 我只是好奇于每个实现的差异。 谈到效率更好?

他的回应是:

战俘和**是等同的; math.sqrt不适用于复数,并且链接到C sqrt()函数。 至于哪一个更快,我不知道...


根据评论,我更新了代码:

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()

现在, math.sqrt函数直接在本地参数中,这意味着它有最快的查找可能性。

更新: python版本似乎在这里。 我曾经认为timeit1会更快,因为当python解析“i **。5”时,它会在语法上知道调用哪种方法( __pow__或某种变体),因此它不必经历查找的开销math.sqrt变体确实。 但我可能是错的:

Python 2.5: 0.191000 vs. 0.224000

Python 2.6: 0.195000与0.139000

另外psyco似乎更好地处理math.sqrt

Python 2.5 + Psyco 2.0: 0.109000与0.043000

Python 2.6 + Psyco 2.0: 0.128000与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

在机器上产生的表格结果:

$ 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

重现结果:

  • 获取源代码: git clone git://gist.github.com/783011.git gist-783011
  • 安装toxpip install tox
  • 使用tox.ini文件从目录运行tox

  • 优化的第一条规则:不要这样做
  • 第二条规则:不要这样做
  • 这里有一些时间(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
    

    该测试表明x**.5sqrt(x)稍快。

    对于Python 3.0,结果是相反的:

    $ 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)总是比另一台机器上的x**.5快(Ubuntu,Python 2.6和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
    

    你真的有多少根方根? 你想用Python编写一些3D图形引擎吗? 如果不是,那么为什么要使用易于阅读的代码来隐藏代码? 在任何我可以预见的应用程序中,时间差都比任何人都可以注意到的要小。 我真的不打算放下你的问题,但似乎你过早的优化会有点过分。

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

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

    下一篇: No indexes on small tables?