我一直在想这个问题.正如标题所说,哪个更快,实际功能还是简单地提升到半功率?
UPDATE
这不是过早优化的问题.这只是底层代码实际工作原理的问题.Python代码的工作原理是什么?
我发送了Guido van Rossum电子邮件,因为我真的很想知道这些方法的不同之处.
在Python中至少有3种方法可以做平方根:math.sqrt,'**'运算符和pow(x,.5).我只是好奇每个实现的差异.谈到效率哪个更好?
pow和**是等价的; math.sqrt不适用于复数,也不适用于C sqrt()函数的链接.至于哪一个更快,我不知道......
Claudiu.. 82
根据评论,我已经更新了代码:
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 vs. 0.139000
psyco似乎也math.sqrt
更好:
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
在机器上生成的表结果:
$ 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
安装tox
:pip install tox
tox
从带有tox.ini
文件的目录运行.
标准的timeit模块是你的朋友.它避免了测量执行时间时常见的陷阱! (8认同)
键盘是一项很棒的服务,但对于时序性能来说很糟糕,我的意思是谁知道服务器在特定时刻会有多忙.每次运行都可能产生非常不同的结果 (2认同)
jfs.. 18
第一条优化规则:不要这样做
第二条规则:不这样做,但
这是一些时间(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**.5
比它快一点sqrt(x)
.
对于Python 3.0,结果恰恰相反:
$ \Python30\python -mtimeit -s"from math import sqrt; x = 123" "x**.5" 1000000 loops, best of 3: 0.803 usec per loop $ \Python30\python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)" 1000000 loops, best of 3: 0.695 usec per loop $ \Python30\python -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
Kibbee.. 10
你真正表现了多少平方根?您是否正在尝试用Python编写一些3D图形引擎?如果没有,那么为什么要使用易于阅读的代码隐藏的代码呢?时间差异将小于任何人可能会注意到的任何我可以预见的应用程序.我真的不是故意放下你的问题,但似乎你因为过早优化而走得太远了.
根据评论,我已经更新了代码:
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 vs. 0.139000
psyco似乎也math.sqrt
更好:
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
在机器上生成的表结果:
$ 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
安装tox
:pip install tox
tox
从带有tox.ini
文件的目录运行.
第一条优化规则:不要这样做
第二条规则:不这样做,但
这是一些时间(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**.5
比它快一点sqrt(x)
.
对于Python 3.0,结果恰恰相反:
$ \Python30\python -mtimeit -s"from math import sqrt; x = 123" "x**.5" 1000000 loops, best of 3: 0.803 usec per loop $ \Python30\python -mtimeit -s"from math import sqrt; x = 123" "sqrt(x)" 1000000 loops, best of 3: 0.695 usec per loop $ \Python30\python -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图形引擎?如果没有,那么为什么要使用易于阅读的代码隐藏的代码呢?时间差异将小于任何人可能会注意到的任何我可以预见的应用程序.我真的不是故意放下你的问题,但似乎你因为过早优化而走得太远了.
在这些微基准测试中,math.sqrt会更慢,因为在math命名空间中查找sqrt所需的时间很短.您可以稍微改善它
from math import sqrt
尽管如此,通过timeit运行一些变化,显示"x**.5"的轻微(4-5%)性能优势
有趣的是,做
import math sqrt = math.sqrt
将速度加快,速度差异在1%以内,具有非常小的统计意义.
我将重复Kibbee,并说这可能是一个不成熟的优化.
在python 2.6中,该(float).__pow__()
函数使用C pow()
函数,math.sqrt()
函数使用C sqrt()
函数.
在glibc编译器中,实现pow(x,y)
非常复杂,并且针对各种异常情况进行了很好的优化.例如,调用C pow(x,0.5)
只调用该sqrt()
函数.
使用.**
或math.sqrt
由C函数周围使用的包装器和速度引起的速度差异很大程度上取决于系统上使用的优化标志/ C编译器.
编辑:
以下是我机器上Claudiu算法的结果.我得到了不同的结果:
zoltan@host:~$ python2.4 p.py Took 0.173994 seconds Took 0.158991 seconds zoltan@host:~$ python2.5 p.py Took 0.182321 seconds Took 0.155394 seconds zoltan@host:~$ python2.6 p.py Took 0.166766 seconds Took 0.097018 seconds