使用太多内存的大规模Python整数集

时间:2010-11-09 09:37:21

标签: python set memory-management

设置

  • Python 2.6
  • Ubuntu x64

我有一组唯一的整数,其值介于1到5千万之间。随机添加新的整数,例如numberset.add(random.randint(1, 50000000))。我需要能够快速添加新的整数并快速检查是否已存在整数。

问题

过了一会儿,这个集合对我的低内存系统来说变得太大了,我遇到了MemoryError

问题

如何在使用更少内存的同时实现这一目标?在没有重新配置系统的情况下使用磁盘执行此操作的最快方法是什么?交换文件?我应该使用像sqlite这样的数据库文件吗?是否有一个库将压缩内存中的整数?

6 个答案:

答案 0 :(得分:5)

使用bit-array。这将减少对巨大空间需求的需求。

已故问题:

答案 1 :(得分:5)

您可以通过自己编写来避免对第三方位阵列模块的依赖 - 所需的功能相当小:

import array

BITS_PER_ITEM = array.array('I').itemsize * 8

def make_bit_array(num_bits, initially=0):
    num_items = (num_bits + BITS_PER_ITEM - 1) // BITS_PER_ITEM
    return array.array('I', [initially]) * num_items

def set_bit(bit_array, offset):
    item_index = offset // BITS_PER_ITEM
    bit_index = offset % BITS_PER_ITEM
    bit_array[item_index] |= 1 << bit_index

def clear_bit(bit_array, offset):
    item_index = offset // BITS_PER_ITEM
    bit_index = offset % BITS_PER_ITEM
    bit_array[item_index] &= ~(1 << bit_index)

def get_bit(bit_array, offset):
    item_index = offset // BITS_PER_ITEM
    bit_index = offset % BITS_PER_ITEM
    return (bit_array[item_index] >> bit_index) & 1

答案 2 :(得分:2)

使用位数组作为每个整数的标志 - 所需的内存将只有5000万位(大约6 MB)。有一些模块可以提供帮助。此示例使用bitstring,另一个选项是bitarray

from bitstring import BitArray
i = BitArray(50000000) # initialise 50 million zero bits
for x in xrange(100):
    v = random.randint(1, 50000000)
    if not i[v]: # Test if it's already present
        i.set(1, v) # Set a single bit

设置和检查位非常快,并且使用的内存非常少。

答案 3 :(得分:1)

尝试使用数组模块。

答案 4 :(得分:0)

如果整数是唯一的,则使用位。示例:binary 01011111表示存在:1,3,4,5,6和7.这样,每个位用于检查是否使用了整数索引(值1)或不使用(值0)。

one chapter of "Programming Pearls" by Jon Bentley中对此进行了描述(查找“该文件最多包含一千万条记录;每条记录都是一个七位整数。”)

似乎Emil提到的bitarray模块以这种方式工作。

答案 5 :(得分:0)

根据您的要求,您可能还会考虑bloom filter。它是一种内存高效的数据结构,用于测试元素是否在集合中。问题在于它可以给出假阳性,但它永远不会给出假阴性。