为什么加法和乘法比比较快?

2024-04-26 11:48:21 发布

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

我一直认为比较是计算机可以执行的最快的操作。我记得在D.Knuth的一次演示中听到过这样的话,他按降序编写循环,“因为与0的比较很快”。我还读到乘法应该比加法here慢。在

我很惊讶地看到,在python2和python3中,在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

在python 3下:

^{pr2}$

Tags: ofloopfalsetruehere计算机bestns
3条回答

快速的disassambling表明比较涉及更多操作。根据this answer,对于乘法、加法,"peephole optimiser"wiki)有一些预计算,但对比较运算符没有:

>>> import dis
>>> def a():
...   return 2*3
... 
>>> dis.dis(a)
  2           0 LOAD_CONST               3 (6)
              3 RETURN_VALUE
>>> def b():
...   return 2 < 3
... 
>>> dis.dis(b)
  2           0 LOAD_CONST               1 (2)
              3 LOAD_CONST               2 (3)
              6 COMPARE_OP               0 (<)
              9 RETURN_VALUE

这是由于Python编译器中的Peep Holeoptimizer中的Constant Folding造成的。在

使用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        

正如其他人所解释的,这是因为Python的窥视孔优化程序优化了算术运算,而不是比较。在

在为一个基本编译器编写了自己的窥视孔优化程序之后,我可以向您保证,优化常量比较和优化常量算术运算一样简单。因此,没有技术上的理由说明Python应该做后者而不是前者。在

然而,每一个这样的优化都必须单独编程,并且有两个成本:编程时间和额外的优化代码占用Python可执行文件中的空间。所以你发现自己不得不做一些分类:这些优化中哪些是最常见的,足以让它值得付出代价?在

似乎Python实现者决定首先优化算术操作,这是合理的。也许在将来的发行版中,它们会进行比较。在

相关问题 更多 >