在这篇文章Why is processing a sorted array faster than random array中,它表示分支预测是排序数组性能提升的原因。
但我只是尝试使用Python的例子;我认为排序和随机数组之间没有区别(我尝试了bytearray和数组;并使用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'
答案 0 :(得分:19)
我可能错了,但我看到链接问题与您的示例之间存在根本区别:Python解释字节码,C ++编译为本机代码。
在if
直接转换为cmp
/ jl
序列的C ++代码中,CPU分支预测器可将其视为单个“预测点”,特定于此周期。
在Python中,比较实际上是几个函数调用,因此有(1)更多的开销;(2)我认为执行该比较的代码是用于每个其他整数比较的解释器的函数 - 所以它是“预测”斑点“不是特定于当前块,这使分支预测器更难以正确猜测。
编辑:另外,如this论文所述,解释器中有更多的间接分支,因此Python代码中的这种优化可能会被分支埋没翻译本身的错误预测。
答案 1 :(得分:5)
有两个原因:
答案 2 :(得分:5)
我将原始代码移植到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)
答案 3 :(得分:4)
sorted()
返回已排序的数组,而不是按位排序。你实际上是在两次测量相同的数组。
答案 4 :(得分:-3)
点击here查看更多答案和类似问题。数据排序时性能大幅提升的原因是分支预测惩罚被删除,正如Mysticial的回答中所解释的那样。