Python3与Python2列表/生成器范围性能

Ima*_*axd 5 python performance generator python-2.7 python-3.x

我有这个简单的函数,它分区列表并返回列表中的索引i,使索引小于i的元素小于list [i],索引大于i的元素更大.

def partition(arr):
    first_high = 0
    pivot = len(arr) - 1
    for i in range(len(arr)):
        if arr[i] < arr[pivot]:
            arr[first_high], arr[i] = arr[i], arr[first_high]
            first_high = first_high + 1

    arr[first_high], arr[pivot] = arr[pivot], arr[first_high]
    return first_high


if __name__ == "__main__":
    arr = [1, 5, 4, 6, 0, 3]
    pivot = partition(arr)
    print(pivot)
Run Code Online (Sandbox Code Playgroud)

OS X上的python 2.7.6的python 3.4运行时间要大得多:

time python3 partition.py
real 0m0.040s
user 0m0.027s
sys  0m0.010s

time python partition.py
real 0m0.031s
user 0m0.018s
sys  0m0.011s
Run Code Online (Sandbox Code Playgroud)

在ubuntu 14.04 /虚拟机上也是如此

python3:

real 0m0.049s
user 0m0.034s
sys  0m0.015s
Run Code Online (Sandbox Code Playgroud)

蟒蛇:

real 0m0.044s
user 0m0.022s
sys  0m0.018s
Run Code Online (Sandbox Code Playgroud)

python3本身是否比python2.7慢,或者是否对代码进行了任何特定的优化,使得运行速度与python2.7一样快

Pau*_* Bu 13

正如评论中所提到的,您应该timeit使用OS工具而不是OS工具进行基准测试.

我的猜测是range函数可能在Python 3中执行得慢一些.在Python 2中它只返回一个列表,在Python 3中它返回的range行为或多或少像一个生成器.我做了一些基准测试,这是结果,这可能暗示你正在经历的事情:

python -mtimeit "range(10)"
1000000 loops, best of 3: 0.474 usec per loop

python3 -mtimeit "range(10)"
1000000 loops, best of 3: 0.59 usec per loop

python -mtimeit "range(100)"
1000000 loops, best of 3: 1.1 usec per loop

python3 -mtimeit "range(100)"
1000000 loops, best of 3: 0.578 usec per loop

python -mtimeit "range(1000)"
100000 loops, best of 3: 11.6 usec per loop

python3 -mtimeit "range(1000)"
1000000 loops, best of 3: 0.66 usec per loop
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,当提供的输入range小时,它在Python 2中往往很快.如果输入增长,那么Python 3的 range表现会更好.

我的建议:测试更大数组的代码,有一百或一千个元素.

实际上,我进一步测试了元素的完整迭代.结果完全支持Python 2:

python -mtimeit "for i in range(1000):pass"
10000 loops, best of 3: 31 usec per loop

python3 -mtimeit "for i in range(1000):pass"
10000 loops, best of 3: 45.3 usec per loop

python -mtimeit "for i in range(10000):pass"
1000 loops, best of 3: 330 usec per loop

python3 -mtimeit "for i in range(10000):pass"
1000 loops, best of 3: 480 usec per loop
Run Code Online (Sandbox Code Playgroud)

我的结论是,迭代列表可能比通过生成器更快.虽然后者在内存消耗方面肯定更有效.这是速度和记忆之间权衡的典型例子.虽然速度差异本身并不(小于几毫秒).因此,您应该重视这一点,并为您的计划做些什么.

  • Python 3`range()`应该与Python 2`xrange()`进行比较.它不首先生成列表,它只迭代值.这样,它对于更大的范围也不会消耗更多的内存. (5认同)
  • 使用具有十亿整数的Python 2的范围会爆炸内存,因为它需要~4GB来存储列表.这正是Python3的`range`或Python2的`xrange`派上用场的时候.我在答案中提到的那种权衡. (2认同)