Python排序消耗了大量的内存? (来自电源发电机)

时间:2013-04-16 19:48:12

标签: python performance sorting memory tuples

我基本上是在寻找可能对此有意见的其他人的反馈。以下不是我正在研究的内容,但示例代码确实重现了这个问题。

我有一个电源设置生成器,如果我正在发送的基本列表,则返回所有排列。我需要对生成的集进行排序(在我的实际情况中,返回的集是具有我想要排序的值的元组通过,下面的例子演示了没有它的问题。

问题是当我在电源设置发生器上使用sorted()时,它会耗尽内存使用量。我意识到2 ^ 50是一个非常大的数字,但没有排序的内存使用是非常平坦的,所以我想知道是否有更好的方法来排序超大量的集合,而不会在一两分钟内耗尽内存。这是在使用Python 2.6.5的Ubuntu上运行的。 (在这种情况下也需要)

def gen_powerset(seq):
    if len(seq) <= 1:
        yield seq
        yield []
    else:
        for i in gen_powerset(seq[1:]):
            yield [seq[0]]+i
            yield i

def main():
    initialSet = range(50)
    powerset = sorted(gen_powerset(initialSet))
    for i in powerset:
        print i

if __name__ == "__main__":
    main()

免责声明:如果您尝试运行此示例,请注意您的内存利用率。 Ctrl-C示例如果它接近90%,因为您的操作系统将开始将内存交换到磁盘。如果样品仍然在运行,那么您的磁盘负载将会出现峰值,并且确实会使速度变慢,从而导致首先难以杀死样品。

3 个答案:

答案 0 :(得分:4)

没有sorted,您永远不需要一次存储超过1或2个值 - 它们是在需要时计算的,因为您使用的是生成器(yield)。不幸的是,没有好的方法可以在不知道整个事情的情况下对列表进行排序(在您查看所有项目之前,您无法从排序中获得值,以确保您拥有该项目有最小的)。

当然,如果你有2个已排序的子列表,你可以懒惰地合并它们,这样你可以构建一个排序,它不会根据合并排序一次性将所有内容存储在内存中,但它在一般情况下会非常低效。

答案 1 :(得分:2)

sorted内存使用率较高的原因是它必须立即将所有项目加载到内存中。由于您编写了一个生成器,它一次只生成一个元素,而您使用它的方式一次只使用一个值,因此Python不需要同时保留所有项目。但是如果没有全部可用的话,你就无法对它们进行排序。

只要您进行排序,就无法解决这个问题,因为排序必须包含所有元素。

解决问题的唯一方法是重写您的powerset生成器,以按您想要的顺序生成项目。根据您想要的顺序,这可能是也可能不可能。

答案 2 :(得分:2)

你正在使用一个只在消耗之前一次创建一个值的生成器,这非常有效。 sorted函数需要将其转换为列表,以便它们一次驻留在内存中。没有办法解决它。