scala中元组的简单并行评估?

时间:2012-10-16 21:07:43

标签: scala concurrency parallel-processing

如果两个表达式e1和e2只处理不可变数据结构,那么并行计算元组(e1,e2)应该很简单,只需要评估不同处理器上的两个表达式,不要担心任何交互,因为不应该有任何。

Scala有很多不可变的数据结构,所以我希望有一种超级简单(写入)的方式来并行评估该元组。像

这样的东西

par_tuple : ( Unit -> T1) -> (Unit -> T2) -> (T1, t2)

并行计算两个函数,并在两个函数完成时返回。

但是,我还没有看到它。它存在吗?如果不是,你会怎么写呢?

1 个答案:

答案 0 :(得分:6)

这取决于被评估的表达式代价高昂。在当前的体系结构中,有两个表达式涉及少数几十个甚至几百个指令,并不能有效地并行评估。因此,您应该始终确保您执行的工作量不会受到并行化本身成本的影响。

考虑到这一免责声明,在Scala 2.10中,您可以使用Future来完成此任务:

val f = future { e1 }
val g = future { e2 }
(Await.result(f), Await.result(g))

请注意,这种计算方式是不受欢迎的(上面的内容是故意过于冗长!),因为它涉及阻塞和阻塞平台,例如JVM,在那里没有有效延续的概念,通常很昂贵(尽管它适用的情况超出了这个答案的范围,可能是这个问题的回答者。在大多数情况下,您应该在将来安装一个回调函数,该函数在其值可用时调用。你可以这样做:

val h = for {
  x <- f
  y <- g
} yield (x, y)

上面的h是一个新的未来,一旦两者都可用,它将包含一个值元组。

您可以将函数par_tuple重写为:

def par_tuple[E1, E2](e1: =>E1, e2: =>E2): Future[(E1, E2)] = {
  val f = future { e1 }
  val g = future { e2 }
  val h: Future[(E1, E2)] = for {
    x <- f
    y <- g
  } yield (x, y)
  h
}

此方法返回所需元组的Future - 一个最终将使用表达式保存元组的对象。您可以使用其他计算进一步构建此未来,或者如果您确定要阻止,则可以使用其他变体:

def par_tuple_blocking[E1, E2](e1: =>E1, e2: =>E2): (E1, E2) = Await.result(par_tuple(e1, e2))

阻止,直到元组将来可用。

请参阅more about futures, callbacks and blocking here