为什么这些常量函数的性能不同?

2024-09-24 22:29:59 发布

您现在位置:Python中文网/ 问答频道 /正文

在下面的代码片段中,为什么py_sqrt2的速度几乎是np_sqrt2的两倍

from time import time
from numpy import sqrt as npsqrt
from math import sqrt as pysqrt

NP_SQRT2 = npsqrt(2.0)
PY_SQRT2 = pysqrt(2.0)

def np_sqrt2():
    return NP_SQRT2

def py_sqrt2():
    return PY_SQRT2

def main():
    samples = 10000000

    it = time()
    E = sum(np_sqrt2() for _ in range(samples)) / samples
    print("executed {} np_sqrt2's in {:.6f} seconds E={}".format(samples, time() - it, E))

    it = time()
    E = sum(py_sqrt2() for _ in range(samples)) / samples
    print("executed {} py_sqrt2's in {:.6f} seconds E={}".format(samples, time() - it, E))


if __name__ == "__main__":
    main()

$ python2.7 snippet.py 
executed 10000000 np_sqrt2's in 1.380090 seconds E=1.41421356238
executed 10000000 py_sqrt2's in 0.855742 seconds E=1.41421356238
$ python3.6 snippet.py 
executed 10000000 np_sqrt2's in 1.628093 seconds E=1.4142135623841212
executed 10000000 py_sqrt2's in 0.932918 seconds E=1.4142135623841212

请注意,它们是常量函数,仅从具有相同值的预计算全局变量加载,并且这些常量仅在程序启动时的计算方式上有所不同

此外,对这些函数的反汇编表明它们按预期执行,并且只访问全局常量

In [73]: dis(py_sqrt2)                                                                                                                                                                            
  2           0 LOAD_GLOBAL              0 (PY_SQRT2)
              2 RETURN_VALUE

In [74]: dis(np_sqrt2)                                                                                                                                                                            
  2           0 LOAD_GLOBAL              0 (NP_SQRT2)
              2 RETURN_VALUE

Tags: infrompyimporttimedefnpit
2条回答

在两个版本的脚本上运行^{}后,一个只使用PY_SQRT2,另一个只使用NP_SQRT2,似乎使用numpy常量的脚本正在进行额外调用

这让我意识到这两个常量有不同的类型:

In [4]: type(PY_SQRT2)                                                          
Out[4]: float

In [5]: type(NP_SQRT2)                                                          
Out[5]: numpy.float64

因此,使用sumon(并可能加载?numpy.float64操作比本机浮点慢

This answer也有帮助

因为每次只为一个值将其发送到c

请尝试以下方法

t0=time.time()
numpy.sqrt([2]*10000)
t1 = time.time()
print("Took %0.3fs to do 10k sqrt(2)"%(t1-t0))

t0 = time.time()
for i in range(10000):
    numpy.sqrt(2)
t1 = time.time()
print("Took %0.3fs to do 10k math.sqrt(2)"%(t1-t0))

相关问题 更多 >