scala:并行集合不起作用?

时间:2011-06-03 01:30:22

标签: scala

我试图通过.par以非常基本的方式使用并行集合 - 我希望集合不按顺序执行,但事实并非如此:

scala> (1 to 10) map println
1
2
3
4
5
6
7
8
9
10

scala> (1 to 10).par map println
1
2
3
4
5
6
7
8
9
10

在后一种情况下,顺序似乎不应该是顺序的。这是scala 2.9,我的机器有2个核心。这可能是某处的错误配置?谢谢!

编辑:我确实尝试使用大集(100k)运行,结果仍然是顺序的。

2 个答案:

答案 0 :(得分:11)

YMMV:

scala> (1 to 10).par map println
1
6
2
3
4
7
5
8
9

这也是双核......

我认为如果你尝试足够的跑步,你可能会看到不同的结果。这是一段代码,展示了一些发生的事情:

import collection.parallel._
import collection.parallel.immutable._

class ParRangeEx(range: Range) extends ParRange(range) {
  // Some minimal number of elements after which this collection 
  // should be handled sequentially by different processors.
  override def threshold(sz: Int, p:Int) = {
    val res = super.threshold(sz, p)
    printf("threshold(%d, %d) returned %d\n", sz, p, res)
    res
  }
  override def splitter = {
    new ParRangeIterator(range) 
        with SignalContextPassingIterator[ParRangeIterator] {
      override def split: Seq[ParRangeIterator] = {
        val res = super.split
        println("split " + res) // probably doesn't show further splits
        res
      }
    }
  }
}

new ParRangeEx((1 to 10)).par map println

一些运行我得到散布处理,一些运行我得到顺序处理。它似乎将负载分成两部分。如果将返回的阈值数更改为11,您将看到工作负载永远不会被拆分。

基础调度机制基于fork-join和work stealing。有关一些见解,请参阅the following JSR166 source code。这可能是驱动同一个线程是否会接收两个任务(因而看起来是顺序的)或者两个线程是否适用于每个任务的原因。

以下是我计算机上的示例输出:

threshold(10, 2) returned 1
split List(ParRangeIterator(over: Range(1, 2, 3, 4, 5)), 
  ParRangeIterator(over: Range(6, 7, 8, 9, 10)))
threshold(10, 2) returned 1
threshold(10, 2) returned 1
threshold(10, 2) returned 1
threshold(10, 2) returned 1
threshold(10, 2) returned 1
6
7
threshold(10, 2) returned 1
8
1
9
2
10
3
4
5

答案 1 :(得分:1)

答案很可能顺序出现;没有保证。在这么小的一套上,你通常会顺序得到它。然而println调用系统调用,如果你运行足够多次,你可能会得到一个混乱的版本。