Scala-以线程安全的方式从parallel for访问阵列
我有以下代码:Scala-以线程安全的方式从parallel for访问阵列,scala,Scala,我有以下代码: //variable arrayToAccess is an array of integers //anotherArray holds integers also anotherArray.par.foreach{ item => val mathValue = mathematicalCalculation(item) if (mathValue > arrayToAccess.last) { //append element
//variable arrayToAccess is an array of integers
//anotherArray holds integers also
anotherArray.par.foreach{ item =>
val mathValue = mathematicalCalculation(item)
if (mathValue > arrayToAccess.last) {
//append element
arrayToAccess :+= mathValue
//sort array and store it in the same variable
arrayToAccess = arrayToAccess.sortWith((i1,i2) => i1 > i2).take(5)
}
}
我认为以这种方式访问arrayToAccess变量不是线程安全的。如何以线程安全的方式实现上述代码?另外,我能控制另一个AARAY.PAR的并行级别(例如,只使用8个可用的2个内核)?如果没有,有办法控制它吗?你想得太多了。
只要做:
arrayToAccess = anotherArray.par
.map { mathematicalCalculation _ }
.seq
.sorted
.reverse
.take(5)
它产生的结果与代码预期的结果相同,但是线程安全的
更新如果您担心排序步骤所需的时间,您可以选择线性时间中的前五位:
val top(data: Array[Int], n: Int) = {
val queue = PriorityQueue()(Ordering[Int].reverse)
data.fold(queue) { case(q,n) =>
q.enqueue(n)
while(q.size > 5) q.dequeue
queue
}
.toArray
.sorted
.reversed
关于配置并行性,我认为这应该有帮助:
更新如果您关心排序步骤,可以将其替换为并行排序或在线性时间内折叠到有界优先级队列中,如下所示:
def topN(data: Array[Int], n: Int) = {
val queue = PriorityQueue()(Ordering[Int].reverse)
data.foldLeft(queue) { case (q, x) =>
q.enqueue(x)
while(q.size > n) q.dequeue
q
}.dequeueAll.reverse
.seq.sorted.reverse.take(5)
如果另一个数组变量很大,则sorted方法和reverse方法需要时间,不是吗?特别是如果它是一个更复杂的排序方法。@Sonex,它不再比原始数组“庞大”。考虑一下,如果后者是“巨大”的,那么你的方法会对输出进行排序并重新排序一个“巨大”的次数。这可能不会比对合并结果进行一次排序快多少。如果你关心并行性,你可以使用并行排序和合并(有限制),但我认为这太过分了。@Sonex或只是。在线性时间内将折叠成一个(有限制的)PriorityQueue
。你能解释一下你最后的评论吗?