59

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

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

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

4

3 回答 3

86

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

火花/线程/工人/核心

具体来说:

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

好吧,创建 1,000,000 个它们当然是可能的。1000太便宜了,甚至都不会出现。您可以在线程创建基准测试中看到,例如“线程环”,GHC 非常非常好

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

一点也不。自 2004 年以来,GHC 一直在多核上运行。在此处跟踪多核运行时的当前状态。

它是如何做到的?阅读此架构的最佳位置是在论文“多核 Haskell 的运行时支持”中

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

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

由于工作线程可能发生变化,我们为每个 CPU 维护一个 Haskell 执行上下文 (HEC)。HEC 是一种数据结构,其中包含 OS 工作线程执行 Haskell 线程所需的所有数据

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

螺纹镜

于 2011-05-01T15:54:58.727 回答
14
  • Warp 网络服务器广泛使用这些轻量级线程来获得非常好的性能。请注意,其他 Haskell Web 服务器也参与竞争:这更像是“Haskell 很好”而不是“Warp 很好”。

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

于 2011-05-01T10:37:50.063 回答
4

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

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

于 2011-05-01T12:46:44.217 回答