3

我是 Elixir 的新手,我开始阅读 Dave Thomas 出色的Programming Elixir。我很好奇我可以将“pmap”函数的并发性带到多远,所以我迭代地将平方的项目数从 1,000 增加到 10,000,000。出于好奇,我看了看输出htop我这样做的输出,通常 CPU 使用率达到峰值,如下所示:

htop 输出

在展示了书中的例子后,戴夫说:

而且,是的,我刚刚启动了 1,000 个后台进程,并且使用了我机器上的所有内核和处理器。

我的问题是,为什么我的机器上只有核心 1、3、5 和 7 亮起?我的猜测是,这与我的iex进程只是一个操作系统级别的进程有关,而 OSX 正在管理该进程的范围。这就是这里发生的事情吗?是否有某种方法可以确保所有内核都用于性能密集型任务?

4

2 回答 2

9

@Thiago Silveira 关于 iex 输出的第一行的精彩评论。该部分[smp:8:8]说明 Erlang 使用了多少操作系统级进程。--smp如果你想禁用它,你可以用 flag来控制它:

iex --erl '-smp disable'

这将确保您只有一个系统进程。您可以通过启用对称多处理来实现类似的结果,但直接设置NumberOfShcedulers:NumberOfSchedulersOnline.

iex --erl '+S 1:1'

每个操作系统进程都需要有自己的 Erlang 进程调度程序,因此您可以轻松查看当前有多少个进程:

:erlang.system_info(:schedulers_online)

回答您关于性能的问题。如果您的处理器没有满负荷工作(100%)并且没有一个处理器什么都不做(0%),那么使负载分布更均匀很可能不会加快速度。为什么?

CPU 使用率是通过在多个时间点探测处理器状态来测量的。这种状态要么是“工作”,要么是“空闲”。82% 的 CPU 使用率意味着您可以在此 CPU 上执行更多任务,而不会减慢其他任务的速度。

Erlang 调度器尽量聪明,不会在内核之间迁移 Erlang 进程,除非因为它需要复制而必须这样做。例如,当调度程序之一空闲时,就会发生迁移。然后它可以从其他调度程序运行队列中借用一个进程。

下一个可能导致奇数核和偶数核之间存在如此大差异的是超线程。在我的双核处理器htop上显示 4 个逻辑核心。在您的情况下,由于 HT,您可能有 4 个物理内核和 8 个逻辑内核。您可能会 100% 使用物理内核。

另一件事:pmap 需要在单独的进程中计算结果,但最后它会将结果发送给调用者,这可能是一个瓶颈。您发送的消息越多,您可以实现的 CPU 利用率就越低。您可以尝试为进程分配一个真正占用大量 CPU 的任务,例如计算Ackerman 函数您甚至可以使用阿姆达尔定律和测量不同内核数量的执行时间来计算您的工作有多少是顺序部分,多少是并行的。

总结一下:截图中的CPU利用率看起来真的很棒!您无需为更多性能密集型任务进行任何更改。

于 2016-04-24T07:55:05.193 回答
2

并发不是并行

为了从 Elixir/BEAM 编码中获得良好的并行性能,您需要对 BEAM 调度程序的工作原理有所了解。

这是一个非常简单的模型,但 BEAM 调度程序在将进程换出下一个进程之前,会为每个进程减少 2000 倍。减少可以被认为是函数调用。默认情况下,进程在生成它的核心/调度程序上运行。如果未完成的进程队列建立在给定的调度程序上,进程只会在调度程序之间移动。默认情况下,BEAM 在每个可用内核上运行一个调度线程。

这意味着,为了充分利用处理器,您需要将任务分解为足够大的工作,这些工作将超过标准的“减少”工作片。通常,pmap 风格的并行性仅在您将许多项目分块为单个任务时才能显着提高速度。

要注意的另一件事是,BEAM 的某些部分在等待工作时使用自旋/等待循环,并且当您使用htop检查 CPU 使用率之类的工具时,这可能会导致使用率出现偏差。使用:observer.

于 2016-04-25T22:50:58.587 回答