将键值对划分为相等的列表,而无需访问键值计数

时间:2018-05-30 23:41:39

标签: algorithm hash

我的问题简要说明:如果一个人不知道任何密钥包含的值的数量,并且一个人不能保存所有密钥,那么是否可以使用一种算法将密钥值对划分为大致相等的长度列表(或同时在RAM中计算它们的值?

我对上下文的问题:我有多个文件包含键/值对,其中键是哈希值,值是给定哈希发生的对象ID列表。相同的密钥在每个文件中都会出现零次或一次,并且很多文件中都会出现一个给定的密钥。

我正在将这些文件读入计算群集中运行的几个工作者。为每个工作人员分配密钥的子集。对于分配了工作程序的每个密钥,该工作程序累积在任何前面提到的密钥/值文件中出现的密钥的所有值。然后,每个工作程序读取所有先前提到的文件,查找每个键的所有值,并将单个输出文件写入磁盘。

我面临的问题是工作人员在分配的密钥中累积了大量不同的值,因此他们的RAM要求完全不同(从低端的33GB到高端的139GB)。现在,要为工作人员分配密钥,我会获取每个密钥的sha1哈希,如果sha1(key) % total_number_of_workers == worker_id(其中worker id是所有工人中给定工人的索引位置),则为工作人员分配给定密钥。

有没有办法为工作人员分配密钥,这有助于确保节点之间更平等地分配RAM要求?任何其他人可以就此问题提供的建议将不胜感激!

如果其他人可能感兴趣,我将Jim Mischel在Python [gist]中描述的k-way合并的简单实现放在一起。此实现不需要同时在内存中包含所有文本文件,这对于大型数据集来说可能是不可能的。

1 个答案:

答案 0 :(得分:2)

这是一个简单的k-way merge。我们假设您有三个文件:

git-worktrees

现在,您对这些文件进行排序:

File 1     File 2     File 3
A=3        B=7        C=22
X=9        B=4        D=19
Q=33       Z=26       A=2
X=47       X=12       D=13

您可以执行合并步骤并以单个文件结束:

Sorted1    Sorted2    Sorted3
A=3        B=7        A=2
Q=33       B=4        C=22
X=9        X=12       D=19
X=47       Z=26       D=13

然后扫描该文件,累积并写入值。

但是你可以一步完成合并和积累。毕竟,当您进行合并时,您将按排序键顺序输出内容,因此您只需在输出步骤之前插入累积代码。

单个进程启动并创建一个包含每个文件中第一个项目的优先级队列。因此优先级队列将包含A=3 A=2 B=7 B=4 C=22 D=19 D=13 Q=33 X=9 X=47 X=12 Z=26 。程序从优先级队列中获取最小的密钥A = 3,并使用第一个已排序文件中的下一个项刷新队列。该队列现在包含[A=3, B=7, A=2]

程序使用键A创建一个新数组,其中包含值[Q=33,B=7,A=2]。然后它再次进入队列并读取最小值:A = 2。它看到密钥等于它正在处理的密钥,因此它将数组更新为[3]。队列将从已排序的文件中刷新,因此现在它包含[3,2]

程序再一次从队列中获取最小的键值。这次它的B. B不等于A,所以程序输出[Q=33,B=7,C=22],用B替换当前的密钥,并用A,[3,2]替换累积数组。

这种情况一直持续到没有其他项目要合并为止。

处理重新填充优先级队列的代码有点繁琐,但并不是很难。

另一种方法是使用操作系统的排序实用程序对文件进行排序和合并,然后编写一个简单的循环,以线性方式遍历单个排序文件以累积值。