【问题标题】:Python, Ruby, Haskell - Do they provide true multithreading?Python、Ruby、Haskell——它们提供真正的多线程吗?
【发布时间】:2010-12-27 14:35:13
【问题描述】:

我们计划用任何一种非常高级的编程语言编写一个高度并发的应用程序。

1) Python、Ruby 或 Haskell 是否支持真正的多线程?

2) 如果程序包含线程,虚拟机是否会自动将工作分配给多个内核(如果主板上有超过 1 个 CPU,则分配给物理 CPU)?

真正的多线程 = 多个独立的执行线程利用多个内核提供的资源(不仅仅是一个内核)。

假多线程 = 线程模拟多线程环境,不依赖任何本机操作系统功能。

【问题讨论】:

  • “真”多线程?那是什么意思?请定义“真正的”多线程。
  • 真正的多线程 = 多个独立的执行线程利用多核提供的资源(不仅仅是 1 个核)
  • @S.Lott:完成,我已经更新了原帖
  • 现在你已经更新了你的问题,我什至更多对你在“真”和“假”多线程之间的区别感到困惑。例如,BEAM Erlang VM 跨多个 CPU 和多个内核调度 Erlang 线程。因此,根据您的定义,BEAM 支持真正的多线程。但是,BEAM 以任何方式依赖本机操作系统功能;事实上,它实际上可以在没有任何操作系统的情况下在裸硬件上运行。因此,根据您的定义,BEAM 支持真正的多线程,而是支持假多线程。它是哪一个?这个定义是没有用的。
  • BEAM 具有如此令人难以置信的可扩展性的全部原因是因为它不依赖于重量级、臃肿、缓慢的操作系统线程,而是实现了自己的线程。例如,Linux 线程在 32 位机器上是 4 或 8 KiBytes,而在 64 位机器上是 8 或 16 KiBytes。我相信 Windows NT 线程是 12 KiBytes。 BEAM 大约 300 字节。 32 位 Linux 可以轻松处理数万个线程。大约 800000 它只会耗尽内存,至少在 32 位系统上是这样。我看到在 Linux 上运行的 BEAM 在一个不太强大的上网本上处理了 100 万个线程,同时进行了演示。

标签: python ruby concurrency haskell multithreading


【解决方案1】:

1) Python、Ruby 或 Haskell 是否支持真正的多线程?

这与语言无关。这是硬件的问题(如果机器只有 1 个 CPU,在物理上根本不可能同时执行两条指令),操作系统(同样,如果操作系统不支持真正的多线程,则什么都没有你可以做)和语言实现/执行引擎。

除非语言规范明确禁止或强制执行真正的多线程,否则这与语言完全无关。

所有您提到的语言,以及迄今为止在答案中提到的所有语言,都有多种实现,其中一些支持真正的多线程,一些不支持,还有一些是建立在其他执行引擎之上,可能支持也可能不支持真正的多线程。

以 Ruby 为例。以下是它的一些实现及其线程模型:

  • MRI:绿色线程,没有真正的多线程
  • YARV:操作系统线程,没有真正的多线程
  • Rubinius:操作系统线程,真正的多线程
  • MacRuby:操作系统线程,真正的多线程
  • JRuby、XRuby:JVM 线程,依赖于 JVM(如果 JVM 支持真正的多线程,那么 JRuby/XRuby 也支持,如果 JVM 不支持,那么 他们 无能为力关于它)
  • IronRuby、Ruby.NET:就像 JRuby、XRuby,但在 CLI 上而不是在 JVM 上

另见my answer to another similar question about Ruby。 (请注意,该答案已有一年多的历史了,其中一些不再准确。例如,Rubinius 现在使用真正并发的本地线程,而不是真正并发的绿色线程。此外,从那时起,几个 new Ruby 实现已经出现,例如 BlueRuby、tinyrb、Ruby Go Lightly、Red Sun 和 SmallRuby。)

Python 类似:

  • CPython:原生线程,没有真正的多线程
  • PyPy:本地线程,取决于执行引擎(PyPy 可以本地运行,也可以在 JVM 上运行,或者在 CLI 上运行,或者在 另一个 Python 执行引擎上运行。无论何时底层平台支持真正的多线程,PyPy 也支持。)
  • Unladen Swallow:本机线程,目前没有真正的多线程,但计划修复
  • Jython:JVM 线程,请参阅 JRuby
  • IronPython:CLI 线程,请参阅 IronRuby

对于 Haskell,至少 Glorious Glasgow Haskell 编译器支持使用本地线程的真正多线程。我不知道 UHC、LHC、JHC、YHC、HUGS 或所有其他的。

对于 Erlang,BEAM 和 HiPE 都支持真正的多线程和绿色线程。

2) 如果程序包含线程,虚拟机是否会自动将工作分配给多个内核(如果主板上有超过 1 个 CPU,则分配给物理 CPU)?

再次重申:这取决于虚拟机、操作系统和硬件。此外,上面提到的一些实现甚至没有虚拟机。

