Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中,为什么处理排序数组的速度不比处理未排序数组的速度快?_Python_Performance - Fatal编程技术网

在Python中,为什么处理排序数组的速度不比处理未排序数组的速度快?

在Python中,为什么处理排序数组的速度不比处理未排序数组的速度快?,python,performance,Python,Performance,在这篇文章中,它说分支预测是排序数组性能提升的原因 但我只是尝试了使用Python的示例;我认为排序数组和随机数组之间没有区别(我尝试了bytearray和array;并使用line_profile分析计算) 我错过什么了吗 这是我的密码: from array import array import random array_size = 1024 loop_cnt = 1000 # I also tried 'array', and it's almost the same a = byte

在这篇文章中,它说分支预测是排序数组性能提升的原因

但我只是尝试了使用Python的示例;我认为排序数组和随机数组之间没有区别(我尝试了bytearray和array;并使用line_profile分析计算)

我错过什么了吗

这是我的密码:

from array import array
import random
array_size = 1024
loop_cnt = 1000
# I also tried 'array', and it's almost the same
a = bytearray(array_size)
for i in xrange(array_size):
    a.append(random.randint(0, 255))
#sorted                                                                         
a = sorted(a)
@profile
def computation():
    sum = 0
    for i in xrange(loop_cnt):
        for j in xrange(size):
            if a[j] >= 128:
                sum += a[j]

computation()
print 'done'
原因有二:

  • 数组大小太小,无法显示效果
  • Python比C有更多的开销,因此总体效果不太明显

sorted()
返回已排序的数组,而不是就地排序。你实际上是两次测量同一个数组。

我可能错了,但是我发现链接问题和你的例子有一个根本的区别:Python解释字节码,C++编译成本机代码。 < C++ >代码< <代码>如果直接转换为<代码> CMP /Cudio> JL> /COD>序列,CPU分支预测器可以将其视为单个“预测点”,具体到那个周期。

在Python中,这种比较实际上是几个函数调用,因此有(1)更多的开销,(2)我假设执行这种比较的代码是一个函数到解释器中,用于每一个其他整数比较-因此它是一个“预测点”,不特定于当前块,这使得分支预测器更难正确猜测



编辑:此外,正如本文所述,解释器中有更多的间接分支,因此Python代码中的这种优化可能会被解释器本身的分支预测失误所掩盖。

我将原始代码移植到Python并使用PyPy运行。我可以确认排序数组的处理速度比未排序数组快,并且无分支方法也可以消除运行时间与排序数组类似的分支。我相信这是因为PyPy是一个JIT编译器,所以分支预测正在发生

[编辑]

以下是我使用的代码:

import random import time def runme(data): sum = 0 start = time.time() for i in xrange(100000): for c in data: if c >= 128: sum += c end = time.time() print end - start print sum def runme_branchless(data): sum = 0 start = time.time() for i in xrange(100000): for c in data: t = (c - 128) >> 31 sum += ~t & c end = time.time() print end - start print sum data = list() for i in xrange(32768): data.append(random.randint(0, 256)) sorted_data = sorted(data) runme(sorted_data) runme(data) runme_branchless(sorted_data) runme_branchless(data) 随机输入 导入时间 def runme(数据): 总和=0 开始=时间。时间() 对于X范围内的i(100000): 对于数据中的c: 如果c>=128: 总和+=c end=time.time() 打印结束-开始 打印金额 def runme_无分支(数据): 总和=0 开始=时间。时间() 对于X范围内的i(100000): 对于数据中的c: t=(c-128)>>31 总和+=~t&c end=time.time() 打印结束-开始 打印金额 数据=列表() 对于X范围内的i(32768): data.append(random.randint(0256)) 已排序的\ u数据=已排序的(数据) 运行时(已排序的_数据) runme(数据) runme_无分支(已排序的_数据) runme_无分支(数据)
单击查看更多答案和类似问题。当对数据进行排序时,性能显著提高的原因是分支预测惩罚被删除,这在Mystical的回答中得到了很好的解释。

sorted(a)
返回另一个已排序的列表,但它不会修改
a
。要使代码按您认为的方式运行,您必须执行
a=sorted(a)
,或者更好的是执行
a.sort()
。您可能希望在此处查看python的结果。这可能会有所帮助。python使用timsort,这可能会有一些影响……fwiw@rogerdpack:排序算法并不重要;所有稳定的算法产生相同的结果。这里没有分析排序时间。这个程序在我的mac air上需要1.5秒,更大的阵列消耗太多时间;我只是不想等待。“我只是不想等待”所以你希望我们为你做…?@dda对不起,我的意思是,当配置如上所述时,该函数已经需要1.5秒;如果我们可以从排序数组中获得一些性能提升,我们肯定可以看到。实际上,我已经将数组大小更改了10倍,或者循环计数更改了10倍,执行时间线性增加。我在我的MBP上做了一个测试,将
array_size
loop_cnt
乘以10,结果如下:随机数组:9.97857904434排序数组:7.98291707039I刚刚将其更改为“a=Sorted(a)”;它仍然是2.53 GHz Intel Core 2 Duo和PyPy 1.9.0的相同MBP,结果是:
//分支-随机秒=36.2439880371//分支-排序秒=18.3833880424//无分支-随机秒=13.1689388752//无分支-排序秒=12.3706789017