【问题标题】:Is there an implementation of rapid concurrent syntactical sugar in scala? eg. map-reducescala中是否有快速并发语法糖的实现?例如。地图减少
【发布时间】:2011-02-13 07:41:39
【问题描述】:

与演员一起传递信息很棒。但我想要更简单的代码。

示例(伪代码)

val splicedList:List[List[Int]]=biglist.partition(100)
val sum:Int=ActorPool.numberOfActors(5).getAllResults(splicedList,foldLeft(_+_))

其中 spliceIntoParts 将一个大列表变成 100 个小列表 numberofactors 部分,创建一个使用 5 个演员的池,并在作业完成后接收新作业 getallresults 使用列表中的方法。所有这些都是通过在后台传递的消息完成的。其中可能是 getFirstResult,计算第一个结果,并停止所有其他线程(如破解密码)

【问题讨论】:

    标签: scala concurrency mapreduce syntactic-sugar


    【解决方案1】:

    你可以使用Scalaz的并发特性来实现你想要的。

    import scalaz._
    import Scalaz._
    import concurrent.strategy.Executor
    import java.util.concurrent.Executors
    
    implicit val s = Executor.strategy[Unit](Executors.newFixedThreadPool(5))
    
    val splicedList = biglist.grouped(100).toList
    val sum = splicedList.parMap(_.sum).map(_.sum).get
    

    让这个更漂亮会很容易(即编写一个函数 mapReduce 将拆分和折叠合二为一)。此外,List 上的 parMap 过于严格。您将需要在整个列表准备好之前开始折叠。更像:

    val splicedList = biglist.grouped(100).toList
    val sum = splicedList.map(promise(_.sum)).toStream.traverse(_.sum).get
    

    【讨论】:

    • 我发现 scalaz 对于生产使用的记录太差了,我希望几个月后它会变得更好
    • 我们正在处理文档。不过,代码非常简单,因此了解源代码是编写自己的代码的下一个最佳选择。
    【解决方案2】:

    在 2010 年 Scala Days 上,Aleksandar Prokopec(在 EPFL 从事 Scala 工作)发表了关于 Parallel Collections 的非常有趣的演讲。这可能会出现在 2.8.1 中,但您可能需要等待更长时间。我会看看我能不能得到演示文稿本身。链接到这里。

    我们的想法是建立一个集合框架,该框架通过完全按照您的建议来并行处理集合,但对用户透明。理论上,您只需将导入从 scala.collections 更改为 scala.parallel.collections。显然,您仍然需要做一些工作,看看您正在做的事情是否真的可以并行化。

    【讨论】:

    • 要将任何集合转换为它的并行版本,您只需要一个与 M[Promise[A]] 同构的 PromiseT[M] monad 转换器。从 PromiseT[M]#Apply[A] 到 M[A] 的隐式转换将使转换器完全透明。
    • 2.8.1?什么时候发布?
    【解决方案3】:

    与使用期货创建演员相比,您可以用更少的开销来做到这一点:

    import scala.actors.Futures._
    val nums = (1 to 1000).grouped(100).toList
    val parts = nums.map(n => future { n.reduceLeft(_ + _) })
    val whole = (0 /: parts)(_ + _())
    

    您必须处理分解问题并编写“未来”块并将其重新组合成最终答案,但这确实使并行执行一堆小代码块变得容易。

    (请注意,左侧折叠中的_() 是未来的应用函数,这意味着,“给我你并行计算的答案!”,它会阻塞,直到答案可用。)

    并行集合库会自动分解问题并为您重新组合答案(与 Clojure 中的 pmap 一样);这还不是主要 API 的一部分。

    【讨论】:

    • 是的,我看到了getAllResults,但是getFirstResultandThrowAwayEverythingElseFunction 怎么样?我们不需要使用all,而是需要any
    • 现在要做的工作更多——请注意,在任何语言中都不是很有效——并且需要将future 替换为actor { loop { react { /* case code */ } } } ! message,然后接收第一个回复并忽略其余部分。无论如何,重点是,你当然可以用演员构建它(即使自动退出,如果你使用链接),但它不是开箱即用的。改进的并发性是 2.9 的主要焦点之一。
    • 2.9?那是什么时候?或者我应该问什么时候 Scala 准备好用于主要生产用途? (是的,有推特,但是,只有推特)
    • 2.9 不会很快准备好让您在想要回答这个问题的时间范围内使用它。关键是你不是唯一一个认识到这样的事情会很好的人,并且正在计划改进。在那之前,您可以使用较低级别的构造(Java 线程和/或 Scala Actor)创建您想要的功能,但需要做更多的工作。
    【解决方案4】:

    我不是在等待 Scala 2.8.1 或 2.9,最好是编写自己的库或使用另一个库,所以我做了更多的谷歌搜索,发现了这个:akka http://doc.akkasource.org/actors

    它有一个带有方法的对象期货

    awaitAll(futures: List[Future]): Unit
    awaitOne(futures: List[Future]): Future
    

    但是http://scalablesolutions.se/akka/api/akka-core-0.8.1/ 根本没有文档。这很糟糕。

    但好的部分是 akka 的演员比 scala 的本地演员更精简
    有了所有这些库(包括 scalaz),如果 scala 本身最终可以正式合并它们,那就太好了

    【讨论】:

      【解决方案5】:

      使用将包含在 2.8.1 中的 Scala Parallel 集合,您将能够执行以下操作:

      val spliced = myList.par // obtain a parallel version of your collection (all operations are parallel)
      spliced.map(process _)   // maps each entry into a corresponding entry using `process`
      spliced.find(check _)    // searches the collection until it finds an element for which
                               // `check` returns true, at which point the search stops, and the element is returned
      

      并且代码将自动并行完成。常规集合库中的其他方法也正在并行化。

      目前,2.8.RC2 非常接近(这周或下周),我猜 2.8 决赛将在几周后到来。如果您使用 2.8.1 nightlies,您将能够尝试并行集合。

      【讨论】:

      • 哇,看起来真的很棒。我猜 foldLeft 也可以在这里工作
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 2023-03-30
      • 2013-07-05
      • 1970-01-01
      • 2014-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多