【问题标题】:Memory overflow in numpy boolean arraynumpy布尔数组中的内存溢出
【发布时间】:2017-11-20 11:57:16
【问题描述】:

我正在尝试创建一个大型布尔数组(用于素数筛)。我使用了第一个 Python 列表,但在 limit = 10^9 这创建了一个 MemoryError

boolarray = [True] * limit

然后我了解了 Numpy 并读到它在空间组织方面更好,所以我尝试了

boolarray = np.full(limit, True, dtype = bool)

限制只是略微增加到10^10,这还不够,因为我需要10^12。我觉得这很令人惊讶,你只需要一点布尔值,不是吗?任何想法,如何克服这个问题?提前致谢。

【问题讨论】:

  • Docs: bool_ Boolean (True or False) stored as a byte。现在我让其他人/你对这个设计决策进行一些研究。它与 CPU 架构和预期用例高度相关。
  • 好吧,我可能犯了一个错误,所以您需要验证一下:)(我将这个数字计算为10**12 / (8 * 1024**3))。除非你有大量的 ram,否则你可能应该寻找不同的方法。
  • @Piinthesky 你可能会觉得this answer 很有趣。它讨论了有效存储素数的方法。但是,我不确定这是否有助于首先生成它们...
  • 优秀。这也是我一直在思考的事情。以防万一其他人对编程不太感兴趣,只想有一个实用的解决方案 - 有像 primesieve.org 这样的 C 库。
  • primesieve 库也有Python bindings

标签: python python-3.x numpy boolean


【解决方案1】:

让我们抛开 10^12 位可能不容易放入内存的事实。如果您更关心内存使用而不是性能,您可以将这些位打包到一个字节数组中。这是以读取/写入位时的额外计算为代价的(这就是 numpy 将布尔值存储为字节的原因)。

import numpy as np


def getbit(bitarray, index):
    i, j = index // 8, index % 8
    x = bitarray[i]
    return x & (1 << j) != 0


def setbit(bitarray, index, value):
    value = bool(value)
    i, j = index // 8, index % 8
    x = bitarray[i]
    bitarray[i] ^= (np.uint(-value) ^ x) & (1 << j)


n = 10**5 // 8
bitarray = np.zeros(n, dtype=np.uint8)  # initialize all bits to 0

print(getbit(bitarray, 19))  # False

setbit(bitarray, 19, True)
print(getbit(bitarray, 19))  # True

setbit(bitarray, 19, False)
print(getbit(bitarray, 19))  # False

【讨论】:

  • 感谢您的解释和示例。在我发现 Python 函数sum() 之前,从我的第一个自写求和函数的经验说起:我认为这些操作意味着更多的计算时间,因为它们不会直接向 Python 提供参数以在它们的内部有效地处理数据用 C 编写的库。如果这是真的,那么恐怕这意味着回到绘图板上。
  • @Piinthesky Jep,如果你经常调用这些函数——我假设你这样做了——你会注意到解释器的开销。无论如何,这并不能解决将 10^12 位压缩到 ram 中的问题,但我认为无论如何都值得回答这个问题,因为它对其他人也有用。
  • 我把它标记为一个好的答案,因为它表明我走错了路。这对我(也许对其他人)来说是有价值的信息。
猜你喜欢
  • 2011-04-12
  • 2010-12-30
  • 2021-01-06
  • 1970-01-01
  • 2016-12-08
  • 2016-03-11
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
相关资源
最近更新 更多