我的问题简要说明:如果一个人不知道任何密钥包含的值的数量,并且一个人不能保存所有密钥,那么是否可以使用一种算法将密钥值对划分为大致相等的长度列表(或同时在RAM中计算它们的值?
我对上下文的问题:我有多个文件包含键/值对,其中键是哈希值,值是给定哈希发生的对象ID列表。相同的密钥在每个文件中都会出现零次或一次,并且很多文件中都会出现一个给定的密钥。
我正在将这些文件读入计算群集中运行的几个工作者。为每个工作人员分配密钥的子集。对于分配了工作程序的每个密钥,该工作程序累积在任何前面提到的密钥/值文件中出现的密钥的所有值。然后,每个工作程序读取所有先前提到的文件,查找每个键的所有值,并将单个输出文件写入磁盘。
我面临的问题是工作人员在分配的密钥中累积了大量不同的值,因此他们的RAM要求完全不同(从低端的33GB到高端的139GB)。现在,要为工作人员分配密钥,我会获取每个密钥的sha1哈希,如果sha1(key) % total_number_of_workers == worker_id
(其中worker id是所有工人中给定工人的索引位置),则为工作人员分配给定密钥。
有没有办法为工作人员分配密钥,这有助于确保节点之间更平等地分配RAM要求?任何其他人可以就此问题提供的建议将不胜感激!
如果其他人可能感兴趣,我将Jim Mischel在Python [gist]中描述的k-way合并的简单实现放在一起。此实现不需要同时在内存中包含所有文本文件,这对于大型数据集来说可能是不可能的。
答案 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]
替换累积数组。
这种情况一直持续到没有其他项目要合并为止。
处理重新填充优先级队列的代码有点繁琐,但并不是很难。
另一种方法是使用操作系统的排序实用程序对文件进行排序和合并,然后编写一个简单的循环,以线性方式遍历单个排序文件以累积值。