繁体   English   中英

如何以最快的方式对用列表填充的数组(大 N)进行排序?

[英]How to sort an array (large N) that is populated with lists in the FASTest way possible?

我需要一个超高效的排序算法。 内置的 Python .sort和 sorted 速度很快,但对于我的任务来说还不够快。 同样,我不能使用numpy.sort()因为我需要对数组进行排序(用列表填充)。 我似乎找不到一个 GitHub 库来对一个充满列表的数组进行排序。 我还需要能够切换升序/降序。 该数组很大,对于不同的数据集,类似大小的数组将被排序数千次。 任何链接或代码将不胜感激!

ex1 = {'index': 0, 'value': 72}
ex2 = {'index': 1, 'value': 49}
ex9999 = {'index': 9999, 'value': 121}
array = [ex1, ex2, ex9999]
array.sort(key=lambda x: x['index'], reverse=False)
#how to sort array of lists in native python  (just too slow)

上面的排序需要 0.3 秒(对于 20K 数据点)但是对于 10K 大小的数组进行排序,运行时间太慢了。 可以接受的是我从这篇文章中知道的可能的 1/10 https://www.quora.com/What-is-the-absolute-fastest-way-to-sort-a-very-large-random-list -of-integers-in-python ,只是无法对填充列表的数组进行排序

改为对元组进行排序。

tuples = [(d['index'], d['value'])
          for d in array]
tuples.sort()

你没有张贴任何timeit数据。 向我们展示代表性数据和实际时间,然后描述什么样的修改时间是可以接受的。 目前尚不清楚您是否可以击败timsort ,尽管 lambda 开销肯定会很大。

如果你还需要更快,去掉不相关的value属性:

indices = [d['index']
           for d in array]
indices.sort()

几个经过的时间很重要:

  1. 创建列表的时间
  2. 排序列表的时间
  3. 是时候使用排序列表了

如上所述,您的问题没有具体说明,因为它不限制 (1.) 或 (3.),而且我们都知道存在谎言、该死的谎言和微观基准。

初始(半排序)顺序、值的分布以及针对排序列表的访问模式对于最终经过的时间都很重要。

有些问题只需要完整 python3 语义的一个子集,并且可以进行numba优化。 您没有告诉我们足够的信息来判断这是否适用于您的业务问题。

编辑

现代平台上的 Timsort 可以轻松地以元组形式每秒对 400 万个项目进行排序,这比需要lambda开销的情况要少一些。

你没有发布计时数据。 您描述了在未知硬件上每秒对 700 K 项进行排序的要求,并声称发布的代码无法做到这一点。

发布的代码按顺序(排序)顺序提供索引,这看起来很奇怪,但我在下面的代码中为元组排序复制了该方面。

这是我在 2.9 GHz 英特尔酷睿 i7 mac 笔记本电脑上运行的内容:

#! /usr/bin/env python

from time import time
import random


def elapsed(fn):
    def print_elapsed(*args, **kw):
        t0 = time()
        ret = fn(*args, **kw)
        print(fn.__name__, '%.3f sec' % (time() - t0))
        return ret
    return print_elapsed


@elapsed
def get_values(k=2_000_000, base_val=42):
    return [dict(index=random.randint(0, 3e6), value=i + base_val + i % 10)
            for i in range(k)]


@elapsed
def get_tuples(dicts):
    return [(d['index'], d['value'])
            for d in dicts]


@elapsed
def get_indices(dicts):
    return [d['index']
            for d in dicts]


@elapsed
def sort_dicts(dicts):
    dicts.sort(key=lambda x: x['index'])


@elapsed
def sort_values(x, reverse=False):
    x.sort(reverse=reverse)


if __name__ == '__main__':
    dicts = get_values()
    sort_dicts(dicts)
    tuples = get_tuples(dicts)
    sort_values(tuples)
    indices = get_indices(dicts)
    sort_values(indices)

2 M 项的输出:

get_values  3.307 sec
sort_dicts  2.121 sec
get_tuples  1.355 sec
sort_values 0.414 sec
get_indices 0.715 sec
sort_values 0.329 sec

将问题规模缩小到您声明的 20 K 项,

get_values  0.034 sec
sort_dicts  0.006 sec
get_tuples  0.005 sec
sort_values 0.001 sec
get_indices 0.002 sec
sort_values 0.001 sec

甚至对于遇到缓存未命中的十倍大的 200 K 项目:

get_values  0.325 sec
sort_dicts  0.105 sec
get_tuples  0.111 sec
sort_values 0.027 sec
get_indices 0.064 sec
sort_values 0.021 sec

很难看出您是如何遇到您所描述的缓慢的。 问题一定有一些看不见的方面:您在慢时钟频率的 CPU 上运行,或者在某种程度上目标主机的缓存很小,或者 DRAM 很慢,或者您正在排序的数据的另一个方面是您还没有向我们透露。 您问题的“填充列表”部分在您发布的代码中并不明显。 您还没有解决像 cython 或 numba 这样的技术是否与您的业务问题相关。 也许您确实遇到了“排序缓慢”的技术问题,但您与我们分享的内容尚未提供证据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM