在itertools.combinations命令

时间:2018-07-03 11:42:06

标签: python jupyter-notebook itertools

我正在使用 Python 3.5.2 | Anaconda 4.3.0(x86_64)| (默认值,2016年7月2日,17:52:12) [与GCC 4.2.1兼容的Apple LLVM 4.2(clang-425.0.28)]

我必须运行以下命令

longList = list(combinations(range(2134), 3))

我知道这大约需要16亿美元。当我运行它时,一段时间后,我收到消息“内核似乎已经死亡。它将自动重新启动。”

运行3而不是2的同一命令没有任何问题:

longList = list(combinations(range(2134), 2))

在这种情况下我该怎么办?

1 个答案:

答案 0 :(得分:0)

您可能用完了内存。快速计算:64位int或指针为8个字节大。您有16亿个组合,它们是元组。每个元组包含三个整数。这意味着您至少需要1.6E9 *(1 + 3)* 8B = 48GB内存。

但是,由于Python的内存模型,您将需要的次数更多:每个整数实际上是一个对象,因此我们需要1个机器字作为列表中的指针,并可能需要3或4个机器字作为对象本身(我不确定细节,请阅读CPython源文件中的实际对象布局)。元组对象也将有开销。我假设每个对象的开销为两个字。因此,我们必须增加额外的1.6E9 *(3 +1)* 2 * 8B = 95GB的额外开销,总计约为143GB。

这可以通过使用密集的numpy数组来避免,因为它使用实数而不是对象。这消除了整数和元组对象的所有开销,因此我们将“仅”需要1.6E9 * 3 * 8B = 35GB。

我认为您运行的内存不足。

您的combinations(..., 2)调用不成问题,因为它仅产生大约200万个元组,其内存需求在兆字节范围内(2.2E6 *(1 + 4 + 2 * 3)* 8B = 180MB)。作为一个numpy数组,我们只需要2.2E6 * 2 * 8B = 33MB。

那这里的解决方案是什么?

  • 从规模上讲,即使对于Python,底层模型细节(例如内存模型)也非常重要
  • 使用numpy可以大幅度减少内存使用量,通常减少4倍。如果使用较小的类型(例如,dtype='int16',则减少4倍。)
  • 认真思考是否需要将combinations()转换为列表,还是可以懒散地或以较小的块使用迭代器