【发布时间】:2017-10-24 10:44:17
【问题描述】:
在并行序列上映射时,Scala 似乎为每个计划的计算元素分配了一个固定的 CPU 内核,然后防止这个初始分配发生变化。
List(a, b, c, d, e, f, g, h, i, j, k, l).par.map(someComputation)
// (Simplified) initial assignment for a 2-cores machine:
// Core 1: a, b, c, d, e, f
// Core 2: g, h, i, j, k, l
问题是,如果 (a .. f) 非常快,而 (g .. l) 每个需要 1 小时,我们最终会导致 Core 1 闲置 6 小时,而 Core 2 则试图完成其工作。
有没有办法进行并行计算,如果 Core X 空闲并且还有未启动的作业,则向 Core X 提供这些作业之一?
编辑
要重现,请启动 Scala REPL 并输入:
scala> :paste
def compute(x: Int) = {
if (x > 10)
(0 to 10e9.toInt).foreach(n => n + 1) // loads 100% of a core for 4-5 seconds on a typical iMac
println(x)
x * 2
}
// hit Ctrl+D
compute: (x: Int)Int
scala> def foo = (0 to 20).toList.par.map(compute)
foo: scala.collection.parallel.immutable.ParSeq[Int]
scala> foo
然后看看会发生什么。一开始,所有核心都处于 100%,随着您的进步,您可以清楚地看到每个进程在开始之前就分配了自己的核心。即使另一个内核当前空闲,它也不会更改内核。到最后,只有一两个核心处理队列中的所有剩余作业,而其他 3 个或更多核心闲置的情况并不罕见(取决于初始分配)。
【问题讨论】: