Erlang因能够支持许多轻量级进程而闻名。它可以做到这一点,因为它们不是传统意义上的进程,甚至不是P线程中的线程,而是完全在用户空间中的线程。

这很好(实际上太棒了)。但是,如何在多核/多处理器环境中并行执行Erlang线程?当然它们必须以某种方式映射到内核线程才能在不同的内核上执行?

假设情况如此,这是怎么做到的?许多轻量级进程是否映射到单个内核线程?

或者还有另外一种解决这个问题的方法吗?

有帮助吗?

解决方案

答案取决于使用的VM:

1)非SMP :有一个调度程序(操作系统线程),它执行所有Erlang进程,取自可运行进程池(即那些未被例如 receive 阻止的人)

2) SMP K调度程序(操作系统线程,K通常是许多CPU内核),它从共享进程执行Erlang进程队列即可。它是一个简单的FIFO队列(带有锁,允许从多个OS线程同时访问)。

3)R13B中的 SMP及更新:将有 K调度程序(如前所述)从多个进程队列执行Erlang进程。每个调度程序都有自己的队列,因此将添加从一个调度程序到另一个调度程序的进程迁移逻辑。此解决方案将通过避免共享进程队列中的过度锁定来提高性能。

有关详细信息,请参阅爱立信AB的Kenneth Lundin编写的本文档, 2008年11月13日,斯德哥尔摩Erlang用户大会。

其他提示

我想提出以前的答案。

Erlang,或者更确切地说是Erlang运行时系统(erts),默认调度程序的数量(操作系统线程)以及平台上处理元素数量的运行队列数。那是处理器核心或硬件线程。您可以使用以下命令在运行时更改这些设置:

erlang:system_flag(schedulers_online, NP) -> PrevNP

Erlang进程与任何调度程序之间没有任何关联。平衡调度程序之间的过程的逻辑遵循两个规则。 1)饥饿的调度程序将窃取另一个调度程序的工作。 2)设置迁移路径以将具有大量进程的调度程序的进程推送到具有较少工作的调度程序。这样做是为了确保每个过程的减少计数(执行时间)的公平性。

但是,

调度程序可以锁定到特定的处理元素。这不是默认情况下完成的。要让erts执行调度程序 - >核心关联使用:

erlang:system_flag(scheduler_bind_type, default_bind) -> PrevBind

可以在文档中找到其他几种绑定类型。使用亲和力可以极大地提高重载情况下的性能!特别是在高锁争用情况下。此外,Linux内核至少可以说无法处理超线程。如果您的平台上有超线程,那么您应该在erlang中使用此功能。

我在这里纯粹猜测,但我想是有少量线程,它从公共进程池中选择进程来执行。一旦进程遇到阻塞操作,执行它的线程就会将其放在一边并选择另一个进程。当正在执行的进程导致另一个进程被解除阻塞时,新的未阻塞进程将被放入池中。我想一个线程也可能会停止执行一个进程,即使它在某些点没有被阻塞以服务于其他进程。

我想在接受的答案中添加一些输入。

Erlang Scheduler是Erlang运行时系统的重要组成部分,它提供了自己的操作系统线程上轻量级进程概念的抽象和实现。

每个计划程序在单个OS线程中运行。通常,CPU(核心)上的调度程序与硬件一样多(虽然它是可配置的,但当调度程序的数量超过硬件核心数时,自然不会带来太多价值)。系统也可能配置为调度程序不会在OS线程之间跳转。

现在,在创建Erlang进程时,ERTS和Scheduler完全负责管理生命周期和资源消耗以及内存占用等。

其中一个核心实现细节是,当调度程序从运行队列中获取该进程时,每个进程的时间预算都可以减少2000个。系统中的每个进度(甚至I / O)都可以保证减少预算。这就是ERTS实际上是一个具有抢先式多任务处理的系统。

我建议由Jesper Louis Andersen撰写一篇关于该主题的精彩博文 http://jlouisramblings.blogspot.com/2013/01/how-erlang-does-scheduling.html

简而言之:Erlang进程不是OS线程,也不直接映射到它们。 Erlang Scheduler是在OS线程上运行的,它提供了更精细的Erlang进程的智能实现,隐藏了程序员眼睛背后的细节。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top