首页 > 解决方案 > scala count word co-occurrence 性能真的很低

问题描述

当我尝试实现一个函数来计算 scala 中的单词共现时,我发现我的函数性能非常低。

词co-occurrences是:
也就是说我们有一个List[List[Int]](实际上是一个单词列表的列表),
我们会为每个List[Int]生成一个组合,
然后我们将所有组合合并成一个map并求和每个重复键的值。

组合:
[0,1,2] -> [((0,1),1),((0,2),1),((1,2),1)]

合并组合:
[((0,1),1),((0,2),1),((1,2),1)] + [((0,1),1),((0, 2),1),((1,2),1)] =
HashMap{(0,1):2,(0,2):2,(1,2):2}

这是斯卡拉版本:

val arr = Array.range(0, 1000)
val counter = scala.collection.mutable.HashMap[(Int, Int), Int](  )
arr.combinations(2).toArray.map{
    row=>
        val key = (row(0), row(1))
        if (!counter.contains(key)) {
            counter(key) = 1
        }
        else {
            counter(key) += 1
        }
}
assert(counter.size == 499500)

斯卡拉版本 2:

val counter = arr.combinations(2).map(x => ((x(0),x(1)), 1)).toArray
.groupBy(_._1).mapValues(_.map(_._2).sum)

这是python版本:

import itertools    
arr = range(0, 1000)
combs = list(itertools.combinations(arr, 2))
counter = dict()
for key in combs:
    try:
        counter[key] += 1
    except KeyError:
        counter[key] = 1
assert len(counter) == 499500

两个 scala 版本都需要 9 秒,而 python 版本需要 1 秒。
我认为我肯定在代码上做错了,但我想不出其他方法来改进它(我对 scala 很陌生)。

另外,我使用 mutable.HashMap 的原因是我想减少内存使用量。

任何帮助将不胜感激,谢谢。

标签: pythonscalaperformance

解决方案


您需要转换arr为并行集合。理想情况下,到 RDD。因此,创建一个 spark 上下文,从您的数组中获取一个 RDD,如下所示,然后在其上运行您的操作。

val arr: RDD[Int] = sparkContext.parallelize(Array.range(0, 1000))

你真的应该看看一些教程


推荐阅读