为什么 < 比 >= 慢

19 投票
7 回答
2448 浏览
提问于 2025-04-16 02:03

我在用下面的代码进行测试,发现<这个操作比>=要慢,不知道为什么会这样?

import timeit
s = """
  x=5
  if x<0: pass
"""
  t = timeit.Timer(stmt=s)
  print "%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)
#0.21 usec/pass
z = """
  x=5
  if x>=0: pass
"""
t2 = timeit.Timer(stmt=z)
print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000)
#0.18 usec/pass

7 个回答

5

你的第一个测试结果是对的,第二个测试结果是错的。可能因此会有一些细微的处理差别。

5

COMPARE_OP这个操作码有一个优化,专门针对两个都是整数的情况,这两个整数和C语言中的整数兼容。在这种情况下,它会直接用一个switch语句来进行比较:

if (PyInt_CheckExact(w) && PyInt_CheckExact(v)) {
        /* INLINE: cmp(int, int) */
        register long a, b;
        register int res;
        a = PyInt_AS_LONG(v);
        b = PyInt_AS_LONG(w);
        switch (oparg) {
        case PyCmp_LT: res = a <  b; break;
        case PyCmp_LE: res = a <= b; break;
        case PyCmp_EQ: res = a == b; break;
        case PyCmp_NE: res = a != b; break;
        case PyCmp_GT: res = a >  b; break;
        case PyCmp_GE: res = a >= b; break;
        case PyCmp_IS: res = v == w; break;
        case PyCmp_IS_NOT: res = v != w; break;
        default: goto slow_compare;
        }
        x = res ? Py_True : Py_False;
        Py_INCREF(x);
}

所以在比较中,你能看到的变化就只有通过switch语句的不同路径,以及结果是True(真)还是False(假)。我猜测你看到的变化可能是因为CPU的执行路径(还有可能是分支预测),所以你观察到的效果在其他版本的Python中也可能会消失,或者正好相反。

32

在Python 3.1.2中,有时候用<比用>=要快。我试着在反汇编工具中查看它。

import dis
def f1():
    x=5
    if x < 0: pass

def f2():
    x = 5
    if x >=0: pass

>>> dis.dis(f1)
  2           0 LOAD_CONST               1 (5) 
              3 STORE_FAST               0 (x) 

  3           6 LOAD_FAST                0 (x) 
              9 LOAD_CONST               2 (0) 
             12 COMPARE_OP               0 (<) 
             15 POP_JUMP_IF_FALSE       21 
             18 JUMP_FORWARD             0 (to 21) 
        >>   21 LOAD_CONST               0 (None) 
             24 RETURN_VALUE         
>>> dis.dis(f2)
  2           0 LOAD_CONST               1 (5) 
              3 STORE_FAST               0 (x) 

  3           6 LOAD_FAST                0 (x) 
              9 LOAD_CONST               2 (0) 
             12 COMPARE_OP               5 (>=) 
             15 POP_JUMP_IF_FALSE       21 
             18 JUMP_FORWARD             0 (to 21) 
        >>   21 LOAD_CONST               0 (None) 
             24 RETURN_VALUE         

代码几乎是一样的,但f1总是执行第15行,然后跳到第21行,而f2总是执行15 -> 18 -> 21。所以性能的影响应该是因为if语句中的真或假,而不是<或>=的问题。

撰写回答