【发布时间】:2016-11-04 15:26:05
【问题描述】:
我是 Scala 新手,想构建一个实时应用程序来匹配某些人。对于给定的 Person,我想获得匹配分数最高的 TOP 50 人。
成语如下:
val persons = new mutable.HashSet[Person]() // Collection of people
/* Feed omitted */
val personsPar = persons.par // Make it parall
val person = ... // The given person
res = personsPar
.filter(...) // Some filters
.map{p => (p,computeMatchingScoreAsFloat(person, p))}
.toList
.sortBy(-_._2)
.take(50)
.map(t => t._1 + "=" + t._2).mkString("\n")
在上面的示例代码中,使用了 HashSet,但它可以是任何类型的集合,因为我很确定它不是最优的
问题在于,persons 包含超过 5M 的元素,computeMatchingScoreAsFloat 方法计算一种具有 200 个浮点数的 2 个向量的相关值。在我的 6 核计算机上,这个计算大约需要 2 秒。
我的问题是,在 Scala 中执行这种 TOPN 模式的最快方法是什么?
子问题: - 我应该使用什么集合(或其他东西?)的实现? - 我应该使用期货吗?
注意:它必须并行计算,仅计算computeMatchingScoreAsFloat(没有排名/TOP N)的纯计算需要超过一秒,如果我是多线程的,则
编辑:感谢 Guillaume,计算时间从 2 秒减少到 700 毫秒
def top[B](n:Int,t: Traversable[B])(implicit ord: Ordering[B]):collection.mutable.PriorityQueue[B] = {
val starter = collection.mutable.PriorityQueue[B]()(ord.reverse) // Need to reverse for us to capture the lowest (of the max) or the greatest (of the min)
t.foldLeft(starter)(
(myQueue,a) => {
if( myQueue.length <= n ){ myQueue.enqueue(a);myQueue}
else if( ord.compare(a,myQueue.head) < 0 ) myQueue
else{
myQueue.dequeue
myQueue.enqueue(a)
myQueue
}
}
)
}
谢谢
【问题讨论】:
-
您对此进行了基准测试吗? computeMatchingScoreAsFloat 是最昂贵的部分吗?它是否足够重,值得并行化?
-
是的,它必须并行计算,computeMatchingScoreAsFloat(没有排名/TOP N)的纯计算需要超过一秒,如果在我的计算机上使用多线程则需要 40 毫秒
标签: scala collections parallel-processing