Erlang 以能够支持许多轻量级进程而闻名。它可以这样做是因为这些不是传统意义上的进程,甚至不是 P 线程中的线程,而是完全在用户空间中的线程。
这很好(实际上很棒)。但是,Erlang 线程如何在多核/多处理器环境中并行执行呢?当然,它们必须以某种方式映射到内核线程才能在单独的内核上执行吗?
假设是这种情况,这是如何完成的?许多轻量级进程是否映射到单个内核线程?
或者有没有其他方法可以解决这个问题?
Erlang 以能够支持许多轻量级进程而闻名。它可以这样做是因为这些不是传统意义上的进程,甚至不是 P 线程中的线程,而是完全在用户空间中的线程。
这很好(实际上很棒)。但是,Erlang 线程如何在多核/多处理器环境中并行执行呢?当然,它们必须以某种方式映射到内核线程才能在单独的内核上执行吗?
假设是这种情况,这是如何完成的?许多轻量级进程是否映射到单个内核线程?
或者有没有其他方法可以解决这个问题?
答案取决于使用的 VM:
1)非SMP:有一个调度器(OS线程),它执行所有Erlang进程,取自可运行进程池(即那些没有被eg阻塞的receive
)
2)SMP:有K个调度器(OS线程,K通常是CPU核数),从共享进程队列中执行Erlang进程。它是一个简单的 FIFO 队列(带有锁以允许从多个 OS 线程同时访问)。
3) R13B 和更新版本中的 SMP:将有K 个调度程序(如前所述)从多个进程队列执行 Erlang 进程。每个调度程序都有自己的队列,因此将添加从一个调度程序到另一个调度程序的进程迁移逻辑。此解决方案将通过避免共享进程队列中的过度锁定来提高性能。
有关详细信息,请参阅爱立信公司的 Kenneth Lundin 为 2008 年 11 月 13 日在斯德哥尔摩举行的 Erlang 用户大会准备的文档。
我想修改以前的答案。
Erlang,或者更确切地说是 Erlang 运行时系统 (erts),将调度程序(OS 线程)的数量和运行队列的数量默认为平台上的处理元素数量。那是处理器内核或硬件线程。您可以使用以下方法在运行时更改这些设置:
erlang:system_flag(schedulers_online, NP) -> PrevNP
Erlang 进程还没有与任何调度程序有任何关联。在调度程序之间平衡进程的逻辑遵循两个规则。1) 饥饿的调度器会窃取另一个调度器的工作。2) 迁移路径设置为将进程从具有大量进程的调度程序推送到具有较少工作的调度程序。这样做是为了确保每个进程的减少计数(执行时间)的公平性。
然而,调度程序可以锁定到特定的处理元素。默认情况下不这样做。要让 erts 执行 scheduler->core affinity 使用:
erlang:system_flag(scheduler_bind_type, default_bind) -> PrevBind
在文档中可以找到其他几种绑定类型。在重负载情况下使用亲和力可以大大提高性能!特别是在高锁争用情况下。此外,至少可以说,Linux 内核无法处理超线程。如果您的平台上有超线程,您应该在 erlang 中真正使用此功能。
我在这里纯粹是猜测,但我想有少量线程,它们从公共进程池中选择进程来执行。一旦一个进程遇到阻塞操作,执行它的线程就会把它放在一边并选择另一个。当一个正在执行的进程导致另一个进程被解除阻塞时,该新解除阻塞的进程将被放入池中。我想一个线程也可能会停止一个进程的执行,即使它在某些点没有被阻塞以服务其他进程。
我想为接受的答案中描述的内容添加一些输入。
Erlang 调度器是 Erlang 运行时系统的重要组成部分,它提供了自己的抽象和实现操作系统线程之上的轻量级进程的概念。
每个调度程序都在单个 OS 线程中运行。通常情况下,硬件上的 CPU(内核)有多少个调度器(虽然它是可配置的,当调度器的数量超过硬件内核的数量时自然不会带来太多价值)。系统也可能被配置为调度程序不会在操作系统线程之间跳转。
现在,当创建 Erlang 进程时,ERTS 和调度程序完全负责管理生命周期和资源消耗以及内存占用等。
核心实现细节之一是,当调度程序从运行队列中选择该进程时,每个进程都有 2000 次可用的时间预算。保证系统中的每一个进展(甚至是 I/O)都有一个减少预算。这就是使 ERTS 成为具有抢先式多任务处理系统的真正原因。
我会推荐 Jesper Louis Andersen 关于该主题的一篇很棒的博客文章http://jlouisramblings.blogspot.com/2013/01/how-erlang-does-scheduling.html
作为简短的回答:Erlang 进程不是操作系统线程,并且不直接映射到它们。Erlang 调度程序是在操作系统线程上运行的,并提供更细粒度的 Erlang 进程的智能实现,将这些细节隐藏在程序员的眼睛后面。