【问题标题】:Easy parallel evaluation of tuples in scala?scala中元组的简单并行评估?
【发布时间】:2012-10-16 21:07:42
【问题描述】:

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

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

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

并行计算两个函数,并在两者都完成后返回。

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

【问题讨论】:

    标签: scala concurrency parallel-processing


    【解决方案1】:

    这取决于被评估的表达式的costly。在当前架构上,两个表达式涉及几条到几十条甚至数百条指令,无法有效地并行计算。因此,您应该始终确保您正在执行的工作量不会被并行化本身的成本所掩盖。

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

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

    请注意,不鼓励这种类型的计算(上面故意过于冗长!),因为它涉及阻塞,并且在没有有效延续概念的 JVM 等平台上阻塞通常代价高昂(尽管适用的情况超出了此答案的范围,可能超出了此回答者的范围)。在大多数情况下,您应该在 future 上安装一个回调,一旦它的值可用,就会调用它。你可以这样做:

    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

    【讨论】:

    • 是的,当然,对于某些操作,并行性并不划算。我的意思是简单的写。如果我理解正确,我想要的具体函数会写成: def par_tuple[T1, T2](e1 : Future[T1], e2 : Future[T2]) : (T1, T2) = for {x
    • 你有更多关于为什么阻止不好的链接吗?
    • 为什么不只使用一个 Future 而另一个在主线程上工作?
    • 捎带调用者线程可能会更有效,是的。至于阻塞,如果您的应用程序只是偶尔阻塞评估并行表达式的结果,那么它可能没问题。但是,如果您的应用程序经常阻塞评估此类表达式,那么性能将大大下降。
    • 阻塞 / 不 / 本质上是邪恶的。这是一个常见的谬误,来自那些不了解缺乏过度并行性的影响的人。阻塞 IO 操作将严重损害单线程程序。所以问题在于程序设计是错误的,而不是阻塞是邪恶的。我们可以更进一步:非阻塞程序不是事件驱动的,因此从并发的角度来看可能更难推理。因此,可能会提出相反的论点,即非阻塞是邪恶的。 (我这么说部分是开玩笑,但重点是这些都是重要的设计问题。)
    猜你喜欢
    • 1970-01-01
    • 2010-11-14
    • 2013-05-17
    • 1970-01-01
    • 2017-12-28
    • 2021-08-28
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多