我有大约1000个文件。每个文件包含约20,000个文档。我还有一个大约1,000,000个单词的列表。
我想计算每个单词与其他单词出现的时间。因此,有一个大小为1M X 1M的稀疏矩阵。
为了加快计算速度,我通过执行以下操作分别处理每个文件:
1-我机器中的每个核心都在处理单个文件并输出以下格式的文件
WordId1 WordId2 Frequency
2-完成每个文件后,我将1000文件合并为一个文件。
这是我目前的方法,但这需要很长时间才能完成,我认为应该有更有效的方法来做到这一点,所以欢迎你的意见。
答案 0 :(得分:2)
我猜你可以通过仔细处理细节来获得合理的表现。有问题的部分看起来是记忆。有足够的内存,你可以避免写出和合并。
处理单个文档时,如果相应的单词存在,则可以在设置每个位时将其转换为BitSet
。
您的关系是对称的,因此我希望您只将(a, b, count)
存储为a < b
。
你需要Multiset<Pair<String, String>>
这样的东西进行计数,但是有更多的内存保存结构。您的文字已编号,因此每个文字都可以用int
表示,一对可以用long
表示。也许像LongIntHashMap这样的东西也可以。您需要并发,因此您可以使用atomics作为条目,也可以将地图划分为N
个部分(通过某些散列,N
大于核心数)并同步。在AtomicIntegerArray
之上构建一些东西应该很容易。
你没有说你的结果是否有可能适合记忆,但如果是这样的话,可能会导致巨大的加速。
字符串编号为0到100万,符合int
。两个这样的数字一起放在long
中,可以用作TLongIntHashMap
的关键字。对于每个文档,您标识所有相关的字符串对,获取相应的long
并增加TLongIntHashMap
中的值。
这里,只需要在锁定下完成增量。由于这种锁定会阻碍并发性,我建议使用多个映射,每个映射都有自己的锁。可以对递增进行分组,以便可以使用单个锁执行多个操作。
更好的解决方案可能是每个单词使用一个TIntIntHashMap
。想象一下,您将文档中找到的所有单词(表示为int
s)放入集合中。然后你可以像这样循环
for (int w1 : words) {
getLock(w1).lock();
TIntIntHashMap map = getMap(w1);
for (int w2 : words) {
if (isLess(w1, w2) map.increment(w2);
}
getLock(w1).unlock();
}
此处,isLess
是一种任意的反对称反自反关系,用于避免同时存储(a, b)
和(b, a)
。虽然只是w1 < w2
会这样做,但它会导致相当不平衡的值(getMap(0)
可能很大而getMap(1000000)
会为空。使用((w1 - w2) ^ ((w1 + w2) << 31)) < 0
应该这样做。
答案 1 :(得分:2)
我做了一些像这样的统计,我把工作分成了两步
步骤1:多线程计数:计算每对的分区ID并直接输出相关的分区文件(partition_id =(md5 of pair)/ partition_count,分区进程是关键点),(我试过hash_map统计数据(当大小大于thread_hold时,将map_data输出到文件,这节省了大量的磁盘空间,并且我把输出文件放在不同的磁盘上,这使得进程加速了很多)
步骤2:多线程合并:合并计数输出步骤1使用map(此过程在内存中完成,如果内存不足,请选择较大的partition_count) 注意:mapreduce是一个简单的工作,step1是map短语,step2是减少短语,关键过程是对应于hadoop减少过程之前的分区部分的分区过程答案 2 :(得分:1)
你在这里达到复杂性的基本规律。您正在尝试为大量单词处理大量文档,并从中生成大量数据集。
它总是很慢。
有些事情可能加快速度:
忘掉一百万字的清单。相反,只要接受文本中找到的任何单词,您就可以随后过滤它们。如果您确实需要对列表进行过滤,请确保列表采用适当的格式(例如HashSet),以便您快速检查。
这种事情更可能是IO绑定而不是CPU绑定,所以尝试在快速SSD驱动器上运行它 - 或者如果文件足够小,则设置一个RAM磁盘并从中运行它。做一些监控以确定瓶颈的位置。
对每组文件的处理就像你已经确定的非常平行一样,所以你可以看看它不只是在多个核心而是在多台机器上传播它。
要尝试的东西(数据库的开销实际上可能会让它变慢): 而不是在最后进行合并,您可以编译结果以在内存中一起处理一个文档。完成处理后,将一个批量插入数据库。然后,数据库将允许您使用sum()等动态查询结果,以查找每个单词组合的总计。这实际上为您提供了比平面文件更灵活/更有用的结果,并避免了单独的合并步骤。