下面的Haskell代码使用par
和pseq
作为玩具进行多核数字运算,以显示正在使用的多个核心。在Scala中表达这个最简单,最惯用的方法是什么?期货和承诺似乎很有希望(咳咳),我一直在关注scalaz.concurrent
,例如this example,但我找不到文档来解释这一切。
import Control.Parallel
main = a `par` b `par` c `pseq` print (a + b + c)
where
a = ack 3 10
b = fac 42
c = fib 35
fac 0 = 1
fac n = n * fac (n-1)
ack 0 n = n+1
ack m 0 = ack (m-1) 1
ack m n = ack (m-1) (ack m (n-1))
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
答案 0 :(得分:4)
您可以在Scala中翻译您的示例,如下所示:
import concurrent.{Await, Future, future}
import concurrent.ExecutionContext.Implicits.global
import concurrent.duration.Duration
object Main extends App {
val fac: Int => Int = {
case 0 => 1
case n => n * fac(n-1)
}
val ack: (Int, Int) => Int = {
case (0, n) => n + 1
case (m, 0) => ack (m-1, 1)
case (m, n) => ack (m-1, ack(m, n-1))
}
val fib: Int => Int = {
case 0 => 0
case 1 => 1
case n => fib(n-1) + fib(n-2)
}
val fa = future { ack(3, 10) }
val fb = future { fac(42) }
val fc = future { fib(35) }
val x = for (((a, b), c) <- fa zip fb zip fc) yield (a + b + c)
val result = Await.result(x, Duration.Inf) //awaiting synchronously after the result
println(s"Value is: $result")
}
future { fib(3, 10) }
位将创建一个异步计算,它将在不同的执行线程上运行并返回一个Future
对象。然后,您可以使用Future.sequence
将所有未来组合成一个大的未来,这将提供所有结果的列表。
我们可以将后一个未来的结果映射到结果的总和,从而获得最终值。
在最后的未来,我们可以做几件事。我们可以进一步组合它,或者我们可以在其上附加回调,或者我们可以在指定的持续时间内同步等待。在我的例子中,我在结果之后以同步的方式等待了无限的时间。
答案 1 :(得分:1)
我建议您使用期货,因为它们是2.10以来的标准库的一部分,非常容易使用。我不会移植你的代码,而是给你一个例子,以便你明白。
// not tailrec, will stack overflow for larger numbers
def fib(x: Int): Int = x match {
case 0 | 1 => x
case x => fib(x-1) + fib(x-2)
}
import scala.concurrent._
import ExecutionContext.Implicits.global
// create all the futures
val futures = Seq(future(fib(3)), future(fib(4)), future(fib(5)))
// make a Future[Seq[Int]] out of Seq[Future[Int]] and sum the ints
val sumFuture = Future.sequence(futures).map(_.sum)
// if the future is completed successfully print the result
sumFuture.onSuccess {
case x => println(x)
}