【问题标题】:Is Scala doing anything in parallel on its own?Scala 自己在做任何并行的事情吗?
【发布时间】:2011-06-07 19:26:14
【问题描述】:

我有一个创建迷宫的小程序。它使用了很多集合(默认变体,它是不可变的,或者至少用作不可变的)。

程序会计算 30 个尺寸不断增加的迷宫。对 (1 到 30) 使用 for 理解

自从有了最新版本的并行集合框架,我想给它一个新版本,希望能获得一些性能提升。

这失败了,当我调查了一下时,我发现了以下内容:

  1. 在不调用任何远程并行程序的情况下运行时,我的机器的 4 个内核中的每一个内核仍然显示出大约 30% 的处理器负载。

  2. 当我将范围 1 到 30 替换为 (1 到 30).par CPU 负载在所有内核上上升到大约 80%(这是我的预期)。迷宫完成的顺序或多或少是随机的(这是我所预料的)。所有迷宫的总时间保持不变。

  3. 将一些内部使用的集合替换为它们的并行计数器部件似乎确实有效果。

我现在有两个问题:

  • 为什么我的 4 个核心都在旋转,虽然没有任何东西并行运行。

  • 程序仍然需要相同时间的可能原因是什么,无论是否并行运行。没有明显的其他瓶颈,但 CPU 周期(没有 IO,没有网络,通过 -Xmx 设置的大量内存)

对此有何想法?

【问题讨论】:

  • 你应该做一个不超过一页的例子并编译。否则只是过多的猜测。唯一可能在您不做任何事情的情况下同时运行的是垃圾收集器。您的程序是否创建了很多在创建后很快就会被垃圾收集的对象?这在函数式编程风格中很常见......
  • 是的,我想确实会创建很多对象,所以 GC 可能是一个不错的选择。我将激活一些日志记录,看看结果如何。
  • 我确实看起来我没有获得任何性能提升,因为我正在等待 GC

标签: scala collections parallel-processing


【解决方案1】:

每个内核版本的 30% 只是一个糟糕的调度程序(听起来像 Windows 7),非常频繁地将进程从内核迁移到内核。对于您的流程,它可能接近每个内核(1/4)的 25%,再加上其他 30% 的负载。如果您在 Linux 下运行相同的示例,您可能会看到固定一个内核。

当您转换为(1 to 30).par 时,您开始真正在所有内核上使用线程,但是分配如此少量工作然后收集结果的同步开销抵消了并行度的提升。你需要把你的工作分成更大的独立块。

编辑:如果 1..30 中的每一个都代表一些更大的工作量(比如解决迷宫),那么如果每个工作单元大致相同,自动并行化将工作得更好。想象一下,你有 29 个简单的迷宫和一个非常非常难的迷宫。第 30 个迷宫仍将与其他所有迷宫连续(或非常接近)运行)。如果您的迷宫按数量增加复杂性,请尝试按30 to 1 by -1 的顺序生成它们,以便最大的任务先执行。可以将其视为背包问题的脑死解决方案。

【讨论】:

  • 是Windows 7。不知道能不能找到一个linux来测试你的理论。较大的迷宫(20 号以上)每个需要 1 秒或更长时间。所以小块理论似乎并不适用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
  • 2017-12-05
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 2020-10-14
  • 1970-01-01
相关资源
最近更新 更多