Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何处理包含2^50个元素的dict变量?_Python_Dictionary_Hash_Ram_Hash Collision - Fatal编程技术网

Python 如何处理包含2^50个元素的dict变量?

Python 如何处理包含2^50个元素的dict变量?,python,dictionary,hash,ram,hash-collision,Python,Dictionary,Hash,Ram,Hash Collision,我必须找到2^25个随机字符串的SHA256哈希。然后寻找冲突(使用生日悖论作为最后一个,比如说,仅50位散列) 我将字符串:散列对存储在dict变量中。然后使用值(不是键)对变量进行排序,然后使用O(n)循环查找冲突 问题是,因为有2^25个字符串及其2^25个哈希,所以dict变量中有2^50个值。这是一项资源极其密集的工作。那么,在内存有限的情况下,比如说1GB左右,我如何做到这一点呢 我已经尝试过的: 1.使用6GB交换空间运行此功能。程序运行了一夜,但仍然没有完成。这实际上比O(n_s

我必须找到2^25个随机字符串的SHA256哈希。然后寻找冲突(使用生日悖论作为最后一个,比如说,仅50位散列)

我将字符串:散列对存储在dict变量中。然后使用值(不是键)对变量进行排序,然后使用O(n)循环查找冲突

问题是,因为有2^25个字符串及其2^25个哈希,所以dict变量中有2^50个值。这是一项资源极其密集的工作。那么,在内存有限的情况下,比如说1GB左右,我如何做到这一点呢

我已经尝试过的:
1.使用6GB交换空间运行此功能。程序运行了一夜,但仍然没有完成。这实际上比O(n_square)搜索还要慢!哈希值是使用大约3.2 GB的RAM使用率计算的。但在那之后,当涉及到排序命令时,所使用的RAM再次启动!我认为python排序使用就地快速排序:(
2.我只存储了哈希值,发现了冲突。但是找不到相应的字符串,因为我没有存储它

我不应该使用数据库等。最多是一个文本文件,但这没有帮助。此外,我对Python非常陌生,但不要让这限制了你的答案的水平

PS:这是一项作业。有些人声称在不到一分钟的时间内发现了300MB内存的碰撞。不知道这是不是真的。我已经解决了这个问题,但无法找到答案! 正在工作,所以现在无法访问代码。将很快添加

代码:


为什么不使用从散列的最后50位到字符串的字典呢?

将散列拆分为10个字符的一组。然后嵌套这些值,这样可以进行递归搜索,但速度应该更快一些

我会这样做:

打开16个文件(以二进制模式打开应该可以;如果所有字符串的长度相同,这将是最简单的)。生成字符串和散列,并根据散列的前4位将它们写入文件。然后分别加载和处理每个文件。这将减少16倍的内存使用。(当然,只要不耗尽文件句柄,您可以使用任意数量的文件。每次访问都必须打开和关闭每个文件会变得相当缓慢。)


如果生成字符串和散列相对便宜,您甚至不需要文件。只需进行16次传递,并且在每次传递中只保留与传递号匹配的上半字节的散列。

解决此问题的一种方法是使用很长的位字段,以便每个散列都映射到
2^25
长内存块

解决这类问题的一种更好的非100%保证方式是通过或其他概率数据结构

Bloom筛选器是一种节省空间的概率数据结构,用于测试元素是否为集合的成员。可能出现误报,但不会出现误报;即查询返回“集合内(可能错误)”或“集合内绝对不存在”

Bloom过滤器在表示集合方面比其他数据结构具有强大的空间优势,例如自平衡二进制搜索树、尝试、哈希表或简单数组或条目链接列表

误差为1%的Bloom过滤器每个元素只需要大约9.6位,而不管元素的大小


因此,每2^25个元素9.6位,只需要38.4MIB的内存。

我认为这里的关键洞察——我承认我一直在回避,直到几小时后我才回到这个问题——是
sha256
哈希摘要是它自己的哈希。换句话说,你不必再做任何额外的哈希或集合创建。你所要做的一切正在创建一个自定义哈希表,使用
sha256
摘要作为哈希。为了节省空间,不存储字符串,只需创建一个位数组(对使用
table=numpy.zero(table_size/bits_per_int+1,dtype='i')创建的整数数组中的整数使用移位操作)
)检测冲突,然后将冲突字符串保存在dict映射中,将哈希映射到字符串,以便在第二次传递中查找

table_size
应该是一个大素数——我选择了一个略大于2**31的素数,这是268MB的表——因为这将产生很少的新冲突/误报(由哈希上的模运算引入)。您可以将字符串本身保存到文本文件中,并可以对其进行迭代

因此,对于任何字符串,要设置的对应位的索引将是
index=int(hashlib.sha256('foo').hexdigest(),base=16)%table_size
。然后计算
主索引=索引/bits_in_int
次索引=索引%bits_in_int
,在
次索引
上使用移位和按位操作检查并存储
表[主索引]
的int中的正确位,依此类推

现在遍历字符串。每当字符串生成一个映射到已设置位的哈希时,在字典中存储一个
hash:string
对。或者更好的是,存储一个
hash:[string\u list]
对,在多次冲突的情况下将新字符串追加到列表中。现在,对于任何冲突的字符串对(a,b),字典将包含散列和值b。然后再次遍历字符串,依次对每个字符串进行散列,并检查字典中的每个散列。如果散列在字典中,而字符串不在相应的列表中,请将该字符串添加到列表中。字典中的某些字符串将不对应于真正的c大多数散列的
[string\u list]
长度只有一项,而那些
散列:[string\u list]
对可能会被丢弃。其他可能是由哈希函数本身而不是模运算导致的真实冲突。但是,您可能仍有一些误报需要剔除
from Crypto.Hash import SHA256
import os
import random
import string
from operator import itemgetter

def shaa():

    trun=[]
    clist={}
    for i in range(0,33554432):

        sha=SHA256.new(str(i)).hexdigest()
        sha=int(bin(int(sha,16))[-50:],2)
        clist[i]=sha

    print 'Hashes done.'

    clist=sorted(clist.items(), key=itemgetter(1))  
    for i in range(0,33554432):

        if(clist[i]==clist[i+1]):
            #print string[i],string[i+1]
            print clist[i]
            return 1
    return 2

result=2
while(result==2):
    result=shaa()