【问题标题】:While-loop with if-statement faster than while-loop带有 if 语句的 While 循环比 while 循环快
【发布时间】:2012-12-02 21:38:44
【问题描述】:

我正在对循环中 if 语句的速度及其对速度的影响进行一些测试。我发现,if 语句始终如一地提高了性能。我的代码:

import time
t = time.time

start = t()
x = 0
while x < 10000000:
    x += 1
time1 = t()
x = 0
while x < 10000000:
    x += 1
    if True:
        pass
time2 = t()

print(start)
print(time1 - start) # Time for simple while-loop
print(time2 - time1) # Time for while+if

示例输出为:

1355517837.993
1.7850000858306885
1.7209999561309814

这完全违反直觉。 while-if-loop 的工作速度比标准的 while-loop 快得多。几乎每次我运行它都会发生这种情况;也许 20 次中有 1 次需要更长的时间。有谁知道为什么?

【问题讨论】:

  • 如果将x=0 移出两个定时块会怎样?我敢打赌,你看到的是解释器必须为第一个块分配 x 而不是第二个。
  • 这里不一样,虽然';我有这样的时间:$ python t.py 1355519439.65 1.92616391182 2.65010595322;在 Python 2.7.3 上运行
  • 如果您先运行 if 循环,然后再运行没有它的循环,结果是否相同?对我来说,第一个总是更快。
  • 我在 2.7 中得到了你所期望的结果,在 3.2 中得到了奇怪的结果。
  • 正如预期的那样,第二个版本(在 Python 3.2.3 中)也持续获得更长的时间。请记住,time.time() 不是分析程序的正确方法(因为其他任务可能会影响结果)。请改用timeit.timeit()

标签: python performance if-statement python-3.x while-loop


【解决方案1】:

我猜编译器会删除 if True 块,因为它是常量。

当我跑步时,我从你那里得到的结果大多相反。我可能只是执行环境的随机效应。

1355519587.2 0.832797050476 1.04382395744

1355519590.03 0.863899946213 1.09347200394

1355519593.72 0.831655025482 1.05389809608

1355519599.71 0.831452131271 1.41783499718

1355519602.99 0.815280914307 1.05724310875

1355519605.72 0.826404094696 1.05700492859

1355519608.94 0.827296972275 1.07807898521

【讨论】:

  • 哪个引擎?没有即时编译器或任何东西。至少在 CPython 中没有。其实根本没有编译器,我们这里说的是Python。
  • 同意。我的结果是:1355519852.98, 0.830796003342, 1.11595201492 with python 2.7.1
  • @TimPietzcker,它是 2.7.1。 Python 确实编译,但编译为字节码。您无法在大多数操作环境中执行原始文本。
  • @delnan:你能举个例子或链接到一些关于编译器可以做哪些优化的文档吗?显然无法删除空的if 语句。
  • @TimPietzcker 我不认为这是记录在案的,因为它是一个实现细节并且很少重要。在3.2 whatsnew 中提到了我见过的优化器。当然,还有来源:peephole.c(有很多 cmets 详细说明了执行的优化)。请参阅第 446 行,了解根据常量对跳转的 a 优化。
【解决方案2】:

dis 表明 if 语句 while 循环有更多步骤。

In [4]: dis.dis(t2)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               0 (x)

  3           6 SETUP_LOOP              26 (to 35)
        >>    9 LOAD_FAST                0 (x)
             12 LOAD_CONST               2 (10000000)
             15 COMPARE_OP               0 (<)
             18 POP_JUMP_IF_FALSE       34

  4          21 LOAD_FAST                0 (x)
             24 LOAD_CONST               3 (1)
             27 INPLACE_ADD
             28 STORE_FAST               0 (x)
             31 JUMP_ABSOLUTE            9
        >>   34 POP_BLOCK
        >>   35 LOAD_CONST               0 (None)
             38 RETURN_VALUE

In [5]: dis.dis(t1)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               0 (x)

  3           6 SETUP_LOOP              35 (to 44)
        >>    9 LOAD_FAST                0 (x)
             12 LOAD_CONST               2 (10000000)
             15 COMPARE_OP               0 (<)
             18 POP_JUMP_IF_FALSE       43

  4          21 LOAD_FAST                0 (x)
             24 LOAD_CONST               3 (1)
             27 INPLACE_ADD
             28 STORE_FAST               0 (x)

  5          31 LOAD_GLOBAL              0 (True)
             34 POP_JUMP_IF_FALSE        9

  6          37 JUMP_ABSOLUTE            9
             40 JUMP_ABSOLUTE            9
        >>   43 POP_BLOCK
        >>   44 LOAD_CONST               0 (None)
             47 RETURN_VALUE

【讨论】:

  • 感谢您发布此内容,我之前不知道 dis 模块。然而,while-if-loop 运行得更快仍然令人困惑,即使在这个非常低的级别上它也需要更多的步骤。
猜你喜欢
  • 2015-05-19
  • 2021-03-18
  • 1970-01-01
  • 1970-01-01
  • 2013-06-09
  • 2014-01-21
  • 2015-11-08
  • 2016-01-12
  • 1970-01-01
相关资源
最近更新 更多