21

我知道这可以说是一个非问题,但我为 HPC 环境编写软件,所以这 3.5 倍的速度提升实际上有所作为。

In [1]: %timeit 10 / float(98765)            
1000000 loops, best of 3: 313 ns per loop

In [2]: %timeit 10 / (98765 * 1.0)
10000000 loops, best of 3: 80.6 ns per loop

我曾经dis看过代码,我认为float()它会更慢,因为它需要一个函数调用(不幸的是我dis.dis(float)看不到它实际上在做什么)。

我想第二个问题是我应该什么时候使用float(n),什么时候应该使用n * 1.0

4

1 回答 1

28

因为窥视孔优化器通过预先计算乘法的结果来优化它

import dis
dis.dis(compile("10 / float(98765)", "<string>", "eval"))

  1           0 LOAD_CONST               0 (10)
              3 LOAD_NAME                0 (float)
              6 LOAD_CONST               1 (98765)
              9 CALL_FUNCTION            1
             12 BINARY_DIVIDE       
             13 RETURN_VALUE        

dis.dis(compile("10 / (98765 * 1.0)", "<string>", "eval"))

  1           0 LOAD_CONST               0 (10)
              3 LOAD_CONST               3 (98765.0)
              6 BINARY_DIVIDE       
              7 RETURN_VALUE        

98765 * 1.0它将字节码中的结果存储为常量值。所以,它只需要加载它并划分,在第一种情况下,我们必须调用函数。

我们可以像这样更清楚地看到

print compile("10 / (98765 * 1.0)", "<string>", "eval").co_consts
# (10, 98765, 1.0, 98765.0)

由于该值是在编译时预先计算的,因此第二个更快。

编辑:正如Davidmh 在评论中指出的那样,

它没有优化除法的原因是因为它的行为取决于标志,比如标志,from __future__ import division也因为-Q标志。

引用Python 2.7.9 的实际窥视孔优化器代码中的评论

        /* Cannot fold this operation statically since
           the result can depend on the run-time presence
           of the -Qnew flag */
于 2014-04-10T09:27:49.267 回答