dan*_*gom 21 python performance
我一直认为比较是计算机可以执行的最快的操作.我记得在D. Knuth的演讲中听到它,他在那里按降序编写循环"因为与0的比较很快".我还读到乘法应该比这里的加法慢.
我很惊讶地看到,在Python 2和Mac下,在Linux和Mac下都进行了测试,比较似乎比算术运算慢得多.
谁有人解释为什么?
%timeit 2 > 0
10000000 loops, best of 3: 41.5 ns per loop
%timeit 2 * 2
10000000 loops, best of 3: 27 ns per loop
%timeit 2 * 0
10000000 loops, best of 3: 27.7 ns per loop
%timeit True != False
10000000 loops, best of 3: 75 ns per loop
%timeit True and False
10000000 loops, best of 3: 58.8 ns per loop
Run Code Online (Sandbox Code Playgroud)
并在python 3下:
$ ipython3
Python 3.5.2 | packaged by conda-forge | (default, Sep 8 2016, 14:36:38)
Type "copyright", "credits" or "license" for more information.
IPython 5.1.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: %timeit 2 + 2
10000000 loops, best of 3: 22.9 ns per loop
In [2]: %timeit 2 * 2
10000000 loops, best of 3: 23.7 ns per loop
In [3]: %timeit 2 > 2
10000000 loops, best of 3: 45.5 ns per loop
In [4]: %timeit True and False
10000000 loops, best of 3: 62.8 ns per loop
In [5]: %timeit True != False
10000000 loops, best of 3: 92.9 ns per loop
Run Code Online (Sandbox Code Playgroud)
mu *_*u 無 19
这是由于Python编译器中的Peep Hole 优化器中的常量折叠而发生的.
使用dis模块,如果我们打破每个语句以查看它们在机器级别的翻译方式,你会发现所有运算符如不等式,等式等首先被加载到内存中然后进行评估.但是,计算所有表达式,如乘法,加法等,并将其作为常量加载到内存中.
总的来说,这会导致执行步骤的数量减少,从而加快了步骤:
>>> import dis
>>> def m1(): True != False
>>> dis.dis(m1)
1 0 LOAD_GLOBAL 0 (True)
3 LOAD_GLOBAL 1 (False)
6 COMPARE_OP 3 (!=)
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>> def m2(): 2 *2
>>> dis.dis(m2)
1 0 LOAD_CONST 2 (4)
3 POP_TOP
4 LOAD_CONST 0 (None)
7 RETURN_VALUE
>>> def m3(): 2*5
>>> dis.dis(m3)
1 0 LOAD_CONST 3 (10)
3 POP_TOP
4 LOAD_CONST 0 (None)
7 RETURN_VALUE
>>> def m4(): 2 > 0
>>> dis.dis(m4)
1 0 LOAD_CONST 1 (2)
3 LOAD_CONST 2 (0)
6 COMPARE_OP 4 (>)
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>> def m5(): True and False
>>> dis.dis(m5)
1 0 LOAD_GLOBAL 0 (True)
3 JUMP_IF_FALSE_OR_POP 9
6 LOAD_GLOBAL 1 (False)
>> 9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
正如其他人所解释的那样,这是因为Python的窥视孔优化器优化了算术运算而不是比较.
为Basic编译器编写了自己的窥孔优化器之后,我可以向您保证,优化常量比较与优化常量算术运算一样简单.所以没有技术上的理由说明为什么Python应该做后者而不是前者.
但是,每个这样的优化都必须单独编程,并且需要两个成本:编程它的时间,以及占用Python可执行文件空间的额外优化代码.因此,您发现自己必须进行一些分类:哪些优化足以使其值得花费?
似乎Python的实现者,合理地决定首先优化算术运算.也许他们将在未来的版本中进行比较.