【问题标题】:Variable lookup: Why is ** with variables so much slower than with values变量查找:为什么 ** 使用变量比使用值慢得多
【发布时间】:2016-04-15 00:13:11
【问题描述】:

我读过math.sqrt** 快,今天我尝试了。但有趣的不是这两者之间的时间差,而是** 带变量和** 带值之间的时间差:

value1 = 10.1
value2 = 0.5
%timeit value1 ** value2
# 1000000 loops, best of 3: 645 ns per loop
%timeit 10.1 ** 0.5
# 10000000 loops, best of 3: 60.7 ns per loop

这快了十倍以上。而对于数学函数来说,时间几乎是相同的(变量查找只需要几纳秒):

import math
%timeit math.sqrt(10.1)
# 1000000 loops, best of 3: 529 ns per loop
%timeit math.sqrt(value1)
# 1000000 loops, best of 3: 568 ns per loop

谁能解释一下为什么变量查找对** 产生了如此大的影响,而对math.sqrt 却没有什么影响?

设置:

  • python 3.5
  • Windows 10 64 位

【问题讨论】:

    标签: python performance


    【解决方案1】:

    使用变量:

    In [41]: def var():
       ....:     value1 ** value2
       ....:     
    
    In [43]: dis.dis(var)
      2           0 LOAD_GLOBAL              0 (value1)
                  3 LOAD_GLOBAL              1 (value2)
                  6 BINARY_POWER
                  7 POP_TOP
                  8 LOAD_CONST               0 (None)
                 11 RETURN_VALUE
    

    使用立即数:

    In [44]: def imm():
       ....:     10.1 ** 0.5
       ....:     
    
    In [45]: dis.dis(imm)
      2           0 LOAD_CONST               3 (3.1780497164141406)
                  3 POP_TOP
                  4 LOAD_CONST               0 (None)
                  7 RETURN_VALUE
    

    事实证明,编译器比我们聪明,提前计算了功率。

    【讨论】:

    • 很高兴知道这些操作是事先执行的。这真的让我感到惊讶,但这是有道理的。你知道这些是什么时候计算的吗?因为通常%timeit 会在一次运行比其他运行花费更长的时间时打印一条消息,而事实并非如此。
    • 编译时间,所以%timeit 没有警告,因为它一遍又一遍地运行相同的LOAD_CONST
    猜你喜欢
    • 2023-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    相关资源
    最近更新 更多