Python 3.x 为什么python';对于大输入,循环是如此非线性?

Python 3.x 为什么python';对于大输入,循环是如此非线性?,python-3.x,for-loop,benchmarking,Python 3.x,For Loop,Benchmarking,我在测试一些python代码时发现了一些奇怪的东西。我使用以下函数来测量遍历空for循环的速度: def f(n): t1 = time.time() for i in range(n): pass print(time.time() - t1) f(10**6)打印关于0.035,f(10**7)关于0.35,f(10**8)关于3.5和f(10**9)关于35。但是f(10**10)?远远超过2000。这当然出乎意料。为什么迭代10倍多的元素需要60

我在测试一些python代码时发现了一些奇怪的东西。我使用以下函数来测量遍历空for循环的速度:

def f(n):
    t1 = time.time()
    for i in range(n):
        pass
    print(time.time() - t1)

f(10**6)
打印关于
0.035
f(10**7)
关于
0.35
f(10**8)
关于
3.5
f(10**9)
关于
35
。但是
f(10**10)
?远远超过
2000
。这当然出乎意料。为什么迭代10倍多的元素需要60倍多的时间?python的for循环是如何导致这种情况的?这是特定于python的,还是在许多语言中都会出现这种情况?

当您超过
10^9
时,您将超出32位整数范围。Python3然后透明地将您移动到上一个位置,这将大大降低分配和使用的速度


一般来说,处理如此大的数字是Python3比Python2慢得多的领域之一(在许多系统上,Python2至少有快速的64位整数)。好的一面是,它使python更易于使用,类型错误更少。

一些使用
timeit
的精确计时显示时间实际上大致随输入大小而增加,因此您的计时似乎相差很远:

In [2]: for n in [10**6,10**7,10**8,10**9,10**10]:
               % timeit f(n)
   ...:     
10 loops, best of 3: 22.8 ms per loop
1 loops, best of 3: 226 ms per loop # roughly ten times previous
1 loops, best of 3: 2.26 s per loop # roughly ten times previous
1 loops, best of 3: 23.3 s per loop # roughly ten times previous
1 loops, best of 3: 4min 18s per loop # roughly ten times previous
使用xrange和python2,我们可以看到大致相同的比率,显然python2总体上要快得多,因为python3 int已被long替换:

In [5]: for n in [10**6,10**7,10**8,10**9,10**10]:
               % timeit f(n)
   ...:     
100 loops, best of 3: 11.3 ms per loop
10 loops, best of 3: 113 ms per loop
1 loops, best of 3: 1.13 s per loop
1 loops, best of 3: 11.4 s per loop
1 loops, best of 3: 1min 56s per loop

运行时的实际差异似乎更多地与的大小有关,而不是与Python3直接相关。当使用unix处理long时,两者之间的差别是微不足道的,因为unix处理long的方式与windows有很大不同,因此这是一个平台特定的问题,如果不超过python的问题。

如果使用python2,使用timeit模块,您的计时效果也会更好,从
10**6
10**9
有很大的不同。指数增长那么我认为这是因为10^9适合标准的32位整数,而10^10 python使用任意大小的整数。这使得每次比较都变慢了。也许python会为列表分配内存。对于太多的项目,操作系统正在分页到磁盘空间。@clemos24不在Py3中,
range
返回一个生成器,而不是一个列表。它从Pep237:开始,使得longs具有任意精度。后来Python3去掉了int类型,这会减慢速度。在3.x版本中,我相信他们一直在努力为更小的整数引入更多的优化。运行时间的实际差异似乎完全是平台特定的。@Padraiccnningham我一直在努力阅读长期实现的源代码,以了解何时进行优化。一个数字应该是15位还是30位当然是有选择的,但在那之后,破译它就成了一项艰巨的工作。我刚刚做了另一项测试,结果如下:
10**6
-0.07520970538367432秒,
10**7
-0.36399144430744984秒,
10**8
-3.492617033957秒,
10**9
-34.71252936832384秒,
10**10
-2190.0514266665177秒。我们在哪个系统上运行它可能会有所不同吗?@user3002473。您在什么设备上运行它?@PadriacCunningham Windows 7 64位,英特尔Core i5 3.20 GHz处理器,安装了4.00 GB内存。@user3002473。我在Ubuntu 14.04上使用类似的规格。我想不出它跑得这么慢的明显原因。您是否使用Python2和xrange进行过尝试?@user3002473,您受到窗口长度大小的限制,因此您会得到
溢出错误。与mu linux机器相比,这可能是导致性能如此差的一个因素。明天我会做更多的挖掘,因为整数大小的解释并不能解释整个故事。如果它是特定于python的,那么我的性能也会受到类似的影响