我有一个非常大的文本文件集。任务是计算这个庞大语料库中所有术语(唯一地)的文档频率(包含某个术语的文档数量)。简单地从第一个文件开始并以序列化的方式计算所有内容似乎是一件愚蠢的事情(我承认我这样做只是为了看看它有多糟糕)。我意识到,如果我以Map-Reduce的方式进行计算,这意味着将我的数据聚类成更小的部分,并最终聚合结果,我将更快地得到结果。
我的PC有4个核心,所以我决定将我的数据分成3个不同的子集,并将每个子集提供给一个单独的线程,等待所有线程完成他们的工作,并将他们的结果传递给另一个方法来聚合一切。
我用一个非常小的数据集测试它,工作良好。在使用实际数据之前,我用更大的数据集进行了测试,以便更好地研究它的行为。我启动了jvisualvm和htop,看看cpu和内存是如何工作的。我可以看到3个线程正在运行,cpu内核也很忙。但这些核心的使用率很少超过50%。这意味着我的应用程序并没有真正使用我的PC的全部功能。这是有关我的代码,或这是如何应该是。我的期望是每个线程使用尽可能多的cpu核心资源。
我用Ubuntu
听起来你有一个IO绑定的应用程序。你花费更多的时间在你的单个线程读取磁盘上的数据,而不是你实际处理读取的信息。
您可以通过将程序迁移到另一个带有SSD的系统来测试这一点,看看CPU性能是否发生了变化。您还可以读入所有文件,然后稍后处理它们,看看这是否会改变处理期间的CPU曲线。我想会的。
如前所述,您遇到了瓶颈,可能是磁盘IO。尝试将从磁盘读取数据的代码与处理数据的代码分开,并为每个代码使用单独的线程池。之后,快速扩展线程池以适当适应资源的一个好方法是使用executor线程池之一。
在单个机器上处理这样的问题是IO受限的,而不是CPU受限的。你在积极阅读文件吗?只有当所有文件都在内存中时,CPU才会开始饱和。这就是为什么map-reduce是有效的。
如果您在Linux上使用tmpfs将数据存储在内存中,而不是磁盘上,则可能会大大加快此速度。