可扩展的seq - > groupby - >计数

时间:2015-02-08 23:45:24

标签: algorithm f#

我有一个非常大的无序序列的int64s - 关于O(1B)条目。我需要生成元素的频率直方图,即:

inSeq
|> Seq.groupBy (fun x->x)
|> Seq.map (fun (x,l) -> (x,Seq.length l))

我们假设我只有1GB的RAM可供使用。完整的结果映射将不适合RAM(我也不能在RAM中动态构建它)。所以,当然我们必须在磁盘上生成结果。有哪些高效的方法可以产生结果? 我尝试过的一种方法是对输入值范围进行分区,并通过对数据的多次传递来计算每个分区内的计数。这很好但我想知道我是否可以在一次通过中更快地完成它。

最后一点是频率是幂律分布的。即列表中的大多数项目仅出现一次或两次,但非常少量的项目可能超过100k或1M。这表明可能会维护某种LRU映射,其中常见项目保存在RAM中,而不常见的项目则转储到磁盘上。

F#是我的首选语言,但我可以使用别的东西来完成工作。

1 个答案:

答案 0 :(得分:1)

如果你有足够的磁盘空间来存储输入数据的副本,那么你的多次传递想法实际上只需要两个。在第一遍中,读取元素x并将其附加到临时文件hash(x) % k,其中k是分片数(使用足以使第二遍成为可能)。在第二遍中,对于每个临时文件,使用主存储器计算该文件的直方图,并将该直方图附加到输出。相对于数据的大小,一千兆字节的主内存应该是足够的缓冲区空间,成本大约是读取和写入数据两次的成本。