在一系列运行中使用Scala Collection par返回不同的结果

时间:2015-03-12 09:13:23

标签: scala

我有要同时执行的任务,每个任务都需要大量内存,所以我必须分批执行它们才能节省内存。

def runme(n: Int = 120) = (1 to n).grouped(2).toList.flatMap{tuple =>
    tuple.par.map{x => {
        println(s"Running $x")
        val s = (1 to 100000).toList // intentionally to make the JVM allocate a sizeable chunk of memory
        s.sum.toLong
    }}
}

val result = runme()
println(result.size + " => " + result.sum)

我从输出中得到的结果是120 => 84609924480,但输出相当随机。返回的集合大小因执行而异。大多数时候,即使所有的期货都是在控制台上执行的,也会丢失计数。我认为flatMap等待map中的并行执行完成后才能返回完成。我应该怎样做才能始终使用par获得正确的结果?感谢

2 个答案:

答案 0 :(得分:1)

仅供记录:在这种情况下更改基础集合不应更改程序的输出。问题与这个已知的bug有关。它是从2.11.6修复的,所以如果你使用那个(或更高版本的)Scala版本,你不应该看到这种奇怪的行为。

关于溢出,我仍然认为你的预期价值是错误的。您可以检查总和是否溢出,因为列表是整数(32位),而总和超过整数限制。您可以使用以下代码段进行检查:

val n = 100000

val s = (1 to n).toList // your original code
val yourValue = s.sum.toLong // your original code

val correctValue = 1l * n * (n + 1) / 2 // use math formula

var bruteForceValue = 0l // in case you don't trust math :) It's Long because of 0l
for (i ← 1 to n) bruteForceValue += i // iterate through range

println(s"yourValue       = $yourValue")
println(s"correctvalue    = $correctValue")
println(s"bruteForceValue = $bruteForceValue")

产生输出

yourValue       = 705082704
correctvalue    = 5000050000
bruteForceValue = 5000050000

干杯!

答案 1 :(得分:0)

谢谢@kaktusito。

我将分组列表更改为Vector或Seq,即(1 to n).grouped(2).toList.flatMap{...(1 to n).grouped(2).toVector.flatMap{...

后,它工作了