【讨论】:

  • CPython 和 YARV 没有真正的多线程的原因,即使在多核处理器上运行,即使它们使用本机线程,也是因为它们有一个全局解释器锁来防止线程看到执行环境(例如一组可用的类定义和方法调用)在其他线程尝试更改时处于不一致状态。
  • YARV 将其称为巨型 VM 锁 (GVL),但原则上您是对的。不过,至少在 YARV 上,有计划移除 GIL。如果您查看thread.c,您可以看到 YARV 已通过或将要通过的三种不同线程模型的描述:绿色线程 -> 具有 GIL 的本机线程 -> 具有细粒度锁定的真正并行本机线程。但是,还没有代码。在 CPython 中,情况类似:Unladen Swallow 计划移除 GIL,并且如果它不太具有侵入性,则将此移除贡献回 CPython。
【解决方案2】:

Haskell 实现 GHC 支持在共享内存多核上并行执行的多种机制。这些机制在“Runtime Support for Multicore Haskell”中有所描述。

具体来说,Haskell 运行时将工作划分为 N 个 OS 线程,分布在可用的计算内核上。这 N 个 OS 线程依次运行 M 个轻量级 Haskell 线程(有时数百万个)。反过来,每个 Haskell 线程都可以为一个火花队列工作(可能有数十亿个火花)。像这样:

运行时安排工作在不同的核心上执行、迁移工作和负载平衡。垃圾收集器也是一个并行的,使用每个核心来收集堆的一部分。

与 Python 或 Ruby 不同,没有全局解释器锁,因此和其他原因,相比之下,GHC 在多核上特别好,例如Haskell v Python on the multicore shootout

【讨论】:

    【解决方案3】:

    如果您使用-threaded 选项进行编译,然后在运行时传递+RTS -N<x> -RTS,GHC 编译器将在多个操作系统线程(因此是多个内核)上运行您的程序,其中<x> = 您想要的操作系统线程数.

    【讨论】:

    • 或者如果你省略了,它会尝试找出最优化的数字。
    【解决方案4】:

    当前版本的Ruby 1.9(基于YARV-C 的版本)有本地线程但是有GIL 的问题。据我所知,Python 也有 GIL 的问题。

    但是,Jython 和 JRuby(Ruby 和 Python 的成熟 Java 实现)都提供原生多线程,没有绿色线程,也没有 GIL。

    不知道 Haskell。

    【讨论】:

    • Jython 和 JRuby 与它们的起源有很大不同吗?
    • GIL 是什么意思?谷歌建议使用“气体绝缘线”,但无济于事......
    • docs.python.org/c-api/… 解释了全局解释器锁 (GIL) 是什么。
    • @psihodelia 不,它们没有区别,它们只是使用 Java 而不是 C 编写的。如果您有一些 C 扩展,那么您将无法在 Jython 和 JRuby 中使用它们,但实际上Jython 和 JRuby 都允许您在代码中使用 Java jar,据我所知,这是一个很大的选择和优势。
    • @tobsen,GIL 代表 Global Interpreter Lock。
    【解决方案5】:

    Haskell 具有线程能力,此外您还可以得到 pure 函数式语言 - 没有 side effects

    【讨论】:

    • 那又怎样?纯线程使线程变得容易,因为您知道函数可以在其他线程中运行并且不会修改环境——Haskell 也有 Monads,它们是代码的不纯部分,但此外,这根本不能回答 OP 问题。请删除此答案。
    【解决方案6】:

    对于真正的并发,你可能想试试 Erlang。

    【讨论】:

    • 看来 Erlanf 也不支持真正的多线程。来自 Wikipedia:进程是构建 Erlang 应用程序的主要手段。 Erlang 进程既不是操作系统进程,也不是操作系统线程,而是轻量级进程,有点类似于 Java 最初的“绿色线程”。
    • 维基百科的引用与真正的多线程有什么关系?
    • Erlang 非常擅长分发,并且具有良好的并发抽象,但并发与并行不一样,而且 Erlang 的多核运行时都是相当新的,而且比 Haskell 慢一些。尽管如此,相比之下还是比 Python 或 Ruby 好很多,而且你会学到很多关于并发的知识,而不是多核并行。 * ghcmutterings.wordpress.com/2009/10/06/parallelism-concurrency * shootout.alioth.debian.org/u64q/…
    【解决方案7】:

    我支持 Erlang 的选择。 Erlang 可以开箱即用地支持分布式高并发编程。不管你叫它“多线程”还是“多处理”。需要考虑的两个重要因素是并发级别和 Erlang 进程不共享状态这一事实。

    进程之间没有共享状态是一件好事。

    【讨论】:

      【解决方案8】:

      Haskell 适用于任何事情。 python 有processing 模块,它(我认为 - 不确定)有助于避免 GIL 问题。 (所以它也适用于任何东西)。

      但我的意见 - 你能做的最好的方法是选择具有静态类型系统的最高级别的语言来处理大事。今天这些语言是:ocaml、haskell、erlang。

      如果你想开发小东西——python 很好。但是当事情变得更大时 - 所有 python 的好处都被无数的测试吃掉了。

      我没有使用红宝石。我仍然认为 ruby​​ 是一种玩具语言。 (或者至少当你知道 python 时没有理由教 ruby​​ - 最好阅读 SICP 书)。

      【讨论】:

      • mm...我的错。不好的句子。关于erlang,我还是换个说法吧。
      猜你喜欢
      • 2010-09-08
      • 2011-01-16
      • 2011-08-18
      • 2017-11-23
      • 2021-11-02
      • 1970-01-01
      • 2012-04-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多