我有要同时执行的任务,每个任务都需要大量内存,所以我必须分批执行它们才能节省内存。
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
获得正确的结果?感谢
答案 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{...