【问题标题】:Haskell lightweight threads overhead and use on multicoresHaskell 轻量级线程开销和多核使用
【发布时间】:2011-08-16 09:36:22
【问题描述】:

我一直在阅读“Real World Haskell”一书,这是关于并发和并行性的一章。我的问题如下:

  • 由于 Haskell 线程实际上只是一个“真实”操作系统线程中的多个“虚拟”线程,这是否意味着创建大量线程(如 1000 个)不会对性能产生重大影响?即,我们可以说使用 forkIO 创建 Haskell 线程所产生的开销(几乎)可以忽略不计吗?如果可能,请提供实用的例子。

  • 轻量级线程的概念难道不会阻止我们利用多核架构的优势吗?据我了解,两个 Haskell 线程不可能在两个单独的内核上同时执行,因为从操作系统的角度来看,它们实际上是一个单线程。或者 Haskell 运行时是否做了一些巧妙的技巧来确保可以使用多个 CPU?

【问题讨论】:

标签: multithreading haskell concurrency multicore lightweight-processes


【解决方案1】:

GHC 的运行时提供了一个执行环境,支持数十亿个 spark、数千个轻量级线程,这些线程可能分布在多个硬件内核上。使用-threaded 编译并使用+RTS -N4 标志设置所​​需的内核数。

具体来说:

这是否意味着创建很多(如 1000 个)不会对性能产生巨大影响?

嗯,creating 1,000,000 of them 当然是可能的。 1000太便宜了,甚至都不会出现。您可以在线程创建基准中看到,例如GHC is very, very good 的“线程环”。

轻量级线程的概念难道不会阻止我们利用多核架构的好处吗?

一点也不。 GHC has been running on multicores 自 2004 年以来。多核运行时的当前状态是 tracked here.

它是如何做到的?阅读此架构的最佳位置是在论文中,"Runtime Support for Multicore Haskell"

GHC 运行时系统支持数百万轻量级线程 通过将它们多路复用到少数操作系统线程上, 每个物理 CPU 大约一个。 ...

Haskell 线程由一组操作系统执行 线程,我们称之为工作线程。我们维持大致一 每个物理 CPU 的工作线程,但确切地说是哪个工作线程 可能会随时变化...

由于工作线程可能发生变化,我们只维护一个 每个 CPU 的 Haskell 执行上下文 (HEC)。 HEC是一个 包含操作系统工作线程的所有数据的数据结构 需要才能执行 Haskell 线程

您可以监视正在创建的线程以及它们在哪里执行,via threadscope.。在这里,例如运行二叉树基准测试:

【讨论】:

  • 非常感谢您提供全面的答案,特别是参考多核 Haskell 的论文。
【解决方案2】:
  • Warp 网络服务器广泛使用这些轻量级线程来获取really good performance。请注意,其他 Haskell Web 服务器也在竞争:这更像是“Haskell 很好”而不是“Warp 很好”。

  • Haskell 提供了一个多线程运行时,可以跨多个系统线程分配轻量级线程。它适用于多达 4 个内核。除此之外,还有一些性能问题,尽管正在积极解决这些问题。

【讨论】:

  • 您对您提到的 >4 个内核的性能问题有任何参考吗?
  • 没有发表,没有。我从个人经验中知道这个问题,并且相信我听说过 Johan 提到他们正在解决这个问题。很抱歉这么含糊。
  • 我有点怀疑。参见例如Simon 最近的论文中的加速:i.imgur.com/rWb7l.png -- 来自这个 .pdf research.microsoft.com/en-us/um/people/simonpj/papers/parallel/… -- 在并发收集和数据并行论文中报告了类似的结果(将一些问题扩展到 32 或 48 个核心标记)。
  • 我相信 Michael 所指的问题是 IO 管理器的体系结构不太适合扩展到几个内核之外。特别是,它可能应该为每个内核使用一个 IO 管理器线程。所以这不是运行时问题,也不会影响 CPU 密集型工作负载的扩展,但 IO 密集型应用程序(例如 Web 服务器)可能会遇到瓶颈。据我所知,还没有人做过彻底的分析。
  • 是的,Snap 也发现了这个问题。最近好些了,但似乎在 5 或 6 个线程之后仍然下降。上次我做基准测试时,Warp 的绝对性能比 Snap 快,但 Snap 在 4 核以上的扩展性更好。这可能不够具体,无法推断出任何具体的东西,但我认为这很有趣。
【解决方案3】:

创建1000个进程相对轻量级;不要担心这样做。至于性能,您应该只对其进行基准测试。

如前所述,多核工作正常。多个 Haskell 线程可以通过调度在不同的 OS 线程上同时运行。

【讨论】:

    猜你喜欢
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-06
    • 1970-01-01
    • 2012-05-16
    • 2013-05-12
    • 1970-01-01
    相关资源
    最近更新 更多