【问题标题】:How does Scala attain parallelism?Scala 如何实现并行性?
【发布时间】:2013-09-18 13:53:41
【问题描述】:

我正在学习关于分布式系统的课程,我们必须使用 Scala 来制作我们的项目。我们的讲师告诉我们,Scala 的优点在于它使用多个核心进行计算,并使用并行性来解决问题,同时与 Actor 模型集成。

这是一个理论问题。我已经学习了一些关于使用 Akka 的演员模型的基础知识,我的问题是,在编程时,用户是否必须向编译器提供详细信息,以便各种演员在多个内核上工作,或者 Scala 是否会处理这个问题并使用多个不同演员的核心?

简而言之,我的问题是:当我们使用 Scala 中的 Akka 库声明多个参与者时,Scala 编译器是否会自动使用多核 CPU 能力在内核之间分配各种参与者,或者程序员是否必须提供一些输入这样做?

【问题讨论】:

    标签: scala akka multicore actor actor-model


    【解决方案1】:

    TL;DR:使用 Akka 中的默认配置,您无需执行任何操作即可在大多数用例中获得相当好的并行性。

    更长的答案: Akka 中的 Actor 在 Dispatcher 上运行,并且 Dispatcher 有一个 ExecutionService,它通常是一个线程池。线程数由开发者配置,但默认为机器上CPU核数的3倍(参考配置见default-dispatcher.parallelism-factorhere)。

    在任何时间点,每个 CPU 内核都可以使用这些线程之一运行 Actor,因此只要您的 Dispatcher 的 ExecutionService 中的线程数等于 CPU 上的内核数,您就可以充分利用你的所有核心。之所以将其设置为默认配置中核心数的三倍,是为了补偿阻塞 IO。

    IO 很慢,阻塞调用有时会占用线程,而不是使用 CPU。所以获得最佳并行度的关键是配置这个线程池:

    • 如果您只执行非阻塞 IO,您可以将其设置为您拥有的 CPU 内核数,并确信您正在充分利用您的 CPU。
    • 您执行的阻塞 IO 越多,您需要越多的线程来保持良好的并行性,但请注意 - 您使用的线程越多,您将使用的内存就越多,而且线程并不是世界上最轻量级的东西。

    【讨论】:

    • 感谢您的快速回复,这是否意味着 AKKA 调度程序负责并行处理,用户只需在编程时提供参与者(或线程)的数量?
    • 根据需要制作尽可能多的 Actor。线程数是您需要调整以获得最佳并行度的东西。如果您只进行非阻塞 IO,请将其设置为您拥有的 CPU 内核数。您执行的阻塞 IO 越多,您需要越多的线程来保持良好的并行性。但是,是的,使用默认配置,您无需执行任何操作即可在大多数用例中获得相当好的并行性。
    【解决方案2】:

    theon 的回答非常好,但我只想指出,actor 并不是在 Scala 中实现并行性的唯一方法。如果您不需要管理状态,Futures 通常是一种更简单的并行执行计算的方法。您只需在调用 Future 工厂函数时包装可以独立于其他代码运行的每个 sn-p 代码,然后您可以使用对 @987654323 的调用来组合/转换每个 sn-p 的结果(也是并行的) @、flatMapfold 等,或使用 for 理解。您只需将ExecutionContext 配置为implicit val,如果您已经在使用Akka,您可以使用与您的actors 相同的,或者您可以使用预先配置的全局默认值。

    【讨论】:

    • 好点。值得一提的是parallel collections。只需像您提到的那样添加范围内的ExecutionContext,然后将任何调用从coll.mapcoll.filter 等更改为coll.par.mapcoll.par.filter 以实现即时并行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    • 2019-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    相关资源
    最近更新 更多