当前位置: 首页 > 知识库问答 >
问题:

为什么在Python中处理排序数组并不比处理未排序数组快?

霍伟彦
2023-03-14

在这篇文章中,为什么处理排序数组比处理随机数组更快,它说分支预测是排序数组性能提升的原因。

但是我刚刚使用Python尝试了这个例子;我认为排序数组和随机数组没有区别(我尝试了字节数组和数组;并使用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'

共有3个答案

富凯风
2023-03-14

我将原始代码移植到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)
欧阳鸿德
2023-03-14

两个原因:

  • 您的数组大小太小,无法显示效果。
  • Python的开销比C的开销更大,因此整体效果不太明显。
百里芷阳
2023-03-14

我可能错了,但我看到了链接问题和您的例子之间的根本区别:Python解释字节码,C编译成本机代码。

if直接转换为cmp/jl序列的C代码中,CPU分支预测器可以将其视为单个“预测点”,特定于该周期。

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

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

 类似资料:
  • 问题内容: 这是一段C ++代码,显示了一些非常特殊的行为。由于某些奇怪的原因,奇迹般地对数据进行排序使代码快了将近六倍: 不使用std::sort(data, data + arraySize);,代码将在11.54秒内运行。 使用排序的数据,代码将在1.93秒内运行。 最初,我认为这可能只是语言或编译器异常,所以我尝试了Java: 具有类似但不太极端的结果。 我首先想到的是排序将数据带入缓存,

  • 我发现了这个流行的9岁左右的问题,并决定重新检查它的结果。 所以,我有AMD Ryzen 9 595 0x、Clang++10和Linux,我从问题中复制粘贴了代码,下面是我得到的: 分类-0.549702秒: 未排序-0.546554s: 我很确定的事实是,未经排序的版本被证明是快了3ms,只是噪音,但它似乎不再慢了。 那么,CPU的架构发生了什么变化(以至于不再慢一个数量级)? 以下是多次运行

  • 假设我有一个二维像素网格(4乘4像素)——我有一个和我草图一样大小的图像,它被切割成16个部分。现在我将所有16个部分加载到一个数组中。我想依次将这个数组映射到2D网格上,这样我的整体图像就可以再次正确地组合在一起。也就是说,左上角图像0.png右下角图像16.png. 我就是找不到能让我这么做的公式。例如,我知道使用可以在所有像素中运行,从左上到右下,所以我试过了。如果没有它就不能正确地坐在一起

  • 我有2列制表符分隔的整数,其中第一列是随机整数,第二列是标识组的整数,可以由此程序生成。() 然后,我使用第二个程序()计算每个组的和。 如果我在给定大小的数据集上运行这些程序,然后打乱相同数据集的行的顺序,打乱的数据计算总和的速度比有序数据快2倍或更多。 我本来希望按组排序的原始数据具有更好的数据局部性并且速度更快,但我观察到相反的行为。我想知道是否有人可以假设原因?

  • 本文向大家介绍JavaScript对象数组的排序处理方法,包括了JavaScript对象数组的排序处理方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JavaScript对象数组的排序处理方法。分享给大家供大家参考,具体如下: javascript的数组排序函数 sort方法,默认是按照ASCII 字符顺序进行升序排列。 arrayobj.sort(sortfunction); 参数:

  • 我发现了这个流行的9岁左右的问题,并决定重新检查它的结果。 所以,我有AMD Ryzen 9 595 0x、Clang++10和Linux,我从问题中复制粘贴了代码,下面是我得到的: 分类-0.549702秒: 未排序-0.546554s: 我很确定的事实是,未经排序的版本被证明是快了3ms,只是噪音,但它似乎不再慢了。 那么,CPU的架构发生了什么变化(以至于不再慢一个数量级)? 以下是多次运行